001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.myfaces.lifecycle;
020:
021: import javax.faces.FacesException;
022: import javax.faces.application.Application;
023: import javax.faces.application.ViewExpiredException;
024: import javax.faces.application.ViewHandler;
025: import javax.faces.component.UIViewRoot;
026: import javax.faces.context.ExternalContext;
027: import javax.faces.context.FacesContext;
028: import javax.faces.event.PhaseId;
029: import javax.portlet.PortletRequest;
030:
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033: import org.apache.myfaces.portlet.MyFacesGenericPortlet;
034: import org.apache.myfaces.portlet.PortletUtil;
035: import org.apache.myfaces.util.DebugUtils;
036:
037: /**
038: * Implements the Restore View Phase (JSF Spec 2.2.1)
039: *
040: * @author Nikolay Petrov
041: * @author Bruno Aranda (JSF 1.2)
042: * @version $Revision: 517403 $ $Date: 2007-03-12 22:17:00 +0100 (Mo, 12 Mrz 2007) $
043: *
044: */
045: class RestoreViewExecutor implements PhaseExecutor {
046:
047: private static final Log log = LogFactory
048: .getLog(LifecycleImpl.class);
049: private RestoreViewSupport _restoreViewSupport;
050:
051: public boolean execute(FacesContext facesContext) {
052: if (facesContext == null) {
053: throw new FacesException("FacesContext is null");
054: }
055:
056: // init the View
057: Application application = facesContext.getApplication();
058: ViewHandler viewHandler = application.getViewHandler();
059: viewHandler.initView(facesContext);
060:
061: UIViewRoot viewRoot = facesContext.getViewRoot();
062:
063: RestoreViewSupport restoreViewSupport = getRestoreViewSupport();
064:
065: if (viewRoot != null) {
066: if (log.isTraceEnabled())
067: log.trace("View already exists in the FacesContext");
068:
069: viewRoot.setLocale(facesContext.getExternalContext()
070: .getRequestLocale());
071: restoreViewSupport.processComponentBinding(facesContext,
072: viewRoot);
073: return false;
074: }
075:
076: String viewId = restoreViewSupport
077: .calculateViewId(facesContext);
078:
079: // Determine if this request is a postback or initial request
080: if (restoreViewSupport.isPostback(facesContext)) {
081: if (log.isTraceEnabled())
082: log.trace("Request is a postback");
083:
084: viewRoot = viewHandler.restoreView(facesContext, viewId);
085: if (viewRoot == null) {
086: throw new ViewExpiredException(
087: "The expected view was not returned "
088: + "for the view identifier: " + viewId,
089: viewId);
090: }
091: restoreViewSupport.processComponentBinding(facesContext,
092: viewRoot);
093: } else {
094: if (log.isTraceEnabled())
095: log
096: .trace("Request is not a postback. New UIViewRoot will be created");
097:
098: viewRoot = viewHandler.createView(facesContext, viewId);
099: facesContext.renderResponse();
100: }
101:
102: facesContext.setViewRoot(viewRoot);
103:
104: return false;
105: }
106:
107: protected RestoreViewSupport getRestoreViewSupport() {
108: if (_restoreViewSupport == null) {
109: _restoreViewSupport = new DefaultRestoreViewSupport();
110: }
111: return _restoreViewSupport;
112: }
113:
114: /**
115: * @param restoreViewSupport
116: * the restoreViewSupport to set
117: */
118: public void setRestoreViewSupport(
119: RestoreViewSupport restoreViewSupport) {
120: _restoreViewSupport = restoreViewSupport;
121: }
122:
123: public PhaseId getPhase() {
124: return PhaseId.RESTORE_VIEW;
125: }
126:
127: /**
128: * TODO place that stuff into the default view handler implementation.
129: */
130: private static String deriveViewId(FacesContext facesContext) {
131: ExternalContext externalContext = facesContext
132: .getExternalContext();
133:
134: if (PortletUtil.isPortletRequest(facesContext)) {
135: PortletRequest request = (PortletRequest) externalContext
136: .getRequest();
137: return request.getParameter(MyFacesGenericPortlet.VIEW_ID);
138: }
139:
140: String viewId = externalContext.getRequestPathInfo(); // getPathInfo
141: if (viewId == null) {
142: // No extra path info found, so it is propably extension mapping
143: viewId = externalContext.getRequestServletPath(); // getServletPath
144: DebugUtils
145: .assertError(viewId != null, log,
146: "RequestServletPath is null, cannot determine viewId of current page.");
147: if (viewId == null)
148: return null;
149:
150: // TODO: JSF Spec 2.2.1 - what do they mean by "if the default
151: // ViewHandler implementation is used..." ?
152: String defaultSuffix = externalContext
153: .getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
154: String suffix = defaultSuffix != null ? defaultSuffix
155: : ViewHandler.DEFAULT_SUFFIX;
156: DebugUtils.assertError(suffix.charAt(0) == '.', log,
157: "Default suffix must start with a dot!");
158:
159: int dot = viewId.lastIndexOf('.');
160: if (dot == -1) {
161: log
162: .error("Assumed extension mapping, but there is no extension in "
163: + viewId);
164: viewId = null;
165: } else {
166: viewId = viewId.substring(0, dot) + suffix;
167: }
168: }
169:
170: return viewId;
171: }
172: }
|