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.ByteArrayInputStream;
021 import java.io.ByteArrayOutputStream;
022 import java.io.IOException;
023 import java.io.InputStream;
024 import java.io.OutputStream;
025 import java.util.ArrayList;
026 import java.util.Collection;
027
028 import org.apache.commons.jci.problems.CompilationProblem;
029 import org.apache.commons.jci.readers.ResourceReader;
030 import org.apache.commons.jci.stores.ResourceStore;
031 import org.apache.commons.logging.Log;
032 import org.apache.commons.logging.LogFactory;
033 import org.codehaus.commons.compiler.CompileException;
034 import org.codehaus.commons.compiler.LocatedException;
035 import org.codehaus.commons.compiler.Location;
036 import org.codehaus.janino.ClassLoaderIClassLoader;
037 import org.codehaus.janino.Compiler;
038 import org.codehaus.janino.FilterWarningHandler;
039 import org.codehaus.janino.UnitCompiler.ErrorHandler;
040 import org.codehaus.janino.WarningHandler;
041 import org.codehaus.janino.util.StringPattern;
042 import org.codehaus.janino.util.resource.Resource;
043 import org.codehaus.janino.util.resource.ResourceCreator;
044 import org.codehaus.janino.util.resource.ResourceFinder;
045
046 /**
047 * @author tcurdt
048 */
049 public final class JaninoJavaCompiler extends AbstractJavaCompiler {
050
051 private final Log log = LogFactory.getLog(JaninoJavaCompiler.class);
052
053 private final JaninoJavaCompilerSettings defaultSettings;
054
055 public JaninoJavaCompiler() {
056 this(new JaninoJavaCompilerSettings());
057 }
058
059 public JaninoJavaCompiler( final JaninoJavaCompilerSettings pSettings ) {
060 defaultSettings = pSettings;
061 }
062
063 private final static class JciResource implements Resource {
064
065 private final String name;
066 private final byte[] bytes;
067
068 public JciResource( final String pName, final byte[] pBytes ) {
069 name = pName;
070 bytes = pBytes;
071 }
072
073 public String getFileName() {
074 return name;
075 }
076
077 public long lastModified() {
078 return 0;
079 }
080
081 public InputStream open() throws IOException {
082 return new ByteArrayInputStream(bytes);
083 }
084 }
085
086 private final static class JciOutputStream extends ByteArrayOutputStream {
087
088 private final String name;
089 private final ResourceStore store;
090
091 public JciOutputStream( final String pName, final ResourceStore pStore ) {
092 name = pName;
093 store = pStore;
094 }
095
096 @Override
097 public void close() throws IOException {
098 super.close();
099
100 final byte[] bytes = toByteArray();
101
102 store.write(name, bytes);
103 }
104 }
105
106 public CompilationResult compile( final String[] pSourceNames, final ResourceReader pResourceReader, final ResourceStore pStore, final ClassLoader pClassLoader, final JavaCompilerSettings pSettings ) {
107
108 final Collection<CompilationProblem> problems = new ArrayList<CompilationProblem>();
109
110 final StringPattern[] pattern = StringPattern.PATTERNS_NONE;
111
112 final Compiler compiler = new Compiler(
113 new ResourceFinder() {
114 @Override
115 public Resource findResource( final String pSourceName ) {
116 final byte[] bytes = pResourceReader.getBytes(pSourceName);
117
118 if (bytes == null) {
119 log.debug("failed to find source " + pSourceName);
120 return null;
121 }
122
123 log.debug("reading " + pSourceName + " (" + bytes.length + ")");
124
125 return new JciResource(pSourceName, bytes);
126 }
127 },
128 new ClassLoaderIClassLoader(pClassLoader),
129 new ResourceFinder() {
130 @Override
131 public Resource findResource( final String pResourceName ) {
132 final byte[] bytes = pStore.read(pResourceName);
133
134 if (bytes == null) {
135 log.debug("failed to find " + pResourceName);
136 return null;
137 }
138
139 log.debug("reading " + pResourceName + " (" + bytes.length + ")");
140
141 return new JciResource(pResourceName, bytes);
142 }
143 },
144 new ResourceCreator() {
145 public OutputStream createResource( final String pResourceName ) throws IOException {
146 return new JciOutputStream(pResourceName, pStore);
147 }
148
149 public boolean deleteResource( final String pResourceName ) {
150 log.debug("removing " + pResourceName);
151
152 pStore.remove(pResourceName);
153 return true;
154 }
155 },
156 pSettings.getSourceEncoding(),
157 false,
158 pSettings.isDebug(),
159 pSettings.isDebug(),
160 pSettings.isDebug(),
161 new FilterWarningHandler(pattern, new WarningHandler() {
162 public void handleWarning( final String pHandle, final String pMessage, final Location pLocation ) {
163 final CompilationProblem problem = new JaninoCompilationProblem(pLocation.getFileName(), pLocation, pMessage, false);
164 if (problemHandler != null) {
165 problemHandler.handle(problem);
166 }
167 problems.add(problem);
168 }
169 })
170 );
171
172
173 compiler.setCompileErrorHandler(new ErrorHandler() {
174 public void handleError( final String pMessage, final Location pLocation ) throws CompileException {
175 final CompilationProblem problem = new JaninoCompilationProblem(pLocation.getFileName(), pLocation, pMessage, true);
176 if (problemHandler != null) {
177 problemHandler.handle(problem);
178 }
179 problems.add(problem);
180 }
181 });
182
183
184 final Resource[] resources = new Resource[pSourceNames.length];
185 for (int i = 0; i < pSourceNames.length; i++) {
186 log.debug("compiling " + pSourceNames[i]);
187 final byte[] source = pResourceReader.getBytes(pSourceNames[i]);
188 resources[i] = new JciResource(pSourceNames[i], source);
189 }
190
191 try {
192 compiler.compile(resources);
193 } catch ( LocatedException e ) {
194 problems.add(new JaninoCompilationProblem(e));
195 } catch ( IOException e ) {
196 // low level problems reading or writing bytes
197 log.error("this error should have been cought before", e);
198 }
199 final CompilationProblem[] result = new CompilationProblem[problems.size()];
200 problems.toArray(result);
201 return new CompilationResult(result);
202 }
203
204 public JavaCompilerSettings createDefaultSettings() {
205 return new JaninoJavaCompilerSettings(defaultSettings);
206 }
207
208 }