You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2018/11/08 13:02:05 UTC

svn commit: r1846135 - in /tomcat/trunk: ./ java/org/apache/catalina/realm/ java/org/apache/catalina/startup/ java/org/apache/catalina/users/ java/org/apache/catalina/valves/rewrite/ java/org/apache/tomcat/util/file/ java/org/apache/tomcat/util/net/ ja...

Author: remm
Date: Thu Nov  8 13:02:05 2018
New Revision: 1846135

URL: http://svn.apache.org/viewvc?rev=1846135&view=rev
Log:
Add ConfigurationSource to improve on ConfigFileLoader and allow more flexibility for configuration files, while standardizing access to most container configuration resources. Previously each of server.xml, web.xml and context.xml used specific additional secret paths and classloader lookups.
Exceptions: JASPIC (both read and write), memory user database (write), OpenSSL configuration (certificate files) and storeconfig (write) continue to use regular file access.
Add a new Tomcat.init(ConfigurationSource) that allows using the regular configuration "files" to configure the embedded instance rather than Java code. Otherwise, embedding necessarily meant lots of code and ultimately reinventing the content of server.xml.

Added:
    tomcat/trunk/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java   (with props)
    tomcat/trunk/java/org/apache/tomcat/util/file/ConfigurationSource.java   (with props)
    tomcat/trunk/test/org/apache/catalina/startup/TestTomcatStandalone.java
Modified:
    tomcat/trunk/TOMCAT-NEXT.txt
    tomcat/trunk/java/org/apache/catalina/realm/MemoryRealm.java
    tomcat/trunk/java/org/apache/catalina/startup/Catalina.java
    tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java
    tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java
    tomcat/trunk/java/org/apache/catalina/users/MemoryUserDatabase.java
    tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java
    tomcat/trunk/java/org/apache/tomcat/util/file/ConfigFileLoader.java
    tomcat/trunk/java/org/apache/tomcat/util/file/LocalStrings.properties
    tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java
    tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java
    tomcat/trunk/java/org/apache/tomcat/util/net/jsse/PEMFile.java
    tomcat/trunk/test/org/apache/tomcat/util/file/TestConfigFileLoader.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/TOMCAT-NEXT.txt
URL: http://svn.apache.org/viewvc/tomcat/trunk/TOMCAT-NEXT.txt?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/TOMCAT-NEXT.txt (original)
+++ tomcat/trunk/TOMCAT-NEXT.txt Thu Nov  8 13:02:05 2018
@@ -37,5 +37,3 @@ New items for 10.0.x onwards:
 
 3.  Remove the ExtensionValidator and associated classes (assuming that the
     minimum Java version is Java 9 or later).
-
-4.  New embedded APIs (likely also for 9.x).

