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 }