ttomcat-1778514358873.zip-extract/_dependencies/maven/com.h2database_h2-2.2.220/org/h2/util/SourceCompiler.java

Path
ttomcat-1778514358873.zip-extract/_dependencies/maven/com.h2database_h2-2.2.220/org/h2/util/SourceCompiler.java
Status
scanned
Type
file
Name
SourceCompiler.java
Extension
.java
Programming language
Java
Mime type
text/x-java
File type
Java source, ASCII text
Tag

      
    
Rootfs path

      
    
Size
21498 (21.0 KB)
MD5
786d8bcea83039dee7667696667f7075
SHA1
1710993fb8bdf7f5f41f61097e579f40157308c8
SHA256
f406dd2306b3245d261e2da5d59d17dec35c5dfcb073cc151a6cc82150dc7eff
SHA512

      
    
SHA1_git
bbb667b748149c243e791cc204feafbac9c81ed4
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
SourceCompiler.java | 21.0 KB |

/* * Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0, * and the EPL 1.0 (https://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.util; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.io.StringReader; import java.io.StringWriter; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URI; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.SecureClassLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import javax.script.Compilable; import javax.script.CompiledScript; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileManager; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.JavaFileObject.Kind; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import org.h2.api.ErrorCode; import org.h2.engine.SysProperties; import org.h2.message.DbException; /** * This class allows to convert source code to a class. It uses one class loader * per class. */ public class SourceCompiler { /** * The "com.sun.tools.javac.Main" (if available). */ static final JavaCompiler JAVA_COMPILER; private static final Class<?> JAVAC_SUN; private static final String COMPILE_DIR = Utils.getProperty("java.io.tmpdir", "."); /** * The class name to source code map. */ final HashMap<String, String> sources = new HashMap<>(); /** * The class name to byte code map. */ final HashMap<String, Class<?>> compiled = new HashMap<>(); /** * The class name to compiled scripts map. */ final Map<String, CompiledScript> compiledScripts = new HashMap<>(); /** * Whether to use the ToolProvider.getSystemJavaCompiler(). */ boolean useJavaSystemCompiler = SysProperties.JAVA_SYSTEM_COMPILER; static { JavaCompiler c; try { c = ToolProvider.getSystemJavaCompiler(); } catch (Exception e) { // ignore c = null; } JAVA_COMPILER = c; Class<?> clazz; try { clazz = Class.forName("com.sun.tools.javac.Main"); } catch (Exception e) { clazz = null; } JAVAC_SUN = clazz; } /** * Set the source code for the specified class. * This will reset all compiled classes. * * @param className the class name * @param source the source code */ public void setSource(String className, String source) { sources.put(className, source); compiled.clear(); } /** * Enable or disable the usage of the Java system compiler. * * @param enabled true to enable */ public void setJavaSystemCompiler(boolean enabled) { this.useJavaSystemCompiler = enabled; } /** * Get the class object for the given name. * * @param packageAndClassName the class name * @return the class * @throws ClassNotFoundException on failure */ public Class<?> getClass(String packageAndClassName) throws ClassNotFoundException { Class<?> compiledClass = compiled.get(packageAndClassName); if (compiledClass != null) { return compiledClass; } String source = sources.get(packageAndClassName); if (isGroovySource(source)) { Class<?> clazz = GroovyCompiler.parseClass(source, packageAndClassName); compiled.put(packageAndClassName, clazz); return clazz; } ClassLoader classLoader = new ClassLoader(getClass().getClassLoader()) { @Override public Class<?> findClass(String name) throws ClassNotFoundException { Class<?> classInstance = compiled.get(name); if (classInstance == null) { String source = sources.get(name); String packageName = null; int idx = name.lastIndexOf('.'); String className; if (idx >= 0) { packageName = name.substring(0, idx); className = name.substring(idx + 1); } else { className = name; } String s = getCompleteSourceCode(packageName, className, source); if (JAVA_COMPILER != null && useJavaSystemCompiler) { classInstance = javaxToolsJavac(packageName, className, s); } else { byte[] data = javacCompile(packageName, className, s); if (data == null) { classInstance = findSystemClass(name); } else { classInstance = defineClass(name, data, 0, data.length); } } compiled.put(name, classInstance); } return classInstance; } }; return classLoader.loadClass(packageAndClassName); } private static boolean isGroovySource(String source) { return source.startsWith("//groovy") || source.startsWith("@groovy"); } private static boolean isJavascriptSource(String source) { return source.startsWith("//javascript"); } private static boolean isRubySource(String source) { return source.startsWith("#ruby"); } /** * Whether the passed source can be compiled using {@link javax.script.ScriptEngineManager}. * * @param source the source to test. * @return <code>true</code> if {@link #getCompiledScript(String)} can be called. */ public static boolean isJavaxScriptSource(String source) { return isJavascriptSource(source) || isRubySource(source); } /** * Get the compiled script. * * @param packageAndClassName the package and class name * @return the compiled script * @throws ScriptException on failure */ public CompiledScript getCompiledScript(String packageAndClassName) throws ScriptException { CompiledScript compiledScript = compiledScripts.get(packageAndClassName); if (compiledScript == null) { String source = sources.get(packageAndClassName); final String lang; if (isJavascriptSource(source)) { lang = "javascript"; } else if (isRubySource(source)) { lang = "ruby"; } else { throw new IllegalStateException("Unknown language for " + source); } final Compilable jsEngine = (Compilable) new ScriptEngineManager().getEngineByName(lang); compiledScript = jsEngine.compile(source); compiledScripts.put(packageAndClassName, compiledScript); } return compiledScript; } /** * Get the first public static method of the given class. * * @param className the class name * @return the method name * @throws ClassNotFoundException on failure */ public Method getMethod(String className) throws ClassNotFoundException { Class<?> clazz = getClass(className); Method[] methods = clazz.getDeclaredMethods(); for (Method m : methods) { int modifiers = m.getModifiers(); if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) { String name = m.getName(); if (!name.startsWith("_") && !m.getName().equals("main")) { return m; } } } return null; } /** * Compile the given class. This method tries to use the class * "com.sun.tools.javac.Main" if available. If not, it tries to run "javac" * in a separate process. * * @param packageName the package name * @param className the class name * @param source the source code * @return the class file */ byte[] javacCompile(String packageName, String className, String source) { Path dir = Paths.get(COMPILE_DIR); if (packageName != null) { dir = dir.resolve(packageName.replace('.', '/')); try { Files.createDirectories(dir); } catch (Exception e) { throw DbException.convert(e); } } Path javaFile = dir.resolve(className + ".java"); Path classFile = dir.resolve(className + ".class"); try { Files.write(javaFile, source.getBytes(StandardCharsets.UTF_8)); Files.deleteIfExists(classFile); if (JAVAC_SUN != null) { javacSun(javaFile); } else { javacProcess(javaFile); } return Files.readAllBytes(classFile); } catch (Exception e) { throw DbException.convert(e); } finally { try { Files.deleteIfExists(javaFile); } catch (IOException e) { } try { Files.deleteIfExists(classFile); } catch (IOException e) { } } } /** * Get the complete source code (including package name, imports, and so * on). * * @param packageName the package name * @param className the class name * @param source the (possibly shortened) source code * @return the full source code */ static String getCompleteSourceCode(String packageName, String className, String source) { if (source.startsWith("package ")) { return source; } StringBuilder buff = new StringBuilder(); if (packageName != null) { buff.append("package ").append(packageName).append("; "); } int endImport = source.indexOf("@CODE"); String importCode = "import java.util.*; " + "import java.math.*; " + "import java.sql.*; "; if (endImport >= 0) { importCode = source.substring(0, endImport); source = source.substring("@CODE".length() + endImport); } buff.append(importCode); buff.append("public class ").append(className).append( " { " + " public static ").append(source).append(" " + "} "); return buff.toString(); } /** * Compile using the standard java compiler. * * @param packageName the package name * @param className the class name * @param source the source code * @return the class */ Class<?> javaxToolsJavac(String packageName, String className, String source) { String fullClassName = packageName + "." + className; StringWriter writer = new StringWriter(); try (JavaFileManager fileManager = new ClassFileManager(JAVA_COMPILER .getStandardFileManager(null, null, null))) { ArrayList<JavaFileObject> compilationUnits = new ArrayList<>(); compilationUnits.add(new StringJavaFileObject(fullClassName, source)); // cannot concurrently compile final boolean ok; synchronized (JAVA_COMPILER) { ok = JAVA_COMPILER.getTask(writer, fileManager, null, null, null, compilationUnits).call(); } String output = writer.toString(); handleSyntaxError(output, (ok? 0: 1)); return fileManager.getClassLoader(null).loadClass(fullClassName); } catch (ClassNotFoundException | IOException e) { throw DbException.convert(e); } } private static void javacProcess(Path javaFile) { exec("javac", "-sourcepath", COMPILE_DIR, "-d", COMPILE_DIR, "-encoding", "UTF-8", javaFile.toAbsolutePath().toString()); } private static int exec(String... args) { ByteArrayOutputStream buff = new ByteArrayOutputStream(); try { ProcessBuilder builder = new ProcessBuilder(); // The javac executable allows some of it's flags // to be smuggled in via environment variables. // But if it sees those flags, it will write out a message // to stderr, which messes up our parsing of the output. builder.environment().remove("JAVA_TOOL_OPTIONS"); builder.command(args); Process p = builder.start(); copyInThread(p.getInputStream(), buff); copyInThread(p.getErrorStream(), buff); p.waitFor(); String output = Utils10.byteArrayOutputStreamToString(buff, StandardCharsets.UTF_8); handleSyntaxError(output, p.exitValue()); return p.exitValue(); } catch (Exception e) { throw DbException.convert(e); } } private static void copyInThread(final InputStream in, final OutputStream out) { new Task() { @Override public void call() throws IOException { IOUtils.copy(in, out); } }.execute(); } private static synchronized void javacSun(Path javaFile) { PrintStream old = System.err; ByteArrayOutputStream buff = new ByteArrayOutputStream(); try { System.setErr(new PrintStream(buff, false, "UTF-8")); Method compile; compile = JAVAC_SUN.getMethod("compile", String[].class); Object javac = JAVAC_SUN.getDeclaredConstructor().newInstance(); // Bugfix: Here we should check exit status value instead of parsing javac output text. // Because of the output text is different in different locale environment. // @since 2018-07-20 little-pan final Integer status = (Integer)compile.invoke(javac, (Object) new String[] { "-sourcepath", COMPILE_DIR, // "-Xlint:unchecked", "-d", COMPILE_DIR, "-encoding", "UTF-8", javaFile.toAbsolutePath().toString() }); String output = Utils10.byteArrayOutputStreamToString(buff, StandardCharsets.UTF_8); handleSyntaxError(output, status); } catch (Exception e) { throw DbException.convert(e); } finally { System.setErr(old); } } private static void handleSyntaxError(String output, int exitStatus) { if(0 == exitStatus){ return; } boolean syntaxError = false; final BufferedReader reader = new BufferedReader(new StringReader(output)); try { for (String line; (line = reader.readLine()) != null;) { if (line.endsWith("warning") || line.endsWith("warnings")) { // ignore summary line } else if (line.startsWith("Note:") || line.startsWith("warning:")) { // just a warning (e.g. unchecked or unsafe operations) } else { syntaxError = true; break; } } } catch (IOException ignored) { // exception ignored } if (syntaxError) { output = StringUtils.replaceAll(output, COMPILE_DIR, ""); throw DbException.get(ErrorCode.SYNTAX_ERROR_1, output); } } /** * Access the Groovy compiler using reflection, so that we do not gain a * compile-time dependency unnecessarily. */ private static final class GroovyCompiler { private static final Object LOADER; private static final Throwable INIT_FAIL_EXCEPTION; static { Object loader = null; Throwable initFailException = null; try { // Create an instance of ImportCustomizer Class<?> importCustomizerClass = Class.forName( "org.codehaus.groovy.control.customizers.ImportCustomizer"); Object importCustomizer = Utils.newInstance( "org.codehaus.groovy.control.customizers.ImportCustomizer"); // Call the method ImportCustomizer.addImports(String[]) String[] importsArray = { "java.sql.Connection", "java.sql.Types", "java.sql.ResultSet", "groovy.sql.Sql", "org.h2.tools.SimpleResultSet" }; Utils.callMethod(importCustomizer, "addImports", new Object[] { importsArray }); // Call the method // CompilerConfiguration.addCompilationCustomizers( // ImportCustomizer...) Object importCustomizerArray = Array.newInstance(importCustomizerClass, 1); Array.set(importCustomizerArray, 0, importCustomizer); Object configuration = Utils.newInstance( "org.codehaus.groovy.control.CompilerConfiguration"); Utils.callMethod(configuration, "addCompilationCustomizers", importCustomizerArray); ClassLoader parent = GroovyCompiler.class.getClassLoader(); loader = Utils.newInstance( "groovy.lang.GroovyClassLoader", parent, configuration); } catch (Exception ex) { initFailException = ex; } LOADER = loader; INIT_FAIL_EXCEPTION = initFailException; } public static Class<?> parseClass(String source, String packageAndClassName) { if (LOADER == null) { throw new RuntimeException( "Compile fail: no Groovy jar in the classpath", INIT_FAIL_EXCEPTION); } try { Object codeSource = Utils.newInstance("groovy.lang.GroovyCodeSource", source, packageAndClassName + ".groovy", "UTF-8"); Utils.callMethod(codeSource, "setCachable", false); return (Class<?>) Utils.callMethod( LOADER, "parseClass", codeSource); } catch (Exception e) { throw new RuntimeException(e); } } } /** * An in-memory java source file object. */ static class StringJavaFileObject extends SimpleJavaFileObject { private final String sourceCode; public StringJavaFileObject(String className, String sourceCode) { super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); this.sourceCode = sourceCode; } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return sourceCode; } } /** * An in-memory java class object. */ static class JavaClassObject extends SimpleJavaFileObject { private final ByteArrayOutputStream out = new ByteArrayOutputStream(); public JavaClassObject(String name, Kind kind) { super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); } public byte[] getBytes() { return out.toByteArray(); } @Override public OutputStream openOutputStream() throws IOException { return out; } } /** * An in-memory class file manager. */ static class ClassFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> { /** * We use map because there can be nested, anonymous etc classes. */ Map<String, JavaClassObject> classObjectsByName = new HashMap<>(); private SecureClassLoader classLoader = new SecureClassLoader() { @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] bytes = classObjectsByName.get(name).getBytes(); return super.defineClass(name, bytes, 0, bytes.length); } }; public ClassFileManager(StandardJavaFileManager standardManager) { super(standardManager); } @Override public ClassLoader getClassLoader(Location location) { return this.classLoader; } @Override public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException { JavaClassObject classObject = new JavaClassObject(className, kind); classObjectsByName.put(className, classObject); return classObject; } } }
Detected license expression

      
    
Detected license expression (SPDX)

      
    
Percentage of license text
0.62
Copyrights
- end_line: 2
  copyright: Copyright 2004-2023 H2 Group. Multiple-Licensed
  start_line: 2
Holders
- holder: H2 Group. Multiple-Licensed
  end_line: 2
  start_line: 2
Authors

      
    
License expression License clue details
(mpl-2.0 OR epl-1.0) AND proprietary-license {'score': 20.37, 'matcher': '3-seq', 'end_line': 3, 'rule_url': 'https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/mpl-2.0_or_epl-1.0_and_proprietary-license_2.RULE', 'from_file': None, 'start_line': 2, 'matched_text': ' * Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0,\n * and the EPL 1.0 (https://h2database.com/html/license.html).', 'match_coverage': 20.37, 'matched_length': 11, 'rule_relevance': 100, 'rule_identifier': 'mpl-2.0_or_epl-1.0_and_proprietary-license_2.RULE', 'license_expression': '(mpl-2.0 OR epl-1.0) AND proprietary-license', 'license_expression_spdx': '(MPL-2.0 OR EPL-1.0) AND LicenseRef-scancode-proprietary-license'}
URL Start line End line
https://h2database.com/html/license.html 3 3
Package URL License Primary language
pkg:osgi/com.h2database.source@2.2.220