View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.jci.compilers;
19  
20  import groovy.lang.GroovyClassLoader;
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.List;
25  
26  import org.apache.commons.jci.problems.CompilationProblem;
27  import org.apache.commons.jci.readers.ResourceReader;
28  import org.apache.commons.jci.stores.ResourceStore;
29  import org.apache.commons.jci.utils.ConversionUtils;
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.codehaus.groovy.control.CompilationFailedException;
33  import org.codehaus.groovy.control.CompilationUnit;
34  import org.codehaus.groovy.control.CompilerConfiguration;
35  import org.codehaus.groovy.control.ErrorCollector;
36  import org.codehaus.groovy.control.MultipleCompilationErrorsException;
37  import org.codehaus.groovy.control.Phases;
38  import org.codehaus.groovy.control.SourceUnit;
39  import org.codehaus.groovy.control.messages.Message;
40  import org.codehaus.groovy.control.messages.WarningMessage;
41  import org.codehaus.groovy.tools.GroovyClass;
42  
43  /**
44   * Groovy implementation of the JavaCompiler interface
45   * 
46   * @author tcurdt
47   */
48  public final class GroovyJavaCompiler extends AbstractJavaCompiler {
49  
50      private final Log log = LogFactory.getLog(GroovyJavaCompiler.class);
51      private final GroovyJavaCompilerSettings defaultSettings;
52      
53      public GroovyJavaCompiler() {
54          defaultSettings = new GroovyJavaCompilerSettings(new CompilerConfiguration());
55      }
56          
57      public CompilationResult compile(
58              final String[] pResourceNames,
59              final ResourceReader pReader,
60              final ResourceStore pStore,
61              final ClassLoader pClassLoader,
62              final JavaCompilerSettings pSettings
63              ) {
64  
65          final CompilerConfiguration configuration = ((GroovyJavaCompilerSettings) pSettings).getCompilerConfiguration();
66          final ErrorCollector collector = new ErrorCollector(configuration);
67          final GroovyClassLoader groovyClassLoader = new GroovyClassLoader(pClassLoader);
68          final CompilationUnit unit = new CompilationUnit(configuration, null, groovyClassLoader);
69          final SourceUnit[] source = new SourceUnit[pResourceNames.length];
70          for (int i = 0; i < source.length; i++) {
71              final String resourceName = pResourceNames[i];
72              source[i] = new SourceUnit(
73                      ConversionUtils.convertResourceToClassName(resourceName),
74                      new String(pReader.getBytes(resourceName)), // FIXME delay the read
75                      configuration,
76                      groovyClassLoader,
77                      collector
78                      );
79              unit.addSource(source[i]);
80          }
81          
82          final Collection<CompilationProblem> problems = new ArrayList<CompilationProblem>();
83  
84          try {
85              log.debug("compiling");
86              unit.compile(Phases.CLASS_GENERATION);
87              
88              @SuppressWarnings("unchecked") // Groovy library is not yet generic
89              final List<GroovyClass> classes = unit.getClasses();
90              for (GroovyClass clazz : classes) {
91                  final byte[] bytes = clazz.getBytes();
92                  pStore.write(ConversionUtils.convertClassToResourcePath(clazz.getName()), bytes);
93              }
94          } catch (final MultipleCompilationErrorsException e) {
95              final ErrorCollector col = e.getErrorCollector();
96              @SuppressWarnings("unchecked") // Groovy library is not yet generic
97              final Collection<WarningMessage> warnings = col.getWarnings();
98              if (warnings != null) {
99                  for (WarningMessage warning : warnings) {
100                     final CompilationProblem problem = new GroovyCompilationProblem(warning); 
101                     if (problemHandler != null) {
102                         problemHandler.handle(problem);
103                     }
104                     problems.add(problem);
105                 }
106             }
107 
108             @SuppressWarnings("unchecked") // Groovy library is not yet generic
109             final Collection<Message> errors = col.getErrors();
110             if (errors != null) {
111                 for (Message message : errors) {
112                     final CompilationProblem problem = new GroovyCompilationProblem(message); 
113                     if (problemHandler != null) {
114                         problemHandler.handle(problem);
115                     }
116                     problems.add(problem);
117                 }
118             }
119         } catch (CompilationFailedException e) {
120             throw new RuntimeException("no expected");
121         }
122 
123         final CompilationProblem[] result = new CompilationProblem[problems.size()];
124         problems.toArray(result);
125         return new CompilationResult(result);
126     }
127 
128     public JavaCompilerSettings createDefaultSettings() {
129         return defaultSettings;
130     }
131 }