From 6acb5be183f9d189628089d186ede0caf887cf0c Mon Sep 17 00:00:00 2001 From: Steve Loughran Date: Fri, 8 Mar 2002 08:40:39 +0000 Subject: [PATCH] reworking of jspc in order to get it into shape. Added name mangling support in dependency checking, jasperc is running in separate process so that exec failure should be caught; classpath param can set path to jasper too git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271795 13f79535-47bb-0310-9956-ffa450edef68 --- .../tools/ant/taskdefs/optional/jsp/JspC.java | 192 ++++++++++++++---- .../taskdefs/optional/jsp/JspNameMangler.java | 188 +++++++++++++++++ .../jsp/compilers/DefaultCompilerAdapter.java | 53 ++++- .../optional/jsp/compilers/JasperC.java | 68 ++++--- 4 files changed, 427 insertions(+), 74 deletions(-) create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspNameMangler.java diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspC.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspC.java index 1c2ad5976..a280f6658 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspC.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspC.java @@ -67,6 +67,7 @@ import org.apache.tools.ant.taskdefs.optional.jsp.compilers.CompilerAdapter; import org.apache.tools.ant.taskdefs.optional.jsp.compilers.CompilerAdapterFactory; import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.Reference; /** Ant task to run the jsp compiler. @@ -99,13 +100,14 @@ import org.apache.tools.ant.types.Reference; * </jspc> * * - * @version $Revision$ $Date$ + * @author Steve Loughran * @author Matthew Watson *

Large Amount of cutting and pasting from the Javac task... * @author James Davidson duncan@x180.com * @author Robin Green greenrd@hotmail.com * @author Stefan Bodewig * @author J D Glanville + * @since 1.5 */ public class JspC extends MatchingTask { @@ -114,10 +116,19 @@ public class JspC extends MatchingTask private Path src; private File destDir; private String packageName ; + /** name of the compiler to use */ + private String compiler="jasper"; + + /** + * -ieplugin Java Plugin classid for Internet Explorer + */ private String iepluginid ; private boolean mapped ; private int verbose = 0; protected Vector compileList = new Vector(); + /** + * flag to control action on execution trouble + */ protected boolean failOnError = true; /** @@ -132,6 +143,24 @@ public class JspC extends MatchingTask * against, */ private File uriroot; + + /** + * -webinc Creates partial servlet mappings for the -webapp option + */ + private File webinc; + + /** + * -webxml Creates a complete web.xml when using the -webapp option. + */ + + private File webxml; + + /** + * web apps + */ + protected WebAppParameter webApp; + + private final static String FAIL_MSG = "Compile failed, messages should have been provided."; @@ -269,14 +298,73 @@ public class JspC extends MatchingTask public Path getClasspath(){ return classpath; } - /* ------------------------------------------------------------ */ + + /** + * -webxml Creates a complete web.xml when using the -webapp option. + * + * @param webxml The new Webxml value + */ + public void setWebxml(File webxml) { + this.webxml = webxml; + } + + public File getWebxml() { + return this.webxml; + } + + /** + * name output file for the fraction of web.xml that lists + * servlets + * @param webinc The new Webinc value + */ + public void setWebinc(File webinc) { + this.webinc = webinc; + } + + public File getWebinc() { + return this.webinc; + } + + /** + * web apps param. only one is allowed. + * + * @param fs add a web app fileset + */ + public void addWebApp(WebAppParameter webappParam) + throws BuildException { + //demand create vector of filesets + if(webApp == null) { + webApp = webappParam; + } + else { + throw new BuildException("Only one webapp can be specified"); + } + } + + public WebAppParameter getWebApp() { + return webApp; + } + + /** + * set the compiler. optional: default=jasper + */ + public void setCompiler(String compiler) { + this.compiler=compiler; + } + + /** + * get the list of files to compile + */ public Vector getCompileList(){ return compileList; } - /* ------------------------------------------------------------ */ + + /** + * execute by building up a list of files that + * have changed and hand them off to a jsp compiler + */ public void execute() - throws BuildException - { + throws BuildException { // first off, make sure that we've got a srcdir if (src == null) { throw new BuildException("srcdir attribute must be set!", @@ -325,10 +413,6 @@ public class JspC extends MatchingTask // compile the source files - String compiler = project.getProperty("jsp.compiler"); - if (compiler == null) { - compiler = "jasper"; - } log("compiling "+compileList.size()+" files",Project.MSG_VERBOSE); if (compileList.size() > 0) { @@ -379,36 +463,72 @@ public class JspC extends MatchingTask long now = (new Date()).getTime(); for (int i = 0; i < files.length; i++) { - File srcFile = new File(srcDir, files[i]); - if (files[i].endsWith(".jsp")) { - // drop leading path (if any) - int fileStart = - files[i].lastIndexOf(File.separatorChar) + 1; - File javaFile = new File(destDir, files[i].substring(fileStart, - files[i].indexOf(".jsp")) + ".java"); - - if (srcFile.lastModified() > now) { - log("Warning: file modified in the future: " + - files[i], Project.MSG_WARN); - } + String filename=files[i]; + File srcFile = new File(srcDir, filename); + File javaFile=mapToJavaFile(srcFile); - if (!javaFile.exists() || - srcFile.lastModified() > javaFile.lastModified()) - { - if (!javaFile.exists()) { - log("Compiling " + srcFile.getPath() + - " because java file " - + javaFile.getPath() + " does not exist", - Project.MSG_DEBUG); - } else { - log("Compiling " + srcFile.getPath() + - " because it is out of date with respect to " - + javaFile.getPath(), Project.MSG_DEBUG); - } - compileList.addElement(srcFile.getAbsolutePath()); + if (srcFile.lastModified() > now) { + log("Warning: file modified in the future: " +filename, + Project.MSG_WARN); + } + boolean shouldCompile=false; + + if (!javaFile.exists()) { + shouldCompile=true; + log("Compiling " + srcFile.getPath() + + " because java file "+ javaFile.getPath() + " does not exist", + Project.MSG_DEBUG); + } else { + if( srcFile.lastModified() > javaFile.lastModified()) { + shouldCompile=true; + log("Compiling " + srcFile.getPath() + + " because it is out of date with respect to " + javaFile.getPath(), + Project.MSG_DEBUG); } } + if(shouldCompile) { + compileList.addElement(srcFile.getAbsolutePath()); + } } } - /* ------------------------------------------------------------ */ + + /** + * get a filename from our jsp file + */ + protected File mapToJavaFile(File srcFile) { + if (!srcFile.getName().endsWith(".jsp")) { + return null; + } + JspNameMangler mangler=new JspNameMangler(); + return new File(destDir, mangler.mapJspToJavaName(srcFile)); + } + + /** + * static inner class used as a parameter element + */ + public static class WebAppParameter { + + /** + * the sole option + */ + private File directory; + + /** + * query current directory + */ + + public File getDirectory() { + return directory; + } + + /** + * set directory; alternate syntax + */ + public void setBaseDir(File directory) { + this.directory=directory; + } + //end inner class + } + +//end class } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspNameMangler.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspNameMangler.java new file mode 100644 index 000000000..f760d1c91 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspNameMangler.java @@ -0,0 +1,188 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant.taskdefs.optional.jsp; +import java.io.File; +import java.io.IOException; + +/** + * this is a class derived from the Jasper code to map from a JSP filename + * to a valid java classname + * + * @author Steve Loughran + * @author Danno Ferrin + * @see org.apache.jasper.compiler.CommandLineCompiler; + */ +public class JspNameMangler { + + /** + * this is the list of keywords which can not be used as classnames + */ + public static String[] keywords = { + "assert", + "abstract", "boolean", "break", "byte", + "case", "catch", "char", "class", + "const", "continue", "default", "do", + "double", "else", "extends", "final", + "finally", "float", "for", "goto", + "if", "implements", "import", + "instanceof", "int", "interface", + "long", "native", "new", "package", + "private", "protected", "public", + "return", "short", "static", "super", + "switch", "synchronized", "this", + "throw", "throws", "transient", + "try", "void", "volatile", "while" + }; + + + /** + * map from a jsp file to a java filename; does not do packages + * + * @param jspFile file + * @return java filename + */ + public String mapJspToJavaName(File jspFile) { + return mapJspToBaseName(jspFile) + ".java"; + } + + + /** + * map from a jsp file to a base name; does not deal with extensions + * + * @param jspFile jspFile file + * @return exensionless potentially remapped name + */ + public String mapJspToBaseName(File jspFile) { + String className; + className = stripExtension(jspFile); + + // since we don't mangle extensions like the servlet does, + // we need to check for keywords as class names + for (int i = 0; i < keywords.length; ++i) { + if (className.equals(keywords[i])) { + className += "%"; + break; + } + } + + // Fix for invalid characters. If you think of more add to the list. + StringBuffer modifiedClassName = new StringBuffer(className.length()); + // first char is more restrictive than the rest + char firstChar = className.charAt(0); + if (Character.isJavaIdentifierStart(firstChar)) { + modifiedClassName.append(firstChar); + } + else { + modifiedClassName.append(mangleChar(firstChar)); + } + // this is the rest + for (int i = 1; i < className.length(); i++) { + char subChar = className.charAt(i); + if (Character.isJavaIdentifierPart(subChar)) { + modifiedClassName.append(subChar); + } + else { + modifiedClassName.append(mangleChar(subChar)); + } + } + return modifiedClassName.toString(); + } + + + /** + * get short filename from file + * + * @param jspFile file in + * @return file without any jsp extension + */ + private String stripExtension(File jspFile) { + String className; + String filename = jspFile.getName(); + if (filename.endsWith(".jsp")) { + className = filename.substring(0, filename.length() - 4); + } + else { + className = filename; + } + return className; + } + + + /** + * definition of the char escaping algorithm + * + * @param ch char to mangle + * @return mangled string; 5 digit hex value + */ + private final static String mangleChar(char ch) { + + if (ch == File.separatorChar) { + ch = '/'; + } + String s = Integer.toHexString(ch); + int nzeros = 5 - s.length(); + char[] result = new char[6]; + result[0] = '_'; + for (int i = 1; i <= nzeros; ++i) { + result[i] = '0'; + } + int resultIndex = 0; + for (int i = nzeros + 1; i < 6; ++i) { + result[i] = s.charAt(resultIndex++); + } + return new String(result); + } + +} + diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/DefaultCompilerAdapter.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/DefaultCompilerAdapter.java index 17e909bc2..d4f49fa88 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/DefaultCompilerAdapter.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/DefaultCompilerAdapter.java @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2001 The Apache Software Foundation. All rights + * Copyright (c) 2001-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,6 +61,7 @@ import org.apache.tools.ant.types.Commandline; import java.util.Vector; import java.util.Enumeration; +import java.io.File; /** * This is the default implementation for the CompilerAdapter interface. @@ -102,14 +103,52 @@ public abstract class DefaultCompilerAdapter jspc.log(niceSourceList.toString(), Project.MSG_VERBOSE); } - /* ------------------------------------------------------------ */ - protected JspC attributes; - public void setJspc( JspC attributes ) { - this.attributes = attributes; + protected JspC owner; + + public void setJspc( JspC owner ) { + this.owner = owner; } public JspC getJspc() { - return attributes; + return owner; } - /* ------------------------------------------------------------ */ + + + /** + * add an argument oneple to the argument list, if the value aint null + * + * @param argument The argument + */ + protected void addArg(Commandline cmd,String argument) { + if(argument != null && argument.length() != 0) { + cmd.createArgument().setValue(argument); + } + } + + + /** + * add an argument tuple to the argument list, if the value aint null + * + * @param argument The argument + * @param value the parameter + */ + protected void addArg(Commandline cmd, String argument, String value) { + if(value!= null) { + cmd.createArgument().setValue(argument); + cmd.createArgument().setValue(value); + } + } + + /** + * add an argument tuple to the arg list, if the file parameter aint null + * + * @param argument The argument + * @param file the parameter + */ + protected void addArg(Commandline cmd, String argument, File file) { + if(file != null) { + cmd.createArgument().setValue(argument); + cmd.createArgument().setFile(file); + } + } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JasperC.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JasperC.java index 93a40a366..f93ac46b9 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JasperC.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JasperC.java @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2001 The Apache Software Foundation. All rights + * Copyright (c) 2001-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,41 +57,55 @@ package org.apache.tools.ant.taskdefs.optional.jsp.compilers; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.types.Path; import org.apache.tools.ant.taskdefs.optional.jsp.JspC; import org.apache.tools.ant.taskdefs.Java; +import java.io.File; + /** * The implementation of the jasper compiler. * This is a cut-and-paste of the original Jspc task. * * @author Matthew Watson mattw@i3sp.com + * @author steve loughran + * @since ant1.5 */ public class JasperC extends DefaultCompilerAdapter { - /* ------------------------------------------------------------ */ + /** + * our execute method + */ public boolean execute() - throws BuildException - { + throws BuildException { getJspc().log("Using jasper compiler", Project.MSG_VERBOSE); Commandline cmd = setupJasperCommand(); try { // Create an instance of the compiler, redirecting output to // the project log + // REVISIT. ugly. Java java = (Java)(getJspc().getProject()).createTask("java"); if (getJspc().getClasspath() != null) { java.setClasspath(getJspc().getClasspath()); } + else { + java.setClasspath(Path.systemClasspath); + } java.setClassname("org.apache.jasper.JspC"); String args[] = cmd.getArguments(); for (int i =0; i < args.length; i++) { java.createArg().setValue(args[i]); } - java.setFailonerror(true); + java.setFailonerror(getJspc().getFailonerror()); + //we are forking here to be sure that if JspC calls + //System.exit() it doesn't halt the build + java.setFork(true); java.execute(); return true; } catch (Exception ex) { + //@todo implement failonerror support here? if (ex instanceof BuildException) { throw (BuildException) ex; } else { @@ -100,38 +114,30 @@ public class JasperC extends DefaultCompilerAdapter } } } - /* ------------------------------------------------------------ */ + + + + /** + * build up a command line + * @return a command line for jasper + */ private Commandline setupJasperCommand() { Commandline cmd = new Commandline(); JspC jspc = getJspc(); - if (jspc.getDestdir() != null) { - cmd.createArgument().setValue("-d"); - cmd.createArgument().setFile(jspc.getDestdir()); - } - if (jspc.getPackage() != null){ - cmd.createArgument().setValue("-p"); - cmd.createArgument().setValue(jspc.getPackage()); - } - if (jspc.getVerbose() != 0) { - cmd.createArgument().setValue("-v" + jspc.getVerbose()); - } + addArg(cmd,"-d",jspc.getDestdir()); + addArg(cmd,"-p",jspc.getPackage()); + addArg(cmd,"-v"+jspc.getVerbose()); + addArg(cmd,"-uriroot",jspc.getUriroot()); + addArg(cmd,"-uribase",jspc.getUribase()); + addArg(cmd,"-ieplugin",jspc.getIeplugin()); if (jspc.isMapped()){ - cmd.createArgument().setValue("-mapped"); - } - if (jspc.getIeplugin() != null){ - cmd.createArgument().setValue("-ieplugin"); - cmd.createArgument().setValue(jspc.getIeplugin()); - } - if (jspc.getUriroot() != null){ - cmd.createArgument().setValue("-uriroot"); - cmd.createArgument().setValue(jspc.getUriroot().toString()); - } - if (jspc.getUribase() != null){ - cmd.createArgument().setValue("-uribase"); - cmd.createArgument().setValue(jspc.getUribase().toString()); + addArg(cmd,"-mapped"); + } + if(jspc.getWebApp()!=null) { + File dir=jspc.getWebApp().getDirectory(); + addArg(cmd,"-webapp",dir); } logAndAddFilesToCompile(getJspc(), getJspc().getCompileList(), cmd); return cmd; } - /* ------------------------------------------------------------ */ }