diff options
Diffstat (limited to 'jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java')
-rw-r--r-- | jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java | 345 |
1 files changed, 191 insertions, 154 deletions
diff --git a/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java b/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java index d7db6fb6cd..482006ebfa 100644 --- a/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java +++ b/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java @@ -25,55 +25,48 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; -import java.net.URI; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; -import java.util.regex.Pattern; import org.apache.jasper.JspC; +import org.apache.jasper.servlet.JspCServletContext; +import org.apache.jasper.servlet.TldScanner; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; +import org.apache.tomcat.JarScanner; +import org.apache.tomcat.util.scan.StandardJarScanner; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.StringUtils; import org.eclipse.jetty.util.IO; -import org.eclipse.jetty.util.PatternMatcher; import org.eclipse.jetty.util.resource.Resource; /** - * <p> * This goal will compile jsps for a webapp so that they can be included in a * war. - * </p> * <p> - * At runtime, the plugin will use the jsp2.0 jspc compiler if you are running - * on a 1.4 or lower jvm. If you are using a 1.5 jvm, then the jsp2.1 compiler - * will be selected. (this is the same behaviour as the <a - * href="http://jetty.mortbay.org/maven-plugin">jetty plugin</a> for executing - * webapps). + * At runtime, the plugin will use the jspc compiler to precompile jsps and tags. * </p> * <p> * Note that the same java compiler will be used as for on-the-fly compiled * jsps, which will be the Eclipse java compiler. - * </p> - * * <p> * See <a - * href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Jspc+Plugin">Usage + * href="https://www.eclipse.org/jetty/documentation/current/jetty-jspc-maven-plugin.html">Usage * Guide</a> for instructions on using this plugin. * </p> - * - * @author janb - * * @goal jspc * @phase process-classes - * @requiresDependencyResolution compile + * @requiresDependencyResolution compile+runtime * @description Runs jspc compiler to produce .java and .class files */ public class JspcMojo extends AbstractMojo @@ -87,13 +80,42 @@ public class JspcMojo extends AbstractMojo * * Add some extra setters to standard JspC class to help configure it * for running in maven. + * + * TODO move all setters on the plugin onto this jspc class instead. */ public static class JettyJspC extends JspC { + + private boolean scanAll; + public void setClassLoader (ClassLoader loader) { this.loader = loader; } + + public void setScanAllDirectories (boolean scanAll) + { + this.scanAll = scanAll; + } + + public boolean getScanAllDirectories () + { + return this.scanAll; + } + + + @Override + protected TldScanner newTldScanner(JspCServletContext context, boolean namespaceAware, boolean validate, boolean blockExternal) + { + if (context != null && context.getAttribute(JarScanner.class.getName()) == null) + { + StandardJarScanner jarScanner = new StandardJarScanner(); + jarScanner.setScanAllDirectories(getScanAllDirectories()); + context.setAttribute(JarScanner.class.getName(), jarScanner); + } + + return super.newTldScanner(context, namespaceAware, validate, blockExternal); + } } @@ -110,7 +132,7 @@ public class JspcMojo extends AbstractMojo * The artifacts for the project. * * @since jetty-7.6.3 - * @parameter expression="${project.artifacts}" + * @parameter default-value="${project.artifacts}" * @readonly */ private Set projectArtifacts; @@ -119,7 +141,7 @@ public class JspcMojo extends AbstractMojo /** * The maven project. * - * @parameter expression="${project}" + * @parameter default-value="${project}" * @required * @readonly */ @@ -130,7 +152,7 @@ public class JspcMojo extends AbstractMojo /** * The artifacts for the plugin itself. * - * @parameter expression="${plugin.artifacts}" + * @parameter default-value="${plugin.artifacts}" * @readonly */ private List pluginArtifacts; @@ -215,7 +237,7 @@ public class JspcMojo extends AbstractMojo /** * The location of the compiled classes for the webapp * - * @parameter expression="${project.build.outputDirectory}" + * @parameter default-value="${project.build.outputDirectory}" */ private File classesDirectory; @@ -229,6 +251,19 @@ public class JspcMojo extends AbstractMojo /** + * Source version - if not set defaults to jsp default (currently 1.7) + * @parameter + */ + private String sourceVersion; + + + /** + * Target version - if not set defaults to jsp default (currently 1.7) + * @parameter + */ + private String targetVersion; + + /** * * The JspC instance being used to compile the jsps. * @@ -237,7 +272,14 @@ public class JspcMojo extends AbstractMojo private JettyJspC jspc; - + /** + * Whether dirs on the classpath should be scanned as well as jars. + * True by default. This allows for scanning for tlds of dependent projects that + * are in the reactor as unassembled jars. + * + * @parameter default-value=true + */ + private boolean scanAllDirectories; public void execute() throws MojoExecutionException, MojoFailureException @@ -251,7 +293,11 @@ public class JspcMojo extends AbstractMojo getLog().info("webXml="+webXml); getLog().info("insertionMarker="+ (insertionMarker == null || insertionMarker.equals("") ? END_OF_WEBAPP : insertionMarker)); getLog().info("keepSources=" + keepSources); - getLog().info("mergeFragment=" + mergeFragment); + getLog().info("mergeFragment=" + mergeFragment); + if (sourceVersion != null) + getLog().info("sourceVersion="+sourceVersion); + if (targetVersion != null) + getLog().info("targetVersion="+targetVersion); } try { @@ -274,21 +320,17 @@ public class JspcMojo extends AbstractMojo List<URL> webAppUrls = setUpWebAppClassPath(); //set up the classpath of the container (ie jetty and jsp jars) - String sysClassPath = setUpSysClassPath(); - - //get the list of system classpath jars that contain tlds - List<URL> tldJarUrls = getSystemJarsWithTlds(); - - for (URL u:tldJarUrls) - { - if (getLog().isDebugEnabled()) - getLog().debug(" sys jar with tlds: "+u); - webAppUrls.add(u); - } - + Set<URL> pluginJars = getPluginJars(); + Set<URL> providedJars = getProvidedScopeJars(pluginJars); + + + //Make a classloader so provided jars will be on the classpath + List<URL> sysUrls = new ArrayList<URL>(); + sysUrls.addAll(providedJars); + URLClassLoader sysClassLoader = new URLClassLoader((URL[])sysUrls.toArray(new URL[0]), currentClassLoader); - //use the classpaths as the classloader - URLClassLoader webAppClassLoader = new URLClassLoader((URL[]) webAppUrls.toArray(new URL[0]), currentClassLoader); + //make a classloader with the webapp classpath + URLClassLoader webAppClassLoader = new URLClassLoader((URL[]) webAppUrls.toArray(new URL[0]), sysClassLoader); StringBuffer webAppClassPath = new StringBuffer(); for (int i = 0; i < webAppUrls.size(); i++) @@ -311,26 +353,40 @@ public class JspcMojo extends AbstractMojo if (jspc == null) jspc = new JettyJspC(); + jspc.setWebXmlFragment(webXmlFragment); jspc.setUriroot(webAppSourceDirectory); jspc.setOutputDir(generatedClasses); - jspc.setClassPath(sysClassPath+System.getProperty("path.separator")+webAppClassPath.toString()); jspc.setClassLoader(fakeWebAppClassLoader); + jspc.setScanAllDirectories(scanAllDirectories); jspc.setCompile(true); + if (sourceVersion != null) + jspc.setCompilerSourceVM(sourceVersion); + if (targetVersion != null) + jspc.setCompilerTargetVM(targetVersion); // JspC#setExtensions() does not exist, so // always set concrete list of files that will be processed. String jspFiles = getJspFiles(webAppSourceDirectory); - getLog().info("Compiling "+jspFiles); - getLog().info("Includes="+includes); - getLog().info("Excludes="+excludes); - jspc.setJspFiles(jspFiles); - - getLog().info("Files selected to precompile: " + jspFiles); - - jspc.execute(); + + try + { + if (jspFiles == null | jspFiles.equals("")) + { + getLog().info("No files selected to precompile"); + } + else + { + getLog().info("Compiling "+jspFiles+" from includes="+includes+" excludes="+excludes); + jspc.setJspFiles(jspFiles); + jspc.execute(); + } + } + finally + { - Thread.currentThread().setContextClassLoader(currentClassLoader); + Thread.currentThread().setContextClassLoader(currentClassLoader); + } } private String getJspFiles(String webAppSourceDirectory) @@ -345,7 +401,7 @@ public class JspcMojo extends AbstractMojo * Until Jasper supports the option to generate the srcs in a different dir * than the classes, this is the best we can do. * - * @throws Exception + * @throws Exception if unable to clean srcs */ public void cleanupSrcs() throws Exception { @@ -391,7 +447,7 @@ public class JspcMojo extends AbstractMojo * If you dont specify the insertionMarker, then the fragment will be * inserted at the end of the file just before the </webapp> * - * @throws Exception + * @throws Exception if unable to merge the web xml */ public void mergeWebXml() throws Exception { @@ -406,57 +462,62 @@ public class JspcMojo extends AbstractMojo return; } - File fragmentWebXml = new File(webXmlFragment); - if (!fragmentWebXml.exists()) + File fragmentWebXml = new File(webXmlFragment); + File mergedWebXml = new File(fragmentWebXml.getParentFile(), "web.xml"); + + try (BufferedReader webXmlReader = new BufferedReader(new FileReader(webXml)); + PrintWriter mergedWebXmlWriter = new PrintWriter(new FileWriter(mergedWebXml))) { - getLog().info("No fragment web.xml file generated"); - } - File mergedWebXml = new File(fragmentWebXml.getParentFile(), - "web.xml"); - try (BufferedReader webXmlReader = new BufferedReader(new FileReader( - webXml)); - PrintWriter mergedWebXmlWriter = new PrintWriter(new FileWriter( - mergedWebXml))) { - - // read up to the insertion marker or the </webapp> if there is no - // marker - boolean atInsertPoint = false; - boolean atEOF = false; - String marker = (insertionMarker == null - || insertionMarker.equals("") ? END_OF_WEBAPP : insertionMarker); - while (!atInsertPoint && !atEOF) + + if (!fragmentWebXml.exists()) { - String line = webXmlReader.readLine(); - if (line == null) - atEOF = true; - else if (line.indexOf(marker) >= 0) - { - atInsertPoint = true; - } - else + getLog().info("No fragment web.xml file generated"); + //just copy existing web.xml to expected position + IO.copy(webXmlReader, mergedWebXmlWriter); + } + else + { + // read up to the insertion marker or the </webapp> if there is no + // marker + boolean atInsertPoint = false; + boolean atEOF = false; + String marker = (insertionMarker == null + || insertionMarker.equals("") ? END_OF_WEBAPP : insertionMarker); + while (!atInsertPoint && !atEOF) { - mergedWebXmlWriter.println(line); + String line = webXmlReader.readLine(); + if (line == null) + atEOF = true; + else if (line.indexOf(marker) >= 0) + { + atInsertPoint = true; + } + else + { + mergedWebXmlWriter.println(line); + } } - } - - if (atEOF && !atInsertPoint) - throw new IllegalStateException("web.xml does not contain insertionMarker "+insertionMarker); - - //put in a context init-param to flag that the contents have been precompiled - mergedWebXmlWriter.println("<context-param><param-name>"+PRECOMPILED_FLAG+"</param-name><param-value>true</param-value></context-param>"); - - // put in the generated fragment - try (BufferedReader fragmentWebXmlReader = new BufferedReader( - new FileReader(fragmentWebXml))) { - IO.copy(fragmentWebXmlReader, mergedWebXmlWriter); + if (atEOF && !atInsertPoint) + throw new IllegalStateException("web.xml does not contain insertionMarker "+insertionMarker); - // if we inserted just before the </web-app>, put it back in - if (marker.equals(END_OF_WEBAPP)) - mergedWebXmlWriter.println(END_OF_WEBAPP); + //put in a context init-param to flag that the contents have been precompiled + mergedWebXmlWriter.println("<context-param><param-name>"+PRECOMPILED_FLAG+"</param-name><param-value>true</param-value></context-param>"); - // copy in the rest of the original web.xml file - IO.copy(webXmlReader, mergedWebXmlWriter); + + // put in the generated fragment + try (BufferedReader fragmentWebXmlReader = + new BufferedReader(new FileReader(fragmentWebXml))) + { + IO.copy(fragmentWebXmlReader, mergedWebXmlWriter); + + // if we inserted just before the </web-app>, put it back in + if (marker.equals(END_OF_WEBAPP)) + mergedWebXmlWriter.println(END_OF_WEBAPP); + + // copy in the rest of the original web.xml file + IO.copy(webXmlReader, mergedWebXmlWriter); + } } } } @@ -510,87 +571,63 @@ public class JspcMojo extends AbstractMojo } - private String setUpSysClassPath () throws Exception + + /** + * @return + * @throws MalformedURLException + */ + private Set<URL> getPluginJars () throws MalformedURLException { - StringBuffer buff = new StringBuffer(); - - //Put each of the plugin's artifacts onto the system classpath for jspc + HashSet<URL> pluginJars = new HashSet<>(); for (Iterator<Artifact> iter = pluginArtifacts.iterator(); iter.hasNext(); ) { Artifact pluginArtifact = iter.next(); if ("jar".equalsIgnoreCase(pluginArtifact.getType())) { if (getLog().isDebugEnabled()) { getLog().debug("Adding plugin artifact "+pluginArtifact);} - buff.append(pluginArtifact.getFile().getAbsolutePath()); - if (iter.hasNext()) - buff.append(File.pathSeparator); + pluginJars.add(pluginArtifact.getFile().toURI().toURL()); } } - - if (useProvidedScope) - { - for ( Iterator<Artifact> iter = projectArtifacts.iterator(); iter.hasNext(); ) - { - Artifact artifact = iter.next(); - if (Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) - { - //test to see if the provided artifact was amongst the plugin artifacts - String path = artifact.getFile().getAbsolutePath(); - if (! buff.toString().contains(path)) - { - if (buff.length() != 0) - buff.append(File.pathSeparator); - buff.append(path); - if (getLog().isDebugEnabled()) { getLog().debug("Adding provided artifact: "+artifact);} - } - else - { - if (getLog().isDebugEnabled()) { getLog().debug("Skipping provided artifact: "+artifact);} - } - } - } - } - - return buff.toString(); + return pluginJars; } - + + /** - * Glassfish jsp requires that we set up the list of system jars that have - * tlds in them. - * - * This method is a little fragile, as it relies on knowing that the jstl jars - * are the only ones in the system path that contain tlds. + * @param pluginJars * @return - * @throws Exception + * @throws MalformedURLException */ - private List<URL> getSystemJarsWithTlds() throws Exception + private Set<URL> getProvidedScopeJars (Set<URL> pluginJars) throws MalformedURLException { - getLog().debug("tld pattern=" + tldJarNamePatterns); - final List<URL> list = new ArrayList<URL>(); - List<URI> artifactUris = new ArrayList<URI>(); - Pattern pattern = Pattern.compile(tldJarNamePatterns); - for (Iterator<Artifact> iter = pluginArtifacts.iterator(); iter.hasNext(); ) - { - Artifact pluginArtifact = iter.next(); - Resource res = Resource.newResource(pluginArtifact.getFile()); - getLog().debug("scan jar: "+res.getURI()); - artifactUris.add(res.getURI()); - } + if (!useProvidedScope) + return Collections.emptySet(); - PatternMatcher matcher = new PatternMatcher() - { - public void matched(URI uri) throws Exception + HashSet<URL> providedJars = new HashSet<>(); + + for ( Iterator<Artifact> iter = projectArtifacts.iterator(); iter.hasNext(); ) + { + Artifact artifact = iter.next(); + if (Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) { - //uri of system artifact matches pattern defining list of jars known to contain tlds - list.add(uri.toURL()); + //test to see if the provided artifact was amongst the plugin artifacts + URL jar = artifact.getFile().toURI().toURL(); + if (!pluginJars.contains(jar)) + { + providedJars.add(jar); + if (getLog().isDebugEnabled()) { getLog().debug("Adding provided artifact: "+artifact);} + } + else + { + if (getLog().isDebugEnabled()) { getLog().debug("Skipping provided artifact: "+artifact);} + } } - }; - matcher.match(pattern, artifactUris.toArray(new URI[artifactUris.size()]), false); - - return list; + } + return providedJars; } + + private File getWebXmlFile () throws IOException |