KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openlaszlo > servlets > LZServlet


1 /******************************************************************************
2  * LZServlet.java
3  * ****************************************************************************/

4
5 /* J_LZ_COPYRIGHT_BEGIN *******************************************************
6 * Copyright 2001-2004 Laszlo Systems, Inc. All Rights Reserved. *
7 * Use is subject to license terms. *
8 * J_LZ_COPYRIGHT_END *********************************************************/

9
10 package org.openlaszlo.servlets;
11
12 import java.io.*;
13 import java.net.*;
14 import java.util.*;
15 import javax.servlet.*;
16 import javax.servlet.http.*;
17 import javax.servlet.ServletConfig JavaDoc.*;
18
19 import org.openlaszlo.servlets.responders.*;
20 import org.openlaszlo.server.*;
21 import org.openlaszlo.utils.ChainedException;
22 import org.openlaszlo.utils.LZUtils;
23 import org.openlaszlo.utils.LZHttpUtils;
24 import org.openlaszlo.utils.MathUtils;
25
26 import org.apache.log4j.*;
27
28 /**
29  * LZServlet is the main entry point for the Laszlo Presentation Server
30  *
31  * The LZServlet will respond to GET (and POST) requests
32  * per the spec at
33  * <a HREF="../../../../lps-servlet-spec.html">
34  * $LPS_HOME/server/doc/lps-servlet-spec.html</a>
35  *
36  * Each request type (lzt query string variable) has
37  * a Responder object that is used to construct a responder.
38  *
39  */

