diff --git a/hotfix/plugins/org.glassfish.com.sun.faces_2.1.18.v201304210537-virgo-1.jar b/hotfix/plugins/org.glassfish.com.sun.faces_2.1.18.v201304210537-virgo-2.jar
old mode 100755
new mode 100644
similarity index 76%
rename from hotfix/plugins/org.glassfish.com.sun.faces_2.1.18.v201304210537-virgo-1.jar
rename to hotfix/plugins/org.glassfish.com.sun.faces_2.1.18.v201304210537-virgo-2.jar
index 6e8922e..a47d741
--- a/hotfix/plugins/org.glassfish.com.sun.faces_2.1.18.v201304210537-virgo-1.jar
+++ b/hotfix/plugins/org.glassfish.com.sun.faces_2.1.18.v201304210537-virgo-2.jar
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$1.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$1.class
new file mode 100644
index 0000000..3eb0e03
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$1.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$AnnotationScanTask.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$AnnotationScanTask.class
new file mode 100644
index 0000000..b7d47eb
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$AnnotationScanTask.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$ParseTask.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$ParseTask.class
new file mode 100644
index 0000000..ba4031c
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$ParseTask.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$ProvideMetadataToAnnotationScanTask.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$ProvideMetadataToAnnotationScanTask.class
new file mode 100644
index 0000000..2f83f9e
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$ProvideMetadataToAnnotationScanTask.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$URITask.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$URITask.class
new file mode 100644
index 0000000..4ce5d47
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager$URITask.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager.class
new file mode 100644
index 0000000..5903a13
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager.java b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager.java
new file mode 100644
index 0000000..1f0e966
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigManager.java
@@ -0,0 +1,1209 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License").  You
+ * may not use this file except in compliance with the License.  You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt.  See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license."  If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above.  However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.faces.config;
+
+import com.sun.faces.RIConstants;
+import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.ValidateFacesConfigFiles;
+import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.DisableFaceletJSFViewHandler;
+import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableThreading;
+import com.sun.faces.spi.ConfigurationResourceProvider;
+import com.sun.faces.spi.ConfigurationResourceProviderFactory;
+import com.sun.faces.spi.AnnotationProvider;
+import com.sun.faces.spi.AnnotationProviderFactory;
+import com.sun.faces.spi.HighAvailabilityEnabler;
+import static com.sun.faces.spi.ConfigurationResourceProviderFactory.ProviderType.*;
+import com.sun.faces.config.configprovider.MetaInfFacesConfigResourceProvider;
+import com.sun.faces.config.configprovider.MojarraFacesConfigResourceProvider;
+import com.sun.faces.config.configprovider.WebFacesConfigResourceProvider;
+import com.sun.faces.config.configprovider.MetaInfFaceletTaglibraryConfigProvider;
+import com.sun.faces.config.configprovider.WebFaceletTaglibResourceProvider;
+import com.sun.faces.config.processor.ApplicationConfigProcessor;
+import com.sun.faces.config.processor.BehaviorConfigProcessor;
+import com.sun.faces.config.processor.ComponentConfigProcessor;
+import com.sun.faces.config.processor.ConfigProcessor;
+import com.sun.faces.config.processor.ConverterConfigProcessor;
+import com.sun.faces.config.processor.FactoryConfigProcessor;
+import com.sun.faces.config.processor.LifecycleConfigProcessor;
+import com.sun.faces.config.processor.ManagedBeanConfigProcessor;
+import com.sun.faces.config.processor.NavigationConfigProcessor;
+import com.sun.faces.config.processor.RenderKitConfigProcessor;
+import com.sun.faces.config.processor.ValidatorConfigProcessor;
+import com.sun.faces.config.processor.FaceletTaglibConfigProcessor;
+import com.sun.faces.config.processor.FacesConfigExtensionProcessor;
+import com.sun.faces.spi.InjectionProvider;
+import com.sun.faces.spi.InjectionProviderFactory;
+import com.sun.faces.util.FacesLogger;
+import com.sun.faces.util.Timer;
+import com.sun.faces.util.Util;
+import org.xml.sax.InputSource;
+
+import javax.faces.FacesException;
+import javax.faces.FactoryFinder;
+import javax.faces.event.PostConstructApplicationEvent;
+import javax.faces.application.Application;
+import javax.faces.context.FacesContext;
+import javax.servlet.ServletContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamSource;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.Iterator;
+
+import org.w3c.dom.*;
+import org.xml.sax.SAXParseException;
+
+/**
+ * <p>
+ *  This class manages the initialization of each web application that uses
+ *  JSF.
+ * </p>
+ */
+public class ConfigManager {
+
+    private static final String SERVLET_CONTEXT_INITIALISED = "com.sap.core.context.initialized";
+
+	private static final Logger LOGGER = FacesLogger.CONFIG.getLogger();
+
+    private static final Pattern JAR_PATTERN = Pattern.compile("(.*/(\\S*\\.jar)).*(/faces-config.xml|/*.\\.faces-config.xml)");
+
+    /**
+     * <p>
+     * A List of resource providers that search for faces-config documents.
+     * By default, this contains a provider for the Mojarra, and two other
+     * providers to satisfy the requirements of the specification.
+     * </p>
+     */
+    private static final List<ConfigurationResourceProvider> FACES_CONFIG_RESOURCE_PROVIDERS;
+
+    /**
+     * <p>
+     * A List of resource providers that search for faces-config documents.
+     * By default, this contains a provider for the Mojarra, and one other
+     * providers to satisfy the requirements of the specification.
+     * </p>
+     */
+    private static final List<ConfigurationResourceProvider> FACELET_TAGLIBRARY_RESOURCE_PROVIDERS;
+
+    /**
+     * <p>
+     *  The <code>ConfigManager</code> will multithread the calls to the
+     *  <code>ConfigurationResourceProvider</code>s as well as any calls
+     *  to parse a resources into a DOM.  By default, we'll use only 5 threads
+     *  per web application.
+     * </p>
+     */
+    private static final int NUMBER_OF_TASK_THREADS = 5;
+
+    /**
+     * <p>
+     *  There is only once instance of <code>ConfigManager</code>.
+     * <p>
+     */
+    private static final ConfigManager CONFIG_MANAGER = new ConfigManager();
+
+
+    /**
+     * The application-scoped key under which the Future responsible for annotation
+     * scanning is associated with.
+     */
+    private static final String ANNOTATIONS_SCAN_TASK_KEY =
+          ConfigManager.class.getName() + "_ANNOTATION_SCAN_TASK";
+
+
+    /**
+     * The initialization time FacesContext scoped key under which the
+     * InjectionProvider is stored.
+     */
+    public static final String INJECTION_PROVIDER_KEY =
+          ConfigManager.class.getName() + "_INJECTION_PROVIDER_TASK";
+
+
+    /**
+     * Name of the attribute added by ParseTask to indicate a
+     * {@link Document} instance as a representation of
+     * <code>/WEB-INF/faces-config.xml</code>.
+     */
+    public static final String WEB_INF_MARKER = "com.sun.faces.webinf";
+
+
+    /**
+     * <p>
+     *   Contains each <code>ServletContext</code> that we've initialized.
+     *   The <code>ServletContext</code> will be removed when the application
+     *   is destroyed.
+     * </p>
+     */
+    @SuppressWarnings({"CollectionWithoutInitialCapacity"})
+    private List<ServletContext> initializedContexts =
+         new CopyOnWriteArrayList<ServletContext>();
+
+    /**
+     * <p>
+     *  The chain of {@link ConfigProcessor} instances to processing of
+     *  faces-config documents.
+     * </p>
+     */
+    private static final ConfigProcessor FACES_CONFIG_PROCESSOR_CHAIN;
+
+
+    /**
+     * <p>
+     *  The chain of {@link ConfigProcessor} instances to processing of
+     *  facelet-taglib documents.
+     * </p>
+     */
+    private static final ConfigProcessor FACELET_TAGLIB_CONFIG_PROCESSOR_CHAIN;
+
+    /**
+     * Stylesheet to convert 1.0 and 1.1 based faces-config documents
+     * to our private 1.1 schema for validation.
+     */
+    private static final String FACES_TO_1_1_PRIVATE_XSL =
+          "/com/sun/faces/jsf1_0-1_1toSchema.xsl";
+
+    /**
+     * Stylesheet to convert 1.0 facelet-taglib documents
+     * from 1.0 to 2.0 for schema validation purposes.
+     */
+    private static final String FACELETS_TO_2_0_XSL =
+          "/com/sun/faces/facelets1_0-2_0toSchema.xsl";
+
+    private static final String FACES_CONFIG_1_X_DEFAULT_NS =
+          "http://java.sun.com/JSF/Configuration";
+
+    private static final String FACELETS_1_0_DEFAULT_NS =
+          "http://java.sun.com/JSF/Facelet";
+
+
+    static {
+
+        // initialize the resource providers for faces-config documents
+        List<ConfigurationResourceProvider> facesConfigProviders =
+          new ArrayList<ConfigurationResourceProvider>(3);
+        facesConfigProviders.add(new MojarraFacesConfigResourceProvider());
+        facesConfigProviders.add(new MetaInfFacesConfigResourceProvider());
+        facesConfigProviders.add(new WebFacesConfigResourceProvider());
+        FACES_CONFIG_RESOURCE_PROVIDERS = Collections.unmodifiableList(facesConfigProviders);
+
+        // initialize the resource providers for facelet-taglib documents
+        List<ConfigurationResourceProvider> faceletTaglibProviders =
+              new ArrayList<ConfigurationResourceProvider>(3);
+        faceletTaglibProviders.add(new MetaInfFaceletTaglibraryConfigProvider());
+        faceletTaglibProviders.add(new WebFaceletTaglibResourceProvider());
+        FACELET_TAGLIBRARY_RESOURCE_PROVIDERS = Collections.unmodifiableList(faceletTaglibProviders);
+
+        // initialize the config processors for faces-config documents
+        ConfigProcessor[] configProcessors = {
+             new FactoryConfigProcessor(),
+             new LifecycleConfigProcessor(),
+             new ApplicationConfigProcessor(),
+             new ComponentConfigProcessor(),
+             new ConverterConfigProcessor(),
+             new ValidatorConfigProcessor(),
+             new ManagedBeanConfigProcessor(),
+             new RenderKitConfigProcessor(),
+             new NavigationConfigProcessor(),
+             new BehaviorConfigProcessor(),
+             new FacesConfigExtensionProcessor()
+        };
+        for (int i = 0; i < configProcessors.length; i++) {
+            ConfigProcessor p = configProcessors[i];
+            if ((i + 1) < configProcessors.length) {
+                p.setNext(configProcessors[i + 1]);
+            }
+        }
+        FACES_CONFIG_PROCESSOR_CHAIN = configProcessors[0];
+
+        // initialize the config processor for facelet-taglib documents
+        FACELET_TAGLIB_CONFIG_PROCESSOR_CHAIN = new FaceletTaglibConfigProcessor();
+
+    }
+
+
+    // ---------------------------------------------------------- Public Methods
+
+
+    /**
+     * @return a <code>ConfigManager</code> instance
+     */
+    public static ConfigManager getInstance() {
+
+        return CONFIG_MANAGER;
+
+    }
+
+
+    /**
+     * <p>
+     *   This method bootstraps JSF based on the parsed configuration resources.
+     * </p>
+     *
+     * @param sc the <code>ServletContext</code> for the application that
+     *  requires initialization
+     */
+    public void initialize(ServletContext sc) {
+
+        if (!hasBeenInitialized(sc)) {
+            initializedContexts.add(sc);
+            sc.setAttribute(SERVLET_CONTEXT_INITIALISED, true);
+            ExecutorService executor = null;
+            try {
+                WebConfiguration webConfig = WebConfiguration.getInstance(sc);
+                boolean validating = webConfig.isOptionEnabled(ValidateFacesConfigFiles);
+                if (useThreads(sc)) {
+                    executor = createExecutorService();
+                }
+
+                DocumentInfo[] facesDocuments =
+                      getConfigDocuments(sc,
+                                         getFacesConfigResourceProviders(),
+                                         executor,
+                                         validating);
+
+                FacesConfigInfo webInfFacesConfigInfo =
+                      new FacesConfigInfo(facesDocuments[facesDocuments.length - 1]);
+
+                facesDocuments = sortDocuments(facesDocuments, webInfFacesConfigInfo);
+                InitFacesContext context = (InitFacesContext) FacesContext.getCurrentInstance();
+
+                InjectionProvider containerConnector =
+                        InjectionProviderFactory.createInstance(context.getExternalContext());
+                context.getAttributes().put(INJECTION_PROVIDER_KEY, containerConnector);
+
+                boolean isFaceletsDisabled =
+                      isFaceletsDisabled(webConfig, webInfFacesConfigInfo);
+                if (!webInfFacesConfigInfo.isWebInfFacesConfig() || !webInfFacesConfigInfo.isMetadataComplete()) {
+                    // execute the Task responsible for finding annotation classes
+                    ProvideMetadataToAnnotationScanTask taskMetadata = new ProvideMetadataToAnnotationScanTask(facesDocuments, containerConnector);
+                    Future<Map<Class<? extends Annotation>,Set<Class<?>>>> annotationScan;
+                    if (executor != null) {
+                        annotationScan = executor.submit(new AnnotationScanTask(sc, context, taskMetadata));
+                        pushTaskToContext(sc, annotationScan);
+                    } else {
+                        annotationScan =
+                              new FutureTask<Map<Class<? extends Annotation>,Set<Class<?>>>>(new AnnotationScanTask(sc, context, taskMetadata));
+                        ((FutureTask) annotationScan).run();
+                    }
+                    pushTaskToContext(sc, annotationScan);
+                }
+
+                //see if the app is running in a HA enabled env               
+                if (containerConnector instanceof HighAvailabilityEnabler) {                   
+                    ((HighAvailabilityEnabler)containerConnector).enableHighAvailability(sc);
+                }
+                // process the ordered documents
+                FACES_CONFIG_PROCESSOR_CHAIN.process(sc, facesDocuments);
+                if (!isFaceletsDisabled) {
+                    FACELET_TAGLIB_CONFIG_PROCESSOR_CHAIN.process(
+                          sc, getConfigDocuments(sc,
+                                             getFaceletConfigResourceProviders(),
+                                             executor,
+                                             validating));
+                }
+
+                publishPostConfigEvent();
+            } catch (Exception e) {
+                // clear out any configured factories
+                releaseFactories();
+                Throwable t = e;
+                if (!(e instanceof ConfigurationException)) {
+                    t = new ConfigurationException("CONFIGURATION FAILED! " + t.getMessage(), t);
+                }
+                throw (ConfigurationException)t;
+            } finally {
+                if (executor != null) {
+                    executor.shutdown();
+                }
+                sc.removeAttribute(ANNOTATIONS_SCAN_TASK_KEY);
+            }
+        }
+
+    }
+
+
+
+
+    /**
+     * <p>
+     *   This method will remove any information about the application.
+     * </p>
+     * @param sc the <code>ServletContext</code> for the application that
+     *  needs to be removed
+     */
+    public void destroy(ServletContext sc) {
+
+        releaseFactories();
+        initializedContexts.remove(sc);
+        sc.removeAttribute(SERVLET_CONTEXT_INITIALISED);
+
+    }
+
+
+    /**
+     * @param sc the <code>ServletContext</code> for the application in question
+     * @return <code>true</code> if this application has already been initialized,
+     *  otherwise returns </code>fase</code>
+     */
+    public boolean hasBeenInitialized(ServletContext sc) {
+        if (sc.getAttribute(SERVLET_CONTEXT_INITIALISED) == null) {
+            return  initializedContexts.contains(sc);
+        } else {
+            sc.removeAttribute(SERVLET_CONTEXT_INITIALISED);
+            return true;
+        }
+    }
+
+
+    /**
+     * @return the results of the annotation scan task
+     */
+    public static Map<Class<? extends Annotation>,Set<Class<?>>> getAnnotatedClasses(FacesContext ctx) {
+
+        Map<String, Object> appMap =
+              ctx.getExternalContext().getApplicationMap();
+        //noinspection unchecked
+        Future<Map<Class<? extends Annotation>,Set<Class<?>>>> scanTask =
+              (Future<Map<Class<? extends Annotation>,Set<Class<?>>>>) appMap.get(ANNOTATIONS_SCAN_TASK_KEY);
+        try {
+            return ((scanTask != null)
+                    ? scanTask.get()
+                    : Collections.<Class<? extends Annotation>,Set<Class<?>>>emptyMap());
+        } catch (Exception e) {
+            throw new FacesException(e);
+        }
+
+    }
+
+
+    // --------------------------------------------------------- Private Methods
+
+
+    private static boolean useThreads(ServletContext ctx) {
+
+        WebConfiguration config = WebConfiguration.getInstance(ctx);
+        return config.isOptionEnabled(EnableThreading);
+
+    }
+
+
+    private List<ConfigurationResourceProvider> getFacesConfigResourceProviders() {
+
+        return getConfigurationResourceProviders(FACES_CONFIG_RESOURCE_PROVIDERS,
+                                                 FacesConfig);
+
+    }
+
+
+    private List<ConfigurationResourceProvider> getFaceletConfigResourceProviders() {
+
+        return getConfigurationResourceProviders(FACELET_TAGLIBRARY_RESOURCE_PROVIDERS,
+                                                 FaceletConfig);
+
+    }
+
+
+    private List<ConfigurationResourceProvider> getConfigurationResourceProviders(List<ConfigurationResourceProvider> defaultProviders,
+                                                                                  ConfigurationResourceProviderFactory.ProviderType providerType) {
+
+        ConfigurationResourceProvider[] custom =
+              ConfigurationResourceProviderFactory.createProviders(providerType);
+        if (custom.length == 0) {
+            return defaultProviders;
+        } else {
+            List<ConfigurationResourceProvider> list = new ArrayList<ConfigurationResourceProvider>();
+            list.addAll(defaultProviders);
+            // insert the custom providers after the META-INF providers and
+            // before those that scan /WEB-INF
+            list.addAll((defaultProviders.size() - 1), Arrays.asList(custom));
+            return Collections.unmodifiableList(list);
+        }
+
+    }
+
+
+    /**
+     * <p>
+     * Sort the <code>faces-config</code> documents found on the classpath
+     * and those specified by the <code>javax.faces.CONFIG_FILES</code> context
+     * init parameter.
+     * </p>
+     *
+     * @param facesDocuments an array of <em>all</em> <code>faces-config</code>
+     *  documents
+     * @param webInfFacesConfig FacesConfigInfo representing the WEB-INF/faces-config.xml
+     *  for this app
+     *
+     * @return the sorted documents
+     */
+    private DocumentInfo[] sortDocuments(DocumentInfo[] facesDocuments,
+                                         FacesConfigInfo webInfFacesConfig) {
+
+
+        int len = (webInfFacesConfig.isWebInfFacesConfig()
+                     ? facesDocuments.length - 1
+                     : facesDocuments.length);
+
+        List<String> absoluteOrdering = webInfFacesConfig.getAbsoluteOrdering();
+
+        if (len > 1) {
+            List<DocumentOrderingWrapper> list =
+                  new ArrayList<DocumentOrderingWrapper>();
+            for (int i = 1; i < len; i++) {
+                list.add(new DocumentOrderingWrapper(facesDocuments[i]));
+            }
+            DocumentOrderingWrapper[] ordering =
+                  list.toArray(new DocumentOrderingWrapper[list.size()]);
+            if (absoluteOrdering == null) {
+                DocumentOrderingWrapper.sort(ordering);
+                // sorting complete, now update the appropriate locations within
+                // the original array with the sorted documentation.
+                for (int i = 1; i < len; i++) {
+                    facesDocuments[i] = ordering[i - 1].getDocument();
+                }
+                return facesDocuments;
+            } else {
+                DocumentOrderingWrapper[] result =
+                      DocumentOrderingWrapper.sort(ordering, absoluteOrdering);
+                DocumentInfo[] ret = new DocumentInfo[((webInfFacesConfig.isWebInfFacesConfig()) ? (result.length + 2) : (result.length + 1))];
+                for (int i = 1; i < len; i++) {
+                    ret[i] = result[i - 1].getDocument();
+                }
+                // add the impl specific config file
+                ret[0] = facesDocuments[0];
+                // add the WEB-INF if necessary
+                if (webInfFacesConfig.isWebInfFacesConfig()) {
+                    ret[ret.length - 1] = facesDocuments[facesDocuments.length - 1];
+                }
+                return ret;
+            }
+        }
+
+        return facesDocuments;
+    }
+
+
+    /**
+     * <p>
+     * Utility method to check if JSF 2.0 Facelets should be disabled.
+     * If it's not explicitly disabled by the context init parameter, then
+     * check the version of the WEB-INF/faces-config.xml document.  If the version
+     * is less than 2.0, then override the default value for the context init
+     * parameter so that other parts of the system that use that config option
+     * will know it has been disabled.
+     * </p>
+     *
+     * <p>
+     * NOTE:  Since this method overrides a configuration value, it should
+     * be called before *any* document parsing is performed the configuration
+     * value may be queried by the <code>ConfigParser</code>s.
+     * </p>
+     *
+     * @param webconfig configuration for this application
+     * @param facesConfigInfo object representing WEB-INF/faces-config.xml
+     * @return <code>true</code> if Facelets should be disabled
+     */
+    private boolean isFaceletsDisabled(WebConfiguration webconfig,
+                                       FacesConfigInfo facesConfigInfo) {
+
+        boolean isFaceletsDisabled = webconfig.isOptionEnabled(DisableFaceletJSFViewHandler);
+        if (!isFaceletsDisabled) {
+            // if not explicitly disabled, make a sanity check against
+            // /WEB-INF/faces-config.xml
+            isFaceletsDisabled = !facesConfigInfo.isVersionGreaterOrEqual(2.0);
+            webconfig.overrideContextInitParameter(DisableFaceletJSFViewHandler, isFaceletsDisabled);
+        }
+        return isFaceletsDisabled;
+
+    }
+
+
+    /**
+     * Push the provided <code>Future</code> to the specified <code>ServletContext</code>.
+     */
+    private void pushTaskToContext(ServletContext sc,
+                                   Future<Map<Class<? extends Annotation>,Set<Class<?>>>> scanTask) {
+
+        sc.setAttribute(ANNOTATIONS_SCAN_TASK_KEY, scanTask);
+
+    }
+
+
+    /**
+     * Publishes a {@link javax.faces.event.PostConstructApplicationEvent} event for the current
+     * {@link Application} instance.
+     */
+    private void publishPostConfigEvent() {
+
+        FacesContext ctx = FacesContext.getCurrentInstance();
+        Application app = ctx.getApplication();
+        app.publishEvent(ctx,
+                         PostConstructApplicationEvent.class,
+                         Application.class,
+                         app);
+
+    }
+
+
+    /**
+     * <p>
+     *   Obtains an array of <code>Document</code>s to be processed
+     *   by {@link ConfigManager#FACES_CONFIG_PROCESSOR_CHAIN}.
+     * </p>
+     *
+     * @param sc the <code>ServletContext</code> for the application to be
+     *  processed
+     * @param providers <code>List</code> of <code>ConfigurationResourceProvider</code>
+     *  instances that provide the URL of the documents to parse.
+     * @param executor the <code>ExecutorService</code> used to dispatch parse
+     *  request to
+     * @param validating flag indicating whether or not the documents
+     *  should be validated
+     * @return an array of <code>DocumentInfo</code>s
+     */
+    private static DocumentInfo[] getConfigDocuments(ServletContext sc,
+                                                 List<ConfigurationResourceProvider> providers,
+                                                 ExecutorService executor,
+                                                 boolean validating) {
+
+        List<FutureTask<Collection<URI>>> urlTasks =
+             new ArrayList<FutureTask<Collection<URI>>>(providers.size());
+        for (ConfigurationResourceProvider p : providers) {
+            FutureTask<Collection<URI>> t =
+                 new FutureTask<Collection<URI>>(new URITask(p, sc));
+            urlTasks.add(t);
+            if (executor != null) {
+                executor.execute(t);
+            } else {
+                t.run();
+            }
+        }
+
+        List<FutureTask<DocumentInfo>> docTasks =
+             new ArrayList<FutureTask<DocumentInfo>>(providers.size() << 1);
+
+        for (FutureTask<Collection<URI>> t : urlTasks) {
+            try {
+                Collection<URI> l = t.get();
+                for (URI u : l) {
+                    FutureTask<DocumentInfo> d =
+                         new FutureTask<DocumentInfo>(new ParseTask(validating, u));
+                    docTasks.add(d);
+                    if (executor != null) {
+                        executor.execute(d);
+                    } else {
+                        d.run();
+                    }
+                }
+            } catch (InterruptedException ignored) {
+            } catch (Exception e) {
+                throw new ConfigurationException(e);
+            }
+        }
+
+        List<DocumentInfo> docs = new ArrayList<DocumentInfo>(docTasks.size());
+        for (FutureTask<DocumentInfo> t : docTasks) {
+            try {
+                docs.add(t.get());
+            } catch (ExecutionException e) {
+                throw new ConfigurationException(e);
+            } catch (InterruptedException ignored) { }
+        }
+
+        return docs.toArray(new DocumentInfo[docs.size()]);
+
+    }
+
+
+    /**
+     * Create a new <code>ExecutorService</code> with
+     * {@link #NUMBER_OF_TASK_THREADS} threads.
+     */
+    private static ExecutorService createExecutorService() {
+
+        int tc = Runtime.getRuntime().availableProcessors();
+        if (tc > NUMBER_OF_TASK_THREADS) {
+            tc = NUMBER_OF_TASK_THREADS;
+        }
+        return Executors.newFixedThreadPool(tc);
+
+    }
+
+
+    /**
+     * @param throwable Throwable
+     * @return the root cause of this error
+     */
+    private Throwable unwind(Throwable throwable) {
+
+          Throwable t = null;
+          if (throwable != null) {
+              t =  unwind(throwable.getCause());
+              if (t == null) {
+                  t = throwable;
+              }
+          }
+          return t;
+
+    }
+
+
+    /**
+     * Calls through to {@link javax.faces.FactoryFinder#releaseFactories()}
+     * ignoring any exceptions.
+     */
+    private void releaseFactories() {
+        try {
+            FactoryFinder.releaseFactories();
+        } catch (FacesException ignored) {
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE,
+                           "Exception thrown from FactoryFinder.releaseFactories()",
+                           ignored);
+            }
+        }
+    }
+
+
+    // ----------------------------------------------------------- Inner Classes
+
+    private static final class ProvideMetadataToAnnotationScanTask {
+        DocumentInfo [] documentInfos;
+        InjectionProvider containerConnector;
+        Set<URI> uris = null;
+        Set<String> jarNames = null;
+
+        private ProvideMetadataToAnnotationScanTask(DocumentInfo [] documentInfos,
+                InjectionProvider containerConnector) {
+            this.documentInfos = documentInfos;
+            this.containerConnector = containerConnector;
+        }
+
+        private void initializeIvars() {
+            if (null != uris || null != jarNames) {
+                assert(null != uris && null != jarNames);
+                return;
+            }
+            uris = new HashSet<URI>(documentInfos.length);
+            jarNames = new HashSet<String>(documentInfos.length);
+            for (DocumentInfo docInfo : documentInfos) {
+                URI sourceURI = docInfo.getSourceURI();
+                Matcher m = JAR_PATTERN.matcher(sourceURI.toString());
+                if (m.matches()) {
+                    String jarName = m.group(2);
+                    if (!jarNames.contains(jarName)) {
+                        FacesConfigInfo configInfo = new FacesConfigInfo(docInfo);
+                        if (!configInfo.isMetadataComplete()) {
+                            uris.add(sourceURI);
+                            jarNames.add(jarName);
+                        }
+                    }
+                }
+            }
+        }
+
+        private Set<URI> getAnnotationScanURIs() {
+            initializeIvars();
+
+            return uris;
+
+        }
+
+        private Set<String> getJarNames() {
+            initializeIvars();
+
+            return jarNames;
+        }
+
+        private com.sun.faces.spi.AnnotationScanner getAnnotationScanner() {
+            com.sun.faces.spi.AnnotationScanner result = null;
+            if (this.containerConnector instanceof com.sun.faces.spi.AnnotationScanner) {
+                result = (com.sun.faces.spi.AnnotationScanner) this.containerConnector;
+            }
+            return result;
+        }
+    }
+
+
+    /**
+     * Scans the class files within a web application returning a <code>Set</code>
+     * of classes that have been annotated with a standard Faces annotation.
+     */
+    private static class AnnotationScanTask implements Callable<Map<Class<? extends Annotation>,Set<Class<?>>>> {
+
+        private ServletContext sc;
+        private InitFacesContext facesContext;
+        private AnnotationProvider provider;
+        private ProvideMetadataToAnnotationScanTask metadataGetter;
+
+        // -------------------------------------------------------- Constructors
+
+
+        public AnnotationScanTask(ServletContext sc, InitFacesContext facesContext, ProvideMetadataToAnnotationScanTask metadataGetter) {
+            this.facesContext = facesContext;
+            this.provider = AnnotationProviderFactory.createAnnotationProvider(sc);
+            this.metadataGetter = metadataGetter;
+
+        }
+
+
+        // ----------------------------------------------- Methods from Callable
+
+
+        public Map<Class<? extends Annotation>,Set<Class<?>>> call() throws Exception {
+
+            Timer t = Timer.getInstance();
+            if (t != null) {
+                t.startTiming();
+            }
+
+            // We are executing on a different thread.
+            facesContext.callSetCurrentInstance();
+            Set<URI> scanUris = null;
+            com.sun.faces.spi.AnnotationScanner annotationScanner =
+                    metadataGetter.getAnnotationScanner();
+
+            // This is where we discover what kind of InjectionProvider
+            // we have.
+            if (provider instanceof DelegatingAnnotationProvider &&
+                null != annotationScanner) {
+                // This InjectionProvider is capable of annotation scanning *and*
+                // injection.
+                ((DelegatingAnnotationProvider)provider).setAnnotationScanner(annotationScanner,
+                        metadataGetter.getJarNames());
+                scanUris = Collections.emptySet();
+            } else {
+                // This InjectionProvider is capable of annotation scanning only
+                scanUris = metadataGetter.getAnnotationScanURIs();
+            }
+            //AnnotationScanner scanner = new AnnotationScanner(sc);
+            Map<Class<? extends Annotation>,Set<Class<?>>> annotatedClasses =
+                  provider.getAnnotatedClasses(scanUris);
+
+            if (t != null) {
+                t.stopTiming();
+                t.logResult("Configuration annotation scan complete.");
+            }
+
+            return annotatedClasses;
+
+        }
+
+
+    } // END AnnotationScanTask
+
+
+    /**
+     * <p>
+     *  This <code>Callable</code> will be used by {@link ConfigManager#getConfigDocuments(javax.servlet.ServletContext, java.util.List, java.util.concurrent.ExecutorService, boolean)}.
+     *  It represents a single configuration resource to be parsed into a DOM.
+     * </p>
+     */
+    private static class ParseTask implements Callable<DocumentInfo> {
+        private static final String JAVAEE_SCHEMA_DEFAULT_NS =
+            "http://java.sun.com/xml/ns/javaee";
+        private static final String EMPTY_FACES_CONFIG =
+                "com/sun/faces/empty-faces-config.xml";
+        private URI documentURI;
+        private DocumentBuilderFactory factory;
+        private boolean validating;
+
+        // -------------------------------------------------------- Constructors
+
+
+        /**
+         * <p>
+         *   Constructs a new ParseTask instance
+         * </p>
+         *
+         * @param validating whether or not we're validating
+         * @param documentURI a URL to the configuration resource to be parsed
+         * @throws Exception general error
+         */
+        public ParseTask(boolean validating, URI documentURI)
+        throws Exception {
+
+            this.documentURI = documentURI;
+            this.validating = validating;
+
+        }
+
+
+        // ----------------------------------------------- Methods from Callable
+
+
+        /**
+         * @return the result of the parse operation (a DOM)
+         * @throws Exception if an error occurs during the parsing process
+         */
+        public DocumentInfo call() throws Exception {
+
+            try {
+                Timer timer = Timer.getInstance();
+                if (timer != null) {
+                    timer.startTiming();
+                }
+
+                Document d = getDocument();
+
+                if (timer != null) {
+                    timer.stopTiming();
+                    timer.logResult("Parse " + documentURI.toURL().toExternalForm());
+                }
+
+                return new DocumentInfo(d, documentURI);
+            } catch (Exception e) {
+                throw new ConfigurationException(MessageFormat.format(
+                     "Unable to parse document ''{0}'': {1}",
+                     documentURI.toURL().toExternalForm(),
+                     e.getMessage()), e);
+            }
+        }
+
+
+        // ----------------------------------------------------- Private Methods
+
+
+        /**
+         * @return <code>Document</code> based on <code>documentURI</code>.
+         * @throws Exception if an error occurs during the process of building a
+         *  <code>Document</code>
+         */
+        private Document getDocument() throws Exception {
+
+            Document returnDoc;
+            DocumentBuilder db = getNonValidatingBuilder();
+            URL documentURL = documentURI.toURL();
+            InputSource is = new InputSource(getInputStream(documentURL));
+                is.setSystemId(documentURI.toURL().toExternalForm());
+            Document doc = null;
+
+            try {
+                doc = db.parse(is);
+            } catch (SAXParseException spe) {
+                // [mojarra-1693]
+                // Test if this is a zero length or whitespace only faces-config.xml file.
+                // If so, just make an empty Document
+                InputStream stream = is.getByteStream();
+                stream.close();
+
+                is = new InputSource(getInputStream(documentURL));
+                stream = is.getByteStream();
+                if (streamIsZeroLengthOrEmpty(stream) &&
+                    documentURL.toExternalForm().endsWith("faces-config.xml")) {
+                    ClassLoader loader = this.getClass().getClassLoader();
+                    is = new InputSource(getInputStream(loader.getResource(EMPTY_FACES_CONFIG)));
+                    doc = db.parse(is);
+                } 
+
+            }
+            String documentNS = doc.getDocumentElement().getNamespaceURI();
+            if (validating && documentNS != null) {
+                DOMSource domSource
+                     = new DOMSource(doc, documentURL.toExternalForm());
+
+                /*
+                 * If the Document in question is 1.2 (i.e. it has a namespace matching
+                 * JAVAEE_SCHEMA_DEFAULT_NS, then perform validation using the cached schema
+                 * and return.  Otherwise we assume a 1.0 or 1.1 faces-config in which case
+                 * we need to transform it to reference a special 1.1 schema before validating.
+                 */
+                Node documentElement = ((Document) domSource.getNode()).getDocumentElement();
+                if (JAVAEE_SCHEMA_DEFAULT_NS.equals(documentNS)) {
+                    Attr version = (Attr)
+                            documentElement.getAttributes().getNamedItem("version");
+                    DbfFactory.FacesSchema schema;
+                    if (version != null) {
+                        String versionStr = version.getValue();
+                        if ("2.0".equals(versionStr)) {
+                            if ("facelet-taglib".equals(documentElement.getLocalName())) {
+                                schema = DbfFactory.FacesSchema.FACELET_TAGLIB_20;
+                            } else {
+                                schema = DbfFactory.FacesSchema.FACES_20;
+                            }
+                        } else if ("2.1".equals(versionStr)) {
+                            if ("facelet-taglib".equals(documentElement.getLocalName())) {
+                                schema = DbfFactory.FacesSchema.FACELET_TAGLIB_20;
+                            } else {
+                                schema = DbfFactory.FacesSchema.FACES_21;
+                            }
+                        } else if ("1.2".equals(versionStr)) {
+                            schema = DbfFactory.FacesSchema.FACES_12;
+                        } else {
+                            throw new ConfigurationException("Unknown Schema version: " + versionStr);
+                        }
+                        DocumentBuilder builder = getBuilderForSchema(schema);
+                        if (builder.isValidating()) {
+                            builder.getSchema().newValidator().validate(domSource);
+                            returnDoc = ((Document) domSource.getNode());
+                        } else {
+                            returnDoc = ((Document) domSource.getNode());
+                        }
+                    } else {
+                        // this shouldn't happen, but...
+                        throw new ConfigurationException("No document version available.");
+                    }
+                } else {
+                    DOMResult domResult = new DOMResult();
+                    Transformer transformer = getTransformer(documentNS);
+                    transformer.transform(domSource, domResult);
+                    // copy the source document URI to the transformed result
+                    // so that processes that need to build URLs relative to the
+                    // document will work as expected.
+                    ((Document) domResult.getNode())
+                          .setDocumentURI(((Document) domSource
+                                .getNode()).getDocumentURI());
+                    DbfFactory.FacesSchema schemaToApply;
+                    if (FACES_CONFIG_1_X_DEFAULT_NS.equals(documentNS)) {
+                        schemaToApply = DbfFactory.FacesSchema.FACES_11;
+                    } else if (FACELETS_1_0_DEFAULT_NS.equals(documentNS)) {
+                        schemaToApply = DbfFactory.FacesSchema.FACELET_TAGLIB_20;
+                    } else {
+                        throw new IllegalStateException();
+                    }
+                    DocumentBuilder builder = getBuilderForSchema(schemaToApply);
+                    if (builder.isValidating()) {
+                        builder.getSchema().newValidator().validate(new DOMSource(domResult.getNode()));
+                        returnDoc = (Document) domResult.getNode();
+                    } else {
+                        returnDoc = (Document) domResult.getNode();
+                    }
+                }
+            } else {
+                returnDoc = doc;
+            }
+
+            // mark this document as the parsed representation of the
+            // WEB-INF/faces-config.xml.  This is used later in the configuration
+            // processing.
+            if (documentURL.toExternalForm().contains("/WEB-INF/faces-config.xml")) {
+                Attr webInf = returnDoc.createAttribute(WEB_INF_MARKER);
+                webInf.setValue("true");
+                returnDoc.getDocumentElement().getAttributes().setNamedItem(webInf);
+            }
+            return returnDoc;
+
+        }
+
+        private boolean streamIsZeroLengthOrEmpty(InputStream is) throws IOException {
+            boolean isZeroLengthOrEmpty = (0 == is.available());
+            final int size = 1024;
+            byte[] b = new byte[size];
+            String s;
+            while (!isZeroLengthOrEmpty && -1 != is.read(b, 0, size)) {
+                s = (new String(b, RIConstants.CHAR_ENCODING)).trim();
+                isZeroLengthOrEmpty = 0 == s.length();
+                b[0] = 0;
+                for (int i = 1; i < size; i += i) {
+                    System.arraycopy(b, 0, b, i, ((size - i) < i) ? (size - i) : i);
+                }
+            }
+
+            return isZeroLengthOrEmpty;
+        }
+
+
+        /**
+         * Obtain a <code>Transformer</code> using the style sheet
+         * referenced by the <code>XSL</code> constant.
+         *
+         * @return a new Tranformer instance
+         * @throws Exception if a Tranformer instance could not be created
+         */
+        private static Transformer getTransformer(String documentNS)
+        throws Exception {
+
+            TransformerFactory factory = Util.createTransformerFactory();
+
+            String xslToApply;
+            if (FACES_CONFIG_1_X_DEFAULT_NS.equals(documentNS)) {
+                xslToApply = FACES_TO_1_1_PRIVATE_XSL;
+            } else if (FACELETS_1_0_DEFAULT_NS.equals(documentNS)) {
+                xslToApply = FACELETS_TO_2_0_XSL;
+            } else {
+                throw new IllegalStateException();
+            }
+            return factory
+                 .newTransformer(new StreamSource(getInputStream(ConfigManager
+                      .class.getResource(xslToApply))));
+
+        }
+
+
+        /**
+         * @return an <code>InputStream</code> to the resource referred to by
+         *         <code>url</code>
+         * @param url source <code>URL</code>
+         * @throws IOException if an error occurs
+         */
+        private static InputStream getInputStream(URL url) throws IOException {
+
+            URLConnection conn = url.openConnection();
+            conn.setUseCaches(false);
+            return new BufferedInputStream(conn.getInputStream());
+
+        }
+
+
+
+        private DocumentBuilder getNonValidatingBuilder() throws Exception {
+
+            DocumentBuilderFactory tFactory = DbfFactory.getFactory();
+            tFactory.setValidating(false);
+            DocumentBuilder tBuilder = tFactory.newDocumentBuilder();
+            tBuilder.setEntityResolver(DbfFactory.FACES_ENTITY_RESOLVER);
+            tBuilder.setErrorHandler(DbfFactory.FACES_ERROR_HANDLER);
+            return tBuilder;
+
+        }
+
+        private DocumentBuilder getBuilderForSchema(DbfFactory.FacesSchema schema)
+        throws Exception {
+            schema.initSchema();
+            this.factory = DbfFactory.getFactory();
+
+            try {
+                factory.setSchema(schema.getSchema());
+            } catch (UnsupportedOperationException upe) {
+                return getNonValidatingBuilder();
+            }
+            DocumentBuilder builder = factory.newDocumentBuilder();
+            builder.setEntityResolver(DbfFactory.FACES_ENTITY_RESOLVER);
+            builder.setErrorHandler(DbfFactory.FACES_ERROR_HANDLER);
+            return builder;
+        }
+
+    } // END ParseTask
+
+
+    /**
+     * <p>
+     *  This <code>Callable</code> will be used by {@link ConfigManager#getConfigDocuments(javax.servlet.ServletContext, java.util.List, java.util.concurrent.ExecutorService, boolean)}.
+     *  It represents one or more URLs to configuration resources that require
+     *  processing.
+     * </p>
+     */
+    private static class URITask implements Callable<Collection<URI>> {
+
+        private ConfigurationResourceProvider provider;
+        private ServletContext sc;
+
+
+        // -------------------------------------------------------- Constructors
+
+
+        /**
+         * Constructs a new <code>URITask</code> instance.
+         * @param provider the <code>ConfigurationResourceProvider</code> from
+         *  which zero or more <code>URL</code>s will be returned
+         * @param sc the <code>ServletContext</code> of the current application
+         */
+        public URITask(ConfigurationResourceProvider provider,
+                       ServletContext sc) {
+            this.provider = provider;
+            this.sc = sc;
+        }
+
+
+        // ----------------------------------------------- Methods from Callable
+
+
+        /**
+         * @return zero or more <code>URL</code> instances
+         * @throws Exception if an Exception is thrown by the underlying
+         *  <code>ConfigurationResourceProvider</code> 
+         */
+        public Collection<URI> call() throws Exception {
+            Collection untypedCollection = provider.getResources(sc);
+            Iterator untypedCollectionIterator = untypedCollection.iterator();
+            Collection<URI> result = Collections.emptyList();
+            if (untypedCollectionIterator.hasNext()) {
+                Object cur = untypedCollectionIterator.next();
+                // account for older versions of the provider that return Collection<URL>.
+                if (cur instanceof URL) {
+                    result = new ArrayList<URI>(untypedCollection.size());
+                    result.add(new URI(((URL)cur).toExternalForm()));
+                    while (untypedCollectionIterator.hasNext()) {
+                        cur = untypedCollectionIterator.next();
+                        result.add(new URI(((URL)cur).toExternalForm()));
+                    }
+                } else {
+                    result = (Collection<URI>) untypedCollection;
+                }
+            }
+
+            return result;
+        }
+
+    } // END URITask
+
+
+}
\ No newline at end of file
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$1.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$1.class
new file mode 100644
index 0000000..1a471f8
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$1.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebConfigResourceMonitor$Monitor.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebConfigResourceMonitor$Monitor.class
new file mode 100644
index 0000000..45f99b8
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebConfigResourceMonitor$Monitor.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebConfigResourceMonitor.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebConfigResourceMonitor.class
new file mode 100644
index 0000000..2cb55c3
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebConfigResourceMonitor.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebXmlProcessor$WebXmlHandler.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebXmlProcessor$WebXmlHandler.class
new file mode 100644
index 0000000..1a15bb4
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebXmlProcessor$WebXmlHandler.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebXmlProcessor.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebXmlProcessor.class
new file mode 100644
index 0000000..393b9cc
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener$WebXmlProcessor.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener.class b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener.class
new file mode 100644
index 0000000..751cc7a
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener.class
Binary files differ
diff --git a/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener.java b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener.java
new file mode 100644
index 0000000..f853735
--- /dev/null
+++ b/hotfix/source/org.glassfish.com.sun.faces_2.1.18/ConfigureListener.java
@@ -0,0 +1,1120 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License").  You
+ * may not use this file except in compliance with the License.  You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt.  See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license."  If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above.  However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+package com.sun.faces.config;
+
+import com.sun.faces.RIConstants;
+import com.sun.faces.application.ApplicationAssociate;
+import com.sun.faces.application.WebappLifecycleListener;
+import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableGroovyScripting;
+import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableLazyBeanValidation;
+import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableThreading;
+import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.ForceLoadFacesConfigFiles;
+import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.VerifyFacesConfigObjects;
+import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.JavaxFacesProjectStage;
+import com.sun.faces.config.InitFacesContext;
+import com.sun.faces.config.WebConfiguration.WebContextInitParameter;
+import com.sun.faces.el.ChainTypeCompositeELResolver;
+import com.sun.faces.el.ELContextImpl;
+import com.sun.faces.el.ELContextListenerImpl;
+import com.sun.faces.el.ELUtils;
+import com.sun.faces.el.FacesCompositeELResolver;
+import com.sun.faces.mgbean.BeanBuilder;
+import com.sun.faces.mgbean.BeanManager;
+import com.sun.faces.scripting.groovy.GroovyHelper;
+import com.sun.faces.scripting.groovy.GroovyHelperFactory;
+import com.sun.faces.util.FacesLogger;
+import com.sun.faces.util.MessageUtils;
+import com.sun.faces.util.MojarraThreadFactory;
+import com.sun.faces.util.ReflectionUtils;
+import com.sun.faces.util.Timer;
+import com.sun.faces.util.Util;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+import javax.el.ELContext;
+import javax.el.ExpressionFactory;
+import javax.faces.FactoryFinder;
+import javax.faces.application.Application;
+import javax.faces.application.ApplicationFactory;
+import javax.faces.application.ProjectStage;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PreDestroyApplicationEvent;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeEvent;
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletRequestAttributeEvent;
+import javax.servlet.ServletRequestAttributeListener;
+import javax.servlet.ServletRequestEvent;
+import javax.servlet.ServletRequestListener;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+import javax.servlet.jsp.JspApplicationContext;
+import javax.servlet.jsp.JspFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * <p>Parse all relevant JavaServer Faces configuration resources, and
+ * configure the Reference Implementation runtime environment.</p>
+ * <p/>
+ */
+public class ConfigureListener implements ServletRequestListener,
+        HttpSessionListener,
+        ServletRequestAttributeListener,
+        HttpSessionAttributeListener,
+        ServletContextAttributeListener,
+        ServletContextListener {
+
+
+    private static final Logger LOGGER = FacesLogger.CONFIG.getLogger();
+
+    private ScheduledThreadPoolExecutor webResourcePool;
+
+    protected WebappLifecycleListener webAppListener;
+    protected WebConfiguration webConfig;
+
+
+    // ------------------------------------------ ServletContextListener Methods
+
+
+    public void contextInitialized(ServletContextEvent sce) {
+        ServletContext context = sce.getServletContext();
+
+        Timer timer = Timer.getInstance();
+        if (timer != null) {
+            timer.startTiming();
+        }
+
+        InitFacesContext initContext = new InitFacesContext(context);
+
+        if (LOGGER.isLoggable(Level.FINE)) {
+            LOGGER.log(Level.FINE,
+                    MessageFormat.format(
+                            "ConfigureListener.contextInitialized({0})",
+                            getServletContextIdentifier(context)));
+        }
+
+        webConfig = WebConfiguration.getInstance(context);
+        ConfigManager configManager = ConfigManager.getInstance();
+
+        if (configManager.hasBeenInitialized(context)) {
+            return;
+        }
+
+        // Check to see if the FacesServlet is present in the
+        // web.xml.   If it is, perform faces configuration as normal,
+        // otherwise, simply return.
+        Object mappingsAdded = context.getAttribute(RIConstants.FACES_INITIALIZER_MAPPINGS_ADDED);
+        if (mappingsAdded != null) {
+            context.removeAttribute(RIConstants.FACES_INITIALIZER_MAPPINGS_ADDED);
+        }
+
+        WebXmlProcessor webXmlProcessor = new WebXmlProcessor(context);
+        if (mappingsAdded == null) {
+            if (!webXmlProcessor.isFacesServletPresent()) {
+                if (!webConfig.isOptionEnabled(ForceLoadFacesConfigFiles)) {
+                    if (LOGGER.isLoggable(Level.FINE)) {
+                        LOGGER.log(Level.FINE,
+                                "No FacesServlet found in deployment descriptor - bypassing configuration");
+                    }
+                    WebConfiguration.clear(context);
+                    return;
+                }
+            } else {
+                if (LOGGER.isLoggable(Level.FINE)) {
+                    LOGGER.log(Level.FINE,
+                            "FacesServlet found in deployment descriptor - processing configuration.");
+                }
+            }
+        }
+
+
+        // bootstrap of faces required
+        webAppListener = new WebappLifecycleListener(context);
+        webAppListener.contextInitialized(sce);
+        ReflectionUtils.initCache(Thread.currentThread().getContextClassLoader());
+        Throwable caughtThrowable = null;
+
+        try {
+
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.log(Level.INFO,
+                        "jsf.config.listener.version",
+                        getServletContextIdentifier(context));
+            }
+
+            if (webConfig.isOptionEnabled(VerifyFacesConfigObjects)) {
+                if (LOGGER.isLoggable(Level.WARNING)) {
+                    LOGGER.warning("jsf.config.verifyobjects.development_only");
+                }
+                // if we're verifying, force bean validation to occur at startup as well
+                webConfig.overrideContextInitParameter(EnableLazyBeanValidation, false);
+                Verifier.setCurrentInstance(new Verifier());
+            }
+            initScripting();
+            configManager.initialize(context);
+            if (shouldInitConfigMonitoring()) {
+                initConfigMonitoring(context);
+            }
+
+            // Step 7, verify that all the configured factories are available
+            // and optionall that configured objects can be created. 
+            Verifier v = Verifier.getCurrentInstance();
+            if (v != null && !v.isApplicationValid()) {
+                if (LOGGER.isLoggable(Level.SEVERE)) {
+                    LOGGER.severe("jsf.config.verifyobjects.failures_detected");
+                    StringBuilder sb = new StringBuilder(128);
+                    for (String m : v.getMessages()) {
+                        sb.append(m).append('\n');
+                    }
+                    LOGGER.severe(sb.toString());
+                }
+            }
+            registerELResolverAndListenerWithJsp(context, false);
+            ELContext elctx = new ELContextImpl(initContext.getApplication().getELResolver());
+            elctx.putContext(FacesContext.class, initContext);
+            initContext.setELContext(elctx);
+            ApplicationAssociate associate =
+                    ApplicationAssociate.getInstance(context);
+            if (associate != null) {
+                associate.setContextName(getServletContextIdentifier(context));
+                BeanManager manager = associate.getBeanManager();
+                List<String> eagerBeans = manager.getEagerBeanNames();
+                if (!eagerBeans.isEmpty()) {
+                    for (String name : eagerBeans) {
+                        manager.create(name, initContext);
+                    }
+                }
+                boolean isErrorPagePresent = webXmlProcessor.isErrorPagePresent();
+                associate.setErrorPagePresent(isErrorPagePresent);
+                context.setAttribute(RIConstants.ERROR_PAGE_PRESENT_KEY_NAME,
+                        isErrorPagePresent);
+
+            }
+
+            webConfig.doPostBringupActions();
+
+        } catch (Throwable t) {
+            if (LOGGER.isLoggable(Level.SEVERE)) {
+                LOGGER.log(Level.SEVERE, "Critical error during deployment: ", t);
+            }
+            caughtThrowable = t;
+
+        } finally {
+            Verifier.setCurrentInstance(null);
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE,
+                        "jsf.config.listener.version.complete");
+            }
+            if (timer != null) {
+                timer.stopTiming();
+                timer.logResult("Initialization of context " +
+                        getServletContextIdentifier(context));
+            }
+            if (null != caughtThrowable) {
+                throw new RuntimeException(caughtThrowable);
+            }
+        }
+    }
+
+
+    public void contextDestroyed(ServletContextEvent sce) {
+        ServletContext context = sce.getServletContext();
+        InitFacesContext initContext = null;
+        boolean initialized = true;
+        try {
+            initContext = getInitFacesContext(context);
+            if (null == initContext) {
+                initContext = new InitFacesContext(context);
+            } else {
+                InitFacesContext.getThreadInitContextMap().put(Thread.currentThread(), initContext);
+            }
+
+            if (webAppListener != null) {
+                webAppListener.contextDestroyed(sce);
+                webAppListener = null;
+            }
+            if (webResourcePool != null) {
+                webResourcePool.shutdownNow();
+            }
+            if (!ConfigManager.getInstance().hasBeenInitialized(context)) {
+                initialized = false;
+                return;
+            }
+            GroovyHelper helper = GroovyHelper.getCurrentInstance(context);
+            if (helper != null) {
+                helper.setClassLoader();
+            }
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE,
+                           "ConfigureListener.contextDestroyed({0})",
+                           context.getServletContextName());
+            }
+
+
+            ELContext elctx = new ELContextImpl(initContext.getApplication().getELResolver());
+            elctx.putContext(FacesContext.class, initContext);
+            initContext.setELContext(elctx);
+            Application app = initContext.getApplication();
+            app.publishEvent(initContext,
+                    PreDestroyApplicationEvent.class,
+                    Application.class,
+                    app);
+
+        } catch (Exception e) {
+            if (LOGGER.isLoggable(Level.SEVERE)) {
+                LOGGER.log(Level.SEVERE,
+                        "Unexpected exception when attempting to tear down the Mojarra runtime",
+                        e);
+            }
+        } finally {
+            if (initialized) {
+                ApplicationAssociate.clearInstance(context);
+                ApplicationAssociate.setCurrentInstance(null);
+                // Release the initialization mark on this web application
+                ConfigManager.getInstance().destroy(context);
+                FactoryFinder.releaseFactories();
+                ReflectionUtils.clearCache(Thread.currentThread()
+                        .getContextClassLoader());
+                WebConfiguration.clear(context);
+                InitFacesContext.cleanupInitMaps(context);
+            }
+        }
+
+    }
+
+
+    // ------------------------------------- Methods from ServletRequestListener
+
+
+    public void requestDestroyed(ServletRequestEvent event) {
+        if (webAppListener != null) {
+            webAppListener.requestDestroyed(event);
+        }
+    }
+
+
+    public void requestInitialized(ServletRequestEvent event) {
+        if (webAppListener != null) {
+            webAppListener.requestInitialized(event);
+        }
+        InitFacesContext.cleanupInitMaps(event.getServletContext());
+    }
+
+
+    // ----------------------------------------- Methods from HttpSessionListener
+
+
+    public void sessionCreated(HttpSessionEvent event) {
+        if (webAppListener != null) {
+            webAppListener.sessionCreated(event);
+        }
+    }
+
+
+    public void sessionDestroyed(HttpSessionEvent event) {
+        if (webAppListener != null) {
+            webAppListener.sessionDestroyed(event);
+        }
+    }
+
+
+    // ---------------------------- Methods from ServletRequestAttributeListener
+
+
+    public void attributeAdded(ServletRequestAttributeEvent event) {
+        // ignored
+    }
+
+
+    public void attributeRemoved(ServletRequestAttributeEvent event) {
+        if (webAppListener != null) {
+            webAppListener.attributeRemoved(event);
+        }
+    }
+
+
+    public void attributeReplaced(ServletRequestAttributeEvent event) {
+        if (webAppListener != null) {
+            webAppListener.attributeReplaced(event);
+        }
+    }
+
+
+    // ------------------------------- Methods from HttpSessionAttributeListener
+
+
+    public void attributeAdded(HttpSessionBindingEvent event) {
+        // ignored
+    }
+
+
+    public void attributeRemoved(HttpSessionBindingEvent event) {
+        if (webAppListener != null) {
+            webAppListener.attributeRemoved(event);
+        }
+    }
+
+
+    public void attributeReplaced(HttpSessionBindingEvent event) {
+        if (webAppListener != null) {
+            webAppListener.attributeReplaced(event);
+        }
+    }
+
+
+    // ---------------------------- Methods from ServletContextAttributeListener
+
+
+    public void attributeAdded(ServletContextAttributeEvent event) {
+        // ignored
+    }
+
+    public void attributeRemoved(ServletContextAttributeEvent event) {
+        if (webAppListener != null) {
+            webAppListener.attributeRemoved(event);
+        }
+    }
+
+    public void attributeReplaced(ServletContextAttributeEvent event) {
+        if (webAppListener != null) {
+            webAppListener.attributeReplaced(event);
+        }
+    }
+
+
+    // --------------------------------------------------------- Private Methods
+
+    private boolean shouldInitConfigMonitoring() {
+
+        boolean development = isDevModeEnabled();
+        boolean threadingOptionSpecified = webConfig.isSet(EnableThreading);
+        if (development && !threadingOptionSpecified) {
+            return true;
+        }
+        boolean threadingOption = webConfig.isOptionEnabled(EnableThreading);
+        return (development && threadingOptionSpecified && threadingOption);
+
+    }
+
+    private void initConfigMonitoring(ServletContext context) {
+
+        //noinspection unchecked
+        Collection<URI> webURIs =
+                (Collection<URI>) context.getAttribute("com.sun.faces.webresources");
+        if (isDevModeEnabled() && webURIs != null && !webURIs.isEmpty()) {
+            webResourcePool = new ScheduledThreadPoolExecutor(1, new MojarraThreadFactory("WebResourceMonitor"));
+            webResourcePool.scheduleAtFixedRate(new WebConfigResourceMonitor(context, webURIs),
+                    2000,
+                    2000,
+                    TimeUnit.MILLISECONDS);
+        }
+        context.removeAttribute("com.sun.faces.webresources");
+
+    }
+
+    private void initScripting() {
+        if (webConfig.isOptionEnabled(EnableGroovyScripting)) {
+            GroovyHelper helper = GroovyHelperFactory.createHelper();
+            if (helper != null) {
+                helper.setClassLoader();
+            }
+        }
+    }
+
+
+    private boolean isDevModeEnabled() {
+
+        // interrogate the init parameter directly vs looking up the application
+        return "Development".equals(webConfig.getOptionValue(JavaxFacesProjectStage));
+
+    }
+
+
+    /**
+     * This method will be invoked {@link WebConfigResourceMonitor} when
+     * changes to any of the faces-config.xml files included in WEB-INF
+     * are modified.
+     */
+    private void reload(ServletContext sc) {
+
+        if (LOGGER.isLoggable(Level.INFO)) {
+            LOGGER.log(Level.INFO,
+                    "Reloading JSF configuration for context {0}",
+                    getServletContextIdentifier(sc));
+        }
+        GroovyHelper helper = GroovyHelper.getCurrentInstance();
+        if (helper != null) {
+            helper.setClassLoader();
+        }
+        // tear down the application
+        try {
+            // this will only be true in the automated test usage scenario
+            if (null != webAppListener) {
+                List<HttpSession> sessions = webAppListener.getActiveSessions();
+                if (sessions != null) {
+                    for (HttpSession session : sessions) {
+                        if (LOGGER.isLoggable(Level.INFO)) {
+                            LOGGER.log(Level.INFO,
+                                    "Invalidating Session {0}",
+                                    session.getId());
+                        }
+                        session.invalidate();
+                    }
+                }
+            }
+            ApplicationAssociate associate = ApplicationAssociate.getInstance(sc);
+            if (associate != null) {
+                BeanManager manager = associate.getBeanManager();
+                for (Map.Entry<String, BeanBuilder> entry : manager.getRegisteredBeans().entrySet()) {
+                    String name = entry.getKey();
+                    BeanBuilder bean = entry.getValue();
+                    if (ELUtils.Scope.APPLICATION.toString().equals(bean.getScope())) {
+                        if (LOGGER.isLoggable(Level.INFO)) {
+                            LOGGER.log(Level.INFO,
+                                    "Removing application scoped managed bean: {0}",
+                                    name);
+                        }
+                        sc.removeAttribute(name);
+                    }
+
+                }
+            }
+            // Release any allocated application resources
+            FactoryFinder.releaseFactories();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            FacesContext initContext = new InitFacesContext(sc);
+            ApplicationAssociate
+                    .clearInstance(initContext.getExternalContext());
+            ApplicationAssociate.setCurrentInstance(null);
+            // Release the initialization mark on this web application
+            ConfigManager.getInstance().destroy(sc);
+            initContext.release();
+            ReflectionUtils.clearCache(Thread.currentThread().getContextClassLoader());
+            WebConfiguration.clear(sc);
+        }
+
+        // bring the application back up, avoid re-registration of certain JSP
+        // artifacts.  No verification will be performed either to make this
+        // light weight.
+
+        // init a new WebAppLifecycleListener so that the cached ApplicationAssociate
+        // is removed.
+        webAppListener = new WebappLifecycleListener(sc);
+
+        FacesContext initContext = new InitFacesContext(sc);
+        ReflectionUtils
+                .initCache(Thread.currentThread().getContextClassLoader());
+
+        try {
+            ConfigManager configManager = ConfigManager.getInstance();
+            configManager.initialize(sc);
+
+
+            registerELResolverAndListenerWithJsp(sc, true);
+            ApplicationAssociate associate =
+                    ApplicationAssociate.getInstance(sc);
+            if (associate != null) {
+                Boolean errorPagePresent = (Boolean) sc.getAttribute(RIConstants.ERROR_PAGE_PRESENT_KEY_NAME);
+                if (null != errorPagePresent) {
+                    associate.setErrorPagePresent(errorPagePresent);
+                    associate.setContextName(getServletContextIdentifier(sc));
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            initContext.release();
+        }
+
+        if (LOGGER.isLoggable(Level.INFO)) {
+            LOGGER.log(Level.INFO,
+                    "Reload complete.",
+                    getServletContextIdentifier(sc));
+        }
+
+    }
+
+
+    private static String getServletContextIdentifier(ServletContext context) {
+        if (context.getMajorVersion() == 2 && context.getMinorVersion() < 5) {
+            return context.getServletContextName();
+        } else {
+            return context.getContextPath();
+        }
+    }
+
+
+    private static boolean isJspTwoOne(ServletContext context) {
+
+        // The following try/catch is a hack to work around
+        // a bug in Tomcat 6 where JspFactory.getDefaultFactory() will
+        // return null unless JspRuntimeContext has been loaded.
+        try {
+            Class.forName("org.apache.jasper.compiler.JspRuntimeContext");
+        } catch (ClassNotFoundException ignored) {
+            // ignored
+        }
+
+        if (JspFactory.getDefaultFactory() == null) {
+            return false;
+        }
+        try {
+            JspFactory.class.getMethod("getJspApplicationContext",
+                    ServletContext.class);
+        } catch (Exception e) {
+            return false;
+        }
+        try {
+            JspFactory.getDefaultFactory().getJspApplicationContext(context);
+        } catch (Throwable e) {
+            return false;
+        }
+        return true;
+
+    }
+
+    public void registerELResolverAndListenerWithJsp(ServletContext context, boolean reloaded) {
+
+        if (webConfig.isSet(WebContextInitParameter.ExpressionFactory)
+                || !isJspTwoOne(context)) {
+
+            // first try to load a factory defined in web.xml
+            if (!installExpressionFactory(context,
+                    webConfig.getOptionValue(
+                            WebContextInitParameter.ExpressionFactory))) {
+
+                throw new ConfigurationException(
+                        MessageUtils.getExceptionMessageString(
+                                MessageUtils.INCORRECT_JSP_VERSION_ID,
+                                WebContextInitParameter.ExpressionFactory.getDefaultValue(),
+                                WebContextInitParameter.ExpressionFactory.getQualifiedName()));
+
+            }
+
+        } else {
+
+            // JSP 2.1 specific check
+            if (JspFactory.getDefaultFactory().getJspApplicationContext(context) == null) {
+                return;
+            }
+
+            // register an empty resolver for now. It will be populated after the 
+            // first request is serviced.
+            FacesCompositeELResolver compositeELResolverForJsp =
+                    new ChainTypeCompositeELResolver(FacesCompositeELResolver.ELResolverChainType.JSP);
+            ApplicationAssociate associate =
+                    ApplicationAssociate.getInstance(context);
+            if (associate != null) {
+                associate.setFacesELResolverForJsp(compositeELResolverForJsp);
+            }
+
+            // get JspApplicationContext.
+            JspApplicationContext jspAppContext = JspFactory.getDefaultFactory()
+                    .getJspApplicationContext(context);
+
+            // cache the ExpressionFactory instance in ApplicationAssociate
+            if (associate != null) {
+                associate.setExpressionFactory(jspAppContext.getExpressionFactory());
+            }
+
+            // register compositeELResolver with JSP
+            try {
+                jspAppContext.addELResolver(compositeELResolverForJsp);
+            }
+            catch (IllegalStateException e) {
+                ApplicationFactory factory = (ApplicationFactory)
+                        FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
+                Application app = factory.getApplication();
+                if (app.getProjectStage() != ProjectStage.UnitTest && !reloaded) {
+                    throw e;
+                }
+            }
+
+            // register JSF ELContextListenerImpl with Jsp
+            ELContextListenerImpl elContextListener = new ELContextListenerImpl();
+            jspAppContext.addELContextListener(elContextListener);
+        }
+    }
+
+    private boolean installExpressionFactory(ServletContext sc,
+                                             String elFactoryType) {
+
+        if (elFactoryType == null) {
+            return false;
+        }
+        try {
+            ExpressionFactory factory = (ExpressionFactory)
+                    Util.loadClass(elFactoryType, this).newInstance();
+            ApplicationAssociate associate =
+                    ApplicationAssociate.getInstance(sc);
+            if (associate != null) {
+                associate.setExpressionFactory(factory);
+            }
+            return true;
+        } catch (Exception e) {
+            if (LOGGER.isLoggable(Level.SEVERE)) {
+                LOGGER.severe(MessageFormat.format("Unable to instantiate ExpressionFactory ''{0}''",
+                        elFactoryType));
+            }
+            return false;
+        }
+
+    }
+
+
+    private InitFacesContext getInitFacesContext(ServletContext context) {
+        Map initContextServletContext = InitFacesContext.getInitContextServletContextMap();
+        Set entries = initContextServletContext.entrySet();
+        InitFacesContext initContext = null;
+        for (Iterator iterator1 = entries.iterator(); iterator1.hasNext();) {
+            Map.Entry entry1 = (Map.Entry)iterator1.next();
+            Object initContextKey = entry1.getKey();
+            Object value1 = entry1.getValue();
+            if (context == value1) {
+                initContext =  (InitFacesContext)initContextKey;
+                break;
+            }
+        }
+        return initContext;
+    }
+
+    // ----------------------------------------------------------- Inner classes
+
+
+    /**
+     * <p>Processes a web application's deployment descriptor looking
+     * for a reference to <code>javax.faces.webapp.FacesServlet</code>.</p>
+     */
+    private static class WebXmlProcessor {
+
+        private static final String WEB_XML_PATH = "/WEB-INF/web.xml";
+        private static final String WEB_FRAGMENT_PATH = "META-INF/web-fragment.xml";
+
+        private boolean facesServletPresent;
+        private boolean errorPagePresent;
+
+
+        /**
+         * <p>When instantiated, the web.xml of the current application
+         * will be scanned looking for a references to the
+         * <code>FacesServlet</code>.  <code>isFacesServletPresent()</code>
+         * will return the appropriate value based on the scan.</p>
+         *
+         * @param context the <code>ServletContext</code> for the application
+         *                of interest
+         */
+        WebXmlProcessor(ServletContext context) {
+
+            if (context != null) {
+                scanForFacesServlet(context);
+            }
+
+        } // END WebXmlProcessor
+
+
+        /**
+         * @return <code>true</code> if the <code>WebXmlProcessor</code>
+         *         detected a <code>FacesServlet</code> entry, otherwise return
+         *         <code>false</code>.</p>
+         */
+        boolean isFacesServletPresent() {
+
+            return facesServletPresent;
+
+        } // END isFacesServletPresent
+
+
+        /**
+         * @return <code>true</code> if <code>WEB-INF/web.xml</code> contains
+         *         a <code>&lt;error-page&gt;</code> element.
+         */
+        boolean isErrorPagePresent() {
+
+            return errorPagePresent;
+
+        }
+
+
+        /**
+         * <p>Parse the web.xml for the current application and scan
+         * for a FacesServlet entry, if found, set the
+         * <code>facesServletPresent</code> property to true.
+         *
+         * @param context the ServletContext instance for this application
+         */
+        private void scanForFacesServlet(ServletContext context) {
+            InputStream in = context.getResourceAsStream(WEB_XML_PATH);
+            if (in == null) {
+                if (context.getMajorVersion() < 3) {
+                    throw new ConfigurationException("no web.xml present");
+                }
+            }
+            SAXParserFactory factory = getConfiguredFactory();
+            if (in != null) {
+                try {
+                    SAXParser parser = factory.newSAXParser();
+                    parser.parse(in, new WebXmlHandler());
+                } catch (Exception e) {
+                    warnProcessingError(e, context);
+                    facesServletPresent = true;
+                    return;
+                } finally {
+                    if (in != null) {
+                        try {
+                            in.close();
+                        } catch (Exception ioe) {
+                            if (LOGGER.isLoggable(Level.FINEST)) {
+                                LOGGER.log(Level.FINEST, "Closing stream", ioe);
+                            }
+                        }
+                    }
+                }
+            }
+            if (!facesServletPresent && context.getMajorVersion() >= 3) {
+                ClassLoader cl = Util.getCurrentLoader(this);
+                Enumeration<URL> urls;
+                try {
+                    urls = cl.getResources(WEB_FRAGMENT_PATH);
+                } catch (IOException ioe) {
+                    throw new ConfigurationException(ioe);
+                }
+                if (urls != null) {
+                    while (urls.hasMoreElements() && !facesServletPresent) {
+                        InputStream fragmentStream = null;
+                        try {
+                            URL url = urls.nextElement();
+                            URLConnection conn = url.openConnection();
+                            conn.setUseCaches(false);
+                            fragmentStream = conn.getInputStream();
+                            SAXParser parser = factory.newSAXParser();
+                            parser.parse(fragmentStream, new WebXmlHandler());
+                        } catch (Exception e) {
+                            warnProcessingError(e, context);
+                            facesServletPresent = true;
+                            return;
+                        } finally {
+                            if (fragmentStream != null) {
+                                try {
+                                    fragmentStream.close();
+                                } catch (IOException ioe) {
+                                    // ignore
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+        } // END scanForFacesServlet
+
+        /**
+         * <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 = Util.createSAXParserFactory();
+            factory.setValidating(false);
+            factory.setNamespaceAware(true);
+            return factory;
+
+        } // END getConfiguredFactory
+
+
+        private void warnProcessingError(Exception e, ServletContext sc) {
+
+            if (LOGGER.isLoggable(Level.WARNING)) {
+                LOGGER.log(Level.WARNING,
+                        MessageFormat.format(
+                                "jsf.configuration.web.xml.parse.failed",
+                                getServletContextIdentifier(sc)),
+                        e);
+            }
+
+        }
+
+
+        /**
+         * <p>A simple SAX handler to process the elements of interested
+         * within a web application's deployment descriptor.</p>
+         */
+        private class WebXmlHandler extends DefaultHandler {
+
+            private static final String ERROR_PAGE = "error-page";
+            private static final String SERVLET_CLASS = "servlet-class";
+            private static final String FACES_SERVLET =
+                    "javax.faces.webapp.FacesServlet";
+
+            private boolean servletClassFound;
+            @SuppressWarnings({"StringBufferField"})
+            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 (!errorPagePresent) {
+                    if (ERROR_PAGE.equals(localName)) {
+                        errorPagePresent = true;
+                        return;
+                    }
+                }
+                if (!facesServletPresent) {
+                    if (SERVLET_CLASS.equals(localName)) {
+                        servletClassFound = true;
+                        //noinspection StringBufferWithoutInitialCapacity
+                        content = new StringBuffer();
+                    } else {
+                        servletClassFound = false;
+                    }
+                }
+
+
+            } // END startElement
+
+
+            public void characters(char[] ch, int start, int length)
+                    throws SAXException {
+
+                if (servletClassFound && !facesServletPresent) {
+                    content.append(ch, start, length);
+                }
+
+            } // END characters
+
+
+            public void endElement(String uri, String localName, String qName)
+                    throws SAXException {
+
+                if (servletClassFound && !facesServletPresent) {
+                    if (FACES_SERVLET.equals(content.toString().trim())) {
+                        facesServletPresent = true;
+                    }
+                }
+
+            } // END endElement
+
+        } // END WebXmlHandler
+
+    } // END WebXmlProcessor
+
+
+    private class WebConfigResourceMonitor implements Runnable {
+
+        private List<Monitor> monitors;
+        private ServletContext sc;
+
+        // -------------------------------------------------------- Constructors
+
+
+        public WebConfigResourceMonitor(ServletContext sc, Collection<URI> uris) {
+
+            assert (uris != null);
+            this.sc = sc;
+            for (URI uri : uris) {
+                if (monitors == null) {
+                    monitors = new ArrayList<Monitor>(uris.size());
+                }
+                try {
+                    Monitor m = new Monitor(uri);
+                    monitors.add(m);
+                } catch (IOException ioe) {
+                    if (LOGGER.isLoggable(Level.SEVERE)) {
+                        LOGGER.severe("Unable to setup resource monitor for "
+                                      + uri.toString()
+                                      + ".  Resource will not be monitored for changes.");
+                    }
+                    if (LOGGER.isLoggable(Level.FINE)) {
+                        LOGGER.log(Level.FINE,
+                                   ioe.toString(),
+                                   ioe);
+                    }
+                }
+            }
+
+        }
+
+
+        // ----------------------------------------------- Methods from Runnable
+
+        /**
+         * PENDING javadocs
+         */
+        public void run() {
+
+            assert (monitors != null);
+            boolean reloaded = false;
+            for (Iterator<Monitor> i = monitors.iterator(); i.hasNext(); ) {
+                Monitor m = i.next();
+                try {
+                    if (m.hasBeenModified()) {
+                        if (!reloaded) {
+                            reloaded = true;
+                        }
+                    }
+                } catch (IOException ioe) {
+                    if (LOGGER.isLoggable(Level.SEVERE)) {
+                        LOGGER.severe("Unable to access url "
+                                      + m.uri.toString()
+                                      + ".  Monitoring for this resource will no longer occur.");
+                    }
+                    if (LOGGER.isLoggable(Level.FINE)) {
+                        LOGGER.log(Level.FINE,
+                                   ioe.toString(),
+                                   ioe);
+                    }
+                    i.remove();
+                }
+            }
+            if (reloaded) {
+                reload(sc);
+            }
+
+        }
+
+
+        // ------------------------------------------------------- Inner Classes
+
+
+        private class Monitor {
+
+            private URI uri;
+            private long timestamp = -1;
+
+            // ---------------------------------------------------- Constructors
+
+
+            Monitor(URI uri) throws IOException {
+
+                this.uri = uri;
+                this.timestamp = getLastModified();
+                if (LOGGER.isLoggable(Level.INFO)) {
+                    LOGGER.log(Level.INFO,
+                            "Monitoring {0} for modifications",
+                            uri.toURL().toExternalForm());
+                }
+
+            }
+
+
+            // ----------------------------------------- Package Private Methods
+
+
+            boolean hasBeenModified() throws IOException {
+                long temp = getLastModified();
+                if (timestamp < temp) {
+                    timestamp = temp;
+                    if (LOGGER.isLoggable(Level.INFO)) {
+                        LOGGER.log(Level.INFO,
+                                "{0} changed!",
+                                uri.toURL().toExternalForm());
+                    }
+                    return true;
+                }
+                return false;
+
+            }
+
+
+            // ------------------------------------------------- Private Methods
+
+
+            private long getLastModified() throws IOException {
+
+                InputStream in = null;
+                try {
+                    URLConnection conn = uri.toURL().openConnection();
+                    conn.connect();
+                    in = conn.getInputStream();
+                    return conn.getLastModified();
+                } finally {
+                    if (in != null) {
+                        try {
+                            in.close();
+                        } catch (IOException ignored) {
+                        }
+                    }
+                }
+
+            }
+
+        } // END Monitor
+
+    } // END WebConfigResourceMonitor
+
+}
+
