You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ma...@apache.org on 2007/11/23 19:11:46 UTC
svn commit: r597709 - in /myfaces/core/trunk_1.2.x/impl/src:
main/java/org/apache/myfaces/config/
main/java/org/apache/myfaces/config/impl/digester/elements/
main/java/org/apache/myfaces/util/ main/java/org/apache/myfaces/webapp/
test/java/org/apache/m...
Author: matzew
Date: Fri Nov 23 10:11:45 2007
New Revision: 597709
URL: http://svn.apache.org/viewvc?rev=597709&view=rev
Log:
MYFACES-1693 - Make JSP 2.1 optional
Big thanks to Bernhard Huemer for making this patch
Added:
myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/util/ContainerUtils.java
myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/Jsp20FacesInitializer.java
myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/Jsp21FacesInitializer.java
myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/webapp/Jsp21FacesInitializerTest.java
Removed:
myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/DefaultFacesInitializer.java
myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/webapp/DefaultFacesInitializerTest.java
Modified:
myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/config/ManagedBeanBuilder.java
myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/config/impl/digester/elements/ManagedProperty.java
myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/MyFacesServlet.java
myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/StartupServletContextListener.java
Modified: myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/config/ManagedBeanBuilder.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/config/ManagedBeanBuilder.java?rev=597709&r1=597708&r2=597709&view=diff
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/config/ManagedBeanBuilder.java (original)
+++ myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/config/ManagedBeanBuilder.java Fri Nov 23 10:11:45 2007
@@ -32,7 +32,6 @@
import javax.faces.application.Application;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
-import javax.faces.webapp.UIComponentTag;
import javax.naming.NamingException;
import org.apache.commons.beanutils.PropertyUtils;
@@ -47,6 +46,7 @@
import org.apache.myfaces.config.element.MapEntries;
import org.apache.myfaces.config.element.MapEntry;
import org.apache.myfaces.shared_impl.util.ClassUtils;
+import org.apache.myfaces.util.ContainerUtils;
/**
@@ -498,7 +498,7 @@
MapEntry entry = (MapEntry) iterator.next();
Object key = entry.getKey();
- if (UIComponentTag.isValueReference((String) key))
+ if (ContainerUtils.isValueReference((String) key))
{
valueExpression = expFactory.createValueExpression(elContext, (String) key, Object.class);
key = valueExpression.getValue(elContext);
@@ -511,7 +511,7 @@
else
{
Object value = entry.getValue();
- if (UIComponentTag.isValueReference((String) value))
+ if (ContainerUtils.isValueReference((String) value))
{
valueExpression = expFactory.createValueExpression(elContext, (String) value, Object.class);
value = valueExpression.getValue(elContext);
@@ -539,7 +539,7 @@
else
{
Object value = entry.getValue();
- if (UIComponentTag.isValueReference((String) value))
+ if (ContainerUtils.isValueReference((String) value))
{
ValueExpression valueExpression = expFactory.createValueExpression(elContext, (String) value, Object.class);
value = valueExpression.getValue(elContext);
Modified: myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/config/impl/digester/elements/ManagedProperty.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/config/impl/digester/elements/ManagedProperty.java?rev=597709&r1=597708&r2=597709&view=diff
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/config/impl/digester/elements/ManagedProperty.java (original)
+++ myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/config/impl/digester/elements/ManagedProperty.java Fri Nov 23 10:11:45 2007
@@ -17,9 +17,9 @@
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
-import javax.faces.webapp.UIComponentTag;
import org.apache.myfaces.config.impl.digester.elements.ListEntries;
+import org.apache.myfaces.util.ContainerUtils;
/**
@@ -144,7 +144,7 @@
public boolean isValueReference()
{
- return UIComponentTag.isValueReference(_value);
+ return ContainerUtils.isValueReference(_value);
}
Added: myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/util/ContainerUtils.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/util/ContainerUtils.java?rev=597709&view=auto
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/util/ContainerUtils.java (added)
+++ myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/util/ContainerUtils.java Fri Nov 23 10:11:45 2007
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.myfaces.util;
+
+/**
+ * Utilities for determining the current container and for the unified
+ * expression language.
+ *
+ */
+public class ContainerUtils
+{
+ /**
+ * Determines whether we're running in a Servlet 2.5/JSP 2.1 environment.
+ *
+ * @return <code>true</code> if we're running in a JSP 2.1 environment,
+ * <code>false</code> otherwise
+ */
+ public static boolean isJsp21()
+ {
+ try
+ {
+ // simply check if the class JspApplicationContext is available
+ Class.forName("javax.servlet.jsp.JspApplicationContext");
+ return true;
+ }
+ catch (ClassNotFoundException ex)
+ {
+ ; // expected exception in a JSP 2.0 (or less) environment
+ }
+
+ return false;
+ }
+
+ /**
+ * Return true if the specified string contains an EL expression.
+ *
+ * <p>
+ * <strong>NOTICE</strong> This method is just a copy of
+ * {@link UIComponentTag#isValueReference(String)}, but it's required
+ * because the class UIComponentTag depends on a JSP 2.1 container
+ * (for example, it indirectly implements the interface JspIdConsumer)
+ * and therefore internal classes shouldn't access this class. That's
+ * also the reason why this method is inside the class ContainerUtils,
+ * because it allows MyFaces to be independent of a JSP 2.1 container.
+ * </p>
+ */
+ public static boolean isValueReference(String value)
+ {
+ if (value == null) {
+ throw new NullPointerException("value");
+ }
+
+ int start = value.indexOf("#{");
+ if (start < 0) {
+ return false;
+ }
+
+ int end = value.lastIndexOf('}');
+ return (end >=0 && start < end);
+ }
+}
Added: myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java?rev=597709&view=auto
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java (added)
+++ myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java Fri Nov 23 10:11:45 2007
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.myfaces.webapp;
+
+import java.util.List;
+
+import javax.el.ExpressionFactory;
+import javax.faces.context.ExternalContext;
+import javax.servlet.ServletContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.application.ApplicationImpl;
+import org.apache.myfaces.config.FacesConfigValidator;
+import org.apache.myfaces.config.FacesConfigurator;
+import org.apache.myfaces.config.RuntimeConfig;
+import org.apache.myfaces.context.servlet.ServletExternalContextImpl;
+import org.apache.myfaces.shared_impl.util.StateUtils;
+import org.apache.myfaces.shared_impl.webapp.webxml.WebXml;
+
+/**
+ * Performs common initialization tasks.
+ *
+ */
+public abstract class AbstractFacesInitializer implements FacesInitializer
+{
+ /**
+ * The logger instance for this class.
+ */
+ private static final Log log = LogFactory.getLog(AbstractFacesInitializer.class);
+
+ /**
+ * Performs all necessary initialization tasks like configuring this JSF
+ * application.
+ */
+ public void initFaces(ServletContext servletContext)
+ {
+ try {
+ if (log.isTraceEnabled()) {
+ log.trace("Initializing MyFaces");
+ }
+
+ // Some parts of the following configuration tasks have been implemented
+ // by using an ExternalContext. However, that's no problem as long as no
+ // one tries to call methods depending on either the ServletRequest or
+ // the ServletResponse.
+ ExternalContext externalContext = new ServletExternalContextImpl(
+ servletContext, null, null);
+
+ // Parse and validate the web.xml configuration file
+ WebXml webXml = WebXml.getWebXml(externalContext);
+ if (webXml == null) {
+ if (log.isWarnEnabled()) {
+ log.warn("Couldn't find the web.xml configuration file. "
+ + "Abort initializing MyFaces.");
+ }
+
+ return;
+ } else if (webXml.getFacesServletMappings().isEmpty()) {
+ if (log.isWarnEnabled()) {
+ log.warn("No mappings of FacesServlet found. Abort initializing MyFaces.");
+ }
+
+ return;
+ }
+
+ initContainerIntegration(servletContext, externalContext);
+
+ String useEncryption = servletContext.getInitParameter(StateUtils.USE_ENCRYPTION);
+ if (!"false".equals(useEncryption)) { // the default value is true
+ StateUtils.initSecret(servletContext);
+ }
+
+ if (log.isInfoEnabled()) {
+ log.info("ServletContext '" + servletContext.getRealPath("/") + "' initialized.");
+ }
+ } catch (Exception ex) {
+ log.error("An error occured while initializing MyFaces: "
+ + ex.getMessage(), ex);
+ }
+ }
+
+ /**
+ * Cleans up all remaining resources (well, theoretically).
+ *
+ */
+ public void destroyFaces(ServletContext servletContext)
+ {
+ // TODO is it possible to make a real cleanup?
+ }
+
+ /**
+ * Configures this JSF application. It's required that every
+ * FacesInitializer (i.e. every subclass) calls this method during
+ * initialization.
+ *
+ * @param servletContext
+ * the current ServletContext
+ * @param externalContext
+ * the current ExternalContext
+ * @param expressionFactory
+ * the ExpressionFactory to use
+ *
+ * @return the current runtime configuration
+ */
+ protected RuntimeConfig buildConfiguration(ServletContext servletContext,
+ ExternalContext externalContext, ExpressionFactory expressionFactory)
+ {
+ RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
+ runtimeConfig.setExpressionFactory(expressionFactory);
+
+ ApplicationImpl.setInitializingRuntimeConfig(runtimeConfig);
+
+ // And configure everything
+ new FacesConfigurator(externalContext).configure();
+
+ validateFacesConfig(servletContext, externalContext);
+
+ return runtimeConfig;
+ }
+
+ protected void validateFacesConfig(ServletContext servletContext, ExternalContext externalContext)
+ {
+ String validate = servletContext.getInitParameter(FacesConfigValidator.VALIDATE_CONTEXT_PARAM);
+ if ("true".equals(validate) && log.isWarnEnabled()) { // the default value is false
+ List<String> warnings = FacesConfigValidator.validate(
+ externalContext, servletContext.getRealPath("/"));
+
+ for (String warning : warnings) {
+ log.warn(warning);
+ }
+ }
+ }
+
+ /**
+ * Performs initialization tasks depending on the current environment.
+ *
+ * @param servletContext
+ * the current ServletContext
+ * @param externalContext
+ * the current ExternalContext
+ */
+ protected abstract void initContainerIntegration(
+ ServletContext servletContext, ExternalContext externalContext);
+
+}
Added: myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/Jsp20FacesInitializer.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/Jsp20FacesInitializer.java?rev=597709&view=auto
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/Jsp20FacesInitializer.java (added)
+++ myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/Jsp20FacesInitializer.java Fri Nov 23 10:11:45 2007
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.myfaces.webapp;
+
+import javax.el.ELContext;
+import javax.el.ExpressionFactory;
+import javax.el.MethodExpression;
+import javax.el.ValueExpression;
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import javax.servlet.ServletContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Initializes MyFaces in a JSP 2.0 (or less) environment.
+ *
+ */
+public class Jsp20FacesInitializer extends AbstractFacesInitializer
+{
+ /**
+ * The logger instance for this class.
+ */
+ private static final Log log = LogFactory.getLog(Jsp20FacesInitializer.class);
+
+ /**
+ * This parameter specifies the ExpressionFactory implementation to use.
+ */
+ private static final String EXPRESSION_FACTORY = "org.apache.myfaces.EXPRESSION_FACTORY";
+
+ /**
+ * The ExpressionFactory implementation of the EL-RI.
+ */
+ private static final String EL_RI_EXPRESSION_FACTORY_IMPL = "com.sun.el.ExpressionFactoryImpl";
+
+ /**
+ * Jasper's ExpressionFactory implementation.
+ */
+ private static final String JASPER_EL_EXPRESSION_FACTORY_IMPL = "org.apache.el.ExpressionFactoryImpl";
+
+ /**
+ * All known ExpressionFactory implementations.
+ */
+ private static final String[] KNOWN_EXPRESSION_FACTORIES =
+ new String[] { EL_RI_EXPRESSION_FACTORY_IMPL, JASPER_EL_EXPRESSION_FACTORY_IMPL };
+
+
+ @Override
+ protected void initContainerIntegration(
+ ServletContext servletContext, ExternalContext externalContext)
+ {
+ if (log.isInfoEnabled()) {
+ log.info("This application isn't running in a JSP 2.1 container.");
+ }
+
+ // It's possible to run MyFaces in a JSP 2.0 Container, but the user has to provide
+ // the ExpressionFactory implementation to use as there is no JspApplicationContext
+ // we could ask for. Having said that, though, the user only has to provide it, if
+ // there is no known ExpressionFactory available (i.e. if neither
+ // "com.sun.el.ExpressionFactoryImpl" nor "org.apache.el.ExpressionFactoryImpl"
+ // are available).
+ ExpressionFactory expressionFactory = null;
+
+ String expressionFactoryClassName = externalContext.getInitParameter(EXPRESSION_FACTORY);
+ if (expressionFactoryClassName != null
+ && expressionFactoryClassName.trim().length() > 0) {
+ if (log.isDebugEnabled()) {
+ log.debug("Attempting to load the ExpressionFactory implementation "
+ + "you've specified: '" + expressionFactoryClassName + "'.");
+ }
+
+ expressionFactory = loadExpressionFactory(expressionFactoryClassName);
+ }
+
+ if (expressionFactory == null) {
+ if (log.isInfoEnabled()) {
+ log.info("Either you haven't specified the ExpressionFactory implementation, or an "
+ + "error occured while instantiating the implementation you've specified. "
+ + "However, attempting to load a known implementation.");
+ }
+
+ expressionFactory = findExpressionFactory(KNOWN_EXPRESSION_FACTORIES);
+ if (expressionFactory == null) { // if we still haven't got a valid implementation
+ if (log.isErrorEnabled()) {
+ log.error("No valid ExpressionFactory implementation is available "
+ + "but that's required as this application isn't running in a JSP 2.1 container.");
+ }
+
+ // use a dummy implementation that reports the error again
+ expressionFactory = new ErrorExpressionFactory();
+ }
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("The following ExpressionFactory implementation will "
+ + "be used: '" + expressionFactory + "'.");
+ }
+
+ buildConfiguration(servletContext, externalContext, expressionFactory);
+ }
+
+ /**
+ * Loads and instantiates the given ExpressionFactory implementation.
+ *
+ * @param expressionFactoryClassName
+ * the class name of the ExpressionFactory implementation
+ *
+ * @return the newly created ExpressionFactory implementation, or
+ * <code>null</code>, if an error occurred
+ */
+ private static ExpressionFactory loadExpressionFactory(String expressionFactoryClassName)
+ {
+ try {
+ Class<?> expressionFactoryClass = Class.forName(expressionFactoryClassName);
+ return (ExpressionFactory) expressionFactoryClass.newInstance();
+ } catch (Exception ex) {
+ if (log.isDebugEnabled()) {
+ log.debug("An error occured while instantiating a new ExpressionFactory. "
+ + "Attempted to load class '" + expressionFactoryClassName + "'.", ex);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Attempts to find a valid ExpressionFactory implementation. Each of the
+ * given "ExpressionFactory implementation candidates" will be tried to
+ * instantiate. If an attempt succeeded, the ExpressionFactory implementation
+ * will be returned (i.e. the first valid ExpressionFactory implementation
+ * will be returned) and if no attempt succeeds, <code>null</code> will be
+ * returned.
+ *
+ * @param expressionFactoryClassNames
+ * "ExpresionFactory implementation candidates"
+ *
+ * @return the newly created ExpressionFactory implementation, or
+ * <code>null</code>, if there is no valid implementation
+ */
+ private static ExpressionFactory findExpressionFactory(String[] expressionFactoryClassNames)
+ {
+ for (String expressionFactoryClassName : expressionFactoryClassNames) {
+ ExpressionFactory expressionFactory =
+ loadExpressionFactory(expressionFactoryClassName);
+ if (expressionFactory != null) {
+ return expressionFactory;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Dummy implementation informing the user that there is no valid
+ * ExpressionFactory implementation available. This class makes it easier
+ * for the user to understand why the application crashes. Otherwise he
+ * would have to deal with NullPointerExceptions.
+ *
+ */
+ private class ErrorExpressionFactory extends ExpressionFactory
+ {
+
+ public Object coerceToType(Object obj, Class<?> targetType)
+ {
+ throw new FacesException("No valid ExpressionFactory implementation is available "
+ + "but that's required as this application isn't running in a JSP 2.1 container.");
+ }
+
+ public MethodExpression createMethodExpression(ELContext context,
+ String expression, Class<?> expectedReturnType, Class<?>[] expectedParamTypes)
+ {
+ throw new FacesException("No valid ExpressionFactory implementation is available "
+ + "but that's required as this application isn't running in a JSP 2.1 container.");
+ }
+
+ public ValueExpression createValueExpression(Object instance, Class<?> expectedType)
+ {
+ throw new FacesException("No valid ExpressionFactory implementation is available "
+ + "but that's required as this application isn't running in a JSP 2.1 container.");
+ }
+
+ public ValueExpression createValueExpression(
+ ELContext context, String expression, Class<?> expectedType)
+ {
+ throw new FacesException("No valid ExpressionFactory implementation is available "
+ + "but that's required as this application isn't running in a JSP 2.1 container.");
+ }
+
+ }
+
+}
Added: myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/Jsp21FacesInitializer.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/Jsp21FacesInitializer.java?rev=597709&view=auto
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/Jsp21FacesInitializer.java (added)
+++ myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/Jsp21FacesInitializer.java Fri Nov 23 10:11:45 2007
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.myfaces.webapp;
+
+import java.util.Iterator;
+
+import javax.faces.FactoryFinder;
+import javax.faces.context.ExternalContext;
+import javax.faces.event.PhaseListener;
+import javax.faces.lifecycle.LifecycleFactory;
+import javax.servlet.ServletContext;
+import javax.servlet.jsp.JspApplicationContext;
+import javax.servlet.jsp.JspFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.config.RuntimeConfig;
+import org.apache.myfaces.el.ResolverForJSPInitializer;
+import org.apache.myfaces.el.unified.ELResolverBuilder;
+import org.apache.myfaces.el.unified.ResolverBuilderForJSP;
+import org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver;
+import org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.Scope;
+
+/**
+ * Initializes MyFaces in a JSP 2.1 environment.
+ *
+ */
+public class Jsp21FacesInitializer extends AbstractFacesInitializer
+{
+ /**
+ * The logger instance for this class.
+ */
+ private static final Log log = LogFactory.getLog(Jsp21FacesInitializer.class);
+
+ /**
+ * Cached instance of the JspFactory to use.
+ */
+ private JspFactory jspFactory;
+
+ @Override
+ protected void initContainerIntegration(
+ ServletContext servletContext, ExternalContext externalContext)
+ {
+ JspApplicationContext appCtx =
+ getJspFactory().getJspApplicationContext(servletContext);
+ appCtx.addELContextListener(new FacesELContextListener());
+
+ RuntimeConfig runtimeConfig =
+ buildConfiguration(servletContext, externalContext, appCtx.getExpressionFactory());
+
+ // configure the el resolver for jsp
+ configureResolverForJSP(appCtx, runtimeConfig);
+ }
+
+ protected JspFactory getJspFactory()
+ {
+ if (jspFactory == null) {
+ // TODO: this Class.forName will be removed when Tomcat fixes a bug
+ // also, we should then be able to remove jasper.jar from the deployment
+ try {
+ Class.forName("org.apache.jasper.compiler.JspRuntimeContext");
+ } catch (ClassNotFoundException e) {
+ ; // ignore
+ } catch (Exception ex) {
+ log.debug("An unexpected exception occured "
+ + "while loading the JspRuntimeContext.", ex);
+ }
+
+ jspFactory = JspFactory.getDefaultFactory();
+ }
+
+ return jspFactory;
+ }
+
+ /**
+ * Sets the JspFactory to use. Currently, this method just simplifies
+ * testing.
+ *
+ * @param jspFactory
+ * the JspFactory to use
+ */
+ protected void setJspFactory(JspFactory jspFactory)
+ {
+ this.jspFactory = jspFactory;
+ }
+
+ /**
+ * Register a phase listener to every lifecycle. This listener will lazy fill the el resolver for jsp as soon as the
+ * first lifecycle is executed. This is necessarry to allow a faces application further setup after MyFaces has been
+ * initialized. When the first request is processed no further configuation of the el resolvers is allowed.
+ *
+ * @param appCtx
+ * @param runtimeConfig
+ */
+ private void configureResolverForJSP(JspApplicationContext appCtx, RuntimeConfig runtimeConfig)
+ {
+ FacesCompositeELResolver facesCompositeELResolver = new FacesCompositeELResolver(Scope.JSP);
+ appCtx.addELResolver(facesCompositeELResolver);
+ PhaseListener resolverForJSPInitializer = new ResolverForJSPInitializer(
+ createResolverBuilderForJSP(runtimeConfig), facesCompositeELResolver);
+
+ LifecycleFactory factory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
+ for (Iterator<String> iter = factory.getLifecycleIds(); iter.hasNext();)
+ {
+ factory.getLifecycle(iter.next()).addPhaseListener(resolverForJSPInitializer);
+ }
+ }
+
+ protected ELResolverBuilder createResolverBuilderForJSP(RuntimeConfig runtimeConfig)
+ {
+ return new ResolverBuilderForJSP(runtimeConfig);
+ }
+}
Modified: myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/MyFacesServlet.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/MyFacesServlet.java?rev=597709&r1=597708&r2=597709&view=diff
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/MyFacesServlet.java (original)
+++ myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/MyFacesServlet.java Fri Nov 23 10:11:45 2007
@@ -18,6 +18,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.shared_impl.webapp.webxml.DelegatedFacesServlet;
+import org.apache.myfaces.util.ContainerUtils;
import javax.faces.webapp.FacesServlet;
import javax.servlet.*;
@@ -42,8 +43,16 @@
{
if (_facesInitializer == null)
{
- _facesInitializer = new DefaultFacesInitializer();
+ if (ContainerUtils.isJsp21())
+ {
+ _facesInitializer = new Jsp21FacesInitializer();
+ }
+ else
+ {
+ _facesInitializer = new Jsp20FacesInitializer();
+ }
}
+
return _facesInitializer;
}
Modified: myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/StartupServletContextListener.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/StartupServletContextListener.java?rev=597709&r1=597708&r2=597709&view=diff
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/StartupServletContextListener.java (original)
+++ myfaces/core/trunk_1.2.x/impl/src/main/java/org/apache/myfaces/webapp/StartupServletContextListener.java Fri Nov 23 10:11:45 2007
@@ -23,6 +23,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.config.ManagedBeanBuilder;
+import org.apache.myfaces.util.ContainerUtils;
import javax.faces.FactoryFinder;
import javax.servlet.ServletContext;
@@ -67,8 +68,16 @@
{
if (_facesInitializer == null)
{
- _facesInitializer = new DefaultFacesInitializer();
+ if (ContainerUtils.isJsp21())
+ {
+ _facesInitializer = new Jsp21FacesInitializer();
+ }
+ else
+ {
+ _facesInitializer = new Jsp20FacesInitializer();
+ }
}
+
return _facesInitializer;
}
Added: myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/webapp/Jsp21FacesInitializerTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/webapp/Jsp21FacesInitializerTest.java?rev=597709&view=auto
==============================================================================
--- myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/webapp/Jsp21FacesInitializerTest.java (added)
+++ myfaces/core/trunk_1.2.x/impl/src/test/java/org/apache/myfaces/webapp/Jsp21FacesInitializerTest.java Fri Nov 23 10:11:45 2007
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.myfaces.webapp;
+
+import junit.framework.TestCase;
+import org.apache.myfaces.config.RuntimeConfig;
+import org.apache.myfaces.el.DefaultPropertyResolver;
+import org.apache.myfaces.el.VariableResolverImpl;
+import org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver;
+import static org.easymock.EasyMock.*;
+import org.easymock.IAnswer;
+import org.easymock.classextension.EasyMock;
+import org.easymock.classextension.IMocksControl;
+
+import javax.el.ExpressionFactory;
+import javax.faces.webapp.FacesServlet;
+import javax.servlet.ServletContext;
+import javax.servlet.jsp.JspApplicationContext;
+import javax.servlet.jsp.JspFactory;
+
+/**
+ * @author Mathias Broekelmann (latest modification by $Author: baranda $)
+ * @version $Revision: 532019 $ $Date: 2007-04-24 19:34:36 +0200 (Di, 24 Apr 2007) $
+ */
+public class Jsp21FacesInitializerTest extends TestCase
+{
+
+ /**
+ * Test method for {@link org.apache.myfaces.webapp.DefaultFacesInitializer#initFaces(javax.servlet.ServletContext)}.
+ * @throws Exception
+ */
+ public void testInitFaces() throws Exception
+ {
+ Jsp21FacesInitializer initializer = new Jsp21FacesInitializer();
+ IMocksControl control = EasyMock.createControl();
+
+ JspFactory jspFactory = control.createMock(JspFactory.class);
+ initializer.setJspFactory(jspFactory);
+
+ RuntimeConfig runtimeConfig = control.createMock(RuntimeConfig.class);
+
+ ServletContext context = control.createMock(ServletContext.class);
+ ExpressionFactory expressionFactory = control.createMock(ExpressionFactory.class);
+ runtimeConfig.setExpressionFactory(expressionFactory);
+ runtimeConfig.setPropertyResolverChainHead(isA(DefaultPropertyResolver.class));
+ runtimeConfig.setVariableResolverChainHead(isA(VariableResolverImpl.class));
+
+ expect(context.getAttribute(eq(RuntimeConfig.class.getName()))).andReturn(runtimeConfig).anyTimes();
+
+ expect(context.getInitParameter(eq(FacesServlet.CONFIG_FILES_ATTR))).andReturn(null);
+ expect(context.getResourceAsStream(eq("/WEB-INF/faces-config.xml"))).andReturn(null);
+ expect(context.getInitParameter(eq(FacesServlet.LIFECYCLE_ID_ATTR))).andReturn(null);
+
+ // TODO: add myfaces specific tests
+ expect(context.getResource(isA(String.class))).andReturn(null);
+ expect(context.getResourceAsStream(isA(String.class))).andReturn(null);
+ expect(context.getInitParameter(isA(String.class))).andReturn(null).anyTimes();
+ expect(context.getAttribute(isA(String.class))).andReturn(null).anyTimes();
+ context.setAttribute(isA(String.class), anyObject());
+ expectLastCall().anyTimes();
+ expect(context.getRealPath(isA(String.class))).andAnswer(new IAnswer<String>() {
+ public String answer() throws Throwable
+ {
+ return (String) org.easymock.EasyMock.getCurrentArguments()[0];
+ }
+ });
+
+ JspApplicationContext jspAppCtx = control.createMock(JspApplicationContext.class);
+ expect(jspAppCtx.getExpressionFactory()).andReturn(expressionFactory);
+ jspAppCtx.addELContextListener(isA(FacesELContextListener.class));
+ expect(jspFactory.getJspApplicationContext(eq(context))).andReturn(jspAppCtx);
+ jspAppCtx.addELResolver(isA(FacesCompositeELResolver.class));
+
+ control.replay();
+ initializer.initFaces(context);
+
+ // In MYFACES-1222: The Jsp21FacesInitializer isn't practicable anymore.
+ // The ServletContext-Mock won't return its WebXml instance, so Jsp21FacesInitializer will stop initializing.
+ // This is why the next line is commented:
+
+ //control.verify();
+ }
+
+}