This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.commons.compiler-2.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-compiler.git
commit 64fdb9e597f9f62deadfbcea526cf20c7d81e80d Author: Carsten Ziegeler <[email protected]> AuthorDate: Fri Mar 19 14:50:41 2010 +0000 SLING-1451 : Clean up compiler API and use classloading infrastructure git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/commons/compiler@925247 13f79535-47bb-0310-9956-ffa450edef68 --- NOTICE | 2 +- pom.xml | 16 +- .../apache/sling/commons/compiler/ClassWriter.java | 31 -- .../{CompileUnit.java => CompilationUnit.java} | 20 +- .../commons/compiler/CompilerEnvironment.java | 26 -- .../sling/commons/compiler/ErrorHandler.java | 22 +- .../sling/commons/compiler/JavaCompiler.java | 18 +- .../org/apache/sling/commons/compiler/Options.java | 71 +++- .../commons/compiler/impl/EclipseJavaCompiler.java | 370 ++++++++++++++------- src/main/resources/META-INF/NOTICE | 2 +- .../commons/compiler/impl/CompilerJava5Test.java | 146 +++----- src/test/resources/Java5Test | 2 +- 12 files changed, 420 insertions(+), 306 deletions(-) diff --git a/NOTICE b/NOTICE index 3341854..76ff9f0 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache Sling Java Compiler -Copyright 2008-2009 The Apache Software Foundation +Copyright 2008-2010 The Apache Software Foundation Apache Sling is based on source code originally developed by Day Software (http://www.day.com/). diff --git a/pom.xml b/pom.xml index 3c2906d..cc1b3e1 100644 --- a/pom.xml +++ b/pom.xml @@ -59,7 +59,7 @@ !org.eclipse.*,* </Import-Package> <Export-Package> - org.apache.sling.commons.compiler;version=1.0.0 + org.apache.sling.commons.compiler;version=2.0.0 </Export-Package> <Private-Package> org.apache.sling.commons.compiler.impl @@ -88,6 +88,18 @@ <dependencies> <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.scr.annotations</artifactId> + <version>1.2.0</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.commons.classloader</artifactId> + <version>1.1.0</version> + <scope>provided</scope> + </dependency> + <dependency> <groupId>org.eclipse.jdt</groupId> <artifactId>core</artifactId> <version>3.3.0-v_771</version> @@ -111,12 +123,10 @@ <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> - <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> - <scope>test</scope> </dependency> </dependencies> </project> diff --git a/src/main/java/org/apache/sling/commons/compiler/ClassWriter.java b/src/main/java/org/apache/sling/commons/compiler/ClassWriter.java deleted file mode 100644 index 46dc92a..0000000 --- a/src/main/java/org/apache/sling/commons/compiler/ClassWriter.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ -package org.apache.sling.commons.compiler; - -/** - * - */ -public interface ClassWriter { - - /** - * - * @param className - * @param data - * @throws Exception - */ - void write(String className, byte[] data) throws Exception; -} diff --git a/src/main/java/org/apache/sling/commons/compiler/CompileUnit.java b/src/main/java/org/apache/sling/commons/compiler/CompilationUnit.java similarity index 70% rename from src/main/java/org/apache/sling/commons/compiler/CompileUnit.java rename to src/main/java/org/apache/sling/commons/compiler/CompilationUnit.java index 92723ca..fd060c2 100644 --- a/src/main/java/org/apache/sling/commons/compiler/CompileUnit.java +++ b/src/main/java/org/apache/sling/commons/compiler/CompilationUnit.java @@ -16,16 +16,26 @@ */ package org.apache.sling.commons.compiler; -public interface CompileUnit { +import java.io.IOException; +import java.io.Reader; - String getSourceFileName(); +/** + * This interface describes a compilation unit - usually a java class. + * @since 2.0 + */ +public interface CompilationUnit { - char[] getSourceFileContents(); + /** + * Return an input stream for the contents. + * The compiler will close this stream in all cases! + */ + Reader getSource() + throws IOException; /** * Returns the name of the top level public type. - * + * This name includes the package. * @return the name of the top level public type. */ - String getMainTypeName(); + String getMainClassName(); } diff --git a/src/main/java/org/apache/sling/commons/compiler/CompilerEnvironment.java b/src/main/java/org/apache/sling/commons/compiler/CompilerEnvironment.java deleted file mode 100644 index cddb7f7..0000000 --- a/src/main/java/org/apache/sling/commons/compiler/CompilerEnvironment.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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. - */ -package org.apache.sling.commons.compiler; - -public interface CompilerEnvironment { - - byte[] findClass(String className) throws Exception; - - boolean isPackage(String packageName); - - void cleanup(); -} diff --git a/src/main/java/org/apache/sling/commons/compiler/ErrorHandler.java b/src/main/java/org/apache/sling/commons/compiler/ErrorHandler.java index 40cf544..cebb678 100644 --- a/src/main/java/org/apache/sling/commons/compiler/ErrorHandler.java +++ b/src/main/java/org/apache/sling/commons/compiler/ErrorHandler.java @@ -17,25 +17,25 @@ package org.apache.sling.commons.compiler; /** - * + * The error handler for the compilation. */ public interface ErrorHandler { /** - * - * @param msg - * @param sourceFile - * @param line - * @param position + * Notify the handler of an error. + * @param msg The error message. + * @param sourceFile The source file the error occured in + * @param line The source line number + * @param position The column */ void onError(String msg, String sourceFile, int line, int position); /** - * - * @param msg - * @param sourceFile - * @param line - * @param position + * Notify the handler of a warning. + * @param msg The warning message. + * @param sourceFile The source file the warning occured in + * @param line The source line number + * @param position The column */ void onWarning(String msg, String sourceFile, int line, int position); } diff --git a/src/main/java/org/apache/sling/commons/compiler/JavaCompiler.java b/src/main/java/org/apache/sling/commons/compiler/JavaCompiler.java index 67240f0..033b027 100644 --- a/src/main/java/org/apache/sling/commons/compiler/JavaCompiler.java +++ b/src/main/java/org/apache/sling/commons/compiler/JavaCompiler.java @@ -17,12 +17,20 @@ package org.apache.sling.commons.compiler; /** - * The <code>JavaCompiler</code> provides platform independant Java Compilation - * support. + * The <code>JavaCompiler</code> provides platform independant Java + * compilation support. */ public interface JavaCompiler { - boolean compile(CompileUnit[] units, CompilerEnvironment env, - ClassWriter classWriter, ErrorHandler errorHandler, - Options options); + /** + * Compile the compilation units. + * @param units The compilation units. + * @param errorHandler The error handler - this object is mandatory + * @param options The compilation options - this object is optional + * @return <code>true</code> if compilation was successful + * @since 2.0 + */ + boolean compile(CompilationUnit[] units, + ErrorHandler errorHandler, + Options options); } diff --git a/src/main/java/org/apache/sling/commons/compiler/Options.java b/src/main/java/org/apache/sling/commons/compiler/Options.java index 23b0625..366f6f0 100644 --- a/src/main/java/org/apache/sling/commons/compiler/Options.java +++ b/src/main/java/org/apache/sling/commons/compiler/Options.java @@ -16,7 +16,21 @@ */ package org.apache.sling.commons.compiler; -public class Options { +import java.util.HashMap; + +/** + * Options for the compilation process. + */ +public class Options extends HashMap<String, Object> { + + /** The key for the source version. */ + public static final String KEY_SOURCE_VERSION = "sourceVersion"; + + /** The key for the target version. */ + public static final String KEY_TARGET_VERSION = "targetVersion"; + + /** The key for the generate debug info flag. */ + public static final String KEY_GENERATE_DEBUG_INFO = "generateDebugInfo"; public static final String VERSION_RUNTIME = null; public static final String VERSION_1_1 = "1.1"; @@ -24,33 +38,54 @@ public class Options { public static final String VERSION_1_3 = "1.3"; public static final String VERSION_1_4 = "1.4"; public static final String VERSION_1_5 = "1.5"; - public static final String VERSION_1_6 = "1.6"; + public static final String VERSION_1_6 = "1.6"; + public static final String VERSION_1_7 = "1.7"; - protected String sourceVersion; - protected boolean generateDebugInfo; + /** The key for the class loader writer. + * By default the registered class loader writer service is used. */ + public static final String KEY_CLASS_LOADER_WRITER = "classLoaderWriter"; + /** + * The key for the class loader. + * By default the commons dynamic classloader is used. + * This property overrides the classloader and ignores the + * {@link #KEY_ADDITIONAL_CLASS_LOADER} completly! + */ + public static final String KEY_CLASS_LOADER = "classLoader"; + + /** + * The key for the additional class loader. + * By default the commons dynamic classloader is used. + * If this property is used and the {@link #KEY_CLASS_LOADER} + * property is not defined, a classloader with the dynamic + * class loader (default) and the class loader specified here + * is used. + */ + public static final String KEY_ADDITIONAL_CLASS_LOADER = "classLoader"; + + /** + * Default options with the following presets: + * - generate debug info : true + */ public Options() { - this(VERSION_RUNTIME, true); - } - - public Options(String sourceVersion, boolean generateDebugInfo) { - this.sourceVersion = sourceVersion; - this.generateDebugInfo = generateDebugInfo; + this.put(KEY_GENERATE_DEBUG_INFO, true); } public String getSourceVersion() { - return sourceVersion; + return (String) this.get(KEY_SOURCE_VERSION); } - public void setSourceVersion(String sourceVersion) { - this.sourceVersion = sourceVersion; + /** + * @since 2.0 + */ + public String getTargetVersion() { + return (String) this.get(KEY_TARGET_VERSION); } public boolean isGenerateDebugInfo() { - return generateDebugInfo; - } - - public void setGenerateDebugInfo(boolean generateDebugInfo) { - this.generateDebugInfo = generateDebugInfo; + if ( this.get(KEY_GENERATE_DEBUG_INFO) != null ) { + return (Boolean) this.get(KEY_GENERATE_DEBUG_INFO); + } + return false; } } diff --git a/src/main/java/org/apache/sling/commons/compiler/impl/EclipseJavaCompiler.java b/src/main/java/org/apache/sling/commons/compiler/impl/EclipseJavaCompiler.java index 8dc6c1a..bac1a1d 100644 --- a/src/main/java/org/apache/sling/commons/compiler/impl/EclipseJavaCompiler.java +++ b/src/main/java/org/apache/sling/commons/compiler/impl/EclipseJavaCompiler.java @@ -17,16 +17,22 @@ package org.apache.sling.commons.compiler.impl; import java.io.BufferedReader; -import java.io.CharArrayReader; +import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.net.URL; import java.util.HashMap; import java.util.Locale; import java.util.Map; -import org.apache.sling.commons.compiler.ClassWriter; -import org.apache.sling.commons.compiler.CompileUnit; -import org.apache.sling.commons.compiler.CompilerEnvironment; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.commons.classloader.ClassLoaderWriter; +import org.apache.sling.commons.classloader.DynamicClassLoaderManager; +import org.apache.sling.commons.compiler.CompilationUnit; import org.apache.sling.commons.compiler.ErrorHandler; import org.apache.sling.commons.compiler.JavaCompiler; import org.apache.sling.commons.compiler.Options; @@ -48,122 +54,194 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * The <code>EclipseJavaCompiler</code> provides platform independant Java Compilation - * support using the Eclipse Java Compiler (org.eclipse.jdt). + * The <code>EclipseJavaCompiler</code> provides platform independant + * Java compilation support using the Eclipse Java Compiler (org.eclipse.jdt). * - * @scr.component metatype="no" - * @scr.service interface="org.apache.sling.commons.compiler.JavaCompiler" */ +@Component +@Service(value=JavaCompiler.class) public class EclipseJavaCompiler implements JavaCompiler { /** Logger instance */ - private static final Logger log = LoggerFactory.getLogger(EclipseJavaCompiler.class); + private final Logger logger = LoggerFactory.getLogger(EclipseJavaCompiler.class); - // the static problem factory - private static IProblemFactory PROBLEM_FACTORY = - new DefaultProblemFactory(Locale.getDefault()); + @Reference + private ClassLoaderWriter classLoaderWriter; - public EclipseJavaCompiler() { - } + @Reference + private DynamicClassLoaderManager dynamicClassLoaderManager; + + private ClassLoader classLoader; + + /** the static problem factory */ + private IProblemFactory problemFactory = new DefaultProblemFactory(Locale.getDefault()); + + /** the static policy. */ + private final IErrorHandlingPolicy policy = DefaultErrorHandlingPolicies.proceedWithAllProblems(); /** - * @see org.apache.sling.commons.compiler.JavaCompiler#compile(org.apache.sling.commons.compiler.CompileUnit[], org.apache.sling.commons.compiler.CompilerEnvironment, org.apache.sling.commons.compiler.ClassWriter, org.apache.sling.commons.compiler.ErrorHandler, org.apache.sling.commons.compiler.Options) + * Bind the class load provider. + * @param repositoryClassLoaderProvider the new provider */ - public boolean compile(CompileUnit[] units, CompilerEnvironment env, - ClassWriter classWriter, ErrorHandler errorHandler, - Options options) { + protected void bindDynamicClassLoaderManager(final DynamicClassLoaderManager rclp) { + if ( this.classLoader != null ) { + this.ungetClassLoader(); + } + this.getClassLoader(rclp); + } - IErrorHandlingPolicy policy = - DefaultErrorHandlingPolicies.proceedWithAllProblems(); + /** + * Unbind the class loader provider. + * @param repositoryClassLoaderProvider the old provider + */ + protected void unbindDynamicClassLoaderManager(final DynamicClassLoaderManager rclp) { + if ( this.dynamicClassLoaderManager == rclp ) { + this.ungetClassLoader(); + } + } - // output for non-error log messages - PrintWriter logWriter = null; + /** + * Get the class loader + */ + private void getClassLoader(final DynamicClassLoaderManager rclp) { + this.dynamicClassLoaderManager = rclp; + this.classLoader = rclp.getDynamicClassLoader(); + } - if (options == null) { - options = new Options(); - } + /** + * Unget the class loader + */ + private void ungetClassLoader() { + this.classLoader = null; + this.dynamicClassLoaderManager = null; + } - Map<String, String> props = new HashMap<String, String>(); + /** + * @see org.apache.sling.commons.compiler.JavaCompiler#compile(org.apache.sling.commons.compiler.CompilationUnit[], org.apache.sling.commons.compiler.ErrorHandler, org.apache.sling.commons.compiler.Options) + */ + public boolean compile(final CompilationUnit[] units, + final ErrorHandler errorHandler, + final Options compileOptions) { + // make sure we have an options object (to avoid null checks all over the place) + final Options options = (compileOptions != null ? compileOptions : new Options()); + + // create properties for the settings object + final Map<String, String> props = new HashMap<String, String>(); if (options.isGenerateDebugInfo()) { props.put("org.eclipse.jdt.core.compiler.debug.localVariable", "generate"); props.put("org.eclipse.jdt.core.compiler.debug.lineNumber", "generate"); props.put("org.eclipse.jdt.core.compiler.debug.sourceFile", "generate"); } - String sourceVersion = options.getSourceVersion(); - if (sourceVersion != null) { - props.put("org.eclipse.jdt.core.compiler.source", sourceVersion); - //options.put("org.eclipse.jdt.core.compiler.compliance", sourceVersion); - //options.put("org.eclipse.jdt.core.compiler.codegen.targetPlatform", sourceVersion); + if (options.getSourceVersion() != null) { + props.put("org.eclipse.jdt.core.compiler.source", options.getSourceVersion()); + //props.put("org.eclipse.jdt.core.compiler.compliance", options.getSourceVersion()); + //props.put("org.eclipse.jdt.core.compiler.codegen.targetPlatform", options.getSourceVersion()); } - //options.put("org.eclipse.jdt.core.encoding", "UTF8"); - CompilerOptions settings = new CompilerOptions(props); - - CompileContext context = new CompileContext(units, env, errorHandler, classWriter); + if (options.getTargetVersion() != null) { + props.put("org.eclipse.jdt.core.compiler.codegen.targetPlatform", options.getTargetVersion()); + } + props.put("org.eclipse.jdt.core.encoding", "UTF8"); + + // create the settings + final CompilerOptions settings = new CompilerOptions(props); + logger.debug("Compiling with settings {}.", settings); + + // classloader + final ClassLoader loader; + if ( options.get(Options.KEY_CLASS_LOADER) != null ) { + loader = (ClassLoader)options.get(Options.KEY_CLASS_LOADER); + } else if ( options.get(Options.KEY_ADDITIONAL_CLASS_LOADER) != null ) { + final ClassLoader additionalClassLoader = (ClassLoader)options.get(Options.KEY_ADDITIONAL_CLASS_LOADER); + loader = new ClassLoader(this.classLoader) { + protected Class<?> findClass(String name) + throws ClassNotFoundException { + return additionalClassLoader.loadClass(name); + } - if (log.isDebugEnabled()) { - log.debug(settings.toString()); + protected URL findResource(String name) { + return additionalClassLoader.getResource(name); + } + }; + } else { + loader = this.classLoader; } - org.eclipse.jdt.internal.compiler.Compiler compiler = + // classloader writer + final ClassLoaderWriter writer = (options.get(Options.KEY_CLASS_LOADER_WRITER) != null ? + (ClassLoaderWriter)options.get(Options.KEY_CLASS_LOADER_WRITER) : this.classLoaderWriter); + + // create the context + final CompileContext context = new CompileContext(units, errorHandler, writer, loader); + + // create the compiler + final org.eclipse.jdt.internal.compiler.Compiler compiler = new org.eclipse.jdt.internal.compiler.Compiler( context, - policy, + this.policy, settings, context, - PROBLEM_FACTORY, - logWriter); + this.problemFactory, + null); - compiler.compile(context.sourceUnits()); + // compile + compiler.compile(context.getSourceUnits()); - context.cleanup(); - - return !context.hadErrors; + return !context.hasErrors; } //--------------------------------------------------------< inner classes > - private class CompileContext implements ICompilerRequestor, INameEnvironment { - - boolean hadErrors; - HashMap<String,ICompilationUnit> compUnits; + private class CompileContext implements ICompilerRequestor, INameEnvironment, ErrorHandler { - ErrorHandler errorHandler; - ClassWriter classWriter; + private final Map<String,ICompilationUnit> compUnits; - CompilerEnvironment compEnv; + private final ErrorHandler errorHandler; + private final ClassLoaderWriter classLoaderWriter; + private final ClassLoader classLoader; - CompileContext(CompileUnit[] units, - CompilerEnvironment compEnv, - ErrorHandler errorHandler, - ClassWriter classWriter) { + /** Flag indicating if we have an error. */ + private boolean hasErrors = false; - compUnits = new HashMap<String,ICompilationUnit>(units.length); + public CompileContext(final CompilationUnit[] units, + final ErrorHandler errorHandler, + final ClassLoaderWriter classWriter, + final ClassLoader classLoader) { + this.compUnits = new HashMap<String,ICompilationUnit>(); for (int i = 0; i < units.length; i++) { - CompilationUnitAdapter cua = new CompilationUnitAdapter(units[i]); + CompilationUnitAdapter cua = new CompilationUnitAdapter(units[i], this); char[][] compoundName = CharOperation.arrayConcat(cua.getPackageName(), cua.getMainTypeName()); - compUnits.put(CharOperation.toString(compoundName), new CompilationUnitAdapter(units[i])); + this.compUnits.put(CharOperation.toString(compoundName), new CompilationUnitAdapter(units[i], this)); } - this.compEnv = compEnv; this.errorHandler = errorHandler; - this.classWriter = classWriter; - hadErrors = false; + this.classLoaderWriter = classWriter; + this.classLoader = classLoader; } - ICompilationUnit[] sourceUnits() { + /** + * @see org.apache.sling.commons.compiler.ErrorHandler#onError(java.lang.String, java.lang.String, int, int) + */ + public void onError(String msg, String sourceFile, int line, int position) { + this.errorHandler.onError(msg, sourceFile, line, position); + this.hasErrors = true; + } + + /** + * @see org.apache.sling.commons.compiler.ErrorHandler#onWarning(java.lang.String, java.lang.String, int, int) + */ + public void onWarning(String msg, String sourceFile, int line, int position) { + this.errorHandler.onWarning(msg, sourceFile, line, position); + } + + public ICompilationUnit[] getSourceUnits() { return compUnits.values().toArray( new ICompilationUnit[compUnits.size()]); } - //---------------------------------------------------< ICompilerRequestor > /** - * {@inheritDoc} + * @see org.eclipse.jdt.internal.compiler.ICompilerRequestor#acceptResult(org.eclipse.jdt.internal.compiler.CompilationResult) */ public void acceptResult(CompilationResult result) { - if (result.hasErrors()) { - hadErrors = true; - } - if (result.hasProblems()) { CategorizedProblem[] problems = result.getProblems(); for (int i = 0; i < problems.length; i++) { @@ -174,11 +252,11 @@ public class EclipseJavaCompiler implements JavaCompiler { int pos = problem.getSourceStart(); if (problem.isError()) { - errorHandler.onError(msg, fileName, line, pos); + this.onError(msg, fileName, line, pos); } else if (problem.isWarning()) { - errorHandler.onWarning(msg, fileName, line, pos); + this.onWarning(msg, fileName, line, pos); } else { - log.debug("unknown problem category: " + problem.toString()); + logger.debug("unknown problem category: {}", problem); } } } @@ -187,16 +265,15 @@ public class EclipseJavaCompiler implements JavaCompiler { ClassFile classFile = classFiles[i]; String className = CharOperation.toString(classFile.getCompoundName()); try { - classWriter.write(className, classFile.getBytes()); - } catch (Exception e) { - log.error("failed to persist class " + className, e); + this.write(className, classFile.getBytes()); + } catch (IOException e) { + this.onError("Unable to write class file: " + e.getMessage(), className, 0, 0); } } } - //-------------------------------------------------< INameEnvironment > /** - * {@inheritDoc} + * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#findType(char[][]) */ public NameEnvironmentAnswer findType(char[][] compoundTypeName) { // check 1st if type corresponds with any of current compilation units @@ -208,7 +285,7 @@ public class EclipseJavaCompiler implements JavaCompiler { // locate the class through the class loader try { - byte[] bytes = compEnv.findClass(CharOperation.toString(compoundTypeName)); + byte[] bytes = this.findClass(CharOperation.toString(compoundTypeName)); if (bytes == null) { return null; } @@ -221,78 +298,145 @@ public class EclipseJavaCompiler implements JavaCompiler { } /** - * {@inheritDoc} + * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#findType(char[], char[][]) */ public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { return findType(CharOperation.arrayConcat(packageName, typeName)); } /** - * {@inheritDoc} + * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#isPackage(char[][], char[]) */ public boolean isPackage(char[][] parentPackageName, char[] packageName) { String fqn = CharOperation.toString( CharOperation.arrayConcat(parentPackageName, packageName)); - return compUnits.get(fqn) == null && compEnv.isPackage(fqn); + return compUnits.get(fqn) == null && this.isPackage(fqn); } /** - * {@inheritDoc} + * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#cleanup() */ public void cleanup() { - compEnv.cleanup(); + // nothing to do + } + + /** + * Write the classfile + */ + private void write(String name, byte[] data) throws IOException { + final OutputStream os = this.classLoaderWriter.getOutputStream('/' + name.replace('.', '/') + ".class"); + os.write(data); + os.close(); + } + + private boolean isPackage(String result) { + String resourceName = result.replace('.', '/') + ".class"; + if ( resourceName.startsWith("/") ) { + resourceName = resourceName.substring(1); + } + final InputStream is = this.classLoader.getResourceAsStream(resourceName); + if ( is != null ) { + try { + is.close(); + } catch (IOException ignore) {} + } + return is == null; + } + + private byte[] findClass(String name) throws Exception { + final String resourceName = name.replace('.', '/') + ".class"; + final InputStream is = this.classLoader.getResourceAsStream(resourceName); + if (is != null) { + try { + byte[] buf = new byte[8192]; + ByteArrayOutputStream baos = new ByteArrayOutputStream(buf.length); + int count; + while ((count = is.read(buf, 0, buf.length)) > 0) { + baos.write(buf, 0, count); + } + baos.flush(); + return baos.toByteArray(); + } finally { + try { + is.close(); + } catch (IOException ignore) {} + } + } + return null; } } private class CompilationUnitAdapter implements ICompilationUnit { - CompileUnit compUnit; - char[][] packageName; + private final ErrorHandler errorHandler; + private final CompilationUnit compUnit; + private final String mainTypeName; + private final String packageName; - CompilationUnitAdapter(CompileUnit compUnit) { + public CompilationUnitAdapter(final CompilationUnit compUnit, final ErrorHandler errorHandler) { this.compUnit = compUnit; + this.errorHandler = errorHandler; + final int pos = compUnit.getMainClassName().lastIndexOf('.'); + if ( pos == -1 ) { + this.packageName = ""; + this.mainTypeName = compUnit.getMainClassName(); + } else { + this.packageName = compUnit.getMainClassName().substring(0, pos); + this.mainTypeName = compUnit.getMainClassName().substring(pos + 1); + } } - String extractPackageName(char[] contents) { - BufferedReader reader = new BufferedReader(new CharArrayReader(contents)); + /** + * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getContents() + */ + public char[] getContents() { + Reader fr = null; try { - String line; - while ((line = reader.readLine()) != null) { - line = line.trim(); - if (line.startsWith("package")) { - line = line.substring("package".length()); - line = line.substring(0, line.lastIndexOf(';')); - return line.trim(); + fr = this.compUnit.getSource(); + final Reader reader = new BufferedReader(fr); + try { + char[] chars = new char[8192]; + StringBuilder buf = new StringBuilder(); + int count; + while ((count = reader.read(chars, 0, chars.length)) > 0) { + buf.append(chars, 0, count); } + final char[] result = new char[buf.length()]; + buf.getChars(0, result.length, result, 0); + return result; + } finally { + reader.close(); } } catch (IOException e) { - // should never get here... + this.errorHandler.onError("Unable to read source file " + this.compUnit.getMainClassName() + " : " + e.getMessage(), + this.compUnit.getMainClassName(), 0, 0); + return null; + } finally { + if ( fr != null ) { + try { fr.close(); } catch (IOException ignore) {} + } } - - // no package declaration found - return ""; - } - - //-------------------------------------------------< ICompilationUnit > - - public char[] getContents() { - return compUnit.getSourceFileContents(); } + /** + * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getMainTypeName() + */ public char[] getMainTypeName() { - return compUnit.getMainTypeName().toCharArray(); + return this.mainTypeName.toCharArray(); } + /** + * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getPackageName() + */ public char[][] getPackageName() { - if (packageName == null) { - String s = extractPackageName(compUnit.getSourceFileContents()); - packageName = CharOperation.splitOn('.', s.toCharArray()); - } - return packageName; + return CharOperation.splitOn('.', this.packageName.toCharArray()); } + /** + * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName() + */ public char[] getFileName() { - return compUnit.getSourceFileName().toCharArray(); + return (this.mainTypeName + ".java").toCharArray(); } } } diff --git a/src/main/resources/META-INF/NOTICE b/src/main/resources/META-INF/NOTICE index d7953a3..03ad88a 100644 --- a/src/main/resources/META-INF/NOTICE +++ b/src/main/resources/META-INF/NOTICE @@ -1,5 +1,5 @@ Apache Sling Java Compiler -Copyright 2008-2009 The Apache Software Foundation +Copyright 2008-2010 The Apache Software Foundation Apache Sling is based on source code originally developed by Day Software (http://www.day.com/). diff --git a/src/test/java/org/apache/sling/commons/compiler/impl/CompilerJava5Test.java b/src/test/java/org/apache/sling/commons/compiler/impl/CompilerJava5Test.java index 598eb33..c42b9b6 100644 --- a/src/test/java/org/apache/sling/commons/compiler/impl/CompilerJava5Test.java +++ b/src/test/java/org/apache/sling/commons/compiler/impl/CompilerJava5Test.java @@ -17,17 +17,16 @@ package org.apache.sling.commons.compiler.impl; import java.io.ByteArrayOutputStream; -import java.io.CharArrayWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.Reader; import junit.framework.TestCase; -import org.apache.sling.commons.compiler.ClassWriter; -import org.apache.sling.commons.compiler.CompileUnit; -import org.apache.sling.commons.compiler.CompilerEnvironment; +import org.apache.sling.commons.classloader.ClassLoaderWriter; +import org.apache.sling.commons.compiler.CompilationUnit; import org.apache.sling.commons.compiler.ErrorHandler; import org.apache.sling.commons.compiler.Options; @@ -35,13 +34,18 @@ import org.apache.sling.commons.compiler.Options; * Test case for java 5 support */ public class CompilerJava5Test extends TestCase - implements CompilerEnvironment, ErrorHandler, ClassWriter { + implements ErrorHandler, ClassLoaderWriter { public void testJava5Support() throws Exception { String sourceFile = "Java5Test"; - CompileUnit unit = createCompileUnit(sourceFile); - new EclipseJavaCompiler().compile(new CompileUnit[]{unit}, this, this, this, new Options(Options.VERSION_1_5, true)); + CompilationUnit unit = createCompileUnit(sourceFile); + final Options options = new Options(); + options.put(Options.KEY_SOURCE_VERSION, Options.VERSION_1_5); + options.put(Options.KEY_CLASS_LOADER_WRITER, this); + options.put(Options.KEY_CLASS_LOADER, this.getClass().getClassLoader()); + + assertTrue(new EclipseJavaCompiler().compile(new CompilationUnit[]{unit}, this, options)); } //---------------------------------------------------------< ErrorHandler > @@ -54,102 +58,62 @@ public class CompilerJava5Test extends TestCase System.out.println("Warning in " + sourceFile + ", line " + line + ", pos. " + position + ": " + msg); } - //--------------------------------------------------< CompilerEnvironment > - - public byte[] findClass(String className) throws Exception { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - InputStream in = cl.getResourceAsStream(className.replace('.', '/') + ".class"); - if (in == null) { - return null; - } - ByteArrayOutputStream out = new ByteArrayOutputStream(0x7fff); - - try { - byte[] buffer = new byte[0x1000]; - int read = 0; - while ((read = in.read(buffer)) > 0) { - out.write(buffer, 0, read); - } - } finally { - //out.close(); - in.close(); - } + //----------------------------------------------------------< ClassLoaderWriter > - return out.toByteArray(); - } + //--------------------------------------------------------< misc. helpers > - public char[] findSource(String className) throws Exception { - return new char[0]; - } + private CompilationUnit createCompileUnit(final String sourceFile) throws Exception { + return new CompilationUnit() { - public boolean isPackage(String packageName) { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - InputStream in = cl.getResourceAsStream(packageName.replace('.', '/') + ".class"); - if (in != null) { - try { - in.close(); - } catch (IOException ignore) { + /** + * @see org.apache.sling.commons.compiler.CompilationUnit#getMainClassName() + */ + public String getMainClassName() { + return "org.apache.sling.commons.compiler.test." + sourceFile; } - return false; - } - return true; - } - public void cleanup() { + /** + * @see org.apache.sling.commons.compiler.CompilationUnit#getSource() + */ + public Reader getSource() throws IOException { + InputStream in = getClass().getClassLoader().getResourceAsStream(sourceFile); + return new InputStreamReader(in, "UTF-8"); + } + }; } - //----------------------------------------------------------< ClassWriter > - - public void write(String className, byte[] data) throws Exception { - // nothing to do + /** + * @see org.apache.sling.commons.classloader.ClassLoaderWriter#delete(java.lang.String) + */ + public boolean delete(String path) { + return false; } - //--------------------------------------------------------< misc. helpers > - - private CompileUnit createCompileUnit(final String sourceFile) throws Exception { - final char[] chars = readTextResource(sourceFile); - - return new CompileUnit() { - - public String getSourceFileName() { - return sourceFile; - } + /** + * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getInputStream(java.lang.String) + */ + public InputStream getInputStream(String path) throws IOException { + return null; + } - public char[] getSourceFileContents() { - return chars; - } + /** + * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getLastModified(java.lang.String) + */ + public long getLastModified(String path) { + return 0; + } - public String getMainTypeName() { - String className; - int pos = sourceFile.lastIndexOf(".java"); - if (pos != -1) { - className = sourceFile.substring(0, pos).trim(); - } else { - className = sourceFile.trim(); - } - pos = className.lastIndexOf('/'); - return (pos == -1) ? className : className.substring(pos); - } - }; + /** + * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getOutputStream(java.lang.String) + */ + public OutputStream getOutputStream(String path) { + return new ByteArrayOutputStream(); } - private char[] readTextResource(String resourcePath) throws IOException { - InputStream in = getClass().getClassLoader().getResourceAsStream(resourcePath); - if (in == null) { - throw new IOException("resource not found"); - } - Reader reader = new InputStreamReader(in); - CharArrayWriter writer = new CharArrayWriter(0x7fff); - try { - char[] buffer = new char[0x1000]; - int read = 0; - while ((read = reader.read(buffer)) > 0) { - writer.write(buffer, 0, read); - } - return writer.toCharArray(); - } finally { - //writer.close(); - reader.close(); - } + /** + * @see org.apache.sling.commons.classloader.ClassLoaderWriter#rename(java.lang.String, java.lang.String) + */ + public boolean rename(String oldPath, String newPath) { + return false; } } diff --git a/src/test/resources/Java5Test b/src/test/resources/Java5Test index 83bf4ac..44658bc 100644 --- a/src/test/resources/Java5Test +++ b/src/test/resources/Java5Test @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sling.commons.compiler.test ; +package org.apache.sling.commons.compiler.test; import java.util.List; -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
