Package com.ocpsoft.pretty.faces.el.resolver

Source Code of com.ocpsoft.pretty.faces.el.resolver.FacesConfigBeanNameResolver$FacesConfigEntry

/*
* Copyright 2010 Lincoln Baxter, III
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ocpsoft.pretty.faces.el.resolver;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.faces.webapp.FacesServlet;
import javax.servlet.ServletContext;

import org.apache.commons.digester.Digester;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.SAXException;

import com.ocpsoft.pretty.faces.spi.ELBeanNameResolver;
import com.ocpsoft.pretty.faces.util.EmptyEntityResolver;

/**
*
* <p>
* Implementation of {@link ELBeanNameResolver} handling beans configured via the
* standard XML configuration mechanism.
* </p>
*
* <p>
* This resolver handles beans specified in faces-config.xml files. The resolver
* will pick up the default configuration file <code>/WEB-INF/faces-config.xml</code>,
* all <code>/META-INF/faces-config.xml</code> found by the supplied {@link ClassLoader}
* and all files specified via the <code>javax.faces.CONFIG_FILES</code> init parameter.
* </p>
*
* @author Christian Kaltepoth
*
*/
public class FacesConfigBeanNameResolver implements ELBeanNameResolver
{

   private final static Log log = LogFactory.getLog(FacesConfigBeanNameResolver.class);

   /**
    * Name of default <code>faces-config.xml</code> loaded via
    * {@link ServletContext#getResource(String)}
    */
   private final static String WEB_INF_FACES_CONFIG_XML = "/WEB-INF/faces-config.xml";

   /**
    * Name of <code>faces-config.xml</code> loaded via
    * {@link ClassLoader#getResource(String)}
    */
   private final static String META_INF_FACES_CONFIG_XML = "META-INF/faces-config.xml";

   /**
    * Lookup map: FQCN -> bean name
    */
   private Map<String, String> beanNameMap = new HashMap<String, String>();

   /**
    * Initialization procedure. Reads all faces-config.xml files and registers
    * the beans found.
    */
   public boolean init(ServletContext servletContext, ClassLoader classLoader)
   {

      // list of beans found
      List<FacesConfigEntry> facesConfigEntries = new ArrayList<FacesConfigEntry>();

      // get the list of faces configuration files to process
      Set<URL> facesConfigs = getFacesConfigFiles(servletContext, classLoader);

      // process all configuration files
      for (URL url : facesConfigs)
      {
         processFacesConfig(url, facesConfigEntries);
      }

      // Create bean name lookup map from all entries found
      for (FacesConfigEntry entry : facesConfigEntries)
      {
         beanNameMap.put(entry.getBeanClass(), entry.getName());
      }

      // debug statement containing number of classes found
      if (log.isDebugEnabled())
      {
         log.debug("Found " + beanNameMap.size() + " bean names in faces configuration.");
      }

      // we will always enable this resolver
      return true;
   }

   /**
    * Returns a set of faces-config.xml files. This set includes the default
    * configuration file, all additional files mentioned via the
    * <code>javax.faces.CONFIG_FILES</code> init parameter and all files found
    * in META-INF folders.
    *
    * @param servletContext
    *           The ServletContext
    * @param classLoader
    *           The classloader used to find files in META-INF directories
    * @return A set of URLs
    */
   private Set<URL> getFacesConfigFiles(ServletContext servletContext, ClassLoader classLoader)
   {

      // set of URLs to process
      Set<URL> result = new HashSet<URL>();

      try
      {

         // get default faces-config.xml
         URL defaultFacesConfig = servletContext.getResource(WEB_INF_FACES_CONFIG_XML);
         if (defaultFacesConfig != null)
         {
            result.add(defaultFacesConfig);
         }

         // get additional configuration files from init parameter
         result.addAll(getConfigFilesFromInitParameter(servletContext));

         // Find configuration files META-INF directories
         try
         {
            Enumeration<URL> resources = classLoader.getResources(META_INF_FACES_CONFIG_XML);
            while (resources.hasMoreElements())
            {
               result.add(resources.nextElement());
            }
         }
         catch (IOException e)
         {
            log.error("Failed to load faces-config.xml files from META-INF directories", e);
         }

      }
      catch (MalformedURLException e)
      {
         // should not happen, because URLs are hard-coded
         throw new IllegalArgumentException(e);
      }

      return result;
   }

