/* JaninoDynamicCompiler.java created 2007-11-07 * */ package org.signalml.compilation.janino; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import org.apache.log4j.Logger; import org.codehaus.janino.DebuggingInformation; import org.codehaus.janino.JavaSourceClassLoader; import org.signalml.compilation.CompilationException; import org.signalml.compilation.DynamicCompiler; import org.signalml.compilation.JavaCodeProvider; /** JaninoDynamicCompiler * * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. */ public class JaninoDynamicCompiler implements DynamicCompiler { protected static final Logger logger = Logger.getLogger(JaninoDynamicCompiler.class); @Override public Class<?> compile(File srcDir, String fqClassName, JavaCodeProvider codeProvider) throws CompilationException { String[] parts = fqClassName.split("\\."); boolean ok; if (parts.length < 1) { throw new CompilationException("Bad class name [" + fqClassName + "]"); } File dir = srcDir.getAbsoluteFile(); for (int i=0; i<parts.length-1; i++) { dir = new File(dir, parts[i]); if (!dir.exists()) { ok = dir.mkdir(); if (!ok) { throw new CompilationException("Failed to create directory [" + dir.getAbsolutePath() + "]"); } } } File javaFile = new File(dir, parts[parts.length-1] + ".java"); if (!javaFile.exists()) { BufferedWriter writer = null; try { writer = new BufferedWriter(new FileWriter(javaFile)); String code = codeProvider.getCode(); writer.write(code); } catch (IOException ex) { } finally { if (writer != null) { try { writer.close(); } catch (IOException ex) { } } } } ClassLoader parentClassLoader = this.getClass().getClassLoader(); if (logger.isDebugEnabled()) { logger.debug("Using srcDir [" + srcDir.getAbsolutePath() + "]"); logger.debug("Using java file [" + javaFile.getAbsolutePath() + "]"); logger.debug("Using class name [" + fqClassName + "]"); logger.debug("Using parent class loader [" + parentClassLoader + "] class [" + (parentClassLoader != null ? parentClassLoader.getClass().getName() : "(null)") + "]"); ClassLoader upperClassLoader = parentClassLoader.getParent(); while (upperClassLoader != null) { logger.debug("Using upper class loader [" + upperClassLoader + "] class [" + upperClassLoader.getClass().getName() + "]"); upperClassLoader = upperClassLoader.getParent(); } } String loaderPath = srcDir.getAbsolutePath(); loaderPath = (loaderPath.startsWith("/") ? "" : "/") + loaderPath + (loaderPath.endsWith("/") ? "" : "/"); String urlPath = "file://" + loaderPath.replace('\\', '/'); logger.debug("Using url path [" + urlPath + "]"); URL url; try { url = new URL(urlPath); } catch (MalformedURLException ex) { logger.error("Failed to parse URL [" + urlPath + "]", ex); throw new CompilationException("Failed to parse URL", ex); } return loadClassInternal(new URL[] { url }, new File[] { srcDir }, fqClassName, parentClassLoader); } @Override public Class<?> compile(File[] path, String fqClassName) throws CompilationException { ClassLoader parentClassLoader = this.getClass().getClassLoader(); if (logger.isDebugEnabled()) { for (File file : path) { logger.debug("Using classpath [" + file.getAbsolutePath() + "]"); } logger.debug("Using class name [" + fqClassName + "]"); logger.debug("Using parent class loader [" + parentClassLoader + "] class [" + (parentClassLoader != null ? parentClassLoader.getClass().getName() : "(null)") + "]"); ClassLoader upperClassLoader = parentClassLoader.getParent(); while (upperClassLoader != null) { logger.debug("Using upper class loader [" + upperClassLoader + "] class [" + upperClassLoader.getClass().getName() + "]"); upperClassLoader = upperClassLoader.getParent(); } } URL[] classPath = new URL[path.length]; File[] sourcePath = new File[path.length]; int sourceIdx = 0; for (int i=0; i<path.length; i++) { try { classPath[i] = path[i].toURI().toURL(); } catch (MalformedURLException ex) { logger.warn("Failed to convert path [" + path[i].getAbsolutePath() + "] to url", ex); } if (path[i].exists() && path[i].isDirectory()) { sourcePath[sourceIdx] = path[i]; sourceIdx++; } } sourcePath = Arrays.copyOf(sourcePath, sourceIdx); return loadClassInternal(classPath, sourcePath, fqClassName, parentClassLoader); } private Class<?> loadClassInternal(URL[] classPath, File[] sourcePath, String fqClassName, ClassLoader parentClassLoader) throws CompilationException { URLClassLoader loader = new URLClassLoader(classPath, parentClassLoader); ClassLoader cl = new JavaSourceClassLoader( loader, // parentClassLoader sourcePath, // optionalSourcePath (String) null, // optionalCharacterEncoding DebuggingInformation.NONE // debuggingInformation ); Class<?> clazz = null; try { clazz = cl.loadClass(fqClassName); } catch (ClassNotFoundException ex) { throw new CompilationException("Failed to load class", ex); } if (clazz == null) { throw new CompilationException("Failed to load class, null returned"); } return clazz; } }