Package org.ajax4jsf.webapp

Source Code of org.ajax4jsf.webapp.WebXml

/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
*/

package org.ajax4jsf.webapp;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.ajax4jsf.Messages;
import org.apache.commons.digester.Digester;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.richfaces.VersionBean;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.LocatorImpl;

/**
* Parse at startup application web.xml and store servlet and filter mappings.
* at runtime, used for convert resource key to uri, and vice versa.
*
* @author asmirnov@exadel.com (latest modification by $Author: alexsmirnov $)
* @version $Revision: 1.1.2.1 $ $Date: 2007/01/09 18:58:59 $
*
*/
public class WebXml implements Serializable {

  public static final String CONTEXT_ATTRIBUTE = WebXml.class.getName();

  /**
   *
   */
  private static final long serialVersionUID = -9042908418843695017L;

  private static final Log _log = LogFactory.getLog(WebXml.class);

  static final String WEB_XML = "/WEB-INF/web.xml";

  public static final String RESOURCE_URI_PREFIX = "a4j_"
      + VersionBean.MAJOR_VERSION + "_" + VersionBean.MINOR_VERSION + "_"
      + VersionBean.REVISION;

  static final String RESOURCE_URI_PREFIX_WITH_SLASH = "/"
      + RESOURCE_URI_PREFIX;

  public static final String RESOURCE_URI_PREFIX_PARAM = "org.ajax4jsf.RESOURCE_URI_PREFIX";

  /**
   * Prefix for Resourse-Ajax filter, in common must be same as for
   * {@link javax.faces.webapp.FacesServlet}
   */
  private String _facesFilterPrefix = null;

  /**
   * Suffix for Resource-Ajax filter , in common must be same as for
   * {@link javax.faces.webapp.FacesServlet}
   */
  private String _facesFilterSuffix = null;

  private String _facesServletPrefix = null;

  private String _facesServletSuffix = null;

  private boolean _prefixMapping = false;

  private String _filterName;

  private Map _servlets = new HashMap();

  private Map _filters = new HashMap();

  /**
   * Prefix for resources handled by Chameleon framework.
   */
  private String _resourcePrefix = RESOURCE_URI_PREFIX_WITH_SLASH;

  /**
   * Parse application web.xml configuration and detect mapping for resources
   * and logs.
   *
   * @param context
   * @param filterName
   * @throws ServletException
   */
  public void init(ServletContext context, String filterName)
      throws ServletException {
    InputStream webXml = context.getResourceAsStream(WEB_XML);
    if (null == webXml) {
      throw new ServletException(Messages.getMessage(
          Messages.GET_RESOURCE_AS_STREAM_ERROR, WEB_XML));
    }
    Digester dig = new Digester();
    dig.setDocumentLocator(new LocatorImpl());
    // Disable xml validations at all - web.xml already validated by
    // container
    dig.setValidating(false);
    dig.setEntityResolver(new EntityResolver() {
      // Dummi resolver - alvays do nothing
      public InputSource resolveEntity(String publicId, String systemId)
          throws SAXException, IOException {
        return new InputSource(new StringReader(""));
      }

    });
    dig.setNamespaceAware(false);
    // dig.setUseContextClassLoader(true);
    dig.setClassLoader(this.getClass().getClassLoader());
    // Parsing rules.
    // Servlets.
    String path = "web-app/servlet";
    dig.addObjectCreate(path, ServletBean.class);
    dig.addBeanPropertySetter(path + "/servlet-name", "servletName");
    dig.addBeanPropertySetter(path + "/servlet-class", "servletClass");
    dig.addBeanPropertySetter(path + "/display-name", "displayName");
    dig.addBeanPropertySetter(path + "/description");
    dig.addSetNext(path, "addServlet");
    // Filters
    path = "web-app/filter";
    dig.addObjectCreate(path, FilterBean.class);
    dig.addBeanPropertySetter(path + "/filter-name", "filterName");
    dig.addBeanPropertySetter(path + "/filter-class", "filterClass");
    dig.addBeanPropertySetter(path + "/display-name", "displayName");
    dig.addBeanPropertySetter(path + "/description");
    dig.addSetNext(path, "addFilter");
    // Servlet mappings
    path = "web-app/servlet-mapping";
    dig.addCallMethod(path, "addServletMapping", 2);
    dig.addCallParam(path + "/servlet-name", 0);
    dig.addCallParam(path + "/url-pattern", 1);
    // Filter mappings
    // TODO - parse dispatcher.
    path = "web-app/filter-mapping";
    dig.addCallMethod(path, "addFilterMapping", 3);
    dig.addCallParam(path + "/filter-name", 0);
    dig.addCallParam(path + "/url-pattern", 1);
    dig.addCallParam(path + "/servlet-name", 2);
    dig.push(this);
    try {
      dig.parse(webXml);
      this.setFilterName(filterName, context);
      this.findFacesServlet(context);
      // Store Instance to context attribute.
      context.setAttribute(CONTEXT_ATTRIBUTE, this);
    } catch (IOException e) {
      String message = Messages
          .getMessage(Messages.PARSING_WEB_XML_IO_ERROR);
      _log.error(message, e);
      throw new ServletException(message, e);
    } catch (SAXException e) {
      String message = Messages
          .getMessage(Messages.PARSING_WEB_XML_SAX_ERROR);
      _log.error(message, e);
      throw new ServletException(message, e);
    } finally {
      try {
        webXml.close();
      } catch (IOException e) {
        // this exception don't affect any aspects of work and can be
        // ignored.
      }
    }
  }

