From bd48d160a50a6e69387ecfd11db0cbc96c8e80c3 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 23 Feb 2023 14:06:46 -0600 Subject: [PATCH] Create vivo/home on application start-up (#192.1) --- .../webapp/application/ApplicationSetup.java | 15 +- .../application/VitroHomeDirectory.java | 261 ++++++++++++++++-- .../config/ConfigurationPropertiesImpl.java | 4 +- .../config/ConfigurationPropertiesSetup.java | 64 ++--- .../ConfigurationPropertiesSmokeTests.java | 27 -- .../webapp/config/ContextProperties.java | 76 +++++ .../utils/developer/DeveloperSettings.java | 11 +- ...onSetup.n3 => default.applicationSetup.n3} | 0 ...roperties => default.developer.properties} | 0 ....properties => default.runtime.properties} | 20 -- .../main/webResources/META-INF/context.xml | 45 ++- 11 files changed, 409 insertions(+), 114 deletions(-) create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ContextProperties.java rename home/src/main/resources/config/{example.applicationSetup.n3 => default.applicationSetup.n3} (100%) rename home/src/main/resources/config/{example.developer.properties => default.developer.properties} (100%) rename home/src/main/resources/config/{example.runtime.properties => default.runtime.properties} (90%) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/ApplicationSetup.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/ApplicationSetup.java index a8fd8aa2fd..5b0ecace9c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/ApplicationSetup.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/ApplicationSetup.java @@ -24,6 +24,7 @@ */ public class ApplicationSetup implements ServletContextListener { 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 StartupStatus ss; @@ -45,6 +46,8 @@ public void contextInitialized(ServletContextEvent sce) { this.vitroHomeDir = VitroHomeDirectory.find(ctx); ss.info(this, vitroHomeDir.getDiscoveryMessage()); + this.vitroHomeDir.populate(); + locateApplicationConfigFile(); loadApplicationConfigFile(); createConfigurationBeanLoader(); @@ -63,11 +66,19 @@ public void contextInitialized(ServletContextEvent sce) { private void locateApplicationConfigFile() { 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)) { - throw new IllegalStateException("'" + path + "' does not exist."); + throw new IllegalStateException("Neither '" + APPLICATION_SETUP_PATH + "' nor '" + + APPLICATION_SETUP_DEFAULT_PATH + "' were found in " + + this.vitroHomeDir.getPath()); } if (!Files.isReadable(path)) { - throw new IllegalStateException("Can't read '" + path + "'"); + throw new IllegalStateException("No readable '" + APPLICATION_SETUP_PATH + "' nor '" + + APPLICATION_SETUP_DEFAULT_PATH + "' files were found in " + + this.vitroHomeDir.getPath()); } this.configFile = path; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/VitroHomeDirectory.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/VitroHomeDirectory.java index b55f9d87ed..a5269e4994 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/VitroHomeDirectory.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/application/VitroHomeDirectory.java @@ -4,25 +4,46 @@ 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.Path; import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; -import javax.naming.InitialContext; 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.LogFactory; +import edu.cornell.mannlib.vitro.webapp.config.ContextProperties; + /** - * Encapsulates some of the info relating to the Vitro home directory. + * Encapsulates some of the info relating to and initializes the Vitro home directory. */ public class VitroHomeDirectory { 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) { HomeDirectoryFinder finder = new HomeDirectoryFinder(ctx); return new VitroHomeDirectory(ctx, finder.getPath(), @@ -52,6 +73,219 @@ public String getDiscoveryMessage() { 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 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 untar(File destination) { + log.info("Syncing VIVO home at: " + destination.getPath()); + + Map digest = new HashMap<>(); + Map 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 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; ` *`. + * + * @param digest checksum digest to write + */ + private void writeDigest(Map digest) { + File storedDigest = new File(getPath().toFile(), DIGEST_FILE_NAME); + try ( + FileOutputStream fos = new FileOutputStream(storedDigest); + OutputStreamWriter osw = new OutputStreamWriter(fos); + ) { + for (Map.Entry 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 ` *` + * @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. * Look in the JDNI environment, the system properties, and the @@ -92,23 +326,12 @@ public Path getPath() { } public void getVhdFromJndi() { - try { - 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( - "JNDI environment '%s' was set to '%s'", - VHD_JNDI_PATH, vhdPath); - foundLocations.add(new Found(Paths.get(vhdPath), message)); - } - } catch (Exception e) { - log.debug("JNDI lookup failed. " + e); - } + String vhdPath = ContextProperties.findJndiProperty(VHD_JNDI_PATH); + log.debug("'" + VHD_JNDI_PATH + "' as specified by JNDI: " + vhdPath); + String message = String.format( + "JNDI environment '%s' was set to '%s'", + VHD_JNDI_PATH, vhdPath); + foundLocations.add(new Found(Paths.get(vhdPath), message)); } private void getVhdFromSystemProperties() { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesImpl.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesImpl.java index 3e99518823..929c76dfd9 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesImpl.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesImpl.java @@ -32,8 +32,10 @@ public class ConfigurationPropertiesImpl extends ConfigurationProperties { public ConfigurationPropertiesImpl(InputStream stream, Map preemptiveProperties, - Map buildProperties) throws IOException { + Map buildProperties, + Map contextProperties) throws IOException { Map map = new HashMap<>(buildProperties); + map.putAll(contextProperties); Properties props = loadFromPropertiesFile(stream); for (String key: props.stringPropertyNames()) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSetup.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSetup.java index 54d0ac90d0..d0e20b35a6 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSetup.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSetup.java @@ -49,12 +49,12 @@ public class ConfigurationPropertiesSetup implements ServletContextListener { /** Name of the file that contains 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 */ 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 public void contextInitialized(ServletContextEvent sce) { ServletContext ctx = sce.getServletContext(); @@ -69,18 +69,17 @@ public void contextInitialized(ServletContextEvent sce) { File vitroHomeDirConfig = new File(vitroHomeDir.getPath() .concat(File.separator).concat("config")); - String rpfLocation = findMultipleRuntimePropertiesFiles( - vitroHomeDir, vitroHomeDirConfig); - File runtimePropertiesFile = locateRuntimePropertiesFile( - vitroHomeDir, vitroHomeDirConfig, ss); + vitroHomeDirConfig, ss); stream = new FileInputStream(runtimePropertiesFile); Map preempts = createPreemptiveProperties( - VHD_CONFIGURATION_PROPERTY, vitroHomeDir, RP_MULTIPLE, rpfLocation); + VHD_CONFIGURATION_PROPERTY, vitroHomeDir); ConfigurationPropertiesImpl bean = new ConfigurationPropertiesImpl( - stream, preempts, new BuildProperties(ctx).getMap()); + stream, preempts, + new BuildProperties(ctx).getMap(), + new ContextProperties().getMap()); ConfigurationProperties.setBean(ctx, bean); ss.info(this, "Loaded " + bean.getPropertyMap().size() @@ -99,53 +98,36 @@ public void contextInitialized(ServletContextEvent sce) { } } - private String findMultipleRuntimePropertiesFiles(File vitroHomeDir, - File vitroHomeDirConfig) { - - File rpf = new File(vitroHomeDir, FILE_RUNTIME_PROPERTIES); - File rpfc = new File(vitroHomeDirConfig, FILE_RUNTIME_PROPERTIES); - - if (rpf.exists() && !rpfc.exists()) { - return "home"; - } else if (rpf.exists() && rpfc.exists()) { - return "both"; - } 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 + "'"); - } - } + private File locateRuntimePropertiesFile(File vitroHomeDirConfig, StartupStatus ss) { - private File locateRuntimePropertiesFile(File vitroHomeDir, - File vitroHomeDirConfig, StartupStatus ss) { + // First look for the user-customized runtime.properties + File rpf = new File(vitroHomeDirConfig, FILE_RUNTIME_PROPERTIES); - File rpf = new File(vitroHomeDir, FILE_RUNTIME_PROPERTIES); - File rpfc = new File(vitroHomeDirConfig, FILE_RUNTIME_PROPERTIES); + // Have we found a suitable runtime.properties file? + if (!rpf.exists() || !rpf.isFile() || !rpf.canRead()) { - if (!rpf.exists()) { - rpf = rpfc; + // If not... look for the default runtime.properties + rpf = new File(vitroHomeDirConfig, FILE_DEFAULT_RUNTIME_PROPERTIES); } - if (!rpf.isFile()) { - throw new IllegalStateException("'" + rpf.getPath() - + "' is not a file."); + if (!rpf.exists() || !rpf.isFile()) { + throw new IllegalStateException("Neither '" + FILE_RUNTIME_PROPERTIES + "' nor '" + + FILE_DEFAULT_RUNTIME_PROPERTIES + "' were found in " + + vitroHomeDirConfig.getAbsolutePath()); } if (!rpf.canRead()) { - throw new IllegalStateException("Cannot read '" + rpf.getPath() - + "'."); + throw new IllegalStateException("No readable '" + FILE_RUNTIME_PROPERTIES + "' nor '" + + FILE_DEFAULT_RUNTIME_PROPERTIES + "' files were found in " + + vitroHomeDirConfig.getAbsolutePath()); } ss.info(this, "Loading runtime properties from '" + rpf.getPath() + "'"); return rpf; } private Map createPreemptiveProperties( - String propertyVitroHome, File vitroHomeDir, String propertyRpfMultiple, - String rpfLocation) { + String propertyVitroHome, File vitroHomeDir) { Map map = new HashMap(); map.put(propertyVitroHome, vitroHomeDir.getAbsolutePath()); - map.put(propertyRpfMultiple, rpfLocation); return map; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java index 80fba112e0..358ffeb150 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java @@ -48,7 +48,6 @@ public void contextInitialized(ServletContextEvent sce) { StartupStatus ss = StartupStatus.getBean(ctx); checkDefaultNamespace(ctx, props, ss); - checkMultipleRPFs(ctx, props, ss); checkLanguages(ctx, props, ss); checkEncryptionParameters(props, ss); @@ -86,32 +85,6 @@ private void checkDefaultNamespace(ServletContext ctx, } } - /** - * 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: * diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ContextProperties.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ContextProperties.java new file mode 100644 index 0000000000..a7e04b0e93 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ContextProperties.java @@ -0,0 +1,76 @@ +/* $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 propertyMap; + + public ContextProperties() { + Map 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 getMap() { + return this.propertyMap; + } + +} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettings.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettings.java index b030db0083..09f97db469 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettings.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/developer/DeveloperSettings.java @@ -202,18 +202,23 @@ public void contextInitialized(ServletContextEvent sce) { File dsFile = homeDir.resolve("config/developer.properties") .toFile(); + if (!dsFile.exists()) { + dsFile = homeDir.resolve("config/default.developer.properties").toFile(); + } + try (FileReader reader = new FileReader(dsFile)) { Properties dsProps = new Properties(); dsProps.load(reader); devSettings.updateFromProperties(dsProps); log.info(devSettings); - ss.info(this, "Loaded the 'developer.properties' file: " + ss.info(this, "Loaded the '" + dsFile.getName() + "' file: " + devSettings); } catch (FileNotFoundException e) { - ss.info(this, "'developer.properties' file does not exist."); + ss.info(this, "Neither 'developer.properties' nor 'default.developer.properties' " + + "files exist."); } catch (Exception e) { ss.warning(this, - "Failed to load the 'developer.properties' file.", e); + "Failed to load the '" + dsFile.getAbsolutePath() + "' file.", e); } } diff --git a/home/src/main/resources/config/example.applicationSetup.n3 b/home/src/main/resources/config/default.applicationSetup.n3 similarity index 100% rename from home/src/main/resources/config/example.applicationSetup.n3 rename to home/src/main/resources/config/default.applicationSetup.n3 diff --git a/home/src/main/resources/config/example.developer.properties b/home/src/main/resources/config/default.developer.properties similarity index 100% rename from home/src/main/resources/config/example.developer.properties rename to home/src/main/resources/config/default.developer.properties diff --git a/home/src/main/resources/config/example.runtime.properties b/home/src/main/resources/config/default.runtime.properties similarity index 90% rename from home/src/main/resources/config/example.runtime.properties rename to home/src/main/resources/config/default.runtime.properties index 989cf19e3f..741b2b1c35 100644 --- a/home/src/main/resources/config/example.runtime.properties +++ b/home/src/main/resources/config/default.runtime.properties @@ -9,19 +9,6 @@ # # ----------------------------------------------------------------------------- -# -# 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: # scheme + server_name + port + "solr" + solr_core_name @@ -92,13 +79,6 @@ email.replyTo = # # listview.usePreciseSubquery = true -# -# 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 # compute a hash. diff --git a/installer/webapp/src/main/webResources/META-INF/context.xml b/installer/webapp/src/main/webResources/META-INF/context.xml index 53ea22ae5f..ac110751c3 100644 --- a/installer/webapp/src/main/webResources/META-INF/context.xml +++ b/installer/webapp/src/main/webResources/META-INF/context.xml @@ -1,8 +1,51 @@ + + + value="${vivo-dir}" override="true"/> + + + + + + + + +