Modified: tomcat/trunk/java/org/apache/catalina/realm/MemoryRealm.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/MemoryRealm.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/MemoryRealm.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/MemoryRealm.java Thu Nov  8 13:02:05 2018
@@ -239,7 +239,7 @@ public class MemoryRealm  extends RealmB
     @Override
     protected void startInternal() throws LifecycleException {
         String pathName = getPathname();
-        try (InputStream is = ConfigFileLoader.getInputStream(pathName)) {
+        try (InputStream is = ConfigFileLoader.getSource().getResource(pathName).getInputStream()) {
             // Load the contents of the database file
             if (log.isDebugEnabled()) {
                 log.debug(sm.getString("memoryRealm.loadPath", pathName));

Modified: tomcat/trunk/java/org/apache/catalina/startup/Catalina.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/Catalina.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/Catalina.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/Catalina.java Thu Nov  8 13:02:05 2018
@@ -45,11 +45,12 @@ import org.apache.tomcat.util.ExceptionU
 import org.apache.tomcat.util.digester.Digester;
 import org.apache.tomcat.util.digester.Rule;
 import org.apache.tomcat.util.digester.RuleSet;
+import org.apache.tomcat.util.file.ConfigFileLoader;
+import org.apache.tomcat.util.file.ConfigurationSource;
 import org.apache.tomcat.util.log.SystemLogHandler;
 import org.apache.tomcat.util.res.StringManager;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
-import org.xml.sax.SAXParseException;
 
 
 /**
@@ -79,6 +80,7 @@ public class Catalina {
     protected static final StringManager sm =
         StringManager.getManager(Constants.Package);
 
+    public static final String SERVER_XML = "conf/server.xml";
 
     // ----------------------------------------------------- Instance Variables
 
@@ -90,7 +92,7 @@ public class Catalina {
     /**
      * Pathname to the server configuration file.
      */
-    protected String configFile = "conf/server.xml";
+    protected String configFile = SERVER_XML;
 
     // XXX Should be moved to embedded
     /**
@@ -549,89 +551,29 @@ public class Catalina {
         // Before digester - it may be needed
         initNaming();
 
+        // Set configuration source
+        ConfigFileLoader.setSource(new CatalinaBaseConfigurationSource(Bootstrap.getCatalinaBaseFile(), getConfigFile()));
+        File file = configFile();
+
         // Create and execute our Digester
         Digester digester = createStartDigester();
 
-        InputSource inputSource = null;
-        InputStream inputStream = null;
-        File file = null;
-        try {
-            try {
-                file = configFile();
-                inputStream = new FileInputStream(file);
-                inputSource = new InputSource(file.toURI().toURL().toString());
-            } catch (Exception e) {
-                if (log.isDebugEnabled()) {
-                    log.debug(sm.getString("catalina.configFail", file), e);
-                }
-            }
-            if (inputStream == null) {
-                try {
-                    inputStream = getClass().getClassLoader()
-                        .getResourceAsStream(getConfigFile());
-                    inputSource = new InputSource
-                        (getClass().getClassLoader()
-                         .getResource(getConfigFile()).toString());
-                } catch (Exception e) {
-                    if (log.isDebugEnabled()) {
-                        log.debug(sm.getString("catalina.configFail",
-                                getConfigFile()), e);
-                    }
-                }
-            }
-
-            // This should be included in catalina.jar
-            // Alternative: don't bother with xml, just create it manually.
-            if (inputStream == null) {
-                try {
-                    inputStream = getClass().getClassLoader()
-                            .getResourceAsStream("server-embed.xml");
-                    inputSource = new InputSource
-                    (getClass().getClassLoader()
-                            .getResource("server-embed.xml").toString());
-                } catch (Exception e) {
-                    if (log.isDebugEnabled()) {
-                        log.debug(sm.getString("catalina.configFail",
-                                "server-embed.xml"), e);
-                    }
-                }
-            }
-
-
-            if (inputStream == null || inputSource == null) {
-                if  (file == null) {
-                    log.warn(sm.getString("catalina.configFail",
-                            getConfigFile() + "] or [server-embed.xml]"));
-                } else {
-                    log.warn(sm.getString("catalina.configFail",
-                            file.getAbsolutePath()));
-                    if (file.exists() && !file.canRead()) {
-                        log.warn("Permissions incorrect, read permission is not allowed on the file.");
-                    }
-                }
-                return;
-            }
-
-            try {
-                inputSource.setByteStream(inputStream);
-                digester.push(this);
-                digester.parse(inputSource);
-            } catch (SAXParseException spe) {
-                log.warn("Catalina.start using " + getConfigFile() + ": " +
-                        spe.getMessage());
-                return;
-            } catch (Exception e) {
-                log.warn("Catalina.start using " + getConfigFile() + ": " , e);
-                return;
-            }
-        } finally {
-            if (inputStream != null) {
-                try {
-                    inputStream.close();
-                } catch (IOException e) {
-                    // Ignore
+        try (ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getServerXml()) {
+            InputStream inputStream = resource.getInputStream();
+            InputSource inputSource = new InputSource(resource.getURI().toURL().toString());
+            inputSource.setByteStream(inputStream);
+            digester.push(this);
+            digester.parse(inputSource);
+        } catch (Exception e) {
+            if  (file == null) {
+                log.warn(sm.getString("catalina.configFail", getConfigFile() + "] or [server-embed.xml]"), e);
+            } else {
+                log.warn(sm.getString("catalina.configFail", file.getAbsolutePath()), e);
+                if (file.exists() && !file.canRead()) {
+                    log.warn("Permissions incorrect, read permission is not allowed on the file.");
                 }
             }
+            return;
         }
 
         getServer().setCatalina(this);

Added: tomcat/trunk/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java?rev=1846135&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java (added)
+++ tomcat/trunk/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java Thu Nov  8 13:02:05 2018
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.startup;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.apache.tomcat.util.file.ConfigurationSource;
+import org.apache.tomcat.util.res.StringManager;
+
+public class CatalinaBaseConfigurationSource implements ConfigurationSource {
+
+    protected static final StringManager sm = StringManager.getManager(Constants.Package);
+
+    private final String serverXmlPath;
+    private final File catalinaBaseFile;
+    private final URI catalinaBaseUri;
+
+    public CatalinaBaseConfigurationSource(File catalinaBaseFile, String serverXmlPath) {
+        this.catalinaBaseFile = catalinaBaseFile;
+        catalinaBaseUri = catalinaBaseFile.toURI();
+        this.serverXmlPath = serverXmlPath;
+    }
+
+    @Override
+    public Resource getServerXml() throws IOException {
+        IOException ioe = null;
+        Resource result = null;
+        try {
+            if (serverXmlPath == null || serverXmlPath.equals(Catalina.SERVER_XML)) {
+                result = ConfigurationSource.super.getServerXml();
+            } else {
+                result = getResource(serverXmlPath);
+            }
+        } catch (IOException e) {
+            ioe = e;
+        }
+        if (result == null) {
+            InputStream inputStream = getClass().getClassLoader().getResourceAsStream("server-embed.xml");
+            if (inputStream != null) {
+                try {
+                    result = new Resource(inputStream, getClass().getClassLoader().getResource("server-embed.xml").toURI());
+                } catch (URISyntaxException e) {
+                    // Ignore
+                }
+            }
+        }
+        if (result == null) {
+            throw ioe;
+        } else {
+            return result;
+        }
+    }
+
+    @Override
+    public Resource getResource(String name) throws IOException {
+        // Location was originally always a file before URI support was added so
+        // try file first.
+
+        File f = new File(name);
+        if (!f.isAbsolute()) {
+            f = new File(catalinaBaseFile, name);
+        }
+        if (f.isFile()) {
+            return new Resource(new FileInputStream(f), f.toURI());
+        }
+
+        // Try classloader
+        InputStream stream = getClass().getClassLoader().getResourceAsStream(name);
+        try {
+            if (stream != null) {
+                return new Resource(stream, getClass().getClassLoader().getResource(name).toURI());
+            }
+        } catch (URISyntaxException e) {
+            throw new IOException(sm.getString("catalinaConfigurationSource.cannotObtainURL", name), e);
+        }
+
+        // Then try URI.
+        URI uri = getURI(name);
+
+        // Obtain the input stream we need
+        try {
+            URL url = uri.toURL();
+            return new Resource(url.openConnection().getInputStream(), uri);
+        } catch (IllegalArgumentException e) {
+            throw new IOException(sm.getString("catalinaConfigurationSource.cannotObtainURL", name), e);
+        }
+    }
+
+    @Override
+    public URI getURI(String name) {
+        File f = new File(name);
+        if (!f.isAbsolute()) {
+            f = new File(catalinaBaseFile, name);
+        }
+        if (f.isFile()) {
+            return f.toURI();
+        }
+
+        // Try classloader
+        try {
+            URL resource = getClass().getClassLoader().getResource(name);
+            if (resource != null) {
+                return resource.toURI();
+            }
+        } catch (Exception e) {
+            // Ignore
+        }
+
+        // Then try URI.
+        // Using resolve() enables the code to handle relative paths that did
+        // not point to a file
+        URI uri;
+        if (catalinaBaseUri != null) {
+            uri = catalinaBaseUri.resolve(name);
+        } else {
+            uri = URI.create(name);
+        }
+        return uri;
+    }
+
+}

Propchange: tomcat/trunk/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Thu Nov  8 13:02:05 2018
@@ -104,6 +104,8 @@ import org.apache.tomcat.util.descriptor
 import org.apache.tomcat.util.descriptor.web.WebXmlParser;
 import org.apache.tomcat.util.digester.Digester;
 import org.apache.tomcat.util.digester.RuleSet;
+import org.apache.tomcat.util.file.ConfigFileLoader;
+import org.apache.tomcat.util.file.ConfigurationSource;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.tomcat.util.scan.JarFactory;
 import org.xml.sax.InputSource;
@@ -458,34 +460,29 @@ public class ContextConfig implements Li
         }
 
         if (!context.getOverride()) {
-            File defaultContextFile = new File(defaultContextXml);
-            if (!defaultContextFile.isAbsolute()) {
-                defaultContextFile =
-                        new File(context.getCatalinaBase(), defaultContextXml);
-            }
-            if (defaultContextFile.exists()) {
-                try {
-                    URL defaultContextUrl = defaultContextFile.toURI().toURL();
-                    processContextConfig(digester, defaultContextUrl);
-                } catch (MalformedURLException e) {
-                    log.error(sm.getString(
-                            "contextConfig.badUrl", defaultContextFile), e);
-                }
+            try (ConfigurationSource.Resource contextXmlResource =
+                    ConfigFileLoader.getSource().getResource(defaultContextXml)) {
+                URL defaultContextUrl = contextXmlResource.getURI().toURL();
+                processContextConfig(digester, defaultContextUrl, contextXmlResource.getInputStream());
+            } catch (MalformedURLException e) {
+                log.error(sm.getString("contextConfig.badUrl", defaultContextXml), e);
+            } catch (IOException e) {
+                // Not found
             }
 
-            File hostContextFile = new File(getHostConfigBase(), Constants.HostContextXml);
-            if (hostContextFile.exists()) {
-                try {
-                    URL hostContextUrl = hostContextFile.toURI().toURL();
-                    processContextConfig(digester, hostContextUrl);
-                } catch (MalformedURLException e) {
-                    log.error(sm.getString(
-                            "contextConfig.badUrl", hostContextFile), e);
-                }
+            String hostContextFile = Container.getConfigPath(context, Constants.HostContextXml);
+            try (ConfigurationSource.Resource contextXmlResource =
+                    ConfigFileLoader.getSource().getConfResource(hostContextFile)) {
+                URL defaultContextUrl = contextXmlResource.getURI().toURL();
+                processContextConfig(digester, defaultContextUrl, contextXmlResource.getInputStream());
+            } catch (MalformedURLException e) {
+                log.error(sm.getString("contextConfig.badUrl", hostContextFile), e);
+            } catch (IOException e) {
+                // Not found
             }
         }
         if (context.getConfigFile() != null) {
-            processContextConfig(digester, context.getConfigFile());
+            processContextConfig(digester, context.getConfigFile(), null);
         }
 
     }
@@ -495,8 +492,9 @@ public class ContextConfig implements Li
      * Process a context.xml.
      * @param digester The digester that will be used for XML parsing
      * @param contextXml The URL to the context.xml configuration
+     * @param stream The XML resource stream
      */
-    protected void processContextConfig(Digester digester, URL contextXml) {
+    protected void processContextConfig(Digester digester, URL contextXml, InputStream stream) {
 
         if (log.isDebugEnabled()) {
             log.debug("Processing context [" + context.getName()
@@ -504,13 +502,14 @@ public class ContextConfig implements Li
         }
 
         InputSource source = null;
-        InputStream stream = null;
 
         try {
             source = new InputSource(contextXml.toString());
-            URLConnection xmlConn = contextXml.openConnection();
-            xmlConn.setUseCaches(false);
-            stream = xmlConn.getInputStream();
+            if (stream == null) {
+                URLConnection xmlConn = contextXml.openConnection();
+                xmlConn.setUseCaches(false);
+                stream = xmlConn.getInputStream();
+            }
         } catch (Exception e) {
             log.error(sm.getString("contextConfig.contextMissing",
                       contextXml) , e);
@@ -1770,8 +1769,7 @@ public class ContextConfig implements Li
         if (Constants.NoDefaultWebXml.equals(defaultWebXml)) {
             return null;
         }
-        return getWebXmlSource(defaultWebXml,
-                context.getCatalinaBase().getPath());
+        return getWebXmlSource(defaultWebXml, true);
     }
 
     /**
@@ -1784,7 +1782,7 @@ public class ContextConfig implements Li
         if (hostConfigBase == null)
             return null;
 
-        return getWebXmlSource(Constants.HostWebXml, hostConfigBase.getPath());
+        return getWebXmlSource(hostConfigBase.getPath(), false);
     }
 
     /**
@@ -1847,43 +1845,64 @@ public class ContextConfig implements Li
         return source;
     }
 
+    public String getConfigBasePath() {
+        String path = null;
+        if (context.getParent() instanceof Host) {
+            Host host = (Host) context.getParent();
+            if (host.getXmlBase() != null) {
+                path = host.getXmlBase();
+            } else {
+                StringBuilder xmlDir = new StringBuilder("conf");
+                Container parent = host.getParent();
+                if (parent instanceof Engine) {
+                    xmlDir.append('/');
+                    xmlDir.append(parent.getName());
+                }
+                xmlDir.append('/');
+                xmlDir.append(host.getName());
+                path = xmlDir.toString();
+            }
+        }
+        return path;
+    }
+
     /**
      * Utility method to create an input source from the specified XML file.
      * @param filename  Name of the file (possibly with one or more leading path
      *                  segments) to read
-     * @param path      Location that filename is relative to
+     * @param global true if processing a shared resource, false if processing
+     *        a host based resource
      * @return the input source
      */
-    protected InputSource getWebXmlSource(String filename, String path) {
-        File file = new File(filename);
-        if (!file.isAbsolute()) {
-            file = new File(path, filename);
+    protected InputSource getWebXmlSource(String filename, boolean global) {
+        ConfigurationSource.Resource webXmlResource = null;
+        try {
+            if (global) {
+                if (Constants.DefaultWebXml.equals(filename)) {
+                    webXmlResource = ConfigFileLoader.getSource().getSharedWebXml();
+                } else {
+                    webXmlResource = ConfigFileLoader.getSource().getResource(filename);
+                }
+            } else {
+                String hostWebXml = Container.getConfigPath(context, Constants.HostWebXml);
+                webXmlResource = ConfigFileLoader.getSource().getConfResource(hostWebXml);
+            }
+        } catch (IOException e) {
+            // Ignore if not found
+            return null;
         }
 
         InputStream stream = null;
         InputSource source = null;
 
         try {
-            if (!file.exists()) {
-                // Use getResource and getResourceAsStream
-                stream =
-                    getClass().getClassLoader().getResourceAsStream(filename);
-                if(stream != null) {
-                    source =
-                        new InputSource(getClass().getClassLoader().getResource(
-                                filename).toURI().toString());
-                }
-            } else {
-                source = new InputSource(file.getAbsoluteFile().toURI().toString());
-                stream = new FileInputStream(file);
-            }
-
+            stream = webXmlResource.getInputStream();
+            source = new InputSource(webXmlResource.getURI().toString());
             if (stream != null && source != null) {
                 source.setByteStream(stream);
             }
         } catch (Exception e) {
-            log.error(sm.getString(
-                    "contextConfig.defaultError", filename, file), e);
+            log.error(sm.getString("contextConfig.defaultError", filename, webXmlResource.getURI()), e);
         } finally {
             if (source == null && stream != null) {
                 try {

Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties [UTF-8] (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties [UTF-8] Thu Nov  8 13:02:05 2018
@@ -157,3 +157,5 @@ webAnnotationSet.invalidInjection=Invali
 
 connector.noSetExecutor=Connector [{0}] does not support external executors. Method setExecutor(java.util.concurrent.Executor) not found.
 connector.noSetSSLImplementationName=Connector [{0}] does not support changing the SSL implementation. Method setSslImplementationName(String) not found.
+
+catalinaConfigurationSource.cannotObtainURL=Cannot obtain URL for the relative path [{0}]. Check that catalina.base is set.

Modified: tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java Thu Nov  8 13:02:05 2018
@@ -63,6 +63,8 @@ import org.apache.catalina.realm.RealmBa
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.buf.UriUtil;
 import org.apache.tomcat.util.descriptor.web.LoginConfig;
+import org.apache.tomcat.util.file.ConfigFileLoader;
+import org.apache.tomcat.util.file.ConfigurationSource;
 import org.apache.tomcat.util.res.StringManager;
 
 // TODO: lazy init for the temp dir - only when a JSP is compiled or
@@ -352,6 +354,25 @@ public class Tomcat {
 
 
     /**
+     * Initialize the server given the specified configuration source.
+     * The server will be loaded according to the Tomcat configuration
+     * files contained in the source (server.xml, web.xml, context.xml,
+     * SSL certificates, etc).
+     * If no configuration source is specified, it will use the default
+     * locations for these files.
+     */
+    public void init(ConfigurationSource source) {
+        ConfigFileLoader.setSource(source);
+        Catalina catalina = new Catalina();
+        // Load the Catalina instance with the regular configuration files
+        // from specified source
+        catalina.load();
+        // Retrieve and set the server
+        server = catalina.getServer();
+    }
+
+
+    /**
      * Initialize the server.
      *
      * @throws LifecycleException Init error
@@ -540,6 +561,9 @@ public class Tomcat {
 
         initBaseDir();
 
+        // Set configuration source
+        ConfigFileLoader.setSource(new CatalinaBaseConfigurationSource(new File(basedir), null));
+
         server.setPort( -1 );
 
         Service service = new StandardService();
@@ -605,7 +629,7 @@ public class Tomcat {
             throw new IllegalArgumentException(e);
         }
 
-        return addWebapp(host,  contextPath, docBase, listener);
+        return addWebapp(host, contextPath, docBase, listener);
     }
 
     /**

Modified: tomcat/trunk/java/org/apache/catalina/users/MemoryUserDatabase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/users/MemoryUserDatabase.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/users/MemoryUserDatabase.java (original)
+++ tomcat/trunk/java/org/apache/catalina/users/MemoryUserDatabase.java Thu Nov  8 13:02:05 2018
@@ -19,7 +19,6 @@ package org.apache.catalina.users;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.net.URI;
@@ -42,6 +41,7 @@ import org.apache.juli.logging.LogFactor
 import org.apache.tomcat.util.digester.AbstractObjectCreationFactory;
 import org.apache.tomcat.util.digester.Digester;
 import org.apache.tomcat.util.file.ConfigFileLoader;
+import org.apache.tomcat.util.file.ConfigurationSource;
 import org.apache.tomcat.util.res.StringManager;
 import org.xml.sax.Attributes;
 
@@ -415,48 +415,40 @@ public class MemoryUserDatabase implemen
      */
     @Override
     public void open() throws Exception {
-
         writeLock.lock();
-        try {
-            // Erase any previous groups and users
-            users.clear();
-            groups.clear();
-            roles.clear();
-
-            String pathName = getPathname();
-            URI uri = ConfigFileLoader.getURI(pathName);
-            URL url = uri.toURL();
-            URLConnection uConn = url.openConnection();
-
-            try (InputStream is = uConn.getInputStream()) {
-                this.lastModified = uConn.getLastModified();
-
-                // Construct a digester to read the XML input file
-                Digester digester = new Digester();
-                try {
-                    digester.setFeature(
-                            "http://apache.org/xml/features/allow-java-encodings", true);
-                } catch (Exception e) {
-                    log.warn(sm.getString("memoryUserDatabase.xmlFeatureEncoding"), e);
-                }
-                digester.addFactoryCreate("tomcat-users/group",
-                        new MemoryGroupCreationFactory(this), true);
-                digester.addFactoryCreate("tomcat-users/role",
-                        new MemoryRoleCreationFactory(this), true);
-                digester.addFactoryCreate("tomcat-users/user",
-                        new MemoryUserCreationFactory(this), true);
-
-                // Parse the XML input to load this database
-                digester.parse(is);
-            } catch (IOException ioe) {
-                log.error(sm.getString("memoryUserDatabase.fileNotFound", pathName));
+        // Erase any previous groups and users
+        users.clear();
+        groups.clear();
+        roles.clear();
+
+        String pathName = getPathname();
+        try (ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getResource(pathName)) {
+            this.lastModified = resource.getURI().toURL().openConnection().getLastModified();
+
+            // Construct a digester to read the XML input file
+            Digester digester = new Digester();
+            try {
+                digester.setFeature(
+                        "http://apache.org/xml/features/allow-java-encodings", true);
+            } catch (Exception e) {
+                log.warn(sm.getString("memoryUserDatabase.xmlFeatureEncoding"), e);
             }
+            digester.addFactoryCreate("tomcat-users/group",
+                    new MemoryGroupCreationFactory(this), true);
+            digester.addFactoryCreate("tomcat-users/role",
+                    new MemoryRoleCreationFactory(this), true);
+            digester.addFactoryCreate("tomcat-users/user",
+                    new MemoryUserCreationFactory(this), true);
+
+            // Parse the XML input to load this database
+            digester.parse(resource.getInputStream());
+        } catch (IOException ioe) {
+            log.error(sm.getString("memoryUserDatabase.fileNotFound", pathName));
         } catch (Exception e) {
             // Fail safe on error
             users.clear();
             groups.clear();
             roles.clear();
-
             throw e;
         } finally {
             writeLock.unlock();
@@ -660,7 +652,7 @@ public class MemoryUserDatabase implemen
             return;
         }
 
-        URI uri = ConfigFileLoader.getURI(getPathname());
+        URI uri = ConfigFileLoader.getSource().getURI(getPathname());
         try {
             URL url = uri.toURL();
             URLConnection uConn = url.openConnection();

Modified: tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java (original)
+++ tomcat/trunk/java/org/apache/catalina/valves/rewrite/RewriteValve.java Thu Nov  8 13:02:05 2018
@@ -17,8 +17,6 @@
 package org.apache.catalina.valves.rewrite;
 
 import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -37,8 +35,6 @@ import javax.servlet.http.HttpServletRes
 
 import org.apache.catalina.Container;
 import org.apache.catalina.Context;
-import org.apache.catalina.Engine;
-import org.apache.catalina.Host;
 import org.apache.catalina.Lifecycle;
 import org.apache.catalina.LifecycleException;
 import org.apache.catalina.Pipeline;
@@ -52,6 +48,8 @@ import org.apache.tomcat.util.buf.CharCh
 import org.apache.tomcat.util.buf.MessageBytes;
 import org.apache.tomcat.util.buf.UDecoder;
 import org.apache.tomcat.util.buf.UriUtil;
+import org.apache.tomcat.util.file.ConfigFileLoader;
+import org.apache.tomcat.util.file.ConfigurationSource;
 import org.apache.tomcat.util.http.RequestUtil;
 
 public class RewriteValve extends ValveBase {
@@ -139,29 +137,15 @@ public class RewriteValve extends ValveB
                     containerLog.debug("Read configuration from: /WEB-INF/" + resourcePath);
                 }
             }
-        } else if (getContainer() instanceof Host) {
-            String resourceName = getHostConfigPath(resourcePath);
-            File file = new File(getConfigBase(), resourceName);
+        } else {
+            String resourceName = Container.getConfigPath(getContainer(), resourcePath);
             try {
-                if (!file.exists()) {
-                    // Use getResource and getResourceAsStream
-                    is = getClass().getClassLoader()
-                        .getResourceAsStream(resourceName);
-                    if (is != null && containerLog.isDebugEnabled()) {
-                        containerLog.debug("Read configuration from CL at " + resourceName);
-                    }
-                } else {
-                    if (containerLog.isDebugEnabled()) {
-                        containerLog.debug("Read configuration from " + file.getAbsolutePath());
-                    }
-                    is = new FileInputStream(file);
-                }
+                ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getConfResource(resourceName);
+                is = resource.getInputStream();
+            } catch (IOException e) {
                 if ((is == null) && (containerLog.isDebugEnabled())) {
-                    containerLog.debug("No configuration resource found: " + resourceName +
-                            " in " + getConfigBase() + " or in the classloader");
+                    containerLog.debug("No configuration resource found: " + resourceName, e);
                 }
-            } catch (Exception e) {
-                containerLog.error("Error opening configuration", e);
             }
         }
 
@@ -564,49 +548,6 @@ public class RewriteValve extends ValveB
     }
 
 
-    /**
-     * @return config base.
-     */
-    protected File getConfigBase() {
-        File configBase =
-            new File(System.getProperty("catalina.base"), "conf");
-        if (!configBase.exists()) {
-            return null;
-        } else {
-            return configBase;
-        }
-    }
-
-
-    /**
-     * Find the configuration path where the rewrite configuration file
-     * will be stored.
-     * @param resourceName The rewrite configuration file name
-     * @return the full rewrite configuration path
-     */
-    protected String getHostConfigPath(String resourceName) {
-        StringBuffer result = new StringBuffer();
-        Container container = getContainer();
-        Container host = null;
-        Container engine = null;
-        while (container != null) {
-            if (container instanceof Host)
-                host = container;
-            if (container instanceof Engine)
-                engine = container;
-            container = container.getParent();
-        }
-        if (engine != null) {
-            result.append(engine.getName()).append('/');
-        }
-        if (host != null) {
-            result.append(host.getName()).append('/');
-        }
-        result.append(resourceName);
-        return result.toString();
-    }
-
-
     /**
      * This factory method will parse a line formed like:
      *

Modified: tomcat/trunk/java/org/apache/tomcat/util/file/ConfigFileLoader.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/file/ConfigFileLoader.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/file/ConfigFileLoader.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/file/ConfigFileLoader.java Thu Nov  8 13:02:05 2018
@@ -17,12 +17,9 @@
  */
 package org.apache.tomcat.util.file;
 
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
-import java.net.URL;
 
 import org.apache.tomcat.util.res.StringManager;
 
@@ -36,17 +33,18 @@ public class ConfigFileLoader {
     private static final StringManager sm = StringManager.getManager(ConfigFileLoader.class
             .getPackage().getName());
 
-    private static final File CATALINA_BASE_FILE;
-    private static final URI CATALINA_BASE_URI;
+    private static ConfigurationSource source;
 
-    static {
-        String catalinaBase = System.getProperty("catalina.base");
-        if (catalinaBase != null) {
-            CATALINA_BASE_FILE = new File(catalinaBase);
-            CATALINA_BASE_URI = CATALINA_BASE_FILE.toURI();
-        } else {
-            CATALINA_BASE_FILE = null;
-            CATALINA_BASE_URI = null;
+    public static final ConfigurationSource getSource() {
+        if (ConfigFileLoader.source == null) {
+            throw new IllegalStateException(sm.getString("configFileLoader.noConfigurationSource"));
+        }
+        return source;
+    }
+
+    public static final void setSource(ConfigurationSource source) {
+        if (ConfigFileLoader.source == null) {
+            ConfigFileLoader.source = source;
         }
     }
 
@@ -68,40 +66,15 @@ public class ConfigFileLoader {
      * @throws IOException If an InputStream cannot be created using the
      *                     provided location
      */
+    @Deprecated
     public static InputStream getInputStream(String location) throws IOException {
-        // Location was originally always a file before URI support was added so
-        // try file first.
-
-        File f = new File(location);
-        if (!f.isAbsolute()) {
-            f = new File(CATALINA_BASE_FILE, location);
-        }
-        if (f.isFile()) {
-            return new FileInputStream(f);
-        }
-
-        // File didn't work so try URI.
-        URI uri = getURI(location);
-
-        // Obtain the input stream we need
-        try {
-            URL url = uri.toURL();
-            return url.openConnection().getInputStream();
-        } catch (IllegalArgumentException e) {
-            throw new IOException(sm.getString("configFileLoader.cannotObtainURL", location), e);
-        }
+        return getSource().getResource(location).getInputStream();
     }
 
 
+    @Deprecated
     public static URI getURI(String location) {
-        // Using resolve() enables the code to handle relative paths that did
-        // not point to a file
-        URI uri;
-        if (CATALINA_BASE_URI != null) {
-            uri = CATALINA_BASE_URI.resolve(location);
-        } else {
-            uri = URI.create(location);
-        }
-        return uri;
+        return getSource().getURI(location);
     }
+
 }

Added: tomcat/trunk/java/org/apache/tomcat/util/file/ConfigurationSource.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/file/ConfigurationSource.java?rev=1846135&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/file/ConfigurationSource.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/util/file/ConfigurationSource.java Thu Nov  8 13:02:05 2018
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.file;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+
+/**
+ * Abstracts configuration file storage. Allows Tomcat embedding using the regular
+ * configuration style.
+ * This abstraction aims to be very simple and does not cover resource listing,
+ * which is usually used for dynamic deployments that are usually not used when
+ * embedding, as well as resource writing.
+ */
+public interface ConfigurationSource {
+
+    /**
+     * Represents a resource: a stream to the resource associated with
+     * its URI.
+     */
+    public class Resource implements AutoCloseable {
+        private final InputStream inputStream;
+        private final URI uri;
+        public Resource(InputStream inputStream, URI uri) {
+            this.inputStream = inputStream;
+            this.uri = uri;
+        }
+        public InputStream getInputStream() {
+            return inputStream;
+        }
+        public URI getURI() {
+            return uri;
+        }
+        public long getLastModified()
+                throws MalformedURLException, IOException {
+            return uri.toURL().openConnection().getLastModified();
+        }
+        @Override
+        public void close() throws IOException {
+            if (inputStream != null) {
+                inputStream.close();
+            }
+        }
+    }
+
+    /**
+     * Returns the contents of the main conf/server.xml file.
+     * @return the server.xml as an InputStream
+     * @throws IOException if an error occurs or if the resource does not exist
+     */
+    public default Resource getServerXml()
+            throws IOException {
+        return getConfResource("server.xml");
+    }
+
+    /**
+     * Returns the contents of the shared conf/web.xml file. This usually
+     * contains the declaration of the default and JSP servlets.
+     * @return the web.xml as an InputStream
+     * @throws IOException if an error occurs or if the resource does not exist
+     */
+    public default Resource getSharedWebXml()
+            throws IOException {
+        return getConfResource("web.xml");
+    }
+
+    /**
+     * Get a resource, based on the conf path.
+     * @param name The resource name
+     * @return the resource as an InputStream
+     * @throws IOException if an error occurs or if the resource does not exist
+     */
+    public default Resource getConfResource(String name)
+            throws IOException {
+        String fullName = "conf/" + name;
+        return getResource(fullName);
+    }
+
+    /**
+     * Get a resource, not based on the conf path.
+     * @param name The resource name
+     * @return the resource
+     * @throws IOException if an error occurs or if the resource does not exist
+     */
+    public Resource getResource(String name)
+            throws IOException;
+
+    /**
+     * Get a URI to the given resource. Unlike getResource, this will also
+     * return URIs to locations where no resource exists.
+     * @param name The resource name
+     * @return a URI representing the resource location
+     */
+    public URI getURI(String name);
+
+}

Propchange: tomcat/trunk/java/org/apache/tomcat/util/file/ConfigurationSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/java/org/apache/tomcat/util/file/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/file/LocalStrings.properties?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/file/LocalStrings.properties [UTF-8] (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/file/LocalStrings.properties [UTF-8] Thu Nov  8 13:02:05 2018
@@ -13,4 +13,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-configFileLoader.cannotObtainURL=Cannot obtain URL for the relative path [{0}]. Check that catalina.base is set.
\ No newline at end of file
+configFileLoader.noConfigurationSource=No configuration source has been set using ConfigFileLoader.setSource.
\ No newline at end of file

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SSLUtilBase.java Thu Nov  8 13:02:05 2018
@@ -149,7 +149,7 @@ public abstract class SSLUtilBase implem
                 ks = KeyStore.getInstance(type, provider);
             }
             if ("DKS".equalsIgnoreCase(type)) {
-                URI uri = ConfigFileLoader.getURI(path);
+                URI uri = ConfigFileLoader.getSource().getURI(path);
                 ks.load(new DomainLoadStoreParameter(uri, Collections.emptyMap()));
             } else {
                 // Some key store types (e.g. hardware) expect the InputStream
@@ -157,7 +157,7 @@ public abstract class SSLUtilBase implem
                 if(!("PKCS11".equalsIgnoreCase(type) ||
                         "".equalsIgnoreCase(path)) ||
                         "NONE".equalsIgnoreCase(path)) {
-                    istream = ConfigFileLoader.getInputStream(path);
+                    istream = ConfigFileLoader.getSource().getResource(path).getInputStream();
                 }
 
                 // The digester cannot differentiate between null and "".

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java Thu Nov  8 13:02:05 2018
@@ -222,15 +222,15 @@ public class JSSEUtil extends SSLUtilBas
                 throw new IOException(sm.getString("jsse.noCertFile"));
             }
 
-            PEMFile privateKeyFile = new PEMFile(SSLHostConfig.adjustRelativePath
-                    (certificate.getCertificateKeyFile() != null ? certificate.getCertificateKeyFile() : certificate.getCertificateFile()),
+            PEMFile privateKeyFile = new PEMFile(
+                    certificate.getCertificateKeyFile() != null ? certificate.getCertificateKeyFile() : certificate.getCertificateFile(),
                     keyPass);
-            PEMFile certificateFile = new PEMFile(SSLHostConfig.adjustRelativePath(certificate.getCertificateFile()));
+            PEMFile certificateFile = new PEMFile(certificate.getCertificateFile());
 
             Collection<Certificate> chain = new ArrayList<>();
             chain.addAll(certificateFile.getCertificates());
             if (certificate.getCertificateChainFile() != null) {
-                PEMFile certificateChainFile = new PEMFile(SSLHostConfig.adjustRelativePath(certificate.getCertificateChainFile()));
+                PEMFile certificateChainFile = new PEMFile(certificate.getCertificateChainFile());
                 chain.addAll(certificateChainFile.getCertificates());
             }
 
@@ -436,7 +436,7 @@ public class JSSEUtil extends SSLUtilBas
         Collection<? extends CRL> crls = null;
         try {
             CertificateFactory cf = CertificateFactory.getInstance("X.509");
-            try (InputStream is = ConfigFileLoader.getInputStream(crlf)) {
+            try (InputStream is = ConfigFileLoader.getSource().getResource(crlf).getInputStream()) {
                 crls = cf.generateCRLs(is);
             }
         } catch(IOException iex) {

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/jsse/PEMFile.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/jsse/PEMFile.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/jsse/PEMFile.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/jsse/PEMFile.java Thu Nov  8 13:02:05 2018
@@ -18,8 +18,8 @@ package org.apache.tomcat.util.net.jsse;
 
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
@@ -42,6 +42,7 @@ import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
 
 import org.apache.tomcat.util.codec.binary.Base64;
+import org.apache.tomcat.util.file.ConfigFileLoader;
 import org.apache.tomcat.util.res.StringManager;
 
 /**
@@ -73,15 +74,17 @@ public class PEMFile {
         this(filename, password, null);
     }
 
-    public PEMFile(String filename, String password, String keyAlgorithm) throws IOException, GeneralSecurityException {
+    public PEMFile(String filename, String password, String keyAlgorithm)
+            throws IOException, GeneralSecurityException {
         this.filename = filename;
 
         List<Part> parts = new ArrayList<>();
-        try (BufferedReader in = new BufferedReader(new InputStreamReader(
-                new FileInputStream(filename), StandardCharsets.US_ASCII))) {
+        try (InputStream inputStream = ConfigFileLoader.getSource().getResource(filename).getInputStream()) {
+            BufferedReader reader =
+                    new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.US_ASCII));
             Part part = null;
             String line;
-            while ((line = in.readLine()) != null) {
+            while ((line = reader.readLine()) != null) {
                 if (line.startsWith(Part.BEGIN_BOUNDARY)) {
                     part = new Part();
                     part.type = line.substring(Part.BEGIN_BOUNDARY.length(), line.length() - 5).trim();

Added: tomcat/trunk/test/org/apache/catalina/startup/TestTomcatStandalone.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/startup/TestTomcatStandalone.java?rev=1846135&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/startup/TestTomcatStandalone.java (added)
+++ tomcat/trunk/test/org/apache/catalina/startup/TestTomcatStandalone.java Thu Nov  8 13:02:05 2018
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.startup;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.startup.TestTomcat.HelloWorld;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+public class TestTomcatStandalone extends LoggingBaseTest {
+
+    protected class ServerXml extends CatalinaBaseConfigurationSource {
+        public ServerXml() {
+            super(getTemporaryDirectory(), null);
+        }
+
+        private static final String SERVER_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+                + "<Server port=\"8005\" shutdown=\"SHUTDOWN\">\n"
+                + "  <Listener className=\"org.apache.catalina.startup.VersionLoggerListener\" />\n"
+                + "  <Listener className=\"org.apache.catalina.core.AprLifecycleListener\" SSLEngine=\"on\" />\n"
+                + "  <Listener className=\"org.apache.catalina.core.JreMemoryLeakPreventionListener\" />\n"
+                + "  <Listener className=\"org.apache.catalina.mbeans.GlobalResourcesLifecycleListener\" />\n"
+                + "  <Listener className=\"org.apache.catalina.core.ThreadLocalLeakPreventionListener\" />\n"
+                + "\n" + "  <GlobalNamingResources>\n"
+                + "    <Resource name=\"UserDatabase\" auth=\"Container\"\n"
+                + "              type=\"org.apache.catalina.UserDatabase\"\n"
+                + "              description=\"User database that can be updated and saved\"\n"
+                + "              factory=\"org.apache.catalina.users.MemoryUserDatabaseFactory\"\n"
+                + "              pathname=\"conf/tomcat-users.xml\" />\n"
+                + "  </GlobalNamingResources>\n" + "\n"
+                + "  <Service name=\"Catalina\">\n" + "\n"
+                + "    <Connector port=\"0\" protocol=\"HTTP/1.1\"\n"
+                + "               connectionTimeout=\"20000\"\n"
+                + "               redirectPort=\"8443\" />\n"
+                + "    <Engine name=\"Catalina\" defaultHost=\"localhost\">\n"
+                + "\n"
+                + "      <Realm className=\"org.apache.catalina.realm.LockOutRealm\">\n"
+                + "        <Realm className=\"org.apache.catalina.realm.UserDatabaseRealm\"\n"
+                + "               resourceName=\"UserDatabase\"/>\n"
+                + "      </Realm>\n" + "\n"
+                + "      <Host name=\"localhost\"  appBase=\"webapps\"\n"
+                + "            unpackWARs=\"true\" autoDeploy=\"true\">\n"
+                + "\n"
+                + "        <Valve className=\"org.apache.catalina.valves.AccessLogValve\" directory=\"logs\"\n"
+                + "               prefix=\"localhost_access_log\" suffix=\".txt\"\n"
+                + "               pattern=\"%h %l %u %t &quot;%r&quot; %s %b\" />\n"
+                + "\n" + "      </Host>\n" + "    </Engine>\n"
+                + "  </Service>\n" + "</Server>";
+
+        @Override
+        public Resource getServerXml() throws IOException {
+            Resource resource;
+            try {
+                resource = new Resource(new ByteArrayInputStream(SERVER_XML.getBytes(StandardCharsets.ISO_8859_1)),
+                        new URI("file:server.xml"));
+            } catch (URISyntaxException e) {
+                throw new IOException(e);
+            }
+            return resource;
+        }
+    }
+
+    @Test
+    public void testServerXml() throws Exception {
+        Tomcat tomcat = new Tomcat();
+        tomcat.init(new ServerXml());
+
+        // No file system docBase required
+        Context ctx = tomcat.addContext("", null);
+
+        Tomcat.addServlet(ctx, "myServlet", new HelloWorld());
+        ctx.addServletMappingDecoded("/", "myServlet");
+
+        tomcat.start();
+
+        ByteChunk res = TomcatBaseTest.getUrl("http://localhost:" + tomcat.getConnector().getLocalPort() + "/");
+        Assert.assertEquals("Hello world", res.toString());
+
+        tomcat.stop();
+        tomcat.destroy();
+    }
+
+}

Modified: tomcat/trunk/test/org/apache/tomcat/util/file/TestConfigFileLoader.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/file/TestConfigFileLoader.java?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/file/TestConfigFileLoader.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/util/file/TestConfigFileLoader.java Thu Nov  8 13:02:05 2018
@@ -17,6 +17,7 @@
  */
 package org.apache.tomcat.util.file;
 
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -25,6 +26,7 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import org.apache.catalina.startup.CatalinaBaseConfigurationSource;
 import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;
 
 public class TestConfigFileLoader {
@@ -33,6 +35,7 @@ public class TestConfigFileLoader {
     public static void setup() {
         TomcatURLStreamHandlerFactory.getInstance();
         System.setProperty("catalina.base", "");
+        ConfigFileLoader.setSource(new CatalinaBaseConfigurationSource(new File(System.getProperty("catalina.base")), null));
     }
 
     @Test
@@ -56,7 +59,7 @@ public class TestConfigFileLoader {
     }
 
     private void doTest(String path) throws IOException {
-        try (InputStream is = ConfigFileLoader.getInputStream(path)) {
+        try (InputStream is = ConfigFileLoader.getSource().getResource(path).getInputStream()) {
             Assert.assertNotNull(is);
         }
     }

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1846135&r1=1846134&r2=1846135&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Thu Nov  8 13:02:05 2018
@@ -75,6 +75,19 @@
       <update>
         Refactor parallel deployment threads using the Service executor. (remm)
       </update>
+      <add>
+        Introduce a ConfigurationSource API to standardize access to the core
+        configuration resources of Tomcat. (remm)
+      </add>
+      <update>
+        Update the Tomcat embedded API by allowing to set a configuration
+        source, which will allow processing of core configuration. (remm)
+      </update>
+      <update>
+        Refactor processing of server.xml, web.xml, context.xml and context
+        configuration files using the ConfigurationSource API. JASPIC and
+        storeconfig remain file based. (remm)
+      </update>
     </changelog>
   </subsection>
   <subsection name="Coyote">
@@ -87,6 +100,10 @@
         Avoid using a dedicated thread for accept on the NIO2 connector, it is
         always less efficient. (remm)
       </update>
+      <update>
+        Load SSL configuration resources for JSSE using the ConfigurationSource
+        API. OpenSSL use requires actual files. (remm)
+      </update>
     </changelog>
   </subsection>
   <subsection name="Tribes">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org