KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jasper > JspCompilationContext


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.jasper;
19
20 import java.io.File JavaDoc;
21 import java.io.FileNotFoundException JavaDoc;
22 import java.net.MalformedURLException JavaDoc;
23 import java.net.URL JavaDoc;
24 import java.net.URLClassLoader JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.Set JavaDoc;
28
29 import javax.servlet.ServletContext JavaDoc;
30 import javax.servlet.jsp.tagext.TagInfo JavaDoc;
31
32 import org.apache.jasper.compiler.Compiler;
33 import org.apache.jasper.compiler.JspRuntimeContext;
34 import org.apache.jasper.compiler.JspUtil;
35 import org.apache.jasper.compiler.Localizer;
36 import org.apache.jasper.compiler.ServletWriter;
37 import org.apache.jasper.servlet.JasperLoader;
38 import org.apache.jasper.servlet.JspServletWrapper;
39
40 /**
41  * A place holder for various things that are used through out the JSP
42  * engine. This is a per-request/per-context data structure. Some of
43  * the instance variables are set at different points.
44  *
45  * Most of the path-related stuff is here - mangling names, versions, dirs,
46  * loading resources and dealing with uris.
47  *
48  * @author Anil K. Vijendran
49  * @author Harish Prabandham
50  * @author Pierre Delisle
51  * @author Costin Manolache
52  * @author Kin-man Chung
53  */

