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 java.io.BufferedReader;
21  import java.io.IOException;
22  import java.io.Reader;
23  import java.io.StringReader;
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.HashMap;
27  import java.util.Iterator;
28  import java.util.Map;
29  
30  import org.apache.commons.jci.problems.CompilationProblem;
31  import org.apache.commons.jci.readers.ResourceReader;
32  import org.apache.commons.jci.stores.ResourceStore;
33  import org.apache.commons.jci.utils.ConversionUtils;
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  import org.codehaus.janino.ClassLoaderIClassLoader;
37  import org.codehaus.janino.CompileException;
38  import org.codehaus.janino.DebuggingInformation;
39  import org.codehaus.janino.Descriptor;
40  import org.codehaus.janino.IClass;
41  import org.codehaus.janino.IClassLoader;
42  import org.codehaus.janino.Java;
43  import org.codehaus.janino.Location;
44  import org.codehaus.janino.Parser;
45  import org.codehaus.janino.Scanner;
46  import org.codehaus.janino.UnitCompiler;
47  import org.codehaus.janino.WarningHandler;
48  import org.codehaus.janino.Scanner.ScanException;
49  import org.codehaus.janino.UnitCompiler.ErrorHandler;
50  import org.codehaus.janino.util.ClassFile;
51  
52  /**
53   * @author art@gramlich-net.com
54   */
55  public final class JaninoJavaCompiler extends AbstractJavaCompiler {
56  
57      private final Log log = LogFactory.getLog(JaninoJavaCompiler.class);
58  
59      private class CompilingIClassLoader extends IClassLoader {
60  
61          private final Map types = new HashMap();
62          private final ResourceReader resourceReader;
63          private final Map classes;
64          private final Collection problems = new ArrayList();
65  
66          private CompilingIClassLoader(final ResourceReader pResourceReader, final Map pClasses, final ClassLoader classLoader) {
67              super( new ClassLoaderIClassLoader( classLoader ) );
68              resourceReader = pResourceReader;
69              classes = pClasses;
70              super.postConstruct();
71          }
72  
73          protected Collection getProblems() {
74              return problems;
75          }
76          
77          protected IClass findIClass(final String pType) {
78              final String className = Descriptor.toClassName(pType);
79              if (types.containsKey(pType)) {
80                  return (IClass) types.get(pType);
81              }
82              
83              // FIXME: should not be tied to the extension            
84              final String resourceNameFromClass = className.replace('.', '/') + ".java";
85  
86              final byte[] content = resourceReader.getBytes(resourceNameFromClass);
87              if (content == null) {
88                  return null;
89              }
90              final Reader reader = new BufferedReader(new StringReader(new String(content)));
91              Scanner scanner = null;
92              try {
93                  scanner = new Scanner(resourceNameFromClass, reader);
94                  final Java.CompilationUnit unit = new Parser(scanner).parseCompilationUnit();
95                  final UnitCompiler uc = new UnitCompiler(unit, this);
96                  uc.setCompileErrorHandler(new ErrorHandler() {
97                      public void handleError(final String pMessage, final Location pOptionalLocation) throws CompileException {
98                          final CompilationProblem problem = new JaninoCompilationProblem(pOptionalLocation, pMessage, true);
99                          if (problemHandler != null) {
100                             problemHandler.handle(problem);
101                         }
102                         problems.add(problem);
103                     }
104                 });
105                 uc.setWarningHandler(new WarningHandler() {
106                     public void handleWarning(final String pHandle, final String pMessage, final Location pOptionalLocation) {
107                         final CompilationProblem problem = new JaninoCompilationProblem(pOptionalLocation, pMessage, false);
108                         if (problemHandler != null) {
109                             problemHandler.handle(problem);
110                         }
111                         problems.add(problem);
112                     }
113                 });
114                 log.debug("compile " + className);
115                 final ClassFile[] classFiles = uc.compileUnit(DebuggingInformation.ALL);
116                 for (int i = 0; i < classFiles.length; i++) {
117                     log.debug("compiled " + classFiles[i].getThisClassName());
118                     classes.put(classFiles[i].getThisClassName(), classFiles[i].toByteArray());
119                 }
120                 final IClass ic = uc.findClass(className);
121                 if (null != ic) {
122                     types.put(pType, ic);
123                 }
124                 return ic;
125             } catch (final ScanException e) {
126                 problems.add(new JaninoCompilationProblem(e));
127             } catch (final IOException e) {
128                 problems.add(new JaninoCompilationProblem(resourceNameFromClass, "IOException:" + e.getMessage(), true));
129             } catch (final Exception e) {
130                 problems.add(new JaninoCompilationProblem(resourceNameFromClass, "Exception:" + e.getMessage(), true));
131             } finally {
132                 if (scanner != null) {
133                     try {
134                         scanner.close();
135                     } catch (IOException e) {
136                         log.error("IOException occured while compiling " + className, e);
137                     }
138                 }
139             }
140             return null;
141         }
142     }
143 
144     public CompilationResult compile( final String[] pSourceNames, final ResourceReader pResourceReader, final ResourceStore pStore, final ClassLoader pClassLoader, final JavaCompilerSettings pSettings ) {
145 
146         final Map classFilesByName = new HashMap();       
147         
148         final CompilingIClassLoader icl = new CompilingIClassLoader(pResourceReader, classFilesByName, pClassLoader);
149         for (int i = 0; i < pSourceNames.length; i++) {
150             log.debug("compiling " + pSourceNames[i]);
151             try {
152                 icl.loadIClass(Descriptor.fromClassName(ConversionUtils.convertResourceToClassName(pSourceNames[i])));
153             } catch (ClassNotFoundException e) {
154                 log.error("ClassNotFoundException occured while compiling " + pSourceNames[i], e);
155             }
156         }
157         
158         // Store all fully compiled classes
159         for (Iterator i = classFilesByName.entrySet().iterator(); i.hasNext();) {
160             final Map.Entry entry = (Map.Entry)i.next();
161             final String clazzName = (String)entry.getKey(); 
162             pStore.write(ConversionUtils.convertClassToResourcePath(clazzName), (byte[])entry.getValue());
163         }
164         
165         final Collection problems = icl.getProblems();
166         final CompilationProblem[] result = new CompilationProblem[problems.size()];
167         problems.toArray(result);
168         return new CompilationResult(result);
169     }
170 
171     public JavaCompilerSettings createDefaultSettings() {
172         // FIXME
173         return null;
174     }
175     
176 }