All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrewrite.java.JavaUnrestrictedClassLoader Maven / Gradle / Ivy

There is a newer version: 8.40.2
Show newest version
/*
 * Copyright 2022 the original author or authors.
 * 

* Licensed 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 *

* https://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. */ package org.openrewrite.java; import org.jspecify.annotations.Nullable; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.List; /** * Rewrite's JavaParser is reliant on java's compiler internal classes that are now encapsulated within Java's * module system. Starting in Java 17, the JVM now enforces strong encapsulation of these internal classes and * default behavior is to throw a security exception when attempting to use these internal classes. This classloader * circumvents these security restrictions by isolating Rewrite's Java 17 parser implementation classes and then * loading any of the internal classes directly from the .jmod files. *

* NOTE: Any classes in the package "org.openrewrite.java.isolated" will be loaded into this isolated classloader. */ public class JavaUnrestrictedClassLoader extends ClassLoader { static { ClassLoader.registerAsParallelCapable(); } final List modules; public JavaUnrestrictedClassLoader(ClassLoader parentClassloader) { super(parentClassloader); //A list of modules to load internal classes from final FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/")); modules = Arrays.asList( fs.getPath("modules", "jdk.compiler"), fs.getPath("modules", "java.compiler"), fs.getPath("modules", "java.base") ); } @Override public Class loadClass(String name) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c != null) { return c; } String internalName = name.replace('.', '/') + ".class"; //If the class is in the package "org.openrewrite.java.isolated", load it from this class loader. Class _class = loadIsolatedClass(name); if (_class != null) { return _class; } //Otherwise look for internal classes in the list of modules. if (name.startsWith("com.sun") || name.startsWith("sun")) { try { for (Path path : modules) { Path classFile = path.resolve(internalName); if (Files.exists(classFile)) { byte[] bytes = Files.readAllBytes(classFile); return defineClass(name, bytes, 0, bytes.length); } } } catch (IOException e) { throw new RuntimeException(e); } } return super.loadClass(name); } } @Override public @Nullable URL getResource(String name) { try { for (Path path : modules) { Path classFile = path.resolve(name); if (Files.exists(classFile)) { return classFile.toUri().toURL(); } } } catch (IOException e) { throw new RuntimeException(e); } return super.getResource(name); } private @Nullable Class loadIsolatedClass(String className) { if (!className.startsWith("org.openrewrite.java.isolated")) { return null; } String internalName = className.replace('.', '/') + ".class"; URL url = JavaParser.class.getClassLoader().getResource(internalName); if (url == null) { return null; } try (InputStream stream = url.openStream()) { ByteArrayOutputStream classBytes = new ByteArrayOutputStream(); byte[] bytes = new byte[4096]; int bytesRead; while ((bytesRead = stream.read(bytes)) > 0) { classBytes.write(bytes, 0, bytesRead); } return defineClass(className, classBytes.toByteArray(), 0, classBytes.size()); } catch (IOException e) { throw new RuntimeException(e); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy