Skip to content

Commit

Permalink
#322, enable to control the exec:java interaction with JVM classloade…
Browse files Browse the repository at this point in the history
…r more finely (#337)


Co-authored-by: Slawomir Jaranowski <s.jaranowski@gmail.com>
  • Loading branch information
rmannibucau and slawekjaranowski authored Oct 22, 2024
1 parent 582aed0 commit 47eac15
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 83 deletions.
1 change: 1 addition & 0 deletions src/it/projects/github322/invoker.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invoker.goals = clean compile exec:java
43 changes: 43 additions & 0 deletions src/it/projects/github322/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<project>
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.codehaus.mojo.exec.it</groupId>
<artifactId>parent</artifactId>
<version>0.1</version>
</parent>

<groupId>org.cb.maven.plugins.exec</groupId>
<artifactId>github322</artifactId>
<version>0.1</version>

<dependencies>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>@pom.version@</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>org.codehaus.mojo.exec.it.github322.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -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
) +
">");
}
}
21 changes: 21 additions & 0 deletions src/it/projects/github322/verify.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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.
*/

File log = new File(basedir, 'build.log')
assert log.text.contains( 'Main Result: <null>')
22 changes: 20 additions & 2 deletions src/main/java/org/codehaus/mojo/exec/ExecJavaMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,23 @@ public class ExecJavaMojo extends AbstractExecMojo {
@Parameter
private List<String> classpathFilenameExclusions;

/**
* Additional packages to load from the jvm even if a classpath dependency matches.
*
* @since 3.5.0
*/
@Parameter
private List<String> 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.5.0
*/
@Parameter
private List<String> excludedJvmPackages;

/**
* Whether to try and prohibit the called Java program from terminating the JVM (and with it the whole Maven build)
* by calling {@link System#exit(int)}. When active, loaded classes will replace this call by a custom callback.
Expand Down Expand Up @@ -678,12 +695,13 @@ private URLClassLoader getClassLoader() throws MojoExecutionException {
this.addRelevantPluginDependenciesToClasspath(classpathURLs);
this.addRelevantProjectDependenciesToClasspath(classpathURLs);
this.addAdditionalClasspathElements(classpathURLs);

try {
final URLClassLoaderBuilder builder = URLClassLoaderBuilder.builder()
.setLogger(getLog())
.setPaths(classpathURLs)
.setExclusions(classpathFilenameExclusions);
.setExclusions(classpathFilenameExclusions)
.setForcedJvmPackages(forcedJvmPackages)
.setExcludedJvmPackages(excludedJvmPackages);
if (blockSystemExit) {
builder.setTransformer(new BlockExitTransformer());
}
Expand Down
150 changes: 69 additions & 81 deletions src/main/java/org/codehaus/mojo/exec/URLClassLoaderBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@
import static java.util.Arrays.asList;

/**
*
* @author Robert Scholte
* @since 3.0.0
*/
class URLClassLoaderBuilder {
private Log logger;
private List<String> forcedJvmPackages;
private List<String> excludedJvmPackages;
private Collection<Path> paths;
private Collection<String> exclusions;
private ClassFileTransformer transformer;
Expand All @@ -58,6 +59,16 @@ static URLClassLoaderBuilder builder() {
return new URLClassLoaderBuilder();
}

URLClassLoaderBuilder setExcludedJvmPackages(List<String> excludedJvmPackages) {
this.excludedJvmPackages = excludedJvmPackages;
return this;
}

URLClassLoaderBuilder setForcedJvmPackages(List<String> forcedJvmPackages) {
this.forcedJvmPackages = forcedJvmPackages;
return this;
}

public URLClassLoaderBuilder setTransformer(final ClassFileTransformer transformer) {
this.transformer = transformer;
return this;
Expand Down Expand Up @@ -96,7 +107,7 @@ URLClassLoader build() throws IOException {
}
}

return new ExecJavaClassLoader(urls.toArray(new URL[0]), transformer, logger);
return new ExecJavaClassLoader(urls.toArray(new URL[0]), transformer, forcedJvmPackages, excludedJvmPackages);
}

// child first strategy
Expand All @@ -110,14 +121,20 @@ private static class ExecJavaClassLoader extends URLClassLoader {
}

private final String jre;
private final Log logger;
private final ClassFileTransformer transformer;

public ExecJavaClassLoader(final URL[] urls, final ClassFileTransformer transformer, final Log logger) {
private final List<String> forcedJvmPackages;
private final List<String> excludedJvmPackages;

public ExecJavaClassLoader(
URL[] urls,
ClassFileTransformer transformer,
List<String> forcedJvmPackages,
List<String> excludedJvmPackages) {
super(urls);
this.jre = getJre();
this.logger = logger;
this.transformer = transformer;
this.forcedJvmPackages = forcedJvmPackages;
this.excludedJvmPackages = excludedJvmPackages;
}

@Override
Expand Down Expand Up @@ -307,130 +324,101 @@ 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.")) {
return true;
}
if (subSun.startsWith("activation.")) {
} else if (subSun.startsWith("activation.")) {
return true;
}
if (subSun.startsWith("awt.")) {
} else if (subSun.startsWith("awt.")) {
return true;
}
if (subSun.startsWith("beans.")) {
} else if (subSun.startsWith("beans.")) {
return true;
}
if (subSun.startsWith("corba.se.")) {
} else if (subSun.startsWith("corba.se.")) {
return true;
}
if (subSun.startsWith("demo.jvmti.")) {
} else if (subSun.startsWith("demo.jvmti.")) {
return true;
}
if (subSun.startsWith("image.codec.jpeg.")) {
} else if (subSun.startsWith("image.codec.jpeg.")) {
return true;
}
if (subSun.startsWith("imageio.")) {
} else if (subSun.startsWith("imageio.")) {
return true;
}
if (subSun.startsWith("istack.internal.")) {
} else if (subSun.startsWith("istack.internal.")) {
return true;
}
if (subSun.startsWith("java.")) {
} else if (subSun.startsWith("java.")) {
return true;
}
if (subSun.startsWith("java_cup.")) {
} else if (subSun.startsWith("java_cup.")) {
return true;
}
if (subSun.startsWith("jmx.")) {
} else if (subSun.startsWith("jmx.")) {
return true;
}
if (subSun.startsWith("jndi.")) {
} else if (subSun.startsWith("jndi.")) {
return true;
}
if (subSun.startsWith("management.")) {
} else if (subSun.startsWith("management.")) {
return true;
}
if (subSun.startsWith("media.sound.")) {
} else if (subSun.startsWith("media.sound.")) {
return true;
}
if (subSun.startsWith("naming.internal.")) {
} else if (subSun.startsWith("naming.internal.")) {
return true;
}
if (subSun.startsWith("net.")) {
} else if (subSun.startsWith("net.")) {
return true;
}
if (subSun.startsWith("nio.")) {
} else if (subSun.startsWith("nio.")) {
return true;
}
if (subSun.startsWith("org.")) {
} else if (subSun.startsWith("org.")) {
return true;
}
if (subSun.startsWith("rmi.rmid.")) {
} else if (subSun.startsWith("rmi.rmid.")) {
return true;
}
if (subSun.startsWith("rowset.")) {
} else if (subSun.startsWith("rowset.")) {
return true;
}
if (subSun.startsWith("security.")) {
} else if (subSun.startsWith("security.")) {
return true;
}
if (subSun.startsWith("swing.")) {
} else if (subSun.startsWith("swing.")) {
return true;
}
if (subSun.startsWith("tracing.")) {
} else if (subSun.startsWith("tracing.")) {
return true;
}
if (subSun.startsWith("xml.internal.")) {
} else if (subSun.startsWith("xml.internal.")) {
return true;
}
return false;
}
}
return false;
return forcedJvmPackages != null && forcedJvmPackages.stream().anyMatch(name::startsWith);
}

private class FilteringUrlEnum implements Enumeration<URL> {
Expand Down

0 comments on commit 47eac15

Please sign in to comment.