001: /*
002: * Copyright (c) 2003 The Visigoth Software Society. All rights
003: * reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * 2. Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in
014: * the documentation and/or other materials provided with the
015: * distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowledgement:
019: * "This product includes software developed by the
020: * Visigoth Software Society (http://www.visigoths.org/)."
021: * Alternately, this acknowledgement may appear in the software itself,
022: * if and wherever such third-party acknowledgements normally appear.
023: *
024: * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
025: * project contributors may be used to endorse or promote products derived
026: * from this software without prior written permission. For written
027: * permission, please contact visigoths@visigoths.org.
028: *
029: * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
030: * nor may "FreeMarker" or "Visigoth" appear in their names
031: * without prior written permission of the Visigoth Software Society.
032: *
033: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
034: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
035: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036: * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
037: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
038: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
039: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
040: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
041: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
042: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
043: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044: * SUCH DAMAGE.
045: * ====================================================================
046: *
047: * This software consists of voluntary contributions made by many
048: * individuals on behalf of the Visigoth Software Society. For more
049: * information on the Visigoth Software Society, please see
050: * http://www.visigoths.org/
051: */
052:
053: package freemarker.cache;
054:
055: import java.io.File;
056: import java.io.FileInputStream;
057: import java.io.IOException;
058: import java.io.InputStreamReader;
059: import java.io.Reader;
060: import java.net.MalformedURLException;
061: import java.net.URL;
062:
063: import javax.servlet.ServletContext;
064:
065: import freemarker.log.Logger;
066:
067: /**
068: * A {@link TemplateLoader} that uses streams reachable through
069: * {@link ServletContext#getResource(String)} as its source of templates.
070: * @version $Id: WebappTemplateLoader.java,v 1.10 2003/01/29 08:01:18 szegedia Exp $
071: * @author Attila Szegedi
072: */
073: public class WebappTemplateLoader implements TemplateLoader {
074: private static final Logger logger = Logger
075: .getLogger("freemarker.cache");
076:
077: private final ServletContext servletContext;
078: private final String path;
079:
080: /**
081: * Creates a resource template cache that will use the specified servlet
082: * context to load the resources. It will use the base path of
083: * <code>"/"</code> meaning templates will be resolved relative to the
084: * servlet context root location.
085: * @param servletContext the servlet context whose
086: * {@link ServletContext#getResource(String)} will be used to load the
087: * templates.
088: */
089: public WebappTemplateLoader(ServletContext servletContext) {
090: this (servletContext, "/");
091: }
092:
093: /**
094: * Creates a template loader that will use the specified servlet
095: * context to load the resources. It will use the specified base path.
096: * The is interpreted as relative to the current context root (does not mater
097: * if you start it with "/" or not). Path components
098: * should be separated by forward slashes independently of the separator
099: * character used by the underlying operating system.
100: * @param servletContext the servlet context whose
101: * {@link ServletContext#getResource(String)} will be used to load the
102: * templates.
103: * @param path the base path to template resources.
104: */
105: public WebappTemplateLoader(ServletContext servletContext,
106: String path) {
107: if (servletContext == null) {
108: throw new IllegalArgumentException("servletContext == null");
109: }
110: if (path == null) {
111: throw new IllegalArgumentException("path == null");
112: }
113:
114: path = path.replace('\\', '/');
115: if (!path.endsWith("/")) {
116: path += "/";
117: }
118: if (!path.startsWith("/")) {
119: path = "/" + path;
120: }
121: this .path = path;
122: this .servletContext = servletContext;
123: }
124:
125: public Object findTemplateSource(String name) throws IOException {
126: String fullPath = path + name;
127: // First try to open as plain file (to bypass servlet container resource caches).
128: try {
129: String realPath = servletContext.getRealPath(fullPath);
130: if (realPath != null) {
131: File file = new File(realPath);
132: if (!file.isFile()) {
133: return null;
134: }
135: if (file.canRead()) {
136: return file;
137: }
138: }
139: } catch (SecurityException e) {
140: ;// ignore
141: }
142:
143: // If it fails, try to open it with servletContext.getResource.
144: URL url = null;
145: try {
146: url = servletContext.getResource(fullPath);
147: } catch (MalformedURLException e) {
148: logger.warn("Could not retrieve resource " + fullPath, e);
149: return null;
150: }
151: return url == null ? null : new URLTemplateSource(url);
152: }
153:
154: public long getLastModified(Object templateSource) {
155: if (templateSource instanceof File) {
156: return ((File) templateSource).lastModified();
157: } else {
158: return ((URLTemplateSource) templateSource).lastModified();
159: }
160: }
161:
162: public Reader getReader(Object templateSource, String encoding)
163: throws IOException {
164: if (templateSource instanceof File) {
165: return new InputStreamReader(new FileInputStream(
166: (File) templateSource), encoding);
167: } else {
168: return new InputStreamReader(
169: ((URLTemplateSource) templateSource)
170: .getInputStream(), encoding);
171: }
172: }
173:
174: public void closeTemplateSource(Object templateSource)
175: throws IOException {
176: if (templateSource instanceof File) {
177: // Do nothing.
178: } else {
179: ((URLTemplateSource) templateSource).close();
180: }
181: }
182: }
|