40 public class LZServlet extends HttpServlet
41 {
42     private static Logger mLogger = null;
43     private File mLogFile = null;
44
45     private final static String JavaDoc DEFAULT_REQUEST_TYPE = "defaultRequestType";
46     private static String JavaDoc mDefaultRequestType = "html";
47
48     /** Responder object map */
49     public static HashMap mResponderMap = new HashMap();
50
51     /** Request counter */
52     private int mRequestCounter = 1;
53
54     /** LPS properties */
55     private Properties mProperties = new Properties();
56
57     /**
58      * @return true if init succeeded
59      * @param config ServletConfig object
60      */

61     public boolean initLPS(HttpServletRequest req,
62             HttpServletResponse res) {
63
64         ServletConfig JavaDoc config = getServletConfig();
65         ServletContext ctxt = config.getServletContext();
66         String JavaDoc webappName = getServletContextName(ctxt);
67
68         // Sanity check the servlet context version
69
if ((ctxt.getMajorVersion() < 2) ||
70             (ctxt.getMajorVersion() == 2 && ctxt.getMinorVersion() < 3)) {
71             respondWithInitError(req, res, "Must be at least " +
72                                        "Version 2.3 Servlet Container!");
73             return false;
74         }
75
76         // Check for LPS_HOME
77
String JavaDoc lhome = getInitParameter("LPS_HOME");
78         if (lhome == null) {
79             // Default to webapp
80
lhome = LZHttpUtils.getRealPath(ctxt, "/");
81
82             // FIXME: [2003-04-28 bloch] remove this code when
83
// we fix bug 540. Safety check for now
84
if (lhome == null) {
85                 respondWithInitError(req, res, "LPS requires a servlet container" +
86                         " that can implements ServletContent.getRealPath()");
87                 return false;
88             }
89         }
90
91         log("LPS_HOME is " + lhome);
92         LPS.setHome(lhome);
93
94         // Configure logging
95
String JavaDoc lpsConfigDir = ConfigDir.get(lhome);
96         log("LPS config directory is: " + lpsConfigDir);
97
98         try {
99             ResponderLOGCONFIG.configure(this);
100         } catch (Exception JavaDoc e) {
101             respondWithInitException(req, res, e);
102             return false;
103         }
104
105         mLogger = Logger.getLogger(LZServlet.class);
106
107         // TODO: 2004-09-08 bloch merge with code in LPS.getInfo()
108
// Log some basic information
109
{
110             logInitInfo("------------------------------------");
111             logInitInfo("Laszlo Presentation Server, " + LPS.getVersion() + ", initialized");
112             logInitInfo("Running in context:" + ctxt.getServerInfo());
113             logInitInfo("Build: " + LPS.getBuild());
114             logInitInfo("Built on: " + LPS.getBuildDate());
115             logInitInfo("Running against JRE " +
116                                    LPS.getSystemPropertyOrUnknowable("java.version"));
117             logInitInfo("Running with Java CLASSPATH: " +
118                                    LPS.getSystemPropertyOrUnknowable("java.class.path"));
119             logInitInfo("Running on " + LPS.getSystemPropertyOrUnknowable("os.name") + " " +
120                                         LPS.getSystemPropertyOrUnknowable("os.version"));
121             logInitInfo("Running as user " + LPS.getSystemPropertyOrUnknowable("user.name"));
122             final double MEG = 1024*1024;
123             final double mx = Runtime.getRuntime().maxMemory() / (MEG);
124             final double total = Runtime.getRuntime().totalMemory() / (MEG);
125             final double avail = Runtime.getRuntime().freeMemory() / (MEG);
126             logInitInfo("Max memory: " + MathUtils.formatDouble(mx, 2) + " MB");
127             logInitInfo("Total memory: " + MathUtils.formatDouble(total, 2) + " MB");
128             logInitInfo("Available memory: " + MathUtils.formatDouble(avail, 2) + " MB");
129
130             mLogger.info("LPS_HOME is: " + lhome);
131         }
132
133         // JRE version detection
134
String JavaDoc jvmVersion = "unknown";
135         try {
136             jvmVersion = LPS.getSystemPropertyOrUnknowable("java.specification.version");
137             int dot1Index = jvmVersion.indexOf('.');
138             if (dot1Index < 0) {
139                 dot1Index = jvmVersion.length();
140             }
141             int dot2Index = jvmVersion.indexOf('.', dot1Index+1);
142             if (dot2Index < 0) {
143                 dot2Index = jvmVersion.length();
144             }
145
146             int jvmMajor = Integer.parseInt(jvmVersion.substring(0, dot1Index));
147             int jvmMinor = Integer.parseInt(jvmVersion.substring(dot1Index+1, dot2Index));
148             if ((jvmMajor == 1 && jvmMinor < 4) || jvmMajor < 1) {
149                 String JavaDoc message = "LPS running against JRE version < 1.4; this is *not* supported!";
150                 log(message);
151                 mLogger.warn(message);
152             }
153         } catch (Exception JavaDoc e) {
154             mLogger.warn("Can't parse JRE specification version: " + jvmVersion);
155         }
156
157         // Initialize
158
LPS.initialize();
159  
160         // Debugging
161
if (mLogger.isDebugEnabled()) {
162             Enumeration attrs = ctxt.getAttributeNames();
163             while(attrs.hasMoreElements()) {
164                 String JavaDoc a = (String JavaDoc)attrs.nextElement();
165                 mLogger.debug("Attribute: " + a + " : " + ctxt.getAttribute(a));
166             }
167         }
168
169         //------------------------------------------------------------
170
// LPS property values
171
//------------------------------------------------------------
172
mProperties = LPS.getProperties();
173
174         LPS.setSWFVersionDefault(LPS.getProperty("compiler.runtime.default", "swf6"));
175
176         // Create responders that create caches (media, data, and compiler)
177
String JavaDoc[] lzt = { "swf", "media", "data" };
178         int i = 0;
179         try {
180             for (;i < lzt.length; i++) {
181                 if (getResponder(lzt[i]) == null) {
182                     respondWithInitError(req, res, "Initialization error: no request type: " + lzt[i]);
183                     return false;
184                 }
185             }
186         } catch (Throwable JavaDoc e) {
187             mLogger.error("Exception", e);
188             respondWithInitException(req, res, e);
189             return false;
190         }
191
192         mDefaultRequestType = mProperties.getProperty(DEFAULT_REQUEST_TYPE, mDefaultRequestType);
193         mLogger.info("Default request type is " + mDefaultRequestType);
194
195         return true;
196     }
197
198
199     /**
200      * Log initialization details (to both servlet log and lps.log)
201      *
202      * @param s String to log
203      */

204     private void logInitInfo(String JavaDoc s) {
205         mLogger.info(s);
206         log(s);
207     }
208
209     /**
210      * @param req @see HttpServletRequest
211      * @param res @see HttpServletResponse
212      */

213     public void doGet(HttpServletRequest req, HttpServletResponse res)
214         throws IOException, ServletException
215     {
216         // This forces clients to talk to us. We may still return NOT_MODIFIED.
217
// TODO: [bloch 2002-12-17] turn this into an lps.property
218
if (! isMacIE(req) ) { // Set only if it's not Mac IE 5.2 (see bug 811)
219
res.setHeader("Expires", "Fri, 05 Oct 2001 00:00:00 GMT");
220         }
221
222         int requestID;
223
224         // Set up logger NDC
225
synchronized (this) {
226             requestID = mRequestCounter;
227             if (requestID == 1) {
228                 if (initLPS(req, res) == false) {
229                     return;
230                 }
231             }
232             mRequestCounter++;
233         }
234
235         NDC.push(req.getRemoteAddr() + " " + (requestID));
236
237         try {
238             _doGet(req, res);
239         } finally {
240
241             mLogger.debug("Request " + requestID + " finished");
242             NDC.pop();
243             NDC.remove();
244         }
245
246     }
247
248     /**
249      * @return lzt String
250      */

251     String JavaDoc getLZT(HttpServletRequest req) {
252         String JavaDoc lzt = req.getParameter("lzt");
253         if (lzt == null || lzt.equals(""))
254             lzt = mDefaultRequestType;
255
256         return lzt;
257     }
258
259
260     /**
261      * @param req @see HttpServletRequest
262      * @param res @see HttpServletResponse
263      */

264     private void _doGet(HttpServletRequest req, HttpServletResponse res)
265         throws IOException, ServletException
266     {
267         ServletContext ctxt = getServletContext();
268         String JavaDoc fileName = LZHttpUtils.getRealPath(ctxt, req);
269
270
271         if (mLogger.isDebugEnabled()) {
272             mLogger.debug("Request: servlet path " + req.getServletPath());
273             mLogger.debug("Request: request uri " + req.getRequestURI());
274             mLogger.debug("Request: query string " + req.getQueryString());
275             mLogger.debug("Request: path info " + req.getPathInfo());
276             mLogger.debug("Request: path xlated " + req.getPathTranslated());
277             mLogger.debug("Request: server name " + req.getServerName());
278             mLogger.debug("Request: server port " + req.getServerPort());
279             mLogger.debug("Request: is secure " + req.isSecure());
280
281             Enumeration headers = req.getHeaderNames();
282             if (headers != null) {
283                 while(headers.hasMoreElements()) {
284                     String JavaDoc h = (String JavaDoc)headers.nextElement();
285                     mLogger.debug(" Header: " + h + " : " + req.getHeader(h));
286                 }
287             }
288         }
289
290         mLogger.info("Request for " + fileName);
291
292         String JavaDoc lzt = getLZT(req);
293         Responder lzres = getResponder(lzt);
294
295         if (lzres == null) {
296             mLogger.debug("No request type: " + lzt);
297             res.sendError(HttpServletResponse.SC_NOT_FOUND, "No request type: " + lzt);
298             return;
299         }
300
301         mLogger.debug("responding via: " + lzres.getClass().getName());
302         lzres.respond(req, res);
303     }
304
305     /**
306      * Get a Responder object for the given lzt string
307      */

308     private synchronized Responder getResponder(String JavaDoc lzt)
309         throws ServletException
310     {
311         Responder lzres = (Responder) mResponderMap.get(lzt);
312         String JavaDoc className = "org.openlaszlo.servlets.responders.Responder";
313
314         if (lzres == null) {
315             Class JavaDoc c = null;
316             try {
317                 className += lzt.toUpperCase();
318                 c = Class.forName(className);
319                 lzres = (Responder)c.newInstance();
320                 lzres.init(lzt, getServletConfig(), mProperties);
321                 mResponderMap.put(lzt, lzres);
322             } catch (InstantiationException JavaDoc e) {
323                 mLogger.error("InstantiationException" , e);
324                 throw new ServletException("InstantiationException: " + e.getMessage());
325             } catch (IllegalAccessException JavaDoc e) {
326                 mLogger.error("IllegalAccessException" , e);
327                 throw new ServletException("IllegalAccessException: " + e.getMessage());
328             } catch (ClassNotFoundException JavaDoc e) {
329                 try {
330                     lzres = TemplateResponder.getResponder(lzt);
331                 } catch (Throwable JavaDoc t) {
332                     mLogger.error("Exception getting template responder", t);
333                 }
334                 // The case where this returns null is handled by the caller.
335
if (lzres == null) {
336                     mLogger.error("no matching template responder " +
337                                   "or class named " + className);
338                 }
339             } catch (Throwable JavaDoc e) {
340                 // TODO: [pkang 2003-05-01] if a user-defined handler exists,
341
// use it.
342
mLogger.error("Throwable: ", e);
343                 log("throwable: " + e.getMessage());
344                 throw new ServletException(e);
345             }
346         }
347         return lzres;
348     }
349
350     /**
351      * Check if it's Mac IE.
352      */

353     private boolean isMacIE(HttpServletRequest req)
354     {
355         // TODO: [pkang 2003-01-30] this was only tested on IE 5.2. We need to
356
// test if this works for IE 5 and 5.1.
357
String JavaDoc ua = req.getHeader("User-Agent");
358         return (ua != null &&
359                 ua.indexOf("MSIE") != -1 &&
360                 ua.indexOf("Mac_PowerPC") != -1);
361     }
362
363     /**
364      * @param req @see HttpServletRequest
365      * @param res @see HttpServletResponse
366      */

367     public void doPost (HttpServletRequest req, HttpServletResponse res)
368         throws IOException, ServletException {
369
370         doGet(req, res);
371
372     }
373
374     /**
375      * Send an error message response based on the request type
376      *
377      * @param req
378      * @param res
379      * @param message
380      */

381     private void respondWithInitError(HttpServletRequest req,
382             HttpServletResponse res,
383             String JavaDoc message) {
384
385         log(message);
386         try {
387             String JavaDoc lzt = null;
388             Responder lzres = null;
389             try {
390                 lzt = getLZT(req);
391                 lzres = getResponder(lzt);
392             } catch (Exception JavaDoc e) {
393                 mLogger.error("Exception trying to respond with initialization error", e);
394             }
395             if (lzres != null) {
396                 lzres.respondWithMessage(res, message);
397             } else {
398                 if ("swf".equalsIgnoreCase(lzt)) {
399                     Responder.respondWithMessageSWF(res, "LPS initialization error: " + message);
400                 } else {
401                     Responder.respondWithErrorHTML(res, "LPS initialization error: " + message);
402                 }
403             }
404         } catch (Throwable JavaDoc e){
405             // Nothing we can do now :-(
406
}
407     }
408
409     /**
410      * Send an error message response based on the request type
411      *
412      * @param req
413      * @param res
414      * @param e
415      */

416     private void respondWithInitException(HttpServletRequest req,
417             HttpServletResponse res,
418             Throwable JavaDoc e) {
419
420         StringWriter s = new StringWriter();
421         PrintWriter p = new PrintWriter(s);
422         e.printStackTrace(p);
423         respondWithInitError(req, res, s.toString());
424     }
425
426     /**
427      * Convenience routine to return webapp name
428      */

429     public static String JavaDoc getServletContextName(ServletContext ctxt) {
430
431          String JavaDoc webappPath = LZHttpUtils.getRealPath(ctxt, "/");
432          int index = webappPath.lastIndexOf(File.separator);
433          int length = webappPath.length();
434          if (index == length - 1) {
435              index = webappPath.lastIndexOf(File.separator, index - 1);
436              return webappPath.substring(index + 1, length - 1);
437          }
438  
439          return webappPath.substring(index + 1);
440     }
441
442     /**
443      * Servlet is going away
444      */

445     public void destroy() {
446         ServletContext ctxt = getServletContext();
447         String JavaDoc webappName = getServletContextName(ctxt);
448         mLogger.info("LPS destroyed in context: " + webappName);
449     }
450 }
451
Popular Tags