Author: remy.maucherat(a)jboss.com
Date: 2009-04-24 15:33:12 -0400 (Fri, 24 Apr 2009)
New Revision: 1028
Added:
trunk/java/org/apache/catalina/JarRepository.java
trunk/java/org/apache/catalina/core/ContextJarRepository.java
Modified:
trunk/java/org/apache/catalina/Container.java
trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
trunk/java/org/apache/catalina/core/ContainerBase.java
trunk/java/org/apache/catalina/core/LocalStrings.properties
trunk/java/org/apache/catalina/deploy/WebOrdering.java
trunk/java/org/apache/catalina/startup/ContextConfig.java
Log:
- Given the amount of JAR open/close needed, add a new JarRespository contained object.
- Existing code (including the CL) will be refactored to use it.
Modified: trunk/java/org/apache/catalina/Container.java
===================================================================
--- trunk/java/org/apache/catalina/Container.java 2009-04-24 15:11:36 UTC (rev 1027)
+++ trunk/java/org/apache/catalina/Container.java 2009-04-24 19:33:12 UTC (rev 1028)
@@ -335,6 +335,23 @@
public void setResources(DirContext resources);
+ /**
+ * Return the JarRepository with which this Container is associated.
+ * If there is no associated JarRepository, return the JarRepository
+ * associated with our parent Container (if any);
+ * otherwise return <code>null</code>.
+ */
+ public JarRepository getJarRepository();
+
+
+ /**
+ * Set the JarRepository with which this Container is associated.
+ *
+ * @param jarRepository The newly associated JarRepository
+ */
+ public void setJarRepository(JarRepository jarRepository);
+
+
// --------------------------------------------------------- Public Methods
Added: trunk/java/org/apache/catalina/JarRepository.java
===================================================================
--- trunk/java/org/apache/catalina/JarRepository.java (rev 0)
+++ trunk/java/org/apache/catalina/JarRepository.java 2009-04-24 19:33:12 UTC (rev 1028)
@@ -0,0 +1,92 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+
+package org.apache.catalina;
+
+import java.util.jar.JarFile;
+
+
+/**
+ * A JARRepository manages a set of JARs associated with a Context, and
+ * allows efficient access to them.
+ *
+ * @author Remy Maucherat
+ * @version $Revision: 515 $ $Date: 2008-03-17 22:02:23 +0100 (Mon, 17 Mar 2008) $
+ */
+public interface JarRepository {
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * Return the Container with which this JARRepository has been associated.
+ */
+ public Container getContainer();
+
+
+ /**
+ * Set the Container with which this JARRepository has been associated.
+ *
+ * @param container The associated Container
+ */
+ public void setContainer(Container container);
+
+
+ /**
+ * Return descriptive information about this JARRepository implementation and
+ * the corresponding version number, in the format
+ * <code><description>/<version></code>.
+ */
+ public String getInfo();
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Execute a periodic task, such as reloading, etc. This method will be
+ * invoked inside the classloading context of this container. Unexpected
+ * throwables will be caught and logged.
+ */
+ public void backgroundProcess();
+
+
+ /**
+ * Get a JarFile with the specified name.
+ *
+ * @param name
+ * @return
+ */
+ public JarFile getJar(String name);
+
+
+ /**
+ * Find all JarFile managed by the JARRepository.
+ *
+ * @return All JarFile
+ */
+ public JarFile[] findJars();
+
+
+}
Modified: trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
===================================================================
--- trunk/java/org/apache/catalina/connector/CoyoteAdapter.java 2009-04-24 15:11:36 UTC
(rev 1027)
+++ trunk/java/org/apache/catalina/connector/CoyoteAdapter.java 2009-04-24 19:33:12 UTC
(rev 1028)
@@ -1,18 +1,46 @@
/*
- * 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
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
*
- *
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.
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 1999-2009 The Apache Software Foundation
+ *
+ * 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.
*/
@@ -20,8 +48,6 @@
import java.io.IOException;
-import javax.servlet.SessionTrackingMode;
-
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.Wrapper;
Modified: trunk/java/org/apache/catalina/core/ContainerBase.java
===================================================================
--- trunk/java/org/apache/catalina/core/ContainerBase.java 2009-04-24 15:11:36 UTC (rev
1027)
+++ trunk/java/org/apache/catalina/core/ContainerBase.java 2009-04-24 19:33:12 UTC (rev
1028)
@@ -43,6 +43,7 @@
import org.apache.catalina.ContainerEvent;
import org.apache.catalina.ContainerListener;
import org.apache.catalina.Globals;
+import org.apache.catalina.JarRepository;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
@@ -255,6 +256,12 @@
/**
+ * The JarRepository with which this Container is associated.
+ */
+ protected JarRepository jarRepository = null;
+
+
+ /**
* The string manager for this package.
*/
protected static StringManager sm =
@@ -722,6 +729,63 @@
/**
+ * Return the JarRepository with which this Container is associated. If there is
+ * no associated JarRepository, return the JarRepository associated with our parent
+ * Container (if any); otherwise return <code>null</code>.
+ */
+ public JarRepository getJarRepository() {
+
+ if (jarRepository != null)
+ return (jarRepository);
+ if (parent != null)
+ return (parent.getJarRepository());
+ return (null);
+
+ }
+
+
+ /**
+ * Set the JarRepository with which this Container is associated.
+ *
+ * @param jarRepository The newly associated JarRepository
+ */
+ public synchronized void setJarRepository(JarRepository jarRepository) {
+
+ // Change components if necessary
+ JarRepository oldJarRepository = this.jarRepository;
+ if (oldJarRepository == jarRepository)
+ return;
+ this.jarRepository = jarRepository;
+
+ // Stop the old component if necessary
+ if (started && (oldJarRepository != null) &&
+ (oldJarRepository instanceof Lifecycle)) {
+ try {
+ ((Lifecycle) oldJarRepository).stop();
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.setJarRepository: stop: ", e);
+ }
+ }
+
+ // Start the new component if necessary
+ if (jarRepository != null)
+ jarRepository.setContainer(this);
+ if (started && (jarRepository != null) &&
+ (jarRepository instanceof Lifecycle)) {
+ try {
+ ((Lifecycle) jarRepository).start();
+ } catch (LifecycleException e) {
+ log.error("ContainerBase.setJarRepository: start: ", e);
+ }
+ }
+
+ // Report this property change to interested listeners
+ support.firePropertyChange("jarRepository", oldJarRepository,
this.jarRepository);
+
+ }
+
+
+ /**
* Return the resources DirContext object with which this Container is
* associated. If there is no associated resources object, return the
* resources associated with our parent Container (if any); otherwise
@@ -1022,6 +1086,8 @@
started = true;
// Start our subordinate components, if any
+ if ((jarRepository != null) && (jarRepository instanceof Lifecycle))
+ ((Lifecycle) jarRepository).start();
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
logger = null;
@@ -1121,6 +1187,9 @@
if ((loader != null) && (loader instanceof Lifecycle)) {
((Lifecycle) loader).stop();
}
+ if ((jarRepository != null) && (jarRepository instanceof Lifecycle)) {
+ ((Lifecycle) jarRepository).stop();
+ }
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
@@ -1324,6 +1393,13 @@
log.warn(sm.getString("containerBase.backgroundProcess.realm",
realm), e);
}
}
+ if (jarRepository != null) {
+ try {
+ jarRepository.backgroundProcess();
+ } catch (Exception e) {
+
log.warn(sm.getString("containerBase.backgroundProcess.jarRepository",
jarRepository), e);
+ }
+ }
Valve current = pipeline.getFirst();
while (current != null) {
try {
Added: trunk/java/org/apache/catalina/core/ContextJarRepository.java
===================================================================
--- trunk/java/org/apache/catalina/core/ContextJarRepository.java
(rev 0)
+++ trunk/java/org/apache/catalina/core/ContextJarRepository.java 2009-04-24 19:33:12 UTC
(rev 1028)
@@ -0,0 +1,435 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ *
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright 1999-2009 The Apache Software Foundation
+ *
+ * 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.core;
+
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.jar.JarFile;
+
+import javax.naming.Binding;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.servlet.ServletContext;
+
+import org.apache.catalina.Contained;
+import org.apache.catalina.Container;
+import org.apache.catalina.Context;
+import org.apache.catalina.Globals;
+import org.apache.catalina.JarRepository;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.util.IOTools;
+import org.apache.catalina.util.LifecycleSupport;
+import org.apache.catalina.util.StringManager;
+import org.apache.naming.resources.Resource;
+import org.jboss.logging.Logger;
+
+
+/**
+ * Context specific implementation for a JAR repository, which will manage
+ * JARs from /WEB-INF/lib in an efficient way.
+ *
+ * @author Remy Maucherat
+ */
+public class ContextJarRepository
+ implements JarRepository, Contained, Lifecycle {
+
+ private static Logger log = Logger.getLogger(ContextJarRepository.class);
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Construct a new ContextJarRepository instance with no associated Container.
+ */
+ public ContextJarRepository() {
+
+ this(null);
+
+ }
+
+
+ /**
+ * Construct a new ContextJarRepository instance that is associated with the
+ * specified Container.
+ *
+ * @param container The container we should be associated with
+ */
+ public ContextJarRepository(Container container) {
+
+ super();
+ setContainer(container);
+
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The Container with which this Pipeline is associated.
+ */
+ protected Container container = null;
+
+
+ /**
+ * Descriptive information about this implementation.
+ */
+ protected String info =
"org.apache.catalina.core.ContextJarRepository/1.0";
+
+
+ /**
+ * The lifecycle event support for this component.
+ */
+ protected LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+
+ /**
+ * The string manager for this package.
+ */
+ protected static StringManager sm =
+ StringManager.getManager(Constants.Package);
+
+
+ /**
+ * Has this component been started yet?
+ */
+ protected boolean started = false;
+
+
+ /**
+ * Library path.
+ */
+ protected String libPath = "/WEB-INF/lib";
+
+
+ /**
+ * Map for the JarFile instances.
+ */
+ protected Map<String, JarFile> jarFiles = new HashMap<String,
JarFile>();
+
+
+ /**
+ * Array of the JarFiles, as convenience.
+ */
+ protected JarFile[] jarFilesArray = new JarFile[0];
+
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Return descriptive information about this implementation class.
+ */
+ public String getInfo() {
+
+ return (this.info);
+
+ }
+
+
+ // ------------------------------------------------------ Contained Methods
+
+
+ /**
+ * Return the Container with which this Pipeline is associated.
+ */
+ public Container getContainer() {
+
+ return (this.container);
+
+ }
+
+
+ /**
+ * Set the Container with which this Pipeline is associated.
+ *
+ * @param container The new associated container
+ */
+ public void setContainer(Container container) {
+
+ this.container = container;
+
+ }
+
+
+ // ------------------------------------------------------ Lifecycle Methods
+
+
+ /**
+ * Add a lifecycle event listener to this component.
+ *
+ * @param listener The listener to add
+ */
+ public void addLifecycleListener(LifecycleListener listener) {
+
+ lifecycle.addLifecycleListener(listener);
+
+ }
+
+
+ /**
+ * Get the lifecycle listeners associated with this lifecycle. If this
+ * Lifecycle has no listeners registered, a zero-length array is returned.
+ */
+ public LifecycleListener[] findLifecycleListeners() {
+
+ return lifecycle.findLifecycleListeners();
+
+ }
+
+
+ /**
+ * Remove a lifecycle event listener from this component.
+ *
+ * @param listener The listener to remove
+ */
+ public void removeLifecycleListener(LifecycleListener listener) {
+
+ lifecycle.removeLifecycleListener(listener);
+
+ }
+
+ /**
+ * Prepare for active use of the public methods of this Component.
+ *
+ * @exception LifecycleException if this component detects a fatal error
+ * that prevents it from being started
+ */
+ public synchronized void start() throws LifecycleException {
+
+ // Validate and update our current component state
+ if (started) {
+ if(log.isDebugEnabled())
+
log.debug(sm.getString("contextJarRepository.alreadyStarted"));
+ return;
+ }
+
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
+
+ started = true;
+
+ if (!(container instanceof Context))
+ throw new IllegalStateException("");
+ DirContext resources = container.getResources();
+ ServletContext servletContext = ((Context) container).getServletContext();
+ if (servletContext == null)
+ return;
+
+ // Check JARs from Context
+ File workDir =
+ (File) servletContext.getAttribute(Globals.WORK_DIR_ATTR);
+ if (workDir == null) {
+ log.info("No work dir for " + servletContext);
+ }
+
+ NamingEnumeration<Binding> libPathListing = null;
+ // Looking up directory /WEB-INF/lib in the context
+ try {
+ libPathListing = resources.listBindings(libPath);
+ } catch (NamingException e) {
+ // Silent catch: it's valid that no /WEB-INF/lib collection
+ // exists
+ }
+
+ if (libPathListing != null) {
+ boolean copyJars = false;
+ String absoluteLibPath = servletContext.getRealPath(libPath);
+ File destDir = null;
+ if (absoluteLibPath != null) {
+ destDir = new File(absoluteLibPath);
+ } else {
+ copyJars = true;
+ destDir = new File(workDir, libPath);
+ destDir.mkdirs();
+ }
+ while (libPathListing.hasMoreElements()) {
+ Binding binding = libPathListing.nextElement();
+ String filename = libPath + "/" + binding.getName();
+ if (!filename.endsWith(".jar"))
+ continue;
+ // Copy JAR in the work directory, always (the JAR file
+ // would get locked otherwise, which would make it
+ // impossible to update it or remove it at runtime)
+ File destFile = new File(destDir, binding.getName());
+ Object obj = binding.getObject();
+ if (!(obj instanceof Resource))
+ continue;
+ Resource jarResource = (Resource) obj;
+ try {
+ if (copyJars) {
+ InputStream is = null;
+ OutputStream os = null;
+ try {
+ is = jarResource.streamContent();
+ os = new FileOutputStream(destFile);
+ IOTools.flow(is, os);
+ // Don't catch IOE - let the outer try/catch handle it
+ } finally {
+ try {
+ if (is != null) is.close();
+ } catch (IOException e){
+ // Ignore
+ }
+ try {
+ if (os != null) os.close();
+ } catch (IOException e){
+ // Ignore
+ }
+ }
+ }
+ JarFile jarFile = new JarFile(destFile);
+ jarFiles.put(destFile.getAbsolutePath(), jarFile);
+ } catch (IOException ex) {
+ // Catch the exception if there is an empty jar file,
+ // or if the JAR cannot be copied to temp
+ // FIXME: throw an error, as webapp will not run
+ }
+ }
+
+ }
+ jarFilesArray = jarFiles.values().toArray(jarFilesArray);
+
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(START_EVENT, null);
+
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
+
+ }
+
+
+ /**
+ * Gracefully shut down active use of the public methods of this Component.
+ *
+ * @exception LifecycleException if this component detects a fatal error
+ * that needs to be reported
+ */
+ public synchronized void stop() throws LifecycleException {
+
+ // Validate and update our current component state
+ if (!started) {
+ if(log.isDebugEnabled())
+ log.debug(sm.getString("standardPipeline.notStarted"));
+ return;
+ }
+
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
+
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(STOP_EVENT, null);
+ started = false;
+
+ // Close JARs and delete temporary copies if needed
+ try {
+ for (int i = 0; i < jarFilesArray.length; i++) {
+ jarFilesArray[i].close();
+ }
+ Iterator<String> jarFilesNames = jarFiles.keySet().iterator();
+ while (jarFilesNames.hasNext()) {
+ File jarFile = new File(jarFilesNames.next());
+ jarFile.delete();
+ }
+ } catch (IOException ex) {
+ // Catch the exception if there is an empty jar file,
+ // or if the JAR cannot be copied to temp
+ // FIXME: throw an error, as webapp will not run
+ }
+ jarFiles.clear();
+ jarFilesArray = new JarFile[0];
+
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
+ }
+
+
+ // -------------------------------------------------- JarRepository Methods
+
+
+ /**
+ * Execute a periodic task, such as reloading, etc. This method will be
+ * invoked inside the classloading context of this container. Unexpected
+ * throwables will be caught and logged.
+ */
+ public void backgroundProcess() {
+
+ }
+
+
+ /**
+ * Get a JarFile with the specified name.
+ *
+ * @param name
+ * @return
+ */
+ public JarFile getJar(String name) {
+ return jarFiles.get(name);
+ }
+
+
+ /**
+ * Find all JarFile managed by the JARRepository.
+ *
+ * @return All JarFile
+ */
+ public JarFile[] findJars() {
+ return jarFilesArray;
+ }
+
+
+}
Modified: trunk/java/org/apache/catalina/core/LocalStrings.properties
===================================================================
--- trunk/java/org/apache/catalina/core/LocalStrings.properties 2009-04-24 15:11:36 UTC
(rev 1027)
+++ trunk/java/org/apache/catalina/core/LocalStrings.properties 2009-04-24 19:33:12 UTC
(rev 1028)
@@ -51,6 +51,7 @@
containerBase.backgroundProcess.manager=Exception processing manager {0} background
process
containerBase.backgroundProcess.realm=Exception processing realm {0} background process
containerBase.backgroundProcess.valve=Exception processing valve {0} background process
+containerBase.backgroundProcess.jarRepository=Exception processing jar repository {0}
background process
fastEngineMapper.alreadyStarted=FastEngineMapper {0} has already been started
fastEngineMapper.notStarted=FastEngineMapper {0} has not yet been started
filterChain.filter=Filter execution threw an exception
Modified: trunk/java/org/apache/catalina/deploy/WebOrdering.java
===================================================================
--- trunk/java/org/apache/catalina/deploy/WebOrdering.java 2009-04-24 15:11:36 UTC (rev
1027)
+++ trunk/java/org/apache/catalina/deploy/WebOrdering.java 2009-04-24 19:33:12 UTC (rev
1028)
@@ -28,6 +28,7 @@
public class WebOrdering implements Serializable {
+ protected String jar = null;
protected String name = null;
protected List<String> after = new ArrayList<String>();
protected List<String> before = new ArrayList<String>();
@@ -54,5 +55,11 @@
public void addBefore(String name) {
before.add(name);
}
+ public String getJar() {
+ return jar;
+ }
+ public void setJar(String jar) {
+ this.jar = jar;
+ }
}
Modified: trunk/java/org/apache/catalina/startup/ContextConfig.java
===================================================================
--- trunk/java/org/apache/catalina/startup/ContextConfig.java 2009-04-24 15:11:36 UTC (rev
1027)
+++ trunk/java/org/apache/catalina/startup/ContextConfig.java 2009-04-24 19:33:12 UTC (rev
1028)
@@ -53,12 +53,14 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
@@ -83,6 +85,7 @@
import org.apache.catalina.Valve;
import org.apache.catalina.Wrapper;
import org.apache.catalina.core.ContainerBase;
+import org.apache.catalina.core.ContextJarRepository;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
@@ -91,6 +94,8 @@
import org.apache.catalina.deploy.FilterMap;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.deploy.SecurityConstraint;
+import org.apache.catalina.deploy.WebAbsoluteOrdering;
+import org.apache.catalina.deploy.WebOrdering;
import org.apache.catalina.util.StringManager;
import org.apache.tomcat.util.digester.Digester;
import org.apache.tomcat.util.digester.RuleSet;
@@ -955,11 +960,131 @@
* Process additional descriptors: TLDs, web fragments, and map overlays.
*/
protected void applicationExtraDescriptorsConfig() {
- // FIXME: Read order from web.xml and fragments (note: if no fragments, skip)
+ // Read order from web.xml and fragments (note: if no fragments, skip)
+ WebAbsoluteOrdering absoluteOrdering = null;
+ List<WebOrdering> orderings = new ArrayList<WebOrdering>();
Iterator<String> jarsWithWebFragments = scanner.getWebFragments();
+
+ /*
+ String altDDName = null;
+
+ // Open the application web.xml file, if it exists
+ InputStream stream = null;
+ ServletContext servletContext = context.getServletContext();
+ if (servletContext != null) {
+ altDDName = (String)servletContext.getAttribute(
+ Globals.ALT_DD_ATTR);
+ if (altDDName != null) {
+ try {
+ stream = new FileInputStream(altDDName);
+ } catch (FileNotFoundException e) {
+ log.error(sm.getString("contextConfig.altDDNotFound",
+ altDDName));
+ }
+ }
+ else {
+ stream = servletContext.getResourceAsStream
+ (Constants.ApplicationWebXml);
+ }
+ }
+ if (stream == null) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("contextConfig.applicationMissing")
+ " " + context);
+ }
+ return;
+ }
+
+ URL url = null;
+
+ // Process the application web.xml file
+ synchronized (orderingDigester) {
+ try {
+ if (altDDName != null) {
+ url = new File(altDDName).toURI().toURL();
+ } else {
+ url = servletContext.getResource(Constants.ApplicationWebXml);
+ }
+ if (url != null) {
+ InputSource is = new InputSource(url.toExternalForm());
+ is.setByteStream(stream);
+ orderingDigester.parse(is);
+ absoluteOrdering = (WebAbsoluteOrdering)
orderingDigester.peek();
+ }
+ } catch (SAXParseException e) {
+ log.error(sm.getString("contextConfig.applicationParse",
url.toExternalForm()), e);
+
log.error(sm.getString("contextConfig.applicationPosition",
+ "" + e.getLineNumber(),
+ "" + e.getColumnNumber()));
+ ok = false;
+ } catch (Exception e) {
+ log.error(sm.getString("contextConfig.applicationParse",
url.toExternalForm()), e);
+ ok = false;
+ } finally {
+ orderingDigester.reset();
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+
log.error(sm.getString("contextConfig.applicationClose"), e);
+ }
+ }
+ }
+ */
+
+ // Process the web fragments
+ // FIXME: Do only if no absolute ordering
+ while (jarsWithWebFragments.hasNext()) {
+ String jar = jarsWithWebFragments.next();
+ JarFile jarFile = null;
+ InputStream is = null;
+ try {
+ jarFile = new JarFile(jar);
+ ZipEntry entry = jarFile.getEntry(Globals.WEB_FRAGMENT_PATH);
+ if (entry != null) {
+ is = jarFile.getInputStream(entry);
+ InputSource input = new InputSource((new
File(jar)).toURI().toURL().toExternalForm());
+ input.setByteStream(is);
+ synchronized (fragmentOrderingDigester) {
+ try {
+ fragmentOrderingDigester.parse(input);
+ WebOrdering ordering = (WebOrdering)
fragmentOrderingDigester.peek();
+ if (ordering != null) {
+ ordering.setJar(jar);
+ orderings.add(ordering);
+ }
+ } finally {
+ fragmentOrderingDigester.reset();
+ }
+ }
+ }
+ } catch (Exception e) {
+ // FIXME: error message
+ log.error(sm.getString("contextConfig.applicationParse", jar),
e);
+ ok = false;
+ } finally {
+ try {
+ if (is != null) {
+ is.close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ try {
+ if (jarFile != null) {
+ jarFile.close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+
+ // FIXME: Generate final web fragments order
+ if (absoluteOrdering != null || (orderings.size() > 0)) {
+
+ }
- // FIXME: Generate final web descriptor order
-
// FIXME: Add overlays
scanner.getOverlays();
}
@@ -984,6 +1109,10 @@
if (context.getConfigFile() != null)
processContextConfig(new File(context.getConfigFile()), null);
+ if (context.getJarRepository() == null) {
+ context.setJarRepository(new ContextJarRepository());
+ }
+
}
@@ -1306,8 +1435,8 @@
defaultWebConfig();
scanner.scan(context);
// FIXME: look where to place it according to the merging rules
+ applicationWebConfig();
applicationExtraDescriptorsConfig();
- applicationWebConfig();
if (!context.getIgnoreAnnotations()) {
applicationAnnotationsConfig();
}