/********************************************************************** * 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.internal.tools; import org.ant4eclipse.lib.core.Assure; import org.ant4eclipse.lib.core.ClassName; import org.ant4eclipse.lib.core.logging.A4ELogging; import org.ant4eclipse.lib.jdt.ecj.ClassFile; import org.ant4eclipse.lib.jdt.ecj.ClassFileLoader; import org.ant4eclipse.lib.jdt.ecj.SourceFile; import org.eclipse.jdt.internal.compiler.env.INameEnvironment; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; /** * <p> * Adapter class to utilize class file loaders in the eclipse java compiler. * </p> * * @author Gerd Wuetherich (gerd@gerd-wuetherich.de) * @author Nils Hartmann (nils@nilshartmann.net) */ public class NameEnvironmentImpl implements INameEnvironment { // the debug flag private static boolean DEBUG_ALL = false; // the debug flag private static boolean DEBUG_TYPE_NOT_FOUND = false; static { DEBUG_ALL = "true".equals(System.getProperty("ant4eclipse.debug.nameenv")); DEBUG_TYPE_NOT_FOUND = "true".equals(System.getProperty("ant4eclipse.debug.nameenv.missingtypes")); } /** used to find binary type as requested by the compiler */ private ClassFileLoader _classFileLoader; /** * <p> * Create a new instance of type {@link NameEnvironmentImpl}. * </p> * * @param classFileLoader * the class file loader to use. */ public NameEnvironmentImpl(ClassFileLoader classFileLoader) { Assure.notNull("classFileLoader", classFileLoader); this._classFileLoader = classFileLoader; if (DEBUG_ALL || DEBUG_TYPE_NOT_FOUND) { A4ELogging.info("NameEnvironment tracing enabled."); } } /** * @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#cleanup() */ public void cleanup() { // nothing to do here... } /** * {@inheritDoc} */ public NameEnvironmentAnswer findType(char[][] compoundTypeName) { // convert char array to string(buffer) StringBuffer buffer = new StringBuffer(); for (int i = 0; i < compoundTypeName.length; i++) { buffer.append(new String(compoundTypeName[i])); if (i < compoundTypeName.length - 1) { buffer.append("."); } } // find class NameEnvironmentAnswer answer = findClass(buffer.toString()); return answer; } /** * {@inheritDoc} */ public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { StringBuffer result = new StringBuffer(); if (packageName != null) { for (char[] element : packageName) { result.append(new String(element)).append("."); } } result.append(new String(typeName)); return findClass(result.toString()); } /** * {@inheritDoc} * * This method returns true if the given packageName is a valid package. * * <p> * Note that this method returns true regardless of any OSGi visibility constraints. * <p> * This method also returns true for top level packages */ public boolean isPackage(char[][] parentPackageName, char[] packageName) { String qualifiedPackageName = toJavaName(parentPackageName); if (qualifiedPackageName.length() > 0) { qualifiedPackageName += "." + new String(packageName); } else { qualifiedPackageName = new String(packageName); } boolean packageFound = this._classFileLoader.hasPackage(qualifiedPackageName); if (DEBUG_ALL) { if (packageFound) { A4ELogging.info("Package '%s' found...", qualifiedPackageName); } else { A4ELogging.info("Package '%s' not found...", qualifiedPackageName); } } return packageFound; } /** * @param className * @return */ protected NameEnvironmentAnswer findClass(String className) { Assure.notNull("className", className); return findClass(ClassName.fromQualifiedClassName(className)); } /** * <p> * Returns a {@link NameEnvironmentAnswer} for the class that is represented by the given {@link ClassName} instance. * </p> * * @param className * represents the class name * @return a {@link NameEnvironmentAnswer} */ protected NameEnvironmentAnswer findClass(ClassName className) { // load class file from class file loader ClassFile classFile = this._classFileLoader.loadClass(className); // return new NameEnvironmentAnswer if classFile was found if (classFile != null) { if (DEBUG_ALL) { A4ELogging.info("Loading class '%s' from '%s'.", className.getQualifiedClassName(), classFile .getLibraryLocation()); } return new NameEnvironmentAnswer(classFile.getBinaryType(), (classFile.hasAccessRestriction() ? classFile .getAccessRestriction() : null)); } // load source file from class file loader // TODO: AccessRestictions for source files!! SourceFile sourceFile = this._classFileLoader.loadSource(className); // load source file from class file loader if (sourceFile != null) { if (DEBUG_ALL) { A4ELogging.info("Loading class '%s' as source from '%s'.", className.getQualifiedClassName(), sourceFile .getSourceFile().getAbsolutePath()); } // TODO: AccessRestictions for source files!! return new NameEnvironmentAnswer(new CompilationUnitImpl(sourceFile), null); } // else return null if (DEBUG_TYPE_NOT_FOUND) { A4ELogging.info("Could not load class '%s'.", className.getQualifiedClassName()); } return null; } /** * <p> * Converts the given char array to a java name (e.g. "net.sf.ant4eclipse"). * </p> * * @param array * the array to convert. * @return the */ private static String toJavaName(char[][] array) { StringBuffer result = new StringBuffer(); if (array != null) { for (int i = 0; i < array.length; i++) { result.append(new String(array[i])); if (i < array.length - 1) { result.append("."); } } } return result.toString(); } }