diff --git java/org/apache/catalina/realm/MemoryRealm.java java/org/apache/catalina/realm/MemoryRealm.java
index b8776de..0baf646 100644
--- java/org/apache/catalina/realm/MemoryRealm.java
+++ java/org/apache/catalina/realm/MemoryRealm.java
@@ -19,17 +19,18 @@
package org.apache.catalina.realm;
-import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
-import org.apache.catalina.Globals;
import org.apache.catalina.LifecycleException;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.digester.Digester;
+import org.apache.tomcat.util.file.ConfigFileLoader;
/**
@@ -282,30 +283,42 @@ public class MemoryRealm extends RealmBase {
@Override
protected void startInternal() throws LifecycleException {
- // Validate the existence of our database file
- File file = new File(pathname);
- if (!file.isAbsolute())
- file = new File(System.getProperty(Globals.CATALINA_BASE_PROP), pathname);
- if (!file.exists() || !file.canRead())
- throw new LifecycleException
- (sm.getString("memoryRealm.loadExist",
- file.getAbsolutePath()));
-
- // Load the contents of the database file
- if (log.isDebugEnabled())
- log.debug(sm.getString("memoryRealm.loadPath",
- file.getAbsolutePath()));
- Digester digester = getDigester();
+ String pathName = getPathname();
+ InputStream is = null;
+
try {
- synchronized (digester) {
- digester.push(this);
- digester.parse(file);
+ is = ConfigFileLoader.getInputStream(pathName);
+
+ // Load the contents of the database file
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("memoryRealm.loadPath", pathName));
}
- } catch (Exception e) {
- throw new LifecycleException
- (sm.getString("memoryRealm.readXml"), e);
+
+ Digester digester = getDigester();
+ try {
+ synchronized (digester) {
+ digester.push(this);
+ digester.parse(is);
+ }
+ } catch (Exception e) {
+ throw new LifecycleException
+ (sm.getString("memoryRealm.readXml"), e);
+ } finally {
+ digester.reset();
+ }
+
+ } catch (IOException ioe) {
+ throw new LifecycleException(sm.getString("memoryRealm.loadExist",
+ pathName), ioe);
+
} finally {
- digester.reset();
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
}
super.startInternal();
diff --git java/org/apache/catalina/users/MemoryUserDatabase.java java/org/apache/catalina/users/MemoryUserDatabase.java
index 4395e36..7ca6d78 100644
--- java/org/apache/catalina/users/MemoryUserDatabase.java
+++ java/org/apache/catalina/users/MemoryUserDatabase.java
@@ -17,9 +17,9 @@
package org.apache.catalina.users;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashMap;
@@ -34,6 +34,7 @@ import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
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.res.StringManager;
import org.xml.sax.Attributes;
@@ -394,52 +395,44 @@ public class MemoryUserDatabase implements UserDatabase {
groups.clear();
roles.clear();
- // Construct a reader for the XML input file (if it exists)
- File file = new File(pathname);
- if (!file.isAbsolute()) {
- file = new File(System.getProperty(Globals.CATALINA_BASE_PROP),
- pathname);
- }
- if (!file.exists()) {
- log.error(sm.getString("memoryUserDatabase.fileNotFound",
- file.getAbsolutePath()));
- return;
- }
+ String pathName = getPathname();
+ InputStream is = null;
- // 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 file to load this database
- FileInputStream fis = null;
try {
- fis = new FileInputStream(file);
- digester.parse(fis);
+ is = ConfigFileLoader.getInputStream(pathName);
+
+ // 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));
} finally {
- if (fis != null) {
+ if (is != null) {
try {
- fis.close();
+ is.close();
} catch (IOException ioe) {
// Ignore
}
}
}
-
}
}
diff --git java/org/apache/naming/resources/ClasspathURLStreamHandler.java java/org/apache/naming/resources/ClasspathURLStreamHandler.java
new file mode 100644
index 0000000..25b56f9
--- /dev/null
+++ java/org/apache/naming/resources/ClasspathURLStreamHandler.java
@@ -0,0 +1,50 @@
+/*
+ * 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.naming.resources;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+import org.apache.tomcat.util.res.StringManager;
+
+public class ClasspathURLStreamHandler extends URLStreamHandler {
+
+ private static final StringManager sm =
+ StringManager.getManager(Constants.Package);
+
+
+ @Override
+ protected URLConnection openConnection(URL u) throws IOException {
+ String path = u.getPath();
+
+ // Thread context class loader first
+ URL classpathUrl = Thread.currentThread().getContextClassLoader().getResource(path);
+ if (classpathUrl == null) {
+ // This class's class loader if no joy with the tccl
+ classpathUrl = ClasspathURLStreamHandler.class.getResource(path);
+ }
+
+ if (classpathUrl == null) {
+ throw new FileNotFoundException(sm.getString("classpathUrlStreamHandler.notFound", u));
+ }
+
+ return classpathUrl.openConnection();
+ }
+}
diff --git java/org/apache/naming/resources/DirContextURLStreamHandlerFactory.java java/org/apache/naming/resources/DirContextURLStreamHandlerFactory.java
index bf41555..14b36c3 100644
--- java/org/apache/naming/resources/DirContextURLStreamHandlerFactory.java
+++ java/org/apache/naming/resources/DirContextURLStreamHandlerFactory.java
@@ -23,8 +23,9 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
- * Factory for Stream handlers to a JNDI directory context that also supports
- * users specifying additional stream handler.
+ * Factory for Stream handlers to a JNDI directory context,
+ * or for Stream handlers to a classpath url,
+ * which also supports users specifying additional stream handler.
*
* @author Remy Maucherat
*/
@@ -64,6 +65,8 @@ public class DirContextURLStreamHandlerFactory
public URLStreamHandler createURLStreamHandler(String protocol) {
if (protocol.equals("jndi")) {
return new DirContextURLStreamHandler();
+ } else if (protocol.equals("classpath")) {
+ return new ClasspathURLStreamHandler();
} else {
for (URLStreamHandlerFactory factory : userFactories) {
URLStreamHandler handler =
diff --git java/org/apache/naming/resources/LocalStrings.properties java/org/apache/naming/resources/LocalStrings.properties
index 4cc7cff..e18f90c 100644
--- java/org/apache/naming/resources/LocalStrings.properties
+++ java/org/apache/naming/resources/LocalStrings.properties
@@ -43,3 +43,4 @@ standardResources.exists=File base {0} does not exist
standardResources.notStarted=Resources has not yet been started
standardResources.null=Document base cannot be null
standardResources.slash=Document base {0} must not end with a slash
+classpathUrlStreamHandler.notFound=Unable to load the resource [{0}] using the thread context class loader or the current class's class loader
diff --git java/org/apache/tomcat/util/file/ConfigFileLoader.java java/org/apache/tomcat/util/file/ConfigFileLoader.java
new file mode 100644
index 0000000..5b64d8b
--- /dev/null
+++ java/org/apache/tomcat/util/file/ConfigFileLoader.java
@@ -0,0 +1,85 @@
+/*
+ * 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.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+
+/**
+ * This class is used to obtain {@link InputStream}s for configuration files
+ * from a given location String. This allows greater flexibility than these
+ * files having to be loaded directly from a file system.
+ */
+public class ConfigFileLoader {
+
+ private static final File CATALINA_BASE_FILE;
+ private static final URI CATALINA_BASE_URI;
+
+ static {
+ CATALINA_BASE_FILE = new File(System.getProperty("catalina.base"));
+ CATALINA_BASE_URI = CATALINA_BASE_FILE.toURI();
+ }
+
+ private ConfigFileLoader() {
+ // Utility class. Hide the default constructor.
+ }
+
+
+ /**
+ * Load the resource from the specified location.
+ *
+ * @param location The location for the resource of interest. The location
+ * may be a URL or a file path. Relative paths will be
+ * resolved against CATALINA_BASE.
+ *
+ * @return The InputStream for the given resource. The caller is responsible
+ * for closing this stream when it is no longer used.
+ *
+ * @throws IOException If an InputStream cannot be created using the
+ * provided location
+ */
+ public static InputStream getInputStream(String location) throws IOException {
+ // Absolute URIs will be left alone
+ // Relative files will be resolved relative to catalina base
+ // Absolute files will be converted to URIs
+
+ // Location was originally always a file before URI support was added so
+ // try file first.
+
+ // First guess, an absolute file path
+ File file = new File(location);
+
+ if (!file.isAbsolute()) {
+ // Second guess, a file path relative to CATALINA_BASE
+ file = new File(CATALINA_BASE_FILE, location);
+ }
+
+ if (file.isFile()) {
+ return new FileInputStream(file);
+ }
+
+ // Third and final guess, a URI
+ URI uri = CATALINA_BASE_URI.resolve(location);
+ return uri.toURL().openStream();
+ }
+
+
+}
\ No newline at end of file
diff --git java/org/apache/tomcat/util/net/AbstractEndpoint.java java/org/apache/tomcat/util/net/AbstractEndpoint.java
index c4ad4ce..9f0349b 100644
--- java/org/apache/tomcat/util/net/AbstractEndpoint.java
+++ java/org/apache/tomcat/util/net/AbstractEndpoint.java
@@ -16,7 +16,6 @@
*/
package org.apache.tomcat.util.net;
-import java.io.File;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -728,25 +727,6 @@ public abstract class AbstractEndpoint {
}
}
-
- public String adjustRelativePath(String path, String relativeTo) {
- // Empty or null path can't point to anything useful. The assumption is
- // that the value is deliberately empty / null so leave it that way.
- if (path == null || path.length() == 0) {
- return path;
- }
- String newPath = path;
- File f = new File(newPath);
- if ( !f.isAbsolute()) {
- newPath = relativeTo + File.separator + newPath;
- f = new File(newPath);
- }
- if (!f.exists()) {
- getLog().warn("configured file:["+newPath+"] does not exist.");
- }
- return newPath;
- }
-
protected abstract Log getLog();
// Flags to indicate optional feature support
// Some of these are always hard-coded, some are hard-coded to false (i.e.
@@ -833,8 +813,7 @@ public abstract class AbstractEndpoint {
private String keystoreFile = System.getProperty("user.home")+"/.keystore";
public String getKeystoreFile() { return keystoreFile;}
public void setKeystoreFile(String s ) {
- keystoreFile = adjustRelativePath(s,
- System.getProperty(Constants.CATALINA_BASE_PROP));
+ keystoreFile = s;
}
private String keystorePass = null;
@@ -874,8 +853,7 @@ public abstract class AbstractEndpoint {
private String truststoreFile = System.getProperty("javax.net.ssl.trustStore");
public String getTruststoreFile() {return truststoreFile;}
public void setTruststoreFile(String s) {
- truststoreFile = adjustRelativePath(s,
- System.getProperty(Constants.CATALINA_BASE_PROP));
+ truststoreFile = s;
}
private String truststorePass =
diff --git java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
index 7a4ade6..7cab87f 100644
--- java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
+++ java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
@@ -17,8 +17,6 @@
package org.apache.tomcat.util.net.jsse;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@@ -63,6 +61,7 @@ import javax.net.ssl.X509KeyManager;
import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.compat.JreVendor;
+import org.apache.tomcat.util.file.ConfigFileLoader;
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.Constants;
import org.apache.tomcat.util.net.SSLUtil;
@@ -431,12 +430,7 @@ public class JSSESocketFactory implements ServerSocketFactory, SSLUtil {
}
if(!("PKCS11".equalsIgnoreCase(type) ||
"".equalsIgnoreCase(path))) {
- File keyStoreFile = new File(path);
- if (!keyStoreFile.isAbsolute()) {
- keyStoreFile = new File(System.getProperty(
- Constants.CATALINA_BASE_PROP), path);
- }
- istream = new FileInputStream(keyStoreFile);
+ istream = ConfigFileLoader.getInputStream(path);
}
char[] storePass = null;
@@ -718,16 +712,11 @@ public class JSSESocketFactory implements ServerSocketFactory, SSLUtil {
protected Collection extends CRL> getCRLs(String crlf)
throws IOException, CRLException, CertificateException {
- File crlFile = new File(crlf);
- if( !crlFile.isAbsolute() ) {
- crlFile = new File(
- System.getProperty(Constants.CATALINA_BASE_PROP), crlf);
- }
Collection extends CRL> crls = null;
InputStream is = null;
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
- is = new FileInputStream(crlFile);
+ is = ConfigFileLoader.getInputStream(crlf);
crls = cf.generateCRLs(is);
} catch(IOException iex) {
throw iex;
diff --git test/org/apache/naming/resources/TestClasspathUrlStreamHandler.java test/org/apache/naming/resources/TestClasspathUrlStreamHandler.java
new file mode 100644
index 0000000..5752658
--- /dev/null
+++ test/org/apache/naming/resources/TestClasspathUrlStreamHandler.java
@@ -0,0 +1,44 @@
+/*
+ * 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.naming.resources;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Properties;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestClasspathUrlStreamHandler {
+
+ @BeforeClass
+ public static void setup() {
+ URL.setURLStreamHandlerFactory(DirContextURLStreamHandlerFactory.getInstance());
+ }
+
+ @Test
+ public void testClasspathURL01() throws IOException {
+ URL u = new URL("classpath:/org/apache/naming/resources/LocalStrings.properties");
+ InputStream is = u.openStream();
+ Properties p = new Properties();
+ p.load(is);
+ String msg = (String) p.get("resources.null");
+ Assert.assertEquals("Document base cannot be null", msg);
+ }
+}
\ No newline at end of file
diff --git test/org/apache/tomcat/util/file/TestConfigFileLoader.java test/org/apache/tomcat/util/file/TestConfigFileLoader.java
new file mode 100644
index 0000000..cf64fe5
--- /dev/null
+++ test/org/apache/tomcat/util/file/TestConfigFileLoader.java
@@ -0,0 +1,84 @@
+/*
+ * 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.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.naming.resources.DirContextURLStreamHandlerFactory;
+import org.apache.tomcat.util.http.fileupload.FileUtils;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestConfigFileLoader {
+
+ @BeforeClass
+ public static void setup() {
+ URL.setURLStreamHandlerFactory(
+ DirContextURLStreamHandlerFactory.getInstance());
+ File buildDir = new File(
+ System.getProperty("tomcat.test.tomcatbuild", "output/build"));
+ System.setProperty("catalina.base", buildDir.getAbsolutePath());
+ }
+
+ @Test
+ public void test01() throws IOException {
+ doTest("classpath:org/apache/catalina/mbeans-descriptors.xml");
+ }
+
+ @Test(expected=FileNotFoundException.class)
+ public void test02() throws IOException {
+ doTest("classpath:org/apache/catalina/foo");
+ }
+
+ @Test
+ public void test03() throws IOException {
+ doTest("conf/server.xml");
+ }
+
+ @Test(expected=FileNotFoundException.class)
+ public void test04() throws IOException {
+ doTest("conf/unknown");
+ }
+
+ @Test
+ public void testAbsolutePath() throws IOException {
+ File test = new File(System.getProperty("java.io.tmpdir"), "testAbsolutePath");
+ if (test.exists()) {
+ FileUtils.forceDelete(test);
+ }
+ test.createNewFile();
+ doTest(test.getAbsolutePath());
+ }
+
+ private void doTest(String path) throws IOException {
+ InputStream is = null;
+ try {
+ is = ConfigFileLoader.getInputStream(path);
+ Assert.assertNotNull(is);
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ }
+}
\ No newline at end of file