All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.codehaus.janino.CachingJavaSourceClassLoader Maven / Gradle / Ivy

There is a newer version: 5.4.0
Show newest version

/*
 * Janino - An embedded Java[TM] com.hazelcast.com.iler
 *
 * Copyright (c) 2001-2010 Arno Unkrig. All rights reserved.
 * Copyright (c) 2015-2016 TIBCO Software Inc. 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. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
 *       products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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 com.hazelcast.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 com.hazelcast.org.codehaus.com.hazelcast.com.ons.nullanalysis.Nullable;
import com.hazelcast.org.codehaus.janino.util.ClassFile;
import com.hazelcast.org.codehaus.janino.util.resource.DirectoryResourceCreator;
import com.hazelcast.org.codehaus.janino.util.resource.DirectoryResourceFinder;
import com.hazelcast.org.codehaus.janino.util.resource.PathResourceFinder;
import com.hazelcast.org.codehaus.janino.util.resource.Resource;
import com.hazelcast.org.codehaus.janino.util.resource.ResourceCreator;
import com.hazelcast.org.codehaus.janino.util.resource.ResourceFinder;

/**
 * A {@link com.hazelcast.org.codehaus.janino.JavaSourceClassLoader} that uses a resource storage provided by the application to
 * cache com.hazelcast.com.iled classes and thus saving unnecessary recompilations.
 * 

* The application provides access to the resource storage through a pair of a {@link * com.hazelcast.org.codehaus.janino.util.resource.ResourceFinder} and a {@link com.hazelcast.org.codehaus.janino.util.resource.ResourceCreator} * (see {@link #CachingJavaSourceClassLoader(ClassLoader, ResourceFinder, String, ResourceFinder, ResourceCreator)}. *

*

* See {@link com.hazelcast.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 * com.hazelcast.com.ile {@code .java} files into {@code .class} files, then don't use this class but {@link Compiler} * instead! *

*/ 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, @Nullable File[] optionalSourcePath, @Nullable 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 classFileCacheResourceCreator stores its * data atomically, i.e. the 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 classFileCacheResourceFinder and the {@code * sourceFinder} must support the {@link com.hazelcast.org.codehaus.janino.util.resource.Resource#lastModified()} method, so * that the modification time of the source and the class files can be com.hazelcast.com.ared. *

* * @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 com.hazelcast.com.iled class {@code pkg.Cls} in resource {@code pkg/Cls.class} (see * class description) */ public CachingJavaSourceClassLoader( ClassLoader parentClassLoader, ResourceFinder sourceFinder, @Nullable String optionalCharacterEncoding, ResourceFinder classFileCacheResourceFinder, ResourceCreator classFileCacheResourceCreator ) { super(parentClassLoader, sourceFinder, optionalCharacterEncoding); this.classFileCacheResourceFinder = classFileCacheResourceFinder; this.classFileCacheResourceCreator = classFileCacheResourceCreator; this.sourceFinder = sourceFinder; } /** * Overrides {@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 @Nullable protected Map generateBytecodes(String className) throws ClassNotFoundException { // Check whether a class file resource exists in the cache. { Resource classFileResource = this.classFileCacheResourceFinder.findResource( ClassFile.getClassFileResourceName(className) ); if (classFileResource != null) { // Check whether a source file resource exists. Resource sourceResource = this.sourceFinder.findResource(ClassFile.getSourceResourceName(className)); if (sourceResource == null) return null; // Check whether the class file is up-to-date. if (sourceResource.lastModified() < classFileResource.lastModified()) { // Yes, it is... read the bytecode from the file and define the class. byte[] bytecode; try { bytecode = CachingJavaSourceClassLoader.readResource(classFileResource); } catch (IOException ex) { throw new ClassNotFoundException("Reading class file from \"" + classFileResource + "\"", ex); } Map m = new HashMap(); m.put(className, bytecode); return m; } } } // Cache miss... generate the bytecode from source. Map bytecodes = super.generateBytecodes(className); if (bytecodes == null) return null; // Write the generated bytecodes to the class file cache. for (Map.Entry me : bytecodes.entrySet()) { String className2 = (String) me.getKey(); byte[] bytecode = (byte[]) me.getValue(); try { CachingJavaSourceClassLoader.writeResource( this.classFileCacheResourceCreator, ClassFile.getClassFileResourceName(className2), bytecode ); } catch (IOException ex) { throw new ClassNotFoundException( "Writing class file to \"" + ClassFile.getClassFileResourceName(className2) + "\"", ex ); } } return bytecodes; } /** * Reads all bytes from the given resource. */ private static byte[] readResource(Resource r) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; InputStream is = r.open(); try { for (;;) { int cnt = is.read(buffer); if (cnt == -1) break; baos.write(buffer, 0, cnt); } } finally { try { is.close(); } catch (IOException ex) {} } return baos.toByteArray(); } /** * Creates a resource with the given name and store the data in it. */ private static void writeResource(ResourceCreator resourceCreator, String resourceName, byte[] data) throws IOException { OutputStream os = resourceCreator.createResource(resourceName); try { os.write(data); } finally { try { os.close(); } catch (IOException ex) {} } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy