001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.jci.compilers;
019    
020    import groovy.lang.GroovyClassLoader;
021    
022    import java.util.ArrayList;
023    import java.util.Collection;
024    import java.util.List;
025    
026    import org.apache.commons.jci.problems.CompilationProblem;
027    import org.apache.commons.jci.readers.ResourceReader;
028    import org.apache.commons.jci.stores.ResourceStore;
029    import org.apache.commons.jci.utils.ConversionUtils;
030    import org.apache.commons.logging.Log;
031    import org.apache.commons.logging.LogFactory;
032    import org.codehaus.groovy.control.CompilationFailedException;
033    import org.codehaus.groovy.control.CompilationUnit;
034    import org.codehaus.groovy.control.CompilerConfiguration;
035    import org.codehaus.groovy.control.ErrorCollector;
036    import org.codehaus.groovy.control.MultipleCompilationErrorsException;
037    import org.codehaus.groovy.control.Phases;
038    import org.codehaus.groovy.control.SourceUnit;
039    import org.codehaus.groovy.control.messages.Message;
040    import org.codehaus.groovy.control.messages.WarningMessage;
041    import org.codehaus.groovy.tools.GroovyClass;
042    
043    /**
044     * Groovy implementation of the JavaCompiler interface
045     * 
046     * @author tcurdt
047     */
048    public final class GroovyJavaCompiler extends AbstractJavaCompiler {
049    
050        private final Log log = LogFactory.getLog(GroovyJavaCompiler.class);
051        private final GroovyJavaCompilerSettings defaultSettings;
052        
053        public GroovyJavaCompiler() {
054            defaultSettings = new GroovyJavaCompilerSettings(new CompilerConfiguration());
055        }
056            
057        public CompilationResult compile(
058                final String[] pResourceNames,
059                final ResourceReader pReader,
060                final ResourceStore pStore,
061                final ClassLoader pClassLoader,
062                final JavaCompilerSettings pSettings
063                ) {
064    
065            final CompilerConfiguration configuration = ((GroovyJavaCompilerSettings) pSettings).getCompilerConfiguration();
066            final ErrorCollector collector = new ErrorCollector(configuration);
067            final GroovyClassLoader groovyClassLoader = new GroovyClassLoader(pClassLoader);
068            final CompilationUnit unit = new CompilationUnit(configuration, null, groovyClassLoader);
069            final SourceUnit[] source = new SourceUnit[pResourceNames.length];
070            for (int i = 0; i < source.length; i++) {
071                final String resourceName = pResourceNames[i];
072                source[i] = new SourceUnit(
073                        ConversionUtils.convertResourceToClassName(resourceName),
074                        new String(pReader.getBytes(resourceName)), // FIXME delay the read
075                        configuration,
076                        groovyClassLoader,
077                        collector
078                        );
079                unit.addSource(source[i]);
080            }
081            
082            final Collection<CompilationProblem> problems = new ArrayList<CompilationProblem>();
083    
084            try {
085                log.debug("compiling");
086                unit.compile(Phases.CLASS_GENERATION);
087                
088                @SuppressWarnings("unchecked") // Groovy library is not yet generic
089                final List<GroovyClass> classes = unit.getClasses();
090                for (GroovyClass clazz : classes) {
091                    final byte[] bytes = clazz.getBytes();
092                    pStore.write(ConversionUtils.convertClassToResourcePath(clazz.getName()), bytes);
093                }
094            } catch (final MultipleCompilationErrorsException e) {
095                final ErrorCollector col = e.getErrorCollector();
096                @SuppressWarnings("unchecked") // Groovy library is not yet generic
097                final Collection<WarningMessage> warnings = col.getWarnings();
098                if (warnings != null) {
099                    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    }