All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jsftemplating.layout.LayoutViewHandler Maven / Gradle / Ivy

/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://jsftemplating.dev.java.net/cddl1.html or
 * jsftemplating/cddl1.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at jsftemplating/cddl1.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */
package com.sun.jsftemplating.layout;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Stack;
import java.util.Set;
import java.util.HashSet;

import javax.faces.FactoryFinder;
import javax.faces.application.StateManager;
import javax.faces.application.ViewHandler;
import javax.faces.application.StateManager.SerializedView;
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.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sun.jsftemplating.el.PageSessionResolver;
import com.sun.jsftemplating.layout.descriptors.LayoutComponent;
import com.sun.jsftemplating.layout.descriptors.LayoutComposition;
import com.sun.jsftemplating.layout.descriptors.LayoutDefinition;
import com.sun.jsftemplating.layout.descriptors.LayoutElement;
import com.sun.jsftemplating.layout.descriptors.LayoutFacet;
import com.sun.jsftemplating.layout.descriptors.LayoutInsert;
import com.sun.jsftemplating.layout.descriptors.Resource;
import com.sun.jsftemplating.util.LayoutElementUtil;
import com.sun.jsftemplating.util.LogUtil;
import com.sun.jsftemplating.util.SimplePatternMatcher;
import com.sun.jsftemplating.util.TypeConversion;
import com.sun.jsftemplating.util.TypeConverter;
import com.sun.jsftemplating.util.UIComponentTypeConversion;
import com.sun.jsftemplating.util.fileStreamer.Context;
import com.sun.jsftemplating.util.fileStreamer.FacesStreamerContext;
import com.sun.jsftemplating.util.fileStreamer.FileStreamer;


// FIXME: Things to consider:
// FIXME:   - What is necessary to support Portlets...
// FIXME:   - Should I attempt to clean up old unused UIComponents?
// FIXME:   - f:view supported setting locale, I should too...

