KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jpublish > template > DefaultTemplateManager


1 /*--
2  Copyright (C) 2001-2003 Aetrion LLC.
3  All rights reserved.
4
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions
7  are met:
8
9  1. Redistributions of source code must retain the above copyright
10     notice, this list of conditions, and the following disclaimer.
11
12  2. Redistributions in binary form must reproduce the above copyright
13     notice, this list of conditions, and the disclaimer that follows
14     these conditions in the documentation and/or other materials
15     provided with the distribution.
16  3. The name "JPublish" must not be used to endorse or promote products
17     derived from this software without prior written permission. For
18     written permission, please contact info@aetrion.com.
19
20  4. Products derived from this software may not be called "JPublish", nor
21     may "JPublish" appear in their name, without prior written permission
22     from Aetrion LLC (info@aetrion.com).
23
24  In addition, the authors of this software request (but do not require)
25  that you include in the end-user documentation provided with the
26  redistribution and/or in the software itself an acknowledgement equivalent
27  to the following:
28      "This product includes software developed by
29       Aetrion LLC (http://www.aetrion.com/)."
30  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
31  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33  DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
34  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
36  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
38  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
39  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40  POSSIBILITY OF SUCH DAMAGE.
41  For more information on JPublish, please see <http://www.jpublish.org/>.
42
43  */

44 package org.jpublish.template;
45
46 import java.io.IOException JavaDoc;
47 import java.io.InputStream JavaDoc;
48 import java.io.InputStreamReader JavaDoc;
49 import java.io.Reader JavaDoc;
50
51 import com.anthonyeden.lib.config.Configuration;
52 import com.anthonyeden.lib.config.ConfigurationException;
53 import com.anthonyeden.lib.util.ClassUtilities;
54 import com.anthonyeden.lib.util.IOUtilities;
55 import com.anthonyeden.lib.util.MessageUtilities;
56 import org.apache.commons.logging.Log;
57 import org.apache.commons.logging.LogFactory;
58 import org.apache.commons.vfs.FileContent;
59 import org.apache.commons.vfs.FileName;
60 import org.apache.commons.vfs.FileObject;
61 import org.apache.commons.vfs.FileSystemManager;
62 import org.jpublish.JPublishEngine;
63 import org.jpublish.JPublishRuntimeException;
64 import org.jpublish.RequestContext;
65 import org.jpublish.SiteContext;
66 import org.jpublish.cache.CacheEntry;
67 import org.jpublish.cache.CacheStorage;
68 import org.jpublish.cache.HashMapCacheStorage;
69 import org.jpublish.util.PathUtilities;
70 import org.jpublish.util.encoding.CharacterEncodingManager;
71
72 /**
73  * The TemplateManager is a central access point for locating templates. Implementations of the TemplateManager
74  * interface will provide the template loading behavior.
75  *
76  * @author Anthony Eden
77  */