  private void findFacesServlet(ServletContext context) {
    for (Iterator servletsIterator = _servlets
        .entrySet().iterator(); servletsIterator.hasNext();) {
      Entry servletEntry = (Entry)servletsIterator.next();
      String servletClass = ((ServletBean)servletEntry.getValue()).getServletClass();
      if("javax.faces.webapp.FacesServlet".equals(servletClass)){
        Mapping mapping = checkMapping(((ServletBean)servletEntry.getValue()).getMappings());
        if(null != mapping){
          this._facesServletPrefix = mapping.getPrefix();
          this._facesServletSuffix = mapping.getSuffix();
        }
      }
    }

  }

  public void addServlet(ServletBean bean) {
    String name = bean.getServletName();
    if (null != name) {
      _servlets.put(name, bean);
    }
  }

  public void addFilter(FilterBean bean) {
    String name = bean.getFilterName();
    if (null != name) {
      _filters.put(name, bean);
    }

  }

  public void addServletMapping(String servletName, String mapping) {
    ServletBean servletBean = (ServletBean) _servlets.get(servletName);
    if (null != servletBean) {
      (servletBean).addMapping(mapping);
    }
  }

  public void addFilterMapping(String filterName, String mapping,
      String servlet) {
    FilterBean filterBean = (FilterBean) _filters.get(filterName);
    if (null != filterBean) {
      if (null != mapping) {
        (filterBean).addMapping(mapping);
      }
      if (null != servlet) {
        (filterBean).addServlet(servlet);
      }
    }
  }

  /**
   * Convert {@link org.ajax4jsf.resource.InternetResource } key to real URL
   * for handle by chameleon filter, depend of mapping in WEB.XML . For prefix
   * or * mapping, prepend servlet prefix and default Resource prefix to key.
   * For suffix mapping, prepend with resource prefix and append default faces
   * suffix to URL ( before request param ). After conversion, call
   * {@link javax.faces.application.ViewHandler#getResourceURL(javax.faces.context.FacesContext, java.lang.String)}
   * and
   * {@link javax.faces.context.ExternalContext#encodeResourceURL(java.lang.String)} .
   *
   * @param context
   * @param Url
   * @return
   */
  public String getFacesResourceURL(FacesContext context, String Url) {
    StringBuffer buf = new StringBuffer();
    buf.append(getResourcePrefix()).append(Url);
    // Insert suffix mapping
    if (isPrefixMapping()) {
      buf.insert(0, getFacesFilterPrefix());
    } else {
      int index;
      if ((index = buf.indexOf("?")) >= 0) {
        buf.insert(index, getFacesFilterSuffix());
      } else {
        buf.append(getFacesFilterSuffix());
      }
    }
    String resourceURL = context.getApplication().getViewHandler()
        .getResourceURL(context, buf.toString());
    return resourceURL;

  }