54 public class JspCompilationContext {
55
56     protected org.apache.commons.logging.Log log =
57         org.apache.commons.logging.LogFactory.getLog(JspCompilationContext.class);
58
59     protected Map JavaDoc<String JavaDoc, URL JavaDoc> tagFileJarUrls;
60     protected boolean isPackagedTagFile;
61
62     protected String JavaDoc className;
63     protected String JavaDoc jspUri;
64     protected boolean isErrPage;
65     protected String JavaDoc basePackageName;
66     protected String JavaDoc derivedPackageName;
67     protected String JavaDoc servletJavaFileName;
68     protected String JavaDoc javaPath;
69     protected String JavaDoc classFileName;
70     protected String JavaDoc contentType;
71     protected ServletWriter writer;
72     protected Options options;
73     protected JspServletWrapper jsw;
74     protected Compiler JavaDoc jspCompiler;
75     protected String JavaDoc classPath;
76
77     protected String JavaDoc baseURI;
78     protected String JavaDoc outputDir;
79     protected ServletContext JavaDoc context;
80     protected URLClassLoader JavaDoc loader;
81
82     protected JspRuntimeContext rctxt;
83
84     protected int removed = 0;
85
86     protected URLClassLoader JavaDoc jspLoader;
87     protected URL JavaDoc baseUrl;
88     protected Class JavaDoc servletClass;
89
90     protected boolean isTagFile;
91     protected boolean protoTypeMode;
92     protected TagInfo JavaDoc tagInfo;
93     protected URL JavaDoc tagFileJarUrl;
94
95     // jspURI _must_ be relative to the context
96
public JspCompilationContext(String JavaDoc jspUri,
97                                  boolean isErrPage,
98                                  Options options,
99                                  ServletContext JavaDoc context,
100                                  JspServletWrapper jsw,
101                                  JspRuntimeContext rctxt) {
102
103         this.jspUri = canonicalURI(jspUri);
104         this.isErrPage = isErrPage;
105         this.options = options;
106         this.jsw = jsw;
107         this.context = context;
108
109         this.baseURI = jspUri.substring(0, jspUri.lastIndexOf('/') + 1);
110         // hack fix for resolveRelativeURI
111
if (baseURI == null) {
112             baseURI = "/";
113         } else if (baseURI.charAt(0) != '/') {
114             // strip the basde slash since it will be combined with the
115
// uriBase to generate a file
116
baseURI = "/" + baseURI;
117         }
118         if (baseURI.charAt(baseURI.length() - 1) != '/') {
119             baseURI += '/';
120         }
121
122         this.rctxt = rctxt;
123         this.tagFileJarUrls = new HashMap JavaDoc<String JavaDoc, URL JavaDoc>();
124         this.basePackageName = Constants.JSP_PACKAGE_NAME;
125     }
126
127     public JspCompilationContext(String JavaDoc tagfile,
128                                  TagInfo JavaDoc tagInfo,
129                                  Options options,
130                                  ServletContext JavaDoc context,
131                                  JspServletWrapper jsw,
132                                  JspRuntimeContext rctxt,
133                                  URL JavaDoc tagFileJarUrl) {
134         this(tagfile, false, options, context, jsw, rctxt);
135         this.isTagFile = true;
136         this.tagInfo = tagInfo;
137         this.tagFileJarUrl = tagFileJarUrl;
138         if (tagFileJarUrl != null) {
139             isPackagedTagFile = true;
140         }
141     }
142
143     /* ==================== Methods to override ==================== */
144     
145     /** ---------- Class path and loader ---------- */
146
147     /**
148      * The classpath that is passed off to the Java compiler.
149      */

150     public String JavaDoc getClassPath() {
151         if( classPath != null )
152             return classPath;
153         return rctxt.getClassPath();
154     }
155
156     /**
157      * The classpath that is passed off to the Java compiler.
158      */

159     public void setClassPath(String JavaDoc classPath) {
160         this.classPath = classPath;
161     }
162
163     /**
164      * What class loader to use for loading classes while compiling
165      * this JSP?
166      */

167     public ClassLoader JavaDoc getClassLoader() {
168         if( loader != null )
169             return loader;
170         return rctxt.getParentClassLoader();
171     }
172
173     public void setClassLoader(URLClassLoader JavaDoc loader) {
174         this.loader = loader;
175     }
176
177     public ClassLoader JavaDoc getJspLoader() {
178         if( jspLoader == null ) {
179             jspLoader = new JasperLoader
180             (new URL JavaDoc[] {baseUrl},
181                     getClassLoader(),
182                     rctxt.getPermissionCollection(),
183                     rctxt.getCodeSource());
184         }
185         return jspLoader;
186     }
187
188     /** ---------- Input/Output ---------- */
189     
190     /**
191      * The output directory to generate code into. The output directory
192      * is make up of the scratch directory, which is provide in Options,
193      * plus the directory derived from the package name.
194      */

195     public String JavaDoc getOutputDir() {
196     if (outputDir == null) {
197         createOutputDir();
198     }
199
200         return outputDir;
201     }
202
203     /**
204      * Create a "Compiler" object based on some init param data. This
205      * is not done yet. Right now we're just hardcoding the actual
206      * compilers that are created.
207      */

208     public Compiler JavaDoc createCompiler() throws JasperException {
209         if (jspCompiler != null ) {
210             return jspCompiler;
211         }
212         jspCompiler = null;
213         if (options.getCompilerClassName() != null) {
214             jspCompiler = createCompiler(options.getCompilerClassName());
215         } else {
216             if (options.getCompiler() == null) {
217                 jspCompiler = createCompiler("org.apache.jasper.compiler.JDTCompiler");
218                 if (jspCompiler == null) {
219                     jspCompiler = createCompiler("org.apache.jasper.compiler.AntCompiler");
220                 }
221             } else {
222                 jspCompiler = createCompiler("org.apache.jasper.compiler.AntCompiler");
223                 if (jspCompiler == null) {
224                     jspCompiler = createCompiler("org.apache.jasper.compiler.JDTCompiler");
225                 }
226             }
227         }
228         if (jspCompiler == null) {
229             throw new IllegalStateException JavaDoc(Localizer.getMessage("jsp.error.compiler"));
230         }
231         jspCompiler.init(this, jsw);
232         return jspCompiler;
233     }
234
235     protected Compiler JavaDoc createCompiler(String JavaDoc className) {
236         Compiler JavaDoc compiler = null;
237         try {
238             compiler = (Compiler JavaDoc) Class.forName(className).newInstance();
239         } catch (InstantiationException JavaDoc e) {
240             log.warn(Localizer.getMessage("jsp.error.compiler"), e);
241         } catch (IllegalAccessException JavaDoc e) {
242             log.warn(Localizer.getMessage("jsp.error.compiler"), e);
243         } catch (NoClassDefFoundError JavaDoc e) {
244             if (log.isDebugEnabled()) {
245                 log.debug(Localizer.getMessage("jsp.error.compiler"), e);
246             }
247         } catch (ClassNotFoundException JavaDoc e) {
248             if (log.isDebugEnabled()) {
249                 log.debug(Localizer.getMessage("jsp.error.compiler"), e);
250             }
251         }
252         return compiler;
253     }
254     
255     public Compiler JavaDoc getCompiler() {
256         return jspCompiler;
257     }
258
259     /** ---------- Access resources in the webapp ---------- */
260
261     /**
262      * Get the full value of a URI relative to this compilations context
263      * uses current file as the base.
264      */

265     public String JavaDoc resolveRelativeUri(String JavaDoc uri) {
266         // sometimes we get uri's massaged from File(String), so check for
267
// a root directory deperator char
268
if (uri.startsWith("/") || uri.startsWith(File.separator)) {
269             return uri;
270         } else {
271             return baseURI + uri;
272         }
273     }
274
275     /**
276      * Gets a resource as a stream, relative to the meanings of this
277      * context's implementation.
278      * @return a null if the resource cannot be found or represented
279      * as an InputStream.
280      */

281     public java.io.InputStream JavaDoc getResourceAsStream(String JavaDoc res) {
282         return context.getResourceAsStream(canonicalURI(res));
283     }
284
285
286     public URL JavaDoc getResource(String JavaDoc res) throws MalformedURLException JavaDoc {
287         return context.getResource(canonicalURI(res));
288     }
289
290     public Set JavaDoc getResourcePaths(String JavaDoc path) {
291         return context.getResourcePaths(canonicalURI(path));
292     }
293
294     /**
295      * Gets the actual path of a URI relative to the context of
296      * the compilation.
297      */

298     public String JavaDoc getRealPath(String JavaDoc path) {
299         if (context != null) {
300             return context.getRealPath(path);
301         }
302         return path;
303     }
304
305     /**
306      * Returns the tag-file-name-to-JAR-file map of this compilation unit,
307      * which maps tag file names to the JAR files in which the tag files are
308      * packaged.
309      *
310      * The map is populated when parsing the tag-file elements of the TLDs
311      * of any imported taglibs.
312      */

313     public URL JavaDoc getTagFileJarUrl(String JavaDoc tagFile) {
314         return this.tagFileJarUrls.get(tagFile);
315     }
316
317     public void setTagFileJarUrl(String JavaDoc tagFile, URL JavaDoc tagFileURL) {
318         this.tagFileJarUrls.put(tagFile, tagFileURL);
319     }
320
321     /**
322      * Returns the JAR file in which the tag file for which this
323      * JspCompilationContext was created is packaged, or null if this
324      * JspCompilationContext does not correspond to a tag file, or if the
325      * corresponding tag file is not packaged in a JAR.
326      */

327     public URL JavaDoc getTagFileJarUrl() {
328         return this.tagFileJarUrl;
329     }
330
331     /* ==================== Common implementation ==================== */
332
333     /**
334      * Just the class name (does not include package name) of the
335      * generated class.
336      */

337     public String JavaDoc getServletClassName() {
338
339         if (className != null) {
340             return className;
341         }
342
343         if (isTagFile) {
344             className = tagInfo.getTagClassName();
345             int lastIndex = className.lastIndexOf('.');
346             if (lastIndex != -1) {
347                 className = className.substring(lastIndex + 1);
348             }
349         } else {
350             int iSep = jspUri.lastIndexOf('/') + 1;
351             className = JspUtil.makeJavaIdentifier(jspUri.substring(iSep));
352         }
353         return className;
354     }
355
356     public void setServletClassName(String JavaDoc className) {
357         this.className = className;
358     }
359     
360     /**
361      * Path of the JSP URI. Note that this is not a file name. This is
362      * the context rooted URI of the JSP file.
363      */

364     public String JavaDoc getJspFile() {
365         return jspUri;
366     }
367
368     /**
369      * Are we processing something that has been declared as an
370      * errorpage?
371      */

372     public boolean isErrorPage() {
373         return isErrPage;
374     }
375
376     public void setErrorPage(boolean isErrPage) {
377         this.isErrPage = isErrPage;
378     }
379
380     public boolean isTagFile() {
381         return isTagFile;
382     }
383
384     public TagInfo JavaDoc getTagInfo() {
385         return tagInfo;
386     }
387
388     public void setTagInfo(TagInfo JavaDoc tagi) {
389         tagInfo = tagi;
390     }
391
392     /**
393      * True if we are compiling a tag file in prototype mode.
394      * ie we only generate codes with class for the tag handler with empty
395      * method bodies.
396      */

397     public boolean isPrototypeMode() {
398         return protoTypeMode;
399     }
400
401     public void setPrototypeMode(boolean pm) {
402         protoTypeMode = pm;
403     }
404
405     /**
406      * Package name for the generated class is make up of the base package
407      * name, which is user settable, and the derived package name. The
408      * derived package name directly mirrors the file heirachy of the JSP page.
409      */

410     public String JavaDoc getServletPackageName() {
411         if (isTagFile()) {
412             String JavaDoc className = tagInfo.getTagClassName();
413             int lastIndex = className.lastIndexOf('.');
414             String JavaDoc pkgName = "";
415             if (lastIndex != -1) {
416                 pkgName = className.substring(0, lastIndex);
417             }
418             return pkgName;
419         } else {
420             String JavaDoc dPackageName = getDerivedPackageName();
421             if (dPackageName.length() == 0) {
422                 return basePackageName;
423             }
424             return basePackageName + '.' + getDerivedPackageName();
425         }
426     }
427
428     protected String JavaDoc getDerivedPackageName() {
429         if (derivedPackageName == null) {
430             int iSep = jspUri.lastIndexOf('/');
431             derivedPackageName = (iSep > 0) ?
432                     JspUtil.makeJavaPackage(jspUri.substring(1,iSep)) : "";
433         }
434         return derivedPackageName;
435     }
436         
437     /**
438      * The package name into which the servlet class is generated.
439      */

440     public void setServletPackageName(String JavaDoc servletPackageName) {
441         this.basePackageName = servletPackageName;
442     }
443
444     /**
445      * Full path name of the Java file into which the servlet is being
446      * generated.
447      */

448     public String JavaDoc getServletJavaFileName() {
449         if (servletJavaFileName == null) {
450             servletJavaFileName = getOutputDir() + getServletClassName() + ".java";
451         }
452         return servletJavaFileName;
453     }
454
455     /**
456      * Get hold of the Options object for this context.
457      */

458     public Options getOptions() {
459         return options;
460     }
461
462     public ServletContext JavaDoc getServletContext() {
463         return context;
464     }
465
466     public JspRuntimeContext getRuntimeContext() {
467         return rctxt;
468     }
469
470     /**
471      * Path of the Java file relative to the work directory.
472      */

473     public String JavaDoc getJavaPath() {
474
475         if (javaPath != null) {
476             return javaPath;
477         }
478
479         if (isTagFile()) {
480         String JavaDoc tagName = tagInfo.getTagClassName();
481             javaPath = tagName.replace('.', '/') + ".java";
482         } else {
483             javaPath = getServletPackageName().replace('.', '/') + '/' +
484                        getServletClassName() + ".java";
485     }
486         return javaPath;
487     }
488
489     public String JavaDoc getClassFileName() {
490         if (classFileName == null) {
491             classFileName = getOutputDir() + getServletClassName() + ".class";
492         }
493         return classFileName;
494     }
495
496     /**
497      * Get the content type of this JSP.
498      *
499      * Content type includes content type and encoding.
500      */

501     public String JavaDoc getContentType() {
502         return contentType;
503     }
504
505     public void setContentType(String JavaDoc contentType) {
506         this.contentType = contentType;
507     }
508
509     /**
510      * Where is the servlet being generated?
511      */

512     public ServletWriter getWriter() {
513         return writer;
514     }
515
516     public void setWriter(ServletWriter writer) {
517         this.writer = writer;
518     }
519
520     /**
521      * Gets the 'location' of the TLD associated with the given taglib 'uri'.
522      *
523      * @return An array of two Strings: The first element denotes the real
524      * path to the TLD. If the path to the TLD points to a jar file, then the
525      * second element denotes the name of the TLD entry in the jar file.
526      * Returns null if the given uri is not associated with any tag library
527      * 'exposed' in the web application.
528      */

529     public String JavaDoc[] getTldLocation(String JavaDoc uri) throws JasperException {
530         String JavaDoc[] location =
531             getOptions().getTldLocationsCache().getLocation(uri);
532         return location;
533     }
534
535     /**
536      * Are we keeping generated code around?
537      */

538     public boolean keepGenerated() {
539         return getOptions().getKeepGenerated();
540     }
541
542     // ==================== Removal ====================
543

544     public void incrementRemoved() {
545         if (removed == 0 && rctxt != null) {
546             rctxt.removeWrapper(jspUri);
547         }
548         removed++;
549     }
550
551     public boolean isRemoved() {
552         if (removed > 1 ) {
553             return true;
554         }
555         return false;
556     }
557
558     // ==================== Compile and reload ====================
559

560     public void compile() throws JasperException, FileNotFoundException JavaDoc {
561         createCompiler();
562         if (isPackagedTagFile || jspCompiler.isOutDated()) {
563             try {
564                 jspCompiler.removeGeneratedFiles();
565                 jspLoader = null;
566                 jspCompiler.compile();
567                 jsw.setReload(true);
568                 jsw.setCompilationException(null);
569             } catch (JasperException ex) {
570                 // Cache compilation exception
571
jsw.setCompilationException(ex);
572                 throw ex;
573             } catch (Exception JavaDoc ex) {
574                 JasperException je = new JasperException(
575                             Localizer.getMessage("jsp.error.unable.compile"),
576                             ex);
577                 // Cache compilation exception
578
jsw.setCompilationException(je);
579                 throw je;
580             }
581         }
582     }
583
584     // ==================== Manipulating the class ====================
585

586     public Class JavaDoc load()
587         throws JasperException, FileNotFoundException JavaDoc
588     {
589         try {
590             getJspLoader();
591             
592             String JavaDoc name;
593             if (isTagFile()) {
594                 name = tagInfo.getTagClassName();
595             } else {
596                 name = getServletPackageName() + "." + getServletClassName();
597             }
598             servletClass = jspLoader.loadClass(name);
599         } catch (ClassNotFoundException JavaDoc cex) {
600             throw new JasperException(Localizer.getMessage("jsp.error.unable.load"),
601                                       cex);
602         } catch (Exception JavaDoc ex) {
603             throw new JasperException(Localizer.getMessage("jsp.error.unable.compile"),
604                                       ex);
605         }
606         removed = 0;
607         return servletClass;
608     }
609
610     // ==================== protected methods ====================
611

612     static Object JavaDoc outputDirLock = new Object JavaDoc();
613
614     public void checkOutputDir() {
615         if (outputDir != null) {
616             if (!(new File JavaDoc(outputDir)).exists()) {
617                 makeOutputDir();
618             }
619         } else {
620             createOutputDir();
621         }
622     }
623         
624     protected boolean makeOutputDir() {
625         synchronized(outputDirLock) {
626             File JavaDoc outDirFile = new File JavaDoc(outputDir);
627             return (outDirFile.exists() || outDirFile.mkdirs());
628         }
629     }
630
631     protected void createOutputDir() {
632         String JavaDoc path = null;
633         if (isTagFile()) {
634         String JavaDoc tagName = tagInfo.getTagClassName();
635             path = tagName.replace('.', '/');
636         path = path.substring(0, path.lastIndexOf('/'));
637         } else {
638             path = getServletPackageName().replace('.', '/');
639     }
640
641             // Append servlet or tag handler path to scratch dir
642
try {
643                 baseUrl = options.getScratchDir().toURL();
644                 String JavaDoc outUrlString = baseUrl.toString() + '/' + path;
645                 URL JavaDoc outUrl = new URL JavaDoc(outUrlString);
646                 outputDir = outUrl.getFile() + File.separator;
647                 if (!makeOutputDir()) {
648                     throw new IllegalStateException JavaDoc(Localizer.getMessage("jsp.error.outputfolder"));
649                 }
650             } catch (MalformedURLException JavaDoc e) {
651                 throw new IllegalStateException JavaDoc(Localizer.getMessage("jsp.error.outputfolder"), e);
652             }
653     }
654     
655     protected static final boolean isPathSeparator(char c) {
656        return (c == '/' || c == '\\');
657     }
658
659     protected static final String JavaDoc canonicalURI(String JavaDoc s) {
660        if (s == null) return null;
661        StringBuffer JavaDoc result = new StringBuffer JavaDoc();
662        final int len = s.length();
663        int pos = 0;
664        while (pos < len) {
665            char c = s.charAt(pos);
666            if ( isPathSeparator(c) ) {
667                /*
668                 * multiple path separators.
669                 * 'foo///bar' -> 'foo/bar'
670                 */

671                while (pos+1 < len && isPathSeparator(s.charAt(pos+1))) {
672                    ++pos;
673                }
674
675                if (pos+1 < len && s.charAt(pos+1) == '.') {
676                    /*
677                     * a single dot at the end of the path - we are done.
678                     */

679                    if (pos+2 >= len) break;
680
681                    switch (s.charAt(pos+2)) {
682                        /*
683                         * self directory in path
684                         * foo/./bar -> foo/bar
685                         */

686                    case '/':
687                    case '\\':
688                        pos += 2;
689                        continue;
690
691                        /*
692                         * two dots in a path: go back one hierarchy.
693                         * foo/bar/../baz -> foo/baz
694                         */

695                    case '.':
696                        // only if we have exactly _two_ dots.
697
if (pos+3 < len && isPathSeparator(s.charAt(pos+3))) {
698                            pos += 3;
699                            int separatorPos = result.length()-1;
700                            while (separatorPos >= 0 &&
701                                   ! isPathSeparator(result
702                                                     .charAt(separatorPos))) {
703                                --separatorPos;
704                            }
705                            if (separatorPos >= 0)
706                                result.setLength(separatorPos);
707                            continue;
708                        }
709                    }
710                }
711            }
712            result.append(c);
713            ++pos;
714        }
715        return result.toString();
716     }
717 }
718
719
Popular Tags