001: /*
002: * Copyright (c) 2005 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.Reader;
056: import java.io.StringReader;
057: import java.util.HashMap;
058: import java.util.Map;
059:
060: /**
061: * A {@link TemplateLoader} that uses a Map with Strings as its source of
062: * templates.
063: *
064: * In most case the regular way of loading templates from files will be fine.
065: * However, there can be situations where you don't want to or can't load a
066: * template from a file, e.g. if you have to deploy a single jar for
067: * JavaWebStart or if they are contained within a database.
068: * A single template can be created manually
069: * e.g.
070: * <pre>
071: * String templateStr="Hello ${user}";
072: * Template t = new Template("name", new StringReader(templateStr),
073: * new Configuration());
074: * </pre>
075: * If, however, you want to create templates from strings which import other
076: * templates this method doesn't work.
077: *
078: * In that case you can create a StringTemplateLoader and add each template to
079: * it:
080: * <pre>
081: * StringTemplateLoader stringLoader = new StringTemplateLoader();
082: * stringLoader.putTemplate("greetTemplate", "<#macro greet>Hello</#macro>");
083: * stringLoader.putTemplate("myTemplate", "<#include \"greetTemplate\"><@greet/> World!");
084: * </pre>
085: * Then you tell your Configuration object to use it:
086: * <pre>
087: * cfg.setTemplateLoader(stringLoader);
088: * </pre>
089: * After that you should be able to use the templates as usual. Often you will
090: * want to combine a <tt>StringTemplateLoader</tt> with another loader. You can
091: * do so using a {@link freemarker.cache.MultiTemplateLoader}.
092: *
093: * @version $Id: v 1.0 2005/04/01
094: * @author Meikel Bisping
095: * @author Attila Szegedi
096: * @version $Id: StringTemplateLoader.java,v 1.1 2005/04/08 11:47:53 szegedia Exp $
097: */
098: public class StringTemplateLoader implements TemplateLoader {
099: private final Map templates = new HashMap();
100:
101: /**
102: * Puts a template into the loader. A call to this method is identical to
103: * the call to the three-arg {@link #putTemplate(String, String, long)}
104: * passing <tt>System.currentTimeMillis()</tt> as the third argument.
105: * @param name the name of the template.
106: * @param templateSource the source code of the template.
107: */
108: public void putTemplate(String name, String templateSource) {
109: putTemplate(name, templateSource, System.currentTimeMillis());
110: }
111:
112: /**
113: * Puts a template into the loader. The name can contain slashes to denote
114: * logical directory structure, but must not start with a slash. If the
115: * method is called multiple times for the same name and with different
116: * last modified time, the configuration's template cache will reload the
117: * template according to its own refresh settings (note that if the refresh
118: * is disabled in the template cache, the template will not be reloaded).
119: * Also, since the cache uses lastModified to trigger reloads, calling the
120: * method with different source and identical timestamp won't trigger
121: * reloading.
122: * @param name the name of the template.
123: * @param templateSource the source code of the template.
124: * @param lastModified the time of last modification of the template in
125: * terms of <tt>System.currentTimeMillis()</tt>
126: */
127: public void putTemplate(String name, String templateSource,
128: long lastModified) {
129: templates.put(name, new StringTemplateSource(name,
130: templateSource, lastModified));
131: }
132:
133: public void closeTemplateSource(Object templateSource) {
134: }
135:
136: public Object findTemplateSource(String name) {
137: return templates.get(name);
138: }
139:
140: public long getLastModified(Object templateSource) {
141: return ((StringTemplateSource) templateSource).lastModified;
142: }
143:
144: public Reader getReader(Object templateSource, String encoding) {
145: return new StringReader(
146: ((StringTemplateSource) templateSource).source);
147: }
148:
149: private static class StringTemplateSource {
150: private final String name;
151: private final String source;
152: private final long lastModified;
153:
154: StringTemplateSource(String name, String source,
155: long lastModified) {
156: if (name == null) {
157: throw new IllegalArgumentException("name == null");
158: }
159: if (source == null) {
160: throw new IllegalArgumentException("source == null");
161: }
162: if (lastModified < -1L) {
163: throw new IllegalArgumentException("lastModified < -1L");
164: }
165: this .name = name;
166: this .source = source;
167: this .lastModified = lastModified;
168: }
169:
170: public boolean equals(Object obj) {
171: if (obj instanceof StringTemplateSource) {
172: return name.equals(((StringTemplateSource) obj).name);
173: }
174: return false;
175: }
176:
177: public int hashCode() {
178: return name.hashCode();
179: }
180: }
181: }
|