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 2004/07/24 00:57:35 UTC
cvs commit: jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina Lifecycle.java Context.java Host.java
remm 2004/07/23 15:57:35
Modified: catalina/src/share/org/apache/catalina/startup
HostConfig.java ContextConfig.java
ContextRuleSet.java
catalina/src/share/org/apache/catalina/core
StandardContext.java
catalina/src/share/org/apache/catalina Lifecycle.java
Context.java Host.java
Removed: catalina/src/share/org/apache/catalina/startup
SetDocBaseRule.java
Log:
- First part of the refactoring of the deployer, where HostConfig will be the only entry point for automated deployments
(= deployments where Container.addChild isn't directly used, as in the embedded world) and redeployments.
- This will allow removing a lot of the complexity involved with the fact that there was 3 components which had
deployment logic inside (HostConfig, StdHostDeployer, and the manager webapp). Now the manager webapp will "talk"
to the HostConfig.
- Some hooks on HostConfig are not there yet.
- Auto redeploy checks aren't done in HostConfig yet.
- ContextConfig is now (logically) in charge of parsing the context config files.
- New default web.xml and context config files have been added. This is not tested (actually, little of this is testedright now: the default
setup deploys ok, but more complex setups might not). Having default context config files should allow removing DefaultContext and its
complexity.
- The new default context config files are:
- conf/context.xml (so this is for all contexts)
- conf/<engine>/<host>/context.xml.default (per host)
- The new default web.xml is:
- conf/<engine>/<host>/web.xml.default (per host)
- Some of the paths to files are hardcoded, but I think I'll add configurability for most of them.
Revision Changes Path
1.34 +327 -446 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/HostConfig.java
Index: HostConfig.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/HostConfig.java,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -r1.33 -r1.34
--- HostConfig.java 23 Jun 2004 16:59:41 -0000 1.33
+++ HostConfig.java 23 Jul 2004 22:57:34 -0000 1.34
@@ -26,26 +26,19 @@
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
-import javax.naming.NamingException;
-import javax.naming.directory.DirContext;
-
import org.apache.catalina.Container;
import org.apache.catalina.Context;
-import org.apache.catalina.Deployer;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
-import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.util.StringManager;
-import org.apache.naming.resources.ResourceAttributes;
+import org.apache.tomcat.util.digester.Digester;
/**
@@ -60,7 +53,7 @@
public class HostConfig
implements LifecycleListener {
- private static org.apache.commons.logging.Log log=
+ protected static org.apache.commons.logging.Log log=
org.apache.commons.logging.LogFactory.getLog( HostConfig.class );
// ----------------------------------------------------- Instance Variables
@@ -69,13 +62,13 @@
/**
* App base.
*/
- private File appBase = null;
+ protected File appBase = null;
/**
* Config base.
*/
- private File configBase = null;
+ protected File configBase = null;
/**
@@ -91,13 +84,6 @@
/**
- * The names of applications that we have auto-deployed (to avoid
- * double deployment attempts).
- */
- protected ArrayList deployed = new ArrayList();
-
-
- /**
* The Host we are associated with.
*/
protected Host host = null;
@@ -113,46 +99,45 @@
/**
* Should we deploy XML Context config files?
*/
- private boolean deployXML = false;
+ protected boolean deployXML = false;
/**
* Should we unpack WAR files when auto-deploying applications in the
* <code>appBase</code> directory?
*/
- private boolean unpackWARs = false;
+ protected boolean unpackWARs = false;
/**
- * Last modified dates of the web.xml files of the contexts, keyed by
- * context name.
+ * Map of deployed applications.
*/
- private HashMap webXmlLastModified = new HashMap();
-
+ protected HashMap deployed = new HashMap();
+
/**
- * Last modified dates of the Context xml files of the contexts, keyed by
- * context name.
+ * List of applications which are being serviced, and shouldn't be
+ * deployed/undeployed/redeployed at the moment.
*/
- private HashMap contextXmlLastModified = new HashMap();
-
+ protected ArrayList serviced = new ArrayList();
+
/**
- * Last modified dates of the source WAR files, keyed by WAR name.
+ * Attribute value used to turn on/off XML validation
*/
- private HashMap warLastModified = new HashMap();
+ protected boolean xmlValidation = false;
/**
- * Attribute value used to turn on/off XML validation
+ * Attribute value used to turn on/off XML namespace awarenes.
*/
- private boolean xmlValidation = false;
+ protected boolean xmlNamespaceAware = false;
/**
- * Attribute value used to turn on/off XML namespace awarenes.
+ * The <code>Digester</code> instance used to parse context descriptors.
*/
- private boolean xmlNamespaceAware = false;
+ protected static Digester digester = createDigester();
// ------------------------------------------------------------- Properties
@@ -319,9 +304,65 @@
}
+
+ /**
+ * Add a serviced application to the list.
+ */
+ public synchronized void addServiced(String name) {
+ serviced.add(name);
+ }
+
+
+ /**
+ * Is application serviced ?
+ * @return state of the application
+ */
+ public synchronized boolean isServiced(String name) {
+ return (serviced.contains(name));
+ }
+
+ /**
+ * Removed a serviced application from the list.
+ */
+ public synchronized void removeServiced(String name) {
+ serviced.remove(name);
+ }
+
+
+ /**
+ * Get the instant where an application was deployed.
+ * @return 0L if no application with that name is deployed, or the instant
+ * on which the application was deployed
+ */
+ public long getDeploymentTime(String name) {
+ DeployedApplication app = (DeployedApplication) deployed.get(name);
+ if (app == null) {
+ return 0L;
+ } else {
+ return app.timestamp;
+ }
+ }
+
+
// ------------------------------------------------------ Protected Methods
+
+ /**
+ * Create the digester which will be used to parse context config files.
+ */
+ protected static Digester createDigester() {
+ Digester digester = new Digester();
+ digester.setValidating(false);
+ // Add object creation rule
+ digester.addObjectCreate("Context", "org.apache.catalina.core.StandardContext",
+ "className");
+ // Set the properties on that object (it doesn't matter if extra
+ // properties are set)
+ digester.addSetProperties("Context");
+ return (digester);
+ }
+
/**
* Return a File object representing the "application root" directory
@@ -379,24 +420,15 @@
*/
protected void deployApps() {
- if (!(host instanceof Deployer))
- return;
-
- // Initialize the deployer
- ((Deployer) host).findDeployedApps();
-
File appBase = appBase();
- if (!appBase.exists() || !appBase.isDirectory())
- return;
File configBase = configBase();
- if (configBase.exists() && configBase.isDirectory()) {
- String configFiles[] = configBase.list();
- deployDescriptors(configBase, configFiles);
- }
-
- String files[] = appBase.list();
- deployWARs(appBase, files);
- deployDirectories(appBase, files);
+ do {
+ // Deploy XML descriptors from configBase
+ deployDescriptors(configBase, configBase.list());
+ // Deploy expanded folders
+ deployDirectories(appBase, appBase.list());
+ // Deploy WARs, and loop if additional descriptors are found
+ } while (deployWARs(appBase, appBase.list()));
}
@@ -406,22 +438,18 @@
*/
protected void deployDescriptors(File configBase, String[] files) {
- if (!deployXML)
- return;
-
+ if (files == null)
+ return;
+
for (int i = 0; i < files.length; i++) {
if (files[i].equalsIgnoreCase("META-INF"))
continue;
if (files[i].equalsIgnoreCase("WEB-INF"))
continue;
- if (deployed.contains(files[i]))
- continue;
- File dir = new File(configBase, files[i]);
+ File contextXml = new File(configBase, files[i]);
if (files[i].toLowerCase().endsWith(".xml")) {
- deployed.add(files[i]);
-
// Calculate the context path and make sure it is unique
String file = files[i].substring(0, files[i].length() - 4);
String contextPath = "/" + file.replace('#', '/');
@@ -429,29 +457,34 @@
contextPath = "";
}
+ if (deployed.containsKey(contextPath))
+ continue;
+
// Assume this is a configuration descriptor and deploy it
log.debug(sm.getString("hostConfig.deployDescriptor", files[i]));
try {
- if (host.findChild(contextPath) != null) {
- if ((deployed.contains(file))
- || (deployed.contains(file + ".war"))) {
- // If this is a newly added context file and
- // it overrides a context with a simple path,
- // that was previously deployed by the auto
- // deployer, undeploy the context
- ((Deployer) host).remove(contextPath);
- } else {
- continue;
- }
+ Context newContext = null;
+ synchronized (digester) {
+ newContext = (Context) digester.parse(contextXml);
+ }
+ if (newContext instanceof Lifecycle) {
+ Class clazz = Class.forName(host.getConfigClass());
+ LifecycleListener listener =
+ (LifecycleListener) clazz.newInstance();
+ ((Lifecycle) newContext).addLifecycleListener(listener);
}
- URL config =
- new URL("file", null, dir.getCanonicalPath());
- ((Deployer) host).install(config, null);
+ newContext.setConfigFile(contextXml.getAbsolutePath());
+ newContext.setPath(contextPath);
+ host.addChild(newContext);
} catch (Throwable t) {
log.error(sm.getString("hostConfig.deployDescriptor.error",
files[i]), t);
}
+ deployed.put(contextPath, new DeployedApplication(contextPath));
+ // FIXME: populate needed resources, such as the docBase (WAR, expanded)
+ // FIXME: populate watched resources
+
}
}
@@ -462,21 +495,22 @@
/**
* Deploy WAR files.
*/
- protected void deployWARs(File appBase, String[] files) {
+ protected boolean deployWARs(File appBase, String[] files) {
+ if (files == null)
+ return false;
+
+ boolean checkAdditionalDeployments = false;
+
for (int i = 0; i < files.length; i++) {
if (files[i].equalsIgnoreCase("META-INF"))
continue;
if (files[i].equalsIgnoreCase("WEB-INF"))
continue;
- if (deployed.contains(files[i]))
- continue;
File dir = new File(appBase, files[i]);
if (files[i].toLowerCase().endsWith(".war")) {
- deployed.add(files[i]);
-
// Calculate the context path and make sure it is unique
String contextPath = "/" + files[i];
int period = contextPath.lastIndexOf(".");
@@ -484,79 +518,9 @@
contextPath = contextPath.substring(0, period);
if (contextPath.equals("/ROOT"))
contextPath = "";
- if (host.findChild(contextPath) != null)
- continue;
- // Checking for a nested /META-INF/context.xml
- JarFile jar = null;
- JarEntry entry = null;
- InputStream istream = null;
- BufferedOutputStream ostream = null;
- File xml = new File
- (configBase, files[i].substring
- (0, files[i].lastIndexOf(".")) + ".xml");
- if (!xml.exists()) {
- try {
- jar = new JarFile(dir);
- entry = jar.getJarEntry("META-INF/context.xml");
- if (entry != null) {
- istream = jar.getInputStream(entry);
-
- // Added for Bugzilla 29038
- xml.mkdirs();
-
- ostream =
- new BufferedOutputStream
- (new FileOutputStream(xml), 1024);
- byte buffer[] = new byte[1024];
- while (true) {
- int n = istream.read(buffer);
- if (n < 0) {
- break;
- }
- ostream.write(buffer, 0, n);
- }
- ostream.flush();
- ostream.close();
- ostream = null;
- istream.close();
- istream = null;
- entry = null;
- jar.close();
- jar = null;
- deployDescriptors(configBase(), configBase.list());
- return;
- }
- } catch (Exception e) {
- // Ignore and continue
- if (ostream != null) {
- try {
- ostream.close();
- } catch (Throwable t) {
- ;
- }
- ostream = null;
- }
- if (istream != null) {
- try {
- istream.close();
- } catch (Throwable t) {
- ;
- }
- istream = null;
- }
- } finally {
- entry = null;
- if (jar != null) {
- try {
- jar.close();
- } catch (Throwable t) {
- ;
- }
- jar = null;
- }
- }
- }
+ if (deployed.containsKey(contextPath))
+ continue;
if (isUnpackWARs()) {
@@ -568,45 +532,122 @@
url = new URL("jar:file:" +
dir.getCanonicalPath() + "!/");
path = ExpandWar.expand(host, url);
+ checkAdditionalDeployments = true;
} catch (IOException e) {
// JAR decompression failure
log.warn(sm.getString
("hostConfig.expand.error", files[i]));
- continue;
} catch (Throwable t) {
log.error(sm.getString
("hostConfig.expand.error", files[i]), t);
- continue;
}
- try {
- if (path != null) {
- url = new URL("file:" + path);
- ((Deployer) host).install(contextPath, url);
+
+ // The webapp will actually be deployed when checking the directories
+
+ } else {
+
+ // FIXME: Don't do that if disabled on Host (sort of "security" feature)
+
+ // Checking for a nested /META-INF/context.xml
+ JarFile jar = null;
+ JarEntry entry = null;
+ InputStream istream = null;
+ BufferedOutputStream ostream = null;
+ File xml = new File
+ (configBase, files[i].substring
+ (0, files[i].lastIndexOf(".")) + ".xml");
+ if (!xml.exists()) {
+ try {
+ jar = new JarFile(dir);
+ entry = jar.getJarEntry("META-INF/context.xml");
+ if (entry != null) {
+ istream = jar.getInputStream(entry);
+
+ configBase.mkdirs();
+
+ ostream =
+ new BufferedOutputStream
+ (new FileOutputStream(xml), 1024);
+ byte buffer[] = new byte[1024];
+ while (true) {
+ int n = istream.read(buffer);
+ if (n < 0) {
+ break;
+ }
+ ostream.write(buffer, 0, n);
+ }
+ ostream.flush();
+ ostream.close();
+ ostream = null;
+ istream.close();
+ istream = null;
+ entry = null;
+ jar.close();
+ jar = null;
+ //deployDescriptors(configBase(), configBase.list());
+ checkAdditionalDeployments = true;
+ continue;
+ }
+ } catch (Exception e) {
+ // Ignore and continue
+ if (ostream != null) {
+ try {
+ ostream.close();
+ } catch (Throwable t) {
+ ;
+ }
+ ostream = null;
+ }
+ if (istream != null) {
+ try {
+ istream.close();
+ } catch (Throwable t) {
+ ;
+ }
+ istream = null;
+ }
+ } finally {
+ entry = null;
+ if (jar != null) {
+ try {
+ jar.close();
+ } catch (Throwable t) {
+ ;
+ }
+ jar = null;
+ }
}
- } catch (Throwable t) {
- log.error(sm.getString
- ("hostConfig.expand.error", files[i]), t);
}
- } else {
-
// Deploy the application in this WAR file
log.info(sm.getString("hostConfig.deployJar", files[i]));
try {
- URL url = new URL("file", null,
- dir.getCanonicalPath());
- url = new URL("jar:" + url.toString() + "!/");
- ((Deployer) host).install(contextPath, url);
+ Context context = (Context) Class.forName(contextClass).newInstance();
+ if (context instanceof Lifecycle) {
+ Class clazz = Class.forName(host.getConfigClass());
+ LifecycleListener listener =
+ (LifecycleListener) clazz.newInstance();
+ ((Lifecycle) context).addLifecycleListener(listener);
+ }
+ context.setPath(contextPath);
+ context.setDocBase(files[i]);
+ host.addChild(context);
} catch (Throwable t) {
log.error(sm.getString("hostConfig.deployJar.error",
files[i]), t);
}
+ deployed.put(contextPath, new DeployedApplication(contextPath));
+ // FIXME: populate needed resources, such as the docBase (context file, WAR, expanded)
+ // FIXME: populate watched resources
+
}
}
}
+
+ return checkAdditionalDeployments;
}
@@ -616,19 +657,18 @@
*/
protected void deployDirectories(File appBase, String[] files) {
+ if (files == null)
+ return;
+
for (int i = 0; i < files.length; i++) {
if (files[i].equalsIgnoreCase("META-INF"))
continue;
if (files[i].equalsIgnoreCase("WEB-INF"))
continue;
- if (deployed.contains(files[i]))
- continue;
File dir = new File(appBase, files[i]);
if (dir.isDirectory()) {
- deployed.add(files[i]);
-
// Make sure there is an application configuration directory
// This is needed if the Context appBase is the same as the
// web server document root to make sure only web applications
@@ -642,7 +682,8 @@
String contextPath = "/" + files[i];
if (files[i].equals("ROOT"))
contextPath = "";
- if (host.findChild(contextPath) != null)
+
+ if (deployed.containsKey(contextPath))
continue;
// Deploy the application in this directory
@@ -650,15 +691,30 @@
log.debug(sm.getString("hostConfig.deployDir", files[i]));
long t1=System.currentTimeMillis();
try {
- URL url = new URL("file", null, dir.getCanonicalPath());
- ((Deployer) host).install(contextPath, url);
+ Context context = (Context) Class.forName(contextClass).newInstance();
+ if (context instanceof Lifecycle) {
+ Class clazz = Class.forName(host.getConfigClass());
+ LifecycleListener listener =
+ (LifecycleListener) clazz.newInstance();
+ ((Lifecycle) context).addLifecycleListener(listener);
+ }
+ context.setPath(contextPath);
+ context.setDocBase(files[i]);
+ // FIXME: Don't set that if disabled on Host (sort of "security" feature)
+ context.setConfigFile((new File(dir, "META-INF/context.xml")).getAbsolutePath());
+ host.addChild(context);
} catch (Throwable t) {
log.error(sm.getString("hostConfig.deployDir.error", files[i]),
t);
}
long t2=System.currentTimeMillis();
- if( (t2-t1) > 200 )
+ if( log.isDebugEnabled() && (t2-t1) > 200 )
log.debug("Deployed " + files[i] + " " + (t2-t1));
+
+ deployed.put(contextPath, new DeployedApplication(contextPath));
+ // FIXME: populate needed resources, such as the docBase (context file, WAR, expanded)
+ // FIXME: populate watched resources
+
}
}
@@ -667,224 +723,58 @@
/**
- * Check deployment descriptors last modified date.
+ * Check resources for redeployment and reloading.
*/
- protected void checkContextLastModified() {
-
- if (!(host instanceof Deployer))
+ protected synchronized void checkResources(DeployedApplication app) {
+ if (isServiced(app.name))
return;
-
- Deployer deployer = (Deployer) host;
-
- String[] contextNames = deployer.findDeployedApps();
-
- for (int i = 0; i < contextNames.length; i++) {
-
- String contextName = contextNames[i];
- Context context = deployer.findDeployedApp(contextName);
-
- if (!(context instanceof Lifecycle))
- continue;
-
- try {
- DirContext resources = context.getResources();
- if (resources == null) {
- // This can happen if there was an error initializing
- // the context
- continue;
- }
- ResourceAttributes webXmlAttributes =
- (ResourceAttributes)
- resources.getAttributes("/WEB-INF/web.xml");
- ResourceAttributes webInfAttributes =
- (ResourceAttributes)
- resources.getAttributes("/WEB-INF");
- long newLastModified = webXmlAttributes.getLastModified();
- long webInfLastModified = webInfAttributes.getLastModified();
- Long lastModified = (Long) webXmlLastModified.get(contextName);
- if (lastModified == null) {
- webXmlLastModified.put
- (contextName, new Long(newLastModified));
- } else {
- if (lastModified.longValue() != newLastModified) {
- if (newLastModified > (webInfLastModified + 5000)) {
- webXmlLastModified.remove(contextName);
- restartContext(context);
- } else {
- webXmlLastModified.put
- (contextName, new Long(newLastModified));
- }
- }
- }
- } catch (NamingException e) {
- ; // Ignore
+ String[] resources = (String[]) app.redeployResources.toArray(new String[0]);
+ for (int i = 0; i < resources.length; i++) {
+ File resource = new File(resources[i]);
+ if (resource.exists()) {
+ if (resource.lastModified() > app.timestamp) {
+ // Redeploy application
+ host.removeChild(host.findChild(app.name));
+ // FIXME: Remove other redeploy resources; need hack here to remove expanded
+ // folder if updated resource is a WAR
+ deployed.remove(app);
+ return;
+ }
+ } else {
+ // Undeploy application
+ host.removeChild(host.findChild(app.name));
+ // FIXME: Delete all redeploy resources
+ deployed.remove(app);
+ return;
}
-
- Long lastModified = (Long) contextXmlLastModified.get(contextName);
- String configBase = configBase().getPath();
- String configFileName = context.getConfigFile();
- if (configFileName != null) {
- File configFile = new File(configFileName);
- if (!configFile.isAbsolute()) {
- configFile = new File(System.getProperty("catalina.base"),
- configFile.getPath());
+ }
+ resources = (String[]) app.reloadResources.toArray(new String[0]);
+ for (int i = 0; i < resources.length; i++) {
+ File resource = new File(resources[i]);
+ if ((!resource.exists()) || (resource.lastModified() > app.timestamp)) {
+ // Reload application
+ Container context = host.findChild(app.name);
+ try {
+ ((Lifecycle) context).stop();
+ } catch (Exception e) {
+ log.warn(sm.getString
+ ("hostConfig.context.restart", app.name), e);
}
- long newLastModified = configFile.lastModified();
- if (lastModified == null) {
- contextXmlLastModified.put
- (contextName, new Long(newLastModified));
- } else {
- if (lastModified.longValue() != newLastModified) {
- contextXmlLastModified.remove(contextName);
- String fileName = configFileName;
- if (fileName.startsWith(configBase)) {
- fileName =
- fileName.substring(configBase.length() + 1);
- try {
- deployed.remove(fileName);
- if (host.findChild(contextName) != null) {
- ((Deployer) host).remove(contextName);
- }
- } catch (Throwable t) {
- log.error(sm.getString
- ("hostConfig.undeployJar.error",
- fileName), t);
- }
- deployApps();
- }
- }
+ // If the context was not started (for example an error
+ // in web.xml) we'll still get to try to start
+ try {
+ ((Lifecycle) context).start();
+ } catch (Exception e) {
+ log.warn(sm.getString
+ ("hostConfig.context.restart", app.name), e);
}
- }
-
- }
-
- // Check for WAR modification
- if (isUnpackWARs()) {
- File appBase = appBase();
- if (!appBase.exists() || !appBase.isDirectory())
+ app.timestamp = System.currentTimeMillis();
return;
- String files[] = appBase.list();
-
- for (int i = 0; i < files.length; i++) {
- if (files[i].endsWith(".war")) {
- File dir = new File(appBase, files[i]);
- Long lastModified = (Long) warLastModified.get(files[i]);
- long dirLastModified = dir.lastModified();
- if (lastModified == null) {
- warLastModified.put
- (files[i], new Long(dir.lastModified()));
- } else if (dirLastModified > lastModified.longValue()) {
- // The WAR has been modified: redeploy
- String expandedDir = files[i];
- int period = expandedDir.lastIndexOf(".");
- if (period >= 0)
- expandedDir = expandedDir.substring(0, period);
- File expanded = new File(appBase, expandedDir);
- String contextPath = "/" + expandedDir;
- if (contextPath.equals("/ROOT"))
- contextPath = "";
- if (dirLastModified > expanded.lastModified()) {
- try {
- // Undeploy current application
- deployed.remove(files[i]);
- deployed.remove(expandedDir + ".xml");
- if (host.findChild(contextPath) != null) {
- ((Deployer) host).remove(contextPath,
- false);
- ExpandWar.deleteDir(expanded);
- }
- } catch (Throwable t) {
- log.error(sm.getString
- ("hostConfig.undeployJar.error",
- files[i]), t);
- }
- deployApps();
- }
- // If deployment was successful, reset
- // the last modified values
- if (host.findChild(contextPath) != null) {
- webXmlLastModified.remove(contextPath);
- warLastModified.put
- (files[i], new Long(dir.lastModified()));
- }
- }
- }
- }
- }
-
- }
-
-
- protected boolean restartContext(Context context) {
- boolean result = true;
- log.info("restartContext(" + context.getName() + ")");
-
- if (context instanceof StandardContext) {
- try {
- StandardContext sctx = (StandardContext)context;
- sctx.reload();
- } catch (Exception e) {
- log.warn(sm.getString
- ("hostConfig.context.restart", context.getName()), e);
- result = false;
- }
- } else {
- try {
- ((Lifecycle) context).stop();
- } catch (Exception e) {
- log.warn(sm.getString
- ("hostConfig.context.restart", context.getName()), e);
- }
- // If the context was not started (for example an error
- // in web.xml) we'll still get to try to start
- try {
- ((Lifecycle) context).start();
- } catch (Exception e) {
- log.warn(sm.getString
- ("hostConfig.context.restart", context.getName()), e);
- result = false;
}
}
-
- return result;
}
-
-
- /**
- * Expand the WAR file found at the specified URL into an unpacked
- * directory structure, and return the absolute pathname to the expanded
- * directory.
- *
- * @param war URL of the web application archive to be expanded
- * (must start with "jar:")
- *
- * @exception IllegalArgumentException if this is not a "jar:" URL
- * @exception IOException if an input/output error was encountered
- * during expansion
- */
- protected String expand(URL war) throws IOException {
-
- return ExpandWar.expand(host,war);
- }
-
-
- /**
- * Expand the specified input stream into the specified directory, creating
- * a file named from the specified relative path.
- *
- * @param input InputStream to be copied
- * @param docBase Document base directory into which we are expanding
- * @param name Relative pathname of the file to be created
- *
- * @exception IOException if an input/output error occurs
- */
- protected void expand(InputStream input, File docBase, String name)
- throws IOException {
-
- ExpandWar.expand(input,docBase,name);
- }
-
-
+
+
/**
* Process a "start" event for this Host.
*/
@@ -893,18 +783,8 @@
if (log.isDebugEnabled())
log.debug(sm.getString("hostConfig.start"));
- if (host.getDeployOnStartup()) {
- deployApps();
- } else {
- // Deploy descriptors anyway (it should be equivalent to being
- // part of server.xml)
- File configBase = configBase();
- if (configBase.exists() && configBase.isDirectory()) {
- String configFiles[] = configBase.list();
- deployDescriptors(configBase, configFiles);
- }
- }
-
+ deployApps();
+
}
@@ -929,77 +809,78 @@
*/
protected void undeployApps() {
- if (!(host instanceof Deployer))
- return;
if (log.isDebugEnabled())
log.debug(sm.getString("hostConfig.undeploying"));
- String contextPaths[] = ((Deployer) host).findDeployedApps();
- for (int i = 0; i < contextPaths.length; i++) {
- if (log.isDebugEnabled())
- log.debug(sm.getString("hostConfig.undeploy", contextPaths[i]));
- try {
- ((Deployer) host).remove(contextPaths[i]);
- } catch (Throwable t) {
- log.error(sm.getString("hostConfig.undeploy.error",
- contextPaths[i]), t);
- }
+ // Soft undeploy all contexts we have deployed
+ DeployedApplication[] apps =
+ (DeployedApplication[]) deployed.values().toArray(new DeployedApplication[0]);
+ for (int i = 0; i < apps.length; i++) {
+ host.removeChild(host.findChild(apps[i].name));
}
-
- webXmlLastModified.clear();
+
deployed.clear();
}
/**
- * Check remove wars, dir and context xml's
- */
- protected void checkRemoveApps() {
- File appBase = appBase();
- File configBase = configBase();
- List currentDeployed = (List) deployed.clone();
- Iterator iter = currentDeployed.iterator();
- while (iter.hasNext()) {
- String filename = (String) iter.next();
- if (filename.toLowerCase().endsWith(".xml")) {
- File file = new File(configBase, filename);
- if (!file.exists()) {
- log.debug(sm.getString("hostConfig.removeXML", filename));
- deployed.remove(filename);
- }
- continue;
- }
- File file = new File(appBase, filename);
- if (!file.exists()) {
- if (log.isDebugEnabled() ) {
- if (filename.toLowerCase().endsWith(".war"))
- log.debug(sm.getString("hostConfig.removeDIR",
- filename));
- else
- log.debug(sm.getString("hostConfig.removeWAR",
- filename));
- }
- deployed.remove(filename);
- }
- }
- }
-
-
- /**
* Deploy webapps.
*/
protected void check() {
if (host.getAutoDeploy()) {
- checkRemoveApps();
- // Deploy apps if the Host allows auto deploying
+ // Check for resources modification to trigger redeployment
+ DeployedApplication[] apps =
+ (DeployedApplication[]) deployed.values().toArray(new DeployedApplication[0]);
+ for (int i = 0; i < apps.length; i++) {
+ checkResources(apps[i]);
+ }
+ // Hotdeploy applications
deployApps();
- // Check for web.xml modification
- checkContextLastModified();
}
}
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * This class represents the state of a deployed application, as well as
+ * the monitored resources.
+ */
+ protected class DeployedApplication {
+ public DeployedApplication(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Application context path. The assertion is that
+ * (host.getChild(name) != null).
+ */
+ public String name;
+
+ /**
+ * Any modification of the specified (static) resources will cause a
+ * redeployment of the application. If any of the specified resources is
+ * removed, the application will be undeployed. Typically, this will
+ * contain resources like the context.xml file, a compressed WAR path.
+ */
+ public ArrayList redeployResources = new ArrayList();
+
+ /**
+ * Any modification of the specified (static) resources will cause a
+ * reload of the application. This will typically contain resources
+ * such as the web.xml of a webapp, but can be configured to contain
+ * additional descriptors.
+ */
+ public ArrayList reloadResources = new ArrayList();
+
+ /**
+ * Instant where the application was last put in service.
+ */
+ public long timestamp = System.currentTimeMillis();
+ }
}
1.47 +348 -54 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/ContextConfig.java
Index: ContextConfig.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/ContextConfig.java,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -r1.46 -r1.47
--- ContextConfig.java 26 Jun 2004 17:41:31 -0000 1.46
+++ ContextConfig.java 23 Jul 2004 22:57:34 -0000 1.47
@@ -41,6 +41,7 @@
import org.apache.catalina.core.ContainerBase;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
+import org.apache.catalina.core.StandardHost;
import org.apache.catalina.deploy.ErrorPage;
import org.apache.catalina.deploy.FilterDef;
import org.apache.catalina.deploy.FilterMap;
@@ -49,6 +50,7 @@
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.util.StringManager;
import org.apache.tomcat.util.digester.Digester;
+import org.apache.tomcat.util.digester.RuleSet;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
@@ -65,7 +67,7 @@
public final class ContextConfig
implements LifecycleListener {
- private static org.apache.commons.logging.Log log=
+ protected static org.apache.commons.logging.Log log=
org.apache.commons.logging.LogFactory.getLog( ContextConfig.class );
// ----------------------------------------------------- Instance Variables
@@ -75,62 +77,69 @@
* the name of the implemented authentication method, and the value is
* the fully qualified Java class name of the corresponding Valve.
*/
- private static Properties authenticators = null;
+ protected static Properties authenticators = null;
/**
* The Context we are associated with.
*/
- private Context context = null;
+ protected Context context = null;
/**
* The default web application's deployment descriptor location.
*/
- private String defaultWebXml = null;
+ protected String defaultWebXml = null;
/**
* Track any fatal errors during startup configuration processing.
*/
- private boolean ok = false;
+ protected boolean ok = false;
/**
* Any parse error which occurred while parsing XML descriptors.
*/
- private SAXParseException parseException = null;
+ protected SAXParseException parseException = null;
/**
* The string resources for this package.
*/
- private static final StringManager sm =
+ protected static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* The <code>Digester</code> we will use to process web application
+ * context files.
+ */
+ protected static Digester contextDigester = null;
+
+
+ /**
+ * The <code>Digester</code> we will use to process web application
* deployment descriptor files.
*/
- private static Digester webDigester = null;
+ protected static Digester webDigester = null;
/**
* The <code>Rule</code> used to parse the web.xml
*/
- private static WebRuleSet webRuleSet = new WebRuleSet();
+ protected static WebRuleSet webRuleSet = new WebRuleSet();
/**
* Attribute value used to turn on/off XML validation
*/
- private static boolean xmlValidation = false;
+ protected static boolean xmlValidation = false;
/**
* Attribute value used to turn on/off XML namespace awarenes.
*/
- private static boolean xmlNamespaceAware = false;
+ protected static boolean xmlNamespaceAware = false;
// ------------------------------------------------------------- Properties
@@ -162,7 +171,7 @@
/**
- * Process the START event for an associated Context.
+ * Process events for an associated Context.
*
* @param event The lifecycle event that has occurred
*/
@@ -171,33 +180,32 @@
// Identify the context we are associated with
try {
context = (Context) event.getLifecycle();
-// if (context instanceof StandardContext) {
-// int contextDebug = ((StandardContext) context).getDebug();
-// if (contextDebug > this.debug)
-// this.debug = contextDebug;
-// }
} catch (ClassCastException e) {
log.error(sm.getString("contextConfig.cce", event.getLifecycle()), e);
return;
}
- // Called from ContainerBase.addChild() -> StandardContext.start()
// Process the event that has occurred
- if (event.getType().equals(Lifecycle.START_EVENT))
+ if (event.getType().equals(Lifecycle.START_EVENT)) {
start();
- else if (event.getType().equals(Lifecycle.STOP_EVENT))
+ } else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
stop();
+ } else if (event.getType().equals(Lifecycle.INIT_EVENT)) {
+ init();
+ } else if (event.getType().equals(Lifecycle.DESTROY_EVENT)) {
+ destroy();
+ }
}
- // -------------------------------------------------------- Private Methods
+ // -------------------------------------------------------- protected Methods
/**
* Process the application configuration file, if it exists.
*/
- private void applicationConfig() {
+ protected void applicationWebConfig() {
// Open the application web.xml file, if it exists
InputStream stream = null;
@@ -271,7 +279,7 @@
/**
* Set up a manager.
*/
- private synchronized void managerConfig() {
+ protected synchronized void managerConfig() {
if (context.getManager() == null) {
if ((context.getCluster() != null) && context.getDistributable()) {
@@ -294,7 +302,7 @@
* Set up an Authenticator automatically if required, and one has not
* already been configured.
*/
- private synchronized void authenticatorConfig() {
+ protected synchronized void authenticatorConfig() {
// Does this Context require an Authenticator?
SecurityConstraint constraints[] = context.findConstraints();
@@ -371,7 +379,7 @@
Pipeline pipeline = ((ContainerBase) context).getPipeline();
if (pipeline != null) {
((ContainerBase) context).addValve(authenticator);
- if( log.isDebugEnabled() )
+ if (log.isDebugEnabled())
log.debug(sm.getString("contextConfig.authenticatorConfigured",
loginConfig.getAuthMethod()));
}
@@ -389,14 +397,14 @@
* Create (if necessary) and return a Digester configured to process the
* web application deployment descriptor (web.xml).
*/
- private static Digester createWebDigester() {
+ protected static Digester createWebDigester() {
Digester webDigester =
createWebXmlDigester(xmlNamespaceAware, xmlValidation);
return webDigester;
}
- /*
+ /**
* Create (if necessary) and return a Digester configured to process the
* web application deployment descriptor (web.xml).
*/
@@ -409,7 +417,23 @@
return webDigester;
}
- private String getBaseDir() {
+
+ /**
+ * Create (if necessary) and return a Digester configured to process the
+ * context configuration descriptor for an application.
+ */
+ protected Digester createContextDigester() {
+ Digester digester = new Digester();
+ digester.setValidating(false);
+ RuleSet contextRuleSet = new ContextRuleSet("", false);
+ digester.addRuleSet(contextRuleSet);
+ RuleSet namingRuleSet = new NamingRuleSet("Context/");
+ digester.addRuleSet(namingRuleSet);
+ return digester;
+ }
+
+
+ protected String getBaseDir() {
Container engineC=context.getParent().getParent();
if( engineC instanceof StandardEngine ) {
return ((StandardEngine)engineC).getBaseDir();
@@ -422,7 +446,7 @@
* The default config must be read with the container loader - so
* container servlets can be loaded
*/
- private void defaultConfig() {
+ protected void defaultWebConfig() {
long t1=System.currentTimeMillis();
// Open the default web.xml file, if it exists
@@ -452,8 +476,6 @@
.getResource(defaultWebXml).toString());
} else {
log.info("No default web.xml");
- // no default web.xml
- return;
}
} else {
source =
@@ -463,27 +485,64 @@
} catch (Exception e) {
log.error(sm.getString("contextConfig.defaultMissing")
+ " " + defaultWebXml + " " + file , e);
- return;
}
if (webDigester == null){
webDigester = createWebDigester();
}
+ if (stream != null) {
+ processDefaultWebConfig(webDigester, stream, source);
+ webRuleSet.recycle();
+ }
+
+ long t2=System.currentTimeMillis();
+ if( (t2-t1) > 200 )
+ log.debug("Processed default web.xml " + file + " " + ( t2-t1));
+
+ stream = null;
+ source = null;
+
+ file = new File(getConfigBase(), "web.xml.default");
+
+ try {
+ if (file.exists()) {
+ source =
+ new InputSource("file://" + file.getAbsolutePath());
+ stream = new FileInputStream(file);
+ }
+ } catch (Exception e) {
+ log.error(sm.getString("contextConfig.defaultMissing")
+ + " " + file , e);
+ }
+
+ if (stream != null) {
+ processDefaultWebConfig(webDigester, stream, source);
+ webRuleSet.recycle();
+ }
+
+ }
+
+
+ /**
+ * Process a default web.xml.
+ */
+ protected void processDefaultWebConfig(Digester digester, InputStream stream,
+ InputSource source) {
// Process the default web.xml file
- synchronized (webDigester) {
+ synchronized (digester) {
try {
source.setByteStream(stream);
if (context instanceof StandardContext)
((StandardContext) context).setReplaceWelcomeFiles(true);
- webDigester.clear();
- webDigester.setClassLoader(this.getClass().getClassLoader());
+ digester.clear();
+ digester.setClassLoader(this.getClass().getClassLoader());
//log.info( "Using cl: " + webDigester.getClassLoader());
- webDigester.setUseContextClassLoader(false);
- webDigester.push(context);
- webDigester.setErrorHandler(new ContextErrorHandler());
- webDigester.parse(source);
+ digester.setUseContextClassLoader(false);
+ digester.push(context);
+ digester.setErrorHandler(new ContextErrorHandler());
+ digester.parse(source);
if (parseException != null) {
ok = false;
}
@@ -507,24 +566,217 @@
}
}
}
- webRuleSet.recycle();
+ }
+
+
+ /**
+ * Process the default configuration file, if it exists.
+ */
+ protected void contextConfig() {
- long t2=System.currentTimeMillis();
- if( (t2-t1) > 200 )
- log.debug("Processed default web.xml " + file + " " + ( t2-t1));
+ // FIXME: Externalize default context.xml path the same way as web.xml
+ processContextConfig(new File(getBaseDir(), "conf/context.xml"));
+ processContextConfig(new File(getConfigBase(), "context.xml.default"));
+ if (context.getConfigFile() != null)
+ processContextConfig(new File(context.getConfigFile()));
+
+ }
+
+
+ /**
+ * Process a context.xml.
+ */
+ protected void processContextConfig(File file) {
+ if (log.isDebugEnabled())
+ log.debug("Processing context [" + context.getName() + "] configuration file " + file);
+ InputSource source = null;
+ InputStream stream = null;
+ try {
+ if (file.exists()) {
+ stream = new FileInputStream(file);
+ source =
+ new InputSource("file://" + file.getAbsolutePath());
+ } else if (log.isDebugEnabled()) {
+ log.debug("Context [" + context.getName() + "] configuration file " + file + " not found");
+ }
+ } catch (Exception e) {
+ log.error(sm.getString("contextConfig.defaultMissing") + file);
+ }
+ if (source == null)
+ return;
+ if (contextDigester == null){
+ contextDigester = createContextDigester();
+ }
+ synchronized (contextDigester) {
+ try {
+ source.setByteStream(stream);
+ contextDigester.clear();
+ contextDigester.setClassLoader(this.getClass().getClassLoader());
+ //log.info( "Using cl: " + webDigester.getClassLoader());
+ contextDigester.setUseContextClassLoader(false);
+ contextDigester.push(context.getParent());
+ contextDigester.push(context);
+ contextDigester.setErrorHandler(new ContextErrorHandler());
+ contextDigester.parse(source);
+ if (parseException != null) {
+ ok = false;
+ }
+ } catch (SAXParseException e) {
+ log.error(sm.getString("contextConfig.defaultParse"), e);
+ log.error(sm.getString("contextConfig.defaultPosition",
+ "" + e.getLineNumber(),
+ "" + e.getColumnNumber()));
+ ok = false;
+ } catch (Exception e) {
+ log.error(sm.getString("contextConfig.defaultParse"), e);
+ ok = false;
+ } finally {
+ parseException = null;
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ log.error(sm.getString("contextConfig.defaultClose"), e);
+ }
+ }
+ }
}
+
+ /**
+ * Adjust docBase.
+ */
+ protected void fixDocBase()
+ throws IOException {
+
+ Host host = (Host) context.getParent();
+ String appBase = host.getAppBase();
+
+ boolean unpackWARs = true;
+ if (host instanceof StandardHost) {
+ unpackWARs = ((StandardHost) host).isUnpackWARs()
+ && ((StandardContext) context).getUnpackWAR();
+ }
+
+ File canonicalAppBase = new File(appBase);
+ if (canonicalAppBase.isAbsolute()) {
+ canonicalAppBase = canonicalAppBase.getCanonicalFile();
+ } else {
+ canonicalAppBase =
+ new File(System.getProperty("catalina.base"), appBase)
+ .getCanonicalFile();
+ }
+
+ String docBase = context.getDocBase();
+ if (docBase == null) {
+ // Trying to guess the docBase according to the path
+ String path = context.getPath();
+ if (path == null) {
+ return;
+ }
+ if (path.equals("")) {
+ docBase = "ROOT";
+ } else {
+ if (path.startsWith("/")) {
+ docBase = path.substring(1);
+ } else {
+ docBase = path;
+ }
+ }
+ }
+
+ File file = new File(docBase);
+ if (!file.isAbsolute()) {
+ docBase = (new File(canonicalAppBase, docBase)).getPath();
+ } else {
+ docBase = file.getCanonicalPath();
+ }
+
+ if (docBase.toLowerCase().endsWith(".war") && unpackWARs) {
+ URL war = new URL("jar:" + (new File(docBase)).toURL() + "!/");
+ String contextPath = context.getPath();
+ if (contextPath.equals("")) {
+ contextPath = "ROOT";
+ }
+ docBase = ExpandWar.expand(host, war, contextPath);
+ file = new File(docBase);
+ docBase = file.getCanonicalPath();
+ } else {
+ File docDir = new File(docBase);
+ if (!docDir.exists()) {
+ File warFile = new File(docBase + ".war");
+ if (warFile.exists()) {
+ if (unpackWARs) {
+ URL war = new URL("jar:" + warFile.toURL() + "!/");
+ docBase = ExpandWar.expand(host, war, context.getPath());
+ file = new File(docBase);
+ docBase = file.getCanonicalPath();
+ } else {
+ docBase = warFile.getCanonicalPath();
+ }
+ }
+ }
+ }
+
+ if (docBase.startsWith(canonicalAppBase.getPath())) {
+ docBase = docBase.substring(canonicalAppBase.getPath().length());
+ docBase = docBase.replace(File.separatorChar, '/');
+ if (docBase.startsWith("/")) {
+ docBase = docBase.substring(1);
+ }
+ } else {
+ docBase = docBase.replace(File.separatorChar, '/');
+ }
+
+ context.setDocBase(docBase);
+
+ }
+
+
+ protected void antiLocking()
+ throws IOException {
+ // FIXME: Implement anti locking, if it is enabled, by copying the whole
+ // contents of the docBase to a unique folder in temp, and setting the docBase
+ // to point to that
+ }
+
/**
- * Process a "start" event for this Context - in background
+ * Process a "init" event for this Context.
*/
- private synchronized void start() {
- // Called from StandardContext.start()
+ protected void init() {
+ // Called from StandardContext.init()
if (log.isDebugEnabled())
- log.debug(sm.getString("contextConfig.start"));
+ log.debug(sm.getString("contextConfig.init"));
context.setConfigured(false);
ok = true;
+
+ contextConfig();
+
+ try {
+ fixDocBase();
+ } catch (IOException e) {
+ log.error(sm.getString("contextConfig.fixDocBase"), e);
+ }
+ try {
+ antiLocking();
+ } catch (IOException e) {
+ log.error(sm.getString("contextConfig.antiLocking"), e);
+ }
+
+ }
+
+
+ /**
+ * Process a "start" event for this Context.
+ */
+ protected synchronized void start() {
+ // Called from StandardContext.start()
+
+ if (log.isDebugEnabled())
+ log.debug(sm.getString("contextConfig.start"));
// Set properties based on DefaultContext
Container container = context.getParent();
@@ -553,8 +805,8 @@
}
// Process the default and application web.xml files
- defaultConfig();
- applicationConfig();
+ defaultWebConfig();
+ applicationWebConfig();
if (ok) {
validateSecurityRoles();
}
@@ -596,7 +848,7 @@
/**
* Process a "stop" event for this Context.
*/
- private synchronized void stop() {
+ protected synchronized void stop() {
if (log.isDebugEnabled())
log.debug(sm.getString("contextConfig.stop"));
@@ -745,7 +997,19 @@
ok = true;
}
-
+
+
+ /**
+ * Process a "destroy" event for this Context.
+ */
+ protected synchronized void destroy() {
+ // Called from StandardContext.destroy()
+ if (log.isDebugEnabled())
+ log.debug(sm.getString("contextConfig.destroy"));
+
+ }
+
+
/**
* Validate the usage of security role names in the web application
* deployment descriptor. If any problems are found, issue warning
@@ -753,7 +1017,7 @@
* (To make these problems fatal instead, simply set the <code>ok</code>
* instance variable to <code>false</code> as well).
*/
- private void validateSecurityRoles() {
+ protected void validateSecurityRoles() {
// Check role names used in <security-constraint> elements
SecurityConstraint constraints[] = context.findConstraints();
@@ -790,7 +1054,37 @@
}
- private class ContextErrorHandler
+ /**
+ * Get config base.
+ */
+ protected File getConfigBase() {
+ File configBase =
+ new File(System.getProperty("catalina.base"), "conf");
+ if (!configBase.exists()) {
+ return null;
+ }
+ Container container = context;
+ 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) {
+ configBase = new File(configBase, engine.getName());
+ }
+ if (host != null) {
+ configBase = new File(configBase, host.getName());
+ }
+ configBase.mkdirs();
+ return configBase;
+ }
+
+
+ protected class ContextErrorHandler
implements ErrorHandler {
public void error(SAXParseException exception) {
1.10 +36 -10 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/ContextRuleSet.java
Index: ContextRuleSet.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/ContextRuleSet.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ContextRuleSet.java 26 Jun 2004 17:41:31 -0000 1.9
+++ ContextRuleSet.java 23 Jul 2004 22:57:34 -0000 1.10
@@ -49,6 +49,12 @@
protected String prefix = null;
+ /**
+ * Should the context be created.
+ */
+ protected boolean create = true;
+
+
// ------------------------------------------------------------ Constructor
@@ -79,6 +85,23 @@
}
+ /**
+ * Construct an instance of this <code>RuleSet</code> with the specified
+ * matching pattern prefix.
+ *
+ * @param prefix Prefix for matching pattern rules (including the
+ * trailing slash character)
+ */
+ public ContextRuleSet(String prefix, boolean create) {
+
+ super();
+ this.namespaceURI = null;
+ this.prefix = prefix;
+ this.create = create;
+
+ }
+
+
// --------------------------------------------------------- Public Methods
@@ -93,27 +116,30 @@
*/
public void addRuleInstances(Digester digester) {
- if (!isDefaultContext()) {
- digester.addObjectCreate(prefix + "Context",
- "org.apache.catalina.core.StandardContext",
- "className");
- } else {
- digester.addObjectCreate(prefix + "Context",
- "org.apache.catalina.core.StandardDefaultContext",
- "className");
+ if (create) {
+ if (!isDefaultContext()) {
+ digester.addObjectCreate(prefix + "Context",
+ "org.apache.catalina.core.StandardContext",
+ "className");
+ } else {
+ digester.addObjectCreate(prefix + "Context",
+ "org.apache.catalina.core.StandardDefaultContext",
+ "className");
+ }
}
digester.addSetProperties(prefix + "Context");
if (!isDefaultContext()) {
digester.addRule(prefix + "Context",
new CopyParentClassLoaderRule());
+ if (create) {
digester.addRule(prefix + "Context",
new LifecycleListenerRule
("org.apache.catalina.startup.ContextConfig",
"configClass"));
- digester.addRule(prefix + "Context", new SetDocBaseRule());
digester.addSetNext(prefix + "Context",
"addChild",
"org.apache.catalina.Container");
+ }
} else {
digester.addSetNext(prefix + "Context",
"addDefaultContext",
1.134 +10 -2 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java
Index: StandardContext.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java,v
retrieving revision 1.133
retrieving revision 1.134
diff -u -r1.133 -r1.134
--- StandardContext.java 24 Jun 2004 22:09:52 -0000 1.133
+++ StandardContext.java 23 Jul 2004 22:57:35 -0000 1.134
@@ -4064,6 +4064,7 @@
boolean ok = true;
// Set config file name
+ /*
File configBase = getConfigBase();
if ((configBase != null) && saveConfig) {
if (getConfigFile() == null) {
@@ -4103,6 +4104,7 @@
}
}
}
+ */
// Install DefaultContext configuration
if (!getOverride()) {
@@ -4589,6 +4591,9 @@
}
super.destroy();
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(DESTROY_EVENT, null);
+
instanceListeners = new String[0];
applicationListeners = new String[0];
}
@@ -4843,7 +4848,7 @@
/**
* Get config base.
*/
- private File getConfigBase() {
+ public File getConfigBase() {
File configBase =
new File(System.getProperty("catalina.base"), "conf");
if (!configBase.exists()) {
@@ -5457,6 +5462,9 @@
}
super.init();
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(INIT_EVENT, null);
+
// Send j2ee.state.starting notification
if (this.getObjectName() != null) {
Notification notification = new Notification("j2ee.state.starting",
1.3 +13 -1 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Lifecycle.java
Index: Lifecycle.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Lifecycle.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Lifecycle.java 27 Feb 2004 14:58:38 -0000 1.2
+++ Lifecycle.java 23 Jul 2004 22:57:35 -0000 1.3
@@ -35,6 +35,12 @@
/**
+ * The LifecycleEvent type for the "component init" event.
+ */
+ public static final String INIT_EVENT = "init";
+
+
+ /**
* The LifecycleEvent type for the "component start" event.
*/
public static final String START_EVENT = "start";
@@ -68,6 +74,12 @@
* The LifecycleEvent type for the "component after stop" event.
*/
public static final String AFTER_STOP_EVENT = "after_stop";
+
+
+ /**
+ * The LifecycleEvent type for the "component destroy" event.
+ */
+ public static final String DESTROY_EVENT = "destroy";
// --------------------------------------------------------- Public Methods
1.14 +3 -1 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Context.java
Index: Context.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Context.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- Context.java 23 Jun 2004 16:59:42 -0000 1.13
+++ Context.java 23 Jul 2004 22:57:35 -0000 1.14
@@ -18,6 +18,8 @@
package org.apache.catalina;
+import java.io.File;
+
import javax.servlet.ServletContext;
import org.apache.tomcat.util.http.mapper.Mapper;
1.9 +17 -1 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Host.java
Index: Host.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Host.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- Host.java 27 Feb 2004 14:58:38 -0000 1.8
+++ Host.java 23 Jul 2004 22:57:35 -0000 1.9
@@ -99,6 +99,22 @@
/**
+ * Return the Java class name of the context configuration class
+ * for new web applications.
+ */
+ public String getConfigClass();
+
+
+ /**
+ * Set the Java class name of the context configuration class
+ * for new web applications.
+ *
+ * @param configClass The new context configuration class
+ */
+ public void setConfigClass(String configClass);
+
+
+ /**
* Set the DefaultContext
* for new web applications.
*
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org