Copyright (c) 2000, 2016 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2016 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.jdt.internal.core; import java.util.HashMap; import java.util.Map; 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.IClasspathEntry; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.core.DeltaProcessor.RootInfo; import org.eclipse.jdt.internal.core.util.HashSetOfArray; import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject; import org.eclipse.jdt.internal.core.util.Util;
Info for IJavaProject.

Note: getChildren() returns all of the IPackageFragmentRoots specified on the classpath for the project. This can include roots external to the project. See JavaProject#getAllPackageFragmentRoots() and JavaProject#getPackageFragmentRoots(). To get only the IPackageFragmentRoots that are internal to the project, use JavaProject#getChildren().

/** * 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>. */
@SuppressWarnings({"rawtypes"}) /* package */ class JavaProjectElementInfo extends OpenableElementInfo { static final IPackageFragmentRoot[] NO_ROOTS = new IPackageFragmentRoot[0]; static class ProjectCache { ProjectCache(IPackageFragmentRoot[] allPkgFragmentRootsCache, Map rootToResolvedEntries, Map pkgFragmentsCaches) { this.allPkgFragmentRootsCache = allPkgFragmentRootsCache; this.rootToResolvedEntries = rootToResolvedEntries; this.pkgFragmentsCaches = pkgFragmentsCaches; } /* * 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 IPackageFragmentRoot[] (the package fragment roots that contain a package fragment with this name)) */ public HashtableOfArrayToObject allPkgFragmentsCache; /* * A cache of package fragments for each package fragment root of this project * (a map from IPackageFragmentRoot to a set of String[] (the package name)) */ public Map pkgFragmentsCaches; public Map rootToResolvedEntries; } ProjectCache projectCache; ProjectCache mainProjectCache; /* * Adds the given name and its super names to the given set * (e.g. for {"a", "b", "c"}, adds {"a", "b", "c"}, {"a", "b"}, and {"a"}) */ static void addSuperPackageNames(String[] pkgName, HashtableOfArrayToObject packageFragments) { for (int i = pkgName.length-1; i > 0; i--) { if (packageFragments.getKey(pkgName, i) == null) { System.arraycopy(pkgName, 0, pkgName = new String[i], 0, i); packageFragments.put(pkgName, NO_ROOTS); } } }
Create and initialize a new instance of the receiver
/** * Create and initialize a new instance of the receiver */
public JavaProjectElementInfo() { this.nonJavaResources = null; }
Compute the non-java resources contained in this java project.
/** * 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[][] inclusionPatterns = null; char[][] exclusionPatterns = null; IPath projectOutput = null; boolean isClasspathResolved = true; try { IClasspathEntry entry = project.getClasspathEntryFor(projectPath); if (entry != null) { srcIsProject = true; inclusionPatterns = ((ClasspathEntry)entry).fullInclusionPatternChars(); exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars(); } projectOutput = project.getOutputLocation(); binIsProject = projectPath.equals(projectOutput); } catch (JavaModelException e) { isClasspathResolved = false; } Object[] resources = new IResource[5]; int resourcesCounter = 0; try { IResource[] members = ((IContainer) project.getResource()).members(); int length = members.length; if (length > 0) { String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true); String complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true); IClasspathEntry[] classpath = project.getResolvedClasspath(); for (int i = 0; i < length; 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 (isClasspathResolved && isClasspathEntryOrOutputLocation(resFullPath, res.getLocation()/* see https://bugs.eclipse.org/bugs/show_bug.cgi?id=244406 */, classpath, projectOutput)) { break; } // ignore .java file if src == project if (srcIsProject && Util.isValidCompilationUnitName(resName, sourceLevel, complianceLevel) && !Util.isExcluded(res, inclusionPatterns, exclusionPatterns)) { break; } // ignore .class file if bin == project if (binIsProject && Util.isValidClassFileName(resName, sourceLevel, complianceLevel)) { 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, inclusionPatterns, exclusionPatterns) && Util.isValidFolderNameForPackage(res.getName(), sourceLevel, complianceLevel)) || (isClasspathResolved && isClasspathEntryOrOutputLocation(resFullPath, res.getLocation(), 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; } ProjectCache getProjectCache(JavaProject project, boolean excludeTestCode) { ProjectCache cache = excludeTestCode ? this.mainProjectCache : this.projectCache; if (cache != null) { for (IPackageFragmentRoot root : cache.allPkgFragmentRootsCache) { IJavaProject rootProject = root.getJavaProject(); if (rootProject != this && !rootProject.exists()) { cache = null; // force rebuilding break; } } } if (cache == null) { IPackageFragmentRoot[] roots; Map<?, ?> reverseMap = new HashMap<>(3); try { roots = project.getAllPackageFragmentRoots(reverseMap, excludeTestCode); } catch (JavaModelException e) { // project does not exist: cannot happen since this is the info of the project roots = new IPackageFragmentRoot[0]; reverseMap.clear(); } Map<IPath, RootInfo> rootInfos = JavaModelManager.getJavaModelManager().deltaState.roots; HashMap<IPackageFragmentRoot, HashSetOfArray> pkgFragmentsCaches = new HashMap<>(); int length = roots.length; JavaModelManager manager = JavaModelManager.getJavaModelManager(); for (int i = 0; i < length; i++) { IPackageFragmentRoot root = roots[i]; DeltaProcessor.RootInfo rootInfo = rootInfos.get(root.getPath()); if (rootInfo == null || rootInfo.project.equals(project)) { // ensure that an identical root is used (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=217059 ) roots[i] = root = (IPackageFragmentRoot) manager.getExistingElement(root); // compute fragment cache HashSetOfArray fragmentsCache = new HashSetOfArray(); initializePackageNames(root, fragmentsCache); pkgFragmentsCaches.put(root, fragmentsCache); } } cache = new ProjectCache(roots, reverseMap, pkgFragmentsCaches); if(excludeTestCode) { this.mainProjectCache = cache; } else { this.projectCache = cache; } } return cache; }
Returns an array of non-java resources contained in the receiver.
/** * Returns an array of non-java resources contained in the receiver. */
Object[] getNonJavaResources(JavaProject project) { Object[] resources = this.nonJavaResources; if (resources == null) { resources = computeNonJavaResources(project); this.nonJavaResources = resources; } return resources; } private void initializePackageNames(IPackageFragmentRoot root, HashSetOfArray fragmentsCache) { IJavaElement[] frags = null; try { if (!root.isOpen()) { PackageFragmentRootInfo info = root.isArchive() ? new JarPackageFragmentRootInfo() : new PackageFragmentRootInfo(); ((PackageFragmentRoot) root).computeChildren(info, ((JavaElement) root).resource()); frags = info.children; } else frags = root.getChildren(); } catch (JavaModelException e) { // root doesn't exist: ignore return; } for (int j = 0, length = frags.length; j < length; j++) { if (frags[j] instanceof PackageFragment) fragmentsCache.add(((PackageFragment) frags[j]).names); } } /* * Returns whether the given path is a classpath entry or an output location. */ private boolean isClasspathEntryOrOutputLocation(IPath path, IPath location, IClasspathEntry[] resolvedClasspath, IPath projectOutput) { if (projectOutput.equals(path)) return true; for (int i = 0, length = resolvedClasspath.length; i < length; i++) { IClasspathEntry entry = resolvedClasspath[i]; IPath entryPath; if ((entryPath = entry.getPath()).equals(path) || entryPath.equals(location)) { return true; } IPath output; if ((output = entry.getOutputLocation()) != null && output.equals(path)) { return true; } } return false; } /* * Creates a new name lookup for this project info. * The given project is assumed to be the handle of this info. * This name lookup first looks in the given working copies. */ NameLookup newNameLookup(JavaProject project, ICompilationUnit[] workingCopies, boolean excludeTestCode) { ProjectCache cache = getProjectCache(project, excludeTestCode); HashtableOfArrayToObject allPkgFragmentsCache = cache.allPkgFragmentsCache; if (allPkgFragmentsCache == null) { Map<IPath, RootInfo> rootInfos = JavaModelManager.getJavaModelManager().deltaState.roots; IPackageFragmentRoot[] allRoots = cache.allPkgFragmentRootsCache; int length = allRoots.length; allPkgFragmentsCache = new HashtableOfArrayToObject(); for (int i = 0; i < length; i++) { IPackageFragmentRoot root = allRoots[i]; DeltaProcessor.RootInfo rootInfo = rootInfos.get(root.getPath()); JavaProject rootProject = rootInfo == null ? project : rootInfo.project; HashSetOfArray fragmentsCache; if (rootProject.equals(project)) { // retrieve package fragments cache from this project fragmentsCache = (HashSetOfArray) cache.pkgFragmentsCaches.get(root); } else { // retrieve package fragments cache from the root's project ProjectCache rootProjectCache; try { rootProjectCache = rootProject.getProjectCache(excludeTestCode); } catch (JavaModelException e) { // project doesn't exit continue; } fragmentsCache = (HashSetOfArray) rootProjectCache.pkgFragmentsCaches.get(root); } if (fragmentsCache == null) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=183833 fragmentsCache = new HashSetOfArray(); initializePackageNames(root, fragmentsCache); } Object[][] set = fragmentsCache.set; for (int j = 0, length2 = set.length; j < length2; j++) { String[] pkgName = (String[]) set[j]; if (pkgName == null) continue; Object existing = allPkgFragmentsCache.get(pkgName); if (existing == null || existing == NO_ROOTS) { allPkgFragmentsCache.put(pkgName, root); // ensure super packages (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=119161) // are also in the map addSuperPackageNames(pkgName, allPkgFragmentsCache); } else { if (existing instanceof PackageFragmentRoot) { allPkgFragmentsCache.put(pkgName, new IPackageFragmentRoot[] {(PackageFragmentRoot) existing, root}); } else { IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) existing; int rootLength = roots.length; System.arraycopy(roots, 0, roots = new IPackageFragmentRoot[rootLength+1], 0, rootLength); roots[rootLength] = root; allPkgFragmentsCache.put(pkgName, roots); } } } } cache.allPkgFragmentsCache = allPkgFragmentsCache; } return new NameLookup(project, cache.allPkgFragmentRootsCache, cache.allPkgFragmentsCache, workingCopies, cache.rootToResolvedEntries); } /* * Reset the package fragment roots and package fragment caches */ void resetCaches() { this.projectCache = null; this.mainProjectCache = null; } }