  /**
   * Detect request to resource and extract key from request
   *
   * @param request
   *            current http request
   * @return resource key, or null for ordinary faces request.
   */
  public String getFacesResourceKey(HttpServletRequest request) {
    String resourcePath = request.getRequestURI().substring(
        request.getContextPath().length());// isPrefixMapping()?request.getPathInfo():request.getServletPath();
    // Remove JSESSIONID - for expired sessions it will merged to path.
    int jsesionidStart;
    if ((jsesionidStart = resourcePath.lastIndexOf(";jsessionid")) >= 0) {
      resourcePath = resourcePath.substring(0, jsesionidStart);
    }
    if (isPrefixMapping()) {
      if (resourcePath.startsWith(getFacesFilterPrefix()
          + getResourcePrefix())) {
        return resourcePath.substring(getFacesFilterPrefix().length()
            + getResourcePrefix().length());
      }
    } else if (resourcePath.startsWith(getResourcePrefix())) {
      return resourcePath.substring(getResourcePrefix().length(),
          resourcePath.length() - getFacesFilterSuffix().length());
    }
    return null;
  }

  /**
   * Detect request to {@link javax.faces.webapp.FacesServlet}
   *
   * @param request
   * @return true if request parsed to JSF.
   */
  public boolean isFacesRequest(HttpServletRequest request) {
    // String resourcePath =
    // request.getRequestURI().substring(request.getContextPath().length());//isPrefixMapping()?request.getPathInfo():request.getServletPath();
    // if(isPrefixMapping() ) {
    // if (resourcePath.startsWith(getFacesFilterPrefix())) {
    // return true;
    // }
    // } else if (resourcePath.endsWith(getFacesFilterSuffix())) {
    // return true;
    // }
    // return false;
    return true;
  }

  /**
   * @return Returns the facesFilterPrefix.
   */
  public String getFacesFilterPrefix() {
    return _facesFilterPrefix;
  }

  /**
   * @param facesFilterPrefix
   *            The facesFilterPrefix to set.
   */
  void setFacesFilterPrefix(String facesFilterPrefix) {
    _facesFilterPrefix = facesFilterPrefix;
  }

  /**
   * @return Returns the facesFilterSuffix.
   */
  public String getFacesFilterSuffix() {
    return _facesFilterSuffix;
  }

  /**
   * @param facesFilterSuffix
   *            The facesFilterSuffix to set.
   */
  void setFacesFilterSuffix(String facesFilterSuffix) {
    _facesFilterSuffix = facesFilterSuffix;
  }

  /**
   * @return Returns the resourcePrefix.
   */
  public String getResourcePrefix() {
    return _resourcePrefix;
  }

  /**
   * @param resourcePrefix
   *            The resourcePrefix to set.
   */
  void setResourcePrefix(String resourcePrefix) {
    _resourcePrefix = resourcePrefix;
  }

  /**
   * @return Returns the filterName.
   */
  public String getFilterName() {
    return _filterName;
  }

