Index: src/main/org/codehaus/groovy/tools/javac/JavacExternalCompilerPlugin.java =================================================================== --- src/main/org/codehaus/groovy/tools/javac/JavacExternalCompilerPlugin.java Sat Mar 07 10:50:52 EET 2009 +++ src/main/org/codehaus/groovy/tools/javac/JavacExternalCompilerPlugin.java Sat Mar 07 10:50:52 EET 2009 @@ -0,0 +1,32 @@ +package org.codehaus.groovy.tools.javac; + +import org.codehaus.groovy.control.CompilationUnit; +import org.codehaus.groovy.control.CompilerConfiguration; + +import java.util.Collections; +import java.util.Set; +import java.util.LinkedHashSet; +import java.io.File; + +public class JavacExternalCompilerPlugin extends ExternalCompilerPlugin { + public JavacExternalCompilerPlugin() { + super("javac", Collections.EMPTY_LIST, Collections.EMPTY_LIST); + } + + public ExternalCompilationUnit createCompilationUnit(final JavaAwareCompilationUnit compilationUnit) { + return new ExternalCompilationUnit(this, compilationUnit) { + private JavaCompilerFactory compilerFactory = new JavacCompilerFactory(); + + public void doCompilation(CompilerConfiguration configuration) { + if (sources.size() != 0) { + JavaCompiler compiler = compilerFactory.createCompiler(configuration); + compiler.compile(sources, compilationUnit); + } + } + }; + } + + public String getFileExt() { + return "java"; + } +} Index: src/main/org/codehaus/groovy/tools/scalac/ScalacScalaCompiler.java =================================================================== --- src/main/org/codehaus/groovy/tools/scalac/ScalacScalaCompiler.java Fri Mar 06 21:22:24 EET 2009 +++ src/main/org/codehaus/groovy/tools/scalac/ScalacScalaCompiler.java Fri Mar 06 21:22:24 EET 2009 @@ -0,0 +1,188 @@ +/* + * Copyright 2003-2007 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 + * + * 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.codehaus.groovy.tools.scalac; + +import groovy.lang.GroovyClassLoader; + +import java.io.File; +import java.io.StringWriter; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.net.URLClassLoader; +import java.net.URL; +import java.net.URISyntaxException; + +import org.codehaus.groovy.control.CompilationUnit; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.control.messages.ExceptionMessage; +import org.codehaus.groovy.control.messages.SimpleMessage; +import org.codehaus.groovy.runtime.DefaultGroovyMethods; +import org.codehaus.groovy.tools.javac.JavacJavaCompiler; +import org.codehaus.groovy.tools.javac.ExternalCompiler; +import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit; + +public class ScalacScalaCompiler extends JavacJavaCompiler implements ExternalCompiler { + public ScalacScalaCompiler(CompilerConfiguration config) { + super(config); + } + + public void compile(Set files, JavaAwareCompilationUnit cu) { + String[] scalacParameters = makeParameters(files, cu.getClassLoader()); + StringWriter scalacOutput=null; + int scalacReturnValue = 0; + try { + Class scalac = findScalac(cu); + Method method=null; + try { + method = scalac.getMethod("process", new Class[]{String[].class}); + scalacOutput = new StringWriter(); + Object ret = method.invoke(null, new Object[]{scalacParameters}); + scalacReturnValue = 0; + } catch (NoSuchMethodException e) {} + cu.getConfiguration().getOutput(); + } catch (InvocationTargetException ite) { + cu.getErrorCollector().addFatalError(new ExceptionMessage((Exception) ite.getCause(), true, cu)); + } catch (Exception e) { + cu.getErrorCollector().addFatalError(new ExceptionMessage(e, true, cu)); + } + if (scalacReturnValue!=0) { + switch (scalacReturnValue) { + case 1: addJavacError("Compile error during compilation with scalac.",cu,scalacOutput); break; + default: addJavacError("unexpected return value by javac.",cu,scalacOutput); break; + } + } + } + + private void addJavacError(String header, CompilationUnit cu, StringWriter msg) { + if (msg!=null) { + header = header+"\n"+msg.getBuffer().toString(); + } else { + header = header+ + "\nThis javac version does not support compile(String[],PrintWriter), "+ + "so no further details of the error are available. The message error text "+ + "should be found on System.err.\n"; + } + cu.getErrorCollector().addFatalError(new SimpleMessage(header,cu)); + } + + + private String[] makeParameters(Set files, GroovyClassLoader parentClassLoader) { + Map options = config.getJointCompilationOptions(); + LinkedList paras = new LinkedList(); + + File target = config.getTargetDirectory(); + if (target == null) target = new File("."); + + // defaults + paras.add("-d"); + paras.add(target.getAbsolutePath()); + + // add flags + String[] flags = (String[]) options.get("flags"); + if (flags != null) { + for (int i = 0; i < flags.length; i++) { + paras.add('-' + flags[i]); + } + } + + boolean hadClasspath=false; + // add namedValues + String[] namedValues = (String[]) options.get("namedValues"); + if (namedValues != null) { + for (int i = 0; i < namedValues.length; i += 2) { + String name = namedValues[i]; + if (name.equals("classpath")) hadClasspath = true; + + if (name.equals("source")) + continue; + + if (name.equals("target")) { + paras.add("-target"); + paras.add("jvm-"+namedValues[i + 1]); + continue; + } + + paras.add('-' + name); + paras.add(namedValues[i + 1]); + } + } + + // append classpath if not already defined + if (!hadClasspath) { + // add all classpaths that compilation unit sees + StringBuffer resultPath = new StringBuffer(DefaultGroovyMethods.join(config.getClasspath(), File.pathSeparator)); + ClassLoader cl = parentClassLoader; + while (cl != null) { + if (cl instanceof URLClassLoader) { + for (URL u : ((URLClassLoader)cl).getURLs()) { + try { + resultPath.append(File.pathSeparator); + resultPath.append(new File(u.toURI()).getPath()); + } catch (URISyntaxException e) { + // ignore it + } + } + } + cl = cl.getParent(); + } + + paras.add("-classpath"); + paras.add(resultPath.toString()); + } + + addFile ((File)options.get("stubDir"), paras); + + // files to compile + paras.addAll(files); + + return (String[]) paras.toArray(new String[paras.size()]); + } + + private void addFile (File file, List ls) { + if (file.isDirectory()) { + for ( File ff : file.listFiles() ) + addFile(ff, ls); + } + else { + if (file.getName().endsWith(".java")) + ls.add(file.getAbsolutePath()); + } + } + + private Class findScalac(CompilationUnit cu) throws ClassNotFoundException { + String main = "scala.tools.nsc.Main"; + try { + return Class.forName(main); + } catch (ClassNotFoundException e) { + try { + ClassLoader cl = this.getClass().getClassLoader(); + return cl.loadClass(main); + } catch (ClassNotFoundException e2) { + try { + return ClassLoader.getSystemClassLoader().loadClass(main); + } catch (ClassNotFoundException e3) { + try { + return cu.getClassLoader().loadClass(main); + } catch (ClassNotFoundException e4) { + throw new ClassNotFoundException("unable to locate the scala compiler " + main + ", please change your classloader settings"); + } + } + } + } + } +} \ No newline at end of file Index: src/test/groovy/JointJava.java =================================================================== --- src/test/groovy/JointJava.java (revision 15551) +++ src/test/groovy/JointJava.java Fri Mar 06 17:25:33 EET 2009 @@ -1,7 +1,7 @@ package groovy; -public class JointJava { - public void method() { - new JointGroovy().getProperty(); +public class JointJava extends JointScala { + public Object method() { + return new JointGroovy().getProperty(); } } Index: src/main/org/codehaus/groovy/tools/scalac/ScalacExternalCompilerPlugin.java =================================================================== --- src/main/org/codehaus/groovy/tools/scalac/ScalacExternalCompilerPlugin.java Sat Mar 07 10:50:52 EET 2009 +++ src/main/org/codehaus/groovy/tools/scalac/ScalacExternalCompilerPlugin.java Sat Mar 07 10:50:52 EET 2009 @@ -0,0 +1,32 @@ +package org.codehaus.groovy.tools.scalac; + +import org.codehaus.groovy.control.CompilationUnit; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.tools.javac.*; + +import java.util.Collections; +import java.util.Set; +import java.util.LinkedHashSet; +import java.util.Arrays; +import java.io.File; + +public class ScalacExternalCompilerPlugin extends ExternalCompilerPlugin { + public ScalacExternalCompilerPlugin() { + super("scalac", Arrays.asList("javac"), Collections.EMPTY_LIST); + } + + public ExternalCompilationUnit createCompilationUnit(final JavaAwareCompilationUnit compilationUnit) { + return new ExternalCompilationUnit(this, compilationUnit) { + + public void doCompilation(CompilerConfiguration configuration) { + if (sources.size() != 0) { + new ScalacScalaCompiler(configuration).compile(sources, compilationUnit); + } + } + }; + } + + public String getFileExt() { + return "scala"; + } +} \ No newline at end of file Index: src/main/org/codehaus/groovy/tools/javac/JavacJavaCompiler.java =================================================================== --- src/main/org/codehaus/groovy/tools/javac/JavacJavaCompiler.java (revision 15551) +++ src/main/org/codehaus/groovy/tools/javac/JavacJavaCompiler.java Fri Mar 06 17:02:09 EET 2009 @@ -35,13 +35,13 @@ import org.codehaus.groovy.runtime.DefaultGroovyMethods; public class JavacJavaCompiler implements JavaCompiler { - private CompilerConfiguration config; + protected CompilerConfiguration config; public JavacJavaCompiler(CompilerConfiguration config) { this.config = config; } - public void compile(List files, CompilationUnit cu) { + public void compile(Set files, JavaAwareCompilationUnit cu) { String[] javacParameters = makeParameters(files, cu.getClassLoader()); StringWriter javacOutput=null; int javacReturnValue = 0; @@ -90,7 +90,7 @@ } - private String[] makeParameters(List files, GroovyClassLoader parentClassLoader) { + private String[] makeParameters(Set files, GroovyClassLoader parentClassLoader) { Map options = config.getJointCompilationOptions(); LinkedList paras = new LinkedList(); Index: src/main/org/codehaus/groovy/tools/javac/JavaCompiler.java =================================================================== --- src/main/org/codehaus/groovy/tools/javac/JavaCompiler.java (revision 15551) +++ src/main/org/codehaus/groovy/tools/javac/JavaCompiler.java Fri Mar 06 17:16:14 EET 2009 @@ -17,6 +17,7 @@ package org.codehaus.groovy.tools.javac; import java.util.List; +import java.util.Set; import org.codehaus.groovy.control.CompilationUnit; @@ -24,5 +25,5 @@ * @author Alex.Tkachman */ public interface JavaCompiler { - void compile(List files, CompilationUnit cu); + void compile(Set files, JavaAwareCompilationUnit cu); } Index: src/main/org/codehaus/groovy/tools/javac/JavaAwareCompilationUnit.java =================================================================== --- src/main/org/codehaus/groovy/tools/javac/JavaAwareCompilationUnit.java (revision 15551) +++ src/main/org/codehaus/groovy/tools/javac/JavaAwareCompilationUnit.java Fri Mar 06 16:49:50 EET 2009 @@ -18,9 +18,7 @@ import groovy.lang.GroovyClassLoader; -import java.util.LinkedList; -import java.util.Iterator; -import java.util.Map; +import java.util.*; import java.io.File; import java.io.FileNotFoundException; @@ -39,19 +37,22 @@ * Date: May 31, 2007 Time: 6:48:28 PM */ public class JavaAwareCompilationUnit extends CompilationUnit { - private LinkedList javaSources; // java sources + private Set javaSources; // java sources private JavaStubGenerator stubGenerator; - private JavaCompilerFactory compilerFactory = new JavacCompilerFactory(); private File generationGoal; private boolean keepStubs; + private List plugins = new ArrayList(); - + public JavaAwareCompilationUnit(CompilerConfiguration configuration) { this(configuration,null); } public JavaAwareCompilationUnit(CompilerConfiguration configuration, GroovyClassLoader groovyClassLoader) { super(configuration,null,groovyClassLoader); - javaSources = new LinkedList(); + + ExternalCompilerPlugin.getPlugins(this, plugins); + + javaSources = new LinkedHashSet(); Map options = configuration.getJointCompilationOptions(); generationGoal = (File) options.get("stubDir"); boolean useJava5 = configuration.getTargetBytecode().equals(CompilerConfiguration.POST_JDK5); @@ -60,14 +61,16 @@ addPhaseOperation(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode node) throws CompilationFailedException { - if (javaSources.size() != 0) new JavaAwareResolveVisitor(JavaAwareCompilationUnit.this).startResolving(node,source); + if (hasAdditionalSources()) + new JavaAwareResolveVisitor(JavaAwareCompilationUnit.this).startResolving(node,source); } },Phases.CONVERSION); addPhaseOperation(new PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { try { - if (javaSources.size() != 0) stubGenerator.generateClass(classNode); + if (hasAdditionalSources()) + stubGenerator.generateClass(classNode); } catch (FileNotFoundException fnfe) { source.addException(fnfe); } @@ -75,21 +78,30 @@ },Phases.CONVERSION); } + private boolean hasAdditionalSources() { + for (ExternalCompilationUnit ext : plugins) + if (ext.hasAdditionalSources()) + return true; + + return false; + } + public void gotoPhase(int phase) throws CompilationFailedException { super.gotoPhase(phase); // compile Java and clean up - if (phase==Phases.SEMANTIC_ANALYSIS && javaSources.size()>0) { + if (phase==Phases.SEMANTIC_ANALYSIS && hasAdditionalSources()) { Iterator modules = getAST().getModules().iterator(); while (modules.hasNext()) { ModuleNode module = (ModuleNode) modules.next(); module.setImportsResolved(false); } try { - JavaCompiler compiler = compilerFactory.createCompiler(getConfiguration()); - compiler.compile(javaSources, this); + for (ExternalCompilationUnit ext : plugins) + ext.doCompilation(getConfiguration()); } finally { if (!keepStubs) stubGenerator.clean(); - javaSources.clear(); + for (ExternalCompilationUnit ext : plugins) + ext.clearSources(); } } } @@ -105,40 +117,24 @@ } } - private void addJavaSource(File file) { - String path = file.getAbsolutePath(); - for (Iterator iter = javaSources.iterator(); iter.hasNext();) { - String su = (String) iter.next(); - if (path.equals(su)) - return; - } - javaSources.add(path); - } - public void addSources(String[] paths) { for (int i = 0; i < paths.length; i++) { File file = new File(paths[i]); - if (file.getName().endsWith(".java")) - addJavaSource(file); - else - addSource(file); + addSrc(file); } } public void addSources(File[] files) { for (int i = 0; i < files.length; i++) { - if (files[i].getName().endsWith(".java")) - addJavaSource(files[i]); - else - addSource(files[i]); + addSrc(files[i]); } } - public JavaCompilerFactory getCompilerFactory() { - return compilerFactory; - } + private void addSrc(File file) { + for (ExternalCompilationUnit ext : plugins) + if (ext.addSource(file)) + return; - public void setCompilerFactory(JavaCompilerFactory compilerFactory) { - this.compilerFactory = compilerFactory; + addSource(file); } } Index: src/test/groovy/JointGroovy.groovy =================================================================== --- src/test/groovy/JointGroovy.groovy (revision 15551) +++ src/test/groovy/JointGroovy.groovy Fri Mar 06 15:59:55 EET 2009 @@ -1,5 +1,25 @@ package groovy +import org.codehaus.groovy.tools.RootLoader + class JointGroovy { - String property + + String property = "abc" + + public Object groovyMethod() { + return new JointJava().getProperty(); -} \ No newline at end of file + } + + static def test () { + new GroovyShell( + new URLClassLoader( + [new URL("file://" + new File("target/test-generated-classes").absolutePath + "/")] as URL[], + JointGroovy.getClassLoader() + ) + ).evaluate(""" + package groovy + + assert new groovy.JointScala ().method ().reverse() == "cba" + """) + } +} \ No newline at end of file Index: src/test/org/codehaus/groovy/tools/FileSystemCompilerTest.java =================================================================== --- src/test/org/codehaus/groovy/tools/FileSystemCompilerTest.java (revision 15551) +++ src/test/org/codehaus/groovy/tools/FileSystemCompilerTest.java Wed Mar 04 16:26:44 EET 2009 @@ -47,7 +47,9 @@ package org.codehaus.groovy.tools; import groovy.util.GroovyTestCase; +import groovy.JointGroovy; import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.tools.scalac.ScalacScalaCompiler; import java.io.File; import java.util.HashMap; @@ -72,8 +74,18 @@ runTest(new String[] {"tree/NestedClosureBugTest.groovy"}); runTest(new String[] {"tree/SmallTreeTest.groovy"}); runTest(new String[] {"LittleClosureTest.groovy"}); - runTest(new String[] {"JointJava.java", "JointGroovy.groovy"}); + + String main = "scala.tools.nsc.Main"; + Class scalac = null; + try { + scalac = Class.forName(main); + } catch (ClassNotFoundException e) {} + if (scalac != null) { + System.out.println("Compiling Scala"); + runTest(new String[] {"JointJava.java", "JointGroovy.groovy", "JointScala.scala"}); + JointGroovy.test(); - } + } + } protected void runTest(String[] names) throws Exception { List files = new ArrayList(); Index: src/main/org/codehaus/groovy/ant/Groovyc.java =================================================================== --- src/main/org/codehaus/groovy/ant/Groovyc.java (revision 15551) +++ src/main/org/codehaus/groovy/ant/Groovyc.java Sat Mar 07 15:07:42 EET 2009 @@ -36,6 +36,8 @@ import org.codehaus.groovy.tools.ErrorReporter; import org.codehaus.groovy.tools.FileSystemCompiler; import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit; +import org.codehaus.groovy.tools.javac.ExternalCompilerPlugin; +import org.codehaus.groovy.tools.javac.ExternalCompilationUnit; import java.io.File; import java.io.FileWriter; @@ -43,10 +45,9 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.net.URLClassLoader; +import java.net.URL; /** * Compiles Groovy source files. This task can take the following arguments: @@ -524,6 +525,29 @@ if (javac != null) jointCompilation = true; + List add = null; + if (jointCompilation) { + configuration = new CompilerConfiguration(); + configuration.setJointCompilationOptions(Collections.EMPTY_MAP); + final GroovyClassLoader loader = new GroovyClassLoader(buildClassLoaderFor()); + Path classpath = getClasspath(); + if (classpath == null) + classpath = new Path(getProject()); + for (String s : classpath.list()) { + loader.addClasspath(s); + } + final JavaAwareCompilationUnit awareCompilationUnit = new JavaAwareCompilationUnit(configuration, loader); + configuration = null; + + final ArrayList external = new ArrayList(); + ExternalCompilerPlugin.getPlugins(awareCompilationUnit, external); + + add = new ArrayList (); + for (ExternalCompilationUnit externalCompilationUnit : external) { + add.add(externalCompilationUnit.getMask()); + } + } + // scan source directories and dest directory to build up // compile lists String[] list = src.list(); @@ -534,7 +558,7 @@ } DirectoryScanner ds = this.getDirectoryScanner(file); String[] files = ds.getIncludedFiles(); - scanDir(file, destDir != null ? destDir : file, files); + scanDir(file, destDir != null ? destDir : file, files, add); } compile(); @@ -560,7 +584,7 @@ * @param destDir The destination directory * @param files An array of filenames */ - protected void scanDir(File srcDir, File destDir, String[] files) { + protected void scanDir(File srcDir, File destDir, String[] files, List add) { GlobPatternMapper m = new GlobPatternMapper(); m.setFrom("*.groovy"); m.setTo("*.class"); @@ -568,12 +592,13 @@ File[] newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m); addToCompileList(newFiles); - if (jointCompilation) { - m.setFrom("*.java"); + if (add != null) + for (String mask : add) { + m.setFrom(mask); - m.setTo("*.class"); - newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m); - addToCompileList(newFiles); - } + m.setTo("*.class"); + newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m); + addToCompileList(newFiles); + } } protected void addToCompileList(File[] newFiles) { Index: src/main/org/codehaus/groovy/tools/FileSystemCompiler.java =================================================================== --- src/main/org/codehaus/groovy/tools/FileSystemCompiler.java (revision 15551) +++ src/main/org/codehaus/groovy/tools/FileSystemCompiler.java Fri Mar 06 12:01:41 EET 2009 @@ -45,7 +45,7 @@ if (cu != null) { unit = cu; } else if (configuration.getJointCompilationOptions() != null) { - this.unit = new JavaAwareCompilationUnit(configuration); + this.unit = new JavaAwareCompilationUnit(configuration, null); } else { this.unit = new CompilationUnit(configuration); } Index: src/main/META-INF/services/org.codehaus.groovy.tools.javac.ExternalCompilerPlugin =================================================================== --- src/main/META-INF/services/org.codehaus.groovy.tools.javac.ExternalCompilerPlugin Fri Mar 06 15:43:14 EET 2009 +++ src/main/META-INF/services/org.codehaus.groovy.tools.javac.ExternalCompilerPlugin Fri Mar 06 15:43:14 EET 2009 @@ -0,0 +1,3 @@ +#javac configuration +org.codehaus.groovy.tools.scalac.ScalacExternalCompilerPlugin +org.codehaus.groovy.tools.javac.JavacExternalCompilerPlugin Index: pom.xml =================================================================== --- pom.xml (revision 15551) +++ pom.xml Fri Mar 06 20:46:00 EET 2009 @@ -695,6 +695,14 @@ + + + org.scala-lang + scala-compiler + 2.7.3 + test + true + @@ -177,8 +177,8 @@ deprecation="on" debug="yes" source="1.5" target="1.5" fork="true" classpathref="compilePath"> - + Index: src/main/org/codehaus/groovy/tools/javac/ExternalCompilerPlugin.java =================================================================== --- src/main/org/codehaus/groovy/tools/javac/ExternalCompilerPlugin.java Sat Mar 07 10:50:52 EET 2009 +++ src/main/org/codehaus/groovy/tools/javac/ExternalCompilerPlugin.java Sat Mar 07 10:50:52 EET 2009 @@ -0,0 +1,108 @@ +package org.codehaus.groovy.tools.javac; + +import java.util.*; +import java.io.IOException; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLClassLoader; + +import org.codehaus.groovy.control.messages.SimpleMessage; +import org.codehaus.groovy.control.messages.WarningMessage; + +public abstract class ExternalCompilerPlugin { + private final String name; + protected final List before, after; + + public ExternalCompilerPlugin(String name, List before, List after) { + this.name = name; + this.before = before; + this.after = after; + } + + public abstract ExternalCompilationUnit createCompilationUnit (JavaAwareCompilationUnit compilationUnit); + + public String getName() { + return name; + } + + public static void getPlugins(JavaAwareCompilationUnit compilationUnit, List external) { + LinkedHashMap pluginNames = new LinkedHashMap(); + + for (ClassLoader cl = compilationUnit.getTransformLoader(); + cl != null; + cl = cl.getParent()) { + if (!(cl instanceof URLClassLoader)) + continue; + + URLClassLoader transformLoader = (URLClassLoader) cl; + + try { + final Enumeration globalServices = transformLoader.findResources("META-INF/services/org.codehaus.groovy.tools.javac.ExternalCompilerPlugin"); + while (globalServices.hasMoreElements()) { + URL service = globalServices.nextElement(); + String className; + BufferedReader svcIn = new BufferedReader(new InputStreamReader(service.openStream())); + try { + className = svcIn.readLine(); + } catch (IOException ioe) { + compilationUnit.getErrorCollector().addError(new SimpleMessage( + "IOException reading the service definition at " + + service.toExternalForm() + " because of exception " + ioe.toString(), null)); + continue; + } + while (className != null) { + if (!className.startsWith("#") && className.length() > 0) { + if (pluginNames.containsKey(className)) { + if (!service.equals(pluginNames.get(className))) { + compilationUnit.getErrorCollector().addWarning( + WarningMessage.POSSIBLE_ERRORS, + "The external compiler for class " + className + " is defined in both " + + pluginNames.get(className).toExternalForm() + + " and " + + service.toExternalForm() + + " - the former definition will be used and the latter ignored.", + null, + null); + } + + } else { + pluginNames.put(className, service); + } + } + try { + className = svcIn.readLine(); + } catch (IOException ioe) { + compilationUnit.getErrorCollector().addError(new SimpleMessage( + "IOException reading the service definition at " + + service.toExternalForm() + " because of exception " + ioe.toString(), null)); + //noinspection UnnecessaryContinue + continue; + } + } + } + } catch (IOException e) { + } + + } + + Map plugins = new LinkedHashMap (); + for (Map.Entry entry : pluginNames.entrySet()) { + try { + Class pluginClass = compilationUnit.getTransformLoader().loadClass(entry.getKey(), false, true, false); + ExternalCompilerPlugin plugin = (ExternalCompilerPlugin) pluginClass.newInstance(); + plugins.put(plugin.getName(), plugin); + //no inspection unchecked + } catch (Exception e) { + compilationUnit.getErrorCollector().addError(new SimpleMessage( + "Could not instantiate external compiler class " + entry.getKey() + " specified at " + + entry.getValue().toExternalForm() + " because of exception " + e.toString(), null)); + } + } + + for (ExternalCompilerPlugin p : plugins.values()) + external.add(p.createCompilationUnit(compilationUnit)); + } + + public abstract String getFileExt(); +}