From 95d5e9b8e6315afefba38666b8e9cde9e400214b Mon Sep 17 00:00:00 2001 From: funkman Date: Wed, 3 Jan 2007 00:51:31 +0000 Subject: [PATCH] http://issues.apache.org/bugzilla/show_bug.cgi?id=41260 [Contribution] WebAppLoader and DirContext implementations for handling with expanded webapp during development by Fabrizio Giustina git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk@491995 13f79535-47bb-0310-9956-ffa450edef68 --- .../catalina/loader/VirtualWebappLoader.java | 96 +++++++++++ .../apache/naming/resources/VirtualDirContext.java | 186 +++++++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100755 java/org/apache/catalina/loader/VirtualWebappLoader.java create mode 100755 java/org/apache/naming/resources/VirtualDirContext.java diff --git a/java/org/apache/catalina/loader/VirtualWebappLoader.java b/java/org/apache/catalina/loader/VirtualWebappLoader.java new file mode 100755 index 000000000..d58bb7082 --- /dev/null +++ b/java/org/apache/catalina/loader/VirtualWebappLoader.java @@ -0,0 +1,96 @@ +/* + * 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.loader; + +import java.io.File; +import java.util.StringTokenizer; + +import org.apache.catalina.LifecycleException; + +/** + * Simple webapp classloader that allows a customized classpath to be added + * through configuration in context xml. Any additional classpath entry will be + * added to the default webapp classpath, making easy to emulate a standard + * webapp without the need for assembly all the webapp dependencies as jars in + * WEB-INF/lib. + * + * + * <Context docBase="\webapps\mydocbase"> + * <Loader className="org.apache.catalina.loader.VirtualWebappLoader" + * virtualClasspath="\dir\classes;\somedir\somejar.jar"/> + * </Context> + * + * @author Fabrizio Giustina + * @version $Id: $ + */ +public class VirtualWebappLoader extends WebappLoader { + + /** + * ; separated list of additional path elements. + */ + private String virtualClasspath; + + /** + * Construct a new WebappLoader with no defined parent class loader (so that + * the actual parent will be the system class loader). + */ + public VirtualWebappLoader() { + super(); + } + + /** + * Construct a new WebappLoader with the specified class loader to be + * defined as the parent of the ClassLoader we ultimately create. + * + * @param parent The parent class loader + */ + public VirtualWebappLoader(ClassLoader parent) { + super(parent); + } + + /** + * virtualClasspath attribute that will be automatically set + * from the Context virtualClasspath attribute + * from the context xml file. + * @param path ; separated list of path elements. + */ + public void setVirtualClasspath(String path) { + virtualClasspath = path; + } + + @Override + public void start() throws LifecycleException { + + // just add any jar/directory set in virtual classpath to the + // repositories list before calling start on the standard WebappLoader + StringTokenizer tkn = new StringTokenizer(virtualClasspath, ";"); + while (tkn.hasMoreTokens()) { + File file = new File(tkn.nextToken()); + if (!file.exists()) { + continue; + } + if (file.isDirectory()) { + addRepository("file:/" + file.getAbsolutePath() + "/"); + } else { + addRepository("file:/" + file.getAbsolutePath()); + } + } + + super.start(); + } + +} diff --git a/java/org/apache/naming/resources/VirtualDirContext.java b/java/org/apache/naming/resources/VirtualDirContext.java new file mode 100755 index 000000000..fef63a4d9 --- /dev/null +++ b/java/org/apache/naming/resources/VirtualDirContext.java @@ -0,0 +1,186 @@ +/* + * 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.File; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import javax.naming.NamingException; +import javax.naming.directory.Attributes; + +import org.apache.naming.NamingEntry; + +/** + * Extended FileDirContext implementation that will allow loading of tld files + * from the META-INF directory (or subdirectories) in classpath. This will fully + * mimic the behavior of compressed jars also when using unjarred resources. Tld + * files can be loaded indifferently from WEB-INF webapp dir (or subdirs) or + * from META-INF dir from jars available in the classpath: using this DirContext + * implementation you will be able to use unexpanded jars during development and + * to make any tld in them virtually available to the webapp. + * + * Sample context xml configuration: + * + * + * <Context docBase="\webapps\mydocbase"> + * <Resources className="org.apache.naming.resources.VirtualDirContext" + * virtualClasspath="\dir\classes;\somedir\somejar.jar"/> + * </Resources> + * + * @author Fabrizio Giustina + * @version $Id: $ + */ +public class VirtualDirContext extends FileDirContext { + + /** + * Map containing generated virtual names for tld files under WEB-INF and + * the actual file reference. + */ + private Map virtualMappings; + + /** + * ; separated list of virtual path elements. + */ + private String virtualClasspath; + + /** + * virtualClasspath attribute that will be automatically set + * from the Context virtualClasspath attribute + * from the context xml file. + * @param path ; separated list of path elements. + */ + public void setVirtualClasspath(String path) { + virtualClasspath = path; + } + + /** + * {@inheritDoc} + */ + @Override + public void allocate() { + super.allocate(); + + virtualMappings = new Hashtable(); + + // looks into any META-INF dir found in classpath entries for tld files. + StringTokenizer tkn = new StringTokenizer(virtualClasspath, ";"); + while (tkn.hasMoreTokens()) { + File file = new File(tkn.nextToken(), "META-INF"); + + if (!file.exists() || !file.isDirectory()) { + continue; + } + scanForTlds(file); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void release() { + super.release(); + virtualMappings = null; + } + + @Override + public Attributes getAttributes(String name) throws NamingException { + + // handle "virtual" tlds + if (name.startsWith("/WEB-INF/") && name.endsWith(".tld")) { + String tldName = name.substring(name.lastIndexOf("/") + 1); + if (virtualMappings.containsKey(tldName)) { + return new FileResourceAttributes(virtualMappings.get(tldName)); + } + } + + return super.getAttributes(name); + } + + @Override + @SuppressWarnings("unchecked") + protected ArrayList list(File file) { + ArrayList entries = super.list(file); + + // adds virtual tlds for WEB-INF listing + if ("WEB-INF".equals(file.getName())) { + entries.addAll(getVirtualNamingEntries()); + } + + return entries; + } + + @Override + public Object lookup(String name) throws NamingException { + + // handle "virtual" tlds + if (name.startsWith("/WEB-INF/") && name.endsWith(".tld")) { + String tldName = name.substring(name.lastIndexOf("/") + 1); + if (virtualMappings.containsKey(tldName)) { + return new FileResource(virtualMappings.get(tldName)); + } + } + + return super.lookup(name); + } + + /** + * Scan a given dir for tld files. Any found tld will be added to the + * virtualMappings. + * @param dir Dir to scan for tlds + */ + private void scanForTlds(File dir) { + + File[] files = dir.listFiles(); + for (int j = 0; j < files.length; j++) { + File file = files[j]; + + if (file.isDirectory()) { + scanForTlds(file); + } else if (file.getName().endsWith(".tld")) { + // just generate a random name using the current timestamp, name + // doesn't matter since it needs to be referenced by URI + String virtualTldName = "~" + System.currentTimeMillis() + "~" + + file.getName(); + virtualMappings.put(virtualTldName, file); + } + } + + } + + /** + * Returns a list of virtual naming entries. + * @return list of naming entries, containing tlds in virtualMappings + */ + private List getVirtualNamingEntries() { + List virtual = new ArrayList(); + + for (String name : virtualMappings.keySet()) { + + File file = virtualMappings.get(name); + NamingEntry entry = new NamingEntry(name, new FileResource(file), + NamingEntry.ENTRY); + virtual.add(entry); + } + return virtual; + } + +} -- 2.11.0