KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > jsp > JspCompiler


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.jsp;
31
32 import com.caucho.config.Config;
33 import com.caucho.java.JavaCompiler;
34 import com.caucho.jsp.cfg.JspConfig;
35 import com.caucho.jsp.cfg.JspPropertyGroup;
36 import com.caucho.jsp.cfg.JspTaglib;
37 import com.caucho.loader.CompilingLoader;
38 import com.caucho.loader.DirectoryLoader;
39 import com.caucho.loader.DynamicClassLoader;
40 import com.caucho.loader.EnvironmentBean;
41 import com.caucho.loader.EnvironmentClassLoader;
42 import com.caucho.loader.SimpleLoader;
43 import com.caucho.log.Log;
44 import com.caucho.server.util.CauchoSystem;
45 import com.caucho.server.webapp.WebApp;
46 import com.caucho.server.webapp.WebAppController;
47 import com.caucho.util.L10N;
48 import com.caucho.vfs.Path;
49 import com.caucho.vfs.Vfs;
50
51 import javax.servlet.SingleThreadModel JavaDoc;
52 import javax.servlet.jsp.HttpJspPage JavaDoc;
53 import javax.servlet.jsp.JspPage JavaDoc;
54 import java.io.IOException JavaDoc;
55 import java.io.InputStream JavaDoc;
56 import java.util.ArrayList JavaDoc;
57 import java.util.HashSet JavaDoc;
58 import java.util.logging.Level JavaDoc;
59 import java.util.logging.Logger JavaDoc;
60
61 /**
62  * Compilation interface for JSP pages.
63  */