78 public class DefaultTemplateManager extends AbstractTemplateManager {
79
80     private final static String JavaDoc ATTRIBUTE_CLASSNAME = "classname";
81
82     private Log log = LogFactory.getLog(DefaultTemplateManager.class);
83     private CacheStorage templateCache = null;
84
85     /**
86      * Get the template cache.
87      *
88      * @return The template cache
89      */

90     public synchronized CacheStorage getTemplateCache() {
91         if (templateCache == null) {
92             templateCache = new HashMapCacheStorage();
93         }
94         return templateCache;
95     }
96
97     /**
98      * Set the template cache.
99      *
100      * @param templateCache The new template cache
101      */

102     public void setTemplateCache(CacheStorage templateCache) {
103         this.templateCache = templateCache;
104     }
105
106     /**
107      * Return the virtual file system manager. This method may return null if the implementation does not support a
108      * virtual file system.
109      *
110      * @return The FileSystemManager
111      * @throws IOException Description of the Exception
112      */

113     public synchronized FileSystemManager getFileSystemManager()
114             throws IOException JavaDoc {
115         if (fileSystemManager == null) {
116             configureDefaultFileSystemManager(SiteContext.DEFAULT_TEMPLATE_ROOT);
117         }
118         return fileSystemManager;
119     }
120
121     /**
122      * Get a Template instance from the given path. If no template can be found then this method will throw a
123      * FileNotFoundException.
124      *
125      * @param path The template path
126      * @return The Template
127      * @throws IOException Any IOException
128      * @throws TemplateNotFoundException
129      */

130     public synchronized Template getTemplate(String JavaDoc path) throws IOException JavaDoc,
131             TemplateNotFoundException {
132         if (log.isDebugEnabled()) {
133             log.debug("getTemplate(" + path + ")");
134         }
135
136         FileSystemManager fileSystemManager = getFileSystemManager();
137         FileObject baseFile = fileSystemManager.getBaseFile();
138         FileObject templateFile = fileSystemManager.resolveFile(baseFile,
139                 PathUtilities.toRelativePath(path));
140         if (!templateFile.exists()) {
141             Object JavaDoc[] args = {path};
142             throw new TemplateNotFoundException(MessageUtilities.getMessage(getClass(), JPublishEngine.MESSAGE_PACKAGE, "templateNotFound",
143                     args));
144         }
145
146         FileContent templateContent = templateFile.getContent();
147         long lastModified = templateContent.getLastModifiedTime();
148
149         // check the cache and load the template if necessary
150
CacheStorage templateCache = getTemplateCache();
151         CacheEntry cacheEntry = (CacheEntry) templateCache.get(path);
152         Template template = null;
153
154         if (cacheEntry == null) {
155             if (log.isDebugEnabled()) {
156                 log.debug("Template (" + path + ") not found in cache.");
157             }
158             template = new Template(siteContext, path, getName());
159
160             // load the template data into the Template object
161
loadTemplate(template, templateFile);
162
163             // configure the template
164
configureTemplate(template, templateFile);
165
166             templateCache.put(path, new CacheEntry(template, lastModified));
167             template.setLastModified(lastModified);
168         } else {
169             if (log.isDebugEnabled()) {
170                 log.debug("Template (" + path + ") found in cache.");
171             }
172             template = (Template) cacheEntry.getObject();
173             if (cacheEntry.getLastModified() !=
174                     templateContent.getLastModifiedTime()) {
175                 log.debug("Template modification dates do not match.");
176                 log.debug("Reloading template.");
177
178                 // load the template data into the Template object
179
loadTemplate(template, templateFile);
180
181                 // configure the template
182
configureTemplate(template, templateFile);
183
184                 cacheEntry.setLastModified(lastModified);
185                 template.setLastModified(lastModified);
186             }
187         }
188
189         return template;
190     }
191
192     /**
193      * Get the last modified time of the page with the given path. This method may return -1 if the last modified time
194      * is not known.
195      *
196      * @param path The page path
197      * @return The last modified time
198      * @throws IOException Any IOException
199      */

200
201     public long getLastModified(String JavaDoc path) throws IOException JavaDoc {
202         FileSystemManager fileSystemManager = getFileSystemManager();
203         FileObject baseFile = fileSystemManager.getBaseFile();
204         FileObject file = fileSystemManager.resolveFile(baseFile,
205                 PathUtilities.toRelativePath(path));
206         FileContent content = file.getContent();
207         return content.getLastModifiedTime();
208     }
209
210     /**
211      * Load the TemplateManager's configuration from the given configuration object.
212      *
213      * @param configuration The configuration object
214      * @throws ConfigurationException
215      */

216
217     public void loadConfiguration(Configuration configuration)
218             throws ConfigurationException {
219         super.loadConfiguration(configuration);
220
221         // set the cache storage type
222
String JavaDoc className = null;
223         try {
224             Configuration cacheStorageElement = configuration.getChild("cache-storage");
225             if (cacheStorageElement != null) {
226                 className = cacheStorageElement.getAttribute(ATTRIBUTE_CLASSNAME, HashMapCacheStorage.class.getName());
227                 CacheStorage cache = (CacheStorage) ClassUtilities.loadClass(className).newInstance();
228                 cache.loadConfiguration(cacheStorageElement);
229                 setTemplateCache(cache);
230             }
231         } catch (ClassNotFoundException JavaDoc e) {
232             Object JavaDoc[] args = {className};
233             throw new ConfigurationException(MessageUtilities.getMessage(getClass(), JPublishEngine.MESSAGE_PACKAGE,
234                     "cacheStorageClassNotFound", args), e, configuration);
235         } catch (Exception JavaDoc e) {
236             throw new ConfigurationException(MessageUtilities.getMessage(getClass(), JPublishEngine.MESSAGE_PACKAGE,
237                     "cacheStorageConfigurationError", null), e, configuration);
238         }
239     }
240
241     /**
242      * Load the specified template's text. <p>
243      *
244      * <b>Note:</b> Template encoding is currently disabled. The original encoding mechanism was based on the page path.
245      * However, now that templates will be loaded and cached independent of a request path, this will need to change.
246      * The new encoding system should be based on the template path, not the page path.</p>
247      *
248      * @param template The Template
249      * @param file The FileObject
250      * @throws IOException
251      */

252
253     protected synchronized void loadTemplate(Template template, FileObject file)
254             throws IOException JavaDoc {
255         // construct a new Template
256

257         RequestContext context = RequestContext.getRequestContext();
258         String JavaDoc path = PathUtilities.getRealPath(siteContext,
259                 context.getRequest().getPathInfo());
260         CharacterEncodingManager encManager =
261                 siteContext.getCharacterEncodingManager();
262         String JavaDoc templateEncoding =
263                 encManager.getMap(path).getTemplateEncoding();
264
265         if (log.isDebugEnabled()) {
266             log.debug("Template encoding: " + templateEncoding);
267         }
268
269         FileContent content = file.getContent();
270
271         Reader JavaDoc in = null;
272         try {
273             in = new InputStreamReader JavaDoc(content.getInputStream(),
274                     templateEncoding);
275             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
276             int c = -1;
277             while ((c = in.read()) != -1) {
278                 buffer.append((char) c);
279             }
280
281             template.setText(buffer.toString());
282
283         } finally {
284             IOUtilities.close(in);
285         }
286     }
287
288     /**
289      * Configure the template.
290      *
291      * @param template The Template
292      * @param file The file for the template
293      * @throws IOException Any exception
294      */

295
296     protected void configureTemplate(Template template, FileObject file)
297             throws IOException JavaDoc {
298         FileName name = file.getName();
299         InputStream JavaDoc in = null;
300         try {
301             // load additional configuration information
302

303             // note that if there is a template with the ending .xml
304
// then this will cause a naming conflict.
305

306             FileObject parentFile = file.getParent();
307             String JavaDoc baseName = name.getBaseName();
308             String JavaDoc namePart = baseName.substring(0, baseName.lastIndexOf("."));
309             FileObject configFile = parentFile.resolveFile(namePart +
310                     getActualConfigurationSuffix());
311             if (configFile.exists()) {
312                 in = configFile.getContent().getInputStream();
313                 template.loadConfiguration(in);
314             }
315         } catch (ConfigurationException e) {
316             Object JavaDoc[] args = {name.getPath(), e.getMessage()};
317             throw new JPublishRuntimeException(MessageUtilities.getMessage(getClass(), JPublishEngine.MESSAGE_PACKAGE,
318                     "templateConfigurationError", args), e);
319         } finally {
320             IOUtilities.close(in);
321         }
322     }
323
324 }
325
326
Popular Tags