/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.core.dom; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.env.INameEnvironment; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.util.Util; import org.eclipse.jdt.internal.core.NameLookup; import org.eclipse.jdt.internal.core.SearchableEnvironment; /** * Internal implementation of package bindings. */ class PackageBinding implements IPackageBinding { private static final String[] NO_NAME_COMPONENTS = CharOperation.NO_STRINGS; private static final String UNNAMED = Util.EMPTY_STRING; private static final char PACKAGE_NAME_SEPARATOR = '.'; private org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding; private String name; private BindingResolver resolver; private String[] components; PackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding, BindingResolver resolver) { this.binding = binding; this.resolver = resolver; } public IAnnotationBinding[] getAnnotations() { try { INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment; if (!(nameEnvironment instanceof SearchableEnvironment)) return AnnotationBinding.NoAnnotations; NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup; if (nameLookup == null) return AnnotationBinding.NoAnnotations; final String pkgName = getName(); IPackageFragment[] pkgs = nameLookup.findPackageFragments(pkgName, false/*exact match*/); if (pkgs == null) return AnnotationBinding.NoAnnotations; for (int i = 0, len = pkgs.length; i < len; i++) { int fragType = pkgs[i].getKind(); switch(fragType) { case IPackageFragmentRoot.K_SOURCE: String unitName = "package-info.java"; //$NON-NLS-1$ ICompilationUnit unit = pkgs[i].getCompilationUnit(unitName); if (unit != null && unit.exists()) { ASTParser p = ASTParser.newParser(AST.JLS3); p.setSource(unit); p.setResolveBindings(true); p.setUnitName(unitName); p.setFocalPosition(0); p.setKind(ASTParser.K_COMPILATION_UNIT); CompilationUnit domUnit = (CompilationUnit) p.createAST(null); PackageDeclaration pkgDecl = domUnit.getPackage(); if (pkgDecl != null) { List annos = pkgDecl.annotations(); if (annos == null || annos.isEmpty()) return AnnotationBinding.NoAnnotations; IAnnotationBinding[] result = new IAnnotationBinding[annos.size()]; int index=0; for (Iterator it = annos.iterator(); it.hasNext(); index++) { result[index] = ((Annotation) it.next()).resolveAnnotationBinding(); // not resolving bindings if (result[index] == null) return AnnotationBinding.NoAnnotations; } return result; } } break; case IPackageFragmentRoot.K_BINARY: NameEnvironmentAnswer answer = nameEnvironment.findType(TypeConstants.PACKAGE_INFO_NAME, this.binding.compoundName); if (answer != null && answer.isBinaryType()) { IBinaryType type = answer.getBinaryType(); char[][][] missingTypeNames = type.getMissingTypeNames(); IBinaryAnnotation[] binaryAnnotations = type.getAnnotations(); org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] binaryInstances = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.binding.environment, missingTypeNames); org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] allInstances = org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding.addStandardAnnotations(binaryInstances, type.getTagBits(), this.binding.environment); int total = allInstances.length; IAnnotationBinding[] domInstances = new AnnotationBinding[total]; for (int a = 0; a < total; a++) { final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(allInstances[a]); if (annotationInstance == null) {// not resolving binding return AnnotationBinding.NoAnnotations; } domInstances[a] = annotationInstance; } return domInstances; } } } } catch(JavaModelException e) { return AnnotationBinding.NoAnnotations; } return AnnotationBinding.NoAnnotations; } /* * @see IBinding#getName() */ public String getName() { if (this.name == null) { computeNameAndComponents(); } return this.name; } /* * @see IPackageBinding#isUnnamed() */ public boolean isUnnamed() { return getName().equals(UNNAMED); } /* * @see IPackageBinding#getNameComponents() */ public String[] getNameComponents() { if (this.components == null) { computeNameAndComponents(); } return this.components; } /* * @see IBinding#getKind() */ public int getKind() { return IBinding.PACKAGE; } /* * @see IBinding#getModifiers() */ public int getModifiers() { return Modifier.NONE; } /* * @see IBinding#isDeprecated() */ public boolean isDeprecated() { return false; } /** * @see IBinding#isRecovered() */ public boolean isRecovered() { return false; } /** * @see IBinding#isSynthetic() */ public boolean isSynthetic() { return false; } /* * @see IBinding#getJavaElement() */ public IJavaElement getJavaElement() { INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment; // a package binding always has a LooupEnvironment set if (!(nameEnvironment instanceof SearchableEnvironment)) return null; // this is not true in standalone DOM/AST NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup; if (nameLookup == null) return null; IJavaElement[] pkgs = nameLookup.findPackageFragments(getName(), false/*exact match*/); if (pkgs == null) return null; if (pkgs.length == 0) { // add additional tracing as this should not happen org.eclipse.jdt.internal.core.util.Util.log( new Status( IStatus.WARNING, JavaCore.PLUGIN_ID, "Searching for package " + getName() + " returns an empty array")); //$NON-NLS-1$ //$NON-NLS-2$ return null; } return pkgs[0]; } /* * @see IBinding#getKey() */ public String getKey() { return new String(this.binding.computeUniqueKey()); } /* * @see IBinding#isEqualTo(Binding) * @since 3.1 */ public boolean isEqualTo(IBinding other) { if (other == this) { // identical binding - equal (key or no key) return true; } if (other == null) { // other binding missing return false; } if (!(other instanceof PackageBinding)) { return false; } org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding2 = ((PackageBinding) other).binding; return CharOperation.equals(this.binding.compoundName, packageBinding2.compoundName); } private void computeNameAndComponents() { char[][] compoundName = this.binding.compoundName; if (compoundName == CharOperation.NO_CHAR_CHAR || compoundName == null) { this.name = UNNAMED; this.components = NO_NAME_COMPONENTS; } else { int length = compoundName.length; this.components = new String[length]; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length - 1; i++) { this.components[i] = new String(compoundName[i]); buffer.append(compoundName[i]).append(PACKAGE_NAME_SEPARATOR); } this.components[length - 1] = new String(compoundName[length - 1]); buffer.append(compoundName[length - 1]); this.name = buffer.toString(); } } /* * For debugging purpose only. * @see java.lang.Object#toString() */ public String toString() { return this.binding.toString(); } }