From b22586f0109a2c12592e67452a406cc3c699bba7 Mon Sep 17 00:00:00 2001 From: Renato Athaydes Date: Thu, 25 Apr 2024 23:00:12 +0200 Subject: [PATCH] Ensure all code runs in "empty" classloader. Hide JGrab's classes. Better error handling. --- .../jgrab/runner/EmptyClassLoaderContext.java | 20 ++++++++++++++++++ .../jgrab/runner/JGrabClassLoaderContext.java | 10 +++------ .../com/athaydes/jgrab/runner/JGrabError.java | 4 ++++ .../athaydes/jgrab/runner/JGrabRunner.java | 21 +++++++++---------- .../com/athaydes/jgrab/test/JGrabTest.java | 21 +++++++++++++++---- 5 files changed, 54 insertions(+), 22 deletions(-) create mode 100644 jgrab-runner/src/main/java/com/athaydes/jgrab/runner/EmptyClassLoaderContext.java diff --git a/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/EmptyClassLoaderContext.java b/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/EmptyClassLoaderContext.java new file mode 100644 index 0000000..9cb3f99 --- /dev/null +++ b/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/EmptyClassLoaderContext.java @@ -0,0 +1,20 @@ +package com.athaydes.jgrab.runner; + +import com.athaydes.osgiaas.api.env.ClassLoaderContext; + +import java.util.Collection; +import java.util.List; + +enum EmptyClassLoaderContext implements ClassLoaderContext { + INSTANCE; + + @Override + public ClassLoader getClassLoader() { + return ClassLoader.getPlatformClassLoader(); + } + + @Override + public Collection getClassesIn( String s ) { + return List.of(); + } +} diff --git a/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabClassLoaderContext.java b/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabClassLoaderContext.java index 074faff..bbb77df 100644 --- a/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabClassLoaderContext.java +++ b/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabClassLoaderContext.java @@ -7,11 +7,7 @@ import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; +import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; @@ -30,7 +26,7 @@ class JGrabClassLoaderContext implements ClassLoaderContext { URL[] jarUrls = new URL[ dependencyJars.size() ]; this.jars = new ArrayList<>( dependencyJars.size() ); - for (int i = 0; i < dependencyJars.size(); i++) { + for ( int i = 0; i < dependencyJars.size(); i++ ) { File jar = dependencyJars.get( i ); try { @@ -41,7 +37,7 @@ class JGrabClassLoaderContext implements ClassLoaderContext { } } - this.dependenciesClassLoader = new URLClassLoader( jarUrls ); + this.dependenciesClassLoader = new URLClassLoader( jarUrls, ClassLoader.getPlatformClassLoader() ); } @Override diff --git a/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabError.java b/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabError.java index e807a3a..c317166 100644 --- a/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabError.java +++ b/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabError.java @@ -8,4 +8,8 @@ public class JGrabError extends RuntimeException { public JGrabError( String message ) { super( message ); } + + public JGrabError( Throwable cause ) { + super( cause ); + } } diff --git a/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabRunner.java b/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabRunner.java index 6de5bf8..92b2aa3 100644 --- a/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabRunner.java +++ b/jgrab-runner/src/main/java/com/athaydes/jgrab/runner/JGrabRunner.java @@ -7,7 +7,6 @@ import com.athaydes.jgrab.daemon.JGrabDaemon; import com.athaydes.jgrab.jbuild.JBuildGrabber; import com.athaydes.osgiaas.api.env.ClassLoaderContext; -import com.athaydes.osgiaas.javac.internal.DefaultClassLoaderContext; import com.athaydes.osgiaas.javac.internal.compiler.OsgiaasJavaCompilerService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -120,7 +119,7 @@ public static void populateClassLoaderCache( Collection classpaths ) private static ClassLoaderContext classLoaderFor( Classpath classpath ) { if ( classpath.isEmpty() ) { - return DefaultClassLoaderContext.INSTANCE; + return EmptyClassLoaderContext.INSTANCE; } return classLoaderCache.computeIfAbsent( classpath.hash, ignore -> new JGrabClassLoaderContext( classpath.resolvedArtifacts ) ); @@ -153,8 +152,7 @@ private static void runJavaSnippet( String snippet, ClassLoaderContext classLoad System.out.println( result ); } } catch ( Throwable t ) { - System.err.println( "Problem running Java snippet: " + t ); - t.printStackTrace(); + throw new JGrabError( t ); } } @@ -172,16 +170,14 @@ private static void runJavaClass( JavaCode javaCode, Runnable runnable = ( Runnable ) compiledClass.getDeclaredConstructor().newInstance(); runnable.run(); } catch ( Throwable t ) { - System.err.println( "Problem running Java class: " + t ); - t.printStackTrace(); + throw new JGrabError( t ); } } else { try { Method method = compiledClass.getMethod( "main", String[].class ); method.invoke( compiledClass, ( Object ) args ); } catch ( Throwable t ) { - System.err.println( "Problem running Java class: " + t ); - t.printStackTrace(); + throw new JGrabError( t ); } } } @@ -201,11 +197,14 @@ private static void run( String currentDir, String[] args ) { run( currentDir, options ); } } catch ( JGrabError e ) { - System.err.println( e.getMessage() ); + if ( e.getMessage() != null ) { + logger.error( "{}", e.getMessage() ); + } else { + logger.error( "JGrab Error", e.getCause() ); + } System.exit( 1 ); } catch ( Exception e ) { - System.err.println( "Unable to run Java class due to " + e ); - e.printStackTrace(); + logger.error( "Unexpected Error", e ); System.exit( 2 ); } } diff --git a/jgrab-test/src/test/java/com/athaydes/jgrab/test/JGrabTest.java b/jgrab-test/src/test/java/com/athaydes/jgrab/test/JGrabTest.java index 1ef554e..73d9511 100644 --- a/jgrab-test/src/test/java/com/athaydes/jgrab/test/JGrabTest.java +++ b/jgrab-test/src/test/java/com/athaydes/jgrab/test/JGrabTest.java @@ -7,6 +7,7 @@ import static com.athaydes.jgrab.test.JGrabTestRunner.jgrab; import static java.util.stream.Collectors.toList; +import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.startsWith; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -32,7 +33,7 @@ public void runRunnableClass() throws Exception { "Ola class jline.console.ConsoleReader" ), result.stdout.lines().collect( toList() ) ); - assertEquals( result.stderr.trim(), "" ); + assertEquals( "", result.stderr.trim() ); } @Test @@ -44,7 +45,7 @@ public void runScript() throws Exception { assertEquals( "Result: " + result, List.of( "5" ), result.stdout.lines().collect( toList() ) ); - assertEquals( result.stderr.trim(), "" ); + assertEquals( "", result.stderr.trim() ); } @Test @@ -52,13 +53,25 @@ public void runVersion() throws Exception { var result = jgrab( "-v" ); result.assertOk(); assertThat( result.stdout, startsWith( "JGrab Version" ) ); - assertEquals( result.stderr.trim(), "" ); + assertEquals( "", result.stderr.trim() ); } @Test public void unknownOption() throws Exception { var result = jgrab( "-f" ); result.assertCode( 1 ); - assertEquals( result.stderr.trim(), "Unknown option: -f" ); + assertEquals( "[main] ERROR com.athaydes.jgrab.runner.JGrabRunner - " + + "Unknown option: -f", result.stderr.trim() ); + } + + @Test + public void codeCannotSeeJGrabClasses() throws Exception { + var result = jgrab( "-e", "com.athaydes.jgrab.runner.JGrabRunner.class" ); + result.assertCode( 1 ); + assertThat( result.stderr.trim(), + containsString( + "java.lang.NoClassDefFoundError: " + + "com/athaydes/jgrab/runner/JGrabRunner" ) ); + assertEquals( "", result.stdout.trim() ); } }