Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
BaseResourceHandlerSupport |
|
| 2.6363636363636362;2.636 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | package org.apache.myfaces.shared.resource; | |
20 | ||
21 | import java.util.Map; | |
22 | ||
23 | import javax.faces.context.ExternalContext; | |
24 | import javax.faces.context.FacesContext; | |
25 | ||
26 | import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam; | |
27 | import org.apache.myfaces.shared.application.FacesServletMapping; | |
28 | import org.apache.myfaces.shared.util.WebConfigParamUtils; | |
29 | ||
30 | /** | |
31 | * A ResourceHandlerSupport implementation for use with standard Java Servlet engines, | |
32 | * ie an engine that supports javax.servlet, and uses a standard web.xml file. | |
33 | */ | |
34 | public class BaseResourceHandlerSupport extends ResourceHandlerSupport | |
35 | { | |
36 | ||
37 | /** | |
38 | * Set the max time in miliseconds set on the "Expires" header for a resource rendered by | |
39 | * the default ResourceHandler. | |
40 | * (default to one week in miliseconds or 604800000) | |
41 | */ | |
42 | @JSFWebConfigParam(since="2.0", defaultValue="604800000", group="resources", tags="performance") | |
43 | public static final String RESOURCE_MAX_TIME_EXPIRES = "org.apache.myfaces.RESOURCE_MAX_TIME_EXPIRES"; | |
44 | ||
45 | /** | |
46 | * Identifies the FacesServlet mapping in the current request map. | |
47 | */ | |
48 | 0 | private static final String CACHED_SERVLET_MAPPING = |
49 | BaseResourceHandlerSupport.class.getName() + ".CACHED_SERVLET_MAPPING"; | |
50 | ||
51 | 0 | private static final ResourceLoader[] EMPTY_RESOURCE_LOADERS = new ResourceLoader[]{}; |
52 | 0 | private static final ContractResourceLoader[] EMPTY_CONTRACT_RESOURCE_LOADERS = |
53 | new ContractResourceLoader[]{}; | |
54 | ||
55 | private Long _startupTime; | |
56 | ||
57 | private Long _maxTimeExpires; | |
58 | ||
59 | public BaseResourceHandlerSupport() | |
60 | 0 | { |
61 | 0 | _startupTime = System.currentTimeMillis(); |
62 | 0 | } |
63 | ||
64 | public ResourceLoader[] getResourceLoaders() | |
65 | { | |
66 | 0 | return EMPTY_RESOURCE_LOADERS; |
67 | } | |
68 | ||
69 | public ContractResourceLoader[] getContractResourceLoaders() | |
70 | { | |
71 | 0 | return EMPTY_CONTRACT_RESOURCE_LOADERS; |
72 | } | |
73 | ||
74 | public ResourceLoader[] getViewResourceLoaders() | |
75 | { | |
76 | 0 | return EMPTY_RESOURCE_LOADERS; |
77 | } | |
78 | ||
79 | public String calculateResourceBasePath(FacesContext facesContext) | |
80 | { | |
81 | 0 | FacesServletMapping mapping = getFacesServletMapping(facesContext); |
82 | 0 | ExternalContext externalContext = facesContext.getExternalContext(); |
83 | ||
84 | 0 | if (mapping != null) |
85 | { | |
86 | 0 | String resourceBasePath = null; |
87 | 0 | if (mapping.isExtensionMapping()) |
88 | { | |
89 | // Mapping using a suffix. In this case we have to strip | |
90 | // the suffix. If we have a url like: | |
91 | // http://localhost:8080/testjsf20/javax.faces.resource/imagen.jpg.jsf?ln=dojo | |
92 | // | |
93 | // The servlet path is /javax.faces.resource/imagen.jpg.jsf | |
94 | // | |
95 | // For obtain the resource name we have to remove the .jsf suffix and | |
96 | // the prefix ResourceHandler.RESOURCE_IDENTIFIER | |
97 | 0 | resourceBasePath = externalContext.getRequestServletPath(); |
98 | 0 | int stripPoint = resourceBasePath.lastIndexOf('.'); |
99 | 0 | if (stripPoint > 0) |
100 | { | |
101 | 0 | resourceBasePath = resourceBasePath.substring(0, stripPoint); |
102 | } | |
103 | 0 | } |
104 | else | |
105 | { | |
106 | // Mapping using prefix. In this case we have to strip | |
107 | // the prefix used for mapping. If we have a url like: | |
108 | // http://localhost:8080/testjsf20/faces/javax.faces.resource/imagen.jpg?ln=dojo | |
109 | // | |
110 | // The servlet path is /faces | |
111 | // and the path info is /javax.faces.resource/imagen.jpg | |
112 | // | |
113 | // For obtain the resource name we have to remove the /faces prefix and | |
114 | // then the prefix ResourceHandler.RESOURCE_IDENTIFIER | |
115 | 0 | resourceBasePath = externalContext.getRequestPathInfo(); |
116 | } | |
117 | 0 | return resourceBasePath; |
118 | } | |
119 | else | |
120 | { | |
121 | //If no mapping is detected, just return the | |
122 | //information follows the servlet path but before | |
123 | //the query string | |
124 | 0 | return externalContext.getRequestPathInfo(); |
125 | } | |
126 | } | |
127 | ||
128 | public boolean isExtensionMapping() | |
129 | { | |
130 | 0 | FacesServletMapping mapping = getFacesServletMapping( |
131 | FacesContext.getCurrentInstance()); | |
132 | 0 | if (mapping != null) |
133 | { | |
134 | 0 | if (mapping.isExtensionMapping()) |
135 | { | |
136 | 0 | return true; |
137 | } | |
138 | } | |
139 | 0 | return false; |
140 | } | |
141 | ||
142 | public String getMapping() | |
143 | { | |
144 | 0 | FacesServletMapping mapping = getFacesServletMapping( |
145 | FacesContext.getCurrentInstance()); | |
146 | 0 | if (mapping != null) |
147 | { | |
148 | 0 | if (mapping.isExtensionMapping()) |
149 | { | |
150 | 0 | return mapping.getExtension(); |
151 | } | |
152 | else | |
153 | { | |
154 | 0 | return mapping.getPrefix(); |
155 | } | |
156 | } | |
157 | 0 | return ""; |
158 | } | |
159 | ||
160 | /** | |
161 | * Read the web.xml file that is in the classpath and parse its internals to | |
162 | * figure out how the FacesServlet is mapped for the current webapp. | |
163 | */ | |
164 | protected FacesServletMapping getFacesServletMapping(FacesContext context) | |
165 | { | |
166 | 0 | Map<Object, Object> attributes = context.getAttributes(); |
167 | ||
168 | // Has the mapping already been determined during this request? | |
169 | 0 | FacesServletMapping mapping = (FacesServletMapping) attributes.get(CACHED_SERVLET_MAPPING); |
170 | 0 | if (mapping == null) |
171 | { | |
172 | 0 | ExternalContext externalContext = context.getExternalContext(); |
173 | 0 | mapping = calculateFacesServletMapping(externalContext.getRequestServletPath(), |
174 | externalContext.getRequestPathInfo()); | |
175 | ||
176 | 0 | attributes.put(CACHED_SERVLET_MAPPING, mapping); |
177 | } | |
178 | 0 | return mapping; |
179 | } | |
180 | ||
181 | /** | |
182 | * Determines the mapping of the FacesServlet in the web.xml configuration | |
183 | * file. However, there is no need to actually parse this configuration file | |
184 | * as runtime information is sufficient. | |
185 | * | |
186 | * @param servletPath The servletPath of the current request | |
187 | * @param pathInfo The pathInfo of the current request | |
188 | * @return the mapping of the FacesServlet in the web.xml configuration file | |
189 | */ | |
190 | protected static FacesServletMapping calculateFacesServletMapping( | |
191 | String servletPath, String pathInfo) | |
192 | { | |
193 | 0 | if (pathInfo != null) |
194 | { | |
195 | // If there is a "extra path", it's definitely no extension mapping. | |
196 | // Now we just have to determine the path which has been specified | |
197 | // in the url-pattern, but that's easy as it's the same as the | |
198 | // current servletPath. It doesn't even matter if "/*" has been used | |
199 | // as in this case the servletPath is just an empty string according | |
200 | // to the Servlet Specification (SRV 4.4). | |
201 | 0 | return FacesServletMapping.createPrefixMapping(servletPath); |
202 | } | |
203 | else | |
204 | { | |
205 | // In the case of extension mapping, no "extra path" is available. | |
206 | // Still it's possible that prefix-based mapping has been used. | |
207 | // Actually, if there was an exact match no "extra path" | |
208 | // is available (e.g. if the url-pattern is "/faces/*" | |
209 | // and the request-uri is "/context/faces"). | |
210 | 0 | int slashPos = servletPath.lastIndexOf('/'); |
211 | 0 | int extensionPos = servletPath.lastIndexOf('.'); |
212 | 0 | if (extensionPos > -1 && extensionPos > slashPos) |
213 | { | |
214 | 0 | String extension = servletPath.substring(extensionPos); |
215 | 0 | return FacesServletMapping.createExtensionMapping(extension); |
216 | } | |
217 | else | |
218 | { | |
219 | // There is no extension in the given servletPath and therefore | |
220 | // we assume that it's an exact match using prefix-based mapping. | |
221 | 0 | return FacesServletMapping.createPrefixMapping(servletPath); |
222 | } | |
223 | } | |
224 | } | |
225 | ||
226 | public long getStartupTime() | |
227 | { | |
228 | 0 | return _startupTime; |
229 | } | |
230 | ||
231 | public long getMaxTimeExpires() | |
232 | { | |
233 | 0 | if (_maxTimeExpires == null) |
234 | { | |
235 | 0 | _maxTimeExpires = WebConfigParamUtils.getLongInitParameter( |
236 | FacesContext.getCurrentInstance().getExternalContext(), | |
237 | RESOURCE_MAX_TIME_EXPIRES, 604800000L); | |
238 | } | |
239 | 0 | return _maxTimeExpires; |
240 | } | |
241 | } |