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 }