/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/ package org.apache.jasper.compiler;
if (smap == null && !options.isSmapSuppressed()) { // Tomcat was restarted so cached SMAP has been lost. However, it // was written to the class file so it can be recovered.
smap = SmapUtil.loadSmap(className, ctxt.getJspLoader()); if (smap != null) {
smaps.put(className, smap);
}
}
return smap;
}
/** * Compile the jsp file into equivalent servlet in .java file * * @return A map of class names to JSR 045 source maps * * @throws Exception Error generating Java source
*/ protected Map<String,SmapStratum> generateJava() throws Exception {
long t1, t2, t3, t4;
t1 = t2 = t3 = t4 = 0;
if (log.isDebugEnabled()) {
t1 = System.currentTimeMillis();
}
// Setup page info area
pageInfo = new PageInfo(new BeanRepository(ctxt.getClassLoader(),
errDispatcher), ctxt);
/* * If the current uri is matched by a pattern specified in a * jsp-property-group in web.xml, initialize pageInfo with those * properties.
*/ if (jspProperty.isELIgnored() != null) {
pageInfo.setELIgnored(JspUtil.booleanValue(jspProperty
.isELIgnored()));
} if (jspProperty.getErrorOnELNotFound() != null) {
pageInfo.setErrorOnELNotFound(JspUtil.booleanValue(jspProperty
.getErrorOnELNotFound()));
} if (jspProperty.isScriptingInvalid() != null) {
pageInfo.setScriptingInvalid(JspUtil.booleanValue(jspProperty
.isScriptingInvalid()));
} if (jspProperty.getIncludePrelude() != null) {
pageInfo.setIncludePrelude(jspProperty.getIncludePrelude());
} if (jspProperty.getIncludeCoda() != null) {
pageInfo.setIncludeCoda(jspProperty.getIncludeCoda());
} if (jspProperty.isDeferedSyntaxAllowedAsLiteral() != null) {
pageInfo.setDeferredSyntaxAllowedAsLiteral(JspUtil.booleanValue(jspProperty
.isDeferedSyntaxAllowedAsLiteral()));
} if (jspProperty.isTrimDirectiveWhitespaces() != null) {
pageInfo.setTrimDirectiveWhitespaces(JspUtil.booleanValue(jspProperty
.isTrimDirectiveWhitespaces()));
} // Default ContentType processing is deferred until after the page has // been parsed if (jspProperty.getBuffer() != null) {
pageInfo.setBufferValue(jspProperty.getBuffer(), null,
errDispatcher);
} if (jspProperty.isErrorOnUndeclaredNamespace() != null) {
pageInfo.setErrorOnUndeclaredNamespace(
JspUtil.booleanValue(
jspProperty.isErrorOnUndeclaredNamespace()));
} if (ctxt.isTagFile()) { try { double libraryVersion = Double.parseDouble(ctxt.getTagInfo()
.getTagLibrary().getRequiredVersion()); if (libraryVersion < 2.0) {
pageInfo.setIsELIgnored("true", null, errDispatcher, true);
} if (libraryVersion < 2.1) {
pageInfo.setDeferredSyntaxAllowedAsLiteral("true", null,
errDispatcher, true);
}
} catch (NumberFormatException ex) {
errDispatcher.jspError(ex);
}
}
try { /* * The setting of isELIgnored changes the behaviour of the parser * in subtle ways. To add to the 'fun', isELIgnored can be set in * any file that forms part of the translation unit so setting it * in a file included towards the end of the translation unit can * change how the parser should have behaved when parsing content * up to the point where isELIgnored was set. Arghh! * Previous attempts to hack around this have only provided partial * solutions. We now use two passes to parse the translation unit. * The first just parses the directives and the second parses the * whole translation unit once we know how isELIgnored has been set. * TODO There are some possible optimisations of this process.
*/ // Parse the file
ParserController parserCtl = new ParserController(ctxt, this);
// Pass 2 - the whole translation unit
pageNodes = parserCtl.parse(ctxt.getJspFile());
// Leave this until now since it can only be set once - bug 49726 if (pageInfo.getContentType() == null &&
jspProperty.getDefaultContentType() != null) {
pageInfo.setContentType(jspProperty.getDefaultContentType());
}
if (ctxt.isPrototypeMode()) { // generate prototype .java file for the tag file try (ServletWriter writer = setupContextWriter(javaFileName)) {
Generator.generate(writer, this, pageNodes); returnnull;
}
}
// Validate and process attributes - don't re-validate the // directives we validated in pass 1
Validator.validateExDirectives(this, pageNodes);
if (log.isDebugEnabled()) {
t2 = System.currentTimeMillis();
}
// Collect page info
Collector.collect(this, pageNodes);
// Compile (if necessary) and load the tag files referenced in // this compilation unit.
tfp = new TagFileProcessor();
tfp.loadTagFiles(this, pageNodes);
if (log.isDebugEnabled()) {
t3 = System.currentTimeMillis();
}
// Determine which custom tag needs to declare which scripting vars
ScriptingVariabler.set(pageNodes, errDispatcher);
// Optimizations by Tag Plugins
TagPluginManager tagPluginManager = options.getTagPluginManager();
tagPluginManager.apply(pageNodes, errDispatcher, pageInfo);
// The writer is only used during the compile, dereference // it in the JspCompilationContext when done to allow it // to be GC'd and save memory.
ctxt.setWriter(null);
} catch (RuntimeException e) { // Remove the generated .java file
File file = new File(javaFileName); if (file.exists()) { if (!file.delete()) {
log.warn(Localizer.getMessage( "jsp.warning.compiler.javafile.delete.fail",
file.getAbsolutePath()));
}
} throw e;
}
Map<String,SmapStratum> smaps = null;
// JSR45 Support if (!options.isSmapSuppressed()) {
smaps = SmapUtil.generateSmap(ctxt, pageNodes); // Add them to the web application wide cache for future lookup in // error handling etc.
ctxt.getRuntimeContext().getSmaps().putAll(smaps);
}
// If any proto type .java and .class files was generated, // the prototype .java may have been replaced by the current // compilation (if the tag file is self referencing), but the // .class file need to be removed, to make sure that javac would // generate .class again from the new .java file just generated.
tfp.removeProtoTypeFiles(ctxt.getClassFileName());
try {
osw = new OutputStreamWriter( new FileOutputStream(javaFileName), javaEncoding);
} catch (UnsupportedEncodingException ex) {
errDispatcher.jspError("jsp.error.needAlternateJavaEncoding",
javaEncoding);
}
if (ctxt.getOptions().getTrimSpaces().equals(TrimSpacesOption.EXTENDED)) {
writer = new NewlineReductionServletWriter(new PrintWriter(osw));
} else {
writer = new ServletWriter(new PrintWriter(osw));
}
ctxt.setWriter(writer); return writer;
}
/** * Servlet compilation. This compiles the generated sources into * Servlets. * * @param smaps The source maps for the class(es) generated from the source * file * * @throws FileNotFoundException Source files not found * @throws JasperException Compilation error * @throws Exception Some other error
*/ protectedabstractvoid generateClass(Map<String,SmapStratum> smaps) throws FileNotFoundException, JasperException, Exception;
/** * Compile the jsp file from the current engine context. * @throws FileNotFoundException Source files not found * @throws JasperException Compilation error * @throws Exception Some other error
*/ publicvoid compile() throws FileNotFoundException, JasperException,
Exception {
compile(true);
}
/** * Compile the jsp file from the current engine context. As an side- effect, * tag files that are referenced by this page are also compiled. * * @param compileClass * If true, generate both .java and .class file If false, * generate only .java file * @throws FileNotFoundException Source files not found * @throws JasperException Compilation error * @throws Exception Some other error
*/ publicvoid compile(boolean compileClass) throws FileNotFoundException,
JasperException, Exception {
compile(compileClass, false);
}
/** * Compile the jsp file from the current engine context. As an side- effect, * tag files that are referenced by this page are also compiled. * * @param compileClass * If true, generate both .java and .class file If false, * generate only .java file * @param jspcMode * true if invoked from JspC, false otherwise * @throws FileNotFoundException Source files not found * @throws JasperException Compilation error * @throws Exception Some other error
*/ publicvoid compile(boolean compileClass, boolean jspcMode) throws FileNotFoundException, JasperException, Exception { if (errDispatcher == null) { this.errDispatcher = new ErrorDispatcher(jspcMode);
}
try { finalLong jspLastModified = ctxt.getLastModified(ctxt.getJspFile());
Map<String,SmapStratum> smaps = generateJava();
File javaFile = new File(ctxt.getServletJavaFileName()); if (!javaFile.setLastModified(jspLastModified.longValue())) { thrownew JasperException(Localizer.getMessage("jsp.error.setLastModified", javaFile));
} if (compileClass) {
generateClass(smaps); // Fix for bugzilla 41606 // Set JspServletWrapper.servletClassLastModifiedTime after successful compile
File targetFile = new File(ctxt.getClassFileName()); if (targetFile.exists()) { if (!targetFile.setLastModified(jspLastModified.longValue())) { thrownew JasperException(
Localizer.getMessage("jsp.error.setLastModified", targetFile));
} if (jsw != null) {
jsw.setServletClassLastModifiedTime(
jspLastModified.longValue());
}
}
}
} finally { if (tfp != null && ctxt.isPrototypeMode()) {
tfp.removeProtoTypeFiles(null);
} // Make sure these object which are only used during the // generation and compilation of the JSP page get // dereferenced so that they can be GC'd and reduce the // memory footprint.
tfp = null;
errDispatcher = null;
pageInfo = null;
pageNodes = null;
if (ctxt.getWriter() != null) {
ctxt.getWriter().close();
ctxt.setWriter(null);
}
}
}
/** * This is a protected method intended to be overridden by subclasses of * Compiler. This is used by the compile method to do all the compilation. * @return <code>true</code> if the source generation and compilation * should occur
*/ publicboolean isOutDated() { return isOutDated(true);
}
/** * Determine if a compilation is necessary by checking the time stamp of the * JSP page with that of the corresponding .class or .java file. If the page * has dependencies, the check is also extended to its dependents, and so * on. This method can by overridden by a subclasses of Compiler. * * @param checkClass * If true, check against .class file, if false, check against * .java file. * @return <code>true</code> if the source generation and compilation * should occur
*/ publicboolean isOutDated(boolean checkClass) {
if (jsw != null
&& (ctxt.getOptions().getModificationTestInterval() > 0)) {
if (jsw.getLastModificationTest()
+ (ctxt.getOptions().getModificationTestInterval() * 1000) > System
.currentTimeMillis()) { returnfalse;
}
jsw.setLastModificationTest(System.currentTimeMillis());
}
// Test the target file first. Unless there is an error checking the // last modified time of the source (unlikely) the target is going to // have to be checked anyway. If the target doesn't exist (likely during // startup) this saves an unnecessary check of the source.
File targetFile; if (checkClass) {
targetFile = new File(ctxt.getClassFileName());
} else {
targetFile = new File(ctxt.getServletJavaFileName());
} if (!targetFile.exists()) { returntrue;
} long targetLastModified = targetFile.lastModified(); if (checkClass && jsw != null) {
jsw.setServletClassLastModifiedTime(targetLastModified);
}
Long jspRealLastModified = ctxt.getLastModified(ctxt.getJspFile()); if (jspRealLastModified.longValue() < 0) { // Something went wrong - assume modification returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.