    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    }