001: package bsh.servlet;
002:
003: /**
004:
005: This file is derived from Pat Niemeyer's free utilities package.
006: Now part of BeanShell.
007:
008: @see http://www.pat.net/javautil/
009: @version 1.0
010: @author Pat Niemeyer (pat@pat.net)
011: */
012:
013: import java.io.*;
014: import java.util.*;
015: import java.net.URL;
016:
017: /**
018: This is a simple template engine. An instance of SimpleTemplate wraps
019: a StringBuffer and performs replace operations on one or more parameters
020: embedded as HMTL style comments. The value can then be retrieved as a
021: String or written to a stream.
022:
023: Template values in the text are of the form:
024:
025: <!-- TEMPLATE-NAME -->
026:
027: Substitutions then take the form of:
028:
029: template.replace( "NAME", value );
030:
031: Two static util methods are provided to help read the text of a template
032: from a stream (perhaps a URL or resource). e.g.
033:
034: @author Pat Niemeyer
035: */
036: public class SimpleTemplate {
037: StringBuffer buff;
038: static String NO_TEMPLATE = "NO_TEMPLATE"; // Flag for non-existent
039: static Map templateData = new HashMap();
040: static boolean cacheTemplates = true;
041:
042: /**
043: Get a template by name, with caching.
044: Note: this should be updated to search the resource path first, etc.
045:
046: Create a new instance of a template from the specified file.
047:
048: The file text is cached so lookup is fast. Failure to find the
049: file is also cached so the read will not happen twice.
050:
051: */
052: public static SimpleTemplate getTemplate(String file) {
053: String templateText = (String) templateData.get(file);
054:
055: if (templateText == null || !cacheTemplates) {
056: try {
057: FileReader fr = new FileReader(file);
058: templateText = SimpleTemplate.getStringFromStream(fr);
059: templateData.put(file, templateText);
060: } catch (IOException e) {
061: // Not found
062: templateData.put(file, NO_TEMPLATE);
063: }
064: } else
065: // Quick check prevents trying each time
066: if (templateText.equals(NO_TEMPLATE))
067: return null;
068:
069: if (templateText == null)
070: return null;
071: else
072: return new SimpleTemplate(templateText);
073: }
074:
075: public static String getStringFromStream(InputStream ins)
076: throws IOException {
077: return getStringFromStream(new InputStreamReader(ins));
078: }
079:
080: public static String getStringFromStream(Reader reader)
081: throws IOException {
082: StringBuffer sb = new StringBuffer();
083: BufferedReader br = new BufferedReader(reader);
084: String line;
085: while ((line = br.readLine()) != null)
086: sb.append(line + "\n");
087:
088: return sb.toString();
089: }
090:
091: public SimpleTemplate(String template) {
092: init(template);
093: }
094:
095: public SimpleTemplate(Reader reader) throws IOException {
096: String template = getStringFromStream(reader);
097: init(template);
098: }
099:
100: public SimpleTemplate(URL url) throws IOException {
101: String template = getStringFromStream(url.openStream());
102: init(template);
103: }
104:
105: private void init(String s) {
106: buff = new StringBuffer(s);
107: }
108:
109: /**
110: Substitute the specified text for the parameter
111: */
112: public void replace(String param, String value) {
113: int[] range;
114: while ((range = findTemplate(param)) != null)
115: buff.replace(range[0], range[1], value);
116: }
117:
118: /**
119: Find the starting (inclusive) and ending (exclusive) index of the
120: named template and return them as a two element int [].
121: Or return null if the param is not found.
122: */
123: int[] findTemplate(String name) {
124: String text = buff.toString();
125: int len = text.length();
126:
127: int start = 0;
128:
129: while (start < len) {
130:
131: // Find begin and end comment
132: int cstart = text.indexOf("<!--", start);
133: if (cstart == -1)
134: return null; // no more comments
135: int cend = text.indexOf("-->", cstart);
136: if (cend == -1)
137: return null; // no more complete comments
138: cend += "-->".length();
139:
140: // Find template tag
141: int tstart = text.indexOf("TEMPLATE-", cstart);
142: if (tstart == -1) {
143: start = cend; // try the next comment
144: continue;
145: }
146:
147: // Is the tag inside the comment we found?
148: if (tstart > cend) {
149: start = cend; // try the next comment
150: continue;
151: }
152:
153: // find begin and end of param name
154: int pstart = tstart + "TEMPLATE-".length();
155:
156: int pend = len;
157: for (pend = pstart; pend < len; pend++) {
158: char c = text.charAt(pend);
159: if (c == ' ' || c == '\t' || c == '-')
160: break;
161: }
162: if (pend >= len)
163: return null;
164:
165: String param = text.substring(pstart, pend);
166:
167: // If it's the correct one, return the comment extent
168: if (param.equals(name))
169: return new int[] { cstart, cend };
170:
171: //System.out.println( "Found param: {"+param+"} in comment: "+ text.substring(cstart, cend) +"}");
172: // Else try the next one
173: start = cend;
174: }
175:
176: // Not found
177: return null;
178: }
179:
180: public String toString() {
181: return buff.toString();
182: }
183:
184: public void write(PrintWriter out) {
185: out.println(toString());
186: }
187:
188: public void write(PrintStream out) {
189: out.println(toString());
190: }
191:
192: /**
193: usage: filename param value
194: */
195: public static void main(String[] args) throws IOException {
196: String filename = args[0];
197: String param = args[1];
198: String value = args[2];
199:
200: FileReader fr = new FileReader(filename);
201: String templateText = SimpleTemplate.getStringFromStream(fr);
202: SimpleTemplate template = new SimpleTemplate(templateText);
203:
204: template.replace(param, value);
205: template.write(System.out);
206: }
207:
208: public static void setCacheTemplates(boolean b) {
209: cacheTemplates = b;
210: }
211:
212: }
|