Save This Page
Home » mojarra-1.2_09-b02-FCS-source » com.sun.faces.config » [javadoc | source]
    1   /*
    2    * $Id: ConfigureListener.java,v 1.117.4.2 2008/04/29 19:33:24 rlubke Exp $
    3    */
    4   /*
    5    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    6    * 
    7    * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    8    * 
    9    * The contents of this file are subject to the terms of either the GNU
   10    * General Public License Version 2 only ("GPL") or the Common Development
   11    * and Distribution License("CDDL") (collectively, the "License").  You
   12    * may not use this file except in compliance with the License. You can obtain
   13    * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
   14    * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
   15    * language governing permissions and limitations under the License.
   16    * 
   17    * When distributing the software, include this License Header Notice in each
   18    * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
   19    * Sun designates this particular file as subject to the "Classpath" exception
   20    * as provided by Sun in the GPL Version 2 section of the License file that
   21    * accompanied this code.  If applicable, add the following below the License
   22    * Header, with the fields enclosed by brackets [] replaced by your own
   23    * identifying information: "Portions Copyrighted [year]
   24    * [name of copyright owner]"
   25    * 
   26    * Contributor(s):
   27    * 
   28    * If you wish your version of this file to be governed by only the CDDL or
   29    * only the GPL Version 2, indicate your decision by adding "[Contributor]
   30    * elects to include this software in this distribution under the [CDDL or GPL
   31    * Version 2] license."  If you don't indicate a single choice of license, a
   32    * recipient has the option to distribute your version of this file under
   33    * either the CDDL, the GPL Version 2 or to extend the choice of license to
   34    * its licensees as provided above.  However, if you add GPL Version 2 code
   35    * and therefore, elected the GPL Version 2 license, then the option applies
   36    * only if the new code is made subject to such option by the copyright
   37    * holder.
   38    */
   39   
   40   package com.sun.faces.config;
   41   
   42   import java.io.IOException;
   43   import java.io.InputStream;
   44   import java.io.StringReader;
   45   import java.net.URL;
   46   import java.net.URLConnection;
   47   import java.text.MessageFormat;
   48   import java.util.ArrayList;
   49   import java.util.List;
   50   import java.util.Map;
   51   import java.util.concurrent.ScheduledThreadPoolExecutor;
   52   import java.util.concurrent.TimeUnit;
   53   import java.util.logging.Level;
   54   import java.util.logging.Logger;
   55   
   56   import javax.el.CompositeELResolver;
   57   import javax.el.ExpressionFactory;
   58   import javax.faces.FactoryFinder;
   59   import javax.faces.context.FacesContext;
   60   import javax.servlet.ServletContext;
   61   import javax.servlet.ServletContextAttributeEvent;
   62   import javax.servlet.ServletContextAttributeListener;
   63   import javax.servlet.ServletContextEvent;
   64   import javax.servlet.ServletContextListener;
   65   import javax.servlet.ServletRequestAttributeEvent;
   66   import javax.servlet.ServletRequestAttributeListener;
   67   import javax.servlet.ServletRequestEvent;
   68   import javax.servlet.ServletRequestListener;
   69   import javax.servlet.http.HttpSession;
   70   import javax.servlet.http.HttpSessionAttributeListener;
   71   import javax.servlet.http.HttpSessionBindingEvent;
   72   import javax.servlet.http.HttpSessionEvent;
   73   import javax.servlet.http.HttpSessionListener;
   74   import javax.servlet.jsp.JspApplicationContext;
   75   import javax.servlet.jsp.JspFactory;
   76   import javax.xml.parsers.SAXParser;
   77   import javax.xml.parsers.SAXParserFactory;
   78   
   79   import com.sun.faces.application.ApplicationAssociate;
   80   import com.sun.faces.application.WebappLifecycleListener;
   81   import com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter;
   82   import com.sun.faces.config.WebConfiguration.WebContextInitParameter;
   83   import com.sun.faces.el.ELContextListenerImpl;
   84   import com.sun.faces.el.ELUtils;
   85   import com.sun.faces.el.FacesCompositeELResolver;
   86   import com.sun.faces.scripting.GroovyHelper;
   87   import com.sun.faces.scripting.GroovyHelperFactory;
   88   import com.sun.faces.mgbean.BeanBuilder;
   89   import com.sun.faces.mgbean.BeanManager;
   90   import com.sun.faces.renderkit.RenderKitUtils;
   91   import com.sun.faces.util.FacesLogger;
   92   import com.sun.faces.util.MessageUtils;
   93   import com.sun.faces.util.ReflectionUtils;
   94   import com.sun.faces.util.Timer;
   95   import com.sun.faces.util.Util;
   96   import org.xml.sax.Attributes;
   97   import org.xml.sax.InputSource;
   98   import org.xml.sax.SAXException;
   99   import org.xml.sax.helpers.DefaultHandler;
  100   
  101   /**
  102    * <p>Parse all relevant JavaServer Faces configuration resources, and
  103    * configure the Reference Implementation runtime environment.</p>
  104    * <p/>
  105    */
  106   public class ConfigureListener implements ServletRequestListener,
  107                                             HttpSessionListener,
  108                                             ServletRequestAttributeListener,
  109                                             HttpSessionAttributeListener,
  110                                             ServletContextAttributeListener,
  111                                             ServletContextListener {
  112   
  113   
  114       private static final Logger LOGGER = FacesLogger.CONFIG.getLogger();
  115   
  116       private ScheduledThreadPoolExecutor webResourcePool =
  117             new ScheduledThreadPoolExecutor(1);
  118   
  119       protected WebappLifecycleListener webAppListener;
  120       protected WebConfiguration webConfig;
  121   
  122      
  123       
  124       // ------------------------------------------ ServletContextListener Methods
  125   
  126   
  127       public void contextInitialized(ServletContextEvent sce) {
  128           ServletContext context = sce.getServletContext();
  129           webAppListener = new WebappLifecycleListener(context);
  130           webAppListener.contextInitialized(sce);
  131           Timer timer = Timer.getInstance();
  132           if (timer != null) {
  133               timer.startTiming();
  134           }
  135   
  136   
  137           if (LOGGER.isLoggable(Level.FINE)) {
  138               LOGGER.log(Level.FINE,
  139                          MessageFormat.format(
  140                               "ConfigureListener.contextInitialized({0})",
  141                               getServletContextIdentifier(context)));
  142           }
  143   
  144           webConfig = WebConfiguration.getInstance(context);
  145           ConfigManager configManager = ConfigManager.getInstance();
  146   
  147           if (configManager.hasBeenInitialized(context)) {
  148               return;
  149           }
  150   
  151           // Check to see if the FacesServlet is present in the
  152           // web.xml.   If it is, perform faces configuration as normal,
  153           // otherwise, simply return.
  154           if (!webConfig.isOptionEnabled(BooleanWebContextInitParameter.ForceLoadFacesConfigFiles)) {
  155               WebXmlProcessor processor = new WebXmlProcessor(context);
  156               if (!processor.isFacesServletPresent()) {
  157                   if (LOGGER.isLoggable(Level.FINE)) {
  158                       LOGGER.log(Level.FINE,
  159                                  "No FacesServlet found in deployment descriptor - bypassing configuration");
  160                   }
  161                   WebConfiguration.clear(context);
  162                   return;
  163               } else {
  164                   if (LOGGER.isLoggable(Level.FINE)) {
  165                       LOGGER.log(Level.FINE,
  166                                  "FacesServlet found in deployment descriptor - processing configuration.");
  167                   }
  168               }
  169           }
  170   
  171           FacesContext initContext = new InitFacesContext(context);
  172           ReflectionUtils.initCache(Thread.currentThread().getContextClassLoader());
  173   
  174           try {
  175   
  176               if (LOGGER.isLoggable(Level.INFO)) {
  177                   LOGGER.log(Level.INFO,
  178                             "jsf.config.listener.version",
  179                             getServletContextIdentifier(context));
  180               }
  181   
  182               // see if we need to disable our TLValidator
  183               Util.setHtmlTLVActive(
  184                     webConfig.isOptionEnabled(BooleanWebContextInitParameter.EnableHtmlTagLibraryValidator));
  185   
  186               if (webConfig.isOptionEnabled(BooleanWebContextInitParameter.VerifyFacesConfigObjects)) {
  187                   if (LOGGER.isLoggable(Level.WARNING)) {
  188                       LOGGER.warning("jsf.config.verifyobjects.development_only");
  189                   }
  190                   // if we're verifying, force bean validation to occur at startup as well
  191                   webConfig.overrideContextInitParameter(BooleanWebContextInitParameter.EnableLazyBeanValidation, false);
  192                   Verifier.setCurrentInstance(new Verifier());
  193               }
  194               initScripting();
  195               configManager.initialize(context);
  196               initConfigMonitoring(context);
  197   
  198               // Step 7, verify that all the configured factories are available
  199               // and optionall that configured objects can be created. 
  200               Verifier v = Verifier.getCurrentInstance();
  201               if (v != null && !v.isApplicationValid()) {
  202                   if (LOGGER.isLoggable(Level.SEVERE)) {
  203                       LOGGER.severe("jsf.config.verifyobjects.failures_detected");
  204                       StringBuilder sb = new StringBuilder(128);
  205                       for (String m : v.getMessages()) {
  206                           sb.append(m).append('\n');
  207                       }
  208                       LOGGER.severe(sb.toString());
  209                   }               
  210               }
  211               registerELResolverAndListenerWithJsp(context, false);
  212               ApplicationAssociate associate =
  213                    ApplicationAssociate.getInstance(context);
  214               if (associate != null) {
  215                   associate.setContextName(getServletContextIdentifier(context));
  216               }
  217               RenderKitUtils.loadSunJsfJs(initContext.getExternalContext());
  218               
  219           } finally {
  220               Verifier.setCurrentInstance(null);
  221               initContext.release();
  222               LOGGER.log(Level.FINE,
  223                          "jsf.config.listener.version.complete");
  224               if (timer != null) {
  225                   timer.stopTiming();
  226                   timer.logResult("Initialization of context " +
  227                                   getServletContextIdentifier(context));
  228               }           
  229           }
  230       }
  231   
  232   
  233       public void contextDestroyed(ServletContextEvent sce) {
  234           webAppListener.contextDestroyed(sce);
  235           webAppListener = null;
  236           ServletContext context = sce.getServletContext();
  237           GroovyHelper helper = GroovyHelper.getCurrentInstance(context);
  238           if (helper != null) {
  239               helper.setClassLoader();
  240           }
  241   
  242           LOGGER.log(Level.FINE,
  243                      "ConfigureListener.contextDestroyed({0})",
  244                      context.getServletContextName());
  245   
  246           try {
  247               // Release any allocated application resources
  248               FactoryFinder.releaseFactories();
  249               //monitor.cancel(true);
  250               //webResourcePool.purge();
  251               webResourcePool.shutdown();
  252           } finally {
  253               FacesContext initContext = new InitFacesContext(context);
  254               ApplicationAssociate
  255                     .clearInstance(initContext.getExternalContext());
  256               ApplicationAssociate.setCurrentInstance(null);
  257               // Release the initialization mark on this web application
  258               ConfigManager.getInstance().destory(context);
  259               initContext.release();
  260               ReflectionUtils.clearCache(Thread.currentThread().getContextClassLoader());
  261               WebConfiguration.clear(context);
  262           }
  263   
  264       }
  265   
  266   
  267       // ------------------------------------- Methods from ServletRequestListener
  268   
  269   
  270       public void requestDestroyed(ServletRequestEvent event) {
  271           if (webAppListener != null) {
  272               webAppListener.requestDestroyed(event);
  273           }
  274       }
  275   
  276   
  277       public void requestInitialized(ServletRequestEvent event) {
  278           if (webAppListener != null) {
  279               webAppListener.requestInitialized(event);
  280           }
  281       }
  282   
  283   
  284       // ----------------------------------------- Methods from HttpSessionListener
  285   
  286   
  287       public void sessionCreated(HttpSessionEvent event) {
  288          if (webAppListener != null) {
  289              webAppListener.sessionCreated(event);
  290          }
  291       }
  292   
  293   
  294       public void sessionDestroyed(HttpSessionEvent event) {
  295           if (webAppListener != null) {
  296               webAppListener.sessionDestroyed(event);
  297           }
  298       }
  299   
  300   
  301       // ---------------------------- Methods from ServletRequestAttributeListener
  302   
  303   
  304       public void attributeAdded(ServletRequestAttributeEvent event) {
  305           // ignored
  306       }
  307   
  308   
  309       public void attributeRemoved(ServletRequestAttributeEvent event) {
  310           if (webAppListener != null) {
  311               webAppListener.attributeRemoved(event);
  312           }
  313       }
  314   
  315   
  316       public void attributeReplaced(ServletRequestAttributeEvent event) {
  317           if (webAppListener != null) {
  318               webAppListener.attributeReplaced(event);
  319           }
  320       }
  321   
  322   
  323       // ------------------------------- Methods from HttpSessionAttributeListener
  324   
  325   
  326       public void attributeAdded(HttpSessionBindingEvent event) {
  327           // ignored
  328       }
  329   
  330   
  331       public void attributeRemoved(HttpSessionBindingEvent event) {
  332           if (webAppListener != null) {
  333               webAppListener.attributeRemoved(event);
  334           }
  335       }
  336   
  337   
  338       public void attributeReplaced(HttpSessionBindingEvent event) {
  339           if (webAppListener != null) {
  340               webAppListener.attributeReplaced(event);
  341           }
  342       }
  343   
  344   
  345       // ---------------------------- Methods from ServletContextAttributeListener
  346   
  347       
  348       public void attributeAdded(ServletContextAttributeEvent event) {
  349           // ignored
  350       }
  351   
  352       public void attributeRemoved(ServletContextAttributeEvent event) {
  353           if (webAppListener != null) {
  354               webAppListener.attributeRemoved(event);
  355           }
  356       }
  357   
  358       public void attributeReplaced(ServletContextAttributeEvent event) {
  359           if (webAppListener != null) {
  360               webAppListener.attributeReplaced(event);
  361           }
  362       }
  363   
  364   
  365       // --------------------------------------------------------- Private Methods
  366   
  367       
  368       private void initConfigMonitoring(ServletContext context) {
  369   
  370           //noinspection unchecked
  371           List<URL> webURLs =
  372                 (List<URL>) context.getAttribute("com.sun.faces.webresources");
  373           if (isDevModeEnabled() && webURLs != null && !webURLs.isEmpty()) {
  374               webResourcePool.scheduleAtFixedRate(new WebConfigResourceMonitor(context, webURLs),
  375                                                  2000,
  376                                                  2000,
  377                                                  TimeUnit.MILLISECONDS);
  378           }
  379           context.removeAttribute("com.sun.faces.webresources");
  380   
  381       }
  382   
  383       private void initScripting() {
  384           //if (isDevModeEnabled()) {
  385               GroovyHelper helper = GroovyHelperFactory.createHelper();
  386               if (helper != null) {
  387                   helper.setClassLoader();
  388               }
  389           //}
  390       }
  391   
  392   
  393       private boolean isDevModeEnabled() {
  394   
  395           return webConfig.isOptionEnabled(BooleanWebContextInitParameter.DevelopmentMode);
  396   
  397       }
  398   
  399   
  400       /**
  401        * This method will be invoked {@link WebConfigResourceMonitor} when
  402        * changes to any of the faces-config.xml files included in WEB-INF
  403        * are modified.
  404        */
  405       private void reload(ServletContext sc) {
  406   
  407           if (LOGGER.isLoggable(Level.INFO)) {
  408               LOGGER.log(Level.INFO,
  409                          "Reloading JSF configuration for context {0}",
  410                          getServletContextIdentifier(sc));
  411           }
  412           GroovyHelper helper = GroovyHelper.getCurrentInstance();
  413           if (helper != null) {
  414               helper.setClassLoader();
  415           }
  416           // tear down the application
  417           try {
  418               List<HttpSession> sessions = webAppListener.getActiveSessions();
  419               if (sessions != null) {
  420                   for (HttpSession session : sessions) {
  421                       if (LOGGER.isLoggable(Level.INFO)) {
  422                           LOGGER.log(Level.INFO,
  423                                      "Invalidating Session {0}",
  424                                      session.getId());
  425                       }
  426                       session.invalidate();
  427                   }
  428               }
  429               ApplicationAssociate associate = ApplicationAssociate.getInstance(sc);
  430               if (associate != null) {
  431                   BeanManager manager = associate.getBeanManager();
  432                   for (Map.Entry<String,BeanBuilder> entry : manager.getRegisteredBeans().entrySet()) {
  433                       String name = entry.getKey();
  434                       BeanBuilder bean = entry.getValue();
  435                       if (bean.getScope() == ELUtils.Scope.APPLICATION) {
  436                           if (LOGGER.isLoggable(Level.INFO)) {
  437                               LOGGER.log(Level.INFO,
  438                                          "Removing application scoped managed bean: {0}",
  439                                          name);
  440                           }
  441                           sc.removeAttribute(name);
  442                       }
  443   
  444                   }
  445               }
  446               // Release any allocated application resources
  447               FactoryFinder.releaseFactories();
  448           } catch (Exception e) {
  449               e.printStackTrace();
  450           } finally {
  451               FacesContext initContext = new InitFacesContext(sc);
  452               ApplicationAssociate
  453                     .clearInstance(initContext.getExternalContext());
  454               ApplicationAssociate.setCurrentInstance(null);
  455               // Release the initialization mark on this web application
  456               ConfigManager.getInstance().destory(sc);
  457               initContext.release();
  458               ReflectionUtils.clearCache(Thread.currentThread().getContextClassLoader());
  459               WebConfiguration.clear(sc);
  460           }
  461   
  462           // bring the application back up, avoid re-registration of certain JSP
  463           // artifacts.  No verification will be performed either to make this
  464           // light weight.
  465   
  466           // init a new WebAppLifecycleListener so that the cached ApplicationAssociate
  467           // is removed.
  468           webAppListener = new WebappLifecycleListener(sc);
  469   
  470           FacesContext initContext = new InitFacesContext(sc);
  471           ReflectionUtils
  472                 .initCache(Thread.currentThread().getContextClassLoader());
  473   
  474           try {
  475               ConfigManager configManager = ConfigManager.getInstance();
  476               configManager.initialize(sc);
  477   
  478   
  479               registerELResolverAndListenerWithJsp(sc, true);
  480               ApplicationAssociate associate =
  481                     ApplicationAssociate.getInstance(sc);
  482               if (associate != null) {
  483                   associate.setContextName(getServletContextIdentifier(sc));
  484               }
  485               RenderKitUtils.loadSunJsfJs(initContext.getExternalContext());
  486           } catch (Exception e) {
  487               e.printStackTrace();
  488           } finally {
  489               initContext.release();
  490           }
  491   
  492           if (LOGGER.isLoggable(Level.INFO)) {
  493               LOGGER.log(Level.INFO,
  494                          "Reload complete.",
  495                          getServletContextIdentifier(sc));
  496           }
  497   
  498       }
  499   
  500   
  501       private static String getServletContextIdentifier(ServletContext context) {
  502           if (context.getMajorVersion() == 2 && context.getMinorVersion() < 5) {
  503               return context.getServletContextName();
  504           } else {
  505               return context.getContextPath();
  506           }
  507       }
  508   
  509   
  510       
  511       private static boolean isJspTwoOne() {
  512   
  513           // The following try/catch is a hack to work around
  514           // a bug in Tomcat 6 where JspFactory.getDefaultFactory() will
  515           // return null unless JspRuntimeContext has been loaded.
  516           try {
  517               Class.forName("org.apache.jasper.compiler.JspRuntimeContext");
  518           } catch (ClassNotFoundException ignored) {
  519               // ignored
  520           }
  521   
  522           if (JspFactory.getDefaultFactory() == null) {
  523               return false;
  524           }
  525           try {
  526               JspFactory.class.getMethod("getJspApplicationContext",
  527                                          ServletContext.class);
  528           } catch (NoSuchMethodException nsme) {
  529               return false;
  530           }
  531           return true;
  532   
  533       }
  534   
  535       public void registerELResolverAndListenerWithJsp(ServletContext context, boolean reloaded) {
  536   
  537           if (webConfig.isSet(WebContextInitParameter.ExpressionFactory) ||
  538                 !isJspTwoOne()) {
  539   
  540               // first try to load a factory defined in web.xml
  541               if (!installExpressionFactory(context,
  542                                             webConfig.getOptionValue(
  543                                                   WebContextInitParameter.ExpressionFactory))) {
  544   
  545                       throw new ConfigurationException(
  546                             MessageUtils.getExceptionMessageString(
  547                                   MessageUtils.INCORRECT_JSP_VERSION_ID,
  548                                   WebContextInitParameter.ExpressionFactory.getDefaultValue(),
  549                                   WebContextInitParameter.ExpressionFactory.getQualifiedName()));
  550   
  551               }
  552   
  553           } else {
  554   
  555               // JSP 2.1 specific check
  556               if (JspFactory.getDefaultFactory().getJspApplicationContext(context) == null) {
  557                   return;
  558               }
  559               
  560               // register an empty resolver for now. It will be populated after the 
  561               // first request is serviced.
  562               CompositeELResolver compositeELResolverForJsp = 
  563                   new FacesCompositeELResolver(FacesCompositeELResolver.ELResolverChainType.JSP);
  564               ApplicationAssociate associate =
  565                        ApplicationAssociate.getInstance(context);
  566               if (associate != null) {
  567                   associate.setFacesELResolverForJsp(compositeELResolverForJsp);
  568               }
  569                       
  570               // get JspApplicationContext.
  571               JspApplicationContext jspAppContext = JspFactory.getDefaultFactory()
  572                       .getJspApplicationContext(context);
  573       
  574               // cache the ExpressionFactory instance in ApplicationAssociate
  575               if (associate != null) {
  576                   associate.setExpressionFactory(jspAppContext.getExpressionFactory());
  577               }
  578       
  579               // register compositeELResolver with JSP
  580               try {
  581                   jspAppContext.addELResolver(compositeELResolverForJsp);
  582               }
  583               catch (IllegalStateException e) {
  584                   if (!Util.isUnitTestModeEnabled() && !reloaded) {
  585                       throw e;
  586                   }
  587               }
  588       
  589               // register JSF ELContextListenerImpl with Jsp
  590               ELContextListenerImpl elContextListener = new ELContextListenerImpl();
  591               jspAppContext.addELContextListener(elContextListener);
  592            }
  593       }
  594   
  595       private boolean installExpressionFactory(ServletContext sc,
  596                                                String elFactoryType){
  597   
  598           if (elFactoryType == null) {
  599               return false;
  600           }
  601           try {
  602               ExpressionFactory factory = (ExpressionFactory)
  603                     Class.forName(elFactoryType).newInstance();
  604               ApplicationAssociate associate =
  605                    ApplicationAssociate.getInstance(sc);
  606               if (associate != null) {
  607                   associate.setExpressionFactory(factory);
  608               }
  609               return true;
  610           } catch (Exception e) {
  611               LOGGER.severe(MessageFormat.format("Unable to instantiate ExpressionFactory ''{0}''",
  612                                                  elFactoryType));
  613               return false;
  614           }
  615   
  616       }
  617   
  618       // ----------------------------------------------------------- Inner classes
  619   
  620   
  621       /**
  622        * <p>Processes a web application's deployment descriptor looking
  623        * for a reference to <code>javax.faces.webapp.FacesServlet</code>.</p>
  624        */
  625       private static class WebXmlProcessor {
  626   
  627           private static final String WEB_XML_PATH = "/WEB-INF/web.xml";
  628   
  629           private boolean facesServletPresent;
  630   
  631   
  632           /**
  633            * <p>When instantiated, the web.xml of the current application
  634            * will be scanned looking for a references to the
  635            * <code>FacesServlet</code>.  <code>isFacesServletPresent()</code>
  636            * will return the appropriate value based on the scan.</p>
  637            * @param context the <code>ServletContext</code> for the application
  638            *  of interest
  639            */
  640           WebXmlProcessor(ServletContext context) {
  641   
  642               if (context != null) {
  643                   scanForFacesServlet(context);
  644               }
  645   
  646           } // END WebXmlProcessor
  647   
  648   
  649           /**
  650            * @return <code>true</code> if the <code>WebXmlProcessor</code>
  651            * detected a <code>FacesServlet</code> entry, otherwise return
  652            * <code>false</code>.</p>        
  653            */
  654           boolean isFacesServletPresent() {
  655   
  656               return facesServletPresent;
  657   
  658           } // END isFacesServletPresent
  659   
  660   
  661           /**
  662            * <p>Parse the web.xml for the current application and scan
  663            * for a FacesServlet entry, if found, set the
  664            * <code>facesServletPresent</code> property to true.
  665            * @param context the ServletContext instance for this application
  666            */
  667           private void scanForFacesServlet(ServletContext context) {
  668   
  669               SAXParserFactory factory = getConfiguredFactory();
  670               try {
  671                   SAXParser parser = factory.newSAXParser();
  672                   parser.parse(context.getResourceAsStream(WEB_XML_PATH),
  673                                 new WebXmlHandler());
  674               } catch (Exception e) {
  675                   // This probably won't happen since the container would
  676                   // catch it before we would, but, if we catch an exception
  677                   // processing the web.xml, set facesServletFound to true to
  678                   // default to our previous behavior of processing the faces
  679                   // configuration.
  680                   if (LOGGER.isLoggable(Level.WARNING)) {
  681                       LOGGER.log(Level.WARNING,
  682                                  MessageFormat.format("Unable to process deployment descriptor for context ''{0}''",
  683                                                       getServletContextIdentifier(context)));
  684                   }
  685                   facesServletPresent = true;
  686               }
  687   
  688           } // END scanForFacesServlet
  689   
  690           /**
  691            * <p>Return a <code>SAXParserFactory</code> instance that is
  692            * non-validating and is namespace aware.</p>
  693            * @return configured <code>SAXParserFactory</code>
  694            */
  695           private SAXParserFactory getConfiguredFactory() {
  696   
  697               SAXParserFactory factory = SAXParserFactory.newInstance();
  698               factory.setValidating(false);
  699               factory.setNamespaceAware(true);
  700               return factory;
  701   
  702           } // END getConfiguredFactory
  703   
  704   
  705           /**
  706            * <p>A simple SAX handler to process the elements of interested
  707            * within a web application's deployment descriptor.</p>
  708            */
  709           private class WebXmlHandler extends DefaultHandler {
  710   
  711               private static final String SERVLET_CLASS = "servlet-class";
  712               private static final String FACES_SERVLET =
  713                   "javax.faces.webapp.FacesServlet";
  714   
  715               private boolean servletClassFound;
  716               @SuppressWarnings({"StringBufferField"})
  717               private StringBuffer content;
  718   
  719               public InputSource resolveEntity(String publicId, String systemId)
  720               throws SAXException {
  721   
  722                   return new InputSource(new StringReader(""));
  723   
  724               } // END resolveEntity
  725   
  726   
  727               public void startElement(String uri, String localName,
  728                                        String qName, Attributes attributes)
  729               throws SAXException {
  730   
  731                   if (!facesServletPresent) {
  732                       if (SERVLET_CLASS.equals(localName)) {
  733                           servletClassFound = true;
  734                           //noinspection StringBufferWithoutInitialCapacity
  735                           content = new StringBuffer();
  736                       } else {
  737                           servletClassFound = false;
  738                       }
  739                   }
  740   
  741               } // END startElement
  742   
  743   
  744               public void characters(char[] ch, int start, int length)
  745               throws SAXException {
  746   
  747                   if (servletClassFound && !facesServletPresent) {
  748                       content.append(ch, start, length);
  749                   }
  750   
  751               } // END characters
  752   
  753   
  754               public void endElement(String uri, String localName, String qName)
  755               throws SAXException {
  756   
  757                   if (servletClassFound && !facesServletPresent) {
  758                       if (FACES_SERVLET.equals(content.toString().trim())) {
  759                           facesServletPresent = true;
  760                       }
  761                   }
  762   
  763               } // END endElement
  764   
  765           } // END WebXmlHandler
  766   
  767       } // END WebXmlProcessor
  768   
  769   
  770        private class WebConfigResourceMonitor implements Runnable {
  771   
  772           private List<Monitor> monitors;
  773           private ServletContext sc;
  774   
  775           // -------------------------------------------------------- Constructors
  776   
  777   
  778           public WebConfigResourceMonitor(ServletContext sc, List<URL> urls) {
  779   
  780               assert (urls != null);
  781               this.sc = sc;
  782               for (URL url : urls) {
  783                   if (monitors == null) {
  784                       monitors = new ArrayList<Monitor>(urls.size());
  785                   }
  786                   monitors.add(new Monitor(url));
  787               }
  788   
  789           }
  790   
  791   
  792           // ----------------------------------------------- Methods from Runnable
  793   
  794           /**
  795            * PENDING javadocs
  796            */
  797           public void run() {
  798   
  799               assert (monitors != null);
  800               boolean reloaded = false;
  801               for (Monitor m : monitors) {
  802                   if (m.hasBeenModified()) {
  803                       if (!reloaded) {
  804                           reloaded = true;
  805                       }
  806                   }
  807               }
  808               if (reloaded) {
  809                   reload(sc);
  810               }
  811   
  812           }
  813   
  814   
  815           // ------------------------------------------------------- Inner Classes
  816   
  817   
  818           private class Monitor {
  819   
  820               private URL url;
  821               private long timestamp = -1;
  822   
  823               // ---------------------------------------------------- Constructors
  824   
  825   
  826               Monitor(URL url) {
  827   
  828                   this.url = url;
  829                   this.timestamp = getLastModified();
  830                   LOGGER.log(Level.INFO,
  831                              "Monitoring {0} for modifications",
  832                              url.toExternalForm());
  833   
  834               }
  835   
  836   
  837               // ----------------------------------------- Package Private Methods
  838   
  839   
  840               boolean hasBeenModified() {
  841                   long temp = getLastModified();
  842                   if (timestamp < temp) {
  843                       timestamp = temp;
  844                       LOGGER.log(Level.INFO,
  845                              "{0} changed!",
  846                              url.toExternalForm());
  847                       return true;
  848                   }
  849                   return false;
  850   
  851               }
  852   
  853   
  854               // ------------------------------------------------- Private Methods
  855   
  856   
  857               private long getLastModified() {
  858   
  859                   InputStream in = null;
  860                   try {
  861                       URLConnection conn = url.openConnection();
  862                       conn.connect();
  863                       in = conn.getInputStream();
  864                       return conn.getLastModified();
  865                   } catch (IOException ioe) {
  866                       if (LOGGER.isLoggable(Level.SEVERE)) {
  867                           LOGGER.log(Level.SEVERE,
  868                                      "Unable to check JAR timestamp.",
  869                                      ioe);
  870                       }
  871                       return this.timestamp;
  872                   } finally {
  873                       if (in != null) {
  874                           try {
  875                               in.close();
  876                           } catch (IOException ignored) {
  877                           }
  878                       }
  879                   }
  880   
  881               }
  882   
  883           } // END Monitor
  884   
  885       } // END WebConfigResourceMonitor
  886   
  887   }
  888   

Save This Page
Home » mojarra-1.2_09-b02-FCS-source » com.sun.faces.config » [javadoc | source]