001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.jsp;
031:
032: import com.caucho.java.LineMap;
033: import com.caucho.loader.DynamicClassLoader;
034: import com.caucho.loader.SimpleLoader;
035: import com.caucho.log.Log;
036: import com.caucho.server.connection.CauchoRequest;
037: import com.caucho.server.connection.CauchoResponse;
038: import com.caucho.server.util.CauchoSystem;
039: import com.caucho.server.webapp.WebApp;
040: import com.caucho.util.L10N;
041: import com.caucho.vfs.Depend;
042: import com.caucho.vfs.Path;
043: import com.caucho.vfs.PersistentDependency;
044:
045: import javax.servlet.*;
046: import javax.servlet.jsp.HttpJspPage;
047: import javax.servlet.jsp.JspFactory;
048: import java.io.IOException;
049: import java.util.ArrayList;
050: import java.util.logging.Level;
051: import java.util.logging.Logger;
052:
053: /**
054: * Manages JSP templates.
055: */
056: public class JspManager extends PageManager {
057: private final static L10N L = new L10N(JspManager.class);
058: private final static Logger log = Logger.getLogger(JspManager.class
059: .getName());
060:
061: private static int _count;
062:
063: private boolean _isXml;
064: private boolean _isLoadTldOnInit;
065: private boolean _precompile = true;
066:
067: public JspManager() {
068: if (JspFactory.getDefaultFactory() == null)
069: JspFactory.setDefaultFactory(new QJspFactory());
070: }
071:
072: /**
073: * Returns true if JSP pages are precompiled.
074: */
075: public boolean getPrecompile() {
076: return _precompile;
077: }
078:
079: /**
080: * Set true if xml is default.
081: */
082: public void setXml(boolean isXml) {
083: _isXml = isXml;
084: }
085:
086: /**
087: * Set true if tld should be loaded on init.
088: */
089: public void setLoadTldOnInit(boolean isLoadOnInit) {
090: _isLoadTldOnInit = isLoadOnInit;
091: }
092:
093: /**
094: * Initialize the manager.
095: */
096: public void init() {
097: if (_isLoadTldOnInit) {
098: try {
099: WebApp app = getWebApp();
100:
101: TldManager tld = TldManager.create(
102: new AppResourceManager(app), app);
103:
104: // must be initialized at startup for <listeners>, e.g. JSF
105: tld.init();
106: } catch (Exception e) {
107: log.log(Level.WARNING, e.toString(), e);
108: }
109: }
110: }
111:
112: /**
113: * Creates a JSP page. The calling servlet will execute the page by
114: * calling the service method.
115: *
116: * @param path path to the JSP file
117: * @param uri the JSP's uri
118: * @param uriPwd the parent of the JSP's uri
119: *
120: * @return the compiled JSP page
121: */
122: Page createGeneratedPage(Path path, String uri, String className,
123: ServletConfig config,
124: ArrayList<PersistentDependency> dependList)
125: throws Exception {
126: return createPage(path, uri, className, config, dependList,
127: true);
128: }
129:
130: /**
131: * Creates a JSP page. The calling servlet will execute the page by
132: * calling the service method.
133: *
134: * @param path path to the JSP file
135: * @param uri the JSP's uri
136: * @param uriPwd the parent of the JSP's uri
137: *
138: * @return the compiled JSP page
139: */
140: Page createPage(Path path, String uri, String className,
141: ServletConfig config,
142: ArrayList<PersistentDependency> dependList)
143: throws Exception {
144: return createPage(path, uri, className, config, dependList,
145: false);
146: }
147:
148: /**
149: * Creates a JSP page. The calling servlet will execute the page by
150: * calling the service method.
151: *
152: * @param path path to the JSP file
153: * @param uri the JSP's uri
154: * @param uriPwd the parent of the JSP's uri
155: *
156: * @return the compiled JSP page
157: */
158: private Page createPage(Path path, String uri, String className,
159: ServletConfig config,
160: ArrayList<PersistentDependency> dependList,
161: boolean isGenerated) throws Exception {
162: Class jspClass = null;
163:
164: Page page = compile(path, uri, className, config, dependList,
165: isGenerated);
166:
167: if (page == null)
168: return null;
169:
170: // need to load class, too
171:
172: //Page page = loadPage(jspClass, parseState.getLineMap(), req);
173: //page = loadPage(page, config, null);
174:
175: boolean alwaysModified = false;
176: if (alwaysModified)
177: page._caucho_setAlwaysModified();
178:
179: return page;
180: }
181:
182: protected void initPageManager() {
183: JspCompiler compiler = new JspCompiler();
184:
185: compiler.setWebApp(_webApp);
186: compiler.setXml(_isXml);
187:
188: try {
189: compiler.init();
190: } catch (Exception e) {
191: throw new RuntimeException(e);
192: }
193: }
194:
195: Page compile(Path path, String uri, String className,
196: ServletConfig config,
197: ArrayList<PersistentDependency> dependList,
198: boolean isGenerated) throws Exception {
199: WebApp app = getWebApp();
200: JspCompiler compiler = new JspCompiler();
201:
202: compiler.setWebApp(_webApp);
203: compiler.setXml(_isXml);
204:
205: Page page = null;
206:
207: try {
208: if (_precompile || _autoCompile)
209: page = preload(className, app.getClassLoader(), app
210: .getAppDir(), config);
211: } catch (Throwable e) {
212: log.log(Level.WARNING, e.toString(), e);
213: }
214:
215: if (page != null) {
216: if (log.isLoggable(Level.FINE))
217: log.fine("loading pre-compiled page for " + uri);
218:
219: return page;
220: }
221:
222: if (path == null || !path.canRead() || path.isDirectory()
223: || !_autoCompile) {
224: return null;
225: }
226:
227: JspCompilerInstance compilerInst = compiler
228: .getCompilerInstance(path, uri, className);
229:
230: compilerInst.setGeneratedSource(isGenerated);
231: compilerInst.addDependList(dependList);
232:
233: page = compilerInst.compile();
234:
235: Path classPath = getClassDir().lookup(
236: className.replace('.', '/') + ".class");
237:
238: loadPage(page, config, null, uri);
239:
240: if (classPath.canRead())
241: page._caucho_addDepend(classPath.createDepend());
242:
243: return page;
244: }
245:
246: void killPage(CauchoRequest request, CauchoResponse response,
247: Page page) {
248: }
249:
250: /**
251: * True if the pre-load would load a valid class.
252: */
253: Page preload(String className, ClassLoader parentLoader,
254: Path appDir, ServletConfig config) throws Exception {
255: DynamicClassLoader loader;
256:
257: String fullClassName = className;
258: String mangledName = fullClassName.replace('.', '/');
259:
260: Path classPath = getClassDir().lookup(mangledName + ".class");
261:
262: /*
263: if (! classPath.exists())
264: return preloadStatic(mangledName);
265: */
266:
267: loader = SimpleLoader.create(parentLoader, getClassDir(), null);
268:
269: Class cl = null;
270:
271: // If the loading fails, remove the class because it may be corrupted
272: try {
273: cl = CauchoSystem.loadClass(fullClassName, false, loader);
274: } catch (ClassNotFoundException e) {
275: log.finest(e.toString());
276:
277: return null;
278: } catch (NoClassDefFoundError e) {
279: log.finest(e.toString());
280:
281: return null;
282: } catch (OutOfMemoryError e) {
283: throw e;
284: } catch (Throwable e) {
285: log.log(Level.FINEST, e.toString(), e);
286:
287: if (_autoCompile) {
288: try {
289: log.warning("removing generated file " + classPath
290: + " due to " + e.toString());
291:
292: classPath.remove();
293: } catch (IOException e1) {
294: log.log(Level.FINE, e1.toString(), e1);
295: }
296: }
297:
298: return null;
299: }
300:
301: HttpJspPage jspPage = (HttpJspPage) cl.newInstance();
302: Page page = null;
303:
304: if (jspPage instanceof CauchoPage) {
305: CauchoPage cPage = (CauchoPage) jspPage;
306:
307: cPage.init(appDir);
308:
309: if (cPage instanceof Page)
310: ((Page) cPage)._caucho_setJspManager(this );
311:
312: if (_autoCompile && cPage._caucho_isModified())
313: return null;
314: else if (cPage instanceof Page)
315: page = (Page) cPage;
316: else
317: page = new WrapperPage(jspPage);
318: } else if (jspPage instanceof SingleThreadModel)
319: page = new SingleThreadWrapperPage((HttpJspPage) jspPage);
320: else
321: page = new WrapperPage(jspPage);
322:
323: page._caucho_addDepend(classPath.createDepend());
324:
325: loadPage(page, config, null, className);
326:
327: return page;
328: }
329:
330: // XXX: disable static pages. The slight memory gain is probably
331: // not worth the separate code paths.
332: private Page preloadStatic(String mangledName) {
333: String staticName = mangledName + ".static";
334: String dependName = mangledName + ".depend";
335:
336: Path staticPath = getClassDir().lookup(staticName);
337:
338: if (!staticPath.canRead())
339: return null;
340:
341: Path dependPath = getClassDir().lookup(dependName);
342:
343: if (!dependPath.canRead())
344: return null;
345:
346: try {
347: ArrayList<Depend> dependList = StaticPage
348: .parseDepend(dependPath);
349:
350: if (dependList == null)
351: return null;
352:
353: StaticPage page = new StaticPage(staticPath, true);
354:
355: for (int i = 0; i < dependList.size(); i++) {
356: Depend depend = dependList.get(i);
357:
358: if (depend.isModified())
359: return null;
360:
361: page._caucho_addDepend(depend);
362: }
363:
364: return page;
365: } catch (Throwable e) {
366: log.log(Level.FINER, e.toString(), e);
367: }
368:
369: return null;
370: }
371:
372: /**
373: * Loads an already-compiled JSP class.
374: *
375: * @param jspClass the class object of the JSP file.
376: * @param lineMap the java to JSP line map.
377: */
378: private Page loadPage(Page page, ServletConfig config,
379: LineMap lineMap, String servletName) throws Exception {
380: page.init(_webApp.getAppDir());
381:
382: page._caucho_setJspManager(this );
383:
384: if (config == null)
385: config = new JspServletConfig(_webApp, null, servletName);
386:
387: page.init(config);
388:
389: return page;
390: }
391:
392: void unload(Page page) {
393: }
394: }
|