/* * Janino - An embedded Java[TM] compiler * * Copyright (c) 2001-2010, Arno Unkrig * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the * following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the * following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.codehaus.janino; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import org.codehaus.janino.util.ClassFile; import org.codehaus.janino.util.resource.DirectoryResourceCreator; import org.codehaus.janino.util.resource.DirectoryResourceFinder; import org.codehaus.janino.util.resource.PathResourceFinder; import org.codehaus.janino.util.resource.Resource; import org.codehaus.janino.util.resource.ResourceCreator; import org.codehaus.janino.util.resource.ResourceFinder; /** * A {@link org.codehaus.janino.JavaSourceClassLoader} that uses a resource storage provided by the application to cache * compiled classes and thus saving unnecessary recompilations. *
* The application provides access to the resource storeage through a pair of a {@link * org.codehaus.janino.util.resource.ResourceFinder} and a {@link org.codehaus.janino.util.resource.ResourceCreator} * (see {@link #CachingJavaSourceClassLoader(ClassLoader, ResourceFinder, String, ResourceFinder, ResourceCreator)}. *
* See {@link org.codehaus.janino.JavaSourceClassLoader#main(String[])} for an example how to use this class. *
* Notice: You must NOT rely on that this class stores some particular data in some particular resources through * the given {@code classFileCacheResourceFinder/Creator}! These serve only as a means for the {@link * CachingJavaSourceClassLoader} to persistently cache some data between invocations. In other words: If you want to * compile {@code .java} files into {@code .class} files, then don't use this class but {@link Compiler} * instead! */ @SuppressWarnings({ "rawtypes", "unchecked" }) public class CachingJavaSourceClassLoader extends JavaSourceClassLoader { private final ResourceFinder classFileCacheResourceFinder; private final ResourceCreator classFileCacheResourceCreator; private final ResourceFinder sourceFinder; /** * See {@link #CachingJavaSourceClassLoader(ClassLoader, ResourceFinder, String, ResourceFinder, ResourceCreator)}. * * @param optionalSourcePath Directories to scan for source files * @param cacheDirectory Directory to use for caching generated class files (see class description) */ public CachingJavaSourceClassLoader( ClassLoader parentClassLoader, File[] optionalSourcePath, String optionalCharacterEncoding, File cacheDirectory ) { this( parentClassLoader, // parentClassLoader ( // sourceFinder optionalSourcePath == null ? (ResourceFinder) new DirectoryResourceFinder(new File(".")) : (ResourceFinder) new PathResourceFinder(optionalSourcePath) ), optionalCharacterEncoding, // optionalCharacterEncoding new DirectoryResourceFinder(cacheDirectory), // classFileCacheResourceFinder new DirectoryResourceCreator(cacheDirectory) // classFileCacheResourceCreator ); } /** * Notice that this class is thread-safe if and only if the {@code classFileCacheResourceCreator} stores its data * atomically, i.e. the {@code classFileCacheResourceFinder} sees the resource written by the {@code * classFileCacheResourceCreator} only after the {@link OutputStream} is closed. *
* In order to make the caching scheme work, both the {@code classFileCacheResourceFinder} and the {@code
* sourceFinder} must support the {@link org.codehaus.janino.util.resource.Resource#lastModified()} method, so that
* the modification time of the source and the class files can be compared.
*
* @param parentClassLoader Attempt to load classes through this one before looking for source files
* @param sourceFinder Finds Java™ source for class {@code pkg.Cls} in resource {@code
* pkg/Cls.java}
* @param optionalCharacterEncoding Encoding of Java™ source or {@code null} for platform default
* encoding
* @param classFileCacheResourceFinder Finds precompiled class {@code pkg.Cls} in resource {@code pkg/Cls.class}
* (see class description)
* @param classFileCacheResourceCreator Stores compiled class {@code pkg.Cls} in resource {@code pkg/Cls.class} (see
* class description)
*/
public
CachingJavaSourceClassLoader(
ClassLoader parentClassLoader,
ResourceFinder sourceFinder,
String optionalCharacterEncoding,
ResourceFinder classFileCacheResourceFinder,
ResourceCreator classFileCacheResourceCreator
) {
super(parentClassLoader, sourceFinder, optionalCharacterEncoding);
this.classFileCacheResourceFinder = classFileCacheResourceFinder;
this.classFileCacheResourceCreator = classFileCacheResourceCreator;
this.sourceFinder = sourceFinder;
}
/**
* Override {@link JavaSourceClassLoader#generateBytecodes(String)} to implement class file caching.
*
* @return String name => byte[] bytecode, or {@code null} if no source code could be found
* @throws ClassNotFoundException Compilation problems or class file cache I/O problems
*/
@Override protected Map