From 1ae99f4639ad022ee8450923d9559a413309c211 Mon Sep 17 00:00:00 2001 From: Romain Manni-Bucau Date: Thu, 8 Sep 2022 09:23:24 +0200 Subject: [PATCH] #322, enable to control the exec:java interaction with JVM classloader more finely --- src/it/projects/github322/invoker.properties | 1 + src/it/projects/github322/pom.xml | 43 ++++++++++++ .../codehaus/mojo/exec/it/github322/Main.java | 16 +++++ src/it/projects/github322/verify.groovy | 20 ++++++ src/it/projects/mexec-29/invoker.properties | 2 +- .../org/codehaus/mojo/exec/ExecJavaMojo.java | 19 ++++++ .../mojo/exec/URLClassLoaderBuilder.java | 66 ++++++++++++++----- 7 files changed, 148 insertions(+), 19 deletions(-) create mode 100644 src/it/projects/github322/invoker.properties create mode 100644 src/it/projects/github322/pom.xml create mode 100644 src/it/projects/github322/src/main/java/org/codehaus/mojo/exec/it/github322/Main.java create mode 100644 src/it/projects/github322/verify.groovy diff --git a/src/it/projects/github322/invoker.properties b/src/it/projects/github322/invoker.properties new file mode 100644 index 00000000..5f52c5a0 --- /dev/null +++ b/src/it/projects/github322/invoker.properties @@ -0,0 +1 @@ +invoker.goals = clean compile exec:java diff --git a/src/it/projects/github322/pom.xml b/src/it/projects/github322/pom.xml new file mode 100644 index 00000000..78201fbc --- /dev/null +++ b/src/it/projects/github322/pom.xml @@ -0,0 +1,43 @@ + + 4.0.0 + + + org.codehaus.mojo.exec.it + parent + 0.1 + + + org.cb.maven.plugins.exec + github322 + 0.1 + + + + xml-apis + xml-apis + 1.4.01 + + + + + + + org.codehaus.mojo + exec-maven-plugin + @pom.version@ + + + test + + java + + + + + org.codehaus.mojo.exec.it.github322.Main + + + + + + diff --git a/src/it/projects/github322/src/main/java/org/codehaus/mojo/exec/it/github322/Main.java b/src/it/projects/github322/src/main/java/org/codehaus/mojo/exec/it/github322/Main.java new file mode 100644 index 00000000..ffae7ac2 --- /dev/null +++ b/src/it/projects/github322/src/main/java/org/codehaus/mojo/exec/it/github322/Main.java @@ -0,0 +1,16 @@ +package org.codehaus.mojo.exec.it.github322; + +import javax.xml.transform.sax.SAXTransformerFactory; + +public class Main { + public static void main(final String... args) { + System.out.println( + "Main Result: <" + + ( + SAXTransformerFactory.class.getProtectionDomain().getCodeSource() != null ? + SAXTransformerFactory.class.getProtectionDomain().getCodeSource().getLocation() : + null + ) + + ">"); + } +} diff --git a/src/it/projects/github322/verify.groovy b/src/it/projects/github322/verify.groovy new file mode 100644 index 00000000..a534c78c --- /dev/null +++ b/src/it/projects/github322/verify.groovy @@ -0,0 +1,20 @@ +/* + * 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. + */ + +new IntegrationBase().checkExistenceAndContentOfAFile(new File( basedir, "build.log" ), [ "Main Result: " ]) diff --git a/src/it/projects/mexec-29/invoker.properties b/src/it/projects/mexec-29/invoker.properties index ba31fa59..b4a42cc1 100644 --- a/src/it/projects/mexec-29/invoker.properties +++ b/src/it/projects/mexec-29/invoker.properties @@ -1,4 +1,4 @@ invoker.goals = clean verify invoker.debug = true -invoker.buildResult = failure +invoker.buildResult = success diff --git a/src/main/java/org/codehaus/mojo/exec/ExecJavaMojo.java b/src/main/java/org/codehaus/mojo/exec/ExecJavaMojo.java index f9444883..21b973d7 100644 --- a/src/main/java/org/codehaus/mojo/exec/ExecJavaMojo.java +++ b/src/main/java/org/codehaus/mojo/exec/ExecJavaMojo.java @@ -206,6 +206,23 @@ public class ExecJavaMojo @Parameter private List classpathFilenameExclusions; + /** + * Additional packages to load from the jvm even if a classpath dependency matches. + * + * @since 3.1.1 + */ + @Parameter + private List forcedJvmPackages; + + /** + * Additional packages to NOT load from the jvm even if it is in a flat classpath. + * Can enable to reproduce a webapp behavior for example where library is loaded over the JVM. + * + * @since 3.1.1 + */ + @Parameter + private List excludedJvmPackages; + /** * Execute goal. * @@ -591,6 +608,8 @@ private URLClassLoader getClassLoader() .setLogger( getLog() ) .setPaths( classpathURLs ) .setExclusions( classpathFilenameExclusions ) + .setForcedJvmPackages( forcedJvmPackages ) + .setExcludedJvmPackages( excludedJvmPackages ) .build(); } catch ( NullPointerException | IOException e ) diff --git a/src/main/java/org/codehaus/mojo/exec/URLClassLoaderBuilder.java b/src/main/java/org/codehaus/mojo/exec/URLClassLoaderBuilder.java index 95762e29..5589b6d3 100644 --- a/src/main/java/org/codehaus/mojo/exec/URLClassLoaderBuilder.java +++ b/src/main/java/org/codehaus/mojo/exec/URLClassLoaderBuilder.java @@ -44,6 +44,8 @@ */ class URLClassLoaderBuilder { + private List forcedJvmPackages; + private List excludedJvmPackages; private Log logger; private Collection paths; private Collection exclusions; @@ -57,6 +59,18 @@ static URLClassLoaderBuilder builder() return new URLClassLoaderBuilder(); } + URLClassLoaderBuilder setExcludedJvmPackages(List excludedJvmPackages ) + { + this.excludedJvmPackages = excludedJvmPackages; + return this; + } + + URLClassLoaderBuilder setForcedJvmPackages(List forcedJvmPackages ) + { + this.forcedJvmPackages = forcedJvmPackages; + return this; + } + URLClassLoaderBuilder setLogger(Log logger ) { this.logger = logger; @@ -99,7 +113,7 @@ URLClassLoader build() throws IOException } } - return new ExecJavaClassLoader( urls.toArray( new URL[0] ) ); + return new ExecJavaClassLoader( urls.toArray( new URL[0] ), forcedJvmPackages, excludedJvmPackages ); } // child first strategy @@ -118,11 +132,15 @@ private static class ExecJavaClassLoader extends URLClassLoader } private final String jre; + private final List forcedJvmPackages; + private final List excludedJvmPackages; - public ExecJavaClassLoader(URL[] urls ) + public ExecJavaClassLoader(URL[] urls, List forcedJvmPackages, List excludedJvmPackages ) { super(urls); - jre = getJre(); + this.jre = getJre(); + this.forcedJvmPackages = forcedJvmPackages; + this.excludedJvmPackages = excludedJvmPackages; } @Override @@ -334,64 +352,77 @@ private boolean postLoad( boolean resolve, Class clazz ) return false; } - // not all jvm classes, for ex "javax" can be overriden so don't list it here + // not all jvm classes, for ex "javax" can be overridden so don't list it them all here (javax.resource for ex) private boolean isDirectJvmClass(final String name) { + if (excludedJvmPackages != null && excludedJvmPackages.stream().anyMatch( name::startsWith )) + { + return false; + } + if (name.startsWith( "java." ) ) { return true; } - if ( name.startsWith( "sun." ) ) + else if (name.startsWith( "javax." ) ) + { + final String sub = name.substring( "javax.".length() ); + if ( sub.startsWith( "xml." ) ) + { + return true; + } + } + else if ( name.startsWith( "sun." ) ) { return true; } - if ( name.startsWith( "jdk." ) ) + else if ( name.startsWith( "jdk." ) ) { return true; } - if ( name.startsWith( "oracle." ) ) + else if ( name.startsWith( "oracle." ) ) { return true; } - if ( name.startsWith( "javafx." ) ) + else if ( name.startsWith( "javafx." ) ) { return true; } - if ( name.startsWith( "netscape." ) ) + else if ( name.startsWith( "netscape." ) ) { return true; } - if ( name.startsWith( "org." ) ) + else if ( name.startsWith( "org." ) ) { final String sub = name.substring( "org.".length() ); if ( sub.startsWith( "w3c.dom." ) ) { return true; } - if ( sub.startsWith( "omg." ) ) + else if ( sub.startsWith( "omg." ) ) { return true; } - if ( sub.startsWith( "xml.sax." ) ) + else if ( sub.startsWith( "xml.sax." ) ) { return true; } - if ( sub.startsWith( "ietf.jgss." ) ) + else if ( sub.startsWith( "ietf.jgss." ) ) { return true; } - if ( sub.startsWith( "jcp.xml.dsig.internal." ) ) + else if ( sub.startsWith( "jcp.xml.dsig.internal." ) ) { return true; } } - if ( name.startsWith( "com." ) ) + else if ( name.startsWith( "com." ) ) { final String sub = name.substring( "com.".length() ); if ( sub.startsWith( "oracle." ) ) { return true; } - if ( sub.startsWith( "sun." ) ) + else if ( sub.startsWith( "sun." ) ) { final String subSun = sub.substring( "sun.".length() ); if ( subSun.startsWith( "accessibility." ) ) @@ -494,10 +525,9 @@ private boolean isDirectJvmClass(final String name) { { return true; } - return false; } } - return false; + return forcedJvmPackages != null && forcedJvmPackages.stream().anyMatch( name::startsWith ); } private class FilteringUrlEnum implements Enumeration