remm 2004/07/27 00:17:21 Modified: catalina/src/share/org/apache/catalina/startup HostConfig.java mbeans-descriptors.xml catalina/src/share/org/apache/catalina Container.java Log: - Modify HostConfig for use in the manager servlet, as planned. - Add JMX registration for this component. - Still some tweak are needed for handling undeploying (one quick example which causes problems right now is trying to undeploy the admin webapp). Revision Changes Path 1.38 +340 -214 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.37 retrieving revision 1.38 diff -u -r1.37 -r1.38 --- HostConfig.java 26 Jul 2004 10:56:53 -0000 1.37 +++ HostConfig.java 27 Jul 2004 07:17:21 -0000 1.38 @@ -28,6 +28,8 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; +import javax.management.ObjectName; + import org.apache.catalina.Container; import org.apache.catalina.Context; import org.apache.catalina.Engine; @@ -38,6 +40,7 @@ import org.apache.catalina.core.ContainerBase; import org.apache.catalina.core.StandardHost; import org.apache.catalina.util.StringManager; +import org.apache.commons.modeler.Registry; import org.apache.tomcat.util.digester.Digester; @@ -88,6 +91,12 @@ */ protected Host host = null; + + /** + * The JMX ObjectName of this component. + */ + protected ObjectName oname = null; + /** * The string resources for this package. @@ -415,6 +424,34 @@ /** + * Given a context path, get the config file name. + */ + protected String getConfigFile(String path) { + String basename = null; + if (path.equals("")) { + basename = "ROOT"; + } else { + basename = path.substring(1).replace('/', '#'); + } + return (basename); + } + + + /** + * Given a context path, get the config file name. + */ + protected String getDocBase(String path) { + String basename = null; + if (path.equals("")) { + basename = "ROOT"; + } else { + basename = path.substring(1); + } + return (basename); + } + + + /** * Deploy applications for any directories or WAR files that are found * in our "application root" directory. */ @@ -433,6 +470,33 @@ /** + * Deploy applications for any directories or WAR files that are found + * in our "application root" directory. + */ + protected void deployApps(String name) { + + File appBase = appBase(); + File configBase = configBase(); + String baseName = getConfigFile(name); + String docBase = getConfigFile(name); + + // Deploy XML descriptors from configBase + File xml = new File(configBase, baseName + ".xml"); + if (xml.exists()) + deployDescriptor(name, xml, baseName + ".xml"); + // Deploy WARs, and loop if additional descriptors are found + File war = new File(appBase, docBase + ".war"); + if (war.exists()) + deployWAR(name, war, docBase + ".war"); + // Deploy expanded folders + File dir = new File(appBase, docBase); + if (dir.exists()) + deployDirectory(name, dir, docBase); + + } + + + /** * Deploy XML context descriptors. */ protected void deployDescriptors(File configBase, String[] files) { @@ -450,78 +514,18 @@ if (files[i].toLowerCase().endsWith(".xml")) { // Calculate the context path and make sure it is unique - String file = files[i].substring(0, files[i].length() - 4); - String contextPath = "/" + file.replace('#', '/'); - if (file.equals("ROOT")) { + String nameTmp = files[i].substring(0, files[i].length() - 4); + String contextPath = "/" + nameTmp.replace('#', '/'); + if (nameTmp.equals("ROOT")) { contextPath = ""; } - if (deployed.containsKey(contextPath)) + if (isServiced(contextPath)) continue; - - DeployedApplication deployedApp = new DeployedApplication(contextPath); - // Assume this is a configuration descriptor and deploy it - log.debug(sm.getString("hostConfig.deployDescriptor", files[i])); - try { - Context context = null; - synchronized (digester) { - context = (Context) digester.parse(contextXml); - } - if (context instanceof Lifecycle) { - Class clazz = Class.forName(host.getConfigClass()); - LifecycleListener listener = - (LifecycleListener) clazz.newInstance(); - ((Lifecycle) context).addLifecycleListener(listener); - } - context.setConfigFile(contextXml.getAbsolutePath()); - context.setPath(contextPath); - // Add the context XML to the list of watched files - deployedApp.reloadResources.put - (contextXml.getAbsolutePath(), new Long(contextXml.lastModified())); - // Add the associated docBase to the redeployed list if it's a WAR - boolean isWar = false; - if (context.getDocBase() != null) { - File docBase = new File(context.getDocBase()); - if (!docBase.isAbsolute()) { - docBase = new File(new File(host.getAppBase()), - context.getDocBase()); - } - deployedApp.redeployResources.put(docBase.getAbsolutePath(), - new Long(docBase.lastModified())); - if (docBase.getAbsolutePath().toLowerCase().endsWith(".war")) { - isWar = true; - } - } - host.addChild(context); - // Add the eventual unpacked WAR and all the resources which will be - // watched inside it - if (isWar && unpackWARs) { - String name = null; - String path = context.getPath(); - if (path.equals("")) { - name = "ROOT"; - } else { - if (path.startsWith("/")) { - name = path.substring(1); - } else { - name = path; - } - } - File docBase = new File(name); - if (!docBase.isAbsolute()) { - docBase = new File(new File(host.getAppBase()), name); - } - deployedApp.redeployResources.put(docBase.getAbsolutePath(), - new Long(docBase.lastModified())); - addWatchedResources(deployedApp, docBase.getAbsolutePath(), context); - } - } catch (Throwable t) { - log.error(sm.getString("hostConfig.deployDescriptor.error", - files[i]), t); - } + String file = files[i]; - deployed.put(contextPath, deployedApp); + deployDescriptor(contextPath, contextXml, file); } @@ -531,6 +535,82 @@ /** + * @param contextPath + * @param contextXml + * @param file + */ + protected void deployDescriptor(String contextPath, File contextXml, String file) { + DeployedApplication deployedApp = new DeployedApplication(contextPath); + + if (deployed.containsKey(contextPath)) + return; + + // Assume this is a configuration descriptor and deploy it + log.debug(sm.getString("hostConfig.deployDescriptor", file)); + try { + Context context = null; + synchronized (digester) { + context = (Context) digester.parse(contextXml); + } + if (context instanceof Lifecycle) { + Class clazz = Class.forName(host.getConfigClass()); + LifecycleListener listener = + (LifecycleListener) clazz.newInstance(); + ((Lifecycle) context).addLifecycleListener(listener); + } + context.setConfigFile(contextXml.getAbsolutePath()); + context.setPath(contextPath); + // Add the context XML to the list of watched files + // FIXME: Special case of a xml which points to a WAR without unpackWAR or + // a directory outside of appBase -> the .xml should be a redeployResource + deployedApp.reloadResources.put + (contextXml.getAbsolutePath(), new Long(contextXml.lastModified())); + // Add the associated docBase to the redeployed list if it's a WAR + boolean isWar = false; + if (context.getDocBase() != null) { + File docBase = new File(context.getDocBase()); + if (!docBase.isAbsolute()) { + docBase = new File(appBase(), context.getDocBase()); + } + deployedApp.redeployResources.put(docBase.getAbsolutePath(), + new Long(docBase.lastModified())); + if (docBase.getAbsolutePath().toLowerCase().endsWith(".war")) { + isWar = true; + } + } + host.addChild(context); + // Add the eventual unpacked WAR and all the resources which will be + // watched inside it + if (isWar && unpackWARs) { + String name = null; + String path = context.getPath(); + if (path.equals("")) { + name = "ROOT"; + } else { + if (path.startsWith("/")) { + name = path.substring(1); + } else { + name = path; + } + } + File docBase = new File(name); + if (!docBase.isAbsolute()) { + docBase = new File(appBase(), name); + } + deployedApp.redeployResources.put(docBase.getAbsolutePath(), + new Long(docBase.lastModified())); + addWatchedResources(deployedApp, docBase.getAbsolutePath(), context); + } + } catch (Throwable t) { + log.error(sm.getString("hostConfig.deployDescriptor.error", + file), t); + } + + deployed.put(contextPath, deployedApp); + } + + + /** * Deploy WAR files. */ protected void deployWARs(File appBase, String[] files) { @@ -557,134 +637,145 @@ if (contextPath.equals("/ROOT")) contextPath = ""; - if (deployed.containsKey(contextPath)) + if (isServiced(contextPath)) continue; - // 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; - } - } 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; + String file = files[i]; + + deployWAR(contextPath, dir, file); + + } + + } + + } + + + /** + * @param contextPath + * @param dir + * @param file + */ + protected void deployWAR(String contextPath, File dir, String file) { + if (deployed.containsKey(contextPath)) + return; + // 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, file.substring(0, file.lastIndexOf(".")) + ".xml"); + if (deployXML && !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; } - - DeployedApplication deployedApp = new DeployedApplication(contextPath); - - // Deploy the application in this WAR file - log.info(sm.getString("hostConfig.deployJar", files[i])); - try { - 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); + } catch (Exception e) { + // Ignore and continue + if (ostream != null) { + try { + ostream.close(); + } catch (Throwable t) { + ; } - context.setPath(contextPath); - context.setDocBase(files[i]); - if (xml.exists()) { - context.setConfigFile(xml.getAbsolutePath()); - deployedApp.reloadResources.put - (xml.getAbsolutePath(), new Long(xml.lastModified())); + ostream = null; + } + if (istream != null) { + try { + istream.close(); + } catch (Throwable t) { + ; } - host.addChild(context); - // If we're unpacking WARs, the docBase will be mutated after - // starting the context - if (unpackWARs && (context.getDocBase() != null)) { - String name = null; - String path = context.getPath(); - if (path.equals("")) { - name = "ROOT"; - } else { - if (path.startsWith("/")) { - name = path.substring(1); - } else { - name = path; - } - } - File docBase = new File(name); - if (!docBase.isAbsolute()) { - docBase = new File(new File(host.getAppBase()), name); - } - deployedApp.redeployResources.put(docBase.getAbsolutePath(), - new Long(docBase.lastModified())); - addWatchedResources(deployedApp, docBase.getAbsolutePath(), context); + istream = null; + } + } finally { + entry = null; + if (jar != null) { + try { + jar.close(); + } catch (Throwable t) { + ; } - } catch (Throwable t) { - log.error(sm.getString("hostConfig.deployJar.error", - files[i]), t); + jar = null; } - - // Populate redeploy resources with the WAR file - deployedApp.redeployResources.put - (dir.getAbsolutePath(), new Long(dir.lastModified())); - deployed.put(contextPath, deployedApp); - } - } + DeployedApplication deployedApp = new DeployedApplication(contextPath); + + // Deploy the application in this WAR file + log.info(sm.getString("hostConfig.deployJar", file)); + try { + 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(file); + if (xml.exists()) { + context.setConfigFile(xml.getAbsolutePath()); + deployedApp.reloadResources.put + (xml.getAbsolutePath(), new Long(xml.lastModified())); + } + host.addChild(context); + // If we're unpacking WARs, the docBase will be mutated after + // starting the context + if (unpackWARs && (context.getDocBase() != null)) { + String name = null; + String path = context.getPath(); + if (path.equals("")) { + name = "ROOT"; + } else { + if (path.startsWith("/")) { + name = path.substring(1); + } else { + name = path; + } + } + File docBase = new File(name); + if (!docBase.isAbsolute()) { + docBase = new File(appBase(), name); + } + deployedApp.redeployResources.put(docBase.getAbsolutePath(), + new Long(docBase.lastModified())); + addWatchedResources(deployedApp, docBase.getAbsolutePath(), context); + } + } catch (Throwable t) { + log.error(sm.getString("hostConfig.deployJar.error", file), t); + } + + // Populate redeploy resources with the WAR file + deployedApp.redeployResources.put + (dir.getAbsolutePath(), new Long(dir.lastModified())); + deployed.put(contextPath, deployedApp); } @@ -719,36 +810,12 @@ if (files[i].equals("ROOT")) contextPath = ""; - if (deployed.containsKey(contextPath)) + if (isServiced(contextPath)) continue; - DeployedApplication deployedApp = new DeployedApplication(contextPath); + String file = files[i]; - // Deploy the application in this directory - if( log.isDebugEnabled() ) - log.debug(sm.getString("hostConfig.deployDir", files[i])); - try { - 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); - deployedApp.redeployResources.put(dir.getAbsolutePath(), - new Long(dir.lastModified())); - addWatchedResources(deployedApp, dir.getAbsolutePath(), context); - } catch (Throwable t) { - log.error(sm.getString("hostConfig.deployDir.error", files[i]), - t); - } - - deployed.put(contextPath, deployedApp); + deployDirectory(contextPath, dir, file); } @@ -758,6 +825,46 @@ /** + * @param contextPath + * @param dir + * @param file + */ + protected void deployDirectory(String contextPath, File dir, String file) { + DeployedApplication deployedApp = new DeployedApplication(contextPath); + + if (deployed.containsKey(contextPath)) + return; + + // Deploy the application in this directory + if( log.isDebugEnabled() ) + log.debug(sm.getString("hostConfig.deployDir", file)); + try { + 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(file); + if (deployXML) { + context.setConfigFile + ((new File(dir, "META-INF/context.xml")).getAbsolutePath()); + } + host.addChild(context); + deployedApp.redeployResources.put(dir.getAbsolutePath(), + new Long(dir.lastModified())); + addWatchedResources(deployedApp, dir.getAbsolutePath(), context); + } catch (Throwable t) { + log.error(sm.getString("hostConfig.deployDir.error", file), t); + } + + deployed.put(contextPath, deployedApp); + } + + + /** * Add watched resources to the specified Context. * @param app */ @@ -766,7 +873,7 @@ // we would only check if at least one resource is newer than app.timestamp File docBaseFile = new File(docBase); if (!docBaseFile.isAbsolute()) { - docBaseFile = new File(new File(host.getAppBase()), docBase); + docBaseFile = new File(appBase(), docBase); } String[] watchedResources = context.findWatchedResources(); for (int i = 0; i < watchedResources.length; i++) { @@ -786,6 +893,8 @@ File resource = new File(resources[i]); if (log.isDebugEnabled()) log.debug("Checking context[" + app.name + "] redeploy resource " + resource); + // FIXME: Limit, as before, resource removal to resources which are inside the + // Host appBase if (resource.exists()) { long lastModified = ((Long) app.redeployResources.get(resources[i])).longValue(); if ((!resource.isDirectory()) && resource.lastModified() > lastModified) { @@ -871,6 +980,16 @@ if (log.isDebugEnabled()) log.debug(sm.getString("hostConfig.start")); + try { + ObjectName hostON = new ObjectName(host.getObjectName()); + oname = new ObjectName + (hostON.getDomain() + ":type=Deployer,host=" + host.getName()); + Registry.getRegistry(null, null).registerComponent + (this, oname, this.getClass().getName()); + } catch (Exception e) { + log.error(sm.getString("hostConfig.jmx.register"), e); + } + deployApps(); } @@ -886,6 +1005,14 @@ undeployApps(); + if (oname != null) { + try { + Registry.getRegistry(null, null).unregisterComponent(oname); + } catch (Exception e) { + log.error(sm.getString("hostConfig.jmx.unregister"), e); + } + } + oname = null; appBase = null; configBase = null; @@ -935,13 +1062,12 @@ /** * Check status of a specific webapp, for use with stuff like management webapps. */ - protected void check(String name) { + public void check(String name) { DeployedApplication app = (DeployedApplication) deployed.get(name); if (app != null) { checkResources(app); } else { - // FIXME: add a version of deployApps which would check only for - // deployment of a specified app.name + deployApps(name); } } 1.3 +36 -0 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/mbeans-descriptors.xml Index: mbeans-descriptors.xml =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/mbeans-descriptors.xml,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- mbeans-descriptors.xml 14 Jul 2004 06:19:32 -0000 1.2 +++ mbeans-descriptors.xml 27 Jul 2004 07:17:21 -0000 1.3 @@ -47,6 +47,42 @@ description="The Java class name of the Context implementation we should use" type="java.lang.String"/> + <operation name="check" + description="Check a web application name for updates" + impact="ACTION" + returnType="void"> + <parameter name="name" + description="Application name" + type="java.lang.String"/> + </operation> + + <operation name="addServiced" + description="Add a web application name to the serviced list" + impact="ACTION" + returnType="void"> + <parameter name="name" + description="Application name" + type="java.lang.String"/> + </operation> + + <operation name="isServiced" + description="Add a web application name to the serviced list" + impact="ACTION" + returnType="boolean"> + <parameter name="name" + description="Application name" + type="java.lang.String"/> + </operation> + + <operation name="removeServiced" + description="Add a web application name to the serviced list" + impact="ACTION" + returnType="void"> + <parameter name="name" + description="Application name" + type="java.lang.String"/> + </operation> + </mbean> </mbeans-descriptors> 1.11 +6 -1 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Container.java Index: Container.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/Container.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- Container.java 23 Jun 2004 13:51:36 -0000 1.10 +++ Container.java 27 Jul 2004 07:17:21 -0000 1.11 @@ -184,6 +184,11 @@ */ public Object getMappingObject(); + + /** + * Return the JMX name associated with this container. + */ + public String getObjectName(); /** * Return the Pipeline object that manages the Valves associated with
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]