You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sl...@apache.org on 2009/07/30 00:42:40 UTC
svn commit: r799109 [1/2] - in
/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view: ./
facelets/ facelets/impl/ jsp/
Author: slessard
Date: Wed Jul 29 22:42:40 2009
New Revision: 799109
URL: http://svn.apache.org/viewvc?rev=799109&view=rev
Log:
Added some Facelet VDL integration code. Missing 3 methods and renderView should probably be revisited.
Added:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewMetadataBase.java
- copied, changed from r798745, myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewMetadataImpl.java
Removed:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewMetadataImpl.java
Modified:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageBase.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageFactoryImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguageStrategy.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletFactory.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/jsp/JspViewDeclarationLanguage.java
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageBase.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageBase.java?rev=799109&r1=799108&r2=799109&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageBase.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageBase.java Wed Jul 29 22:42:40 2009
@@ -18,40 +18,13 @@
*/
package org.apache.myfaces.view;
-import java.beans.BeanDescriptor;
-import java.beans.BeanInfo;
-import java.beans.PropertyDescriptor;
-import java.util.List;
-
-import javax.el.ExpressionFactory;
-import javax.el.MethodExpression;
-import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.application.ViewHandler;
-import javax.faces.component.ActionSource2;
-import javax.faces.component.EditableValueHolder;
-import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
-import javax.faces.event.ActionEvent;
-import javax.faces.event.MethodExpressionActionListener;
-import javax.faces.event.MethodExpressionValueChangeListener;
-import javax.faces.event.ValueChangeEvent;
-import javax.faces.validator.MethodExpressionValidator;
-import javax.faces.view.ActionSource2AttachedObjectHandler;
-import javax.faces.view.ActionSource2AttachedObjectTarget;
-import javax.faces.view.AttachedObjectHandler;
-import javax.faces.view.AttachedObjectTarget;
-import javax.faces.view.EditableValueHolderAttachedObjectHandler;
-import javax.faces.view.EditableValueHolderAttachedObjectTarget;
-import javax.faces.view.ValueHolderAttachedObjectHandler;
-import javax.faces.view.ValueHolderAttachedObjectTarget;
import javax.faces.view.ViewDeclarationLanguage;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.application.InvalidViewIdException;
-import org.apache.myfaces.application.ViewHandlerImpl;
/**
* @author Simon Lessard (latest modification by $Author: slessard $)
@@ -76,6 +49,7 @@
try
{
viewId = calculateViewId(context, viewId);
+
Application application = context.getApplication();
// Create a new UIViewRoot object instance using Application.createComponent(UIViewRoot.COMPONENT_TYPE).
@@ -114,10 +88,55 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public UIViewRoot restoreView(FacesContext context, String viewId)
+ {
+ checkNull(context, "context");
+ checkNull(viewId, "viewId");
+
+ Application application = context.getApplication();
+
+ ViewHandler applicationViewHandler = application.getViewHandler();
+
+ String renderKitId = applicationViewHandler.calculateRenderKitId(context);
+
+ UIViewRoot viewRoot = application.getStateManager().restoreView(context, viewId, renderKitId);
+
+ return viewRoot;
+ }
+
+ /**
+ * Calculates the effective view identifier for the specified raw view identifier.
+ *
+ * @param context le current FacesContext
+ * @param viewId the raw view identifier
+ *
+ * @return the effective view identifier
+ */
protected abstract String calculateViewId(FacesContext context, String viewId);
+ /**
+ * Send a source not found to the client. Although it can be considered ok in JSP mode,
+ * I think it's pretty lame to have this kind of requirement at VDL level considering VDL
+ * represents the page --> JSF tree link, not the transport layer required to send a
+ * SC_NOT_FOUND.
+ *
+ * @param context le current FacesContext
+ * @param message the message associated with the error
+ */
protected abstract void sendSourceNotFound(FacesContext context, String message);
-
+
+ /**
+ * Check if the specified value of a param is <code>null</code>.
+ *
+ * @param o the parameter's value
+ * @param param the parameter's name
+ *
+ * @throws NullPointerException if the value is <code>null</code>
+ */
protected void checkNull(final Object o, final String param)
{
if (o == null)
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageFactoryImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageFactoryImpl.java?rev=799109&r1=799108&r2=799109&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageFactoryImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewDeclarationLanguageFactoryImpl.java Wed Jul 29 22:42:40 2009
@@ -61,6 +61,9 @@
throw new NullPointerException("viewId");
}
+ // TODO: It would be nice to be able to preinitialize the factory. However, since it requires
+ // access to the ExternalContext it may not be possible, depending on the loading order
+ // in the FactoryFinder. Could use ideas here. -= SL =-
initialize();
for (ViewDeclarationLanguageStrategy strategy : _supportedLanguages)
@@ -71,10 +74,12 @@
}
}
- // FIXME: Notify EG - Cannot throw undeclared ClassNotFoundException like the spec requires
- throw new FacesException(new ClassNotFoundException("Cannot find a valid PDL for view id " + viewId));
+ throw new FacesException("Cannot find a valid PDL for view id " + viewId);
}
+ /**
+ * Initialize the supported view declaration languages.
+ */
private void initialize()
{
if (!_initialized)
@@ -87,6 +92,7 @@
}
else
{
+ // Support JSP only
_supportedLanguages = new ViewDeclarationLanguageStrategy[1];
_supportedLanguages[0] = new JspViewDeclarationLanguageStrategy();
}
@@ -95,12 +101,19 @@
}
}
+ /**
+ * Determines if the current application uses Facelets.
+ *
+ * @return <code>true</code> if the current application uses Facelets, <code>false</code>
+ * otherwise.
+ */
private boolean isFaceletsEnabled()
{
FacesContext context = FacesContext.getCurrentInstance();
String param = context.getExternalContext().getInitParameter(PARAM_DISABLE_JSF_FACELET);
if (param == null)
{
+ // Facelets is supported by default
return true;
}
else
Copied: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewMetadataBase.java (from r798745, myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewMetadataImpl.java)
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewMetadataBase.java?p2=myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewMetadataBase.java&p1=myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewMetadataImpl.java&r1=798745&r2=799109&rev=799109&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewMetadataImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/ViewMetadataBase.java Wed Jul 29 22:42:40 2009
@@ -18,35 +18,26 @@
*/
package org.apache.myfaces.view;
-import javax.faces.component.UIViewRoot;
-import javax.faces.context.FacesContext;
import javax.faces.view.ViewMetadata;
/**
* This class represents the default implementation of javax.faces.view.ViewMetaData.
*/
-
-public class ViewMetadataImpl extends ViewMetadata
+public abstract class ViewMetadataBase extends ViewMetadata
{
- private String viewID;
-
- public ViewMetadataImpl (String viewID)
- {
- this.viewID = viewID;
- }
-
- @Override
- public UIViewRoot createMetadataView (FacesContext context)
+ private String _viewId;
+
+ public ViewMetadataBase(String viewId)
{
- // TODO implement. This will require supporting Facelet parser/compiler logic
- // to extract metadata.
-
- return null;
+ _viewId = viewId;
}
+ /**
+ * {@inheritDoc}
+ */
@Override
- public String getViewId ()
+ public String getViewId()
{
- return this.viewID;
+ return _viewId;
}
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java?rev=799109&r1=799108&r2=799109&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java Wed Jul 29 22:42:40 2009
@@ -18,48 +18,26 @@
*/
package org.apache.myfaces.view.facelets;
-import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
-import java.beans.PropertyDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Writer;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Map;
-import java.util.logging.Level;
import javax.el.ELException;
-import javax.el.ExpressionFactory;
-import javax.el.MethodExpression;
-import javax.el.ValueExpression;
import javax.faces.FacesException;
+import javax.faces.application.Application;
+import javax.faces.application.ProjectStage;
import javax.faces.application.Resource;
import javax.faces.application.StateManager;
import javax.faces.application.ViewHandler;
-import javax.faces.component.ActionSource2;
-import javax.faces.component.EditableValueHolder;
-import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
-import javax.faces.event.ActionEvent;
-import javax.faces.event.MethodExpressionActionListener;
-import javax.faces.event.MethodExpressionValueChangeListener;
-import javax.faces.event.ValueChangeEvent;
import javax.faces.render.RenderKit;
-import javax.faces.validator.MethodExpressionValidator;
-import javax.faces.view.ActionSource2AttachedObjectHandler;
-import javax.faces.view.ActionSource2AttachedObjectTarget;
-import javax.faces.view.AttachedObjectHandler;
-import javax.faces.view.AttachedObjectTarget;
-import javax.faces.view.EditableValueHolderAttachedObjectHandler;
-import javax.faces.view.EditableValueHolderAttachedObjectTarget;
import javax.faces.view.StateManagementStrategy;
-import javax.faces.view.ValueHolderAttachedObjectHandler;
-import javax.faces.view.ValueHolderAttachedObjectTarget;
import javax.faces.view.ViewMetadata;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@@ -70,7 +48,7 @@
import org.apache.myfaces.application.DefaultViewHandlerSupport;
import org.apache.myfaces.application.ViewHandlerSupport;
import org.apache.myfaces.view.ViewDeclarationLanguageBase;
-import org.apache.myfaces.view.ViewMetadataImpl;
+import org.apache.myfaces.view.ViewMetadataBase;
import org.apache.myfaces.view.facelets.FaceletViewHandler.NullWriter;
import org.apache.myfaces.view.facelets.compiler.Compiler;
import org.apache.myfaces.view.facelets.compiler.SAXCompiler;
@@ -79,7 +57,6 @@
import org.apache.myfaces.view.facelets.impl.DefaultResourceResolver;
import org.apache.myfaces.view.facelets.impl.ResourceResolver;
import org.apache.myfaces.view.facelets.tag.TagDecorator;
-import org.apache.myfaces.view.facelets.tag.TagLibrary;
import org.apache.myfaces.view.facelets.tag.ui.UIDebug;
import org.apache.myfaces.view.facelets.util.DevTools;
import org.apache.myfaces.view.facelets.util.ReflectionUtil;
@@ -89,245 +66,61 @@
*
* @author Simon Lessard (latest modification by $Author: slessard $)
* @version $Revision: 696523 $ $Date: 2009-03-21 14:57:08 -0400 (mer., 17 sept. 2008) $
- *
+ *
* @since 2.0
*/
public class FaceletViewDeclarationLanguage extends ViewDeclarationLanguageBase
{
- private ViewHandlerSupport _cachedViewHandlerSupport;
private static final Log log = LogFactory.getLog(FaceletViewDeclarationLanguage.class);
-
- private FaceletFactory faceletFactory;
- public final static long DEFAULT_REFRESH_PERIOD = 2;
+ public static final String CHARACTER_ENCODING_KEY = "javax.faces.request.charset";
- public final static String PARAM_REFRESH_PERIOD = "facelets.REFRESH_PERIOD";
+ public final static long DEFAULT_REFRESH_PERIOD = 2;
- public final static String PARAM_SKIP_COMMENTS = "facelets.SKIP_COMMENTS";
+ public final static String DEFAULT_CHARACTER_ENCODING = "UTF-8";
- public final static String PARAM_VIEW_MAPPINGS = "facelets.VIEW_MAPPINGS";
+ public final static String PARAM_BUFFER_SIZE = "facelets.BUFFER_SIZE";
- public final static String PARAM_LIBRARIES = "facelets.LIBRARIES";
+ public final static String PARAM_BUILD_BEFORE_RESTORE = "facelets.BUILD_BEFORE_RESTORE";
public final static String PARAM_DECORATORS = "facelets.DECORATORS";
- public final static String PARAM_DEVELOPMENT = "facelets.DEVELOPMENT";
+ public final static String PARAM_ENCODING = "facelets.Encoding";
+
+ public final static String PARAM_LIBRARIES = "facelets.LIBRARIES";
+
+ public final static String PARAM_REFRESH_PERIOD = "facelets.REFRESH_PERIOD";
public final static String PARAM_RESOURCE_RESOLVER = "facelets.RESOURCE_RESOLVER";
- public final static String PARAM_BUILD_BEFORE_RESTORE = "facelets.BUILD_BEFORE_RESTORE";
+ public final static String PARAM_SKIP_COMMENTS = "facelets.SKIP_COMMENTS";
- public final static String PARAM_BUFFER_SIZE = "facelets.BUFFER_SIZE";
+ public final static String PARAM_VIEW_MAPPINGS = "facelets.VIEW_MAPPINGS";
private final static String STATE_KEY = "~facelets.VIEW_STATE~";
private final static int STATE_KEY_LEN = STATE_KEY.length();
- private final ViewHandler parent;
-
- private boolean developmentMode = false;
+ private int _bufferSize;
- private boolean buildBeforeRestore = false;
+ private boolean _buildBeforeRestore = false;
- private int bufferSize;
+ private ViewHandlerSupport _cachedViewHandlerSupport;
- private String defaultSuffix;
+ private String _defaultSuffix;
- // Array of viewId extensions that should be handled by Facelets
- private String[] extensionsArray;
+ private FaceletFactory _faceletFactory;
- // Array of viewId prefixes that should be handled by Facelets
- private String[] prefixesArray;
-
private StateManagementStrategy stateMgmtStrategy;
-
- /**
- *
- */
- public FaceletViewDeclarationLanguage(ViewHandler parent)
- {
- this.parent = parent;
- }
-
- /**
- * Initialize the ViewHandler during its first request.
- */
- protected void initialize(FacesContext context)
- {
- synchronized (this)
- {
- if (this.faceletFactory == null)
- {
- log.trace("Initializing");
- Compiler c = this.createCompiler();
- this.initializeCompiler(c);
- this.faceletFactory = this.createFaceletFactory(c);
-
- this.initializeMappings(context);
- this.initializeMode(context);
- this.initializeBuffer(context);
-
- log.trace("Initialization Successful");
- }
- }
- }
-
- private void initializeMode(FacesContext context)
- {
- ExternalContext external = context.getExternalContext();
- String param = external.getInitParameter(PARAM_DEVELOPMENT);
- this.developmentMode = "true".equals(param);
-
- String restoreMode = external.getInitParameter(PARAM_BUILD_BEFORE_RESTORE);
- this.buildBeforeRestore = "true".equals(restoreMode);
- }
-
- private void initializeBuffer(FacesContext context)
- {
- ExternalContext external = context.getExternalContext();
- String param = external.getInitParameter(PARAM_BUFFER_SIZE);
- this.bufferSize = (param != null && !"".equals(param)) ? Integer.parseInt(param) : -1;
- }
/**
- * Initialize mappings, during the first request.
+ *
*/
- private void initializeMappings(FacesContext context)
- {
- ExternalContext external = context.getExternalContext();
- String viewMappings = external.getInitParameter(PARAM_VIEW_MAPPINGS);
- if ((viewMappings != null) && (viewMappings.length() > 0))
- {
- String[] mappingsArray = viewMappings.split(";");
-
- List<String> extensionsList = new ArrayList<String>(mappingsArray.length);
- List<String> prefixesList = new ArrayList<String>(mappingsArray.length);
-
- for (int i = 0; i < mappingsArray.length; i++)
- {
- String mapping = mappingsArray[i].trim();
- int mappingLength = mapping.length();
- if (mappingLength <= 1)
- {
- continue;
- }
-
- if (mapping.charAt(0) == '*')
- {
- extensionsList.add(mapping.substring(1));
- }
- else if (mapping.charAt(mappingLength - 1) == '*')
- {
- prefixesList.add(mapping.substring(0, mappingLength - 1));
- }
- }
-
- extensionsArray = new String[extensionsList.size()];
- extensionsList.toArray(extensionsArray);
-
- prefixesArray = new String[prefixesList.size()];
- prefixesList.toArray(prefixesArray);
- }
- }
-
- protected FaceletFactory createFaceletFactory(Compiler c)
- {
-
- // refresh period
- long refreshPeriod = DEFAULT_REFRESH_PERIOD;
- FacesContext ctx = FacesContext.getCurrentInstance();
- String userPeriod = ctx.getExternalContext().getInitParameter(PARAM_REFRESH_PERIOD);
- if (userPeriod != null && userPeriod.length() > 0)
- {
- refreshPeriod = Long.parseLong(userPeriod);
- }
-
- // resource resolver
- ResourceResolver resolver = new DefaultResourceResolver();
- String resolverName = ctx.getExternalContext().getInitParameter(PARAM_RESOURCE_RESOLVER);
- if (resolverName != null && resolverName.length() > 0)
- {
- try
- {
- resolver = (ResourceResolver) ReflectionUtil.forName(resolverName).newInstance();
- }
- catch (Exception e)
- {
- throw new FacesException("Error Initializing ResourceResolver[" + resolverName + "]", e);
- }
- }
-
- // Resource.getResourceUrl(ctx,"/")
- return new DefaultFaceletFactory(c, resolver, refreshPeriod);
- }
-
- protected Compiler createCompiler()
+ public FaceletViewDeclarationLanguage(FacesContext context)
{
- return new SAXCompiler();
+ initialize(context);
}
- protected void initializeCompiler(Compiler c)
- {
- FacesContext ctx = FacesContext.getCurrentInstance();
- ExternalContext ext = ctx.getExternalContext();
-
- // load libraries
- String libParam = ext.getInitParameter(PARAM_LIBRARIES);
- if (libParam != null)
- {
- libParam = libParam.trim();
- String[] libs = libParam.split(";");
- URL src;
- TagLibrary libObj;
- for (int i = 0; i < libs.length; i++)
- {
- try
- {
- src = ext.getResource(libs[i].trim());
- if (src == null)
- {
- throw new FileNotFoundException(libs[i]);
- }
- libObj = TagLibraryConfig.create(src);
- c.addTagLibrary(libObj);
- log.trace("Successfully Loaded Library: " + libs[i]);
- }
- catch (IOException e)
- {
- log.fatal("Error Loading Library: " + libs[i], e);
- }
- }
- }
-
- // load decorators
- String decParam = ext.getInitParameter(PARAM_DECORATORS);
- if (decParam != null)
- {
- decParam = decParam.trim();
- String[] decs = decParam.split(";");
- TagDecorator decObj;
- for (int i = 0; i < decs.length; i++)
- {
- try
- {
- decObj = (TagDecorator) ReflectionUtil.forName(decs[i]).newInstance();
- c.addTagDecorator(decObj);
- log.trace("Successfully Loaded Decorator: " + decs[i]);
- }
- catch (Exception e)
- {
- log.fatal("Error Loading Decorator: " + decs[i], e);
- }
- }
- }
-
- // skip params?
- String skipParam = ext.getInitParameter(PARAM_SKIP_COMMENTS);
- if (skipParam != null && "true".equals(skipParam))
- {
- c.setTrimmingComments(true);
- }
- }
/**
* {@inheritDoc}
*/
@@ -335,7 +128,8 @@
public void buildView(FacesContext context, UIViewRoot view) throws IOException
{
// setup our viewId
- String renderedViewId = this.getRenderedViewId(context, view.getViewId());
+ String renderedViewId = getRenderedViewId(context, view.getViewId());
+
view.setViewId(renderedViewId);
if (log.isTraceEnabled())
@@ -343,84 +137,37 @@
log.trace("Building View: " + renderedViewId);
}
- // grab our FaceletFactory and create a Facelet
- Facelet f = null;
- FaceletFactory.setInstance(this.faceletFactory);
- try
- {
- f = this.faceletFactory.getFacelet(view.getViewId());
- }
- finally
- {
- FaceletFactory.setInstance(null);
- }
-
// populate UIViewRoot
- long time = System.currentTimeMillis();
- f.apply(context, view);
- time = System.currentTimeMillis() - time;
- if (log.isTraceEnabled()) {
- log.trace("Took " + time + "ms to build view: " + view.getViewId());
- }
+ _getFacelet(renderedViewId).apply(context, view);
}
/**
* {@inheritDoc}
*/
@Override
- public UIViewRoot createView(FacesContext context, String viewId)
+ public BeanInfo getComponentMetadata(FacesContext context, Resource componentResource)
{
- UIViewRoot viewRoot = super.createView(context, viewId);
- context.setViewRoot(viewRoot);
-
- return viewRoot;
+ // TODO Auto-generated method stub
+ return null;
}
/**
* {@inheritDoc}
*/
@Override
- public BeanInfo getComponentMetadata(FacesContext context, Resource componentResource)
+ public Resource getScriptComponentResource(FacesContext context, Resource componentResource)
{
- checkNull(context, "context");
- checkNull(componentResource, "componentResource");
-
- try {
- UIComponent tempViewRoot;
- Facelet facelet;
-
- // TODO: make sure this is the right implementation. I believe we need to create
- // the Facelet, apply it against some new viewroot, and pull the BeanInfo out of
- // its attributes. Caching would probably be nice too.
-
- facelet = faceletFactory.getFacelet(componentResource.getURL());
-
- tempViewRoot = context.getApplication().createComponent (UIViewRoot.COMPONENT_TYPE);
-
- facelet.apply (context, tempViewRoot);
-
- return (BeanInfo) tempViewRoot.getAttributes().get (UIComponent.BEANINFO_KEY);
- }
-
- catch (Throwable e) {
- if (e instanceof FacesException) {
- throw ((FacesException) e);
- }
-
- throw new FacesException ("unable to get component metadata", e);
- }
+ // TODO Auto-generated method stub
+ return null;
}
/**
* {@inheritDoc}
*/
@Override
- public Resource getScriptComponentResource(FacesContext context, Resource componentResource)
+ public StateManagementStrategy getStateManagementStrategy(FacesContext context, String viewId)
{
- checkNull(context, "context");
- checkNull(componentResource, "componentResource");
-
- // TODO: IMPLEMENT HERE
+ // TODO Auto-generated method stub
return null;
}
@@ -430,12 +177,7 @@
@Override
public ViewMetadata getViewMetadata(FacesContext context, String viewId)
{
- checkNull(context, "context");
- checkNull(viewId, "viewId");
-
- // TODO: cache?
-
- return new ViewMetadataImpl (viewId);
+ return new FaceletViewMetadata(viewId);
}
/**
@@ -444,35 +186,17 @@
@Override
public void renderView(FacesContext context, UIViewRoot view) throws IOException
{
- checkNull(context, "context");
- checkNull(view, "view");
-
- // lazy initialize so we have a FacesContext to use
- if (this.faceletFactory == null)
- {
- this.initialize(context);
- }
-
- // exit if the view is not to be rendered
if (!view.isRendered())
{
return;
}
- // if facelets is not supposed to handle this request
- if (!handledByFacelets(view.getViewId()))
- {
- this.parent.renderView(context, view);
- return;
- }
-
// log request
- if (log.isTraceEnabled())
+ if (log.isDebugEnabled())
{
- log.trace("Rendering View: " + view.getViewId());
+ log.debug("Rendering View: " + view.getViewId());
}
- StateWriter stateWriter = null;
try
{
// build view - but not if we're in "buildBeforeRestore"
@@ -482,102 +206,103 @@
// should that be handled? Or
// is this optimization simply so minor that it should just
// be trimmed altogether?
- if (!this.buildBeforeRestore || view.getChildren().isEmpty())
+ if (view.getChildren().isEmpty())
{
- this.buildView(context, view);
+ buildView(context, view);
}
// setup writer and assign it to the context
- ResponseWriter origWriter = this.createResponseWriter(context);
- // QUESTION: should we use bufferSize? Or, since the
- // StateWriter usually only needs a small bit at the end,
- // should we always use a much smaller size?
- stateWriter = new StateWriter(origWriter, this.bufferSize != -1 ? this.bufferSize : 1024);
-
- ResponseWriter writer = origWriter.cloneWithWriter(stateWriter);
- context.setResponseWriter(writer);
-
- // force creation of session if saving state there
- StateManager stateMgr = context.getApplication().getStateManager();
- if (!stateMgr.isSavingStateInClient(context))
- {
- context.getExternalContext().getSession(true);
- }
+ ResponseWriter origWriter = createResponseWriter(context);
- long time = System.currentTimeMillis();
-
- // render the view to the response
- writer.startDocument();
- view.encodeAll(context);
- writer.endDocument();
-
- // finish writing
- writer.close();
-
- boolean writtenState = stateWriter.isStateWritten();
- // flush to origWriter
- if (writtenState)
+ StateWriter stateWriter = new StateWriter(origWriter, 1024);
+ try
{
- String content = stateWriter.getAndResetBuffer();
- int end = content.indexOf(STATE_KEY);
- // See if we can find any trace of the saved state.
- // If so, we need to perform token replacement
- if (end >= 0)
+ ResponseWriter writer = origWriter.cloneWithWriter(stateWriter);
+ try
{
- // save state
- Object stateObj = stateMgr.saveSerializedView(context);
- String stateStr;
- if (stateObj == null)
- {
- stateStr = null;
- }
- else
+ context.setResponseWriter(writer);
+
+ // force creation of session if saving state there
+ StateManager stateMgr = context.getApplication().getStateManager();
+ if (!stateMgr.isSavingStateInClient(context))
{
- stateMgr.writeState(context, (StateManager.SerializedView) stateObj);
- stateStr = stateWriter.getAndResetBuffer();
+ context.getExternalContext().getSession(true);
}
- int start = 0;
+ // render the view to the response
+ writer.startDocument();
+
+ view.encodeAll(context);
+
+ writer.endDocument();
- while (end != -1)
+ // finish writing
+ writer.close();
+
+ boolean writtenState = stateWriter.isStateWritten();
+ // flush to origWriter
+ if (writtenState)
{
- origWriter.write(content, start, end - start);
- if (stateStr != null)
+ String content = stateWriter.getAndResetBuffer();
+ int end = content.indexOf(STATE_KEY);
+ // See if we can find any trace of the saved state.
+ // If so, we need to perform token replacement
+ if (end >= 0)
+ {
+ // save state
+ Object stateObj = stateMgr.saveSerializedView(context);
+ String stateStr;
+ if (stateObj == null)
+ {
+ stateStr = null;
+ }
+ else
+ {
+ stateMgr.writeState(context, (StateManager.SerializedView) stateObj);
+ stateStr = stateWriter.getAndResetBuffer();
+ }
+
+ int start = 0;
+
+ while (end != -1)
+ {
+ origWriter.write(content, start, end - start);
+ if (stateStr != null)
+ {
+ origWriter.write(stateStr);
+ }
+ start = end + STATE_KEY_LEN;
+ end = content.indexOf(STATE_KEY, start);
+ }
+
+ origWriter.write(content, start, content.length() - start);
+ // No trace of any saved state, so we just need to flush
+ // the buffer
+ }
+ else
{
- origWriter.write(stateStr);
+ origWriter.write(content);
}
- start = end + STATE_KEY_LEN;
- end = content.indexOf(STATE_KEY, start);
}
- origWriter.write(content, start, content.length() - start);
- // No trace of any saved state, so we just need to flush
- // the buffer
}
- else
+ finally
{
- origWriter.write(content);
+ // The Facelets implementation must close the writer used to write the response
+ writer.close();
}
}
-
- time = System.currentTimeMillis() - time;
- if (log.isTraceEnabled())
+ finally
{
- log.trace("Took " + time + "ms to render view: " + view.getViewId());
+ stateWriter.release();
}
-
}
catch (FileNotFoundException fnfe)
{
- this.handleFaceletNotFound(context, view.getViewId());
+ handleFaceletNotFound(context, view.getViewId());
}
catch (Exception e)
{
- this.handleRenderException(context, e);
- }
- finally
- {
- if (stateWriter != null)
- stateWriter.release();
+ handleRenderException(context, e);
}
}
@@ -587,46 +312,46 @@
@Override
public UIViewRoot restoreView(FacesContext context, String viewId)
{
- checkNull(context, "context");
- checkNull(viewId, "viewId");
-
if (UIDebug.debugRequest(context))
{
return new UIViewRoot();
}
-
- if (!this.buildBeforeRestore || !handledByFacelets(viewId))
+ else if (!_buildBeforeRestore)
{
- return this.parent.restoreView(context, viewId);
+ return super.restoreView(context, viewId);
}
-
- if (this.faceletFactory == null)
+ else
{
- this.initialize(context);
- }
+ // TODO: VALIDATE - Is _buildBeforeRestore relevant at all for 2.0? -= SL =-
- // In JSF 1.2, restoreView() will only be called on postback.
- // But in JSF 1.1, it will be called for an initial request too,
- // in which case we must return null in order to fall through
- // to createView()
+ UIViewRoot viewRoot = createView(context, viewId);
- ViewHandler outerViewHandler = context.getApplication().getViewHandler();
- String renderKitId = outerViewHandler.calculateRenderKitId(context);
+ context.setViewRoot(viewRoot);
- UIViewRoot viewRoot = createView(context, viewId);
- context.setViewRoot(viewRoot);
- try
- {
- this.buildView(context, viewRoot);
- }
- catch (IOException ioe)
- {
- log.fatal("Error Building View", ioe);
+ try
+ {
+ buildView(context, viewRoot);
+ }
+ catch (IOException ioe)
+ {
+ log.error("Error Building View", ioe);
+ }
+
+ Application application = context.getApplication();
+
+ ViewHandler applicationViewHandler = application.getViewHandler();
+
+ String renderKitId = applicationViewHandler.calculateRenderKitId(context);
+
+ application.getStateManager().restoreView(context, viewId, renderKitId);
+
+ return viewRoot;
}
- context.getApplication().getStateManager().restoreView(context, viewId, renderKitId);
- return viewRoot;
}
+ /**
+ * {@inheritDoc}
+ */
@Override
protected String calculateViewId(FacesContext context, String viewId)
{
@@ -634,258 +359,275 @@
{
_cachedViewHandlerSupport = new DefaultViewHandlerSupport();
}
-
+
return _cachedViewHandlerSupport.calculateViewId(context, viewId);
}
- @Override
- protected void sendSourceNotFound(FacesContext context, String message)
+ /**
+ * Creates the Facelet page compiler.
+ *
+ * @param context
+ * the current FacesContext
+ *
+ * @return the application's Facelet page compiler
+ */
+ protected Compiler createCompiler(FacesContext context)
{
- HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
- try
- {
- context.responseComplete();
- response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
- }
- catch (IOException ioe)
- {
- throw new FacesException(ioe);
- }
+ Compiler compiler = new SAXCompiler();
+
+ loadLibraries(context, compiler);
+ loadDecorators(context, compiler);
+ loadOptions(context, compiler);
+
+ return compiler;
}
- @Override
- public StateManagementStrategy getStateManagementStrategy(
- FacesContext context, String viewId)
+ /**
+ * Creates a FaceletFactory instance using the specified compiler.
+ *
+ * @param context
+ * the current FacesContext
+ * @param compiler
+ * the compiler to be used by the factory
+ *
+ * @return the factory used by this VDL to load pages
+ */
+ protected FaceletFactory createFaceletFactory(FacesContext context, Compiler compiler)
{
- if (stateMgmtStrategy == null) {
- stateMgmtStrategy = new DefaultFaceletsStateManagementStrategy (this);
+ ExternalContext eContext = context.getExternalContext();
+
+ // refresh period
+ long refreshPeriod = _getLongParameter(eContext, PARAM_REFRESH_PERIOD, DEFAULT_REFRESH_PERIOD);
+
+ // resource resolver
+ ResourceResolver resolver = _getInstanceParameter(eContext, PARAM_RESOURCE_RESOLVER, null);
+ if (resolver == null)
+ {
+ resolver = new DefaultResourceResolver();
}
-
- return stateMgmtStrategy;
+
+ return new DefaultFaceletFactory(compiler, resolver, refreshPeriod);
}
-
- @Override
- public void retargetMethodExpressions(FacesContext context, UIComponent topLevelComponent)
+
+ protected ResponseWriter createResponseWriter(FacesContext context) throws IOException, FacesException
{
- checkNull(context, "context");
- checkNull(topLevelComponent, "topLevelComponent");
-
- BeanInfo beanInfo = (BeanInfo)topLevelComponent.getAttributes().get(UIComponent.BEANINFO_KEY);
- if(beanInfo == null)
+ ExternalContext extContext = context.getExternalContext();
+ RenderKit renderKit = context.getRenderKit();
+ // Avoid a cryptic NullPointerException when the renderkit ID
+ // is incorrectly set
+ if (renderKit == null)
{
- return; // should we log an error here? spec doesn't say one way or the other so leaving it alone for now.
+ String id = context.getViewRoot().getRenderKitId();
+ throw new IllegalStateException("No render kit was available for id \"" + id + "\"");
}
-
- PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
- for(PropertyDescriptor curDescriptor : descriptors)
+
+ ServletResponse response = (ServletResponse) extContext.getResponse();
+
+ // set the buffer for content
+ if (_bufferSize != -1)
{
- ExpressionFactory expressionFactory = null;
- ValueExpression valueExpression = null;
- MethodExpression attributeMethodExpression = null;
- Class expectedReturn = null;
- Class expectedParams[] = null;
-
- if(curDescriptor.getValue("type") != null || curDescriptor.getValue("method-signature") == null)
- {
- continue;
- }
-
- String targets = null;
- valueExpression = (ValueExpression)curDescriptor.getValue("targets");
- if(valueExpression != null)
- {
- targets = (String)valueExpression.getValue(context.getELContext());
- }
+ response.setBufferSize(_bufferSize);
+ }
- if(targets == null)
- {
- targets = curDescriptor.getName();
- }
-
- if(targets == null)
- {
- continue; //not explicitly part of the algorithm, but could lead to an NPE if we don't check this
- }
-
- String[] targetArray = targets.split(" ");
- for (String curTarget : targetArray)
- {
- UIComponent target = topLevelComponent.findComponent(curTarget);
- if(target == null)
- {
- log.error("target not found");
- continue;
- }
-
- String name = curDescriptor.getName();
-
- ValueExpression attributeValueExpression = (ValueExpression)topLevelComponent.getAttributes().get(name);
-
- if(attributeValueExpression == null)
- {
- log.error("attributeValueExpression not found");
- continue;
- }
+ // get our content type
+ String contentType = (String) extContext.getRequestMap().get("facelets.ContentType");
- if(expressionFactory == null)
- { //initialize expression factory if hasn't been used yet
- expressionFactory = context.getApplication().getExpressionFactory();
- }
-
- boolean isAction = name.equals("action"),
- isActionListener = name.equals("actionListener"),
- isValidator = name.equals("validator"),
- isValueChangeListener = name.equals("valueChangeListener");
-
- String expressionString = attributeValueExpression.getExpressionString();
-
- if(isAction)
- expectedReturn = Object.class;
- else
- expectedReturn = Void.class;
-
- if(isAction)
- {
- expectedParams = new Class[]{};
- attributeMethodExpression = expressionFactory.createMethodExpression(context.getELContext(), expressionString, expectedReturn, expectedParams);
- ((ActionSource2) target).setActionExpression(attributeMethodExpression);
- }
- else if(isActionListener)
- {
- expectedParams = new Class[]{ActionEvent.class};
- attributeMethodExpression = expressionFactory.createMethodExpression(context.getELContext(), expressionString, expectedReturn, expectedParams);
- ((ActionSource2) target).addActionListener(new MethodExpressionActionListener(attributeMethodExpression));
- }
- else if(isValidator)
- {
- expectedParams = new Class[]{FacesContext.class,UIComponent.class,Object.class};
- attributeMethodExpression = expressionFactory.createMethodExpression(context.getELContext(), expressionString, expectedReturn, expectedParams);
- ((EditableValueHolder) target).addValidator(new MethodExpressionValidator(attributeMethodExpression));
- }
- else if(isValueChangeListener)
- {
- expectedParams = new Class[]{ValueChangeEvent.class};
- attributeMethodExpression = expressionFactory.createMethodExpression(context.getELContext(), expressionString, expectedReturn, expectedParams);
- ((EditableValueHolder) target).addValueChangeListener(new MethodExpressionValueChangeListener(attributeMethodExpression));
- }
- else
- {
- //TODO: implement here - derive attribute name from method-signature
- //If name is not equal to any of the previously listed strings, call getExpressionString() on the attributeValueExpression and use that string to create a MethodExpression
- //where the signature is created based on the value of the "method-signature" attribute of the <composite:attribute /> tag.
-
- //Otherwise, assume that the MethodExpression should be placed in the components attribute set. The runtme must create the MethodExpression instance based on the value of the "method-signature" attribute.
- }
-
-
- }
+ // get the encoding
+ String encoding = (String) extContext.getRequestMap().get("facelets.Encoding");
+
+ ResponseWriter writer;
+ // append */* to the contentType so createResponseWriter will succeed no matter
+ // the requested contentType.
+ if (contentType != null && !contentType.equals("*/*"))
+ {
+ contentType += ",*/*";
}
- }
-
- @Override
- public void retargetAttachedObjects(FacesContext context,
- UIComponent topLevelComponent, List<AttachedObjectHandler> handlers)
- {
- checkNull(context, "context");
- checkNull(topLevelComponent, "topLevelComponent");
- checkNull(handlers, "handlers");
-
- BeanInfo beanInfo = (BeanInfo)topLevelComponent.getAttributes().get(UIComponent.BEANINFO_KEY);
-
- if(beanInfo == null)
+ // Create a dummy ResponseWriter with a bogus writer,
+ // so we can figure out what content type the ReponseWriter
+ // is really going to ask for
+ try
{
- log.error("BeanInfo not found");
- return;
+ writer = renderKit.createResponseWriter(NullWriter.Instance, contentType, encoding);
}
-
- BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor();
- List<AttachedObjectTarget> targetList = (List<AttachedObjectTarget>)beanDescriptor.getValue(AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY);
-
- for (AttachedObjectHandler curHandler : handlers)
+ catch (IllegalArgumentException e)
{
- String forAttributeValue = curHandler.getFor();
+ // Added because of an RI bug prior to 1.2_05-b3. Might as well leave it in case other
+ // impls have the same problem. https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=613
+ log.trace("The impl didn't correctly handled '*/*' in the content type list. Trying '*/*' directly.");
+ writer = renderKit.createResponseWriter(NullWriter.Instance, "*/*", encoding);
+ }
- for(AttachedObjectTarget curTarget : targetList)
- {
- List<UIComponent> targetUIComponents = curTarget.getTargets(topLevelComponent);
- String curTargetName = curTarget.getName();
+ // Override the JSF provided content type if necessary
+ contentType = getResponseContentType(context, writer.getContentType());
+ encoding = getResponseEncoding(context, writer.getCharacterEncoding());
- if( (curHandler instanceof ActionSource2AttachedObjectHandler) && curHandler instanceof ActionSource2AttachedObjectTarget)
- {
- applyAttachedObjects(context,targetUIComponents, curHandler);
- break;
- }
- if( (curHandler instanceof EditableValueHolderAttachedObjectHandler) && curHandler instanceof EditableValueHolderAttachedObjectTarget)
- {
- applyAttachedObjects(context,targetUIComponents, curHandler);
- break;
- }
- if( (curHandler instanceof ValueHolderAttachedObjectHandler) && curHandler instanceof ValueHolderAttachedObjectTarget)
- {
- applyAttachedObjects(context,targetUIComponents, curHandler);
- break;
- }
- }
- }
+ // apply them to the response
+ response.setContentType(contentType + "; charset=" + encoding);
+
+ // removed 2005.8.23 to comply with J2EE 1.3
+ // response.setCharacterEncoding(encoding);
+
+ // Now, clone with the real writer
+ writer = writer.cloneWithWriter(response.getWriter());
+
+ return writer;
}
-
- protected void applyAttachedObjects(FacesContext context, List<UIComponent> targetUIComponents, AttachedObjectHandler curHandler)
+
+ protected String getDefaultSuffix(FacesContext context) throws FacesException
{
- for (UIComponent target : targetUIComponents)
+ if (_defaultSuffix == null)
{
- curHandler.applyAttachedObject(context, target);
+ ExternalContext eContext = context.getExternalContext();
+
+ String viewSuffix = eContext.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
+
+ _defaultSuffix = viewSuffix == null ? ViewHandler.DEFAULT_FACELETS_SUFFIX : viewSuffix;
}
+
+ return _defaultSuffix;
}
-
+
protected String getRenderedViewId(FacesContext context, String actionId)
{
- ExternalContext extCtx = context.getExternalContext();
+ ExternalContext eContext = context.getExternalContext();
String viewId = actionId;
- if (extCtx.getRequestPathInfo() == null)
+ if (eContext.getRequestPathInfo() == null)
{
- String viewSuffix = this.getDefaultSuffix(context);
- viewId = new StringBuffer(viewId).replace(viewId.lastIndexOf('.'), viewId.length(), viewSuffix).toString();
+ String viewSuffix = getDefaultSuffix(context);
+
+ StringBuilder builder = new StringBuilder(viewId);
+
+ viewId = builder.replace(viewId.lastIndexOf('.'), viewId.length(), viewSuffix).toString();
}
+
if (log.isTraceEnabled())
{
log.trace("ActionId -> ViewId: " + actionId + " -> " + viewId);
}
+
return viewId;
}
-
- protected String getDefaultSuffix(FacesContext context) throws FacesException
+
+ /**
+ * Generate the content type
+ *
+ * @param context
+ * @param orig
+ * @return
+ */
+ protected String getResponseContentType(FacesContext context, String orig)
{
- if (this.defaultSuffix == null)
+ String contentType = orig;
+
+ // see if we need to override the contentType
+ Map<String, Object> m = context.getExternalContext().getRequestMap();
+ if (m.containsKey("facelets.ContentType"))
{
- ExternalContext extCtx = context.getExternalContext();
- String viewSuffix = extCtx.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
- this.defaultSuffix = (viewSuffix != null) ? viewSuffix : ViewHandler.DEFAULT_FACELETS_SUFFIX;
+ contentType = (String) m.get("facelets.ContentType");
+ if (log.isTraceEnabled())
+ {
+ log.trace("Facelet specified alternate contentType '" + contentType + "'");
+ }
+ }
+
+ // safety check
+ if (contentType == null)
+ {
+ contentType = "text/html";
+ log.trace("ResponseWriter created had a null ContentType, defaulting to text/html");
}
- return this.defaultSuffix;
+
+ return contentType;
}
- protected void handleRenderException(FacesContext context, Exception e) throws IOException, ELException,
- FacesException
+ /**
+ * Generate the encoding
+ *
+ * @param context
+ * @param orig
+ * @return
+ */
+ protected String getResponseEncoding(FacesContext context, String orig)
{
- Object resp = context.getExternalContext().getResponse();
+ String encoding = orig;
+
+ // see if we need to override the encoding
+ Map<String, Object> m = context.getExternalContext().getRequestMap();
+ Map<String, Object> sm = context.getExternalContext().getSessionMap();
+
+ // 1. check the request attribute
+ if (m.containsKey(PARAM_ENCODING))
+ {
+ encoding = (String) m.get(PARAM_ENCODING);
+ if (encoding != null && log.isTraceEnabled())
+ {
+ log.trace("Facelet specified alternate encoding '" + encoding + "'");
+ }
+
+ sm.put(CHARACTER_ENCODING_KEY, encoding);
+ }
+
+ // 2. get it from request
+ Object request = context.getExternalContext().getRequest();
+ if (encoding == null && request instanceof ServletRequest)
+ {
+ encoding = ((ServletRequest) request).getCharacterEncoding();
+ }
- // always log
- if (log.isFatalEnabled())
+ // 3. get it from the session
+ if (encoding == null)
{
- UIViewRoot root = context.getViewRoot();
- StringBuffer sb = new StringBuffer(64);
- sb.append("Error Rendering View");
- if (root != null)
+ encoding = (String) sm.get(CHARACTER_ENCODING_KEY);
+ if (encoding != null && log.isTraceEnabled())
{
- sb.append('[');
- sb.append(root.getViewId());
- sb.append(']');
+ log.trace("Session specified alternate encoding '" + encoding + "'");
}
- log.fatal(sb.toString(), e);
}
+ // 4. default it
+ if (encoding == null)
+ {
+ encoding = DEFAULT_CHARACTER_ENCODING;
+ if (log.isTraceEnabled())
+ {
+ log.trace("ResponseWriter created had a null CharacterEncoding, defaulting to " + encoding);
+ }
+ }
+
+ return encoding;
+ }
+
+ protected void handleFaceletNotFound(FacesContext context, String viewId) throws FacesException, IOException
+ {
+ String actualId = context.getApplication().getViewHandler().getActionURL(context, viewId);
+ Object respObj = context.getExternalContext().getResponse();
+ if (respObj instanceof HttpServletResponse)
+ {
+ HttpServletResponse respHttp = (HttpServletResponse) respObj;
+ respHttp.sendError(HttpServletResponse.SC_NOT_FOUND, actualId);
+ context.responseComplete();
+ }
+ }
+
+ protected void handleRenderException(FacesContext context, Exception e) throws IOException, ELException,
+ FacesException
+ {
+ Object resp = context.getExternalContext().getResponse();
+
+ UIViewRoot root = context.getViewRoot();
+ StringBuffer sb = new StringBuffer(64);
+ sb.append("Error Rendering View");
+ if (root != null)
+ {
+ sb.append('[');
+ sb.append(root.getViewId());
+ sb.append(']');
+ }
+
+ log.error(sb.toString(), e);
+
// handle dev response
- if (this.developmentMode && !context.getResponseComplete() && resp instanceof HttpServletResponse)
+ if (_isDevelopmentMode(context) && !context.getResponseComplete() && resp instanceof HttpServletResponse)
{
HttpServletResponse httpResp = (HttpServletResponse) resp;
if (!httpResp.isCommitted())
@@ -912,215 +654,376 @@
}
}
- protected void handleFaceletNotFound(FacesContext context, String viewId) throws FacesException, IOException
+ /**
+ * Initialize the ViewHandler during its first request.
+ */
+ protected void initialize(FacesContext context)
{
- if(_cachedViewHandlerSupport == null)
- {
- _cachedViewHandlerSupport = new DefaultViewHandlerSupport();
- }
-
- String actualId = _cachedViewHandlerSupport.calculateActionURL(context, viewId);
- Object respObj = context.getExternalContext().getResponse();
- if (respObj instanceof HttpServletResponse)
- {
- HttpServletResponse respHttp = (HttpServletResponse) respObj;
- respHttp.sendError(HttpServletResponse.SC_NOT_FOUND, actualId);
- context.responseComplete();
- }
+ log.trace("Initializing");
+
+ Compiler compiler = createCompiler(context);
+
+ _faceletFactory = createFaceletFactory(context, compiler);
+
+ ExternalContext eContext = context.getExternalContext();
+ _initializeBuffer(eContext);
+ _initializeMode(eContext);
+
+ log.trace("Initialization Successful");
}
-
+
/**
- * Determine if Facelets needs to handle this request.
+ * Load the various decorators for Facelets.
+ *
+ * @param context
+ * the current FacesContext
+ * @param compiler
+ * the page compiler
*/
- private boolean handledByFacelets(String viewId)
+ protected void loadDecorators(FacesContext context, Compiler compiler)
{
- // If there's no extensions array or prefixes array, then
- // just make Facelets handle everything
- if ((extensionsArray == null) && (prefixesArray == null))
+ String param = _getStringParameter(context.getExternalContext(), PARAM_DECORATORS);
+ if (param != null)
{
- return true;
- }
-
- if (extensionsArray != null)
- {
- for (int i = 0; i < extensionsArray.length; i++)
+ for (String decorator : param.split(";"))
{
- String extension = extensionsArray[i];
- if (viewId.endsWith(extension))
+ try
{
- return true;
+ compiler.addTagDecorator((TagDecorator) ReflectionUtil.forName(decorator).newInstance());
+ if (log.isDebugEnabled())
+ {
+ log.debug("Successfully loaded decorator: " + decorator);
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("Error Loading decorator: " + decorator, e);
}
}
}
+ }
- if (prefixesArray != null)
+ /**
+ * Load the various tag libraries for Facelets.
+ *
+ * @param context
+ * the current FacesContext
+ * @param compiler
+ * the page compiler
+ */
+ protected void loadLibraries(FacesContext context, Compiler compiler)
+ {
+ ExternalContext eContext = context.getExternalContext();
+
+ String param = _getStringParameter(eContext, PARAM_LIBRARIES);
+ if (param != null)
{
- for (int i = 0; i < prefixesArray.length; i++)
+ for (String library : param.split(";"))
{
- String prefix = prefixesArray[i];
- if (viewId.startsWith(prefix))
+ try
{
- return true;
+ URL src = eContext.getResource(library.trim());
+ if (src == null)
+ {
+ throw new FileNotFoundException(library);
+ }
+
+ compiler.addTagLibrary(TagLibraryConfig.create(src));
+ if (log.isDebugEnabled())
+ {
+ log.debug("Successfully loaded library: " + library);
+ }
+ }
+ catch (IOException e)
+ {
+ log.error("Error Loading library: " + library, e);
}
}
}
+ }
- return false;
+ /**
+ * Load the various options for Facelets compiler. Currently only comment skipping is supported.
+ *
+ * @param context
+ * the current FacesContext
+ * @param compiler
+ * the page compiler
+ */
+ protected void loadOptions(FacesContext context, Compiler compiler)
+ {
+ ExternalContext eContext = context.getExternalContext();
+
+ // skip comments?
+ compiler.setTrimmingComments(_getBooleanParameter(eContext, PARAM_SKIP_COMMENTS, false));
}
- protected ResponseWriter createResponseWriter(FacesContext context) throws IOException, FacesException
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void sendSourceNotFound(FacesContext context, String message)
{
- ExternalContext extContext = context.getExternalContext();
- RenderKit renderKit = context.getRenderKit();
- // Avoid a cryptic NullPointerException when the renderkit ID
- // is incorrectly set
- if (renderKit == null)
+ // This is incredibly lame, but I see no other option. -= SL =-
+ HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
+ try
{
- String id = context.getViewRoot().getRenderKitId();
- throw new IllegalStateException("No render kit was available for id \"" + id + "\"");
+ context.responseComplete();
+ response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
}
-
- ServletResponse response = (ServletResponse) extContext.getResponse();
-
- // set the buffer for content
- if (this.bufferSize != -1)
+ catch (IOException ioe)
{
- response.setBufferSize(this.bufferSize);
+ throw new FacesException(ioe);
}
+ }
- // get our content type
- String contentType = (String) extContext.getRequestMap().get("facelets.ContentType");
-
- // get the encoding
- String encoding = (String) extContext.getRequestMap().get("facelets.Encoding");
+ /**
+ * Gets the boolean init parameter value from the specified context. If the parameter was not specified, the default
+ * value is used instead.
+ *
+ * TODO: This method should be in an utility class. Anyone knows if we have such a class already? -= SL =-
+ *
+ * @param context
+ * the application's external context
+ * @param name
+ * the init parameter's name
+ * @param defaultValue
+ * the default value to return in case the ârameter was not set
+ *
+ * @return the init parameter value as a boolean
+ *
+ * @throws NullPointerException
+ * if context or name is <code>null</code>
+ */
+ private boolean _getBooleanParameter(ExternalContext context, String name, boolean defaultValue)
+ {
+ String param = _getStringParameter(context, name);
+ if (param == null)
+ {
+ return defaultValue;
+ }
+ else
+ {
+ return Boolean.parseBoolean(param.toLowerCase());
+ }
+ }
- ResponseWriter writer;
- // append */* to the contentType so createResponseWriter will succeed no matter
- // the requested contentType.
- if (contentType != null && !contentType.equals("*/*"))
+ /**
+ * Gets the int init parameter value from the specified context. If the parameter was not specified, the default
+ * value is used instead.
+ *
+ * TODO: This method should be in an utility class. Anyone knows if we have such a class already? -= SL =-
+ *
+ * @param context
+ * the application's external context
+ * @param name
+ * the init parameter's name
+ * @param defaultValue
+ * the default value to return in case the ârameter was not set
+ *
+ * @return the init parameter value as a int
+ *
+ * @throws NullPointerException
+ * if context or name is <code>null</code>
+ */
+ private int _getIntegerParameter(ExternalContext context, String name, int defaultValue)
+ {
+ String param = _getStringParameter(context, name);
+ if (param == null)
{
- contentType += ",*/*";
+ return defaultValue;
}
- // Create a dummy ResponseWriter with a bogus writer,
- // so we can figure out what content type the ReponseWriter
- // is really going to ask for
+ else
+ {
+ return Integer.parseInt(param);
+ }
+ }
+
+ /**
+ * Gets the Facelet representing the specified view identifier.
+ *
+ * @param viewId
+ * the view identifier
+ *
+ * @return the Facelet representing the specified view identifier
+ *
+ * @throws IOException
+ * if a read or parsing error occurs
+ */
+ private Facelet _getFacelet(String viewId) throws IOException
+ {
+ // grab our FaceletFactory and create a Facelet
+ FaceletFactory.setInstance(_faceletFactory);
try
{
- writer = renderKit.createResponseWriter(NullWriter.Instance, contentType, encoding);
+ return _faceletFactory.getFacelet(viewId);
}
- catch (IllegalArgumentException e)
+ finally
{
- // Added because of an RI bug prior to 1.2_05-b3. Might as well leave it in case other
- // impls have the same problem. https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=613
- log.trace("The impl didn't correctly handled '*/*' in the content type list. Trying '*/*' directly.");
- writer = renderKit.createResponseWriter(NullWriter.Instance, "*/*", encoding);
+ FaceletFactory.setInstance(null);
}
-
- // Override the JSF provided content type if necessary
- contentType = getResponseContentType(context, writer.getContentType());
- encoding = getResponseEncoding(context, writer.getCharacterEncoding());
-
- // apply them to the response
- response.setContentType(contentType + "; charset=" + encoding);
-
- // removed 2005.8.23 to comply with J2EE 1.3
- // response.setCharacterEncoding(encoding);
-
- // Now, clone with the real writer
- writer = writer.cloneWithWriter(response.getWriter());
-
- return writer;
}
-
/**
- * Generate the encoding
+ * Gets the init parameter value from the specified context and instanciate it. If the parameter was not specified,
+ * the default value is used instead.
+ *
+ * TODO: This method should be in an utility class. Anyone knows if we have such a class already? -= SL =-
*
* @param context
- * @param orig
- * @return
+ * the application's external context
+ * @param name
+ * the init parameter's name
+ * @param defaultValue
+ * the default value to return in case the ârameter was not set
+ *
+ * @return the init parameter value as an object instance
+ *
+ * @throws NullPointerException
+ * if context or name is <code>null</code>
*/
- protected String getResponseEncoding(FacesContext context, String orig)
+ @SuppressWarnings("unchecked")
+ private <T> T _getInstanceParameter(ExternalContext context, String name, T defaultValue)
{
- String encoding = orig;
-
- // see if we need to override the encoding
- Map<String, Object> m = context.getExternalContext().getRequestMap();
- Map<String, Object> sm = context.getExternalContext().getSessionMap();
-
- // 1. check the request attribute
- if (m.containsKey("facelets.Encoding"))
+ String param = _getStringParameter(context, name);
+ if (param == null)
{
- encoding = (String) m.get("facelets.Encoding");
- if (log.isTraceEnabled())
+ return defaultValue;
+ }
+ else
+ {
+ try
{
- log.trace("Facelet specified alternate encoding '" + encoding + "'");
+ return (T) ReflectionUtil.forName(param).newInstance();
+ }
+ catch (Exception e)
+ {
+ throw new FacesException("Error Initializing Object[" + param + "]", e);
}
- sm.put(ViewHandler.CHARACTER_ENCODING_KEY, encoding);
}
+ }
- // 2. get it from request
- Object request = context.getExternalContext().getRequest();
- if (encoding == null && request instanceof ServletRequest)
+ /**
+ * Gets the long init parameter value from the specified context. If the parameter was not specified, the default
+ * value is used instead.
+ *
+ * TODO: This method should be in an utility class. Anyone knows if we have such a class already? -= SL =-
+ *
+ * @param context
+ * the application's external context
+ * @param name
+ * the init parameter's name
+ * @param defaultValue
+ * the default value to return in case the ârameter was not set
+ *
+ * @return the init parameter value as a long
+ *
+ * @throws NullPointerException
+ * if context or name is <code>null</code>
+ */
+ private long _getLongParameter(ExternalContext context, String name, long defaultValue)
+ {
+ String param = _getStringParameter(context, name);
+ if (param == null)
{
- encoding = ((ServletRequest) request).getCharacterEncoding();
+ return defaultValue;
}
+ else
+ {
+ return Long.parseLong(param);
+ }
+ }
- // 3. get it from the session
- if (encoding == null)
+ /**
+ * Gets the String init parameter value from the specified context. If the parameter is an empty String or a String
+ * containing only white space, this method returns <code>null</code>
+ *
+ * TODO: This method should be in an utility class. Anyone knows if we have such a class already? -= SL =-
+ *
+ * @param context
+ * the application's external context
+ * @param name
+ * the init parameter's name
+ *
+ * @return the parameter if it was specified and was not empty, <code>null</code> otherwise
+ *
+ * @throws NullPointerException
+ * if context or name is <code>null</code>
+ */
+ private String _getStringParameter(ExternalContext context, String name)
+ {
+ String param = context.getInitParameter(name);
+ if (param == null)
{
- encoding = (String) sm.get(ViewHandler.CHARACTER_ENCODING_KEY);
- if (log.isTraceEnabled())
- {
- log.trace("Session specified alternate encoding '" + encoding + "'");
- }
+ return null;
}
- // 4. default it
- if (encoding == null)
+ param = param.trim();
+ if (param.length() == 0)
{
- encoding = "UTF-8";
- if (log.isTraceEnabled())
- {
- log.trace("ResponseWriter created had a null CharacterEncoding, defaulting to UTF-8");
- }
+ return null;
}
- return encoding;
+ return param;
}
+ private void _initializeBuffer(ExternalContext context)
+ {
+ _bufferSize = _getIntegerParameter(context, PARAM_BUFFER_SIZE, -1);
+ }
+
+ private void _initializeMode(ExternalContext context)
+ {
+ _buildBeforeRestore = _getBooleanParameter(context, PARAM_BUILD_BEFORE_RESTORE, false);
+ }
+
/**
- * Generate the content type
+ * Determines if the application is currently in devlopment mode.
*
- * @param context
- * @param orig
- * @return
+ * @param context the current FacesContext
+ *
+ * @return <code>true</code> if the application is in devlopment mode, <code>false</code> otherwise
*/
- protected String getResponseContentType(FacesContext context, String orig)
+ private boolean _isDevelopmentMode(FacesContext context)
{
- String contentType = orig;
+ return ProjectStage.Development.equals(context.getApplication().getProjectStage());
+ }
- // see if we need to override the contentType
- Map<String, Object> m = context.getExternalContext().getRequestMap();
- if (m.containsKey("facelets.ContentType"))
+ private class FaceletViewMetadata extends ViewMetadataBase
+ {
+ /**
+ *
+ */
+ public FaceletViewMetadata(String viewId)
{
- contentType = (String) m.get("facelets.ContentType");
- if (log.isTraceEnabled())
- {
- log.trace("Facelet specified alternate contentType '" + contentType + "'");
- }
+ super(viewId);
}
- // safety check
- if (contentType == null)
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public UIViewRoot createMetadataView(FacesContext context)
{
- contentType = "text/html";
- if (log.isTraceEnabled())
+ try
{
- log.trace("ResponseWriter created had a null ContentType, defaulting to text/html");
+ context.setProcessingEvents(false);
+
+ String viewId = getViewId();
+ UIViewRoot view = createView(context, viewId);
+ buildView(context, view);
+
+ return view;
+ }
+ catch (IOException ioe)
+ {
+ throw new FacesException(ioe);
+ }
+ finally
+ {
+ context.setProcessingEvents(true);
}
}
-
- return contentType;
}
+
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguageStrategy.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguageStrategy.java?rev=799109&r1=799108&r2=799109&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguageStrategy.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguageStrategy.java Wed Jul 29 22:42:40 2009
@@ -30,28 +30,28 @@
/**
* @author Simon Lessard (latest modification by $Author: slessard $)
* @version $Revision: 696523 $ $Date: 2009-03-22 13:15:03 -0400 (mer., 17 sept. 2008) $
- *
+ *
* @since 2.0
*/
public class FaceletViewDeclarationLanguageStrategy implements ViewDeclarationLanguageStrategy
{
private Pattern _acceptPatterns;
private String _extension;
-
+
private ViewDeclarationLanguage _language;
-
+
public FaceletViewDeclarationLanguageStrategy()
{
- ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
-
- _acceptPatterns = loadAcceptPattern(context);
-
- _extension = loadFaceletExtension(context);
-
- _language = new FaceletViewDeclarationLanguage
- (FacesContext.getCurrentInstance().getApplication().getViewHandler());
+ FacesContext context = FacesContext.getCurrentInstance();
+ ExternalContext eContext = context.getExternalContext();
+
+ _acceptPatterns = loadAcceptPattern(eContext);
+
+ _extension = loadFaceletExtension(eContext);
+
+ _language = new FaceletViewDeclarationLanguage(context);
}
-
+
/**
* {@inheritDoc}
*/
@@ -68,38 +68,46 @@
// Check extension first as it's faster than mappings
if (viewId.endsWith(_extension))
{
+ // If the extension matches, it's a Facelet viewId.
return true;
}
-
-
- // Try to match the view identifier with the facelet mappings
+
+ // Otherwise, try to match the view identifier with the facelet mappings
return _acceptPatterns != null && _acceptPatterns.matcher(viewId).matches();
}
-
+
+ /**
+ * Load and compile a regular expression pattern built from the Facelet view mapping parameters.
+ *
+ * @param context
+ * the application's external context
+ *
+ * @return the compiled regular expression
+ */
private Pattern loadAcceptPattern(ExternalContext context)
{
assert context != null;
-
+
String mappings = context.getInitParameter(ViewHandler.FACELETS_VIEW_MAPPINGS_PARAM_NAME);
if (mappings == null)
{
return null;
}
-
+
// Make sure the mappings contain something
mappings = mappings.trim();
if (mappings.length() == 0)
{
return null;
}
-
+
return Pattern.compile(toRegex(mappings));
}
-
+
private String loadFaceletExtension(ExternalContext context)
{
assert context != null;
-
+
String suffix = context.getInitParameter(ViewHandler.FACELETS_SUFFIX_PARAM_NAME);
if (suffix == null)
{
@@ -113,33 +121,34 @@
suffix = ViewHandler.DEFAULT_FACELETS_SUFFIX;
}
}
-
+
return suffix;
}
-
+
/**
* Convert the specified mapping string to an equivalent regular expression.
*
- * @param mappings le mapping string
+ * @param mappings
+ * le mapping string
*
* @return an uncompiled regular expression representing the mappings
*/
private String toRegex(String mappings)
{
assert mappings != null;
-
+
// Get rid of spaces
mappings = mappings.replaceAll("\\s", "");
-
+
// Escape '.'
mappings = mappings.replaceAll("\\.", "\\\\.");
-
+
// Change '*' to '.*' to represent any match
mappings = mappings.replaceAll("\\*", ".*");
-
+
// Split the mappings by changing ';' to '|'
mappings = mappings.replaceAll(";", "|");
-
+
return mappings;
}
}