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;
     }
 }