%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 553014 2007-07-03 23:10:53Z ate $ |
|
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)); |
140 | 0 | if (null == template) |
141 | { |
|
142 | // Try to locate it directly on file system, perhaps it was recently added |
|
143 | 0 | useNameCache = false; |
144 | 0 | template = locateTemplate(locator, (String)roots.get(ix)); |
145 | 0 | if (null != template) |
146 | { |
|
147 | // add it to the map |
|
148 | 0 | templateMap.put(template.getAbsolutePath(), null); |
149 | } |
|
150 | 0 | useNameCache = true; |
151 | } |
|
152 | 0 | if (template != null) |
153 | { |
|
154 | 0 | return template; |
155 | } |
|
156 | } |
|
157 | 0 | return null; |
158 | } |
|
159 | ||
160 | /** |
|
161 | * General template location algorithm. Starts with the most specific resource, |
|
162 | * including mediatype + nls specification, and fallsback to least specific. |
|
163 | * |
|
164 | * @param locator The template locator |
|
165 | * @param root The root directory to search |
|
166 | * |
|
167 | * @return TemplateDescriptor the exact path to the template, or null if not found. |
|
168 | */ |
|
169 | private TemplateDescriptor locateTemplate(LocatorDescriptor locator, String root) |
|
170 | { |
|
171 | 0 | String templateName = locator.getName(); |
172 | 0 | String path = locator.toPath(); |
173 | ||
174 | 0 | String realPath = null; |
175 | 0 | String workingPath = null; |
176 | ||
177 | int lastSeperator; |
|
178 | 0 | while (path !=null && (lastSeperator = path.lastIndexOf(PATH_SEPARATOR))> 0) |
179 | { |
|
180 | 0 | path = path.substring(0, lastSeperator); |
181 | ||
182 | 0 | workingPath = path + PATH_SEPARATOR + templateName; |
183 | 0 | realPath = root + workingPath; |
184 | ||
185 | // the current template exists, return the corresponding path |
|
186 | 0 | if (templateExists(realPath)) |
187 | { |
|
188 | 0 | if (log.isDebugEnabled()) |
189 | { |
|
190 | 0 | log.debug( |
191 | "TemplateLocator: template exists: " |
|
192 | + realPath |
|
193 | + " returning " |
|
194 | + workingPath); |
|
195 | } |
|
196 | 0 | int appRootLength = appRoot.length(); |
197 | // remove the application root path from the reall path to |
|
198 | // give us a app relative path |
|
199 | 0 | String appRelativePath = realPath.substring(appRootLength, realPath.length()); |
200 | // return createTemplateFromPath(path, templateName, realPath, "/WEB-INF/templates" + workingPath); |
|
201 | 0 | return createTemplateFromPath(path, templateName, realPath, appRelativePath); |
202 | } |
|
203 | } |
|
204 | 0 | return null; |
205 | } |
|
206 | ||
207 | /** |
|
208 | * Checks for the existence of a template resource given a key. |
|
209 | * The key are absolute paths to the templates, and are cached |
|
210 | * in a template cache for performance. |
|
211 | * |
|
212 | * @param key The absolute path to the template resource. |
|
213 | * |
|
214 | * @return True when the template is found, otherwise false. |
|
215 | */ |
|
216 | public boolean templateExists(String templateKey) |
|
217 | { |
|
218 | 0 | if (null == templateKey) |
219 | { |
|
220 | 0 | return false; |
221 | } |
|
222 | 0 | if (useNameCache == true) |
223 | { |
|
224 | 0 | return templateMap.containsKey(templateKey); |
225 | } |
|
226 | 0 | return (new File(templateKey).exists()); |
227 | } |
|
228 | ||
229 | ||
230 | public LocatorDescriptor createFromString(String path) |
|
231 | throws TemplateLocatorException |
|
232 | { |
|
233 | 0 | LocatorDescriptor locator = createLocatorDescriptor(this.defaultLocatorType); |
234 | 0 | StringTokenizer tok = new StringTokenizer(path, "/"); |
235 | 0 | while (tok.hasMoreTokens()) |
236 | { |
|
237 | 0 | String name = tok.nextToken(); |
238 | 0 | if (name.equals(LocatorDescriptor.PARAM_TYPE) && tok.hasMoreTokens()) |
239 | { |
|
240 | 0 | locator.setType( tok.nextToken() ); |
241 | } |
|
242 | 0 | else if (name.equals(LocatorDescriptor.PARAM_MEDIA_TYPE) && tok.hasMoreTokens()) |
243 | { |
|
244 | 0 | locator.setMediaType(tok.nextToken()); |
245 | } |
|
246 | 0 | else if (name.equals(LocatorDescriptor.PARAM_LANGUAGE) && tok.hasMoreTokens()) |
247 | { |
|
248 | 0 | locator.setLanguage(tok.nextToken()); |
249 | } |
|
250 | 0 | else if (name.equals(LocatorDescriptor.PARAM_COUNTRY) && tok.hasMoreTokens()) |
251 | { |
|
252 | 0 | locator.setCountry(tok.nextToken()); |
253 | } |
|
254 | ||
255 | 0 | else if (name.equals(LocatorDescriptor.PARAM_NAME) && tok.hasMoreTokens()) |
256 | { |
|
257 | 0 | locator.setName(tok.nextToken()); |
258 | } |
|
259 | 0 | } |
260 | 0 | return locator; |
261 | } |
|
262 | ||
263 | /** |
|
264 | * Given a path, name and realPath creates a new template object |
|
265 | * |
|
266 | * @param path the relative path to the template |
|
267 | * @param name the template name |
|
268 | * @param realPath the real path on the file system |
|
269 | * @return newly created TemplateDescriptor |
|
270 | */ |
|
271 | private TemplateDescriptor createTemplateFromPath(String path, String name, String realPath, String relativePath) |
|
272 | { |
|
273 | 0 | TemplateDescriptor template = this.createTemplate(); |
274 | 0 | template.setAbsolutePath(realPath); |
275 | 0 | if(relativePath.indexOf("/") != 0) |
276 | { |
|
277 | 0 | relativePath = "/"+relativePath; |
278 | } |
|
279 | 0 | template.setAppRelativePath(relativePath); |
280 | 0 | template.setName(name); |
281 | 0 | StringTokenizer tok = new StringTokenizer(path, "/"); |
282 | 0 | int count = 0; |
283 | 0 | while (tok.hasMoreTokens()) |
284 | { |
|
285 | 0 | String token = tok.nextToken(); |
286 | 0 | switch (count) |
287 | { |
|
288 | case 0: |
|
289 | 0 | template.setType(token); |
290 | 0 | break; |
291 | case 1: |
|
292 | 0 | template.setMediaType(token); |
293 | 0 | break; |
294 | case 2: |
|
295 | 0 | template.setLanguage(token); |
296 | 0 | break; |
297 | case 3: |
|
298 | 0 | template.setCountry(token); |
299 | break; |
|
300 | } |
|
301 | 0 | count++; |
302 | 0 | } |
303 | 0 | return template; |
304 | } |
|
305 | ||
306 | public LocatorDescriptor createLocatorDescriptor(String type) |
|
307 | throws TemplateLocatorException |
|
308 | { |
|
309 | 0 | LocatorDescriptor locator = null; |
310 | ||
311 | try |
|
312 | { |
|
313 | 0 | locator = (LocatorDescriptor)locatorClass.newInstance(); |
314 | 0 | locator.setType(type); |
315 | } |
|
316 | 0 | catch(Exception e) |
317 | { |
|
318 | 0 | throw new TemplateLocatorException("Failed instantiate a Template Locator implementation object: ", e); |
319 | 0 | } |
320 | 0 | return locator; |
321 | } |
|
322 | ||
323 | private TemplateDescriptor createTemplate() |
|
324 | { |
|
325 | 0 | TemplateDescriptor template = null; |
326 | ||
327 | try |
|
328 | { |
|
329 | 0 | template = (TemplateDescriptor)templateClass.newInstance(); |
330 | } |
|
331 | 0 | catch(Exception e) |
332 | { |
|
333 | 0 | log.error("Failed to create template", e); |
334 | 0 | template = new JetspeedTemplateDescriptor(); |
335 | 0 | } |
336 | 0 | return template; |
337 | } |
|
338 | ||
339 | public void start() |
|
340 | { |
|
341 | 0 | this.templateMap = Collections.synchronizedMap(new HashMap()); |
342 | ||
343 | 0 | for (int ix = 0; ix < roots.size(); ix++) |
344 | { |
|
345 | 0 | String templateRoot = (String)roots.get(ix); |
346 | ||
347 | 0 | if (!templateRoot.endsWith(PATH_SEPARATOR)) |
348 | { |
|
349 | 0 | templateRoot = templateRoot + PATH_SEPARATOR; |
350 | } |
|
351 | ||
352 | 0 | loadNameCache(templateRoot, ""); |
353 | } |
|
354 | 0 | } |
355 | ||
356 | public void stop() |
|
357 | { |
|
358 | 0 | } |
359 | ||
360 | public Iterator query(LocatorDescriptor locator) |
|
361 | { |
|
362 | 0 | return null; // TODO: implement this |
363 | } |
|
364 | ||
365 | /** |
|
366 | * Loads the template name cache map to accelerate template searches. |
|
367 | * |
|
368 | * @param path The template |
|
369 | * @param name just the name of the resource |
|
370 | */ |
|
371 | private void loadNameCache(String path, String name) |
|
372 | { |
|
373 | 0 | File file = new File(path); |
374 | 0 | if (file.isFile()) |
375 | { |
|
376 | // add it to the map |
|
377 | 0 | templateMap.put(path, null); |
378 | } |
|
379 | else |
|
380 | { |
|
381 | 0 | if (file.isDirectory()) |
382 | { |
|
383 | 0 | if (!path.endsWith(File.separator)) |
384 | { |
|
385 | 0 | path += File.separator; |
386 | } |
|
387 | ||
388 | 0 | String list[] = file.list(); |
389 | ||
390 | // Process all files recursivly |
|
391 | 0 | for (int ix = 0; list != null && ix < list.length; ix++) |
392 | { |
|
393 | 0 | loadNameCache(path + list[ix], list[ix]); |
394 | } |
|
395 | } |
|
396 | } |
|
397 | 0 | } |
398 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |