/** Locate all jsp files in the webapp. Used if no explicit jsps are specified. */ public void scanFiles(File base) { Stack<String> dirs = new Stack<>(); dirs.push(base.toString()); // Make sure default extensions are always included if ((getExtensions() == null) || (getExtensions().size() < 2)) { addExtension("jsp"); addExtension("jspx"); } while (!dirs.isEmpty()) { String s = dirs.pop(); File f = new File(s); if (f.exists() && f.isDirectory()) { String[] files = f.list(); String ext; for (int i = 0; (files != null) && i < files.length; i++) { File f2 = new File(s, files[i]); if (f2.isDirectory()) { dirs.push(f2.getPath()); } else { String path = f2.getPath(); String uri = path.substring(uriRoot.length()); ext = files[i].substring(files[i].lastIndexOf('.') + 1); if (getExtensions().contains(ext) || jspConfig.isJspPage(uri)) { pages.add(path); } } } } } }
/** Compile the jsp file into equivalent servlet in java source */ private void generateJava() throws Exception { long t1, t2, t3, t4; t1 = t2 = t3 = t4 = 0; if (log.isLoggable(Level.FINE)) { t1 = System.currentTimeMillis(); } // Setup page info area pageInfo = new PageInfo(new BeanRepository(ctxt.getClassLoader(), errDispatcher), ctxt.getJspFile()); JspConfig jspConfig = options.getJspConfig(); JspProperty jspProperty = jspConfig.findJspProperty(ctxt.getJspFile()); /* * If the current uri is matched by a pattern specified in * a jsp-property-group in web.xml, initialize pageInfo with * those properties. */ pageInfo.setELIgnored(JspUtil.booleanValue(jspProperty.isELIgnored())); pageInfo.setScriptingInvalid(JspUtil.booleanValue(jspProperty.isScriptingInvalid())); pageInfo.setTrimDirectiveWhitespaces(JspUtil.booleanValue(jspProperty.getTrimSpaces())); pageInfo.setDeferredSyntaxAllowedAsLiteral(JspUtil.booleanValue(jspProperty.getPoundAllowed())); pageInfo.setErrorOnUndeclaredNamespace( JspUtil.booleanValue(jspProperty.errorOnUndeclaredNamespace())); if (jspProperty.getIncludePrelude() != null) { pageInfo.setIncludePrelude(jspProperty.getIncludePrelude()); } if (jspProperty.getIncludeCoda() != null) { pageInfo.setIncludeCoda(jspProperty.getIncludeCoda()); } if (options.isDefaultBufferNone() && pageInfo.getBufferValue() == null) { // Set to unbuffered if not specified explicitly pageInfo.setBuffer(0); } String javaFileName = ctxt.getServletJavaFileName(); ServletWriter writer = null; try { // Setup the ServletWriter Writer javaWriter = javaCompiler.getJavaWriter(javaFileName, ctxt.getOptions().getJavaEncoding()); writer = new ServletWriter(new PrintWriter(javaWriter)); ctxt.setWriter(writer); // Reset the temporary variable counter for the generator. JspUtil.resetTemporaryVariableName(); // Parse the file ParserController parserCtl = new ParserController(ctxt, this); pageNodes = parserCtl.parse(ctxt.getJspFile()); if (ctxt.isPrototypeMode()) { // generate prototype .java file for the tag file Generator.generate(writer, this, pageNodes); writer.close(); writer = null; return; } // Validate and process attributes Validator.validate(this, pageNodes); if (log.isLoggable(Level.FINE)) { 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.isLoggable(Level.FINE)) { 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); // Optimization: concatenate contiguous template texts. TextOptimizer.concatenate(this, pageNodes); // Generate static function mapper codes. ELFunctionMapper.map(this, pageNodes); // generate servlet .java file Generator.generate(writer, this, pageNodes); writer.close(); writer = null; // 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); if (log.isLoggable(Level.FINE)) { t4 = System.currentTimeMillis(); log.fine( "Generated " + javaFileName + " total=" + (t4 - t1) + " generate=" + (t4 - t3) + " validate=" + (t2 - t1)); } } catch (Exception e) { if (writer != null) { try { writer.close(); writer = null; } catch (Exception e1) { // do nothing } } // Remove the generated .java file javaCompiler.doJavaFile(false); throw e; } finally { if (writer != null) { try { writer.close(); } catch (Exception e2) { // do nothing } } } // JSR45 Support if (!options.isSmapSuppressed()) { smapUtil.generateSmap(pageNodes); } // 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()); }
/** * Compile the jsp file into equivalent servlet in .java file * * @return a smap for the current JSP page, if one is generated, null otherwise */ protected String[] generateJava() throws Exception { String[] smapStr = null; 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.getJspFile()); JspConfig jspConfig = options.getJspConfig(); JspConfig.JspProperty jspProperty = jspConfig.findJspProperty(ctxt.getJspFile()); /* * 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.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); } } ctxt.checkOutputDir(); String javaFileName = ctxt.getServletJavaFileName(); ServletWriter writer = null; 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 1 - the directives Node.Nodes directives = parserCtl.parseDirectives(ctxt.getJspFile()); Validator.validateDirectives(this, directives); // 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 writer = setupContextWriter(javaFileName); Generator.generate(writer, this, pageNodes); writer.close(); writer = null; return null; } // 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); // Optimization: concatenate contiguous template texts. TextOptimizer.concatenate(this, pageNodes); // Generate static function mapper codes. ELFunctionMapper.map(pageNodes); // generate servlet .java file writer = setupContextWriter(javaFileName); Generator.generate(writer, this, pageNodes); writer.close(); writer = null; // 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); if (log.isDebugEnabled()) { t4 = System.currentTimeMillis(); log.debug( "Generated " + javaFileName + " total=" + (t4 - t1) + " generate=" + (t4 - t3) + " validate=" + (t2 - t1)); } } catch (Exception e) { if (writer != null) { try { writer.close(); writer = null; } catch (Exception e1) { // do nothing } } // 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; } finally { if (writer != null) { try { writer.close(); } catch (Exception e2) { // do nothing } } } // JSR45 Support if (!options.isSmapSuppressed()) { smapStr = SmapUtil.generateSmap(ctxt, pageNodes); } // 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()); return smapStr; }