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 java.io.BufferedReader;
021: import java.io.IOException;
022: import java.io.Reader;
023: import java.io.StringReader;
024: import java.util.ArrayList;
025: import java.util.Collection;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.Map;
029:
030: import org.apache.commons.jci.problems.CompilationProblem;
031: import org.apache.commons.jci.readers.ResourceReader;
032: import org.apache.commons.jci.stores.ResourceStore;
033: import org.apache.commons.jci.utils.ConversionUtils;
034: import org.apache.commons.logging.Log;
035: import org.apache.commons.logging.LogFactory;
036: import org.codehaus.janino.ClassLoaderIClassLoader;
037: import org.codehaus.janino.CompileException;
038: import org.codehaus.janino.DebuggingInformation;
039: import org.codehaus.janino.Descriptor;
040: import org.codehaus.janino.IClass;
041: import org.codehaus.janino.IClassLoader;
042: import org.codehaus.janino.Java;
043: import org.codehaus.janino.Location;
044: import org.codehaus.janino.Parser;
045: import org.codehaus.janino.Scanner;
046: import org.codehaus.janino.UnitCompiler;
047: import org.codehaus.janino.WarningHandler;
048: import org.codehaus.janino.Scanner.LocatedException;
049: import org.codehaus.janino.UnitCompiler.ErrorHandler;
050: import org.codehaus.janino.util.ClassFile;
051:
052: /**
053: * @author art@gramlich-net.com
054: */
055: public final class JaninoJavaCompiler extends AbstractJavaCompiler {
056:
057: private final Log log = LogFactory.getLog(JaninoJavaCompiler.class);
058:
059: private class CompilingIClassLoader extends IClassLoader {
060:
061: private final Map types = new HashMap();
062: private final ResourceReader resourceReader;
063: private final Map classes;
064: private final Collection problems = new ArrayList();
065:
066: private CompilingIClassLoader(
067: final ResourceReader pResourceReader,
068: final Map pClasses, final ClassLoader classLoader) {
069: super (new ClassLoaderIClassLoader(classLoader));
070: resourceReader = pResourceReader;
071: classes = pClasses;
072: super .postConstruct();
073: }
074:
075: protected Collection getProblems() {
076: return problems;
077: }
078:
079: protected IClass findIClass(final String pType) {
080: final String className = Descriptor.toClassName(pType);
081: if (types.containsKey(pType)) {
082: return (IClass) types.get(pType);
083: }
084:
085: // FIXME: should not be tied to the extension
086: final String resourceNameFromClass = className.replace('.',
087: '/')
088: + ".java";
089:
090: final byte[] content = resourceReader
091: .getBytes(resourceNameFromClass);
092: if (content == null) {
093: return null;
094: }
095: final Reader reader = new BufferedReader(new StringReader(
096: new String(content)));
097: Scanner scanner = null;
098: try {
099: scanner = new Scanner(resourceNameFromClass, reader);
100: final Java.CompilationUnit unit = new Parser(scanner)
101: .parseCompilationUnit();
102: final UnitCompiler uc = new UnitCompiler(unit, this );
103: uc.setCompileErrorHandler(new ErrorHandler() {
104: public void handleError(final String pMessage,
105: final Location pOptionalLocation)
106: throws CompileException {
107: final CompilationProblem problem = new JaninoCompilationProblem(
108: pOptionalLocation, pMessage, true);
109: if (problemHandler != null) {
110: problemHandler.handle(problem);
111: }
112: problems.add(problem);
113: }
114: });
115: uc.setWarningHandler(new WarningHandler() {
116: public void handleWarning(final String pHandle,
117: final String pMessage,
118: final Location pOptionalLocation) {
119: final CompilationProblem problem = new JaninoCompilationProblem(
120: pOptionalLocation, pMessage, false);
121: if (problemHandler != null) {
122: problemHandler.handle(problem);
123: }
124: problems.add(problem);
125: }
126: });
127: log.debug("compile " + className);
128: final ClassFile[] classFiles = uc
129: .compileUnit(DebuggingInformation.ALL);
130: for (int i = 0; i < classFiles.length; i++) {
131: log.debug("compiled "
132: + classFiles[i].getThisClassName());
133: classes.put(classFiles[i].getThisClassName(),
134: classFiles[i].toByteArray());
135: }
136: final IClass ic = uc.findClass(className);
137: if (null != ic) {
138: types.put(pType, ic);
139: }
140: return ic;
141: } catch (final LocatedException e) {
142: problems.add(new JaninoCompilationProblem(e));
143: } catch (final IOException e) {
144: problems.add(new JaninoCompilationProblem(
145: resourceNameFromClass, "IOException:"
146: + e.getMessage(), true));
147: } catch (final Exception e) {
148: problems.add(new JaninoCompilationProblem(
149: resourceNameFromClass, "Exception:"
150: + e.getMessage(), true));
151: } finally {
152: if (scanner != null) {
153: try {
154: scanner.close();
155: } catch (IOException e) {
156: log.error(
157: "IOException occured while compiling "
158: + className, e);
159: }
160: }
161: }
162: return null;
163: }
164: }
165:
166: public CompilationResult compile(final String[] pSourceNames,
167: final ResourceReader pResourceReader,
168: final ResourceStore pStore, final ClassLoader pClassLoader,
169: final JavaCompilerSettings pSettings) {
170:
171: final Map classFilesByName = new HashMap();
172:
173: final CompilingIClassLoader icl = new CompilingIClassLoader(
174: pResourceReader, classFilesByName, pClassLoader);
175: for (int i = 0; i < pSourceNames.length; i++) {
176: log.debug("compiling " + pSourceNames[i]);
177: icl.loadIClass(Descriptor.fromClassName(ConversionUtils
178: .convertResourceToClassName(pSourceNames[i])));
179: }
180:
181: // Store all fully compiled classes
182: for (Iterator i = classFilesByName.entrySet().iterator(); i
183: .hasNext();) {
184: final Map.Entry entry = (Map.Entry) i.next();
185: final String clazzName = (String) entry.getKey();
186: pStore.write(ConversionUtils
187: .convertClassToResourcePath(clazzName),
188: (byte[]) entry.getValue());
189: }
190:
191: final Collection problems = icl.getProblems();
192: final CompilationProblem[] result = new CompilationProblem[problems
193: .size()];
194: problems.toArray(result);
195: return new CompilationResult(result);
196: }
197:
198: public JavaCompilerSettings createDefaultSettings() {
199: // FIXME
200: return null;
201: }
202:
203: }
|