64 public class JspCompiler implements EnvironmentBean {
65   private static final L10N L = new L10N(JspCompiler.class);
66   private static final Logger JavaDoc log = Log.open(JspCompiler.class);
67
68   private ClassLoader JavaDoc _loader;
69
70   private WebApp _app;
71
72   private Path _classDir;
73   private Path _appDir;
74
75   private JspResourceManager _resourceManager;
76   private TaglibManager _taglibManager;
77   private final TagFileManager _tagFileManager;
78
79   private JspPropertyGroup _jspPropertyGroup;
80
81   private boolean _isXml;
82   private ArrayList JavaDoc<String JavaDoc> _preludeList = new ArrayList JavaDoc<String JavaDoc>();
83   private ArrayList JavaDoc<String JavaDoc> _codaList = new ArrayList JavaDoc<String JavaDoc>();
84
85   private HashSet JavaDoc<String JavaDoc> _compilingTags = new HashSet JavaDoc<String JavaDoc>();
86   private boolean _hasRecursiveCompile;
87
88   private ArrayList JavaDoc<JspCompilerInstance> _pending =
89     new ArrayList JavaDoc<JspCompilerInstance>();
90
91   public JspCompiler()
92   {
93     _loader = new EnvironmentClassLoader();
94
95     _tagFileManager = new TagFileManager(this);
96   }
97
98   /**
99    * Returns the classloader for configuration.
100    */

101   public ClassLoader JavaDoc getClassLoader()
102   {
103     return _loader;
104   }
105
106   /**
107    * Sets the destination class directory.
108    */

109   public void setClassDir(Path path)
110   {
111     _classDir = path;
112   }
113
114   /**
115    * Sets the destination class directory.
116    */

117   public void setClassDirectory(Path path)
118   {
119     setClassDir(path);
120   }
121
122   /**
123    * Gets the destination class directory.
124    */

125   public Path getClassDir()
126   {
127     if (_classDir != null)
128       return _classDir;
129     else
130       return CauchoSystem.getWorkPath();
131   }
132
133   /**
134    * Sets the source webApp directory.
135    */

136   public void setAppDir(Path path)
137   {
138     _appDir = path;
139   }
140
141   /**
142    * Gets the source webApp directory.
143    */

144   public Path getAppDir()
145   {
146     if (_appDir != null)
147       return _appDir;
148     else if (_app != null)
149       return _app.getAppDir();
150     else
151       return null;
152   }
153
154   /**
155    * Adds a prelude include.
156    */

157   public void addPrelude(String JavaDoc prelude)
158   {
159     _preludeList.add(prelude);
160   }
161
162   /**
163    * Adds a coda include.
164    */

165   public void addCoda(String JavaDoc coda)
166   {
167     _codaList.add(coda);
168   }
169
170   /**
171    * Set true when XML is the default parser.
172    */

173   public void setXml(boolean isXml)
174   {
175     _isXml = isXml;
176   }
177
178   /**
179    * True when XML is the default parser.
180    */

181   public boolean isXml()
182   {
183     return _isXml;
184   }
185
186   /**
187    * Sets the resource manager.
188    */

189   public void setResourceManager(JspResourceManager manager)
190   {
191     _resourceManager = manager;
192   }
193
194   /**
195    * Gets the resource manager.
196    */

197   public JspResourceManager getResourceManager()
198   {
199     return _resourceManager;
200   }
201
202   /**
203    * Gets the tag file manager.
204    */

205   public TagFileManager getTagFileManager()
206   {
207     return _tagFileManager;
208   }
209
210   public TaglibManager getTaglibManager()
211     throws JspParseException, IOException JavaDoc
212   {
213     synchronized (this) {
214       if (_taglibManager == null) {
215     WebApp app = getWebApp();
216     
217     Path appDir = getAppDir();
218     if (appDir == null && app != null)
219       appDir = app.getAppDir();
220
221     JspResourceManager resourceManager = getResourceManager();
222     if (resourceManager != null) {
223     }
224     else if (app != null)
225       resourceManager = new AppResourceManager(app);
226     else {
227       resourceManager = new AppDirResourceManager(appDir);
228     }
229     
230     _taglibManager = new TaglibManager(resourceManager,
231                        app,
232                        _tagFileManager);
233     _taglibManager.setWebApp(app);
234
235     JspConfig jspConfig = null;
236
237     if (app != null)
238       jspConfig = (JspConfig) app.getExtension("jsp-config");
239
240     if (jspConfig != null) {
241       ArrayList JavaDoc<JspTaglib> tldMapList = jspConfig.getTaglibList();
242       for (int i = 0; i < tldMapList.size(); i++) {
243         JspTaglib taglib = tldMapList.get(i);
244
245         _taglibManager.addLocationMap(taglib.getTaglibUri(),
246                       taglib.getTaglibLocation());
247       }
248     }
249
250     if (app != null) {
251       ArrayList JavaDoc<JspTaglib> taglibs = app.getTaglibList();
252       for (int i = 0; taglibs != null && i < taglibs.size(); i++) {
253         JspTaglib taglib = taglibs.get(i);
254
255         _taglibManager.addLocationMap(taglib.getTaglibUri(),
256                       taglib.getTaglibLocation());
257       }
258     }
259       }
260     }
261
262     return _taglibManager;
263   }
264
265   /**
266    * Sets the JspPropertyGroup
267    */

268   public JspPropertyGroup createJsp()
269   {
270     if (_jspPropertyGroup == null) {
271       _jspPropertyGroup = new JspPropertyGroup();
272     }
273
274     return _jspPropertyGroup;
275   }
276
277   /**
278    * Sets the JspPropertyGroup
279    */

280   public JspPropertyGroup getJspPropertyGroup()
281   {
282     return _jspPropertyGroup;
283   }
284
285   /**
286    * Initialize values based on the ServletContext. When the calling code
287    * has the ServletContext available, it can take advantage of it.
288    */

289   public WebApp createWebApp()
290   {
291     if (_app == null) {
292       WebAppController controller =
293     new WebAppController("", getAppDir(), null);
294
295       _app = controller.getDeployInstance();
296     }
297
298     return _app;
299   }
300
301   /**
302    * Initialize values based on the ServletContext. When the calling code
303    * has the ServletContext available, it can take advantage of it.
304    */

305   public void setWebApp(WebApp app)
306   {
307     _app = app;
308
309     if (_resourceManager == null)
310       _resourceManager = new AppResourceManager(_app);
311   }
312
313   /**
314    * Initialize values based on the ServletContext. When the calling code
315    * has the ServletContext available, it can take advantage of it.
316    */

317   public WebApp createApplication()
318   {
319     return createWebApp();
320   }
321
322   /**
323    * Initialize values based on the ServletContext. When the calling code
324    * has the ServletContext available, it can take advantage of it.
325    */

326   public void setApplication(WebApp webApp)
327   {
328     setWebApp(webApp);
329   }
330
331   /**
332    * Returns the app.
333    */

334   public WebApp getWebApp()
335   {
336     return _app;
337   }
338
339   /**
340    * Adds a new tag being compiled.
341    */

342   public boolean addTag(String JavaDoc className)
343   {
344     if (_compilingTags.contains(className)) {
345       _hasRecursiveCompile = true;
346       return true;
347     }
348
349     _compilingTags.add(className);
350
351     return false;
352   }
353
354   /**
355    * Has recursive compile.
356    */

357   public boolean hasRecursiveCompile()
358   {
359     return _hasRecursiveCompile;
360   }
361
362   /**
363    * Mangles the name.
364    */

365   public static String JavaDoc urlToClassName(String JavaDoc name)
366   {
367     return JavaCompiler.mangleName("jsp/" + name);
368   }
369
370   /**
371    * Adds a pending compilation.
372    */

373   void addPending(JspCompilerInstance pending)
374   {
375     _pending.add(pending);
376   }
377
378   /**
379    * Compiles pending compilations.
380    */

381   void compilePending()
382     throws Exception JavaDoc
383   {
384     if (_pending.size() == 0)
385       return;
386
387     ArrayList JavaDoc<JspCompilerInstance> pendingList;
388     pendingList = new ArrayList JavaDoc<JspCompilerInstance>(_pending);
389
390     for (int i = 0; i < pendingList.size(); i++) {
391       JspCompilerInstance pending = pendingList.get(i);
392
393       pending.completeTag();
394     }
395
396     _pending.clear();
397   }
398
399   /**
400    * Compiles the JSP file specified with jspFile.
401    *
402    * @param jspPath the path to the JSP source
403    * @param uri the uri for the JSP file
404    *
405    * @return a JspPage instance
406    */

407   public Page compile(Path jspPath, String JavaDoc uri)
408     throws Exception JavaDoc
409   {
410     return getCompilerInstance(jspPath, uri).compile();
411   }
412
413   /**
414    * Returns the compilation instance.
415    */

416   public JspCompilerInstance getCompilerInstance(Path jspPath,
417                          String JavaDoc uri)
418     throws Exception JavaDoc
419   {
420     return getCompilerInstance(jspPath, uri, null);
421   }
422
423   public void init()
424     throws JspParseException, IOException JavaDoc
425   {
426     getTaglibManager();
427   }
428   
429   /**
430    * Returns the compilation instance.
431    */

432   public JspCompilerInstance getCompilerInstance(Path jspPath,
433                          String JavaDoc uri,
434                          String JavaDoc className)
435     throws Exception JavaDoc
436   {
437     JspCompilerInstance instance = new JspCompilerInstance(this);
438
439     instance.setJspPath(jspPath);
440     instance.setURI(uri);
441     instance.setClassName(className);
442
443     instance.init();
444
445     return instance;
446   }
447   
448   /**
449    * Loads an already-compiled JSP class.
450    *
451    * @param className the mangled classname for the JSP file.
452    */

453   public Page loadPage(String JavaDoc className, boolean isAutoCompile)
454     throws Throwable JavaDoc
455   {
456     JspPage JavaDoc jspPage = (JspPage JavaDoc) loadClass(className, isAutoCompile);
457
458     Page page;
459     if (jspPage instanceof Page)
460       page = (Page) jspPage;
461     else if (jspPage instanceof SingleThreadModel JavaDoc)
462       page = new SingleThreadWrapperPage((HttpJspPage JavaDoc) jspPage);
463     else
464       page = new WrapperPage((HttpJspPage JavaDoc) jspPage);
465
466     return page;
467   }
468
469   /**
470    * Loads an already-compiled JSP class.
471    *
472    * @param className the mangled classname for the JSP file.
473    */

474   public Object JavaDoc loadClass(String JavaDoc className, boolean autoCompile)
475     throws Throwable JavaDoc
476   {
477     ClassLoader JavaDoc parentLoader = Thread.currentThread().getContextClassLoader();
478     ClassLoader JavaDoc jspLoader = SimpleLoader.create(parentLoader,
479                                                 getClassDir(), null);
480
481     // If the loading fails, remove the class because it may be corrupted
482
try {
483       Class JavaDoc cl = CauchoSystem.loadClass(className, false, jspLoader);
484
485       readSmap(parentLoader, className);
486
487       return cl.newInstance();
488     } catch (Throwable JavaDoc e) {
489       if (autoCompile) {
490         try {
491           String JavaDoc pathName = className.replace('.', '/') + ".class";
492           Path classPath = getClassDir().lookup(pathName);
493
494           classPath.remove();
495         } catch (IOException JavaDoc e1) {
496           log.log(Level.FINE, e1.toString(), e1);
497         }
498       }
499
500       throw e;
501     }
502   }
503
504   /**
505    * Loads an already-compiled JSP class.
506    *
507    * @param className the mangled classname for the JSP file.
508    */

509   public Page loadStatic(String JavaDoc className, boolean isSession)
510     throws Exception JavaDoc
511   {
512     ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
513
514     // If the loading fails, remove the class because it may be corrupted
515
String JavaDoc staticName = className.replace('.', '/') + ".static";
516
517     Path path = getClassDir().lookup(staticName);
518
519     return new StaticPage(path, isSession);
520   }
521
522   private void readSmap(ClassLoader JavaDoc loader, String JavaDoc className)
523   {
524     if (loader == null)
525       return;
526
527     String JavaDoc smapName = className.replace('.', '/') + ".java.smap";
528
529     InputStream JavaDoc is = null;
530     try {
531       is = loader.getResourceAsStream(smapName);
532     } catch (Exception JavaDoc e) {
533       log.log(Level.FINE, e.toString(), e);
534     } finally {
535       if (is != null) {
536         try {
537           is.close();
538         } catch (IOException JavaDoc e) {
539         }
540       }
541     }
542   }
543
544   public static void main(String JavaDoc []args)
545     throws Exception JavaDoc
546   {
547     if (args.length == 0) {
548       System.out.println("usage: com.caucho.jsp.JspCompiler [flags] jsp1 jsp2 ...");
549       System.out.println(" -app-dir : The directory root of the web-app.");
550       System.out.println(" -class-dir: The working directory to use as output.");
551       System.out.println(" -conf: A configuration file for the compiler.");
552       System.exit(1);
553     }
554
555     // needed at minimum to handle the qa jsp/1933
556
Thread JavaDoc thread = Thread.currentThread();
557     ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
558     try {
559       JspCompiler compiler = new JspCompiler();
560
561       ClassLoader JavaDoc loader = compiler.getClassLoader();
562
563       thread.setContextClassLoader(loader);
564
565       JspPropertyGroup jsp = compiler.createJsp();
566       jsp.setRequireSource(false);
567
568       int i = 0;
569       boolean hasConf = false;
570
571       while (i < args.length) {
572     if (args[i].equals("-app-dir")) {
573       Path appDir = Vfs.lookup(args[i + 1]);
574
575       WebApp app = compiler.createWebApp();
576       app.setDocumentDirectory(appDir);
577
578       compiler.setWebApp(app);
579       compiler.setAppDir(appDir);
580
581       i += 2;
582     }
583     else if (args[i].equals("-class-dir") || args[i].equals("-d")) {
584       compiler.setClassDirectory(Vfs.lookup(args[i + 1]));
585       i += 2;
586     }
587     else if (args[i].equals("-conf")) {
588       Path path = Vfs.lookup(args[i + 1]);
589
590       new Config().configureBean(compiler, path);
591       hasConf = true;
592
593       i += 2;
594     }
595     else
596       break;
597       }
598
599       WebApp app = compiler.getWebApp();
600       if (app != null && ! hasConf) {
601     Path appDir = app.getAppDir();
602
603     DynamicClassLoader dynLoader = app.getEnvironmentClassLoader();
604     dynLoader.addLoader(new CompilingLoader(appDir.lookup("WEB-INF/classes")));
605     dynLoader.addLoader(new DirectoryLoader(appDir.lookup("WEB-INF/lib")));
606
607     Path webXml = appDir.lookup("WEB-INF/web.xml");
608
609     if (webXml.canRead()) {
610       try {
611         new Config().configureBean(app, webXml);
612       } catch (Exception JavaDoc e) {
613         log.log(Level.WARNING, e.toString(), e);
614       }
615     }
616       }
617
618       Path appDir = null;
619
620       if (app == null && compiler.getAppDir() != null) {
621     app = compiler.createWebApp();
622
623     app.setDocumentDirectory(compiler.getAppDir());
624     compiler.setWebApp(app);
625       }
626
627       if (app != null) {
628     app.init();
629
630     appDir = compiler.getWebApp().getAppDir();
631     loader = compiler.getWebApp().getClassLoader();
632       }
633
634       if (appDir == null) {
635     appDir = Vfs.lookup();
636
637     if (compiler.getAppDir() == null && compiler.getWebApp() == null) {
638       System.err.println(L.l("-app-dir must be specified for JspCompiler"));
639       return;
640     }
641       }
642
643       thread.setContextClassLoader(loader);
644
645       ArrayList JavaDoc<String JavaDoc> pendingClasses = new ArrayList JavaDoc<String JavaDoc>();
646
647       for (; i < args.length; i++) {
648     String JavaDoc uri = args[i];
649
650     Path path = Vfs.lookup(uri);
651
652     if (path.isDirectory())
653       compileDirectory(path, appDir, compiler, pendingClasses);
654     else
655       compileJsp(path, appDir, compiler, pendingClasses);
656       }
657
658       JavaCompiler javaCompiler = JavaCompiler.create(loader);
659       javaCompiler.setClassDir(compiler.getClassDir());
660
661       String JavaDoc files[] = new String JavaDoc[pendingClasses.size()];
662       pendingClasses.toArray(files);
663
664       javaCompiler.compileBatch(files);
665     } finally {
666       Thread.currentThread().setContextClassLoader(oldLoader);
667     }
668   }
669
670   private static void compileDirectory(Path path,
671                        Path appDir,
672                        JspCompiler compiler,
673                        ArrayList JavaDoc<String JavaDoc> pendingClasses)
674     throws Exception JavaDoc
675   {
676     if (path.isDirectory()) {
677       String JavaDoc []list = path.list();
678
679       for (int i = 0; i < list.length; i++) {
680     Path subpath = path.lookup(list[i]);
681
682     compileDirectory(subpath, appDir, compiler, pendingClasses);
683       }
684     }
685     else if (path.getPath().endsWith(".jsp") ||
686          path.getPath().endsWith(".jsfx") ||
687          path.getPath().endsWith(".jspx") ||
688          path.getPath().endsWith(".jsfx")) {
689       compileJsp(path, appDir, compiler, pendingClasses);
690     }
691   }
692
693   private static void compileJsp(Path path,
694                  Path appDir,
695                  JspCompiler compiler,
696                  ArrayList JavaDoc<String JavaDoc> pendingClasses)
697     throws Exception JavaDoc
698   {
699     String JavaDoc uri;
700
701     uri = path.getPath().substring(appDir.getPath().length());
702
703
704     if (uri.endsWith("x"))
705       compiler.setXml(true);
706     else
707       compiler.setXml(false);
708     
709     String JavaDoc className = JspCompiler.urlToClassName(uri);
710     JspCompilerInstance compInst;
711     compInst = compiler.getCompilerInstance(path, uri, className);
712     
713     JspGenerator gen = compInst.generate();
714
715     if (! gen.isStatic())
716       pendingClasses.add(className.replace('.', '/') + ".java");
717   }
718 }
719
Popular Tags