KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > kawa > servlet > KawaPageServlet


1 // Copyright (c) 2003 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.kawa.servlet;
5
6 import gnu.expr.*;
7 import gnu.mapping.*;
8 import gnu.text.*;
9 import java.io.*;
10 import java.net.*;
11 import java.util.*;
12 import javax.servlet.*;
13 import javax.servlet.http.*;
14
15 /**
16  * The Kawa servlet interpreter
17  *
18  * This servlet is responsible for reading and interpeting Kawa language files
19  * using the QEXO GNU library.
20  *
21  * The implementation borrows ideas from Apache Jakarta Tomcat Jasper.
22  *
23  * @author Ivelin Ivanov
24  * @author Tom Reilly
25  * @author Per Bothner
26  */

27 public class KawaPageServlet extends KawaServlet
28 {
29   private ServletContext context;
30
31   public void init(ServletConfig config)
32       throws ServletException
33   {
34     super.init(config);
35     context = config.getServletContext();
36   }
37
38   public void run(CallContext ccontext) throws Throwable JavaDoc
39   {
40     ServletCallContext ctx = (ServletCallContext) ccontext;
41     HttpServletRequest request = ctx.request;
42     HttpServletResponse response = ctx.response;
43
44     boolean saveClass = request.getParameter("qexo-save-class") != null;
45     String JavaDoc path = request.getServletPath();
46     Object JavaDoc mod = getModule(ctx, path, saveClass, response);
47
48     if (mod instanceof ModuleBody)
49       ((ModuleBody) mod).run(ctx);
50   }
51
52   private static final String JavaDoc MODULE_MAP_ATTRIBUTE = "gnu.kawa.module-map";
53
54   private Object JavaDoc getModule(ServletCallContext ctx, String JavaDoc path, boolean saveClass, HttpServletResponse response)
55     throws Exception JavaDoc
56   {
57     Hashtable mmap
58       = (Hashtable) context.getAttribute(MODULE_MAP_ATTRIBUTE);
59     if (mmap == null)
60       {
61         mmap = new Hashtable();
62         context.setAttribute(MODULE_MAP_ATTRIBUTE, mmap);
63       }
64     ModuleContext mcontext
65       = (ModuleContext) context.getAttribute("gnu.kawa.module-context");
66     if (mcontext == null)
67       mcontext = ModuleContext.getContext();
68     ModuleInfo minfo = (ModuleInfo) mmap.get(path);
69     long now = System.currentTimeMillis();
70     ModuleManager mmanager = mcontext.getManager();
71
72     // avoid hitting the disk too much
73
if (minfo != null
74         && now - minfo.lastCheckedTime < mmanager.lastModifiedCacheTime)
75       return mcontext.findInstance(minfo);
76
77     URL url = context.getResource(path);
78     String JavaDoc upath = path;
79     if (url == null)
80       {
81         String JavaDoc xpath = path;
82         for (;;)
83           {
84             int sl = xpath.lastIndexOf('/');
85             if (sl < 0)
86               {
87                 ctx.response.reset();
88                 ctx.response.sendError(HttpServletResponse.SC_NOT_FOUND, path);
89                 return null;
90               }
91             xpath = xpath.substring(0, sl);
92             upath = xpath + "/+default+";
93             url = context.getResource(upath);
94             if (url != null)
95               break;
96           }
97       }
98
99     if (url == null)
100       {
101     ctx.response.reset();
102     ctx.response.sendError(HttpServletResponse.SC_NOT_FOUND, path);
103     return null;
104       }
105
106     URLConnection connection = url.openConnection();
107     String JavaDoc urlString = url.toExternalForm();
108     long lastModified = connection.getLastModified();
109     if (minfo != null
110         && minfo.lastModifiedTime == lastModified
111         && urlString.equals(minfo.sourceAbsPath))
112       {
113         minfo.lastCheckedTime = now;
114         return mcontext.findInstance(minfo);
115       }
116
117     minfo = mmanager.findWithURL(url);
118     minfo.lastModifiedTime = lastModified;
119     minfo.lastCheckedTime = now;
120     mmap.put(path, minfo);
121
122     InputStream resourceStream = connection.getInputStream();
123             
124     Language language
125       = Language.getInstanceFromFilenameExtension(path);
126     if (language == null)
127       language = Language.detect(resourceStream);
128     if (language == null)
129       {
130         if (path != upath)
131           {
132             ctx.response.reset();
133             ctx.response.sendError(HttpServletResponse.SC_NOT_FOUND, path);
134             return null;
135           }
136         String JavaDoc contentType = context.getMimeType(path);
137         response.setContentType(contentType);
138         ServletOutputStream out = response.getOutputStream();
139         byte[] buffer = new byte[4*1024];
140         for (;;)
141           {
142             int n = resourceStream.read(buffer);
143             if (n < 0)
144               break;
145             out.write(buffer, 0, n);
146           }
147         resourceStream.close();
148         return null;
149       }
150     InPort port = new InPort(resourceStream,
151                              path.substring(path.lastIndexOf('/')+1));
152     Language.setDefaultLanguage(language);
153     SourceMessages messages = new SourceMessages();
154     Compilation comp;
155     try
156       {
157         comp = language.parse(port, messages, Language.PARSE_IMMEDIATE);
158         int dot = path.indexOf('.');
159         if (dot < 0)
160           dot = path.length();
161         String JavaDoc name = path.substring(path.lastIndexOf('/')+1, dot);
162         comp.getModule().setName(name);
163         language.resolve(comp);
164       }
165     catch (SyntaxException ex)
166       {
167         if (ex.getMessages() != messages)
168           throw ex;
169         // Otherwise handled below ...
170
comp = null; // Needed to avoid spurious compilation error.
171
}
172
173     Class JavaDoc cl = null;
174     if (! messages.seenErrors())
175       {
176         ModuleExp mexp = comp.getModule();
177         comp.addMainClass(mexp);
178         comp.walkModule(mexp);
179         comp.setState(Compilation.WALKED);
180         cl = ModuleExp.evalToClass(comp, url);
181       }
182
183     // FIXME: we could output a nice pretty HTML table of the errors
184
// or show the script with the errors highlighted, for bonus
185
// points the pretty page could be generated by a precompiled
186
// xql script with the errors passed as XML somehow and accessed
187
// via input()
188
if (messages.seenErrors())
189       {
190         ctx.response.reset();
191         ServletOutputStream out = ctx.response.getOutputStream();
192         out.print(messages.toString(20));
193         return null;
194       }
195
196     minfo.moduleClass = cl;
197     minfo.className = cl.getName();
198
199     if (saveClass)
200       comp.outputClass(context.getRealPath("WEB-INF/classes")+'/');
201
202     return mcontext.findInstance(minfo);
203   }
204 }
205
206
Popular Tags