   /**
    * Returns a collection of faces configuration files mentioned via the
    * default <code>javax.faces.CONFIG_FILES</code> init parameter
    *
    * @param servletContext
    *           The ServletContext
    * @return A collection of URLs (never null)
    */
   private Collection<URL> getConfigFilesFromInitParameter(ServletContext servletContext)
   {

      // read init parameter
      String initParam = servletContext.getInitParameter(FacesServlet.CONFIG_FILES_ATTR);

      // empty? return empty set
      if (initParam == null || initParam.trim().length() == 0)
      {
         return Collections.emptySet();
      }

      // split string at each comma
      String[] files = initParam.split(",");

      // the result
      Set<URL> result = new HashSet<URL>();

      // process each single file
      for (String file : files)
      {

         // ignore empty entries
         if (file.trim().length() == 0)
         {
            continue;
         }

         try
         {
            // try get URL for this file
            URL url = servletContext.getResource(file.trim());

            // add it to the result, if it exists
            if (url != null)
            {
               result.add(url);
            }
         }
         catch (MalformedURLException e)
         {
            // log on debug level, because the JSF implementation should
            // handle such a case
            log.debug("Invalid entry in javax.faces.CONFIG_FILES init parameter: " + file);
         }

      }

      return result;
   }

   /**
    * Process a single <code>faces-config.xml</code> file and add all beans
    * found to the supplied list of {@link FacesConfigEntry} objects.
    *
    * @param url
    *           The faces-config.xml file
    * @param facesConfigEntries
    *           list of entries to add the beans to
    */
   private void processFacesConfig(URL url, List<FacesConfigEntry> facesConfigEntries)
   {

      // log name of current file
      if (log.isTraceEnabled())
      {
         log.trace("Loading bean names from: " + url.toString());
      }

      // setup digester
      Digester digester = new Digester();
     
      /*
       * We use the context class loader to resolve classes.
       * This fixes ClassNotFoundExceptions on Geronimo.
       */
      digester.setUseContextClassLoader(true);     

      // prevent downloading of DTDs
      digester.setEntityResolver(new EmptyEntityResolver());

      digester.setValidating(false);
      digester.push(facesConfigEntries);
      digester.addObjectCreate("faces-config/managed-bean", FacesConfigEntry.class);
      digester.addCallMethod("faces-config/managed-bean/managed-bean-name", "setName", 0);
      digester.addCallMethod("faces-config/managed-bean/managed-bean-class", "setBeanClass", 0);
      digester.addSetNext("faces-config/managed-bean", "add");

      // stream used to read faces-config.xml file
      InputStream stream = null;

      try
      {
         // open the file and let digester pares it
         stream = url.openStream();
         digester.parse(stream);

      }
      catch (IOException e)
      {
         // may be thrown when reading the file
         log.error("Failed to parse: " + url.toString(), e);
      }
      catch (SAXException e)
      {
         // parsing errors
         log.error("Failed to parse: " + url.toString(), e);
      }
      finally
      {
         // close stream
         if (stream != null)
         {
            try
            {
               stream.close();
            }
            catch (IOException e)
            {
               // ignore IOExceptions on close
            }

         }
      }

   }

   /*
    * Implementation if interface method
    */
   public String getBeanName(Class<?> clazz)
   {
      // first check bean name map containing faces-config.xml entries
      String name = beanNameMap.get(clazz.getName());
      if (name != null)
      {
         return name;
      }

      return null;
   }

   /**
    * Private class to hold values of single "managed-bean" entries
    */
   public static class FacesConfigEntry
   {

      private String name;

      private String beanClass;

      public String getName()
      {
         return name;
      }

      public void setName(String name)
      {
         this.name = name;
      }

      public String getBeanClass()
      {
         return beanClass;
      }

      public void setBeanClass(String beanClass)
      {
         this.beanClass = beanClass;
      }

   }

}
TOP

Related Classes of com.ocpsoft.pretty.faces.el.resolver.FacesConfigBeanNameResolver$FacesConfigEntry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.