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.application;
020:
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023: import org.apache.myfaces.shared_impl.webapp.webxml.ServletMapping;
024: import org.apache.myfaces.shared_impl.webapp.webxml.WebXml;
025:
026: import javax.faces.application.ViewHandler;
027: import javax.faces.context.ExternalContext;
028: import javax.faces.context.FacesContext;
029: import java.util.List;
030: import java.util.Map;
031:
032: /**
033: * @author Mathias Broekelmann (latest modification by $Author: baranda $)
034: * @version $Revision: 534632 $ $Date: 2007-05-03 00:13:12 +0200 (Do, 03 Mai 2007) $
035: */
036: public class DefaultViewHandlerSupport implements ViewHandlerSupport {
037: private static final String SERVLET_MAPPING = DefaultViewHandlerSupport.class
038: .getName()
039: + ".ServletMapping";
040:
041: private static final Log log = LogFactory
042: .getLog(DefaultViewHandlerSupport.class);
043:
044: public String calculateViewId(FacesContext context, String viewId) {
045: ServletMapping mapping = calculateServletMapping(context);
046: if (mapping == null || mapping.isExtensionMapping()) {
047: viewId = applyDefaultSuffix(context, viewId);
048: } else if (mapping != null && viewId != null
049: && mapping.getUrlPattern().startsWith(viewId)) {
050: throw new InvalidViewIdException(viewId);
051: }
052: return viewId;
053: }
054:
055: public String calculateActionURL(FacesContext context, String viewId) {
056: if (viewId == null || !viewId.startsWith("/"))
057: throw new IllegalArgumentException(
058: "ViewId must start with a '/': " + viewId);
059:
060: ServletMapping mapping = calculateServletMapping(context);
061: ExternalContext externalContext = context.getExternalContext();
062: String contextPath = externalContext.getRequestContextPath();
063: StringBuilder builder = new StringBuilder(contextPath);
064: if (mapping != null) {
065: if (mapping.isExtensionMapping()) {
066: String contextSuffix = getContextSuffix(context);
067: if (viewId.endsWith(contextSuffix)) {
068: builder.append(viewId.substring(0, viewId
069: .indexOf(contextSuffix)));
070: builder.append(mapping.getExtension());
071: } else {
072: builder.append(viewId);
073: }
074: } else {
075: builder.append(mapping.getPrefix());
076: builder.append(viewId);
077: }
078: } else {
079: builder.append(viewId);
080: }
081: String calculatedActionURL = builder.toString();
082: if (log.isTraceEnabled()) {
083: log.trace("Calculated actionURL: '" + calculatedActionURL
084: + "' for viewId: '" + viewId + "'");
085: }
086: return calculatedActionURL;
087: }
088:
089: protected ServletMapping calculateServletMapping(
090: FacesContext context) {
091: ExternalContext externalContext = context.getExternalContext();
092: Map<String, Object> requestMap = externalContext
093: .getRequestMap();
094: ServletMapping mapping = null;
095: if (requestMap.containsKey(externalContext)) {
096: mapping = (ServletMapping) requestMap.get(SERVLET_MAPPING);
097: } else {
098: String servletPath = externalContext
099: .getRequestServletPath();
100: String requestPathInfo = externalContext
101: .getRequestPathInfo();
102:
103: WebXml webxml = WebXml.getWebXml(externalContext);
104: List mappings = webxml.getFacesServletMappings();
105:
106: if (requestPathInfo == null) {
107: // might be extension mapping
108: for (int i = 0, size = mappings.size(); i < size
109: && mapping == null; i++) {
110: ServletMapping servletMapping = (ServletMapping) mappings
111: .get(i);
112: String urlpattern = servletMapping.getUrlPattern();
113: String extension = urlpattern.substring(1,
114: urlpattern.length());
115: if (servletPath.endsWith(extension)) {
116: mapping = servletMapping;
117: } else if (servletPath.equals(urlpattern)) {
118: // path mapping with no pathInfo for the current request
119: mapping = servletMapping;
120: }
121: }
122: } else {
123: // path mapping
124: for (int i = 0, size = mappings.size(); i < size
125: && mapping == null; i++) {
126:
127: ServletMapping servletMapping = (ServletMapping) mappings
128: .get(i);
129: String urlpattern = servletMapping.getUrlPattern();
130: urlpattern = urlpattern.substring(0, urlpattern
131: .length() - 2);
132: // servletPath starts with "/" except in the case where the
133: // request is matched with the "/*" pattern, in which case
134: // it is the empty string (see Servlet Sepc 2.3 SRV4.4)
135: if (servletPath.equals(urlpattern)) {
136: mapping = servletMapping;
137: }
138: }
139: }
140:
141: // handle cases as best possible where servletPath is not a faces servlet,
142: // such as when coming through struts-faces
143: if (mapping == null && mappings.size() > 0) {
144: mapping = (ServletMapping) mappings.get(0);
145: }
146:
147: if (mapping == null && log.isWarnEnabled())
148: log.warn("no faces servlet mappings found");
149:
150: requestMap.put(SERVLET_MAPPING, mapping);
151: }
152: return mapping;
153: }
154:
155: protected String getContextSuffix(FacesContext context) {
156: String defaultSuffix = context
157: .getExternalContext()
158: .getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
159: if (defaultSuffix == null) {
160: defaultSuffix = ViewHandler.DEFAULT_SUFFIX;
161: }
162: return defaultSuffix;
163: }
164:
165: protected String applyDefaultSuffix(FacesContext context,
166: String viewId) {
167: String defaultSuffix = getContextSuffix(context);
168:
169: if (viewId == null) {
170: return null;
171: }
172:
173: if (!viewId.endsWith(defaultSuffix)) {
174: StringBuilder builder = new StringBuilder(viewId);
175: int index = viewId.lastIndexOf('.');
176: if (index != -1) {
177: builder.replace(index, viewId.length(), defaultSuffix);
178: } else {
179: builder.append(defaultSuffix);
180: }
181: viewId = builder.toString();
182: if (log.isTraceEnabled()) {
183: log.trace("view id after applying the context suffix: "
184: + viewId);
185: }
186: }
187: return viewId;
188: }
189: }
|