Consider the case where JSF is installed in the common classloader of
Tomcat, or SJSAS.
With this configuration, the ConfigureListener will be invoked for every
web application
whether or not it uses JSF.
This modification to ConfigureListener will process the web.xml of the
current web application
scanning for the presence of javax.faces.webapp.FacesServlet. If found,
perform the normal
application processing, otherwise return.
I've validated that this is working using Tomcat and deploying some
applications that
have a FacesServlet entry and others that do not.
SECTION: Modified Files
----------------------------
M src/com/sun/faces/config/ConfigureListener.java
SECTION: Diffs
----------------------------
Index: src/com/sun/faces/config/ConfigureListener.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/config/ConfigureListener.java,v
retrieving revision 1.28
diff -u -r1.28 ConfigureListener.java
--- src/com/sun/faces/config/ConfigureListener.java 13 Jan 2005
19:57:49 -0000 1.28
+++ src/com/sun/faces/config/ConfigureListener.java 17 Feb 2005
20:40:25 -0000
@@ -8,28 +8,22 @@
package com.sun.faces.config;
-import com.sun.faces.RIConstants;
-import com.sun.faces.application.ApplicationAssociate;
-import com.sun.faces.application.ConfigNavigationCase;
-import com.sun.faces.config.beans.ApplicationBean;
-import com.sun.faces.config.beans.ComponentBean;
-import com.sun.faces.config.beans.ConverterBean;
-import com.sun.faces.config.beans.FacesConfigBean;
-import com.sun.faces.config.beans.FactoryBean;
-import com.sun.faces.config.beans.LifecycleBean;
-import com.sun.faces.config.beans.LocaleConfigBean;
-import com.sun.faces.config.beans.ManagedBeanBean;
-import com.sun.faces.config.beans.NavigationCaseBean;
-import com.sun.faces.config.beans.NavigationRuleBean;
-import com.sun.faces.config.beans.RenderKitBean;
-import com.sun.faces.config.beans.RendererBean;
-import com.sun.faces.config.beans.ValidatorBean;
-import com.sun.faces.config.rules.FacesConfigRuleSet;
-import com.sun.faces.util.Util;
-import org.apache.commons.digester.Digester;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.xml.sax.InputSource;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
import javax.faces.FacesException;
import javax.faces.FactoryFinder;
@@ -52,22 +46,35 @@
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.parsers.SAXParser;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
+import com.sun.faces.RIConstants;
+import com.sun.faces.application.ApplicationAssociate;
+import com.sun.faces.application.ConfigNavigationCase;
+import com.sun.faces.config.beans.ApplicationBean;
+import com.sun.faces.config.beans.ComponentBean;
+import com.sun.faces.config.beans.ConverterBean;
+import com.sun.faces.config.beans.FacesConfigBean;
+import com.sun.faces.config.beans.FactoryBean;
+import com.sun.faces.config.beans.LifecycleBean;
+import com.sun.faces.config.beans.LocaleConfigBean;
+import com.sun.faces.config.beans.ManagedBeanBean;
+import com.sun.faces.config.beans.NavigationCaseBean;
+import com.sun.faces.config.beans.NavigationRuleBean;
+import com.sun.faces.config.beans.RenderKitBean;
+import com.sun.faces.config.beans.RendererBean;
+import com.sun.faces.config.beans.ValidatorBean;
+import com.sun.faces.config.rules.FacesConfigRuleSet;
+import com.sun.faces.util.Util;
+
+import org.apache.commons.digester.Digester;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.DefaultHandler;
/**
@@ -217,10 +224,30 @@
}
public void contextInitialized(ServletContextEvent sce) {
+
+ ServletContext context = sce.getServletContext();
+
+ // Check to see if the FacesServlet is present in the
+ // web.xml. If it is, perform faces configuration as normal,
+ // otherwise, simply return.
+ WebXmlProcessor processor = new WebXmlProcessor(context);
+ if (!processor.isFacesServletPresent()) {
+ if (log.isDebugEnabled()) {
+ log.debug("No FacesServlet found in deployment
descriptor -" +
+ " bypassing configuration.");
+ }
+ return;
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("FacesServlet found in deployment descriptor -" +
+ " processing configuration.");
+ }
+
// Prepare local variables we will need
Digester digester = null;
FacesConfigBean fcb = new FacesConfigBean();
- ServletContext context = sce.getServletContext();
+
// store the servletContext instance in Thread local Storage.
// This enables our Application's ApplicationAssociate to locate
@@ -1471,5 +1498,109 @@
} // END ApplicationMap
-}
+ private static class WebXmlProcessor {
+
+ private static final String WEB_XML_PATH = "/WEB-INF/web.xml";
+
+ private boolean facesServletFound;
+
+ WebXmlProcessor(ServletContext context) {
+ scanForFacesServlet(context);
+ }
+
+ boolean isFacesServletPresent() {
+ return facesServletFound;
+ }
+
+ private void scanForFacesServlet(ServletContext context) {
+ SAXParserFactory factory = getConfiguredFactory();
+ try {
+ SAXParser parser = factory.newSAXParser();
+ parser.parse(context.getResourceAsStream(WEB_XML_PATH),
+ new WebXmlHandler());
+ } catch (Exception e) {
+ // This probably won't happen since the container would
+ // catch it before we would, but, if we catch an exception
+ // processing the web.xml, set facesServletFound to true to
+ // default to our previous behavior of processing the faces
+ // configuration.
+ if (log.isWarnEnabled()) {
+ log.warn("Unable to process deployment descriptor
for" +
+ " context '" + context.getServletContextName()
+ '\'');
+ }
+ facesServletFound = true;
+ }
+ }
+
+ /**
+ * <p>Return a <code>SAXParserFactory</code> instance that is
+ * non-validating and is namespace aware.</p>
+ * @return configured <code>SAXParserFactory</code>
+ */
+ private SAXParserFactory getConfiguredFactory() {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setValidating(false);
+ factory.setNamespaceAware(true);
+ return factory;
+ }
+
+ private class WebXmlHandler extends DefaultHandler {
+
+ private final String SERVLET_CLASS = "servlet-class";
+ private final String FACES_SERVLET =
+ "javax.faces.webapp.FacesServlet";
+
+ private boolean servletClassFound;
+ private StringBuffer content;
+
+ public InputSource resolveEntity(String publicId, String
systemId)
+ throws SAXException {
+
+ return new InputSource(new StringReader(""));
+
+ } // END resolveEntity
+
+
+ public void startElement(String uri, String localName,
+ String qName, Attributes attributes)
+ throws SAXException {
+
+ if (!facesServletFound) {
+ if (SERVLET_CLASS.equals(localName)) {
+ servletClassFound = true;
+ content = new StringBuffer();
+ } else {
+ servletClassFound = false;
+ }
+ }
+
+ } // END startElement
+
+
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {
+
+ if (servletClassFound && !facesServletFound) {
+ content.append(ch, start, length);
+ }
+
+ } // END characters
+
+
+ public void endElement(String uri, String localName, String
qName)
+ throws SAXException {
+
+ if (servletClassFound && !facesServletFound) {
+ if (FACES_SERVLET.equals(content.toString().trim())) {
+ facesServletFound = true;
+ }
+ }
+
+ } // END endElement
+
+ } // END WebXmlHandler
+
+ } // END WebXmlProcessor
+
+}