001: /******************************************************************************
002: * ResponderXMLDATA.java
003: * ****************************************************************************/package org.openlaszlo.servlets.responders;
004:
005: import java.io.*;
006: import java.net.InetAddress;
007: import java.net.MalformedURLException;
008: import java.net.URL;
009: import java.net.UnknownHostException;
010: import java.util.Date;
011: import java.util.HashMap;
012: import java.util.Iterator;
013: import java.util.Properties;
014: import javax.servlet.ServletConfig;
015: import javax.servlet.ServletContext;
016: import javax.servlet.ServletException;
017: import javax.servlet.ServletOutputStream;
018: import javax.servlet.http.HttpServletRequest;
019: import javax.servlet.http.HttpServletResponse;
020: import javax.servlet.http.HttpUtils;
021: import org.apache.commons.httpclient.URI;
022: import org.apache.commons.httpclient.URIException;
023: import org.openlaszlo.cache.RequestCache;
024: import org.openlaszlo.cache.XMLDataCache;
025: import org.openlaszlo.compiler.Canvas;
026: import org.openlaszlo.compiler.CompilationError;
027: import org.openlaszlo.data.*;
028: import org.openlaszlo.media.MimeType;
029: import org.openlaszlo.server.LPS;
030: import org.openlaszlo.servlets.LoadCount;
031: import org.openlaszlo.utils.ChainedException;
032: import org.openlaszlo.utils.FileUtils;
033: import org.openlaszlo.utils.LZHttpUtils;
034: import org.openlaszlo.utils.SWFUtils;
035: import org.openlaszlo.xml.internal.DataCompiler;
036: import org.openlaszlo.xml.internal.XMLUtils;
037:
038: import org.apache.log4j.Logger;
039:
040: /**
041: * Cache HTTP XML data requests as XML source
042: */
043: public final class ResponderXMLDATA extends ResponderCache {
044: private static XMLDataCache mCache = null;
045: private static boolean mIsInitialized = false;
046: private static Logger mLogger = Logger
047: .getLogger(ResponderXMLDATA.class);
048:
049: synchronized public void init(String reqName, ServletConfig config,
050: Properties prop) throws ServletException, IOException {
051: // Cache should only be initialized once.
052: if (!mIsInitialized) {
053: // Initialize data cache
054: String cacheDir = config
055: .getInitParameter("lps.dxcache.directory");
056: if (cacheDir == null) {
057: cacheDir = prop.getProperty("dxcache.directory");
058: }
059: if (cacheDir == null) {
060: cacheDir = LPS.getWorkDirectory() + File.separator
061: + "dxcache";
062: }
063:
064: File cache = checkDirectory(cacheDir);
065: mLogger.info("Data Cache is at " + cacheDir);
066:
067: //------------------------------------------------------------
068: // Support for new style data response
069: //------------------------------------------------------------
070: try {
071: mCache = new XMLDataCache(cache, prop);
072: } catch (IOException e) {
073: throw new ServletException(e.getMessage());
074: }
075:
076: mIsInitialized = true;
077: }
078: super .init(reqName, config, mCache, prop);
079: }
080:
081: static public RequestCache getCache() {
082: return mCache;
083: }
084:
085: protected void respondImpl(HttpServletRequest req,
086: HttpServletResponse res) {
087:
088: String path = req.getServletPath();
089: String url;
090: try {
091: url = DataSource.getURL(req);
092: } catch (java.net.MalformedURLException e) {
093: respondWithError(res, "bad url: " + e.getMessage(),
094: MIME_TYPE_XML);
095: if (mCollectStat) {
096: mURLStat
097: .error(URLStat.ERRTYPE_MALFORMED_URL, "bad-url");
098: }
099: return;
100: }
101:
102: res.setContentType("application/xml");
103:
104: if (req.getMethod().intern() == "POST") {
105: float fpv = getFlashPlayerVersion(req);
106: String ua = req.getHeader(LZHttpUtils.USER_AGENT);
107: mLogger.debug(
108: /* (non-Javadoc)
109: * @i18n.test
110: * @org-mes="POST request, flash player version: " + p[0]
111: */
112: org.openlaszlo.i18n.LaszloMessages.getMessage(
113: ResponderCache.class.getName(), "051018-328",
114: new Object[] { new Float(fpv) }));
115: if (fpv < 6.47
116: && LPS.configuration.optionAllows(
117: "disable-post-keep-alive", ua)) {
118: // Prevent browser keep-alive to get around bug 4048.
119: mLogger.debug(
120: /* (non-Javadoc)
121: * @i18n.test
122: * @org-mes="Disabling keep-alive for " + p[0]
123: */
124: org.openlaszlo.i18n.LaszloMessages.getMessage(
125: ResponderCache.class.getName(), "051018-339",
126: new Object[] { ua }));
127: res.setHeader("Connection", "close");
128: res.setHeader("Keep-Alive", "close");
129: }
130: }
131:
132: if (!LPS.configuration.optionAllows(path,
133: "proxy-security-urls", url)) {
134: String err = "Forbidden url: " + url;
135: respondWithError(res, err, MIME_TYPE_XML);
136: mLogger.error(err);
137: if (mCollectStat) {
138: mURLStat.error(URLStat.ERRTYPE_FORBIDDEN, url);
139: }
140: return;
141: }
142:
143: int errType = URLStat.ERRTYPE_NONE;
144:
145: try {
146:
147: DataSource source = getDataSource(req, res);
148: if (source == null) {
149: return;
150: }
151:
152: res.setContentType("application/xml");
153:
154: String app = LZHttpUtils.getRealPath(mContext, req);
155: boolean isClientCacheable = DataSource
156: .isClientCacheable(req);
157: if (mCache.isCacheable(req)) {
158: if (isClientCacheable) {
159: mLogger.info(
160: /* (non-Javadoc)
161: * @i18n.test
162: * @org-mes="proxying " + p[0] + ", cacheable on server and client"
163: */
164: org.openlaszlo.i18n.LaszloMessages.getMessage(
165: ResponderCache.class.getName(),
166: "051018-377", new Object[] { url }));
167: } else {
168: mLogger.info(
169: /* (non-Javadoc)
170: * @i18n.test
171: * @org-mes="proxying " + p[0] + ", cacheable on server and not client"
172: */
173: org.openlaszlo.i18n.LaszloMessages.getMessage(
174: ResponderCache.class.getName(),
175: "051018-386", new Object[] { url }));
176: }
177: mCache.getAsSWF(app, req, res, source);
178: } else {
179: if (isClientCacheable) {
180: mLogger.info(
181: /* (non-Javadoc)
182: * @i18n.test
183: * @org-mes="proxying " + p[0] + ", not cacheable on server and cacheable on the client"
184: */
185: org.openlaszlo.i18n.LaszloMessages.getMessage(
186: ResponderCache.class.getName(),
187: "051018-398", new Object[] { url }));
188: } else {
189: mLogger.info(
190: /* (non-Javadoc)
191: * @i18n.test
192: * @org-mes="proxying " + p[0] + ", not cacheable on server or client"
193: */
194: org.openlaszlo.i18n.LaszloMessages.getMessage(
195: ResponderCache.class.getName(),
196: "051018-407", new Object[] { url }));
197: }
198: source.getAsSWF(app, req, res, getConverter());
199: }
200: } catch (ConversionException e) {
201: respondWithError(res,
202: /* (non-Javadoc)
203: * @i18n.test
204: * @org-mes="data conversion error for " + p[0] + ": " + p[1]
205: */
206: org.openlaszlo.i18n.LaszloMessages.getMessage(
207: ResponderCache.class.getName(), "051018-419",
208: new Object[] { url, e.getMessage() }),
209: MIME_TYPE_XML);
210: errType = URLStat.ERRTYPE_CONVERSION;
211: } catch (DataSourceException e) {
212: respondWithError(res,
213: /* (non-Javadoc)
214: * @i18n.test
215: * @org-mes="data source error for " + p[0] + ": " + p[1]
216: */
217: org.openlaszlo.i18n.LaszloMessages.getMessage(
218: ResponderCache.class.getName(), "051018-428",
219: new Object[] { url, e.getMessage() }),
220: MIME_TYPE_XML);
221: errType = URLStat.ERRTYPE_DATA_SOURCE;
222: } catch (UnknownHostException e) {
223: respondWithError(res,
224: /* (non-Javadoc)
225: * @i18n.test
226: * @org-mes="unknown host for " + p[0] + ": " + p[1]
227: */
228: org.openlaszlo.i18n.LaszloMessages.getMessage(
229: ResponderCache.class.getName(), "051018-437",
230: new Object[] { url, e.getMessage() }),
231: MIME_TYPE_XML);
232: errType = URLStat.ERRTYPE_UNKNOWN_HOST;
233: } catch (URIException e) {
234: respondWithError(res,
235: /* (non-Javadoc)
236: * @i18n.test
237: * @org-mes="bad url: " + p[0]
238: */
239: org.openlaszlo.i18n.LaszloMessages.getMessage(
240: ResponderCache.class.getName(), "051018-446",
241: new Object[] { e.getMessage() }), MIME_TYPE_XML);
242: errType = URLStat.ERRTYPE_MALFORMED_URL;
243: } catch (MalformedURLException e) {
244: respondWithError(res,
245: /* (non-Javadoc)
246: * @i18n.test
247: * @org-mes="bad url: " + p[0]
248: */
249: org.openlaszlo.i18n.LaszloMessages.getMessage(
250: ResponderCache.class.getName(), "051018-446",
251: new Object[] { e.getMessage() }), MIME_TYPE_XML);
252: errType = URLStat.ERRTYPE_MALFORMED_URL;
253: } catch (InterruptedIOException e) {
254: respondWithError(res,
255: /* (non-Javadoc)
256: * @i18n.test
257: * @org-mes="backend timeout for " + p[0] + ": " + p[1]
258: */
259: org.openlaszlo.i18n.LaszloMessages.getMessage(
260: ResponderCache.class.getName(), "051018-466",
261: new Object[] { url, e.getMessage() }),
262: MIME_TYPE_XML);
263: errType = URLStat.ERRTYPE_TIMEOUT;
264: } catch (IOException e) {
265: // Handle SocketTimeoutExceptions as timeouts instead of IO issues
266: Class stec = null;
267: try {
268: stec = Class.forName("java.net.SocketTimeoutException");
269: } catch (ClassNotFoundException cfne) {
270: }
271: if (stec != null && stec.isAssignableFrom(e.getClass())) {
272: errType = URLStat.ERRTYPE_TIMEOUT;
273: respondWithError(res,
274: /* (non-Javadoc)
275: * @i18n.test
276: * @org-mes="backend timeout for " + p[0] + ": " + p[1]
277: */
278: org.openlaszlo.i18n.LaszloMessages.getMessage(
279: ResponderCache.class.getName(), "051018-466",
280: new Object[] { url, e.getMessage() }),
281: MIME_TYPE_XML);
282: } else {
283: respondWithException(res, e);
284: errType = URLStat.ERRTYPE_IO;
285: }
286: } catch (IllegalArgumentException e) {
287: respondWithException(res, e);
288: errType = URLStat.ERRTYPE_ILLEGAL_ARGUMENT;
289: } catch (Throwable e) {
290: // Makes much easier to debug runtime exceptions
291: // but perhaps not strictly correct.
292: respondWithException(res, e);
293: errType = URLStat.ERRTYPE_OTHER;
294: }
295:
296: if (mCollectStat) {
297: if (errType == URLStat.ERRTYPE_NONE)
298: mURLStat.success(url);
299: else
300: mURLStat.error(errType, url);
301: }
302: }
303:
304: public int getMimeType() {
305: return MIME_TYPE_XMLDATA;
306: }
307:
308: }
|