001: /*
002: * SSIMediator.java
003: * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/ssi/SSIMediator.java,v 1.1 2002/05/24 04:38:58 billbarker Exp $
004: * $Revision: 1.1 $
005: * $Date: 2002/05/24 04:38:58 $
006: *
007: * ====================================================================
008: *
009: * The Apache Software License, Version 1.1
010: *
011: * Copyright (c) 1999 The Apache Software Foundation. All rights
012: * reserved.
013: *
014: * Redistribution and use in source and binary forms, with or without
015: * modification, are permitted provided that the following conditions
016: * are met:
017: *
018: * 1. Redistributions of source code must retain the above copyright
019: * notice, this list of conditions and the following disclaimer.
020: *
021: * 2. Redistributions in binary form must reproduce the above copyright
022: * notice, this list of conditions and the following disclaimer in
023: * the documentation and/or other materials provided with the
024: * distribution.
025: *
026: * 3. The end-user documentation included with the redistribution, if
027: * any, must include the following acknowlegement:
028: * "This product includes software developed by the
029: * Apache Software Foundation (http://www.apache.org/)."
030: * Alternately, this acknowlegement may appear in the software itself,
031: * if and wherever such third-party acknowlegements normally appear.
032: *
033: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
034: * Foundation" must not be used to endorse or promote products derived
035: * from this software without prior written permission. For written
036: * permission, please contact apache@apache.org.
037: *
038: * 5. Products derived from this software may not be called "Apache"
039: * nor may "Apache" appear in their names without prior written
040: * permission of the Apache Group.
041: *
042: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
043: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
044: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
045: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
046: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
047: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
048: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
049: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
050: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
051: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
052: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
053: * SUCH DAMAGE.
054: * ====================================================================
055: *
056: * This software consists of voluntary contributions made by many
057: * individuals on behalf of the Apache Software Foundation. For more
058: * information on the Apache Software Foundation, please see
059: * <http://www.apache.org/>.
060: *
061: * [Additional notices, if required by prior licensing conditions]
062: *
063: */
064: package org.apache.catalina.ssi;
065:
066: import java.io.IOException;
067: import java.io.PrintWriter;
068: import java.io.StringWriter;
069: import java.text.DateFormat;
070: import java.text.SimpleDateFormat;
071: import java.util.ArrayList;
072: import java.util.Collection;
073: import java.util.Date;
074: import java.util.HashMap;
075: import java.util.HashSet;
076: import java.util.Iterator;
077: import java.util.List;
078: import java.util.Set;
079: import java.util.TimeZone;
080: import org.apache.catalina.util.DateTool;
081: import org.apache.catalina.util.URLEncoder;
082: import org.apache.catalina.util.Strftime;
083:
084: /**
085: * Allows the different SSICommand implementations to share data/talk to each other
086: *
087: * @author Bip Thelin
088: * @author Amy Roh
089: * @author Dan Sandberg
090: * @version $Revision: 1.1 $, $Date: 2002/05/24 04:38:58 $
091: */
092: public class SSIMediator {
093: protected final static String DEFAULT_CONFIG_ERR_MSG = "[an error occurred while processing this directive]";
094: protected final static String DEFAULT_CONFIG_TIME_FMT = "%A, %d-%b-%Y %T %Z";
095: protected final static String DEFAULT_CONFIG_SIZE_FMT = "abbrev";
096: protected static URLEncoder urlEncoder;
097: protected String configErrMsg = DEFAULT_CONFIG_ERR_MSG;
098: protected String configTimeFmt = DEFAULT_CONFIG_TIME_FMT;
099: protected String configSizeFmt = DEFAULT_CONFIG_SIZE_FMT;
100: protected String className = getClass().getName();
101: protected SSIExternalResolver ssiExternalResolver;
102: protected Date lastModifiedDate;
103: protected int debug;
104: protected Strftime strftime;
105:
106: static {
107: //We try to encode only the same characters that apache does
108: urlEncoder = new URLEncoder();
109: urlEncoder.addSafeCharacter(',');
110: urlEncoder.addSafeCharacter(':');
111: urlEncoder.addSafeCharacter('-');
112: urlEncoder.addSafeCharacter('_');
113: urlEncoder.addSafeCharacter('.');
114: urlEncoder.addSafeCharacter('*');
115: urlEncoder.addSafeCharacter('/');
116: urlEncoder.addSafeCharacter('!');
117: urlEncoder.addSafeCharacter('~');
118: urlEncoder.addSafeCharacter('\'');
119: urlEncoder.addSafeCharacter('(');
120: urlEncoder.addSafeCharacter(')');
121: }
122:
123: public SSIMediator(SSIExternalResolver ssiExternalResolver,
124: Date lastModifiedDate, int debug) {
125: this .ssiExternalResolver = ssiExternalResolver;
126: this .lastModifiedDate = lastModifiedDate;
127: this .debug = debug;
128:
129: setConfigTimeFmt(DEFAULT_CONFIG_TIME_FMT, true);
130: }
131:
132: public void setConfigErrMsg(String configErrMsg) {
133: this .configErrMsg = configErrMsg;
134: }
135:
136: public void setConfigTimeFmt(String configTimeFmt) {
137: setConfigTimeFmt(configTimeFmt, false);
138: }
139:
140: public void setConfigTimeFmt(String configTimeFmt,
141: boolean fromConstructor) {
142: this .configTimeFmt = configTimeFmt;
143:
144: //What's the story here with DateTool.LOCALE_US?? Why??
145: this .strftime = new Strftime(configTimeFmt, DateTool.LOCALE_US);
146:
147: //Variables like DATE_LOCAL, DATE_GMT, and LAST_MODIFIED need to be updated when
148: //the timefmt changes. This is what Apache SSI does.
149: setDateVariables(fromConstructor);
150: }
151:
152: public void setConfigSizeFmt(String configSizeFmt) {
153: this .configSizeFmt = configSizeFmt;
154: }
155:
156: public String getConfigErrMsg() {
157: return configErrMsg;
158: }
159:
160: public String getConfigTimeFmt() {
161: return configTimeFmt;
162: }
163:
164: public String getConfigSizeFmt() {
165: return configSizeFmt;
166: }
167:
168: public Collection getVariableNames() {
169: Set variableNames = new HashSet();
170: //These built-in variables are supplied by the mediator ( if not over-written by the user ) and always exist
171: variableNames.add("DATE_GMT");
172: variableNames.add("DATE_LOCAL");
173: variableNames.add("LAST_MODIFIED");
174: ssiExternalResolver.addVariableNames(variableNames);
175:
176: //Remove any variables that are reserved by this class
177: Iterator iter = variableNames.iterator();
178: while (iter.hasNext()) {
179: String name = (String) iter.next();
180: if (isNameReserved(name)) {
181: iter.remove();
182: }
183: }
184: return variableNames;
185: }
186:
187: public long getFileSize(String path, boolean virtual)
188: throws IOException {
189: return ssiExternalResolver.getFileSize(path, virtual);
190: }
191:
192: public long getFileLastModified(String path, boolean virtual)
193: throws IOException {
194: return ssiExternalResolver.getFileLastModified(path, virtual);
195: }
196:
197: public String getFileText(String path, boolean virtual)
198: throws IOException {
199: return ssiExternalResolver.getFileText(path, virtual);
200: }
201:
202: protected boolean isNameReserved(String name) {
203: return name.startsWith(className + ".");
204: }
205:
206: public String getVariableValue(String variableName) {
207: return getVariableValue(variableName, "none");
208: }
209:
210: public void setVariableValue(String variableName,
211: String variableValue) {
212: if (!isNameReserved(variableName)) {
213: ssiExternalResolver.setVariableValue(variableName,
214: variableValue);
215: }
216: }
217:
218: public String getVariableValue(String variableName, String encoding) {
219: String lowerCaseVariableName = variableName.toLowerCase();
220: String variableValue = null;
221:
222: if (!isNameReserved(lowerCaseVariableName)) {
223: //Try getting it externally first, if it fails, try getting the 'built-in' value
224: variableValue = ssiExternalResolver
225: .getVariableValue(variableName);
226: if (variableValue == null) {
227: variableName = variableName.toUpperCase();
228: variableValue = (String) ssiExternalResolver
229: .getVariableValue(className + "."
230: + variableName);
231: }
232: if (variableValue != null) {
233: variableValue = encode(variableValue, encoding);
234: }
235: }
236: return variableValue;
237: }
238:
239: protected String formatDate(Date date, TimeZone timeZone) {
240: String retVal;
241:
242: if (timeZone != null) {
243: //we temporarily change strftime. Since SSIMediator is inherently single-threaded, this
244: //isn't a problem
245: TimeZone oldTimeZone = strftime.getTimeZone();
246: strftime.setTimeZone(timeZone);
247: retVal = strftime.format(date);
248: strftime.setTimeZone(oldTimeZone);
249: } else {
250: retVal = strftime.format(date);
251: }
252: return retVal;
253: }
254:
255: protected String encode(String value, String encoding) {
256: String retVal = null;
257:
258: if (encoding.equalsIgnoreCase("url")) {
259: retVal = urlEncoder.encode(value);
260: } else if (encoding.equalsIgnoreCase("none")) {
261: retVal = value;
262: } else if (encoding.equalsIgnoreCase("entity")) {
263: //Not sure how this is really different than none
264: retVal = value;
265: } else {
266: //This shouldn't be possible
267: throw new IllegalArgumentException("Unknown encoding: "
268: + encoding);
269: }
270: return retVal;
271: }
272:
273: public void log(String message) {
274: ssiExternalResolver.log(message, null);
275: }
276:
277: public void log(String message, Throwable throwable) {
278: ssiExternalResolver.log(message, throwable);
279: }
280:
281: protected void setDateVariables(boolean fromConstructor) {
282: boolean alreadySet = ssiExternalResolver
283: .getVariableValue(className + ".alreadyset") != null;
284: //skip this if we are being called from the constructor, and this has already been set
285: if (!(fromConstructor && alreadySet)) {
286: ssiExternalResolver.setVariableValue(className
287: + ".alreadyset", "true");
288:
289: Date date = new Date();
290: TimeZone timeZone = TimeZone.getTimeZone("GMT");
291: String retVal = formatDate(date, timeZone);
292:
293: //If we are setting on of the date variables, we want to remove them from the user
294: //defined list of variables, because this is what Apache does
295: setVariableValue("DATE_GMT", null);
296: ssiExternalResolver.setVariableValue(className
297: + ".DATE_GMT", retVal);
298:
299: retVal = formatDate(date, null);
300: setVariableValue("DATE_LOCAL", null);
301: ssiExternalResolver.setVariableValue(className
302: + ".DATE_LOCAL", retVal);
303:
304: retVal = formatDate(lastModifiedDate, null);
305: setVariableValue("LAST_MODIFIED", null);
306: ssiExternalResolver.setVariableValue(className
307: + ".LAST_MODIFIED", retVal);
308: }
309: }
310: }
|