%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.jetspeed.locator.JetspeedTemplateLocator |
|
|
1 | /* |
|
2 | * Licensed to the Apache Software Foundation (ASF) under one or more |
|
3 | * contributor license agreements. See the NOTICE file distributed with |
|
4 | * this work for additional information regarding copyright ownership. |
|
5 | * The ASF licenses this file to You under the Apache License, Version 2.0 |
|
6 | * (the "License"); you may not use this file except in compliance with |
|
7 | * the License. You may obtain a copy of the License at |
|
8 | * |
|
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
10 | * |
|
11 | * Unless required by applicable law or agreed to in writing, software |
|
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 | * See the License for the specific language governing permissions and |
|
15 | * limitations under the License. |
|
16 | */ |
|
17 | package org.apache.jetspeed.locator; |
|
18 | ||
19 | import java.io.File; |
|
20 | import java.io.FileNotFoundException; |
|
21 | import java.util.Collections; |
|
22 | import java.util.HashMap; |
|
23 | import java.util.Iterator; |
|
24 | import java.util.List; |
|
25 | import java.util.Map; |
|
26 | import java.util.StringTokenizer; |
|
27 | ||
28 | import org.apache.commons.logging.Log; |
|
29 | import org.apache.commons.logging.LogFactory; |
|
30 | ||
31 | /** |
|
32 | * Jetspeed's default implementation of a template locator. |
|
33 | * |
|
34 | * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a> |
|
35 | * @version $Id: JetspeedTemplateLocator.java 587334 2007-10-23 00:30:49Z taylor $ |
|
36 | */ |
|
37 | public class JetspeedTemplateLocator implements TemplateLocator |
|
38 | { |
|
39 | 0 | private final static Log log = LogFactory.getLog(JetspeedTemplateLocator.class); |
40 | ||
41 | private static final String PATH_SEPARATOR = "/"; |
|
42 | ||
43 | /** the template root directories, all application root relative */ |
|
44 | private List roots; |
|
45 | ||
46 | /** Root of the application running this locator */ |
|
47 | private String appRoot; |
|
48 | ||
49 | /** the Template class is factory created */ |
|
50 | 0 | private Class templateClass = JetspeedTemplateDescriptor.class; |
51 | ||
52 | /** the TemplateLocator class is factory created */ |
|
53 | 0 | private Class locatorClass = JetspeedLocatorDescriptor.class; |
54 | ||
55 | /** the default locator type */ |
|
56 | 0 | private String defaultLocatorType = "layout"; |
57 | ||
58 | /** template name cache used to speed up searches for templates */ |
|
59 | 0 | private Map templateMap = null; |
60 | ||
61 | /** use the name cache when looking up a template */ |
|
62 | 0 | private boolean useNameCache = true; |
63 | ||
64 | private JetspeedTemplateLocator() |
|
65 | 0 | { |
66 | // need to know roots |
|
67 | 0 | } |
68 | ||
69 | /** |
|
70 | * Minimal assembly with a list of resource directory roots. |
|
71 | * |
|
72 | * @param roots A list of resource root directories where templates are located. |
|
73 | * @param appRoot Root from where this application runs |
|
74 | */ |
|
75 | public JetspeedTemplateLocator(List roots, String appRoot) throws FileNotFoundException |
|
76 | 0 | { |
77 | 0 | this.appRoot = appRoot; |
78 | 0 | log.info("Locator application root "+new File(appRoot).getAbsolutePath()); |
79 | 0 | this.roots = roots; |
80 | 0 | Iterator itr = roots.iterator(); |
81 | 0 | while(itr.hasNext()) |
82 | { |
|
83 | 0 | String path = (String) itr.next(); |
84 | 0 | File checkFile = new File(path); |
85 | 0 | if(!checkFile.exists()) |
86 | { |
|
87 | 0 | throw new FileNotFoundException("Locator resource root "+checkFile.getAbsolutePath()+" does not exist."); |
88 | } |
|
89 | 0 | } |
90 | 0 | } |
91 | ||
92 | /** |
|
93 | * Construct with a root list and a default locator type. |
|
94 | * |
|
95 | * @param roots A list of resource root directories where templates are located. |
|
96 | * @param defaultLocatorType Under root directories, subdirectories represent locator types. |
|
97 | * A locator type represents a classification of templates. |
|
98 | * Any value is allowed. Use locator types to group templates together. |
|
99 | */ |
|
100 | public JetspeedTemplateLocator(List roots, |
|
101 | String defaultLocatorType, |
|
102 | String appRoot) throws FileNotFoundException |
|
103 | { |
|
104 | 0 | this(roots, appRoot); |
105 | 0 | this.defaultLocatorType = defaultLocatorType; |
106 | 0 | } |
107 | ||
108 | /** |
|
109 | * Assemble with list resource directory roots and OM classes and a defaultLocatorType. |
|
110 | * |
|
111 | * @param roots A list of resource root directories where templates are located. |
|
112 | * @param omClasses Template replacable object model implementations for Template and TemplateLocator. |
|
113 | * Required order, with second optional: [ <code>Template</code>, <code>TemplateLocator</code> implementations. |
|
114 | * @param defaultLocatorType Under root directories, subdirectories represent locator types. |
|
115 | * A locator type represents a classification of templates. |
|
116 | * Any value is allowed. Use locator types to group templates together. |
|
117 | */ |
|
118 | public JetspeedTemplateLocator(List roots, |
|
119 | List omClasses, |
|
120 | String defaultLocatorType, |
|
121 | String appRoot) throws FileNotFoundException |
|
122 | { |
|
123 | 0 | this(roots, defaultLocatorType, appRoot); |
124 | ||
125 | 0 | if (omClasses.size() > 0) |
126 | { |
|
127 | 0 | this.templateClass = (Class)omClasses.get(0); |
128 | 0 | if (omClasses.size() > 1) |
129 | { |
|
130 | 0 | this.locatorClass = (Class)omClasses.get(1); |
131 | } |
|
132 | } |
|
133 | 0 | } |
134 | ||
135 | public TemplateDescriptor locateTemplate(LocatorDescriptor locator) |
|
136 | { |
|
137 | 0 | for (int ix = 0; ix < roots.size(); ix++) |
138 | { |
|
139 | 0 | TemplateDescriptor template = locateTemplate(locator, (String)roots.get(ix), this.useNameCache); |
140 | 0 | if (null == template) |
141 | { |
|
142 | // Try to locate it directly on file system, perhaps it was recently added |
|
143 | 0 | template = locateTemplate(locator, (String)roots.get(ix), false); |
144 | 0 | if (null != template) |
145 | { |
|
146 | // add it to the map |
|
147 | 0 | templateMap.put(template.getAbsolutePath(), null); |
148 | } |
|
149 | } |
|
150 | 0 | if (template != null) |
151 | { |
|
152 | 0 | return template; |
153 | } |
|
154 | } |
|
155 | 0 | return null; |
156 | } |
|
157 | ||
158 | /** |
|
159 | * General template location algorithm. Starts with the most specific resource, |
|
160 | * including mediatype + nls specification, and fallsback to least specific. |
|
161 | * |
|
162 | * @param locator The template locator |
|
163 | * @param root The root directory to search |
|
164 | * |
|
165 | * @return TemplateDescriptor the exact path to the template, or null if not found. |
|
166 | */ |
|
167 | private TemplateDescriptor locateTemplate(LocatorDescriptor locator, String root, boolean useCache) |
|
168 | { |
|
169 | 0 | String templateName = locator.getName(); |
170 | 0 | String path = locator.toPath(); |
171 | ||
172 | 0 | String realPath = null; |
173 | 0 | String workingPath = null; |
174 | ||
175 | int lastSeperator; |
|
176 | 0 | while (path !=null && (lastSeperator = path.lastIndexOf(PATH_SEPARATOR))> 0) |
177 | { |
|
178 | 0 | path = path.substring(0, lastSeperator); |
179 | ||
180 | 0 | workingPath = path + PATH_SEPARATOR + templateName; |
181 | 0 | realPath = root + workingPath; |
182 | ||
183 | // the current template exists, return the corresponding path |
|
184 | 0 | if (templateExists(realPath, useCache)) |
185 | { |
|
186 | 0 | if (log.isDebugEnabled()) |
187 | { |
|
188 | 0 | log.debug( |
189 | "TemplateLocator: template exists: " |
|
190 | + realPath |
|
191 | + " returning " |
|
192 | + workingPath); |
|
193 | } |
|
194 | 0 | int appRootLength = appRoot.length(); |
195 | // remove the application root path from the reall path to |
|
196 | // give us a app relative path |
|
197 | 0 | String appRelativePath = realPath.substring(appRootLength, realPath.length()); |
198 | // return createTemplateFromPath(path, templateName, realPath, "/WEB-INF/templates" + workingPath); |
|
199 | 0 | return createTemplateFromPath(path, templateName, realPath, appRelativePath); |
200 | } |
|
201 | } |
|
202 | 0 | return null; |
203 | } |
|
204 | ||
205 | /** |
|
206 | * Checks for the existence of a template resource given a key. |
|
207 | * The key are absolute paths to the templates, and are cached |
|
208 | * in a template cache for performance. |
|
209 | * |
|
210 | * @param key The absolute path to the template resource. |
|
211 | * |
|
212 | * @return True when the template is found, otherwise false. |
|
213 | */ |
|
214 | public boolean templateExists(String templateKey, class="keyword">boolean useCache) |
|
215 | { |
|
216 | 0 | if (null == templateKey) |
217 | { |
|
218 | 0 | return false; |
219 | } |
|
220 | 0 | if (useCache == true) |
221 | { |
|
222 | 0 | return templateMap.containsKey(templateKey); |
223 | } |
|
224 | 0 | return (new File(templateKey).exists()); |
225 | } |
|
226 | ||
227 | public boolean templateExists(String templateKey) |
|
228 | { |
|
229 | 0 | return templateExists(templateKey, this.useNameCache); |
230 | } |
|
231 | ||
232 | public LocatorDescriptor createFromString(String path) |
|
233 | throws TemplateLocatorException |
|
234 | { |
|
235 | 0 | LocatorDescriptor locator = createLocatorDescriptor(this.defaultLocatorType); |
236 | 0 | StringTokenizer tok = new StringTokenizer(path, "/"); |
237 | 0 | while (tok.hasMoreTokens()) |
238 | { |
|
239 | 0 | String name = tok.nextToken(); |
240 | 0 | if (name.equals(LocatorDescriptor.PARAM_TYPE) && tok.hasMoreTokens()) |
241 | { |
|
242 | 0 | locator.setType( tok.nextToken() ); |
243 | } |
|
244 | 0 | else if (name.equals(LocatorDescriptor.PARAM_MEDIA_TYPE) && tok.hasMoreTokens()) |
245 | { |
|
246 | 0 | locator.setMediaType(tok.nextToken()); |
247 | } |
|
248 | 0 | else if (name.equals(LocatorDescriptor.PARAM_LANGUAGE) && tok.hasMoreTokens()) |
249 | { |
|
250 | 0 | locator.setLanguage(tok.nextToken()); |
251 | } |
|
252 | 0 | else if (name.equals(LocatorDescriptor.PARAM_COUNTRY) && tok.hasMoreTokens()) |
253 | { |
|
254 | 0 | locator.setCountry(tok.nextToken()); |
255 | } |
|
256 | ||
257 | 0 | else if (name.equals(LocatorDescriptor.PARAM_NAME) && tok.hasMoreTokens()) |
258 | { |
|
259 | 0 | locator.setName(tok.nextToken()); |
260 | } |
|
261 | 0 | } |
262 | 0 | return locator; |
263 | } |
|
264 | ||
265 | /** |
|
266 | * Given a path, name and realPath creates a new template object |
|
267 | * |
|
268 | * @param path the relative path to the template |
|
269 | * @param name the template name |
|
270 | * @param realPath the real path on the file system |
|
271 | * @return newly created TemplateDescriptor |
|
272 | */ |
|
273 | private TemplateDescriptor createTemplateFromPath(String path, String name, String realPath, String relativePath) |
|
274 | { |
|
275 | 0 | TemplateDescriptor template = this.createTemplate(); |
276 | 0 | template.setAbsolutePath(realPath); |
277 | 0 | if(relativePath.indexOf("/") != 0) |
278 | { |
|
279 | 0 | relativePath = "/"+relativePath; |
280 | } |
|
281 | 0 | template.setAppRelativePath(relativePath); |
282 | 0 | template.setName(name); |
283 | 0 | StringTokenizer tok = new StringTokenizer(path, "/"); |
284 | 0 | int count = 0; |
285 | 0 | while (tok.hasMoreTokens()) |
286 | { |
|
287 | 0 | String token = tok.nextToken(); |
288 | 0 | switch (count) |
289 | { |
|
290 | case 0: |
|
291 | 0 | template.setType(token); |
292 | 0 | break; |
293 | case 1: |
|
294 | 0 | template.setMediaType(token); |
295 | 0 | break; |
296 | case 2: |
|
297 | 0 | template.setLanguage(token); |
298 | 0 | break; |
299 | case 3: |
|
300 | 0 | template.setCountry(token); |
301 | break; |
|
302 | } |
|
303 | 0 | count++; |
304 | 0 | } |
305 | 0 | return template; |
306 | } |
|
307 | ||
308 | public LocatorDescriptor createLocatorDescriptor(String type) |
|
309 | throws TemplateLocatorException |
|
310 | { |
|
311 | 0 | LocatorDescriptor locator = null; |
312 | ||
313 | try |
|
314 | { |
|
315 | 0 | locator = (LocatorDescriptor)locatorClass.newInstance(); |
316 | 0 | locator.setType(type); |
317 | } |
|
318 | 0 | catch(Exception e) |
319 | { |
|
320 | 0 | throw new TemplateLocatorException("Failed instantiate a Template Locator implementation object: ", e); |
321 | 0 | } |
322 | 0 | return locator; |
323 | } |
|
324 | ||
325 | private TemplateDescriptor createTemplate() |
|
326 | { |
|
327 | 0 | TemplateDescriptor template = null; |
328 | ||
329 | try |
|
330 | { |
|
331 | 0 | template = (TemplateDescriptor)templateClass.newInstance(); |
332 | } |
|
333 | 0 | catch(Exception e) |
334 | { |
|
335 | 0 | log.error("Failed to create template", e); |
336 | 0 | template = new JetspeedTemplateDescriptor(); |
337 | 0 | } |
338 | 0 | return template; |
339 | } |
|
340 | ||
341 | public void start() |
|
342 | { |
|
343 | 0 | this.templateMap = Collections.synchronizedMap(new HashMap()); |
344 | ||
345 | 0 | for (int ix = 0; ix < roots.size(); ix++) |
346 | { |
|
347 | 0 | String templateRoot = (String)roots.get(ix); |
348 | ||
349 | 0 | if (!templateRoot.endsWith(PATH_SEPARATOR)) |
350 | { |
|
351 | 0 | templateRoot = templateRoot + PATH_SEPARATOR; |
352 | } |
|
353 | ||
354 | 0 | loadNameCache(templateRoot, ""); |
355 | } |
|
356 | 0 | } |
357 | ||
358 | public void stop() |
|
359 | { |
|
360 | 0 | } |
361 | ||
362 | public Iterator query(LocatorDescriptor locator) |
|
363 | { |
|
364 | 0 | return null; // TODO: implement this |
365 | } |
|
366 | ||
367 | /** |
|
368 | * Loads the template name cache map to accelerate template searches. |
|
369 | * |
|
370 | * @param path The template |
|
371 | * @param name just the name of the resource |
|
372 | */ |
|
373 | private void loadNameCache(String path, String name) |
|
374 | { |
|
375 | 0 | File file = new File(path); |
376 | 0 | if (file.isFile()) |
377 | { |
|
378 | // add it to the map |
|
379 | 0 | templateMap.put(path, null); |
380 | } |
|
381 | else |
|
382 | { |
|
383 | 0 | if (file.isDirectory()) |
384 | { |
|
385 | 0 | if (!path.endsWith(File.separator)) |
386 | { |
|
387 | 0 | path += File.separator; |
388 | } |
|
389 | ||
390 | 0 | String list[] = file.list(); |
391 | ||
392 | // Process all files recursivly |
|
393 | 0 | for (int ix = 0; list != null && ix < list.length; ix++) |
394 | { |
|
395 | 0 | loadNameCache(path + list[ix], list[ix]); |
396 | } |
|
397 | } |
|
398 | } |
|
399 | 0 | } |
400 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |