revert deployment changes (#217)
This commit is contained in:
parent
6b612316ee
commit
e4e0a7d061
12 changed files with 135 additions and 409 deletions
|
@ -24,7 +24,6 @@ import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableModel
|
||||||
*/
|
*/
|
||||||
public class ApplicationSetup implements ServletContextListener {
|
public class ApplicationSetup implements ServletContextListener {
|
||||||
private static final String APPLICATION_SETUP_PATH = "config/applicationSetup.n3";
|
private static final String APPLICATION_SETUP_PATH = "config/applicationSetup.n3";
|
||||||
private static final String APPLICATION_SETUP_DEFAULT_PATH = "config/default.applicationSetup.n3";
|
|
||||||
|
|
||||||
private ServletContext ctx;
|
private ServletContext ctx;
|
||||||
private StartupStatus ss;
|
private StartupStatus ss;
|
||||||
|
@ -46,8 +45,6 @@ public class ApplicationSetup implements ServletContextListener {
|
||||||
this.vitroHomeDir = VitroHomeDirectory.find(ctx);
|
this.vitroHomeDir = VitroHomeDirectory.find(ctx);
|
||||||
ss.info(this, vitroHomeDir.getDiscoveryMessage());
|
ss.info(this, vitroHomeDir.getDiscoveryMessage());
|
||||||
|
|
||||||
this.vitroHomeDir.populate();
|
|
||||||
|
|
||||||
locateApplicationConfigFile();
|
locateApplicationConfigFile();
|
||||||
loadApplicationConfigFile();
|
loadApplicationConfigFile();
|
||||||
createConfigurationBeanLoader();
|
createConfigurationBeanLoader();
|
||||||
|
@ -66,19 +63,11 @@ public class ApplicationSetup implements ServletContextListener {
|
||||||
private void locateApplicationConfigFile() {
|
private void locateApplicationConfigFile() {
|
||||||
Path path = this.vitroHomeDir.getPath().resolve(APPLICATION_SETUP_PATH);
|
Path path = this.vitroHomeDir.getPath().resolve(APPLICATION_SETUP_PATH);
|
||||||
|
|
||||||
if (!Files.exists(path) || !Files.isReadable(path)) {
|
|
||||||
path = this.vitroHomeDir.getPath().resolve(APPLICATION_SETUP_DEFAULT_PATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Files.exists(path)) {
|
if (!Files.exists(path)) {
|
||||||
throw new IllegalStateException("Neither '" + APPLICATION_SETUP_PATH + "' nor '" +
|
throw new IllegalStateException("'" + path + "' does not exist.");
|
||||||
APPLICATION_SETUP_DEFAULT_PATH + "' were found in " +
|
|
||||||
this.vitroHomeDir.getPath());
|
|
||||||
}
|
}
|
||||||
if (!Files.isReadable(path)) {
|
if (!Files.isReadable(path)) {
|
||||||
throw new IllegalStateException("No readable '" + APPLICATION_SETUP_PATH + "' nor '" +
|
throw new IllegalStateException("Can't read '" + path + "'");
|
||||||
APPLICATION_SETUP_DEFAULT_PATH + "' files were found in " +
|
|
||||||
this.vitroHomeDir.getPath());
|
|
||||||
}
|
}
|
||||||
this.configFile = path;
|
this.configFile = path;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,46 +4,25 @@ package edu.cornell.mannlib.vitro.webapp.application;
|
||||||
|
|
||||||
import static edu.cornell.mannlib.vitro.webapp.application.BuildProperties.WEBAPP_PATH_BUILD_PROPERTIES;
|
import static edu.cornell.mannlib.vitro.webapp.application.BuildProperties.WEBAPP_PATH_BUILD_PROPERTIES;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
|
import javax.naming.InitialContext;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
|
||||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.config.ContextProperties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates some of the info relating to and initializes the Vitro home directory.
|
* Encapsulates some of the info relating to the Vitro home directory.
|
||||||
*/
|
*/
|
||||||
public class VitroHomeDirectory {
|
public class VitroHomeDirectory {
|
||||||
private static final Log log = LogFactory.getLog(VitroHomeDirectory.class);
|
private static final Log log = LogFactory.getLog(VitroHomeDirectory.class);
|
||||||
|
|
||||||
private static final String DIGEST_FILE_NAME = "digest.md5";
|
|
||||||
|
|
||||||
private static final Pattern CHECKSUM_PATTERN = Pattern.compile("^[a-f0-9]{32} \\*.+$");
|
|
||||||
|
|
||||||
public static VitroHomeDirectory find(ServletContext ctx) {
|
public static VitroHomeDirectory find(ServletContext ctx) {
|
||||||
HomeDirectoryFinder finder = new HomeDirectoryFinder(ctx);
|
HomeDirectoryFinder finder = new HomeDirectoryFinder(ctx);
|
||||||
return new VitroHomeDirectory(ctx, finder.getPath(),
|
return new VitroHomeDirectory(ctx, finder.getPath(),
|
||||||
|
@ -73,219 +52,6 @@ public class VitroHomeDirectory {
|
||||||
return discoveryMessage;
|
return discoveryMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates VIVO home directory with files required to run.
|
|
||||||
*
|
|
||||||
* NOTE: Will not overwrite any modified files on redeploy.
|
|
||||||
*/
|
|
||||||
public void populate() {
|
|
||||||
File vhdDir = getPath().toFile();
|
|
||||||
|
|
||||||
if (!vhdDir.isDirectory() || vhdDir.list() == null) {
|
|
||||||
throw new RuntimeException("Application home dir is not a directory! " + vhdDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> digest = untar(vhdDir);
|
|
||||||
|
|
||||||
writeDigest(digest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A non-destructive untar process that returns checksum digest of tarred files.
|
|
||||||
*
|
|
||||||
* Checksum digest can be manually created with the following command.
|
|
||||||
*
|
|
||||||
* `find /vivo/home -type f | cut -c3- | grep -E '^bin/|^config/|^rdf/' | xargs md5sum > /vivo/home/digest.md5`
|
|
||||||
*
|
|
||||||
* @param destination VIVO home directory
|
|
||||||
* @return digest of each files checksum
|
|
||||||
*/
|
|
||||||
private Map<String, String> untar(File destination) {
|
|
||||||
log.info("Syncing VIVO home at: " + destination.getPath());
|
|
||||||
|
|
||||||
Map<String, String> digest = new HashMap<>();
|
|
||||||
Map<String, String> storedDigest = loadDigest();
|
|
||||||
|
|
||||||
TarArchiveEntry tarEntry;
|
|
||||||
try (
|
|
||||||
InputStream homeDirTar = getHomeDirTar();
|
|
||||||
TarArchiveInputStream tarInput = new TarArchiveInputStream(homeDirTar);
|
|
||||||
) {
|
|
||||||
while ((tarEntry = tarInput.getNextTarEntry()) != null) {
|
|
||||||
|
|
||||||
// Use the example configurations
|
|
||||||
String outFilename = tarEntry.getName().replace("example.", "");
|
|
||||||
File outFile = new File(destination, outFilename);
|
|
||||||
|
|
||||||
// Is the entry a directory?
|
|
||||||
if (tarEntry.isDirectory()) {
|
|
||||||
if (!outFile.exists()) {
|
|
||||||
outFile.mkdirs();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Entry is a File
|
|
||||||
boolean write = true;
|
|
||||||
|
|
||||||
// reading bytes into memory to avoid having to unreliably reset stream
|
|
||||||
byte[] bytes = IOUtils.toByteArray(tarInput);
|
|
||||||
String newFileChecksum = checksum(bytes);
|
|
||||||
digest.put(outFilename, newFileChecksum);
|
|
||||||
|
|
||||||
// if file already exists and stored digest contains the file,
|
|
||||||
// check to determine if it has changed
|
|
||||||
if (outFile.exists() && storedDigest.containsKey(outFilename)) {
|
|
||||||
String existingFileChecksum = checksum(outFile);
|
|
||||||
// if file has not changed in home and is not the same as new file, overwrite
|
|
||||||
write = storedDigest.get(outFilename).equals(existingFileChecksum)
|
|
||||||
&& !existingFileChecksum.equals(newFileChecksum);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write) {
|
|
||||||
outFile.getParentFile().mkdirs();
|
|
||||||
try (
|
|
||||||
InputStream is = new ByteArrayInputStream(bytes);
|
|
||||||
FileOutputStream fos = new FileOutputStream(outFile);
|
|
||||||
) {
|
|
||||||
IOUtils.copy(is, fos);
|
|
||||||
log.info(outFile.getAbsolutePath() + " source has changed and has not been "
|
|
||||||
+ "edited in home, updated file has been copied to home directory.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.debug(outFile.getAbsolutePath() + " has been preserved.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException | NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException("Error creating home directory!", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return digest;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load checksum digest of VIVO home directory.
|
|
||||||
*
|
|
||||||
* @return checksum digest
|
|
||||||
*/
|
|
||||||
private Map<String, String> loadDigest() {
|
|
||||||
File storedDigest = new File(getPath().toFile(), DIGEST_FILE_NAME);
|
|
||||||
if (storedDigest.exists() && storedDigest.isFile()) {
|
|
||||||
log.info("Reading VIVO home digest: " + storedDigest.getPath());
|
|
||||||
try {
|
|
||||||
return FileUtils
|
|
||||||
.readLines(storedDigest, StandardCharsets.UTF_8)
|
|
||||||
.stream()
|
|
||||||
.filter(CHECKSUM_PATTERN.asPredicate())
|
|
||||||
.map(this::split)
|
|
||||||
.collect(Collectors.toMap(this::checksumFile, this::checksumValue));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Error reading VIVO home checksum digest!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info("VIVO home digest not found: " + storedDigest.getPath());
|
|
||||||
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write VIVO home checksum digest following md5 format; `<checksum> *<file>`.
|
|
||||||
*
|
|
||||||
* @param digest checksum digest to write
|
|
||||||
*/
|
|
||||||
private void writeDigest(Map<String, String> digest) {
|
|
||||||
File storedDigest = new File(getPath().toFile(), DIGEST_FILE_NAME);
|
|
||||||
try (
|
|
||||||
FileOutputStream fos = new FileOutputStream(storedDigest);
|
|
||||||
OutputStreamWriter osw = new OutputStreamWriter(fos);
|
|
||||||
) {
|
|
||||||
for (Map.Entry<String, String> entry : digest.entrySet()) {
|
|
||||||
String filename = entry.getKey();
|
|
||||||
String checksum = entry.getValue();
|
|
||||||
osw.write(String.format("%s *%s\n", checksum, filename));
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Error writing home directory checksum digest!", e);
|
|
||||||
}
|
|
||||||
log.info("VIVO home digest created: " + storedDigest.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Split checksum.
|
|
||||||
*
|
|
||||||
* @param checksum checksum delimited by space and asterisks `<checksum> *<file>`
|
|
||||||
* @return split checksum
|
|
||||||
*/
|
|
||||||
private String[] split(String checksum) {
|
|
||||||
return checksum.split("\\s+");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get value from split checksum.
|
|
||||||
*
|
|
||||||
* @param checksum split checksum
|
|
||||||
* @return checksum value
|
|
||||||
*/
|
|
||||||
private String checksumValue(String[] checksum) {
|
|
||||||
return checksum[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return file from split checksum.
|
|
||||||
*
|
|
||||||
* @param checksum split checksum
|
|
||||||
* @return filename
|
|
||||||
*/
|
|
||||||
private String checksumFile(String[] checksum) {
|
|
||||||
return checksum[1].substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get md5 checksum from file.
|
|
||||||
*
|
|
||||||
* @param file file
|
|
||||||
* @return md5 checksum as string
|
|
||||||
* @throws IOException
|
|
||||||
* @throws NoSuchAlgorithmException
|
|
||||||
*/
|
|
||||||
private String checksum(File file) throws IOException, NoSuchAlgorithmException {
|
|
||||||
return checksum(FileUtils.readFileToByteArray(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get md5 checksum from bytes.
|
|
||||||
*
|
|
||||||
* @param bytes bytes from file
|
|
||||||
* @return md5 checksum as string
|
|
||||||
* @throws NoSuchAlgorithmException
|
|
||||||
*/
|
|
||||||
private String checksum(byte[] bytes) throws NoSuchAlgorithmException {
|
|
||||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
|
||||||
md.update(bytes);
|
|
||||||
// bytes to hex
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
for (byte b : md.digest()) {
|
|
||||||
result.append(String.format("%02x", b));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get prepacked VIVO home tar file as input stream.
|
|
||||||
*
|
|
||||||
* @return input stream of VIVO home tar file
|
|
||||||
*/
|
|
||||||
private InputStream getHomeDirTar() {
|
|
||||||
String tarLocation = "/WEB-INF/resources/home-files/vivo-home.tar";
|
|
||||||
InputStream tar = ctx.getResourceAsStream(tarLocation);
|
|
||||||
if (tar == null) {
|
|
||||||
log.error("Application home tar not found in: " + tarLocation);
|
|
||||||
throw new RuntimeException("Application home tar not found in: " + tarLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tar;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find something that specifies the location of the Vitro home directory.
|
* Find something that specifies the location of the Vitro home directory.
|
||||||
* Look in the JDNI environment, the system properties, and the
|
* Look in the JDNI environment, the system properties, and the
|
||||||
|
@ -326,13 +92,24 @@ public class VitroHomeDirectory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getVhdFromJndi() {
|
public void getVhdFromJndi() {
|
||||||
String vhdPath = ContextProperties.findJndiProperty(VHD_JNDI_PATH);
|
try {
|
||||||
log.debug("'" + VHD_JNDI_PATH + "' as specified by JNDI: " + vhdPath);
|
String vhdPath = (String) new InitialContext()
|
||||||
|
.lookup(VHD_JNDI_PATH);
|
||||||
|
if (vhdPath == null) {
|
||||||
|
log.debug("Didn't find a JNDI value at '" + VHD_JNDI_PATH
|
||||||
|
+ "'.");
|
||||||
|
} else {
|
||||||
|
log.debug("'" + VHD_JNDI_PATH + "' as specified by JNDI: "
|
||||||
|
+ vhdPath);
|
||||||
String message = String.format(
|
String message = String.format(
|
||||||
"JNDI environment '%s' was set to '%s'",
|
"JNDI environment '%s' was set to '%s'",
|
||||||
VHD_JNDI_PATH, vhdPath);
|
VHD_JNDI_PATH, vhdPath);
|
||||||
foundLocations.add(new Found(Paths.get(vhdPath), message));
|
foundLocations.add(new Found(Paths.get(vhdPath), message));
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("JNDI lookup failed. " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void getVhdFromSystemProperties() {
|
private void getVhdFromSystemProperties() {
|
||||||
String vhdPath = System.getProperty(VHD_SYSTEM_PROPERTY);
|
String vhdPath = System.getProperty(VHD_SYSTEM_PROPERTY);
|
||||||
|
|
|
@ -32,10 +32,8 @@ public class ConfigurationPropertiesImpl extends ConfigurationProperties {
|
||||||
|
|
||||||
public ConfigurationPropertiesImpl(InputStream stream,
|
public ConfigurationPropertiesImpl(InputStream stream,
|
||||||
Map<String, String> preemptiveProperties,
|
Map<String, String> preemptiveProperties,
|
||||||
Map<String, String> buildProperties,
|
Map<String, String> buildProperties) throws IOException {
|
||||||
Map<String, String> contextProperties) throws IOException {
|
|
||||||
Map<String, String> map = new HashMap<>(buildProperties);
|
Map<String, String> map = new HashMap<>(buildProperties);
|
||||||
map.putAll(contextProperties);
|
|
||||||
|
|
||||||
Properties props = loadFromPropertiesFile(stream);
|
Properties props = loadFromPropertiesFile(stream);
|
||||||
for (String key: props.stringPropertyNames()) {
|
for (String key: props.stringPropertyNames()) {
|
||||||
|
|
|
@ -49,12 +49,12 @@ public class ConfigurationPropertiesSetup implements ServletContextListener {
|
||||||
/** Name of the file that contains runtime properties. */
|
/** Name of the file that contains runtime properties. */
|
||||||
private static final String FILE_RUNTIME_PROPERTIES = "runtime.properties";
|
private static final String FILE_RUNTIME_PROPERTIES = "runtime.properties";
|
||||||
|
|
||||||
/** Fall-back name of the file that contains runtime properties. */
|
|
||||||
private static final String FILE_DEFAULT_RUNTIME_PROPERTIES = "default.runtime.properties";
|
|
||||||
|
|
||||||
/** Configuration property to store the Vitro home directory */
|
/** Configuration property to store the Vitro home directory */
|
||||||
private static final String VHD_CONFIGURATION_PROPERTY = "vitro.home";
|
private static final String VHD_CONFIGURATION_PROPERTY = "vitro.home";
|
||||||
|
|
||||||
|
/** Configuration property used to determine if there are runtime.properties files in multiple locations **/
|
||||||
|
static final String RP_MULTIPLE = "rp.multiple";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contextInitialized(ServletContextEvent sce) {
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
ServletContext ctx = sce.getServletContext();
|
ServletContext ctx = sce.getServletContext();
|
||||||
|
@ -69,17 +69,18 @@ public class ConfigurationPropertiesSetup implements ServletContextListener {
|
||||||
File vitroHomeDirConfig = new File(vitroHomeDir.getPath()
|
File vitroHomeDirConfig = new File(vitroHomeDir.getPath()
|
||||||
.concat(File.separator).concat("config"));
|
.concat(File.separator).concat("config"));
|
||||||
|
|
||||||
|
String rpfLocation = findMultipleRuntimePropertiesFiles(
|
||||||
|
vitroHomeDir, vitroHomeDirConfig);
|
||||||
|
|
||||||
File runtimePropertiesFile = locateRuntimePropertiesFile(
|
File runtimePropertiesFile = locateRuntimePropertiesFile(
|
||||||
vitroHomeDirConfig, ss);
|
vitroHomeDir, vitroHomeDirConfig, ss);
|
||||||
stream = new FileInputStream(runtimePropertiesFile);
|
stream = new FileInputStream(runtimePropertiesFile);
|
||||||
|
|
||||||
Map<String, String> preempts = createPreemptiveProperties(
|
Map<String, String> preempts = createPreemptiveProperties(
|
||||||
VHD_CONFIGURATION_PROPERTY, vitroHomeDir);
|
VHD_CONFIGURATION_PROPERTY, vitroHomeDir, RP_MULTIPLE, rpfLocation);
|
||||||
|
|
||||||
ConfigurationPropertiesImpl bean = new ConfigurationPropertiesImpl(
|
ConfigurationPropertiesImpl bean = new ConfigurationPropertiesImpl(
|
||||||
stream, preempts,
|
stream, preempts, new BuildProperties(ctx).getMap());
|
||||||
new BuildProperties(ctx).getMap(),
|
|
||||||
new ContextProperties().getMap());
|
|
||||||
|
|
||||||
ConfigurationProperties.setBean(ctx, bean);
|
ConfigurationProperties.setBean(ctx, bean);
|
||||||
ss.info(this, "Loaded " + bean.getPropertyMap().size()
|
ss.info(this, "Loaded " + bean.getPropertyMap().size()
|
||||||
|
@ -98,36 +99,53 @@ public class ConfigurationPropertiesSetup implements ServletContextListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private File locateRuntimePropertiesFile(File vitroHomeDirConfig, StartupStatus ss) {
|
private String findMultipleRuntimePropertiesFiles(File vitroHomeDir,
|
||||||
|
File vitroHomeDirConfig) {
|
||||||
|
|
||||||
// First look for the user-customized runtime.properties
|
File rpf = new File(vitroHomeDir, FILE_RUNTIME_PROPERTIES);
|
||||||
File rpf = new File(vitroHomeDirConfig, FILE_RUNTIME_PROPERTIES);
|
File rpfc = new File(vitroHomeDirConfig, FILE_RUNTIME_PROPERTIES);
|
||||||
|
|
||||||
// Have we found a suitable runtime.properties file?
|
if (rpf.exists() && !rpfc.exists()) {
|
||||||
if (!rpf.exists() || !rpf.isFile() || !rpf.canRead()) {
|
return "home";
|
||||||
|
} else if (rpf.exists() && rpfc.exists()) {
|
||||||
// If not... look for the default runtime.properties
|
return "both";
|
||||||
rpf = new File(vitroHomeDirConfig, FILE_DEFAULT_RUNTIME_PROPERTIES);
|
} else if (rpfc.exists()) {
|
||||||
|
return "config";
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Did not find '"
|
||||||
|
+ FILE_RUNTIME_PROPERTIES + "' in vitro home directory '"
|
||||||
|
+ vitroHomeDir + "' or config directory '" + vitroHomeDirConfig + "'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rpf.exists() || !rpf.isFile()) {
|
private File locateRuntimePropertiesFile(File vitroHomeDir,
|
||||||
throw new IllegalStateException("Neither '" + FILE_RUNTIME_PROPERTIES + "' nor '" +
|
File vitroHomeDirConfig, StartupStatus ss) {
|
||||||
FILE_DEFAULT_RUNTIME_PROPERTIES + "' were found in " +
|
|
||||||
vitroHomeDirConfig.getAbsolutePath());
|
File rpf = new File(vitroHomeDir, FILE_RUNTIME_PROPERTIES);
|
||||||
|
File rpfc = new File(vitroHomeDirConfig, FILE_RUNTIME_PROPERTIES);
|
||||||
|
|
||||||
|
if (!rpf.exists()) {
|
||||||
|
rpf = rpfc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rpf.isFile()) {
|
||||||
|
throw new IllegalStateException("'" + rpf.getPath()
|
||||||
|
+ "' is not a file.");
|
||||||
}
|
}
|
||||||
if (!rpf.canRead()) {
|
if (!rpf.canRead()) {
|
||||||
throw new IllegalStateException("No readable '" + FILE_RUNTIME_PROPERTIES + "' nor '" +
|
throw new IllegalStateException("Cannot read '" + rpf.getPath()
|
||||||
FILE_DEFAULT_RUNTIME_PROPERTIES + "' files were found in " +
|
+ "'.");
|
||||||
vitroHomeDirConfig.getAbsolutePath());
|
|
||||||
}
|
}
|
||||||
ss.info(this, "Loading runtime properties from '" + rpf.getPath() + "'");
|
ss.info(this, "Loading runtime properties from '" + rpf.getPath() + "'");
|
||||||
return rpf;
|
return rpf;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> createPreemptiveProperties(
|
private Map<String, String> createPreemptiveProperties(
|
||||||
String propertyVitroHome, File vitroHomeDir) {
|
String propertyVitroHome, File vitroHomeDir, String propertyRpfMultiple,
|
||||||
|
String rpfLocation) {
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
map.put(propertyVitroHome, vitroHomeDir.getAbsolutePath());
|
map.put(propertyVitroHome, vitroHomeDir.getAbsolutePath());
|
||||||
|
map.put(propertyRpfMultiple, rpfLocation);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ public class ConfigurationPropertiesSmokeTests implements
|
||||||
StartupStatus ss = StartupStatus.getBean(ctx);
|
StartupStatus ss = StartupStatus.getBean(ctx);
|
||||||
|
|
||||||
checkDefaultNamespace(ctx, props, ss);
|
checkDefaultNamespace(ctx, props, ss);
|
||||||
|
checkMultipleRPFs(ctx, props, ss);
|
||||||
checkLanguages(ctx, props, ss);
|
checkLanguages(ctx, props, ss);
|
||||||
checkEncryptionParameters(props, ss);
|
checkEncryptionParameters(props, ss);
|
||||||
|
|
||||||
|
@ -85,6 +86,32 @@ public class ConfigurationPropertiesSmokeTests implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warn if runtime.properties exists in multiple locations
|
||||||
|
* or is located vivo.home instead of vivo.home/config
|
||||||
|
*/
|
||||||
|
private void checkMultipleRPFs(ServletContext ctx,
|
||||||
|
ConfigurationProperties props, StartupStatus ss) {
|
||||||
|
String rpfStatus = props.getProperty(ConfigurationPropertiesSetup.RP_MULTIPLE);
|
||||||
|
|
||||||
|
if (rpfStatus.equals("both")) {
|
||||||
|
ss.warning(this,
|
||||||
|
"Deprecation warning: Files matching the name 'runtime.properties' "
|
||||||
|
+ "were found in both vivo.home and vivo.home/config. Using "
|
||||||
|
+ "the file in vivo.home. Future releases may require "
|
||||||
|
+ "runtime.properties be placed in vivo.home/config.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rpfStatus.equals("home")) {
|
||||||
|
ss.warning(this,
|
||||||
|
"Deprecation warning: runtime.properties was found in the "
|
||||||
|
+ "vivo.home directory. The recommended directory for "
|
||||||
|
+ "runtime.properties is now vivo.home/config. Future releases "
|
||||||
|
+ "may require runtime.properties be placed in "
|
||||||
|
+ "vivo.home/config.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Warn if we set up the languages incorrectly:
|
* Warn if we set up the languages incorrectly:
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in LICENSE$ */
|
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.config;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.naming.InitialContext;
|
|
||||||
import javax.naming.NamingException;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains and provides the properties from the web application's context.xml
|
|
||||||
*
|
|
||||||
* @author awoods
|
|
||||||
* @since 2020-10-23
|
|
||||||
*/
|
|
||||||
public class ContextProperties {
|
|
||||||
private static final Log log = LogFactory.getLog(ContextProperties.class);
|
|
||||||
|
|
||||||
private static final String DEFAULT_NAMESPACE_JNDI_PATH = "java:comp/env/vitro/defaultNamespace";
|
|
||||||
private static final String ROOT_USER_ADDRESS_JNDI_PATH = "java:comp/env/vitro/rootUserAddress";
|
|
||||||
private static final String APP_NAME_JNDI_PATH = "java:comp/env/vitro/appName";
|
|
||||||
|
|
||||||
private static final String DEFAULT_NAMESPACE_KEY = "Vitro.defaultNamespace";
|
|
||||||
private static final String ROOT_USER_ADDRESS_KEY = "rootUser.emailAddress";
|
|
||||||
private static final String APP_NAME_KEY = "app-name";
|
|
||||||
|
|
||||||
private final Map<String, String> propertyMap;
|
|
||||||
|
|
||||||
public ContextProperties() {
|
|
||||||
Map<String, String> map = new HashMap<>();
|
|
||||||
|
|
||||||
// Find default namespace
|
|
||||||
map.put(DEFAULT_NAMESPACE_KEY, findJndiProperty(DEFAULT_NAMESPACE_JNDI_PATH));
|
|
||||||
|
|
||||||
// Find root user email address
|
|
||||||
map.put(ROOT_USER_ADDRESS_KEY, findJndiProperty(ROOT_USER_ADDRESS_JNDI_PATH));
|
|
||||||
|
|
||||||
// Find application name
|
|
||||||
map.put(APP_NAME_KEY, findJndiProperty(APP_NAME_JNDI_PATH));
|
|
||||||
|
|
||||||
propertyMap = Collections.unmodifiableMap(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String findJndiProperty(String jndiProperty) {
|
|
||||||
try {
|
|
||||||
return (String) new InitialContext().lookup(jndiProperty);
|
|
||||||
|
|
||||||
} catch (NamingException e) {
|
|
||||||
log.error("Unable to find name in JNDI: " + jndiProperty, e);
|
|
||||||
|
|
||||||
StringBuilder msg = new StringBuilder("\n====================\n");
|
|
||||||
msg.append("Error loading JNDI property: ");
|
|
||||||
msg.append(jndiProperty);
|
|
||||||
msg.append("\n");
|
|
||||||
msg.append("\tAn application context XML file (named after deployed war file, e.g. vivo.xml) ");
|
|
||||||
msg.append("must be placed in servlet container.\n");
|
|
||||||
msg.append("\tFor Tomcat, see documentation for location of file: \n");
|
|
||||||
msg.append("\t\thttps://tomcat.apache.org/tomcat-9.0-doc/config/context.html#Defining_a_context \n");
|
|
||||||
msg.append("\tThe common location on the server is: $CATALINA_BASE/conf/[enginename]/[hostname]/ \n");
|
|
||||||
msg.append("\t\te.g. /var/lib/tomcat9/conf/Catalina/localhost/vivo.xml\n");
|
|
||||||
msg.append("\tAn example 'context.xml' file is in the META-INF directory of this project.\n");
|
|
||||||
msg.append("====================\n");
|
|
||||||
throw new RuntimeException(msg.toString(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> getMap() {
|
|
||||||
return this.propertyMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -202,23 +202,18 @@ public class DeveloperSettings {
|
||||||
File dsFile = homeDir.resolve("config/developer.properties")
|
File dsFile = homeDir.resolve("config/developer.properties")
|
||||||
.toFile();
|
.toFile();
|
||||||
|
|
||||||
if (!dsFile.exists()) {
|
|
||||||
dsFile = homeDir.resolve("config/default.developer.properties").toFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
try (FileReader reader = new FileReader(dsFile)) {
|
try (FileReader reader = new FileReader(dsFile)) {
|
||||||
Properties dsProps = new Properties();
|
Properties dsProps = new Properties();
|
||||||
dsProps.load(reader);
|
dsProps.load(reader);
|
||||||
devSettings.updateFromProperties(dsProps);
|
devSettings.updateFromProperties(dsProps);
|
||||||
log.info(devSettings);
|
log.info(devSettings);
|
||||||
ss.info(this, "Loaded the '" + dsFile.getName() + "' file: "
|
ss.info(this, "Loaded the 'developer.properties' file: "
|
||||||
+ devSettings);
|
+ devSettings);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
ss.info(this, "Neither 'developer.properties' nor 'default.developer.properties' " +
|
ss.info(this, "'developer.properties' file does not exist.");
|
||||||
"files exist.");
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ss.warning(this,
|
ss.warning(this,
|
||||||
"Failed to load the '" + dsFile.getAbsolutePath() + "' file.", e);
|
"Failed to load the 'developer.properties' file.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,19 @@
|
||||||
#
|
#
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#
|
||||||
|
# This namespace will be used when generating URIs for objects created in the
|
||||||
|
# editor. In order to serve linked data, the default namespace must be composed
|
||||||
|
# as follows (optional elements in parentheses):
|
||||||
|
#
|
||||||
|
# scheme + server_name (+ port) (+ servlet_context) + "/individual/"
|
||||||
|
#
|
||||||
|
# For example, Cornell's default namespace is:
|
||||||
|
#
|
||||||
|
# http://vivo.cornell.edu/individual/
|
||||||
|
#
|
||||||
|
Vitro.defaultNamespace = http://vivo.mydomain.edu/individual/
|
||||||
|
|
||||||
#
|
#
|
||||||
# URL of Solr context used in local Vitro search. This will usually consist of:
|
# URL of Solr context used in local Vitro search. This will usually consist of:
|
||||||
# scheme + server_name + port + vitro_webapp_name + "solr"
|
# scheme + server_name + port + vitro_webapp_name + "solr"
|
||||||
|
@ -57,6 +70,13 @@ VitroConnection.DataSource.dbtype = MySQL
|
||||||
VitroConnection.DataSource.driver = com.mysql.jdbc.Driver
|
VitroConnection.DataSource.driver = com.mysql.jdbc.Driver
|
||||||
VitroConnection.DataSource.validationQuery = SELECT 1
|
VitroConnection.DataSource.validationQuery = SELECT 1
|
||||||
|
|
||||||
|
#
|
||||||
|
# The email address of the root user for the VIVO application. The password
|
||||||
|
# for this user is initially set to "rootPassword", but you will be asked to
|
||||||
|
# change the password the first time you log in.
|
||||||
|
#
|
||||||
|
rootUser.emailAddress = root@myDomain.com
|
||||||
|
|
||||||
#
|
#
|
||||||
# Argon2 password hashing parameters for time, memory and parallelism required to
|
# Argon2 password hashing parameters for time, memory and parallelism required to
|
||||||
# compute a hash.
|
# compute a hash.
|
21
installer/example-settings.xml
Normal file
21
installer/example-settings.xml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>defaults</id>
|
||||||
|
<properties>
|
||||||
|
<app-name>vitro</app-name>
|
||||||
|
|
||||||
|
<vitro-dir>/usr/local/vitro/home</vitro-dir>
|
||||||
|
<tomcat-dir>/usr/local/tomcat</tomcat-dir>
|
||||||
|
|
||||||
|
<default-theme>vitro</default-theme>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<activeProfiles>
|
||||||
|
<activeProfile>defaults</activeProfile>
|
||||||
|
</activeProfiles>
|
||||||
|
</settings>
|
|
@ -1,51 +1,8 @@
|
||||||
<Context> <!-- useHttpOnly="false" -->
|
<Context> <!-- useHttpOnly="false" -->
|
||||||
|
|
||||||
<!--
|
|
||||||
# The 'home' property specifies the location of Vitro HOME.
|
|
||||||
# The system user used to run the Vitro web application must have write access
|
|
||||||
# to the parent directory of the directory defined in this property, if Vitro HOME
|
|
||||||
# does not already exist.
|
|
||||||
# If this directory already exists, the system user used to run the Vitro web application
|
|
||||||
# must have write access to this directory.
|
|
||||||
-->
|
|
||||||
<Environment
|
<Environment
|
||||||
type="java.lang.String"
|
type="java.lang.String"
|
||||||
name="vitro/home"
|
name="vitro/home"
|
||||||
value="${vivo-dir}" override="true"/>
|
value="${vitro-dir}" override="true"/>
|
||||||
|
|
||||||
<!--
|
|
||||||
# The name of the application (possibly not used).
|
|
||||||
-->
|
|
||||||
<Environment
|
|
||||||
type="java.lang.String"
|
|
||||||
name="vitro/appName"
|
|
||||||
value="vivo" override="true"/>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
# The email address of the root user for the Vitro application. The password
|
|
||||||
# for this user is initially set to "rootPassword", but you will be asked to
|
|
||||||
# change the password the first time you log in.
|
|
||||||
-->
|
|
||||||
<Environment
|
|
||||||
type="java.lang.String"
|
|
||||||
name="vitro/rootUserAddress"
|
|
||||||
value="vivo_root@mydomain.edu" override="true"/>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
# This namespace will be used when generating URIs for objects created in the
|
|
||||||
# editor. In order to serve linked data, the default namespace must be composed
|
|
||||||
# as follows (optional elements in parentheses):
|
|
||||||
#
|
|
||||||
# scheme + server_name (+ port) (+ servlet_context) + "/individual/"
|
|
||||||
#
|
|
||||||
# For example, Cornell's default namespace is:
|
|
||||||
#
|
|
||||||
# http://vivo.cornell.edu/individual/
|
|
||||||
-->
|
|
||||||
<Environment
|
|
||||||
type="java.lang.String"
|
|
||||||
name="vitro/defaultNamespace"
|
|
||||||
value="http://vivo.mydomain.edu/individual/" override="true"/>
|
|
||||||
|
|
||||||
<!-- Disable persist sessions on shut down.-->
|
<!-- Disable persist sessions on shut down.-->
|
||||||
<Manager pathname="" />
|
<Manager pathname="" />
|
||||||
|
|
Loading…
Add table
Reference in a new issue