  /**
   * After parsing web.xml set chameleon filter name, for wich we must
   * calculate mappings for resources, logs etc.
   *
   * @param filterName
   *            The filterName to set.
   * @param context
   *            TODO
   */
  void setFilterName(String filterName, ServletContext context) {
    if (null == filterName) {
      _log.warn(Messages.getMessage(Messages.NULL_FILTER_NAME_WARNING));
      return;
    }
    _filterName = filterName.trim();
    // get config for this filter
    FilterBean filter = (FilterBean) _filters.get(_filterName);
    if (null == filter) {
      _log.warn(Messages.getMessage(Messages.FILTER_NOT_FOUND_ERROR,
          _filterName));
      throw new IllegalStateException(Messages.getMessage(
          Messages.FILTER_NOT_FOUND_ERROR, filterName));
    }
    // find faces servlet
    Mapping mapping = checkMapping(filter.getMappings());
    // Filter mapped only to servlet.
    if (null == mapping) {
      for (Iterator sevlets = filter.getServlets().iterator(); sevlets
          .hasNext()
          && _facesFilterPrefix == null && _facesFilterSuffix == null;) {
        String servletname = (String) sevlets.next();
        ServletBean servlet = (ServletBean) _servlets.get(servletname);
        if (null != servlet) {
          mapping = checkMapping(servlet.getMappings());
        }
      }
    }
    if (null != mapping) {
      setFacesFilterPrefix(mapping.getPrefix());
      setFacesFilterSuffix(mapping.getSuffix());
    } else {
      throw new IllegalStateException(Messages.getMessage(
          Messages.NO_PREFIX_OR_SUFFIX_IN_FILTER_MAPPING_ERROR,
          filterName));
    }
    String resourcePrefix = (String) context
        .getInitParameter(RESOURCE_URI_PREFIX_PARAM);
    if (null == resourcePrefix) {
      resourcePrefix = RESOURCE_URI_PREFIX;
    }
    if (null != _facesFilterPrefix) {
      _prefixMapping = true;
      if (_facesFilterPrefix.endsWith("/")) {
        setResourcePrefix(resourcePrefix);
      } else {
        setResourcePrefix("/" + resourcePrefix);
      }
    } else if (null != _facesFilterSuffix) {
      _prefixMapping = false;
      setResourcePrefix("/" + resourcePrefix);
    }
  }

  private Mapping checkMapping(Set mappings) {
    Mapping mapping = null;
    if (null != mappings) {
      for (Iterator iter = mappings.iterator(); iter.hasNext();) {
        String mappingPattern = (String) iter.next();
        // first test - for prefix, like /xxx/*
        // TODO - select correct dispatcher.
        if (mappingPattern.endsWith("*")) {
          if (null == mapping) {
            mapping = new Mapping();
          }
          int cut = mappingPattern.endsWith("/*")?2:1;
          mapping.setPrefix(mappingPattern.substring(0,
              mappingPattern.length() - cut));
          break;
        } else
        // test for suffix mapping, eg *.xxx
        if (mappingPattern.startsWith("*")) {
          if (null == mapping) {
            mapping = new Mapping();
          }
          mapping.setSuffix(mappingPattern.substring(1));
        } else {
          // Fixed mapping - do not use it.
        }
      }
    }
    return mapping;
  }

  /**
   * @return Returns the prefixMapping.
   */
  public boolean isPrefixMapping() {
    return _prefixMapping;
  }

  private static class Mapping {
    private String prefix;
    private String suffix;

    /**
     * @return the prefix
     */
    public String getPrefix() {
      return prefix;
    }

    /**
     * @param prefix
     *            the prefix to set
     */
    public void setPrefix(String prefix) {
      this.prefix = prefix;
    }

    /**
     * @return the suffix
     */
    public String getSuffix() {
      return suffix;
    }

    /**
     * @param suffix
     *            the suffix to set
     */
    public void setSuffix(String suffix) {
      this.suffix = suffix;
    }
  }

  /**
   * @return the facesServletPrefix
   */
  public String getFacesServletPrefix() {
    return _facesServletPrefix;
  }

  /**
   * @return the facesServletSuffix
   */
  public String getFacesServletSuffix() {
    return _facesServletSuffix;
  }
}
TOP

Related Classes of org.ajax4jsf.webapp.WebXml

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.