/**
 *  

This class provides a custom ViewHandler that is able to * create and populate a UIViewRoot from a * {@link LayoutDefinition}. This is often defined by an XML document, * the default implementation's DTD is defined in * layout.dtd.

* *

Besides the default ViewHandler behavior, this class is * responsible for using the given viewId as the * {@link LayoutDefinition} key and setting it on the UIViewRoot that is * created. It will obtain the {@link LayoutDefinition}, initialize the * declared {@link Resource}s, and instantiate UIComponent * tree using the {@link LayoutDefinition}'s declared * {@link LayoutComponent} structure. During rendering, it delegates to * the {@link LayoutDefinition}.

* * @author Ken Paulsen ([email protected]) */ public class LayoutViewHandler extends ViewHandler { /** *

Constructor.

* * @param oldViewHandler The old ViewHandler. */ public LayoutViewHandler(ViewHandler oldViewHandler) { _oldViewHandler = oldViewHandler; // FIXME: Fire an initializtion event, work out how to listen for this event // This is added here to ensure that if the ViewHandler is reloaded in // a running application, that handlers, ct's, and resources will get // re-read. Ryan added a feature which may introduce this code path. LayoutDefinitionManager.clearGlobalComponentTypes(null); LayoutDefinitionManager.clearGlobalHandlerDefinitions(null); LayoutDefinitionManager.clearGlobalResources(null); } /** *

Initialize the view for the request processing lifecycle. It is * called at the beginning of the Restore View phase.

public void initView(FacesContext context) throws FacesException { // Not used yet... I left this here as a reminder that it is here } */ /** *

This method is invoked when restoreView does not yield a * UIViewRoot (initial requests and new pages).

* *

This implementation should work with both * {@link LayoutDefinition}-based pages as well as traditional * JSP pages (or other frameworks).

*/ public UIViewRoot createView(FacesContext context, String viewId) { //_time = new java.util.Date(); // Check to see if this is a resource request String path = getResourcePath(viewId); if (path != null) { // Serve Resource return serveResource(context, path); } // Check to see if jsftemplating should create the view if(!this.isMappedView(viewId)) { UIViewRoot viewRoot = _oldViewHandler.createView(context, viewId); return viewRoot; } Locale locale = null; String renderKitId = null; // use the locale from the previous view if is was one which will be // the case if this is called from NavigationHandler. There wouldn't be // one for the initial case. if (context.getViewRoot() != null) { UIViewRoot oldViewRoot = context.getViewRoot(); LayoutDefinition oldLD = ViewRootUtil.getLayoutDefinition(oldViewRoot); if ((oldLD != null) && oldViewRoot.getViewId().equals(viewId)) { // If you navigate to the page you are already on, JSF will // re-create the UIViewRoot of the current page. The initPage // event needs to be reset so that it will re-execute itself. oldLD.setInitPageExecuted(context, Boolean.FALSE); } locale = context.getViewRoot().getLocale(); renderKitId = context.getViewRoot().getRenderKitId(); } // Create the ViewRoot UIViewRoot viewRoot = _oldViewHandler.createView(context, viewId); viewRoot.setViewId(viewId); ViewRootUtil.setLayoutDefinitionKey(viewRoot, viewId); // if there was no locale from the previous view, calculate the locale // for this view. if (locale == null) { locale = calculateLocale(context); } viewRoot.setLocale(locale); // set the renderkit if (renderKitId == null) { renderKitId = calculateRenderKitId(context); } viewRoot.setRenderKitId(renderKitId); // Save the current viewRoot, temporarily set the new UIViewRoot so // beforeCreate, afterCreate will function correctly UIViewRoot currentViewRoot = context.getViewRoot(); // Set the View Root to the new viewRoot // NOTE: This must happen after return _oldViewHandler.createView(...) // NOTE2: However, we really want the UIViewRoot available during // initPage events which are fired during // getLayoutDefinition()... so we need to set this, then unset // it if we go through _oldViewHandler.createView(...) context.setViewRoot(viewRoot); // Initialize Resources / Create Tree LayoutDefinition def = null; try { def = ViewRootUtil.getLayoutDefinition(viewRoot); } catch (LayoutDefinitionException ex) { if (LogUtil.configEnabled()) { LogUtil.config("JSFT0005", (Object) viewId); if (LogUtil.finestEnabled()) { LogUtil.finest( "File (" + viewId + ") not found!", ex); } } // Restore original ViewRoot, we set it prematurely if (currentViewRoot != null) { // FIXME: Talk to Ryan about restoring the ViewRoot to null!! context.setViewRoot(currentViewRoot); } // FIXME: Provide better feedback when no .jsf & no .jsp // FIXME: Difficult to tell at this stage if no .jsp is present // Not found, delegate to old ViewHandler return _oldViewHandler.createView(context, viewId); } catch (RuntimeException ex) { // Restore original ViewRoot, we set it prematurely if (currentViewRoot != null) { // FIXME: Talk to Ryan about restoring the ViewRoot to null!! context.setViewRoot(currentViewRoot); } // Allow error to be thrown (this isn't the normal code path) throw ex; } // We need to do this again b/c an initPage handler may have changed // the viewRoot viewRoot = context.getViewRoot(); // Check to make sure we found a LD and that the response isn't // already finished (initPage could complete the response... // i.e. during a redirect). if ((def != null) && !context.getResponseComplete()) { // Ensure that our Resources are available Iterator it = def.getResources().iterator(); Resource resource = null; while (it.hasNext()) { resource = it.next(); // Just calling getResource() puts it in the Request scope resource.getFactory().getResource(context, resource); } // Get the Tree and pre-walk it if (LayoutDefinitionManager.isDebug(context)) { // Make sure to reset all the client ids we're about to check getClientIdMap(context).clear(); } buildUIComponentTree(context, viewRoot, def); } // Restore the current UIViewRoot if (currentViewRoot != null) { context.setViewRoot(currentViewRoot); } // Return the populated UIViewRoot return viewRoot; } /** *

Tests if the provided viewId matches one of the * configured view-mappings. If no view-mappings are defined, all * viewIds will match.

* * @param viewId The viewId to be tested. * * @return true If the viewId matched or no view-mappings are defined, * false otherwise. * @since 1.2 */ private boolean isMappedView(String viewId) { if (this._viewMappings == null) { String initParam = (String) FacesContext.getCurrentInstance(). getExternalContext().getInitParameterMap().get(VIEW_MAPPINGS); this._viewMappings = SimplePatternMatcher. parseMultiPatternString(initParam, ";"); } if (this._viewMappings.isEmpty()) { return true; } for (SimplePatternMatcher mapping : this._viewMappings) { if (mapping.matches(viewId)) { return true; } } return false; } /** *

If this is a resource request, this method will handle the * request.

*/ public static UIViewRoot serveResource(FacesContext context, String path) { // Mark the response complete so no more processing occurs context.responseComplete(); // Create dummy UIViewRoot UIViewRoot root = new UIViewRoot(); root.setRenderKitId("dummy"); // Setup the FacesStreamerContext Context fsContext = new FacesStreamerContext(context); fsContext.setAttribute(Context.FILE_PATH, path); // Get the HttpServletResponse Object obj = context.getExternalContext().getResponse(); HttpServletResponse resp = null; if (obj instanceof HttpServletResponse) { resp = (HttpServletResponse) obj; // We have an HttpServlet response, do some extra stuff... // Check the last modified time to see if we need to serve the resource long mod = fsContext.getContentSource().getLastModified(fsContext); if (mod != -1) { long ifModifiedSince = ((HttpServletRequest) context.getExternalContext().getRequest()). getDateHeader("If-Modified-Since"); // Round down to the nearest second for a proper compare if (ifModifiedSince < (mod / 1000 * 1000)) { // A ifModifiedSince of -1 will always be less resp.setDateHeader("Last-Modified", mod); } else { // Set not modified header and complete response resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return root; } } } // Stream the content try { FileStreamer.getFileStreamer(context).streamContent(fsContext); } catch (FileNotFoundException ex) { if (LogUtil.infoEnabled()) { LogUtil.info("JSFT0004", (Object) path); } if (resp != null) { try { ((HttpServletResponse) resp).sendError( HttpServletResponse.SC_NOT_FOUND); } catch (IOException ioEx) { // Ignore } } } catch (IOException ex) { if (LogUtil.infoEnabled()) { LogUtil.info("JSFT0004", (Object) path); if (LogUtil.fineEnabled()) { LogUtil.fine( "Resource (" + path + ") not available!", ex); } } // FIXME: send 404? } // Return dummy UIViewRoot to avoid NPE return root; } /** *

Returns the current encoding type.

* * @param ctx The FacesContext. */ public static String getEncoding(FacesContext ctx) { // Sanity check if (ctx == null) { return null; } String encType = null; UIViewRoot root = ctx.getViewRoot(); Map map = PageSessionResolver.getPageSession(ctx, root); if (map != null) { //check for page session encType = (String) map.get(ENCODING_TYPE); } if ((encType == null) || encType.equals("")) { //check for application level encType = ctx.getExternalContext().getInitParameter(ENCODING_TYPE); } if ((encType == null) || encType.equals("")) { ExternalContext extCtx = ctx.getExternalContext(); try { ServletRequest request = (ServletRequest) extCtx.getRequest(); encType = request.getCharacterEncoding(); } catch (Exception ex) { // FIXME: Portlet? } if ((encType == null) || encType.equals("")) { //default encoding type encType="UTF-8"; } } return encType; } /** *

This method checks the given viewId and returns a the path to the * requested resource if it refers to a resource. Resources are * things like JavaScript files, images, etc. Basically anything that * is not a JSF page that you'd like to serve up via the FacesServlet. * Serving resources this way allows you to bundle the resources in a * jar file, this is useful if you want to package up part of an app * (or a JSF component) in a single file.

* *

A request for a resource must be prefixed by the resource prefix, * see @{link #getResourcePrefixes}. This prefix must also be mapped to * the FacesServlet in order for this class to handle the * request.

*/ public String getResourcePath(String viewId) { ExternalContext extCtx = FacesContext.getCurrentInstance().getExternalContext(); // FIXME: Portlet! String servletPath = extCtx.getRequestServletPath(); Iterator it = getResourcePrefixes().iterator(); while (it.hasNext()) { if (servletPath.equals(it.next())) { return extCtx.getRequestPathInfo(); } } return null; } /** *

This method returns the prefix that a URL must contain in order to * retrieve a "resource" through this ViewHandler.

* *

The prefix itself does not manifest itself in the file system / * classpath.

* *

If the prefix is not set, then an init parameter (see * {@link #RESOURCE_PREFIX}) will be checked. If that is still not * specified, then the {@link #DEFAULT_RESOURCE_PREFIX} will be * used.

*/ public Set getResourcePrefixes() { if (_resourcePrefix == null) { HashSet set = new HashSet(); // Check to see if it's specified by a context param // Get context parameter map (initParams in JSF are context params) String initParam = (String) FacesContext.getCurrentInstance(). getExternalContext().getInitParameterMap().get(RESOURCE_PREFIX); if (initParam != null) { for(String token: initParam.split(",")) { set.add(token.trim()); } } // Add default... set.add(DEFAULT_RESOURCE_PREFIX); _resourcePrefix = set; } return _resourcePrefix; } /** *

This method allows a user to set the resource prefix which will be * checked to obtain a resource via this Viewhandler. * Currently, only 1 prefix is supported. The prefix itself does not * manifest itself in the file system / classpath.

*/ public void setResourcePrefixes(Set prefix) { _resourcePrefix = prefix; } /** *

This method iterates over the child {@link LayoutElement}s of the * given elt to create UIComponents for each * {@link LayoutComponent}.

* * @param context The FacesContext. * @param parent The parent UIComponent of the * UIComponent to be found or created. * @param elt The LayoutElement driving everything. */ public static void buildUIComponentTree(FacesContext context, UIComponent parent, LayoutElement elt) { // FIXME: Consider processing *ALL* LayoutElements so that and others // FIXME: have meaning when inside other components. Iterator it = elt.getChildLayoutElements().iterator(); LayoutElement childElt; UIComponent child = null; while (it.hasNext()) { childElt = it.next(); if (childElt instanceof LayoutFacet) { if (!((LayoutFacet) childElt).isRendered()) { // The contents of this should be a single UIComponent buildUIComponentTree(context, parent, childElt); } // NOTE: LayoutFacets that aren't JSF facets aren't // NOTE: meaningful in this context } else if (childElt instanceof LayoutComposition) { LayoutComposition compo = ((LayoutComposition) childElt); String template = compo.getTemplate(); if (template != null) { // Add LayoutComposition to the stack LayoutComposition.push(context, childElt); try { // Add the template here. buildUIComponentTree(context, parent, LayoutDefinitionManager.getLayoutDefinition( context, template)); } catch (LayoutDefinitionException ex) { if (((LayoutComposition) childElt).isRequired()) { throw ex; } } // Remove the LayoutComposition from the stack LayoutComposition.pop(context); } else { // In this case we don't have a template, so instead we // render the body buildUIComponentTree(context, parent, childElt); } } else if (childElt instanceof LayoutInsert) { Stack stack = LayoutComposition.getCompositionStack(context); if (stack.empty()) { // No template-client found... // Is this supposed to do nothing? Or throw an exception? throw new IllegalArgumentException( "'ui:insert' encountered, however, no " + "'ui:composition' was used!"); } // Get associated UIComposition String insertName = ((LayoutInsert) childElt).getName(); if (insertName == null) { // include everything buildUIComponentTree(context, parent, stack.get(0)); } else { // First resolve any EL in the insertName insertName = "" + ((LayoutInsert) childElt).resolveValue( context, parent, insertName); // Search for specific LayoutDefine LayoutElement def = LayoutInsert.findLayoutDefine( context, parent, stack, insertName); if (def == null) { // Not found include the body-content of the insert buildUIComponentTree(context, parent, childElt); } else { // Found, include the ui:define content buildUIComponentTree(context, parent, def); } } } else if (childElt instanceof LayoutComponent) { // Calling getChild will add the child UIComponent to tree child = ((LayoutComponent) childElt). getChild(context, parent); if (LayoutDefinitionManager.isDebug(context)) { // To help developer avoid duplicate ids, we'll check the // ids here. Map idMap = getClientIdMap(context); String id = child.getClientId(context); if (idMap.containsKey(id)) { throw new IllegalArgumentException("The clientId (" + id + ") appears more than once! Make sure you " + "have not included multiple times in the same " + "NamingContainer."); } idMap.put(id, id); } // Check for events // NOTE: For now I am only supporting "action" and // NOTE: "actionListener" event types. In the future it // NOTE: may be desirable to support beforeEncode / // NOTE: afterEncode as well. At this time, those events // NOTE: are supported by the "Event" UIComponent. That // NOTE: component can wrap non-layout-based components to // NOTE: achieve this functionality (supporting that // NOTE: functionality here will simply do the same thing // NOTE: automatically). // Recurse buildUIComponentTree(context, child, childElt); } else { buildUIComponentTree(context, parent, childElt); } } } /** *

This method provides access to a Map of clientIds * that have been used in this page.

*/ private static Map getClientIdMap(FacesContext context) { Map reqMap = context.getExternalContext().getRequestMap(); Map idMap = (Map) reqMap.get("__debugIdMap"); if (idMap == null) { idMap = new HashMap(); reqMap.put("__debugIdMap", idMap); } return idMap; } /** *

This implementation relies on the default behavior to reconstruct * the UIViewRoot.

* *

...

*/ public UIViewRoot restoreView(FacesContext context, String viewId) { //_time = new java.util.Date(); Map map = context.getExternalContext().getRequestMap(); if (map.get(RESTORE_VIEW_ID) == null) { map.put(RESTORE_VIEW_ID, viewId); } else { // This request has already been processed, it must be a forward() return createView(context, viewId); } // Perform default behavior... UIViewRoot root = _oldViewHandler.restoreView(context, viewId); // We can check for JSFT UIViewRoots by calling // getLayoutDefinitionKey(root) as this will return null if not JSFT if (root != null) { String key = ViewRootUtil.getLayoutDefinitionKey(root); if (key != null) { // Set the View Root to the new viewRoot (needed for initPage) // NOTE: See createView note about saving / restoring the // NOTE: original UIViewRoot and issue with setting it to // NOTE: (null). restoreView is less important b/c it is not // NOTE: normally called by a developer or framework as // NOTE: navigation rules will call createView. For this // NOTE: reason, I am not resetting the UIViewRoot for now. context.setViewRoot(root); // Call getLayoutDefinition() to ensure initPage events are // fired, only do this for JSFT ViewRoots. Its good to call // this after restoreView as we need the UIViewRoot available // during initPage events. Formerly this was done during the // ApplyRequestValuesPhase, however, I no longer have a custom // UIViewRoot to use for this purpose, so I will do it here, // which should be just as good. LayoutDefinition def = ViewRootUtil.getLayoutDefinition(key); // While we're at it, we should call the LD decode() event so // we can provide a page-level decode() functionality. This // won't effect components in the page, or JSFT-based // components. def.decode(context, root); } } // Return the UIViewRoot return root; } /** * */ public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException { // Make sure we have a def LayoutDefinition def = ViewRootUtil.getLayoutDefinition(viewToRender); if (def == null) { // PartialRequest or No def, fall back to default behavior _oldViewHandler.renderView(context, viewToRender); } else { // Start document if (!context.getPartialViewContext().isPartialRequest() || context.getPartialViewContext().isRenderAll()) { ResponseWriter writer = setupResponseWriter(context); writer.startDocument(); // Render content def.encode(context, viewToRender); // End document writer.endDocument(); } else { // NOTE: This "if" branch has been added to avoid the // NOTE: start/endDocument calls being called 2x on PartialView // NOTE: requests. JSF Issue #1307 has been filed to resolve // NOTE: this correctly (assuming checking here is not // NOTE: correct... which I do not feel that it is). // // Render content def.encode(context, viewToRender); } } //System.out.println("PROCESSING TIME: " + (new java.util.Date().getTime() - _time.getTime())); } private static void renderComponent(FacesContext context, UIComponent comp) throws IOException { if (!comp.isRendered()) { return; } comp.encodeBegin(context); if (comp.getRendersChildren()) { comp.encodeChildren(context); } else { UIComponent child = null; Iterator it = comp.getChildren().iterator(); while (it.hasNext()) { child = it.next(); renderComponent(context, child); } } comp.encodeEnd(context); } /** * */ private ResponseWriter setupResponseWriter(FacesContext context) throws IOException { ResponseWriter writer = context.getResponseWriter(); if (writer != null) { // It is already setup return writer; } ExternalContext extCtx = context.getExternalContext(); // FIXME: Portlet? ServletResponse response = (ServletResponse) extCtx.getResponse(); RenderKitFactory renderFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY); RenderKit renderKit = renderFactory.getRenderKit(context, context.getViewRoot().getRenderKitId()); // See if the user (page author) specified a ContentType... String contentTypeList = null; // FIXME: Provide a way for the user to specify this... // FIXME: Test multiple browsers against this code!! String userContentType = "text/html"; if((userContentType != null) && (userContentType.length() > 0)) { // User picked this, use it... response.setContentType(userContentType); } else { // No explicit Content-type, find best match... contentTypeList = (String) extCtx.getRequestHeaderMap().get("Accept"); if (contentTypeList == null) { contentTypeList = "text/html;q=1.0"; } } String encType = getEncoding(context); // Object encValue = extCtx.getSessionMap().get( // ViewHandler.CHARACTER_ENCODING_KEY); extCtx.getSessionMap().put(ViewHandler.CHARACTER_ENCODING_KEY, encType); // FIXME: use the external context to set the character encoding, it is supported response.setCharacterEncoding(encType); // FIXME: Portlet? writer = renderKit.createResponseWriter( new OutputStreamWriter(response.getOutputStream(), encType), contentTypeList, encType); context.setResponseWriter(writer); // Not setting the contentType here results in XHTML which formats differently // than text/html in Mozilla.. even though the documentation claims this // works, it doesn't (try viewing the Tree) // response.setContentType("text/html"); // As far as I can tell JSF doesn't ever set the Content-type that it // works so hard to calculate... This is the code we should be // calling, however we can't do this yet response.setContentType(writer.getContentType()); return writer; } /** *

Take any appropriate action to either immediately write out the * current state information (by calling * StateManager.writeState, or noting where state * information should later be written.

* * @param context FacesContext for the current request * * @exception IOException if an input/output error occurs */ public void writeState(FacesContext context) throws IOException { // Check to see if we should delegate back to the legacy ViewHandler UIViewRoot root = context.getViewRoot(); // FIXME: For now I am treating "@all" Ajax requests as normal requests... // FIXME: Otherwise the view state is not written. if ((root == null) || (context.getPartialViewContext().isPartialRequest() && !context.getPartialViewContext().isRenderAll()) || (ViewRootUtil.getLayoutDefinition(root) == null)) { // Use old behavior... _oldViewHandler.writeState(context); } else { // b/c we pre-processed the ViewTree, we can just add it... StateManager stateManager = context.getApplication().getStateManager(); SerializedView view = stateManager.saveSerializedView(context); // New versions of JSF 1.2 changed the contract so that state is // always written (client and server state saving) stateManager.writeState(context, view); } } /** *

Return a URL suitable for rendering (after optional encoding * performed by the encodeResourceURL() method of * ExternalContext that selects the specified web * application resource. If the specified path starts with a slash, * it must be treated as context relative; otherwise, it must be * treated as relative to the action URL of the current view.

* * @param context FacesContext for the current request * @param path Resource path to convert to a URL * * @exception IllegalArgumentException If viewId is not * valid for this ViewHandler. */ public String getResourceURL(FacesContext context, String path) { return _oldViewHandler.getResourceURL(context, path); } /** *

Return a URL suitable for rendering (after optional encoding * performed by the encodeActionURL() method of * ExternalContext that selects the specified view * identifier.

* * @param context FacesContext for this request * @param viewId View identifier of the desired view * * @exception IllegalArgumentException If viewId is not * valid for this ViewHandler. */ public String getActionURL(FacesContext context, String viewId) { return _oldViewHandler.getActionURL(context, viewId); } /** *

Returns an appropriate Locale to use for this and * subsequent requests for the current client.

* * @param context FacesContext for the current request * * @exception NullPointerException if context is * null */ public Locale calculateLocale(FacesContext context) { return _oldViewHandler.calculateLocale(context); } /** *

Return an appropriate renderKitId for this * and subsequent requests from the current client.

* *

The default return value is * javax.faces.render.RenderKitFactory.HTML_BASIC_RENDER_KIT. *

* * @param context FacesContext for the current request. */ public String calculateRenderKitId(FacesContext context) { return _oldViewHandler.calculateRenderKitId(context); } /** *

This is the key that may be used to identify the clientId of the * UIComponent that is to be updated via an Ajax request.

*/ public static final String AJAX_REQ_KEY = "ajaxReq"; public static final String RESTORE_VIEW_ID = "_resViewID"; /** *

This is the default prefix that must be included on all requests * for resources.

*/ public static final String DEFAULT_RESOURCE_PREFIX = "/resource"; /** *

The name of the context-param to set the resource * prefix.

*/ public static final String RESOURCE_PREFIX = "com.sun.jsftemplating.RESOURCE_PREFIX"; private Set _resourcePrefix = null; //private transient java.util.Date _time = null; private ViewHandler _oldViewHandler = null; static final String AJAX_REQ_TARGET_KEY = "_ajaxReqTarget"; /** *

The name of the context-param to set the view mappings

*/ // TODO: should these keys be added to a new Class f.e. com.sun.jsftemplating.Keys? private static final String VIEW_MAPPINGS = "com.sun.jsftemplating.VIEW_MAPPINGS"; /** * */ private static final TypeConversion UICOMPONENT_TYPE_CONVERSION = new UIComponentTypeConversion(); /* *

This is intended to initialize additional type conversions * for the {@link TypeConverter}. These additional type conversions * are typically specific to JSF or JSFTemplating. If you are * reading this and want additional custom type conversions, bug * Ken Paulsen to add an init event which will allow you to easily * initialize your own type conversions.

*/ static { // Add type conversions by class TypeConverter.registerTypeConversion(null, UIComponent.class, UICOMPONENT_TYPE_CONVERSION); // Add type conversions by class name TypeConverter.registerTypeConversion(null, UIComponent.class.getName(), UICOMPONENT_TYPE_CONVERSION); } private Collection _viewMappings = null; /** *

This key can be used to override the encoding type used in your * application.

*/ public static final String ENCODING_TYPE="com.sun.jsftemplating.ENCODING"; }