/********************************************************************** * Copyright (c) 2005-2009 ant4eclipse project team. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nils Hartmann, Daniel Kasmeroglu, Gerd Wuetherich **********************************************************************/ package org.ant4eclipse.lib.jdt.ecj; import java.io.File; import java.util.Arrays; import org.ant4eclipse.lib.core.util.PerformanceLogging; import org.ant4eclipse.lib.jdt.ecj.internal.tools.loader.ClassFileLoaderCache; import org.ant4eclipse.lib.jdt.ecj.internal.tools.loader.ClasspathClassFileLoaderImpl; import org.ant4eclipse.lib.jdt.ecj.internal.tools.loader.CompoundClassFileLoaderImpl; import org.ant4eclipse.lib.jdt.ecj.internal.tools.loader.FilteringClassFileLoader; /** * <p> * Provides static factory methods to create class file finders. * </p> * * @author Gerd Wütherich (gerd@gerd-wuetherich.de) */ public class ClassFileLoaderFactory { // /** // * <p> // * Creates an new instance of type {@link ClassFileLoader}, that can load {@link ClassFile ClassFiles} from an array // * of files (jar files or directories). // * </p> // * // * @param source // * the file, that represents the source (e.g. a jar file, the root directory of an "exploded" bundle or the // * root directory of an eclipse project) for the {@link ClassFileLoader}. // * @param type // * the type of the source. Possible values are {@link EcjAdapter#LIBRARY} and {@link EcjAdapter#PROJECT}. // * @param classpathEntries // * the class path entries for the {@link ClassFileLoader}. // * // * @return creates an new instance of type {@link ClassFileLoader}, that can load {@link ClassFile ClassFiles} from // an // * array of files (jar files or directories). // */ // public static ClassFileLoader createClasspathClassFileLoader(File source, byte type, File[] classpathEntries) { // PerformanceLogging.start(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneSourcePath"); // PerformanceLogging.start(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneSourcePath-" + source); // try { // return new ClasspathClassFileLoaderImpl(source, type, classpathEntries); // } finally { // PerformanceLogging.stop(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneSourcePath"); // PerformanceLogging.stop(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneSourcePath-" + source); // } // } /** * <p> * </p> * * @param source * @param type * @param classpathEntries * @param sourcepathEntries * @return */ public static ClassFileLoader createClasspathClassFileLoader(File source, byte type, File[] classpathEntries, File[] sourcepathEntries) { PerformanceLogging.start(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-mitSourcePath"); PerformanceLogging.start(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-mitSourcePath-" + source); try { ClassFileLoaderCacheKey cacheKey = new ClassFileLoaderCacheKey(source, type, classpathEntries, sourcepathEntries); // Try to get already initialized ClassFileLoader from cache ClassFileLoader classFileLoader = ClassFileLoaderCache.getInstance().getClassFileLoader(cacheKey); if (classFileLoader == null) { // Create new ClassFileLoader classFileLoader = new ClasspathClassFileLoaderImpl(source, type, classpathEntries, sourcepathEntries); // add ClassFileLoader to Cache ClassFileLoaderCache.getInstance().storeClassFileLoader(cacheKey, classFileLoader); } // Return the ClassFileLoader return classFileLoader; } finally { // Stop performance logging PerformanceLogging.stop(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-mitSourcePath"); PerformanceLogging.stop(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-mitSourcePath-" + source); } } private static class ClassFileLoaderCacheKey { private final File _source; private final byte _type; private final File[] _classpathEntries; private final File[] _sourcepathEntries; public ClassFileLoaderCacheKey(File source, byte type, File[] classpathEntries, File[] sourcepathEntries) { super(); this._source = source; this._type = type; this._classpathEntries = classpathEntries; this._sourcepathEntries = sourcepathEntries; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(this._classpathEntries); result = prime * result + ((this._source == null) ? 0 : this._source.hashCode()); result = prime * result + Arrays.hashCode(this._sourcepathEntries); result = prime * result + this._type; return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } ClassFileLoaderCacheKey other = (ClassFileLoaderCacheKey) obj; if (!Arrays.equals(this._classpathEntries, other._classpathEntries)) { return false; } if (this._source == null) { if (other._source != null) { return false; } } else if (!this._source.equals(other._source)) { return false; } if (!Arrays.equals(this._sourcepathEntries, other._sourcepathEntries)) { return false; } if (this._type != other._type) { return false; } return true; } @Override public String toString() { return "ClassFileLoaderCacheKey [_source=" + this._source + ", _type=" + this._type + ", _classpathEntries=" + Arrays.toString(this._classpathEntries) + ", _sourcepathEntries=" + Arrays.toString(this._sourcepathEntries) + "]"; } } // /** // * <p> // * </p> // * // * @param classPathEntry // * @param type // * @param sourcePathEntry // * @return // */ // public static ClassFileLoader createClasspathClassFileLoader(File classPathEntry, byte type, File sourcePathEntry) // { // PerformanceLogging.start(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneBinaryPath"); // PerformanceLogging.start(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneBinaryPath-" // + classPathEntry); // try { // return new ClasspathClassFileLoaderImpl(classPathEntry, type, sourcePathEntry); // } finally { // PerformanceLogging.stop(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneBinaryPath"); // PerformanceLogging.stop(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneBinaryPath-" // + classPathEntry); // } // } /** * <p> * Creates an new instance of type {@link ClassFileLoader}, that can load {@link ClassFile ClassFiles} from a jar file * or directory. * </p> * * @param entry * the class path entry for the {@link ClassFileLoader}. * @param type * the type of the source. Possible values are {@link EcjAdapter#LIBRARY} and {@link EcjAdapter#PROJECT}. * * @return a new instance of type {@link ClassFileLoader}. */ public static ClassFileLoader createClasspathClassFileLoader(File entry, byte type) { PerformanceLogging.start(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneAlles"); PerformanceLogging.start(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneAlles-" + entry); try { String cacheKey = String.valueOf(entry) + "/" + type; // Try to get ClassFileLoader from cache ClassFileLoader classFileLoader = ClassFileLoaderCache.getInstance().getClassFileLoader(cacheKey); if (classFileLoader == null) { // Create new ClassFileLoader classFileLoader = new ClasspathClassFileLoaderImpl(entry, type); // add to cache ClassFileLoaderCache.getInstance().storeClassFileLoader(cacheKey, classFileLoader); } return classFileLoader; } finally { PerformanceLogging.stop(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneAlles"); PerformanceLogging.stop(ClassFileLoaderFactory.class, "createClasspathClassFileLoader-ohneAlles-" + entry); } } /** * <p> * Creates an new instance of type {@link ClassFileLoader}, that can load classes from multiple underlying class file * loaders. * </p> * * @param classFileLoaders * the class file loaders that should be contained in the compound class file loader. * @return an new instance of type {@link ClassFileLoader}, that can load classes from multiple underlying class file * loaders. */ public static ClassFileLoader createCompoundClassFileLoader(ClassFileLoader[] classFileLoaders) { PerformanceLogging.start(ClassFileLoaderFactory.class, "createCompoundClassFileLoader"); try { return new CompoundClassFileLoaderImpl(classFileLoaders); } finally { PerformanceLogging.stop(ClassFileLoaderFactory.class, "createCompoundClassFileLoader"); } } /** * <p> * Creates an new instance of type {@link ClassFileLoader}, that can filter the access to classes in an underlying * class file loader. * </p> * * @param classFileLoader * the underlying class file loader * @param filter * the filter * @return the class file loader */ public static ClassFileLoader createFilteringClassFileLoader(ClassFileLoader classFileLoader, String filter) { PerformanceLogging.start(ClassFileLoaderFactory.class, "createFilteringClassFileLoader"); try { return new FilteringClassFileLoader(classFileLoader, filter); } finally { PerformanceLogging.stop(ClassFileLoaderFactory.class, "createFilteringClassFileLoader"); } } }