| /******************************************************************************* |
| * Copyright (c) 2000, 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.core; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.jdt.core.*; |
| import org.eclipse.jdt.core.IClasspathEntry; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.internal.core.util.Util; |
| |
| /** |
| * Info for IJavaProject. |
| * <p> |
| * Note: <code>getChildren()</code> returns all of the <code>IPackageFragmentRoots</code> |
| * specified on the classpath for the project. This can include roots external to the |
| * project. See <code>JavaProject#getAllPackageFragmentRoots()</code> and |
| * <code>JavaProject#getPackageFragmentRoots()</code>. To get only the <code>IPackageFragmentRoots</code> |
| * that are internal to the project, use <code>JavaProject#getChildren()</code>. |
| */ |
| |
| /* package */ |
| class JavaProjectElementInfo extends OpenableElementInfo { |
| |
| /** |
| * A array with all the non-java resources contained by this PackageFragment |
| */ |
| private Object[] nonJavaResources; |
| |
| /* |
| * A cache of all package fragment roots of this project. |
| */ |
| public IPackageFragmentRoot[] allPkgFragmentRootsCache; |
| |
| /* |
| * A cache of all package fragments in this project. |
| * (a map from String (the package name) to IPackageFragment[] (the package fragments with this name) |
| */ |
| private HashMap allPkgFragmentsCache; |
| |
| /** |
| * Create and initialize a new instance of the receiver |
| */ |
| public JavaProjectElementInfo() { |
| this.nonJavaResources = null; |
| } |
| |
| /** |
| * Compute the non-java resources contained in this java project. |
| */ |
| private Object[] computeNonJavaResources(JavaProject project) { |
| |
| // determine if src == project and/or if bin == project |
| IPath projectPath = project.getProject().getFullPath(); |
| boolean srcIsProject = false; |
| boolean binIsProject = false; |
| char[][] exclusionPatterns = null; |
| IClasspathEntry[] classpath = null; |
| IPath projectOutput = null; |
| try { |
| classpath = project.getResolvedClasspath(true/*ignore unresolved variable*/); |
| for (int i = 0; i < classpath.length; i++) { |
| IClasspathEntry entry = classpath[i]; |
| if (projectPath.equals(entry.getPath())) { |
| srcIsProject = true; |
| exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars(); |
| break; |
| } |
| } |
| projectOutput = project.getOutputLocation(); |
| binIsProject = projectPath.equals(projectOutput); |
| } catch (JavaModelException e) { |
| // ignore |
| } |
| |
| Object[] resources = new IResource[5]; |
| int resourcesCounter = 0; |
| try { |
| IResource[] members = ((IContainer) project.getResource()).members(); |
| for (int i = 0, max = members.length; i < max; i++) { |
| IResource res = members[i]; |
| switch (res.getType()) { |
| case IResource.FILE : |
| IPath resFullPath = res.getFullPath(); |
| String resName = res.getName(); |
| |
| // ignore a jar file on the classpath |
| if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resName) && this.isClasspathEntryOrOutputLocation(resFullPath, classpath, projectOutput)) { |
| break; |
| } |
| // ignore .java file if src == project |
| if (srcIsProject |
| && Util.isValidCompilationUnitName(resName) |
| && !Util.isExcluded(res, exclusionPatterns)) { |
| break; |
| } |
| // ignore .class file if bin == project |
| if (binIsProject && Util.isValidClassFileName(resName)) { |
| break; |
| } |
| // else add non java resource |
| if (resources.length == resourcesCounter) { |
| // resize |
| System.arraycopy( |
| resources, |
| 0, |
| (resources = new IResource[resourcesCounter * 2]), |
| 0, |
| resourcesCounter); |
| } |
| resources[resourcesCounter++] = res; |
| break; |
| case IResource.FOLDER : |
| resFullPath = res.getFullPath(); |
| |
| // ignore non-excluded folders on the classpath or that correspond to an output location |
| if ((srcIsProject && !Util.isExcluded(res, exclusionPatterns) && Util.isValidFolderNameForPackage(res.getName())) |
| || this.isClasspathEntryOrOutputLocation(resFullPath, classpath, projectOutput)) { |
| break; |
| } |
| // else add non java resource |
| if (resources.length == resourcesCounter) { |
| // resize |
| System.arraycopy( |
| resources, |
| 0, |
| (resources = new IResource[resourcesCounter * 2]), |
| 0, |
| resourcesCounter); |
| } |
| resources[resourcesCounter++] = res; |
| } |
| } |
| if (resources.length != resourcesCounter) { |
| System.arraycopy( |
| resources, |
| 0, |
| (resources = new IResource[resourcesCounter]), |
| 0, |
| resourcesCounter); |
| } |
| } catch (CoreException e) { |
| resources = NO_NON_JAVA_RESOURCES; |
| resourcesCounter = 0; |
| } |
| return resources; |
| } |
| |
| IPackageFragmentRoot[] getAllPackageFragmentRoots(JavaProject project) { |
| if (this.allPkgFragmentRootsCache == null) { |
| try { |
| this.allPkgFragmentRootsCache = project.getAllPackageFragmentRoots(); |
| } catch (JavaModelException e) { |
| // project does not exist: cannot happend since this is the info of the project |
| } |
| } |
| return this.allPkgFragmentRootsCache; |
| } |
| |
| HashMap getAllPackageFragments(JavaProject project) { |
| if (this.allPkgFragmentsCache == null) { |
| HashMap cache = new HashMap(); |
| IPackageFragmentRoot[] roots = getAllPackageFragmentRoots(project); |
| IPackageFragment[] frags = this.getPackageFragmentsInRoots(roots, project); |
| for (int i= 0; i < frags.length; i++) { |
| IPackageFragment fragment= frags[i]; |
| IPackageFragment[] entry= (IPackageFragment[]) cache.get(fragment.getElementName()); |
| if (entry == null) { |
| entry= new IPackageFragment[1]; |
| entry[0]= fragment; |
| cache.put(fragment.getElementName(), entry); |
| } else { |
| IPackageFragment[] copy= new IPackageFragment[entry.length + 1]; |
| System.arraycopy(entry, 0, copy, 0, entry.length); |
| copy[entry.length]= fragment; |
| cache.put(fragment.getElementName(), copy); |
| } |
| } |
| this.allPkgFragmentsCache = cache; |
| } |
| return this.allPkgFragmentsCache; |
| } |
| |
| /** |
| * Returns an array of non-java resources contained in the receiver. |
| */ |
| Object[] getNonJavaResources(JavaProject project) { |
| |
| if (this.nonJavaResources == null) { |
| this.nonJavaResources = computeNonJavaResources(project); |
| } |
| return this.nonJavaResources; |
| } |
| |
| /** |
| * Returns all the package fragments found in the specified |
| * package fragment roots. Make sure the returned fragments have the given |
| * project as great parent. This ensures the name lookup will not refer to another |
| * project (through jar package fragment roots) |
| */ |
| private IPackageFragment[] getPackageFragmentsInRoots(IPackageFragmentRoot[] roots, IJavaProject project) { |
| |
| // The following code assumes that all the roots have the given project as their parent |
| ArrayList frags = new ArrayList(); |
| for (int i = 0; i < roots.length; i++) { |
| IPackageFragmentRoot root = roots[i]; |
| try { |
| IJavaElement[] pkgs = root.getChildren(); |
| |
| /* 2 jar package fragment roots can be equals but not belonging |
| to the same project. As a result, they share the same element info. |
| So this jar package fragment root could get the children of |
| another jar package fragment root. |
| The following code ensures that the children of this jar package |
| fragment root have the given project as a great parent. |
| */ |
| int length = pkgs.length; |
| if (length == 0) continue; |
| if (pkgs[0].getParent().getParent().equals(project)) { |
| // the children have the right parent, simply add them to the list |
| for (int j = 0; j < length; j++) { |
| frags.add(pkgs[j]); |
| } |
| } else { |
| // create a new handle with the root as the parent |
| for (int j = 0; j < length; j++) { |
| frags.add(root.getPackageFragment(pkgs[j].getElementName())); |
| } |
| } |
| } catch (JavaModelException e) { |
| // do nothing |
| } |
| } |
| IPackageFragment[] fragments = new IPackageFragment[frags.size()]; |
| frags.toArray(fragments); |
| return fragments; |
| } |
| |
| /* |
| * Returns whether the given path is a classpath entry or an output location. |
| */ |
| private boolean isClasspathEntryOrOutputLocation(IPath path, IClasspathEntry[] resolvedClasspath, IPath projectOutput) { |
| if (projectOutput.equals(path)) return true; |
| for (int i = 0, length = resolvedClasspath.length; i < length; i++) { |
| IClasspathEntry entry = resolvedClasspath[i]; |
| if (entry.getPath().equals(path)) { |
| return true; |
| } |
| IPath output; |
| if ((output = entry.getOutputLocation()) != null && output.equals(path)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /* |
| * Reset the package fragment roots and package fragment caches |
| */ |
| void resetCaches() { |
| this.allPkgFragmentRootsCache = null; |
| this.allPkgFragmentsCache = null; |
| } |
| |
| /** |
| * Set the fNonJavaResources to res value |
| */ |
| void setNonJavaResources(Object[] resources) { |
| |
| this.nonJavaResources = resources; |
| } |
| |
| } |