From d7f0bcf2e87010a76251395966dd059fab4da878 Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Thu, 22 Oct 2015 12:37:37 +0200 Subject: [PATCH] Compilation Checker cleanup --- .../mode/java/pdex/CompilationChecker.java | 501 ------------------ .../mode/java/pdex/ErrorCheckerService.java | 175 ++++-- 2 files changed, 139 insertions(+), 537 deletions(-) delete mode 100644 java/src/processing/mode/java/pdex/CompilationChecker.java diff --git a/java/src/processing/mode/java/pdex/CompilationChecker.java b/java/src/processing/mode/java/pdex/CompilationChecker.java deleted file mode 100644 index 7c97dfa31..000000000 --- a/java/src/processing/mode/java/pdex/CompilationChecker.java +++ /dev/null @@ -1,501 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* -Part of the Processing project - http://processing.org -Copyright (c) 2012-15 The Processing Foundation - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software Foundation, Inc. -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -package processing.mode.java.pdex; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.StringTokenizer; - -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.compiler.CharOperation; -import org.eclipse.jdt.core.compiler.IProblem; -import org.eclipse.jdt.core.dom.AST; -import org.eclipse.jdt.core.dom.ASTParser; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.PackageDeclaration; -import org.eclipse.jdt.core.dom.TypeDeclaration; -import org.eclipse.jdt.internal.compiler.ClassFile; -import org.eclipse.jdt.internal.compiler.CompilationResult; -import org.eclipse.jdt.internal.compiler.Compiler; -import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; -import org.eclipse.jdt.internal.compiler.ICompilerRequestor; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; -import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; -import org.eclipse.jdt.internal.compiler.env.INameEnvironment; -import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; -import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; -import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; -import org.eclipse.jface.text.Document; - - -/** - * Provides compilation checking functionality - * @author Manindra Moharana <me@mkmoharana.com> - */ -public class CompilationChecker { - - private class CompilationUnitImpl implements ICompilationUnit { - private CompilationUnit unit; - - CompilationUnitImpl(CompilationUnit unit) { - this.unit = unit; - } - - public char[] getContents() { - char[] contents = null; - try { - Document doc = new Document(); - doc.set(sourceText); - // TextEdit edits = unit.rewrite(doc, null); - // edits.apply(doc); - String sourceCode = doc.get(); - if (sourceCode != null) - contents = sourceCode.toCharArray(); - } catch (Exception e) { - throw new RuntimeException(e); - } - return contents; - } - - public char[] getMainTypeName() { - TypeDeclaration classType = (TypeDeclaration) unit.types().get(0); - return classType.getName().getFullyQualifiedName().toCharArray(); - } - - public char[][] getPackageName() { - String[] names = getSimpleNames(this.unit.getPackage().getName() - .getFullyQualifiedName()); - char[][] packages = new char[names.length][]; - for (int i = 0; i < names.length; ++i) - packages[i] = names[i].toCharArray(); - - return packages; - } - - public char[] getFileName() { - TypeDeclaration classType = (TypeDeclaration) unit.types().get(0); - String name = classType.getName().getFullyQualifiedName() + ".java"; - return name.toCharArray(); - } - - @Override - public boolean ignoreOptionalProblems() { - return false; - } - } - - /** - * ICompilerRequestor implementation - */ - private class CompileRequestorImpl implements ICompilerRequestor { - - private List problems; - - private List classes; - - public CompileRequestorImpl() { - this.problems = new ArrayList(); - this.classes = new ArrayList(); - } - - public void acceptResult(CompilationResult result) { - boolean errors = false; - if (result.hasProblems()) { - IProblem[] problems = result.getProblems(); - for (int i = 0; i < problems.length; i++) { - if (problems[i].isError()) - errors = true; - - this.problems.add(problems[i]); - } - } - if (!errors) { - ClassFile[] classFiles = result.getClassFiles(); - for (int i = 0; i < classFiles.length; i++) - this.classes.add(classFiles[i]); - } - } - - List getProblems() { - return this.problems; - } - -// List getResults() { -// //System.out.println("Calling get results"); -// return this.classes; -// } - } - - /** - * INameEnvironment implementation - */ - private class NameEnvironmentImpl implements INameEnvironment { - - private ICompilationUnit unit; - - private String fullName; - - NameEnvironmentImpl(ICompilationUnit unit) { - this.unit = unit; - this.fullName = CharOperation.toString(this.unit.getPackageName()) + "." - + new String(this.unit.getMainTypeName()); - } - - public NameEnvironmentAnswer findType(char[][] compoundTypeName) { - return findType(CharOperation.toString(compoundTypeName)); - } - - public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { - String fullName = CharOperation.toString(packageName); - if (typeName != null) { - if (fullName.length() > 0) - fullName += "."; - - fullName += new String(typeName); - } - return findType(fullName); - } - - public boolean isPackage(char[][] parentPackageName, char[] packageName) { - String fullName = CharOperation.toString(parentPackageName); - if (packageName != null) { - if (fullName.length() > 0) - fullName += "."; - - fullName += new String(packageName); - } - if (findType(fullName) != null) - return false; - - try { - return (getClassLoader().loadClass(fullName) == null); - } catch (ClassNotFoundException e) { - return true; - } - } - - public void cleanup() { - } - - private NameEnvironmentAnswer findType(String fullName) { - - if (this.fullName.equals(fullName)) - return new NameEnvironmentAnswer(unit, null); - - try { - InputStream is = getClassLoader().getResourceAsStream(fullName - .replace('.', - '/') - + ".class"); - if (is != null) { - // System.out.println("Find type: " + fullName); - byte[] buffer = new byte[8192]; - int bytes = 0; - ByteArrayOutputStream os = new ByteArrayOutputStream(buffer.length); - while ((bytes = is.read(buffer, 0, buffer.length)) > 0) - os.write(buffer, 0, bytes); - - os.flush(); - ClassFileReader classFileReader = new ClassFileReader( - os.toByteArray(), - fullName - .toCharArray(), - true); - return new NameEnvironmentAnswer(classFileReader, null); - } - return null; - } catch (IOException e) { - throw new RuntimeException(e); - } catch (ClassFormatException e) { - throw new RuntimeException(e); - } - } - } - - private URLClassLoader urlClassLoader; - - private ClassLoader getClassLoader() { - if (urlClassLoader != null) { - return urlClassLoader; - } else { - return getClass().getClassLoader(); - } - } - - private void prepareClassLoader(ArrayList jarList) { - URL urls[] = new URL[jarList.size()]; - for (int i = 0; i < urls.length; i++) { - try { - urls[i] = jarList.get(i).toURI().toURL(); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - } - urlClassLoader = new URLClassLoader(urls); - //System.out.println("URL Classloader ready"); - } - - /** - * ClassLoader implementation - */ - /* - private class CustomClassLoader extends ClassLoader { - - private Map classMap; - - CustomClassLoader(ClassLoader parent, List classesList) { - this.classMap = new HashMap(); - for (int i = 0; i < classesList.size(); i++) { - ClassFile classFile = (ClassFile) classesList.get(i); - String className = CharOperation.toString(classFile.getCompoundName()); - this.classMap.put(className, classFile.getBytes()); - } - } - - public Class findClass(String name) throws ClassNotFoundException { - byte[] bytes = (byte[]) this.classMap.get(name); - if (bytes != null) - return defineClass(name, bytes, 0, bytes.length); - - return super.findClass(name); - } - }; - */ - - @SuppressWarnings("unchecked") - private ICompilationUnit generateCompilationUnit() { - ASTParser parser = ASTParser.newParser(AST.JLS8); - try { - parser.setSource("".toCharArray()); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - Map options = JavaCore.getOptions(); - - JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options); - parser.setCompilerOptions(options); - CompilationUnit unit = (CompilationUnit) parser.createAST(null); - unit.recordModifications(); - - AST ast = unit.getAST(); - - // Package statement - // package astexplorer; - - PackageDeclaration packageDeclaration = ast.newPackageDeclaration(); - unit.setPackage(packageDeclaration); - // unit.se - packageDeclaration.setName(ast.newSimpleName(fileName)); - // System.out.println("Filename: " + fileName); - // class declaration - // public class SampleComposite extends Composite { - - TypeDeclaration classType = ast.newTypeDeclaration(); - classType.setInterface(false); - // classType.s - classType.setName(ast.newSimpleName(fileName)); - unit.types().add(classType); - // classType.setSuperclass(ast.newSimpleName("Composite")); - return new CompilationUnitImpl(unit); - } - - static private String fileName = null; //"HelloPeasy"; - - - - private void compileMeQuitely(ICompilationUnit unit, Map compilerSettings) { - - Map settings; - if (compilerSettings == null) { - settings = new HashMap<>(); - - settings.put(CompilerOptions.OPTION_LineNumberAttribute, - CompilerOptions.GENERATE); - settings.put(CompilerOptions.OPTION_SourceFileAttribute, - CompilerOptions.GENERATE); - settings.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6); - settings.put(CompilerOptions.OPTION_SuppressWarnings, - CompilerOptions.DISABLED); - // settings.put(CompilerOptions.OPTION_ReportUnusedImport, - // CompilerOptions.IGNORE); - // settings.put(CompilerOptions.OPTION_ReportMissingSerialVersion, - // CompilerOptions.IGNORE); - // settings.put(CompilerOptions.OPTION_ReportRawTypeReference, - // CompilerOptions.IGNORE); - // settings.put(CompilerOptions.OPTION_ReportUncheckedTypeOperation, - // CompilerOptions.IGNORE); - } else { - settings = compilerSettings; - } - -// CompilerOptions cop = new CompilerOptions(); -// cop.set(settings); - CompileRequestorImpl requestor = new CompileRequestorImpl(); - Compiler compiler = new Compiler(new NameEnvironmentImpl(unit), - DefaultErrorHandlingPolicies - .proceedWithAllProblems(), - new CompilerOptions(settings), requestor, - new DefaultProblemFactory(Locale - .getDefault())); - compiler.compile(new ICompilationUnit[] { unit }); - - List problems = requestor.getProblems(); - prob = new IProblem[problems.size()]; - int count = 0; - for (Iterator it = problems.iterator(); it.hasNext();) { - IProblem problem = it.next(); - prob[count++] = problem; - } - } - - private void compileMeQuitely(ICompilationUnit unit) { - compileMeQuitely(unit, null); - } - - static private String[] getSimpleNames(String qualifiedName) { - StringTokenizer st = new StringTokenizer(qualifiedName, "."); - ArrayList list = new ArrayList(); - while (st.hasMoreTokens()) { - String name = st.nextToken().trim(); - if (!name.equals("*")) - list.add(name); - } - return list.toArray(new String[0]); - } - - public static void main(String[] args) { - ArrayList fl = new ArrayList(); - fl.add(new File( - "/home/quarkninja/Workspaces/processing_workspace/processing/core/library/core.jar")); - CompilationChecker cc = new CompilationChecker(fl); - cc.getErrors("Brightness"); - cc.display(); - } - - public void display() { - boolean error = false; - int errorCount = 0, warningCount = 0, count = 0; - for (int i = 0; i < prob.length; i++) { - IProblem problem = prob[i]; - if (problem == null) - continue; - StringBuilder sb = new StringBuilder(); - sb.append(problem.getMessage()); - sb.append(" | line: "); - sb.append(problem.getSourceLineNumber()); - String msg = sb.toString(); - if (problem.isError()) { - error = true; - msg = "Error: " + msg; - errorCount++; - } else if (problem.isWarning()) { - msg = "Warning: " + msg; - warningCount++; - } - System.out.println(msg); - prob[count++] = problem; - } - - if (!error) { - System.out.println("===================================="); - System.out.println(" Compiled without any errors. "); - System.out.println("===================================="); - } else { - System.out.println("===================================="); - System.out.println(" Compilation failed. You erred man! "); - System.out.println("===================================="); - - } - System.out.print("Total warnings: " + warningCount); - System.out.println(", Total errors: " + errorCount); - } - - IProblem[] prob; - - public IProblem[] getErrors(String name) { - fileName = name; - compileMeQuitely(generateCompilationUnit()); - // System.out.println("getErrors()"); - - return prob; - } - - /** - * Performs compiler error check. - * @param sourceName - name of the class - * @param source - source code - * @param settings - compiler options - * @param classLoader - custom classloader which can load all dependencies - * @return IProblem[] - list of compiler errors and warnings - */ - public IProblem[] getErrors(String sourceName, String source, Map settings, - URLClassLoader classLoader) { - fileName = sourceName; - sourceText = "package " + fileName + ";\n" + source; - if (classLoader != null) - this.urlClassLoader = classLoader; - compileMeQuitely(generateCompilationUnit(), settings); - // System.out.println("getErrors(), Done."); - - return prob; - } - - String sourceText = null; //""; - - - public IProblem[] getErrors(String sourceName, String source) { - return getErrors(sourceName, source, null); - } - - - public IProblem[] getErrors(String sourceName, String source, Map settings) { - fileName = sourceName; - sourceText = "package " + fileName + ";\n" + source; - - compileMeQuitely(generateCompilationUnit(), settings); - // System.out.println("getErrors(), Done."); - return prob; - } - - - public CompilationChecker() { - // System.out.println("Compilation Checker initialized."); - } - - - public CompilationChecker(ArrayList fileList) { - prepareClassLoader(fileList); - // System.out.println("Compilation Checker initialized."); - } -} diff --git a/java/src/processing/mode/java/pdex/ErrorCheckerService.java b/java/src/processing/mode/java/pdex/ErrorCheckerService.java index b1ccf88f1..ea68a0084 100644 --- a/java/src/processing/mode/java/pdex/ErrorCheckerService.java +++ b/java/src/processing/mode/java/pdex/ErrorCheckerService.java @@ -21,14 +21,19 @@ along with this program; if not, write to the Free Software Foundation, Inc. package processing.mode.java.pdex; import java.awt.EventQueue; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -46,12 +51,23 @@ import javax.swing.text.Element; import javax.swing.text.PlainDocument; import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.Compiler; +import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; +import org.eclipse.jdt.internal.compiler.ICompilerRequestor; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; +import org.eclipse.jdt.internal.compiler.env.INameEnvironment; +import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; import processing.app.Library; import processing.app.Messages; @@ -122,12 +138,6 @@ public class ErrorCheckerService { */ protected boolean loadCompClass = true; - /** - * Compilation Checker object. - */ - protected CompilationChecker compilationChecker; - - /** * List of jar files to be present in compilation checker's classpath */ @@ -260,7 +270,6 @@ public class ErrorCheckerService { synchronized (astGenerator) { astGenerator.disposeAllWindows(); } - compilationChecker = null; classLoader = null; System.gc(); Messages.loge("Thread stopped: " + editor.getSketch().getName()); @@ -355,7 +364,6 @@ public class ErrorCheckerService { CompilationUnit compilationUnit; String sourceCode; - int sourceCodeOffset; final List problems = new ArrayList(); @@ -366,12 +374,11 @@ public class ErrorCheckerService { CodeCheckResult result = new CodeCheckResult(); result.sourceCode = preprocessCode(); - result.sourceCodeOffset = 0; char[] sourceCodeArray = result.sourceCode.toCharArray(); - IProblem[] problems; + List problems; {{ // SYNTAX CHECK @@ -391,9 +398,9 @@ public class ErrorCheckerService { result.compilationUnit = (CompilationUnit) parser.createAST(null); // Store errors returned by the ast parser - problems = result.compilationUnit.getProblems(); + problems = Arrays.asList(result.compilationUnit.getProblems()); - if (problems.length == 0) { + if (problems.isEmpty()) { result.syntaxErrors = false; result.containsErrors = false; } else { @@ -404,7 +411,7 @@ public class ErrorCheckerService { }} // No syntax errors, proceed for compilation check, Stage 2. - if (problems.length == 0 && !editor.hasJavaTabs()) { + if (problems.isEmpty() && !editor.hasJavaTabs()) { String sourceCode = xqpreproc.handle(result.sourceCode, programImports); prepareCompilerClasspath(); @@ -422,7 +429,6 @@ public class ErrorCheckerService { result.compilationUnit = (CompilationUnit) parser.createAST(null); result.sourceCode = sourceCode; - result.sourceCodeOffset = 1; // Currently (Sept, 2012) I'm using Java's reflection api to load the // CompilationChecker class(from CompilationChecker.jar) that houses the @@ -441,25 +447,19 @@ public class ErrorCheckerService { classPath = new URL[classpathJars.size()]; classPath = classpathJars.toArray(classPath); - compilationChecker = null; classLoader = null; System.gc(); - // log("CP Len -- " + classpath.length); classLoader = new URLClassLoader(classPath); - compilationChecker = new CompilationChecker(); loadCompClass = false; } -// for(URL cpUrl: classPath) { -// Messages.log("CP jar: " + cpUrl.getPath()); -// } if (compilerSettings == null) { prepareCompilerSetting(); } - problems = compilationChecker.getErrors(className, sourceCode, - compilerSettings, classLoader); + problems = compileAndReturnProblems(className, sourceCode, + compilerSettings, classLoader); } catch (Exception e) { System.err.println("compileCheck() problem." + e); e.printStackTrace(); @@ -483,7 +483,7 @@ public class ErrorCheckerService { continue; } - int sourceLine = problem.getSourceLineNumber() - result.sourceCodeOffset; + int sourceLine = problem.getSourceLineNumber(); int[] a = calculateTabIndexAndLineNumber(sourceLine); Problem p = new Problem(problem, a[0], a[1]); @@ -515,6 +515,50 @@ public class ErrorCheckerService { protected URLClassLoader classLoader; + /** + * Performs compiler error check. + * @param sourceName - name of the class + * @param source - source code + * @param options - compiler options + * @param classLoader - custom classloader which can load all dependencies + * @return list of compiler errors and warnings + */ + static public List compileAndReturnProblems(String sourceName, + String source, + Map options, + URLClassLoader classLoader) { + final List problems = new ArrayList<>(); + + ICompilerRequestor requestor = new ICompilerRequestor() { + @Override + public void acceptResult(CompilationResult cr) { + if (cr.hasProblems()) Collections.addAll(problems, cr.getProblems()); + } + }; + + final char[] contents = source.toCharArray(); + final char[][] packageName = new char[][]{}; + final char[] mainTypeName = sourceName.toCharArray(); + final char[] fileName = (sourceName + ".java").toCharArray(); + + ICompilationUnit unit = new ICompilationUnit() { + @Override public char[] getContents() { return contents; } + @Override public char[][] getPackageName() { return packageName; } + @Override public char[] getMainTypeName() { return mainTypeName; } + @Override public char[] getFileName() { return fileName; } + @Override public boolean ignoreOptionalProblems() { return false; } + }; + + org.eclipse.jdt.internal.compiler.Compiler compiler = + new Compiler(new NameEnvironmentImpl(classLoader), + DefaultErrorHandlingPolicies.proceedWithAllProblems(), + new CompilerOptions(options), + requestor, + new DefaultProblemFactory(Locale.getDefault())); + compiler.compile(new ICompilationUnit[]{unit}); + return problems; + } + /** * Calculates PDE Offsets from Java Offsets for Problems @@ -535,22 +579,11 @@ public class ErrorCheckerService { } pdeTabs.add(tab); } - int pkgNameOffset = ("package " + className + ";\n").length(); - // package name is added only during compile check - if (codeCheckResult.sourceCodeOffset == 0) { - pkgNameOffset = 0; - } for (Problem p : codeCheckResult.problems) { - int prbStart = p.getIProblem().getSourceStart() - pkgNameOffset; - int prbEnd = p.getIProblem().getSourceEnd() - pkgNameOffset; + int prbStart = p.getIProblem().getSourceStart(); + int prbEnd = p.getIProblem().getSourceEnd(); int javaLineNumber = p.getSourceLineNumber() - 1; - // not sure if this is necessary [fry 150808] - javaLineNumber -= codeCheckResult.sourceCodeOffset; - // errors on the first line were setting this to -1 [fry 150808] - if (javaLineNumber < 0) { - javaLineNumber = 0; - } Element lineElement = javaSource.getDefaultRootElement().getElement(javaLineNumber); if (lineElement == null) { @@ -1496,4 +1529,74 @@ public class ErrorCheckerService { public ArrayList getProgramImports() { return programImports; } + + + private static class NameEnvironmentImpl implements INameEnvironment { + + private final ClassLoader classLoader; + + NameEnvironmentImpl(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + + @Override + public NameEnvironmentAnswer findType(char[][] compoundTypeName) { + return readClassFile(CharOperation.toString(compoundTypeName), classLoader); + } + + + @Override + public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { + String fullName = CharOperation.toString(packageName); + if (typeName != null) { + if (fullName.length() > 0) fullName += "."; + fullName += new String(typeName); + } + return readClassFile(fullName, classLoader); + } + + + @Override + public boolean isPackage(char[][] parentPackageName, char[] packageName) { + String fullName = CharOperation.toString(parentPackageName); + if (packageName != null) { + if (fullName.length() > 0) fullName += "."; + fullName += new String(packageName); + } + if (readClassFile(fullName, classLoader) != null) return false; + try { + return (classLoader.loadClass(fullName) == null); + } catch (ClassNotFoundException e) { + return true; + } + } + + + @Override + public void cleanup() { } + + + private static NameEnvironmentAnswer readClassFile(String fullName, ClassLoader classLoader) { + String classFileName = fullName.replace('.', '/') + ".class"; + + InputStream is = classLoader.getResourceAsStream(classFileName); + if (is == null) return null; + + byte[] buffer = new byte[8192]; + ByteArrayOutputStream os = new ByteArrayOutputStream(buffer.length); + try { + int bytes; + while ((bytes = is.read(buffer, 0, buffer.length)) > 0) { + os.write(buffer, 0, bytes); + } + os.flush(); + ClassFileReader classFileReader = + new ClassFileReader(os.toByteArray(), fullName.toCharArray(), true); + return new NameEnvironmentAnswer(classFileReader, null); + } catch (IOException | ClassFormatException e) { + return null; + } + } + } }