Copyright (c) 2000, 2019 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 Stephan Herrmann - Contributions for Bug 320618 - inconsistent initialization of classpath container backed by external class folder Bug 346010 - [model] strange initialization dependency in OptionTests
/******************************************************************************* * Copyright (c) 2000, 2019 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 * Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for * Bug 320618 - inconsistent initialization of classpath container backed by external class folder * Bug 346010 - [model] strange initialization dependency in OptionTests *******************************************************************************/
package org.eclipse.jdt.internal.core; import java.io.*; import java.net.URI; import java.nio.file.FileVisitResult; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.jar.Manifest; import java.util.stream.Collectors; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.eclipse.core.resources.ICommand; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IProjectNature; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.content.IContentDescription; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaModelMarker; import org.eclipse.jdt.core.IJavaModelStatus; import org.eclipse.jdt.core.IJavaModelStatusConstants; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IRegion; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeHierarchy; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.eval.IEvaluationContext; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; import org.eclipse.jdt.internal.compiler.env.AutomaticModuleNaming; import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference; import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.util.JRTUtil; import org.eclipse.jdt.internal.compiler.util.ObjectVector; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo; import org.eclipse.jdt.internal.core.JavaProjectElementInfo.ProjectCache; import org.eclipse.jdt.internal.core.builder.JavaBuilder; import org.eclipse.jdt.internal.core.eval.EvaluationContextWrapper; import org.eclipse.jdt.internal.core.util.JavaElementFinder; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.eclipse.jdt.internal.core.util.Messages; import org.eclipse.jdt.internal.core.util.Util; import org.eclipse.jdt.internal.eval.EvaluationContext; import org.osgi.service.prefs.BackingStoreException; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException;
Handle for a Java Project.

A Java Project internally maintains a devpath that corresponds to the project's classpath. The classpath may include source folders from the current project; jars in the current project, other projects, and the local file system; and binary folders (output location) of other projects. The Java Model presents source elements corresponding to output .class files in other projects, and thus uses the devpath rather than the classpath (which is really a compilation path). The devpath mimics the classpath, except has source folder entries in place of output locations in external projects.

Each JavaProject has a NameLookup facility that locates elements on by name, based on the devpath.

See Also:
  • IJavaProject
/** * Handle for a Java Project. * * <p>A Java Project internally maintains a devpath that corresponds * to the project's classpath. The classpath may include source folders * from the current project; jars in the current project, other projects, * and the local file system; and binary folders (output location) of other * projects. The Java Model presents source elements corresponding to output * .class files in other projects, and thus uses the devpath rather than * the classpath (which is really a compilation path). The devpath mimics * the classpath, except has source folder entries in place of output * locations in external projects. * * <p>Each JavaProject has a NameLookup facility that locates elements * on by name, based on the devpath. * * @see IJavaProject */
@SuppressWarnings({ "rawtypes", "unchecked" }) public class JavaProject extends Openable implements IJavaProject, IProjectNature, SuffixConstants {
Name of file containing project classpath
/** * Name of file containing project classpath */
public static final String CLASSPATH_FILENAME = IJavaProject.CLASSPATH_FILE_NAME;
Value of the project's raw classpath if the .classpath file contains invalid entries.
/** * Value of the project's raw classpath if the .classpath file contains invalid entries. */
public static final IClasspathEntry[] INVALID_CLASSPATH = new IClasspathEntry[0];
Whether the underlying file system is case sensitive.
/** * Whether the underlying file system is case sensitive. */
protected static final boolean IS_CASE_SENSITIVE = !new File("Temp").equals(new File("temp")); //$NON-NLS-1$ //$NON-NLS-2$
An empty array of strings indicating that a project doesn't have any prerequesite projects.
/** * An empty array of strings indicating that a project doesn't have any prerequesite projects. */
protected static final String[] NO_PREREQUISITES = CharOperation.NO_STRINGS;
Name of file containing custom project preferences
See Also:
/** * Name of file containing custom project preferences * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=59258">bug 59258</a> */
private static final String PREF_FILENAME = ".jprefs"; //$NON-NLS-1$
Name of directory containing preferences file
/** * Name of directory containing preferences file */
public static final String DEFAULT_PREFERENCES_DIRNAME = ".settings"; //$NON-NLS-1$
Extension for file containing custom project preferences
/** * Extension for file containing custom project preferences */
public static final String JAVA_CORE_PREFS_FILE = JavaCore.PLUGIN_ID+".prefs"; //$NON-NLS-1$ /* * Value of project's resolved classpath while it is being resolved */ private static final IClasspathEntry[] RESOLUTION_IN_PROGRESS = new IClasspathEntry[0]; /* * For testing purpose only */ private static ArrayList CP_RESOLUTION_BP_LISTENERS; public static class ClasspathResolutionBreakpointListener { public void breakpoint(int bp) { // override in listener implementation } }
The platform project this IJavaProject is based on
/** * The platform project this <code>IJavaProject</code> is based on */
protected IProject project;
Preferences listeners
/** * Preferences listeners */
private IEclipsePreferences.INodeChangeListener preferencesNodeListener; private IEclipsePreferences.IPreferenceChangeListener preferencesChangeListener;
Constructor needed for IProject.getNature() and IProject.addNature().
See Also:
  • setProject(IProject)
/** * Constructor needed for <code>IProject.getNature()</code> and <code>IProject.addNature()</code>. * * @see #setProject(IProject) */
public JavaProject() { super(null); } public JavaProject(IProject project, JavaElement parent) { super(parent); this.project = project; } /* * For testing purpose only */ public static synchronized void addCPResolutionBPListener(ClasspathResolutionBreakpointListener listener) { if (CP_RESOLUTION_BP_LISTENERS == null) CP_RESOLUTION_BP_LISTENERS = new ArrayList(); CP_RESOLUTION_BP_LISTENERS.add(listener); } /* * For testing purpose only */ public static synchronized void removeCPResolutionBPListener(ClasspathResolutionBreakpointListener listener) { if (CP_RESOLUTION_BP_LISTENERS == null) return; CP_RESOLUTION_BP_LISTENERS.remove(listener); if (CP_RESOLUTION_BP_LISTENERS.size() == 0) CP_RESOLUTION_BP_LISTENERS = null; } private static synchronized ClasspathResolutionBreakpointListener[] getBPListeners() { if (CP_RESOLUTION_BP_LISTENERS == null) return null; return (ClasspathResolutionBreakpointListener[]) CP_RESOLUTION_BP_LISTENERS.toArray(new ClasspathResolutionBreakpointListener[CP_RESOLUTION_BP_LISTENERS.size()]); } private static void breakpoint(int bp, JavaProject project) { ClasspathResolutionBreakpointListener[] listeners = getBPListeners(); if (listeners == null) return; for (int j = 0, length = listeners.length; j < length; j++) { listeners[j].breakpoint(bp); } } public static boolean areClasspathsEqual( IClasspathEntry[] firstClasspath, IClasspathEntry[] secondClasspath, IPath firstOutputLocation, IPath secondOutputLocation) { int length = firstClasspath.length; if (length != secondClasspath.length) return false; for (int i = 0; i < length; i++) { if (!firstClasspath[i].equals(secondClasspath[i])) return false; } if (firstOutputLocation == null) return secondOutputLocation == null; return firstOutputLocation.equals(secondOutputLocation); }
Compare current classpath with given one to see if any different. Note that the argument classpath contains its binary output.
Params:
  • newClasspath – IClasspathEntry[]
  • newOutputLocation – IPath
  • otherClasspathWithOutput – IClasspathEntry[]
Returns:boolean
/** * Compare current classpath with given one to see if any different. * Note that the argument classpath contains its binary output. * @param newClasspath IClasspathEntry[] * @param newOutputLocation IPath * @param otherClasspathWithOutput IClasspathEntry[] * @return boolean */
private static boolean areClasspathsEqual(IClasspathEntry[] newClasspath, IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput) { if (otherClasspathWithOutput == null || otherClasspathWithOutput.length == 0) return false; int length = otherClasspathWithOutput.length; if (length != newClasspath.length + 1) // output is amongst file entries (last one) return false; // compare classpath entries for (int i = 0; i < length - 1; i++) { if (!otherClasspathWithOutput[i].equals(newClasspath[i])) return false; } // compare binary outputs IClasspathEntry output = otherClasspathWithOutput[length - 1]; if (output.getContentKind() != ClasspathEntry.K_OUTPUT || !output.getPath().equals(newOutputLocation)) return false; return true; } private static boolean areClasspathsEqual(IClasspathEntry[] first, IClasspathEntry[] second) { if (first != second){ if (first == null) return false; int length = first.length; if (second == null || second.length != length) return false; for (int i = 0; i < length; i++) { if (!first[i].equals(second[i])) return false; } } return true; }
Returns a canonicalized path from the given external path. Note that the return path contains the same number of segments and it contains a device only if the given path contained one.
Params:
  • externalPath – IPath
See Also:
Returns:IPath
/** * Returns a canonicalized path from the given external path. * Note that the return path contains the same number of segments * and it contains a device only if the given path contained one. * @param externalPath IPath * @see java.io.File for the definition of a canonicalized path * @return IPath */
public static IPath canonicalizedPath(IPath externalPath) { if (externalPath == null) return null; if (IS_CASE_SENSITIVE) { return externalPath; } // if not external path, return original path IWorkspace workspace = ResourcesPlugin.getWorkspace(); if (workspace == null) return externalPath; // protection during shutdown (30487) if (workspace.getRoot().findMember(externalPath) != null) { return externalPath; } IPath canonicalPath = null; try { canonicalPath = new Path(new File(externalPath.toOSString()).getCanonicalPath()); } catch (IOException e) { // default to original path return externalPath; } IPath result; int canonicalLength = canonicalPath.segmentCount(); if (canonicalLength == 0) { // the java.io.File canonicalization failed return externalPath; } else if (externalPath.isAbsolute()) { result = canonicalPath; } else { // if path is relative, remove the first segments that were added by the java.io.File canonicalization // e.g. 'lib/classes.zip' was converted to 'd:/myfolder/lib/classes.zip' int externalLength = externalPath.segmentCount(); if (canonicalLength >= externalLength) { result = canonicalPath.removeFirstSegments(canonicalLength - externalLength); } else { return externalPath; } } // keep device only if it was specified (this is because File.getCanonicalPath() converts '/lib/classes.zip' to 'd:/lib/classes/zip') if (externalPath.getDevice() == null) { result = result.setDevice(null); } // keep trailing separator only if it was specified (this is because File.getCanonicalPath() converts 'd:/lib/classes/' to 'd:/lib/classes') if (externalPath.hasTrailingSeparator()) { result = result.addTrailingSeparator(); } return result; }
Returns true if the given project is accessible and it has a java nature, otherwise false.
Params:
  • project – IProject
Returns:boolean
/** * Returns true if the given project is accessible and it has * a java nature, otherwise false. * @param project IProject * @return boolean */
public static boolean hasJavaNature(IProject project) { try { return project.hasNature(JavaCore.NATURE_ID); } catch (CoreException e) { if (ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(project.getName())) return true; // project does not exist or is not open } return false; } /* * Detect cycles in the classpath of the workspace's projects * and create markers if necessary. * @param preferredClasspaths Map * @throws JavaModelException */ public static void validateCycles(Map preferredClasspaths) throws JavaModelException { //long start = System.currentTimeMillis(); IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); IProject[] rscProjects = workspaceRoot.getProjects(); int length = rscProjects.length; JavaProject[] projects = new JavaProject[length]; LinkedHashSet<IPath> cycleParticipants = new LinkedHashSet<>(); HashSet traversed = new HashSet(); // compute cycle participants List<IPath> prereqChain = new ArrayList<>(); Map<IPath,List<CycleInfo>> cyclesPerProject = new HashMap<>(); for (int i = 0; i < length; i++){ if (hasJavaNature(rscProjects[i])) { JavaProject project = (projects[i] = (JavaProject)JavaCore.create(rscProjects[i])); if (!traversed.contains(project.getPath())){ prereqChain.clear(); project.updateCycleParticipants(prereqChain, cycleParticipants, cyclesPerProject, workspaceRoot, traversed, preferredClasspaths); } } } //System.out.println("updateAllCycleMarkers: " + (System.currentTimeMillis() - start) + " ms"); for (int i = 0; i < length; i++){ JavaProject project = projects[i]; if (project != null) { List<CycleInfo> cycles = cyclesPerProject.get(project.getPath()); if (cycles != null) { StringBuilder cycleString = new StringBuilder(); boolean first = true; for (CycleInfo cycleInfo : cycles) { if (!first) cycleString.append('\n'); cycleString.append(cycleInfo.pathToCycleAsString()); cycleString.append("->{"); //$NON-NLS-1$ cycleString.append(cycleInfo.cycleAsString()); cycleString.append('}'); first = false; } IMarker cycleMarker = project.getCycleMarker(); String circularCPOption = project.getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true); int circularCPSeverity = JavaCore.ERROR.equals(circularCPOption) ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING; if (cycleMarker != null) { // update existing cycle marker if needed try { int existingSeverity = ((Integer)cycleMarker.getAttribute(IMarker.SEVERITY)).intValue(); if (existingSeverity != circularCPSeverity) { cycleMarker.setAttribute(IMarker.SEVERITY, circularCPSeverity); } String existingMessage = cycleMarker.getAttribute(IMarker.MESSAGE, ""); //$NON-NLS-1$ String newMessage = new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE, project, cycleString.toString()).getMessage(); if (!newMessage.equals(existingMessage)) { cycleMarker.setAttribute(IMarker.MESSAGE, newMessage); } } catch (CoreException e) { throw new JavaModelException(e); } } else { // create new marker project.createClasspathProblemMarker( new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE, project, cycleString.toString())); } } else { project.flushClasspathProblemMarkers(true, false, false); } } } }
Adds a builder to the build spec for the given project.
/** * Adds a builder to the build spec for the given project. */
protected void addToBuildSpec(String builderID) throws CoreException { IProjectDescription description = this.project.getDescription(); int javaCommandIndex = getJavaCommandIndex(description.getBuildSpec()); if (javaCommandIndex == -1) { // Add a Java command to the build spec ICommand command = description.newCommand(); command.setBuilderName(builderID); setJavaCommand(description, command); } }
See Also:
  • Openable
/** * @see Openable */
@Override protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException { // cannot refresh cp markers on opening (emulate cp check on startup) since can create deadlocks (see bug 37274) IClasspathEntry[] resolvedClasspath = getResolvedClasspath(); // compute the pkg fragment roots IPackageFragmentRoot[] roots = computePackageFragmentRoots(resolvedClasspath, false, true, null /*no reverse map*/); info.setChildren(roots); IModuleDescription module = null; IModuleDescription current = null; for (IPackageFragmentRoot root : roots) { if (root.getKind() != IPackageFragmentRoot.K_SOURCE) continue; module = root.getModuleDescription(); if (module != null) { if (current != null) { throw new JavaModelException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Messages.bind(Messages.classpath_duplicateEntryPath, TypeConstants.MODULE_INFO_FILE_NAME_STRING, getElementName()))); } current = module; JavaModelManager.getModulePathManager().addEntry(module, this); //break; continue looking, there may be other roots containing module-info info.setModule(module); } } return true; } @Override public void close() throws JavaModelException { if (JavaProject.hasJavaNature(this.project)) { // Get cached preferences if exist JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, false); if (perProjectInfo != null && perProjectInfo.preferences != null) { IEclipsePreferences eclipseParentPreferences = (IEclipsePreferences) perProjectInfo.preferences.parent(); if (this.preferencesNodeListener != null) { eclipseParentPreferences.removeNodeChangeListener(this.preferencesNodeListener); this.preferencesNodeListener = null; } if (this.preferencesChangeListener != null) { perProjectInfo.preferences.removePreferenceChangeListener(this.preferencesChangeListener); this.preferencesChangeListener = null; } } } super.close(); }
Internal computation of an expanded classpath. It will eliminate duplicates, and produce copies of exported or restricted classpath entries to avoid possible side-effects ever after.
Params:
  • excludeTestCode –
/** * Internal computation of an expanded classpath. It will eliminate duplicates, and produce copies * of exported or restricted classpath entries to avoid possible side-effects ever after. * @param excludeTestCode */
private void computeExpandedClasspath( ClasspathEntry referringEntry, HashMap<String, Boolean> rootIDs, ArrayList<ClasspathEntry> accumulatedEntries, boolean excludeTestCode) throws JavaModelException { IClasspathEntry[] resolvedClasspath = getResolvedClasspath(); IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); boolean isInitialProject = referringEntry == null; for (int i = 0, length = resolvedClasspath.length; i < length; i++){ ClasspathEntry entry = (ClasspathEntry) resolvedClasspath[i]; if (excludeTestCode && entry.isTest()) { continue; } if (isInitialProject || entry.isExported()){ String rootID = entry.rootID(); // recurse in project to get all its indirect exports (only consider exported entries from there on) if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { boolean nestedWithoutTestCode = excludeTestCode || entry.isWithoutTestCode(); Boolean previousValue = rootIDs.get(rootID); ClasspathEntry combinedEntry; if (previousValue == Boolean.FALSE) { continue; // already handled including test code } else if (previousValue == Boolean.TRUE) { // project was already handled, but without test code. if (nestedWithoutTestCode) { continue; } else { // find the existing entry and update it. rootIDs.put(rootID, Boolean.FALSE); for (int j = 0; j < accumulatedEntries.size(); j++) { // it is unclear how oldEntry and combinedEntry could be merged. // main code compilation should remain untouched as far as possible, // so take all settings from oldEntry and just remove WITHOUT_TEST_CODE ClasspathEntry oldEntry = accumulatedEntries.get(j); if (oldEntry.rootID().equals(rootID)) { accumulatedEntries.set(j, oldEntry.withExtraAttributeRemoved(IClasspathAttribute.WITHOUT_TEST_CODE)); break; } } // combine restrictions along the project chain combinedEntry = entry.combineWith(referringEntry); } } else { rootIDs.put(rootID, nestedWithoutTestCode); // combine restrictions along the project chain combinedEntry = entry.combineWith(referringEntry); accumulatedEntries.add(combinedEntry); } IResource member = workspaceRoot.findMember(entry.getPath()); if (member != null && member.getType() == IResource.PROJECT){ // double check if bound to project (23977) IProject projRsc = (IProject) member; if (JavaProject.hasJavaNature(projRsc)) { JavaProject javaProject = (JavaProject) JavaCore.create(projRsc); javaProject.computeExpandedClasspath( combinedEntry, rootIDs, accumulatedEntries, nestedWithoutTestCode); } } } else { if (!rootIDs.containsKey(rootID)) { // combine restrictions along the project chain ClasspathEntry combinedEntry = entry.combineWith(referringEntry); accumulatedEntries.add(combinedEntry); rootIDs.put(rootID, excludeTestCode); // value actually doesn't matter for non-projects } } } } }
Computes the package fragment roots identified by the given entry. Only works with resolved entry
Params:
  • resolvedEntry – IClasspathEntry
Returns:IPackageFragmentRoot[]
/** * Computes the package fragment roots identified by the given entry. * Only works with resolved entry * @param resolvedEntry IClasspathEntry * @return IPackageFragmentRoot[] */
public IPackageFragmentRoot[] computePackageFragmentRoots(IClasspathEntry resolvedEntry) { try { return computePackageFragmentRoots( new IClasspathEntry[]{ resolvedEntry }, false, // don't retrieve exported roots true, // respect limit-modules null /* no reverse map */ ); } catch (JavaModelException e) { return new IPackageFragmentRoot[] {}; } } public void computePackageFragmentRoots( IClasspathEntry resolvedEntry, ObjectVector accumulatedRoots, HashSet rootIDs, IClasspathEntry referringEntry, boolean retrieveExportedRoots, boolean filterModuleRoots, Map rootToResolvedEntries) throws JavaModelException { computePackageFragmentRoots(resolvedEntry, accumulatedRoots, rootIDs, referringEntry, retrieveExportedRoots, filterModuleRoots, rootToResolvedEntries, false); }
Returns the package fragment roots identified by the given entry. In case it refers to a project, it will follow its classpath so as to find exported roots as well. Only works with resolved entry

Note: this method is retained for the sole purpose of supporting old versions of Xtext [2.8.x,2.12], which illegally call this internal method.

Params:
  • resolvedEntry – IClasspathEntry
  • accumulatedRoots – ObjectVector
  • rootIDs – HashSet
  • referringEntry – the CP entry (project) referring to this entry, or null if initial project
  • retrieveExportedRoots – boolean
Throws:
/** * Returns the package fragment roots identified by the given entry. In case it refers to * a project, it will follow its classpath so as to find exported roots as well. * Only works with resolved entry * <p><strong>Note:</strong> this method is retained for the sole purpose of supporting * old versions of Xtext [2.8.x,2.12], which illegally call this internal method. * </p> * @param resolvedEntry IClasspathEntry * @param accumulatedRoots ObjectVector * @param rootIDs HashSet * @param referringEntry the CP entry (project) referring to this entry, or null if initial project * @param retrieveExportedRoots boolean * @throws JavaModelException */
public void computePackageFragmentRoots( IClasspathEntry resolvedEntry, ObjectVector accumulatedRoots, HashSet rootIDs, IClasspathEntry referringEntry, boolean retrieveExportedRoots, Map rootToResolvedEntries) throws JavaModelException { computePackageFragmentRoots(resolvedEntry, accumulatedRoots, rootIDs, referringEntry, retrieveExportedRoots, true, rootToResolvedEntries); }
Returns the package fragment roots identified by the given entry. In case it refers to a project, it will follow its classpath so as to find exported roots as well. Only works with resolved entry
Params:
  • resolvedEntry – IClasspathEntry
  • accumulatedRoots – ObjectVector
  • rootIDs – HashSet
  • referringEntry – the CP entry (project) referring to this entry, or null if initial project
  • retrieveExportedRoots – boolean
  • filterModuleRoots – if true, roots corresponding to modules will be filtered if applicable: if a limit-modules attribute exists, this is used, otherwise system modules will be filtered according to the rules of root modules per JEP 261.
Throws:
/** * Returns the package fragment roots identified by the given entry. In case it refers to * a project, it will follow its classpath so as to find exported roots as well. * Only works with resolved entry * @param resolvedEntry IClasspathEntry * @param accumulatedRoots ObjectVector * @param rootIDs HashSet * @param referringEntry the CP entry (project) referring to this entry, or null if initial project * @param retrieveExportedRoots boolean * @param filterModuleRoots if true, roots corresponding to modules will be filtered if applicable: * if a limit-modules attribute exists, this is used, otherwise system modules will be filtered * according to the rules of root modules per JEP 261. * @throws JavaModelException */
public void computePackageFragmentRoots( IClasspathEntry resolvedEntry, ObjectVector accumulatedRoots, HashSet rootIDs, IClasspathEntry referringEntry, boolean retrieveExportedRoots, boolean filterModuleRoots, Map rootToResolvedEntries, boolean excludeTestCode) throws JavaModelException { String rootID = ((ClasspathEntry)resolvedEntry).rootID(); if (rootIDs.contains(rootID)) return; if(excludeTestCode && ((ClasspathEntry)resolvedEntry).isTest()) { return; } IPath projectPath = this.project.getFullPath(); IPath entryPath = resolvedEntry.getPath(); IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); IPackageFragmentRoot root = null; switch(resolvedEntry.getEntryKind()){ // source folder case IClasspathEntry.CPE_SOURCE : if (projectPath.isPrefixOf(entryPath)){ Object target = JavaModel.getTarget(entryPath, true/*check existency*/); if (target == null) return; if (target instanceof IFolder || target instanceof IProject){ root = getPackageFragmentRoot((IResource)target); } } break; // internal/external JAR or folder case IClasspathEntry.CPE_LIBRARY : if (referringEntry != null && !resolvedEntry.isExported()) return; Object target = JavaModel.getTarget(entryPath, true/*check existency*/); if (target == null) return; if (target instanceof IResource){ // internal target root = getPackageFragmentRoot((IResource) target, entryPath, resolvedEntry.getExtraAttributes()); } else if (target instanceof File) { // external target if (JavaModel.isFile(target)) { if (JavaModel.isJimage((File) target)) { PerProjectInfo info = getPerProjectInfo(); ObjectVector imageRoots; if (info.jrtRoots == null || !info.jrtRoots.containsKey(entryPath)) { imageRoots = new ObjectVector(); loadModulesInJimage(entryPath, imageRoots, rootToResolvedEntries, resolvedEntry, referringEntry); info.setJrtPackageRoots(entryPath, imageRoots); // unfiltered rootIDs.add(rootID); } else { imageRoots = info.jrtRoots.get(entryPath); } if (filterModuleRoots) { List<String> rootModules = null; String limitModules = ClasspathEntry.getExtraAttribute(resolvedEntry, IClasspathAttribute.LIMIT_MODULES); if (limitModules != null) { rootModules = Arrays.asList(limitModules.split(",")); //$NON-NLS-1$ } else if (isUnNamedModule()) { rootModules = defaultRootModules((Iterable) imageRoots); } if (rootModules != null) { imageRoots = filterLimitedModules(entryPath, imageRoots, rootModules); } } accumulatedRoots.addAll(imageRoots); } else if (JavaModel.isJmod((File) target)) { root = new JModPackageFragmentRoot(entryPath, this, resolvedEntry.getExtraAttributes()); } else { root = new JarPackageFragmentRoot(null, entryPath, this, resolvedEntry.getExtraAttributes()); } } else if (((File) target).isDirectory()) { root = new ExternalPackageFragmentRoot(entryPath, this); } } break; // recurse into required project case IClasspathEntry.CPE_PROJECT : if (!retrieveExportedRoots) return; if (referringEntry != null && !resolvedEntry.isExported()) return; IResource member = workspaceRoot.findMember(entryPath); if (member != null && member.getType() == IResource.PROJECT){// double check if bound to project (23977) IProject requiredProjectRsc = (IProject) member; if (JavaProject.hasJavaNature(requiredProjectRsc)){ // special builder binary output rootIDs.add(rootID); JavaProject requiredProject = (JavaProject)JavaCore.create(requiredProjectRsc); requiredProject.computePackageFragmentRoots( requiredProject.getResolvedClasspath(), accumulatedRoots, rootIDs, rootToResolvedEntries == null ? resolvedEntry : ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry), // only combine if need to build the reverse map retrieveExportedRoots, filterModuleRoots, rootToResolvedEntries, excludeTestCode); } break; } } if (root != null) { accumulatedRoots.add(root); rootIDs.add(rootID); if (rootToResolvedEntries != null) rootToResolvedEntries.put(root, ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry)); } }
Implements selection of root modules per JEP 261.
/** Implements selection of root modules per JEP 261. */
public static List<String> defaultRootModules(Iterable<IPackageFragmentRoot> allSystemRoots) { return internalDefaultRootModules(allSystemRoots, IPackageFragmentRoot::getElementName, r -> (r instanceof JrtPackageFragmentRoot) ? ((JrtPackageFragmentRoot) r).getModule() : null); } public static <T> List<String> internalDefaultRootModules(Iterable<T> allSystemModules, Function<T,String> getModuleName, Function<T,IModule> getModule) { List<String> result = new ArrayList<>(); boolean hasJavaDotSE = false; for (T mod : allSystemModules) { String moduleName = getModuleName.apply(mod); if ("java.se".equals(moduleName)) { //$NON-NLS-1$ result.add(moduleName); hasJavaDotSE = true; break; } } for (T mod : allSystemModules) { String moduleName = getModuleName.apply(mod); boolean isJavaDotStart = moduleName.startsWith("java."); //$NON-NLS-1$ boolean isPotentialRoot = !isJavaDotStart; // always include non-java.* if (!hasJavaDotSE) isPotentialRoot |= isJavaDotStart; // no java.se => add all java.* if (isPotentialRoot) { IModule module = getModule.apply(mod); if (module != null) { for (IPackageExport packageExport : module.exports()) { if (!packageExport.isQualified()) { result.add(moduleName); break; } } } } } return result; } private ObjectVector filterLimitedModules(IPath jrtPath, ObjectVector imageRoots, List<String> rootModuleNames) { Set<String> limitModulesSet = new HashSet<>(rootModuleNames); ModuleLookup lookup = new ModuleLookup(jrtPath.toFile()); // collect all module roots: for (int i = 0; i < imageRoots.size(); i++) { lookup.recordRoot((JrtPackageFragmentRoot) imageRoots.elementAt(i)); } // for those contained in limitModules, add the transitive closure: for (int i = 0; i < imageRoots.size(); i++) { String moduleName = ((JrtPackageFragmentRoot) imageRoots.elementAt(i)).moduleName; if (limitModulesSet.contains(moduleName)) lookup.addTransitive(moduleName); } // map the result back to package fragment roots: ObjectVector result = new ObjectVector(lookup.resultModuleSet.size()); for (IModule mod : lookup.resultModuleSet) { result.add(lookup.getRoot(mod)); } return result; }
Helper for computing the transitive closure of a set of modules.
/** Helper for computing the transitive closure of a set of modules. */
private static class ModuleLookup { File jrtFile; Map<String, JrtPackageFragmentRoot> modNames2Roots = new HashMap<>(); Map<String, IModule> modules = new HashMap<>(); Set<IModule> resultModuleSet = new HashSet<>(); public ModuleLookup(File jrtFile) { this.jrtFile = jrtFile; } void recordRoot(JrtPackageFragmentRoot root) { this.modNames2Roots.put(root.moduleName, root); } void addTransitive(String moduleName) { IModule module = getModule(moduleName); if (module != null && this.resultModuleSet.add(module)) { for (IModuleReference reqRef : module.requires()) addTransitive(String.valueOf(reqRef.name())); } } private IModule getModule(String moduleName) { IModule result = this.modules.get(moduleName); if (result == null) { JrtPackageFragmentRoot root = this.modNames2Roots.get(moduleName); if (root != null) { try { ClassFileReader classFile = JRTUtil.getClassfile(this.jrtFile, TypeConstants.MODULE_INFO_CLASS_NAME_STRING, root.moduleName, null); result = classFile.getModuleDeclaration(); this.modules.put(moduleName, result); } catch (IOException | ClassFormatException e) { JavaCore.getJavaCore().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Failed to read module-info.class", e)); //$NON-NLS-1$ } } } return result; } JrtPackageFragmentRoot getRoot(IModule module) { return this.modNames2Roots.get(String.valueOf(module.name())); } }
This bogus package fragment root acts as placeholder plus bridge for the real one until the module name becomes available. It is useful in certain scenarios like creating package roots from delta processors, search etc.
/** * This bogus package fragment root acts as placeholder plus bridge for the * real one until the module name becomes available. It is useful in certain * scenarios like creating package roots from delta processors, search etc. */
class JImageModuleFragmentBridge extends JarPackageFragmentRoot { protected JImageModuleFragmentBridge(IPath externalJarPath, IClasspathAttribute[] extraAttributes) { super(null, externalJarPath, JavaProject.this, extraAttributes); } @Override public PackageFragment getPackageFragment(String[] pkgName) { return getPackageFragment(pkgName, null); } @Override public PackageFragment getPackageFragment(String[] pkgName, String mod) { PackageFragmentRoot realRoot = new JrtPackageFragmentRoot(this.jarPath, mod == null ? JRTUtil.JAVA_BASE : mod, JavaProject.this, this.extraAttributes); return new JarPackageFragment(realRoot, pkgName); } @Override protected boolean computeChildren(OpenableElementInfo info, IResource underlyingResource) throws JavaModelException { // Do nothing, idea is to avoid this being read in JarPackageFragmentRoot as a Jar. return true; } public boolean isModule() { return true; } } private void loadModulesInJimage(final IPath imagePath, final ObjectVector roots, final Map rootToResolvedEntries, final IClasspathEntry resolvedEntry, final IClasspathEntry referringEntry) { try { org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imagePath.toFile(), new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<java.nio.file.Path>() { @Override public FileVisitResult visitPackage(java.nio.file.Path dir, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException { return FileVisitResult.SKIP_SIBLINGS; } @Override public FileVisitResult visitFile(java.nio.file.Path path, java.nio.file.Path mod, BasicFileAttributes attrs) throws IOException { return FileVisitResult.SKIP_SIBLINGS; } @Override public FileVisitResult visitModule(java.nio.file.Path path, String name) throws IOException { JrtPackageFragmentRoot root = new JrtPackageFragmentRoot(imagePath, name, JavaProject.this, resolvedEntry.getExtraAttributes()); roots.add(root); if (rootToResolvedEntries != null) rootToResolvedEntries.put(root, ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry)); return FileVisitResult.SKIP_SUBTREE; } }, JRTUtil.NOTIFY_MODULES); } catch (IOException e) { Util.log(IStatus.ERROR, "Error reading modules from " + imagePath.toOSString()); //$NON-NLS-1$ } } @Override public IPackageFragmentRoot[] findUnfilteredPackageFragmentRoots(IClasspathEntry entry) { try { IClasspathEntry[] resolvedEntries = resolveClasspath(new IClasspathEntry[]{ entry }); return computePackageFragmentRoots(resolvedEntries, false /* not exported roots */, false /* don't filter! */, null /* no reverse map */); } catch (JavaModelException e) { // according to comment in findPackageFragmentRoots() we assume that this is caused by the project no longer existing return new IPackageFragmentRoot[] {}; } } public IPackageFragmentRoot[] computePackageFragmentRoots( IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots, boolean filterModuleRoots, Map rootToResolvedEntries) throws JavaModelException { return computePackageFragmentRoots(resolvedClasspath, retrieveExportedRoots, filterModuleRoots, rootToResolvedEntries, false); }
Returns (local/all) the package fragment roots identified by the given project's classpath. Note: this follows project classpath references to find required project contributions, eliminating duplicates silently. Only works with resolved entries
Params:
  • resolvedClasspath – IClasspathEntry[]
  • retrieveExportedRoots – boolean
  • filterModuleRoots – if true, roots corresponding to modules will be filtered if applicable: if a limit-modules attribute exists, this is used, otherwise system modules will be filtered according to the rules of root modules per JEP 261.
Throws:
Returns:IPackageFragmentRoot[]
/** * Returns (local/all) the package fragment roots identified by the given project's classpath. * Note: this follows project classpath references to find required project contributions, * eliminating duplicates silently. * Only works with resolved entries * @param resolvedClasspath IClasspathEntry[] * @param retrieveExportedRoots boolean * @param filterModuleRoots if true, roots corresponding to modules will be filtered if applicable: * if a limit-modules attribute exists, this is used, otherwise system modules will be filtered * according to the rules of root modules per JEP 261. * @return IPackageFragmentRoot[] * @throws JavaModelException */
public IPackageFragmentRoot[] computePackageFragmentRoots( IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots, boolean filterModuleRoots, Map rootToResolvedEntries, boolean excludeTestCode) throws JavaModelException { ObjectVector accumulatedRoots = new ObjectVector(); computePackageFragmentRoots( resolvedClasspath, accumulatedRoots, new HashSet(5), // rootIDs null, // inside original project retrieveExportedRoots, filterModuleRoots, rootToResolvedEntries, excludeTestCode); IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots.size()]; accumulatedRoots.copyInto(rootArray); return rootArray; } @Deprecated public void computePackageFragmentRoots( IClasspathEntry[] resolvedClasspath, ObjectVector accumulatedRoots, HashSet rootIDs, IClasspathEntry referringEntry, boolean retrieveExportedRoots, boolean filterModuleRoots, Map rootToResolvedEntries) throws JavaModelException { computePackageFragmentRoots(resolvedClasspath, accumulatedRoots, rootIDs, referringEntry, retrieveExportedRoots, filterModuleRoots, rootToResolvedEntries, false); }
Returns (local/all) the package fragment roots identified by the given project's classpath. Note: this follows project classpath references to find required project contributions, eliminating duplicates silently. Only works with resolved entries
Params:
  • resolvedClasspath – IClasspathEntry[]
  • accumulatedRoots – ObjectVector
  • rootIDs – HashSet
  • referringEntry – project entry referring to this CP or null if initial project
  • retrieveExportedRoots – boolean
  • filterModuleRoots – if true, roots corresponding to modules will be filtered if applicable: if a limit-modules attribute exists, this is used, otherwise system modules will be filtered according to the rules of root modules per JEP 261.
Throws:
/** * Returns (local/all) the package fragment roots identified by the given project's classpath. * Note: this follows project classpath references to find required project contributions, * eliminating duplicates silently. * Only works with resolved entries * @param resolvedClasspath IClasspathEntry[] * @param accumulatedRoots ObjectVector * @param rootIDs HashSet * @param referringEntry project entry referring to this CP or null if initial project * @param retrieveExportedRoots boolean * @param filterModuleRoots if true, roots corresponding to modules will be filtered if applicable: * if a limit-modules attribute exists, this is used, otherwise system modules will be filtered * according to the rules of root modules per JEP 261. * @throws JavaModelException */
public void computePackageFragmentRoots( IClasspathEntry[] resolvedClasspath, ObjectVector accumulatedRoots, HashSet rootIDs, IClasspathEntry referringEntry, boolean retrieveExportedRoots, boolean filterModuleRoots, Map rootToResolvedEntries, boolean excludeTestCode) throws JavaModelException { if (referringEntry == null){ rootIDs.add(rootID()); } for (int i = 0, length = resolvedClasspath.length; i < length; i++){ computePackageFragmentRoots( resolvedClasspath[i], accumulatedRoots, rootIDs, referringEntry, retrieveExportedRoots, filterModuleRoots, rootToResolvedEntries, excludeTestCode); } }
Compute the file name to use for a given shared property
Params:
  • qName – QualifiedName
Returns:String
/** * Compute the file name to use for a given shared property * @param qName QualifiedName * @return String */
public String computeSharedPropertyFileName(QualifiedName qName) { return '.' + qName.getLocalName(); }
Configure the project with Java nature.
/** * Configure the project with Java nature. */
@Override public void configure() throws CoreException { // register Java builder addToBuildSpec(JavaCore.BUILDER_ID); } /* * Returns whether the given resource is accessible through the children or the non-Java resources of this project. * Returns true if the resource is not in the project. * Assumes that the resource is a folder or a file. */ public boolean contains(IResource resource) { IClasspathEntry[] classpath; IPath output; try { classpath = getResolvedClasspath(); output = getOutputLocation(); } catch (JavaModelException e) { return false; } IPath fullPath = resource.getFullPath(); IPath innerMostOutput = output.isPrefixOf(fullPath) ? output : null; IClasspathEntry innerMostEntry = null; ExternalFoldersManager foldersManager = JavaModelManager.getExternalManager(); for (int j = 0, cpLength = classpath.length; j < cpLength; j++) { IClasspathEntry entry = classpath[j]; IPath entryPath = entry.getPath(); if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { IResource linkedFolder = foldersManager.getFolder(entryPath); if (linkedFolder != null) entryPath = linkedFolder.getFullPath(); } if ((innerMostEntry == null || innerMostEntry.getPath().isPrefixOf(entryPath)) && entryPath.isPrefixOf(fullPath)) { innerMostEntry = entry; } IPath entryOutput = classpath[j].getOutputLocation(); if (entryOutput != null && entryOutput.isPrefixOf(fullPath)) { innerMostOutput = entryOutput; } } if (innerMostEntry != null) { // special case prj==src and nested output location if (innerMostOutput != null && innerMostOutput.segmentCount() > 1 // output isn't project && innerMostEntry.getPath().segmentCount() == 1) { // 1 segment must be project name return false; } if (resource instanceof IFolder) { // folders are always included in src/lib entries return true; } switch (innerMostEntry.getEntryKind()) { case IClasspathEntry.CPE_SOURCE: // .class files are not visible in source folders return !org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(fullPath.lastSegment()); case IClasspathEntry.CPE_LIBRARY: // .java files are not visible in library folders return !org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(fullPath.lastSegment()); } } if (innerMostOutput != null) { return false; } return true; }
Record a new marker denoting a classpath problem
/** * Record a new marker denoting a classpath problem */
public void createClasspathProblemMarker(IJavaModelStatus status) { IMarker marker = null; int severity; String[] arguments = CharOperation.NO_STRINGS; boolean isCycleProblem = false, isClasspathFileFormatProblem = false, isOutputOverlapping = false; switch (status.getCode()) { case IJavaModelStatusConstants.CLASSPATH_CYCLE : isCycleProblem = true; if (JavaCore.ERROR.equals(getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true))) { severity = IMarker.SEVERITY_ERROR; } else { severity = IMarker.SEVERITY_WARNING; } break; case IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT : isClasspathFileFormatProblem = true; severity = IMarker.SEVERITY_ERROR; break; case IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL : String setting = getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true); if (JavaCore.ERROR.equals(setting)) { severity = IMarker.SEVERITY_ERROR; } else if (JavaCore.WARNING.equals(setting)) { severity = IMarker.SEVERITY_WARNING; } else { return; // setting == IGNORE } break; case IJavaModelStatusConstants.OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE : isOutputOverlapping = true; setting = getOption(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, true); if (JavaCore.ERROR.equals(setting)) { severity = IMarker.SEVERITY_ERROR; } else if (JavaCore.WARNING.equals(setting)) { severity = IMarker.SEVERITY_WARNING; } else { return; // setting == IGNORE } break; case IJavaModelStatusConstants.MAIN_ONLY_PROJECT_DEPENDS_ON_TEST_ONLY_PROJECT: setting = getOption(JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY, true); if (JavaCore.ERROR.equals(setting)) { severity = IMarker.SEVERITY_ERROR; } else { return; // setting == IGNORE } break; default: IPath path = status.getPath(); if (path != null) arguments = new String[] { path.toString() }; if (JavaCore.ERROR.equals(getOption(JavaCore.CORE_INCOMPLETE_CLASSPATH, true)) && status.getSeverity() != IStatus.WARNING) { severity = IMarker.SEVERITY_ERROR; } else { severity = IMarker.SEVERITY_WARNING; } break; } try { marker = this.project.createMarker(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER); marker.setAttributes( new String[] { IMarker.MESSAGE, IMarker.SEVERITY, IMarker.LOCATION, IJavaModelMarker.CYCLE_DETECTED, IJavaModelMarker.CLASSPATH_FILE_FORMAT, IJavaModelMarker.OUTPUT_OVERLAPPING_SOURCE, IJavaModelMarker.ID, IJavaModelMarker.ARGUMENTS , IJavaModelMarker.CATEGORY_ID, IMarker.SOURCE_ID, }, new Object[] { status.getMessage(), Integer.valueOf(severity), Messages.classpath_buildPath, isCycleProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$ isClasspathFileFormatProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$ isOutputOverlapping ? "true" : "false", //$NON-NLS-1$ //$NON-NLS-2$ Integer.valueOf(status.getCode()), Util.getProblemArgumentsForMarker(arguments) , Integer.valueOf(CategorizedProblem.CAT_BUILDPATH), JavaBuilder.SOURCE_ID, } ); } catch (CoreException e) { // could not create marker: cannot do much if (JavaModelManager.VERBOSE) { e.printStackTrace(); } } }
Returns a new element info for this element.
/** * Returns a new element info for this element. */
@Override protected Object createElementInfo() { return new JavaProjectElementInfo(); }
Reads and decode an XML classpath string. Returns a two-dimensional array, where the number of elements in the row is fixed to 2. The first element is an array of raw classpath entries and the second element is an array of referenced entries that may have been stored by the client earlier. See IJavaProject.getReferencedClasspathEntries() for more details.
/** * Reads and decode an XML classpath string. Returns a two-dimensional array, where the number of elements in the row is fixed to 2. * The first element is an array of raw classpath entries and the second element is an array of referenced entries that may have been stored * by the client earlier. See {@link IJavaProject#getReferencedClasspathEntries()} for more details. * */
public IClasspathEntry[][] decodeClasspath(String xmlClasspath, Map unknownElements) throws IOException, ClasspathEntry.AssertionFailedException { ArrayList paths = new ArrayList(); IClasspathEntry defaultOutput = null; StringReader reader = new StringReader(xmlClasspath); Element cpElement; try { DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); cpElement = parser.parse(new InputSource(reader)).getDocumentElement(); } catch (SAXException | ParserConfigurationException e) { throw new IOException(Messages.file_badFormat, e); } finally { reader.close(); } if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$ throw new IOException(Messages.file_badFormat); } NodeList list = cpElement.getElementsByTagName(ClasspathEntry.TAG_CLASSPATHENTRY); int length = list.getLength(); for (int i = 0; i < length; ++i) { Node node = list.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this, unknownElements); if (entry != null){ if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { defaultOutput = entry; // separate output } else { paths.add(entry); } } } } int pathSize = paths.size(); IClasspathEntry[][] entries = new IClasspathEntry[2][]; entries[0] = new IClasspathEntry[pathSize + (defaultOutput == null ? 0 : 1)]; paths.toArray(entries[0]); if (defaultOutput != null) entries[0][pathSize] = defaultOutput; // ensure output is last item paths.clear(); list = cpElement.getElementsByTagName(ClasspathEntry.TAG_REFERENCED_ENTRY); length = list.getLength(); for (int i = 0; i < length; ++i) { Node node = list.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this, unknownElements); if (entry != null){ paths.add(entry); } } } entries[1] = new IClasspathEntry[paths.size()]; paths.toArray(entries[1]); return entries; } @Override public IClasspathEntry decodeClasspathEntry(String encodedEntry) { try { if (encodedEntry == null) return null; StringReader reader = new StringReader(encodedEntry); Element node; try { DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); node = parser.parse(new InputSource(reader)).getDocumentElement(); } catch (SAXException | ParserConfigurationException e) { return null; } finally { reader.close(); } if (!node.getNodeName().equalsIgnoreCase(ClasspathEntry.TAG_CLASSPATHENTRY) || node.getNodeType() != Node.ELEMENT_NODE) { return null; } return ClasspathEntry.elementDecode(node, this, null/*not interested in unknown elements*/); } catch (IOException e) { // bad format return null; } }
/** Removes the Java nature from the project.
/** /** * Removes the Java nature from the project. */
@Override public void deconfigure() throws CoreException { // deregister Java builder removeFromBuildSpec(JavaCore.BUILDER_ID); // remove .classpath file // getProject().getFile(ClasspathHelper.CLASSPATH_FILENAME).delete(false, null); }
Returns a default class path. This is the root of the project
/** * Returns a default class path. * This is the root of the project */
protected IClasspathEntry[] defaultClasspath() { return new IClasspathEntry[] { JavaCore.newSourceEntry(this.project.getFullPath())}; }
Returns a default output location. This is the project bin folder
/** * Returns a default output location. * This is the project bin folder */
protected IPath defaultOutputLocation() { return this.project.getFullPath().append("bin"); //$NON-NLS-1$ }
Returns the XML String encoding of the class path.
/** * Returns the XML String encoding of the class path. */
protected String encodeClasspath(IClasspathEntry[] classpath, IClasspathEntry[] referencedEntries, IPath outputLocation, boolean indent, Map unknownElements) throws JavaModelException { try { ByteArrayOutputStream s = new ByteArrayOutputStream(); OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$ XMLWriter xmlWriter = new XMLWriter(writer, this, true/*print XML version*/); xmlWriter.startTag(ClasspathEntry.TAG_CLASSPATH, indent); for (int i = 0; i < classpath.length; ++i) { ((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements, false); } if (outputLocation != null) { outputLocation = outputLocation.removeFirstSegments(1); outputLocation = outputLocation.makeRelative(); HashMap parameters = new HashMap(); parameters.put(ClasspathEntry.TAG_KIND, ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT)); parameters.put(ClasspathEntry.TAG_PATH, String.valueOf(outputLocation)); xmlWriter.printTag(ClasspathEntry.TAG_CLASSPATHENTRY, parameters, indent, true, true); } if (referencedEntries != null) { for (int i = 0; i < referencedEntries.length; ++i) { ((ClasspathEntry) referencedEntries[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements, true); } } xmlWriter.endTag(ClasspathEntry.TAG_CLASSPATH, indent, true/*insert new line*/); writer.flush(); writer.close(); return s.toString("UTF8");//$NON-NLS-1$ } catch (IOException e) { throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); } } @Override public String encodeClasspathEntry(IClasspathEntry classpathEntry) { try { ByteArrayOutputStream s = new ByteArrayOutputStream(); OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$ XMLWriter xmlWriter = new XMLWriter(writer, this, false/*don't print XML version*/); ((ClasspathEntry)classpathEntry).elementEncode(xmlWriter, this.project.getFullPath(), true/*indent*/, true/*insert new line*/, null/*not interested in unknown elements*/, (classpathEntry.getReferencingEntry() != null)); writer.flush(); writer.close(); return s.toString("UTF8");//$NON-NLS-1$ } catch (IOException e) { return null; // never happens since all is done in memory } }
Returns true if this handle represents the same Java project as the given handle. Two handles represent the same project if they are identical or if they represent a project with the same underlying resource and occurrence counts.
See Also:
  • equals.equals(Object)
/** * Returns true if this handle represents the same Java project * as the given handle. Two handles represent the same * project if they are identical or if they represent a project with * the same underlying resource and occurrence counts. * * @see JavaElement#equals(Object) */
@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof JavaProject)) return false; JavaProject other = (JavaProject) o; return this.project.equals(other.getProject()); }
See Also:
  • findElement.findElement(IPath)
/** * @see IJavaProject#findElement(IPath) */
@Override public IJavaElement findElement(IPath path) throws JavaModelException { return findElement(path, DefaultWorkingCopyOwner.PRIMARY); }
See Also:
  • findElement.findElement(IPath, WorkingCopyOwner)
/** * @see IJavaProject#findElement(IPath, WorkingCopyOwner) */
@Override public IJavaElement findElement(IPath path, WorkingCopyOwner owner) throws JavaModelException { if (path == null || path.isAbsolute()) { throw new JavaModelException( new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, path)); } try { String extension = path.getFileExtension(); if (extension == null) { String packageName = path.toString().replace(IPath.SEPARATOR, '.'); return findPackageFragment(packageName); } else if (Util.isJavaLikeFileName(path.lastSegment()) || extension.equalsIgnoreCase(EXTENSION_class)) { IPath packagePath = path.removeLastSegments(1); String packageName = packagePath.toString().replace(IPath.SEPARATOR, '.'); String typeName = path.lastSegment(); typeName = typeName.substring(0, typeName.length() - extension.length() - 1); String qualifiedName = null; if (packageName.length() > 0) { qualifiedName = packageName + "." + typeName; //$NON-NLS-1$ } else { qualifiedName = typeName; } // lookup type NameLookup lookup = newNameLookup(owner); NameLookup.Answer answer = lookup.findType( qualifiedName, false, NameLookup.ACCEPT_ALL, true/* consider secondary types */, false/* do NOT wait for indexes */, false/*don't check restrictions*/, null); if (answer != null) { return answer.type.getParent(); } else { return null; } } else { // unsupported extension return null; } } catch (JavaModelException e) { if (e.getStatus().getCode() == IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST) { return null; } else { throw e; } } } public IJavaElement findPackageFragment(String packageName) throws JavaModelException { NameLookup lookup = newNameLookup((WorkingCopyOwner)null/*no need to look at working copies for pkgs*/); IPackageFragment[] pkgFragments = lookup.findPackageFragments(packageName, false); if (pkgFragments == null) { return null; } else { // try to return one that is a child of this project for (int i = 0, length = pkgFragments.length; i < length; i++) { IPackageFragment pkgFragment = pkgFragments[i]; if (equals(pkgFragment.getParent().getParent())) { return pkgFragment; } } // default to the first one return pkgFragments[0]; } } @Override public IJavaElement findElement(String bindingKey, WorkingCopyOwner owner) throws JavaModelException { JavaElementFinder elementFinder = new JavaElementFinder(bindingKey, this, owner); elementFinder.parse(); if (elementFinder.exception != null) throw elementFinder.exception; return elementFinder.element; }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IPackageFragment findPackageFragment(IPath path) throws JavaModelException { return findPackageFragment0(JavaProject.canonicalizedPath(path)); } /* * non path canonicalizing version */ private IPackageFragment findPackageFragment0(IPath path) throws JavaModelException { NameLookup lookup = newNameLookup((WorkingCopyOwner)null/*no need to look at working copies for pkgs*/); return lookup.findPackageFragment(path); }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IPackageFragmentRoot findPackageFragmentRoot(IPath path) throws JavaModelException { return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path)); } /* * no path canonicalization */ public IPackageFragmentRoot findPackageFragmentRoot0(IPath path) throws JavaModelException { IPackageFragmentRoot[] allRoots = this.getAllPackageFragmentRoots(); if (!path.isAbsolute()) { throw new IllegalArgumentException(Messages.path_mustBeAbsolute); } for (int i= 0; i < allRoots.length; i++) { IPackageFragmentRoot classpathRoot= allRoots[i]; if (classpathRoot.getPath() != null && classpathRoot.getPath().equals(path)) { return classpathRoot; } } return null; }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IPackageFragmentRoot[] findPackageFragmentRoots(IClasspathEntry entry) { try { IClasspathEntry[] classpath = getRawClasspath(); for (int i = 0, length = classpath.length; i < length; i++) { if (classpath[i].equals(entry)) { // entry may need to be resolved return computePackageFragmentRoots( resolveClasspath(new IClasspathEntry[] {entry}), false, // don't retrieve exported roots true, // filterModuleRoots null); /*no reverse map*/ } } } catch (JavaModelException e) { // project doesn't exist: return an empty array } return new IPackageFragmentRoot[] {}; }
See Also:
  • findType.findType(String)
/** * @see IJavaProject#findType(String) */
@Override public IType findType(String fullyQualifiedName) throws JavaModelException { return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY); }
See Also:
  • findType.findType(String, IProgressMonitor)
/** * @see IJavaProject#findType(String, IProgressMonitor) */
@Override public IType findType(String fullyQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException { return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY, progressMonitor); } /* * Internal findType with instanciated name lookup */ IType findType(String fullyQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException { NameLookup.Answer answer = lookup.findType( fullyQualifiedName, false, NameLookup.ACCEPT_ALL, considerSecondaryTypes, true, /* wait for indexes (only if consider secondary types)*/ false/*don't check restrictions*/, progressMonitor); if (answer == null) { // try to find enclosing type int lastDot = fullyQualifiedName.lastIndexOf('.'); if (lastDot == -1) return null; IType type = findType(fullyQualifiedName.substring(0, lastDot), lookup, considerSecondaryTypes, progressMonitor); if (type != null) { type = type.getType(fullyQualifiedName.substring(lastDot+1)); if (!type.exists()) { return null; } } return type; } return answer.type; }
See Also:
  • findType.findType(String, String)
/** * @see IJavaProject#findType(String, String) */
@Override public IType findType(String packageName, String typeQualifiedName) throws JavaModelException { return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY); }
See Also:
  • findType.findType(String, String, IProgressMonitor)
/** * @see IJavaProject#findType(String, String, IProgressMonitor) */
@Override public IType findType(String packageName, String typeQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException { return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY, progressMonitor); } /* * Internal findType with instanciated name lookup */ IType findType(String packageName, String typeQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException { NameLookup.Answer answer = lookup.findType( typeQualifiedName, packageName, false, NameLookup.ACCEPT_ALL, considerSecondaryTypes, true, // wait for indexes (in case we need to consider secondary types) false/*don't check restrictions*/, progressMonitor); return answer == null ? null : answer.type; }
See Also:
  • findType.findType(String, String, WorkingCopyOwner)
/** * @see IJavaProject#findType(String, String, WorkingCopyOwner) */
@Override public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException { NameLookup lookup = newNameLookup(owner); return findType( packageName, typeQualifiedName, lookup, false, // do not consider secondary types null); }
See Also:
  • findType.findType(String, String, WorkingCopyOwner, IProgressMonitor)
/** * @see IJavaProject#findType(String, String, WorkingCopyOwner, IProgressMonitor) */
@Override public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException { NameLookup lookup = newNameLookup(owner); return findType( packageName, typeQualifiedName, lookup, true, // consider secondary types progressMonitor); }
See Also:
  • findType.findType(String, WorkingCopyOwner)
/** * @see IJavaProject#findType(String, WorkingCopyOwner) */
@Override public IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException { NameLookup lookup = newNameLookup(owner); return findType(fullyQualifiedName, lookup, false, null); }
See Also:
  • findType.findType(String, WorkingCopyOwner, IProgressMonitor)
/** * @see IJavaProject#findType(String, WorkingCopyOwner, IProgressMonitor) */
@Override public IType findType(String fullyQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException { NameLookup lookup = newNameLookup(owner); return findType(fullyQualifiedName, lookup, true, progressMonitor); } @Override public IModuleDescription findModule(String moduleName, WorkingCopyOwner owner) throws JavaModelException { NameLookup lookup = newNameLookup(owner); return findModule(moduleName, lookup); } /* * Internal findModule with instantiated name lookup */ IModuleDescription findModule(String moduleName, NameLookup lookup) throws JavaModelException { NameLookup.Answer answer = lookup.findModule(moduleName.toCharArray()); if (answer != null) return answer.module; return null; }
Remove all markers denoting classpath problems
/** * Remove all markers denoting classpath problems */
//TODO (philippe) should improve to use a bitmask instead of booleans (CYCLE, FORMAT, VALID) protected void flushClasspathProblemMarkers(boolean flushCycleMarkers, boolean flushClasspathFormatMarkers, boolean flushOverlappingOutputMarkers) { try { if (this.project.isAccessible()) { IMarker[] markers = this.project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); for (int i = 0, length = markers.length; i < length; i++) { IMarker marker = markers[i]; if (flushCycleMarkers && flushClasspathFormatMarkers && flushOverlappingOutputMarkers) { marker.delete(); } else { String cycleAttr = (String)marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED); String classpathFileFormatAttr = (String)marker.getAttribute(IJavaModelMarker.CLASSPATH_FILE_FORMAT); String overlappingOutputAttr = (String) marker.getAttribute(IJavaModelMarker.OUTPUT_OVERLAPPING_SOURCE); if ((flushCycleMarkers == (cycleAttr != null && cycleAttr.equals("true"))) //$NON-NLS-1$ && (flushOverlappingOutputMarkers == (overlappingOutputAttr != null && overlappingOutputAttr.equals("true"))) //$NON-NLS-1$ && (flushClasspathFormatMarkers == (classpathFileFormatAttr != null && classpathFileFormatAttr.equals("true")))){ //$NON-NLS-1$ marker.delete(); } } } } } catch (CoreException e) { // could not flush markers: not much we can do if (JavaModelManager.VERBOSE) { e.printStackTrace(); } } }
Returns the set of patterns corresponding to this project visibility given rules
Returns:an array of IPath or null if none
/** * Returns the set of patterns corresponding to this project visibility given rules * @return an array of IPath or null if none */
public IPath[] getAccessRestrictions(String optionName) { String sequence = getOption(optionName, true); // inherit from workspace if (sequence == null || sequence.length() == 0) return null; IPath[] rules = null; char[][] patterns = CharOperation.splitOn('|', sequence.toCharArray()); int patternCount; if ((patternCount = patterns.length) > 0) { rules = new IPath[patternCount]; for (int j = 0; j < patterns.length; j++){ rules[j] = new Path(new String(patterns[j])); } } return rules; }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IPackageFragmentRoot[] getAllPackageFragmentRoots() throws JavaModelException { return getAllPackageFragmentRoots(null /*no reverse map*/, false); } @Deprecated public IPackageFragmentRoot[] getAllPackageFragmentRoots(Map rootToResolvedEntries) throws JavaModelException { return getAllPackageFragmentRoots(rootToResolvedEntries, false); } public IPackageFragmentRoot[] getAllPackageFragmentRoots(Map rootToResolvedEntries, boolean excludeTestCode) throws JavaModelException { return computePackageFragmentRoots(getResolvedClasspath(), true/*retrieveExportedRoots*/, true/*filterModuleRoots*/, rootToResolvedEntries, excludeTestCode); } @Override public IClasspathEntry getClasspathEntryFor(IPath path) throws JavaModelException { getResolvedClasspath(); // force resolution PerProjectInfo perProjectInfo = getPerProjectInfo(); if (perProjectInfo == null) return null; Map rootPathToResolvedEntries = perProjectInfo.rootPathToResolvedEntries; if (rootPathToResolvedEntries == null) return null; IClasspathEntry classpathEntry = (IClasspathEntry) rootPathToResolvedEntries.get(path); if (classpathEntry == null) { path = getProject().getWorkspace().getRoot().getLocation().append(path); classpathEntry = (IClasspathEntry) rootPathToResolvedEntries.get(path); } return classpathEntry; } /* * Returns the cycle marker associated with this project or null if none. */ public IMarker getCycleMarker(){ try { if (this.project.isAccessible()) { IMarker[] markers = this.project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); for (int i = 0, length = markers.length; i < length; i++) { IMarker marker = markers[i]; String cycleAttr = (String)marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED); if (cycleAttr != null && cycleAttr.equals("true")){ //$NON-NLS-1$ return marker; } } } } catch (CoreException e) { // could not get markers: return null } return null; }
Returns the project custom preference pool. Project preferences may include custom encoding.
Returns:IEclipsePreferences or null if the project does not have a java nature.
/** * Returns the project custom preference pool. * Project preferences may include custom encoding. * @return IEclipsePreferences or <code>null</code> if the project * does not have a java nature. */
public IEclipsePreferences getEclipsePreferences() { if (!JavaProject.hasJavaNature(this.project)) return null; // Get cached preferences if exist JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, true); if (perProjectInfo.preferences != null) return perProjectInfo.preferences; // Init project preferences IScopeContext context = new ProjectScope(getProject()); final IEclipsePreferences eclipsePreferences = context.getNode(JavaCore.PLUGIN_ID); updatePreferences(eclipsePreferences); perProjectInfo.preferences = eclipsePreferences; // Listen to new preferences node final IEclipsePreferences eclipseParentPreferences = (IEclipsePreferences) eclipsePreferences.parent(); if (eclipseParentPreferences != null) { if (this.preferencesNodeListener != null) { eclipseParentPreferences.removeNodeChangeListener(this.preferencesNodeListener); } this.preferencesNodeListener = new IEclipsePreferences.INodeChangeListener() { @Override public void added(IEclipsePreferences.NodeChangeEvent event) { // do nothing } @Override public void removed(IEclipsePreferences.NodeChangeEvent event) { if (event.getChild() == eclipsePreferences) { JavaModelManager.getJavaModelManager().resetProjectPreferences(JavaProject.this); } } }; eclipseParentPreferences.addNodeChangeListener(this.preferencesNodeListener); } // Listen to preferences changes if (this.preferencesChangeListener != null) { eclipsePreferences.removePreferenceChangeListener(this.preferencesChangeListener); } this.preferencesChangeListener = new IEclipsePreferences.IPreferenceChangeListener() { @Override public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) { String propertyName = event.getKey(); JavaModelManager manager = JavaModelManager.getJavaModelManager(); if (propertyName.startsWith(JavaCore.PLUGIN_ID)) { if (propertyName.equals(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER) || propertyName.equals(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER) || propertyName.equals(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE) || propertyName.equals(JavaCore.CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER) || propertyName.equals(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH) || propertyName.equals(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS) || propertyName.equals(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS) || propertyName.equals(JavaCore.CORE_INCOMPLETE_CLASSPATH) || propertyName.equals(JavaCore.CORE_CIRCULAR_CLASSPATH) || propertyName.equals(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE) || propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL) || propertyName.equals(JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY) || propertyName.equals(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM)) { manager.deltaState.addClasspathValidation(JavaProject.this); } manager.resetProjectOptions(JavaProject.this); JavaProject.this.resetCaches(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=233568 } } }; eclipsePreferences.addPreferenceChangeListener(this.preferencesChangeListener); return eclipsePreferences; } @Override public String getElementName() { return this.project.getName(); }
See Also:
  • IJavaElement
/** * @see IJavaElement */
@Override public int getElementType() { return JAVA_PROJECT; }
This is a helper method returning the expanded classpath for the project, as a list of classpath entries, where all classpath variable entries have been resolved and substituted with their final target entries. All project exports have been appended to project entries.
Throws:
Returns:IClasspathEntry[]
/** * This is a helper method returning the expanded classpath for the project, as a list of classpath entries, * where all classpath variable entries have been resolved and substituted with their final target entries. * All project exports have been appended to project entries. * @return IClasspathEntry[] * @throws JavaModelException */
public IClasspathEntry[] getExpandedClasspath() throws JavaModelException { return getExpandedClasspath(false); } public IClasspathEntry[] getExpandedClasspath(boolean excludeTestCode) throws JavaModelException { ArrayList<ClasspathEntry> accumulatedEntries = new ArrayList<>(); HashMap<String,Boolean> rootIDs = new HashMap<>(5); rootIDs.put(this.rootID(), excludeTestCode); computeExpandedClasspath(null, rootIDs, accumulatedEntries, excludeTestCode); IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries.size()]; accumulatedEntries.toArray(expandedPath); return expandedPath; }
The path is known to match a source/library folder entry.
Params:
  • path – IPath
Returns:IPackageFragmentRoot
/** * The path is known to match a source/library folder entry. * @param path IPath * @return IPackageFragmentRoot */
public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) { if (path.segmentCount() == 1) { // default project root return getPackageFragmentRoot(this.project); } return getPackageFragmentRoot(this.project.getWorkspace().getRoot().getFolder(path)); } /* * @see JavaElement */ @Override public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) { String mod = null; switch (token.charAt(0)) { case JEM_PACKAGEFRAGMENTROOT: String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH; token = null; List<IClasspathAttribute> attributes = new ArrayList<>(); while (memento.hasMoreTokens()) { token = memento.nextToken(); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=331821 if (token == MementoTokenizer.PACKAGEFRAGMENT || token == MementoTokenizer.COUNT) { break; } else if (token == MementoTokenizer.MODULE) { if (memento.hasMoreTokens()) { token = memento.nextToken(); if (token != null) { mod = token; } } continue; } else if (token == MementoTokenizer.CLASSPATH_ATTRIBUTE) { // PFR memento is optionally trailed by all extra classpath attributes ("=/name=/value=/"): String name = memento.getStringDelimitedBy(MementoTokenizer.CLASSPATH_ATTRIBUTE); String value = memento.getStringDelimitedBy(MementoTokenizer.CLASSPATH_ATTRIBUTE); attributes.add(new ClasspathAttribute(name, value)); token = null; // consumed continue; } rootPath += token; } IClasspathAttribute[] attributesArray = null; if (!attributes.isEmpty()) attributesArray = attributes.toArray(new IClasspathAttribute[attributes.size()]); JavaElement root = (mod == null) ? (JavaElement)getPackageFragmentRoot(new Path(rootPath), attributesArray) : new JrtPackageFragmentRoot(new Path(rootPath), mod, this, attributesArray); if (token != null && (token.charAt(0) == JEM_PACKAGEFRAGMENT)) { return root.getHandleFromMemento(token, memento, owner); } else { return root.getHandleFromMemento(memento, owner); } } return null; }
Returns the char that marks the start of this handles contribution to a memento.
/** * Returns the <code>char</code> that marks the start of this handles * contribution to a memento. */
@Override protected char getHandleMementoDelimiter() { return JEM_JAVAPROJECT; }
Find the specific Java command amongst the given build spec and return its index or -1 if not found.
/** * Find the specific Java command amongst the given build spec * and return its index or -1 if not found. */
private int getJavaCommandIndex(ICommand[] buildSpec) { for (int i = 0; i < buildSpec.length; ++i) { if (buildSpec[i].getBuilderName().equals(JavaCore.BUILDER_ID)) { return i; } } return -1; }
Convenience method that returns the specific type of info for a Java project.
/** * Convenience method that returns the specific type of info for a Java project. */
protected JavaProjectElementInfo getJavaProjectElementInfo() throws JavaModelException { return (JavaProjectElementInfo) getElementInfo(); }
Returns an array of non-java resources contained in the receiver.
/** * Returns an array of non-java resources contained in the receiver. */
@Override public Object[] getNonJavaResources() throws JavaModelException { return ((JavaProjectElementInfo) getElementInfo()).getNonJavaResources(this); }
See Also:
  • getOption.getOption(String, boolean)
/** * @see org.eclipse.jdt.core.IJavaProject#getOption(String, boolean) */
@Override public String getOption(String optionName, boolean inheritJavaCoreOptions) { return JavaModelManager.getJavaModelManager().getOption(optionName, inheritJavaCoreOptions, getEclipsePreferences()); }
See Also:
  • getOptions.getOptions(boolean)
/** * @see org.eclipse.jdt.core.IJavaProject#getOptions(boolean) */
@Override public Map<String, String> getOptions(boolean inheritJavaCoreOptions) { // initialize to the defaults from JavaCore options pool Map<String, String> options = inheritJavaCoreOptions ? JavaCore.getOptions() : new Hashtable<String, String>(5); // Get project specific options JavaModelManager.PerProjectInfo perProjectInfo = null; Hashtable projectOptions = null; JavaModelManager javaModelManager = JavaModelManager.getJavaModelManager(); HashSet optionNames = javaModelManager.optionNames; try { perProjectInfo = getPerProjectInfo(); projectOptions = perProjectInfo.options; if (projectOptions == null) { // get eclipse preferences IEclipsePreferences projectPreferences= getEclipsePreferences(); if (projectPreferences == null) return options; // cannot do better (non-Java project) // create project options String[] propertyNames = projectPreferences.keys(); projectOptions = new Hashtable(propertyNames.length); for (int i = 0; i < propertyNames.length; i++){ String propertyName = propertyNames[i]; String value = projectPreferences.get(propertyName, null); if (value != null) { value = value.trim(); // Keep the option value, even if it's deprecated // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=324987 projectOptions.put(propertyName, value); if (!optionNames.contains(propertyName)) { // try to migrate deprecated options String[] compatibleOptions = javaModelManager.deprecatedOptions.get(propertyName); if (compatibleOptions != null) { for (int co=0, length=compatibleOptions.length; co < length; co++) { String compatibleOption = compatibleOptions[co]; if (!projectOptions.containsKey(compatibleOption)) projectOptions.put(compatibleOption, value); } } } } } // cache project options perProjectInfo.options = projectOptions; } } catch (JavaModelException | BackingStoreException e) { projectOptions = new Hashtable(); } // Inherit from JavaCore options if specified if (inheritJavaCoreOptions) { Iterator propertyNames = projectOptions.entrySet().iterator(); while (propertyNames.hasNext()) { Map.Entry entry = (Map.Entry) propertyNames.next(); String propertyName = (String) entry.getKey(); String propertyValue = (String) entry.getValue(); if (propertyValue != null && javaModelManager.knowsOption(propertyName)){ options.put(propertyName, propertyValue.trim()); } } Util.fixTaskTags(options); return options; } Util.fixTaskTags(projectOptions); return projectOptions; }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IPath getOutputLocation() throws JavaModelException { // Do not create marker while getting output location JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo(); IPath outputLocation = perProjectInfo.outputLocation; if (outputLocation != null) return outputLocation; // force to read classpath - will position output location as well getRawClasspath(); outputLocation = perProjectInfo.outputLocation; if (outputLocation == null) { return defaultOutputLocation(); } return outputLocation; }
Params:
  • path – IPath
Returns:A handle to the package fragment root identified by the given path. This method is handle-only and the element may or may not exist. Returns null if unable to generate a handle from the path (for example, an absolute path that has less than 1 segment. The path may be relative or absolute.
/** * @param path IPath * @return A handle to the package fragment root identified by the given path. * This method is handle-only and the element may or may not exist. Returns * <code>null</code> if unable to generate a handle from the path (for example, * an absolute path that has less than 1 segment. The path may be relative or * absolute. */
public IPackageFragmentRoot getPackageFragmentRoot(IPath path, IClasspathAttribute[] extraAttributes) { if (!path.isAbsolute()) { path = getPath().append(path); } int segmentCount = path.segmentCount(); if (segmentCount == 0) { return null; } if (path.getDevice() != null || JavaModel.getExternalTarget(path, true/*check existence*/) != null) { // external path return getPackageFragmentRoot0(path, extraAttributes); } IWorkspaceRoot workspaceRoot = this.project.getWorkspace().getRoot(); IResource resource = workspaceRoot.findMember(path); if (resource == null) { // resource doesn't exist in workspace if (path.getFileExtension() != null) { if (!workspaceRoot.getProject(path.segment(0)).exists()) { // assume it is an external ZIP archive return getPackageFragmentRoot0(path, extraAttributes); } else { // assume it is an internal ZIP archive resource = workspaceRoot.getFile(path); } } else if (segmentCount == 1) { // assume it is a project String projectName = path.segment(0); if (getElementName().equals(projectName)) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75814 // default root resource = this.project; } else { // lib being another project resource = workspaceRoot.getProject(projectName); } } else { // assume it is an internal folder resource = workspaceRoot.getFolder(path); } } return getPackageFragmentRoot(resource, null, extraAttributes); }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IPackageFragmentRoot getPackageFragmentRoot(IResource resource) { return getPackageFragmentRoot(resource, null/*no entry path*/, null/*no extra attributes*/); } public IPackageFragmentRoot getPackageFragmentRoot(IResource resource, IPath entryPath, IClasspathAttribute[] extraAttributes) { switch (resource.getType()) { case IResource.FILE: return new JarPackageFragmentRoot(resource, resource.getFullPath(), this, extraAttributes); case IResource.FOLDER: if (ExternalFoldersManager.isInternalPathForExternalFolder(resource.getFullPath())) return new ExternalPackageFragmentRoot(resource, entryPath, this); return new PackageFragmentRoot(resource, this); case IResource.PROJECT: return new PackageFragmentRoot(resource, this); default: return null; } }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IPackageFragmentRoot getPackageFragmentRoot(String externalLibraryPath) { return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new Path(externalLibraryPath)), null); } /* * no path canonicalization */ public IPackageFragmentRoot getPackageFragmentRoot0(IPath externalLibraryPath, IClasspathAttribute[] extraAttributes) { IFolder linkedFolder = JavaModelManager.getExternalManager().getFolder(externalLibraryPath); if (linkedFolder != null) return new ExternalPackageFragmentRoot(linkedFolder, externalLibraryPath, this); if (JavaModelManager.isJrt(externalLibraryPath)) { return this.new JImageModuleFragmentBridge(externalLibraryPath, extraAttributes); } Object target = JavaModel.getTarget(externalLibraryPath, true/*check existency*/); if (target instanceof File && JavaModel.isFile(target)) { if (JavaModel.isJmod((File) target)) { return new JModPackageFragmentRoot(externalLibraryPath, this, extraAttributes); } } return new JarPackageFragmentRoot(null, externalLibraryPath, this, extraAttributes); }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IPackageFragmentRoot[] getPackageFragmentRoots() throws JavaModelException { Object[] children; int length; IPackageFragmentRoot[] roots; System.arraycopy( children = getChildren(), 0, roots = new IPackageFragmentRoot[length = children.length], 0, length); return roots; }
See Also:
  • IJavaProject
Deprecated:
/** * @see IJavaProject * @deprecated */
@Override public IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry) { return findPackageFragmentRoots(entry); }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IPackageFragment[] getPackageFragments() throws JavaModelException { IPackageFragmentRoot[] roots = getPackageFragmentRoots(); return getPackageFragmentsInRoots(roots); }
Returns all the package fragments found in the specified package fragment roots.
Params:
  • roots – IPackageFragmentRoot[]
Returns:IPackageFragment[]
/** * Returns all the package fragments found in the specified * package fragment roots. * @param roots IPackageFragmentRoot[] * @return IPackageFragment[] */
public IPackageFragment[] getPackageFragmentsInRoots(IPackageFragmentRoot[] roots) { ArrayList frags = new ArrayList(); for (int i = 0; i < roots.length; i++) { IPackageFragmentRoot root = roots[i]; try { IJavaElement[] rootFragments = root.getChildren(); Collections.addAll(frags, rootFragments); } catch (JavaModelException e) { // do nothing } } IPackageFragment[] fragments = new IPackageFragment[frags.size()]; frags.toArray(fragments); return fragments; }
See Also:
  • IJavaElement
/** * @see IJavaElement */
@Override public IPath getPath() { return this.project.getFullPath(); } public JavaModelManager.PerProjectInfo getPerProjectInfo() throws JavaModelException { return JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.project); } private IPath getPluginWorkingLocation() { return this.project.getWorkingLocation(JavaCore.PLUGIN_ID); }
See Also:
  • getProject.getProject()
/** * @see IJavaProject#getProject() */
@Override public IProject getProject() { return this.project; } @Deprecated public ProjectCache getProjectCache() throws JavaModelException { return getProjectCache(false); } public ProjectCache getProjectCache(boolean excludeTestCode) throws JavaModelException { return ((JavaProjectElementInfo) getElementInfo()).getProjectCache(this, excludeTestCode); }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IClasspathEntry[] getRawClasspath() throws JavaModelException { JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo(); IClasspathEntry[] classpath = perProjectInfo.rawClasspath; if (classpath != null) return classpath; classpath = perProjectInfo.readAndCacheClasspath(this)[0]; if (classpath == JavaProject.INVALID_CLASSPATH) return defaultClasspath(); return classpath; }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IClasspathEntry[] getReferencedClasspathEntries() throws JavaModelException { return getPerProjectInfo().referencedEntries; }
See Also:
  • getRequiredProjectNames.getRequiredProjectNames()
/** * @see IJavaProject#getRequiredProjectNames() */
@Override public String[] getRequiredProjectNames() throws JavaModelException { return projectPrerequisites(getResolvedClasspath()); } public IClasspathEntry[] getResolvedClasspath() throws JavaModelException { PerProjectInfo perProjectInfo = getPerProjectInfo(); IClasspathEntry[] resolvedClasspath = perProjectInfo.getResolvedClasspath(); if (resolvedClasspath == null) { resolveClasspath(perProjectInfo, false/*don't use previous session values*/, true/*add classpath change*/); resolvedClasspath = perProjectInfo.getResolvedClasspath(); if (resolvedClasspath == null) { // another thread reset the resolved classpath, use a temporary PerProjectInfo PerProjectInfo temporaryInfo = newTemporaryInfo(); resolveClasspath(temporaryInfo, false/*don't use previous session values*/, true/*add classpath change*/); resolvedClasspath = temporaryInfo.getResolvedClasspath(); } } return resolvedClasspath; }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry) throws JavaModelException { if (JavaModelManager.getJavaModelManager().isClasspathBeingResolved(this)) { if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED) verbose_reentering_classpath_resolution(); return RESOLUTION_IN_PROGRESS; } PerProjectInfo perProjectInfo = getPerProjectInfo(); // use synchronized block to ensure consistency IClasspathEntry[] resolvedClasspath; IJavaModelStatus unresolvedEntryStatus; synchronized (perProjectInfo) { resolvedClasspath = perProjectInfo.getResolvedClasspath(); unresolvedEntryStatus = perProjectInfo.unresolvedEntryStatus; } if (resolvedClasspath == null || (unresolvedEntryStatus != null && !unresolvedEntryStatus.isOK())) { // force resolution to ensure initializers are run again resolveClasspath(perProjectInfo, false/*don't use previous session values*/, true/*add classpath change*/); synchronized (perProjectInfo) { resolvedClasspath = perProjectInfo.getResolvedClasspath(); unresolvedEntryStatus = perProjectInfo.unresolvedEntryStatus; } if (resolvedClasspath == null) { // another thread reset the resolved classpath, use a temporary PerProjectInfo PerProjectInfo temporaryInfo = newTemporaryInfo(); resolveClasspath(temporaryInfo, false/*don't use previous session values*/, true/*add classpath change*/); resolvedClasspath = temporaryInfo.getResolvedClasspath(); unresolvedEntryStatus = temporaryInfo.unresolvedEntryStatus; } } if (!ignoreUnresolvedEntry && unresolvedEntryStatus != null && !unresolvedEntryStatus.isOK()) throw new JavaModelException(unresolvedEntryStatus); return resolvedClasspath; } private void verbose_reentering_classpath_resolution() { Util.verbose( "CPResolution: reentering raw classpath resolution, will use empty classpath instead" + //$NON-NLS-1$ " project: " + getElementName() + '\n' + //$NON-NLS-1$ " invocation stack trace:"); //$NON-NLS-1$ new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$ }
See Also:
  • IJavaElement
/** * @see IJavaElement */
@Override public IResource resource(PackageFragmentRoot root) { return this.project; }
Retrieve a shared property on a project. If the property is not defined, answers null. Note that it is orthogonal to IResource persistent properties, and client code has to decide which form of storage to use appropriately. Shared properties produce real resource files which can be shared through a VCM onto a server. Persistent properties are not shareable.
Params:
  • key – String
Throws:
See Also:
Returns:String
/** * Retrieve a shared property on a project. If the property is not defined, answers null. * Note that it is orthogonal to IResource persistent properties, and client code has to decide * which form of storage to use appropriately. Shared properties produce real resource files which * can be shared through a VCM onto a server. Persistent properties are not shareable. * * @param key String * @see JavaProject#setSharedProperty(String, String) * @return String * @throws CoreException */
public String getSharedProperty(String key) throws CoreException { String property = null; IFile rscFile = this.project.getFile(key); if (rscFile.exists()) { byte[] bytes = Util.getResourceContentsAsByteArray(rscFile); try { property = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8 } catch (UnsupportedEncodingException e) { Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$ // fallback to default property = new String(bytes); } } else { // when a project is imported, we get a first delta for the addition of the .project, but the .classpath is not accessible // so default to using java.io.File // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=96258 URI location = rscFile.getLocationURI(); if (location != null) { File file = Util.toLocalFile(location, null/*no progress monitor available*/); if (file != null && file.exists()) { byte[] bytes; try { bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file); } catch (IOException e) { return null; } try { property = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8 } catch (UnsupportedEncodingException e) { Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$ // fallback to default property = new String(bytes); } } } } return property; }
See Also:
  • JavaElement
/** * @see JavaElement */
@Override public SourceMapper getSourceMapper() { return null; }
See Also:
  • IJavaElement
/** * @see IJavaElement */
@Override public IResource getUnderlyingResource() throws JavaModelException { if (!exists()) throw newNotPresentException(); return this.project; }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public boolean hasBuildState() { return JavaModelManager.getJavaModelManager().getLastBuiltState(this.project, null) != null; }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public boolean hasClasspathCycle(IClasspathEntry[] preferredClasspath) { LinkedHashSet cycleParticipants = new LinkedHashSet(); HashMap preferredClasspaths = new HashMap(1); preferredClasspaths.put(this, preferredClasspath); updateCycleParticipants(new ArrayList(2), cycleParticipants, new HashMap<>(), ResourcesPlugin.getWorkspace().getRoot(), new HashSet(2), preferredClasspaths); return !cycleParticipants.isEmpty(); } public boolean hasCycleMarker(){ return getCycleMarker() != null; } @Override public int hashCode() { return this.project.hashCode(); } private boolean hasUTF8BOM(byte[] bytes) { if (bytes.length > IContentDescription.BOM_UTF_8.length) { for (int i = 0, length = IContentDescription.BOM_UTF_8.length; i < length; i++) { if (IContentDescription.BOM_UTF_8[i] != bytes[i]) return false; } return true; } return false; }
Answers true if the project potentially contains any source. A project which has no source is immutable.
Returns:boolean
/** * Answers true if the project potentially contains any source. A project which has no source is immutable. * @return boolean */
public boolean hasSource() { // look if any source folder on the classpath // no need for resolved path given source folder cannot be abstracted IClasspathEntry[] entries; try { entries = getRawClasspath(); } catch (JavaModelException e) { return true; // unsure } for (int i = 0, max = entries.length; i < max; i++) { if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) { return true; } } return false; } /* * @see IJavaProject */ @Override public boolean isOnClasspath(IJavaElement element) { IClasspathEntry[] rawClasspath; try { rawClasspath = getRawClasspath(); } catch(JavaModelException e){ return false; // not a Java project } int elementType = element.getElementType(); boolean isPackageFragmentRoot = false; boolean isFolderPath = false; boolean isSource = false; switch (elementType) { case IJavaElement.JAVA_MODEL: return false; case IJavaElement.JAVA_PROJECT: break; case IJavaElement.PACKAGE_FRAGMENT_ROOT: isPackageFragmentRoot = true; break; case IJavaElement.PACKAGE_FRAGMENT: isFolderPath = !((IPackageFragmentRoot)element.getParent()).isArchive(); break; case IJavaElement.COMPILATION_UNIT: isSource = true; break; default: isSource = element.getAncestor(IJavaElement.COMPILATION_UNIT) != null; break; } IPath elementPath = element.getPath(); // first look at unresolved entries int length = rawClasspath.length; for (int i = 0; i < length; i++) { IClasspathEntry entry = rawClasspath[i]; switch (entry.getEntryKind()) { case IClasspathEntry.CPE_LIBRARY: case IClasspathEntry.CPE_PROJECT: case IClasspathEntry.CPE_SOURCE: if (isOnClasspathEntry(elementPath, isFolderPath, isPackageFragmentRoot, entry)) return true; break; } } // no need to go further for compilation units and elements inside a compilation unit // it can only be in a source folder, thus on the raw classpath if (isSource) return false; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=304081 // All the resolved classpath entries need to be considered, including the referenced classpath entries IClasspathEntry[] resolvedClasspath = null; try { resolvedClasspath = getResolvedClasspath(); } catch (JavaModelException e) { return false; // Perhaps, not a Java project } for (int index = 0; index < resolvedClasspath.length; index++) { if (isOnClasspathEntry(elementPath, isFolderPath, isPackageFragmentRoot, resolvedClasspath[index])) return true; } return false; } /* * @see IJavaProject */ @Override public boolean isOnClasspath(IResource resource) { IPath exactPath = resource.getFullPath(); IPath path = exactPath; // ensure that folders are only excluded if all of their children are excluded int resourceType = resource.getType(); boolean isFolderPath = resourceType == IResource.FOLDER || resourceType == IResource.PROJECT; IClasspathEntry[] classpath; try { classpath = this.getResolvedClasspath(); } catch(JavaModelException e){ return false; // not a Java project } for (int i = 0; i < classpath.length; i++) { IClasspathEntry entry = classpath[i]; IPath entryPath = entry.getPath(); if (entryPath.equals(exactPath)) { // package fragment roots must match exactly entry pathes (no exclusion there) return true; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=276373 // When a classpath entry is absolute, convert the resource's relative path to a file system path and compare // e.g - /P/lib/variableLib.jar and /home/P/lib/variableLib.jar when compared should return true if (entryPath.isAbsolute() && entryPath.equals(ResourcesPlugin.getWorkspace().getRoot().getLocation().append(exactPath))) { return true; } if (entryPath.isPrefixOf(path) && !Util.isExcluded(path, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), isFolderPath)) { return true; } } return false; } private boolean isOnClasspathEntry(IPath elementPath, boolean isFolderPath, boolean isPackageFragmentRoot, IClasspathEntry entry) { IPath entryPath = entry.getPath(); if (isPackageFragmentRoot) { // package fragment roots must match exactly entry pathes (no exclusion there) if (entryPath.equals(elementPath)) return true; } else { if (entryPath.isPrefixOf(elementPath) && !Util.isExcluded(elementPath, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), isFolderPath)) return true; } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=276373 if (entryPath.isAbsolute() && entryPath.equals(ResourcesPlugin.getWorkspace().getRoot().getLocation().append(elementPath))) { return true; } return false; }
load preferences from a shareable format (VCM-wise)
/** * load preferences from a shareable format (VCM-wise) */
private IEclipsePreferences loadPreferences() { IEclipsePreferences preferences = null; IPath projectMetaLocation = getPluginWorkingLocation(); if (projectMetaLocation != null) { File prefFile = projectMetaLocation.append(PREF_FILENAME).toFile(); if (prefFile.exists()) { // load preferences from file InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(prefFile)); preferences = Platform.getPreferencesService().readPreferences(in); } catch (CoreException | IOException e) { // problems loading preference store - quietly ignore } finally { if (in != null) { try { in.close(); } catch (IOException e) { // ignore problems with close } } } // one shot read, delete old preferences prefFile.delete(); return preferences; } } return null; }
See Also:
  • newEvaluationContext.newEvaluationContext()
/** * @see IJavaProject#newEvaluationContext() */
@Override public IEvaluationContext newEvaluationContext() { EvaluationContext context = new EvaluationContext(); context.setLineSeparator(Util.getLineSeparator(null/*no existing source*/, this)); return new EvaluationContextWrapper(context, this); } public NameLookup newNameLookup(ICompilationUnit[] workingCopies) throws JavaModelException { return newNameLookup(workingCopies, false); } /* * Returns a new name lookup. This name lookup first looks in the given working copies. */ public NameLookup newNameLookup(ICompilationUnit[] workingCopies, boolean excludeTestCode) throws JavaModelException { return getJavaProjectElementInfo().newNameLookup(this, workingCopies, excludeTestCode); } public NameLookup newNameLookup(WorkingCopyOwner owner) throws JavaModelException { return newNameLookup(owner, false); } /* * Returns a new name lookup. This name lookup first looks in the working copies of the given owner. */ public NameLookup newNameLookup(WorkingCopyOwner owner, boolean excludeTestCode) throws JavaModelException { JavaModelManager manager = JavaModelManager.getJavaModelManager(); ICompilationUnit[] workingCopies = owner == null ? null : manager.getWorkingCopies(owner, true/*add primary WCs*/); return newNameLookup(workingCopies); } public SearchableEnvironment newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws JavaModelException { return newSearchableNameEnvironment(workingCopies, false); } /* * Returns a new search name environment for this project. This name environment first looks in the given working copies. */ public SearchableEnvironment newSearchableNameEnvironment(ICompilationUnit[] workingCopies, boolean excludeTestCode) throws JavaModelException { return new SearchableEnvironment(this, workingCopies, excludeTestCode); } /* * Returns a new search name environment for this project. This name environment first looks in the working copies * of the given owner. */ public SearchableEnvironment newSearchableNameEnvironment(WorkingCopyOwner owner) throws JavaModelException { return newSearchableNameEnvironment(owner, false); } public SearchableEnvironment newSearchableNameEnvironment(WorkingCopyOwner owner, boolean excludeTestCode) throws JavaModelException { return new SearchableEnvironment(this, owner, excludeTestCode); } /* * Returns a PerProjectInfo that doesn't register classpath change * and that should be used as a temporary info. */ public PerProjectInfo newTemporaryInfo() { return new PerProjectInfo(this.project.getProject()) { @Override protected ClasspathChange addClasspathChange() { return null; } }; }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public ITypeHierarchy newTypeHierarchy( IRegion region, IProgressMonitor monitor) throws JavaModelException { return newTypeHierarchy(region, DefaultWorkingCopyOwner.PRIMARY, monitor); }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public ITypeHierarchy newTypeHierarchy( IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException { if (region == null) { throw new IllegalArgumentException(Messages.hierarchy_nullRegion); } ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/); CreateTypeHierarchyOperation op = new CreateTypeHierarchyOperation(region, workingCopies, null, true); op.runOperation(monitor); return op.getResult(); }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public ITypeHierarchy newTypeHierarchy( IType type, IRegion region, IProgressMonitor monitor) throws JavaModelException { return newTypeHierarchy(type, region, DefaultWorkingCopyOwner.PRIMARY, monitor); }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public ITypeHierarchy newTypeHierarchy( IType type, IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException { if (type == null) { throw new IllegalArgumentException(Messages.hierarchy_nullFocusType); } if (region == null) { throw new IllegalArgumentException(Messages.hierarchy_nullRegion); } ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/); CreateTypeHierarchyOperation op = new CreateTypeHierarchyOperation(region, workingCopies, type, true/*compute subtypes*/); op.runOperation(monitor); return op.getResult(); } public String[] projectPrerequisites(IClasspathEntry[] resolvedClasspath) throws JavaModelException { ArrayList prerequisites = new ArrayList(); for (int i = 0, length = resolvedClasspath.length; i < length; i++) { IClasspathEntry entry = resolvedClasspath[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { prerequisites.add(entry.getPath().lastSegment()); } } int size = prerequisites.size(); if (size == 0) { return NO_PREREQUISITES; } else { String[] result = new String[size]; prerequisites.toArray(result); return result; } }
Reads the classpath file entries of this project's .classpath file. Returns a two-dimensional array, where the number of elements in the row is fixed to 2. The first element is an array of raw classpath entries, which includes the output entry, and the second element is an array of referenced entries that may have been stored by the client earlier. See IJavaProject.getReferencedClasspathEntries() for more details. As a side effect, unknown elements are stored in the given map (if not null) Throws exceptions if the file cannot be accessed or is malformed.
/** * Reads the classpath file entries of this project's .classpath file. * Returns a two-dimensional array, where the number of elements in the row is fixed to 2. * The first element is an array of raw classpath entries, which includes the output entry, * and the second element is an array of referenced entries that may have been stored * by the client earlier. * See {@link IJavaProject#getReferencedClasspathEntries()} for more details. * As a side effect, unknown elements are stored in the given map (if not null) * Throws exceptions if the file cannot be accessed or is malformed. */
public IClasspathEntry[][] readFileEntriesWithException(Map unknownElements) throws CoreException, IOException, ClasspathEntry.AssertionFailedException { IFile rscFile = this.project.getFile(JavaProject.CLASSPATH_FILENAME); byte[] bytes; if (rscFile.exists()) { bytes = Util.getResourceContentsAsByteArray(rscFile); } else { // when a project is imported, we get a first delta for the addition of the .project, but the .classpath is not accessible // so default to using java.io.File // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=96258 URI location = rscFile.getLocationURI(); if (location == null) throw new IOException("Cannot obtain a location URI for " + rscFile); //$NON-NLS-1$ File file = Util.toLocalFile(location, null/*no progress monitor available*/); if (file == null) throw new IOException("Unable to fetch file from " + location); //$NON-NLS-1$ try { bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file); } catch (IOException e) { if (!file.exists()) return new IClasspathEntry[][]{defaultClasspath(), ClasspathEntry.NO_ENTRIES}; throw e; } } if (hasUTF8BOM(bytes)) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=240034 int length = bytes.length-IContentDescription.BOM_UTF_8.length; System.arraycopy(bytes, IContentDescription.BOM_UTF_8.length, bytes = new byte[length], 0, length); } String xmlClasspath; try { xmlClasspath = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8 } catch (UnsupportedEncodingException e) { Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$ // fallback to default xmlClasspath = new String(bytes); } return decodeClasspath(xmlClasspath, unknownElements); } /* * Reads the classpath file entries of this project's .classpath file. * This includes the output entry. * As a side effect, unknown elements are stored in the given map (if not null) */ private IClasspathEntry[][] readFileEntries(Map unkwownElements) { try { return readFileEntriesWithException(unkwownElements); } catch (CoreException | IOException | ClasspathEntry.AssertionFailedException e) { Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$ return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES}; } }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IPath readOutputLocation() { // Read classpath file without creating markers nor logging problems IClasspathEntry[][] classpath = readFileEntries(null/*not interested in unknown elements*/); if (classpath[0] == JavaProject.INVALID_CLASSPATH) return defaultOutputLocation(); // extract the output location IPath outputLocation = null; if (classpath[0].length > 0) { IClasspathEntry entry = classpath[0][classpath[0].length - 1]; if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { outputLocation = entry.getPath(); } } return outputLocation; }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public IClasspathEntry[] readRawClasspath() { // Read classpath file without creating markers nor logging problems IClasspathEntry[][] classpath = readFileEntries(null/*not interested in unknown elements*/); if (classpath[0] == JavaProject.INVALID_CLASSPATH) return defaultClasspath(); // discard the output location if (classpath[0].length > 0) { IClasspathEntry entry = classpath[0][classpath[0].length - 1]; if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { IClasspathEntry[] copy = new IClasspathEntry[classpath[0].length - 1]; System.arraycopy(classpath[0], 0, copy, 0, copy.length); classpath[0] = copy; } } return classpath[0]; }
Removes the given builder from the build spec for the given project.
/** * Removes the given builder from the build spec for the given project. */
protected void removeFromBuildSpec(String builderID) throws CoreException { IProjectDescription description = this.project.getDescription(); ICommand[] commands = description.getBuildSpec(); for (int i = 0; i < commands.length; ++i) { if (commands[i].getBuilderName().equals(builderID)) { ICommand[] newCommands = new ICommand[commands.length - 1]; System.arraycopy(commands, 0, newCommands, 0, i); System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1); description.setBuildSpec(newCommands); this.project.setDescription(description, null); return; } } } /* * Resets this project's caches */ public void resetCaches() { JavaProjectElementInfo info = (JavaProjectElementInfo) JavaModelManager.getJavaModelManager().peekAtInfo(this); if (info != null){ info.resetCaches(); } } public ClasspathChange resetResolvedClasspath() { try { return getPerProjectInfo().resetResolvedClasspath(); } catch (JavaModelException e) { // project doesn't exist return null; } } /* * Resolve the given raw classpath. */ public IClasspathEntry[] resolveClasspath(IClasspathEntry[] rawClasspath) throws JavaModelException { return resolveClasspath(rawClasspath, false/*don't use previous session*/, true/*resolve chained libraries*/).resolvedClasspath; } static class ResolvedClasspath { IClasspathEntry[] resolvedClasspath; IJavaModelStatus unresolvedEntryStatus = JavaModelStatus.VERIFIED_OK; HashMap rawReverseMap = new HashMap(); Map rootPathToResolvedEntries = new HashMap(); IClasspathEntry[] referencedEntries = null; } public ResolvedClasspath resolveClasspath(IClasspathEntry[] rawClasspath, boolean usePreviousSession, boolean resolveChainedLibraries) throws JavaModelException { return resolveClasspath(rawClasspath, null, usePreviousSession, resolveChainedLibraries); } public ResolvedClasspath resolveClasspath(IClasspathEntry[] rawClasspath, IClasspathEntry[] referencedEntries, boolean usePreviousSession, boolean resolveChainedLibraries) throws JavaModelException { JavaModelManager manager = JavaModelManager.getJavaModelManager(); ExternalFoldersManager externalFoldersManager = JavaModelManager.getExternalManager(); ResolvedClasspath result = new ResolvedClasspath(); Map knownDrives = new HashMap(); Map referencedEntriesMap = new HashMap(); Set<IPath> rawLibrariesPath = new LinkedHashSet<>(); LinkedHashSet resolvedEntries = new LinkedHashSet(); if(resolveChainedLibraries) { for (int index = 0; index < rawClasspath.length; index++) { IClasspathEntry currentEntry = rawClasspath[index]; if (currentEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { rawLibrariesPath.add(ClasspathEntry.resolveDotDot(getProject().getLocation(), currentEntry.getPath())); } } if (referencedEntries != null) { // The Set is required to keep the order intact while the referencedEntriesMap (Map) // is used to map the referenced entries with path LinkedHashSet referencedEntriesSet = new LinkedHashSet(); for (int index = 0; index < referencedEntries.length; index++) { IPath path = referencedEntries[index].getPath(); if (!rawLibrariesPath.contains(path) && referencedEntriesMap.get(path) == null) { referencedEntriesMap.put(path, referencedEntries[index]); referencedEntriesSet.add(referencedEntries[index]); } } if (referencedEntriesSet.size() > 0) { result.referencedEntries = new IClasspathEntry[referencedEntriesSet.size()]; referencedEntriesSet.toArray(result.referencedEntries); } } } int length = rawClasspath.length; for (int i = 0; i < length; i++) { IClasspathEntry rawEntry = rawClasspath[i]; IClasspathEntry resolvedEntry = rawEntry; switch (rawEntry.getEntryKind()){ case IClasspathEntry.CPE_VARIABLE : try { resolvedEntry = manager.resolveVariableEntry(rawEntry, usePreviousSession); } catch (ClasspathEntry.AssertionFailedException e) { // Catch the assertion failure and set status instead // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992 result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, e.getMessage()); break; } if (resolvedEntry == null) { result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, this, rawEntry.getPath()); } else { // If the entry is already present in the rawReversetMap, it means the entry and the chained libraries // have already been processed. So, skip it. if (resolveChainedLibraries && resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && result.rawReverseMap.get(resolvedEntry.getPath()) == null) { // resolve Class-Path: in manifest ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries(); for (int j = 0, length2 = extraEntries.length; j < length2; j++) { if (!rawLibrariesPath.contains(extraEntries[j].getPath())) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=305037 // referenced entries for variable entries could also be persisted with extra attributes, so addAsChainedEntry = true addToResult(rawEntry, extraEntries[j], result, resolvedEntries, externalFoldersManager, referencedEntriesMap, true, knownDrives); } } } addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false, knownDrives); } break; case IClasspathEntry.CPE_CONTAINER : IClasspathContainer container = usePreviousSession ? manager.getPreviousSessionContainer(rawEntry.getPath(), this) : JavaCore.getClasspathContainer(rawEntry.getPath(), this); if (container == null){ result.unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_CONTAINER_PATH_UNBOUND, this, rawEntry.getPath()); break; } IClasspathEntry[] containerEntries = container.getClasspathEntries(); if (containerEntries == null) { if (JavaModelManager.CP_RESOLVE_VERBOSE || JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { JavaModelManager.getJavaModelManager().verbose_missbehaving_container_null_entries(this, rawEntry.getPath()); } break; } // container was bound for (int j = 0, containerLength = containerEntries.length; j < containerLength; j++){ ClasspathEntry cEntry = (ClasspathEntry) containerEntries[j]; if (cEntry == null) { if (JavaModelManager.CP_RESOLVE_VERBOSE || JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { JavaModelManager.getJavaModelManager().verbose_missbehaving_container(this, rawEntry.getPath(), containerEntries); } break; } // if container is exported or restricted, then its nested entries must in turn be exported (21749) and/or propagate restrictions cEntry = cEntry.combineWith((ClasspathEntry) rawEntry); if (cEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { // resolve ".." in library path cEntry = cEntry.resolvedDotDot(getProject().getLocation()); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=313965 // Do not resolve if the system attribute is set to false if (resolveChainedLibraries && JavaModelManager.getJavaModelManager().resolveReferencedLibrariesForContainers && result.rawReverseMap.get(cEntry.getPath()) == null) { // resolve Class-Path: in manifest ClasspathEntry[] extraEntries = cEntry.resolvedChainedLibraries(); for (int k = 0, length2 = extraEntries.length; k < length2; k++) { if (!rawLibrariesPath.contains(extraEntries[k].getPath())) { addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false, knownDrives); } } } } addToResult(rawEntry, cEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false, knownDrives); } break; case IClasspathEntry.CPE_LIBRARY: // resolve ".." in library path resolvedEntry = ((ClasspathEntry) rawEntry).resolvedDotDot(getProject().getLocation()); if (resolveChainedLibraries && result.rawReverseMap.get(resolvedEntry.getPath()) == null) { // resolve Class-Path: in manifest ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries(); for (int k = 0, length2 = extraEntries.length; k < length2; k++) { if (!rawLibrariesPath.contains(extraEntries[k].getPath())) { addToResult(rawEntry, extraEntries[k], result, resolvedEntries, externalFoldersManager, referencedEntriesMap, true, knownDrives); } } } addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false, knownDrives); break; default : addToResult(rawEntry, resolvedEntry, result, resolvedEntries, externalFoldersManager, referencedEntriesMap, false, knownDrives); break; } } result.resolvedClasspath = new IClasspathEntry[resolvedEntries.size()]; resolvedEntries.toArray(result.resolvedClasspath); return result; } private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, LinkedHashSet resolvedEntries, ExternalFoldersManager externalFoldersManager, Map oldChainedEntriesMap, boolean addAsChainedEntry, Map knownDrives) { IPath resolvedPath; // If it's already been resolved, do not add to resolvedEntries if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) { result.rawReverseMap.put(resolvedPath, rawEntry); result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry); resolvedEntries.add(resolvedEntry); if (addAsChainedEntry) { IClasspathEntry chainedEntry = null; chainedEntry = (ClasspathEntry) oldChainedEntriesMap.get(resolvedPath); if (chainedEntry != null) { // This is required to keep the attributes if any added by the user in // the previous session such as source attachment path etc. copyFromOldChainedEntry((ClasspathEntry) resolvedEntry, (ClasspathEntry) chainedEntry); } } } if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) { externalFoldersManager.addFolder(resolvedPath, true/*scheduleForCreation*/); // no-op if not an external folder or if already registered } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=336046 // The source attachment path could be external too and in which case, must be added. IPath sourcePath = resolvedEntry.getSourceAttachmentPath(); if (sourcePath != null && driveExists(sourcePath, knownDrives) && ExternalFoldersManager.isExternalFolderPath(sourcePath)) { externalFoldersManager.addFolder(sourcePath, true); } } private void copyFromOldChainedEntry(ClasspathEntry resolvedEntry, ClasspathEntry chainedEntry) { IPath path = chainedEntry.getSourceAttachmentPath(); if ( path != null) { resolvedEntry.sourceAttachmentPath = path; } path = chainedEntry.getSourceAttachmentRootPath(); if (path != null) { resolvedEntry.sourceAttachmentRootPath = path; } IClasspathAttribute[] attributes = chainedEntry.getExtraAttributes(); if (attributes != null) { resolvedEntry.extraAttributes = attributes; } } /* * File#exists() takes lot of time for an unmapped drive. Hence, cache the info. * https://bugs.eclipse.org/bugs/show_bug.cgi?id=338649 */ private boolean driveExists(IPath sourcePath, Map knownDrives) { String drive = sourcePath.getDevice(); if (drive == null) return true; Boolean good = (Boolean)knownDrives.get(drive); if (good == null) { if (new File(drive).exists()) { knownDrives.put(drive, Boolean.TRUE); return true; } else { knownDrives.put(drive, Boolean.FALSE); return false; } } return good.booleanValue(); } /* * Resolve the given perProjectInfo's raw classpath and store the resolved classpath in the perProjectInfo. */ public void resolveClasspath(PerProjectInfo perProjectInfo, boolean usePreviousSession, boolean addClasspathChange) throws JavaModelException { if (CP_RESOLUTION_BP_LISTENERS != null) breakpoint(1, this); JavaModelManager manager = JavaModelManager.getJavaModelManager(); boolean isClasspathBeingResolved = manager.isClasspathBeingResolved(this); try { if (!isClasspathBeingResolved) { manager.setClasspathBeingResolved(this, true); } // get raw info inside a synchronized block to ensure that it is consistent IClasspathEntry[][] classpath = new IClasspathEntry[2][]; int timeStamp; synchronized (perProjectInfo) { classpath[0] = perProjectInfo.rawClasspath; classpath[1] = perProjectInfo.referencedEntries; // Checking null only for rawClasspath enough if (classpath[0] == null) classpath = perProjectInfo.readAndCacheClasspath(this); timeStamp = perProjectInfo.rawTimeStamp; } ResolvedClasspath result = resolveClasspath(classpath[0], classpath[1], usePreviousSession, true/*resolve chained libraries*/); if (CP_RESOLUTION_BP_LISTENERS != null) breakpoint(2, this); // store resolved info along with the raw info to ensure consistency perProjectInfo.setResolvedClasspath(result.resolvedClasspath, result.referencedEntries, result.rawReverseMap, result.rootPathToResolvedEntries, usePreviousSession ? PerProjectInfo.NEED_RESOLUTION : result.unresolvedEntryStatus, timeStamp, addClasspathChange); } finally { if (!isClasspathBeingResolved) { manager.setClasspathBeingResolved(this, false); } if (CP_RESOLUTION_BP_LISTENERS != null) breakpoint(3, this); } }
Answers an ID which is used to distinguish project/entries during package fragment root computations
Returns:String
/** * Answers an ID which is used to distinguish project/entries during package * fragment root computations * @return String */
public String rootID(){ return "[PRJ]"+this.project.getFullPath(); //$NON-NLS-1$ }
Writes the classpath in a sharable format (VCM-wise) only when necessary, that is, if it is semantically different from the existing one in file. Will never write an identical one.
Params:
  • newClasspath – IClasspathEntry[]
  • newOutputLocation – IPath
Throws:
Returns:boolean Return whether the .classpath file was modified.
/** * Writes the classpath in a sharable format (VCM-wise) only when necessary, that is, if it is semantically different * from the existing one in file. Will never write an identical one. * * @param newClasspath IClasspathEntry[] * @param newOutputLocation IPath * @return boolean Return whether the .classpath file was modified. * @throws JavaModelException */
public boolean writeFileEntries(IClasspathEntry[] newClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation) throws JavaModelException { if (!this.project.isAccessible()) return false; Map unknownElements = new HashMap(); IClasspathEntry[][] fileEntries = readFileEntries(unknownElements); if (fileEntries[0] != JavaProject.INVALID_CLASSPATH && areClasspathsEqual(newClasspath, newOutputLocation, fileEntries[0]) && (referencedEntries == null || areClasspathsEqual(referencedEntries, fileEntries[1])) ) { // no need to save it, it is the same return false; } // actual file saving try { setSharedProperty(JavaProject.CLASSPATH_FILENAME, encodeClasspath(newClasspath, referencedEntries, newOutputLocation, true, unknownElements)); return true; } catch (CoreException e) { throw new JavaModelException(e); } } public boolean writeFileEntries(IClasspathEntry[] newClasspath, IPath newOutputLocation) throws JavaModelException { return writeFileEntries(newClasspath, ClasspathEntry.NO_ENTRIES, newOutputLocation); }
Update the Java command in the build spec (replace existing one if present, add one first if none).
/** * Update the Java command in the build spec (replace existing one if present, * add one first if none). */
private void setJavaCommand( IProjectDescription description, ICommand newCommand) throws CoreException { ICommand[] oldBuildSpec = description.getBuildSpec(); int oldJavaCommandIndex = getJavaCommandIndex(oldBuildSpec); ICommand[] newCommands; if (oldJavaCommandIndex == -1) { // Add a Java build spec before other builders (1FWJK7I) newCommands = new ICommand[oldBuildSpec.length + 1]; System.arraycopy(oldBuildSpec, 0, newCommands, 1, oldBuildSpec.length); newCommands[0] = newCommand; } else { oldBuildSpec[oldJavaCommandIndex] = newCommand; newCommands = oldBuildSpec; } // Commit the spec change into the project description.setBuildSpec(newCommands); this.project.setDescription(description, null); }
See Also:
  • setOption.setOption(String, String)
/** * @see org.eclipse.jdt.core.IJavaProject#setOption(java.lang.String, java.lang.String) */
@Override public void setOption(String optionName, String optionValue) { // Store option value IEclipsePreferences projectPreferences = getEclipsePreferences(); boolean modified = JavaModelManager.getJavaModelManager().storePreference(optionName, optionValue, projectPreferences, null); // Write changes if (modified) { try { projectPreferences.flush(); } catch (BackingStoreException e) { // problem with pref store - quietly ignore } } }
See Also:
  • setOptions.setOptions(Map)
/** * @see org.eclipse.jdt.core.IJavaProject#setOptions(Map) */
@Override public void setOptions(Map<String, String> newOptions) { IEclipsePreferences projectPreferences = getEclipsePreferences(); if (projectPreferences == null) return; try { if (newOptions == null){ projectPreferences.clear(); } else { Iterator<Map.Entry<String, String>> entries = newOptions.entrySet().iterator(); JavaModelManager javaModelManager = JavaModelManager.getJavaModelManager(); while (entries.hasNext()){ Map.Entry<String, String> entry = entries.next(); String key = entry.getKey(); String value = entry.getValue(); javaModelManager.storePreference(key, value, projectPreferences, newOptions); } // reset to default all options not in new map // @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=26255 // @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49691 String[] pNames = projectPreferences.keys(); int ln = pNames.length; for (int i=0; i<ln; i++) { String key = pNames[i]; if (!newOptions.containsKey(key)) { projectPreferences.remove(key); // old preferences => remove from preferences table } } } // persist options projectPreferences.flush(); // flush cache immediately try { getPerProjectInfo().options = null; } catch (JavaModelException e) { // do nothing } } catch (BackingStoreException e) { // problem with pref store - quietly ignore } }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public void setOutputLocation(IPath path, IProgressMonitor monitor) throws JavaModelException { if (path == null) { throw new IllegalArgumentException(Messages.path_nullPath); } if (path.equals(getOutputLocation())) { return; } setRawClasspath(getRawClasspath(), path, monitor); }
Sets the underlying kernel project of this Java project, and fills in its parent and name. Called by IProject.getNature().
See Also:
  • setProject.setProject(IProject)
/** * Sets the underlying kernel project of this Java project, * and fills in its parent and name. * Called by IProject.getNature(). * * @see IProjectNature#setProject(IProject) */
@Override public void setProject(IProject project) { this.project = project; this.parent = JavaModelManager.getJavaModelManager().getJavaModel(); }
See Also:
  • setRawClasspath.setRawClasspath(IClasspathEntry[], boolean, IProgressMonitor)
/** * @see IJavaProject#setRawClasspath(IClasspathEntry[],boolean,IProgressMonitor) */
@Override public void setRawClasspath( IClasspathEntry[] entries, boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException { setRawClasspath( entries, getOutputLocation()/*don't change output*/, canModifyResources, monitor); }
See Also:
  • setRawClasspath.setRawClasspath(IClasspathEntry[], IPath, boolean, IProgressMonitor)
/** * @see IJavaProject#setRawClasspath(IClasspathEntry[],IPath,boolean,IProgressMonitor) */
@Override public void setRawClasspath( IClasspathEntry[] newRawClasspath, IPath newOutputLocation, boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException { setRawClasspath(newRawClasspath, null, newOutputLocation, canModifyResources, monitor); }
See Also:
  • setRawClasspath.setRawClasspath(IClasspathEntry[], IPath, IProgressMonitor)
/** * @see IJavaProject#setRawClasspath(IClasspathEntry[],IPath,IProgressMonitor) */
@Override public void setRawClasspath( IClasspathEntry[] entries, IPath outputLocation, IProgressMonitor monitor) throws JavaModelException { setRawClasspath( entries, outputLocation, true/*can change resource (as per API contract)*/, monitor); } @Override public void setRawClasspath(IClasspathEntry[] entries, IClasspathEntry[] referencedEntries, IPath outputLocation, IProgressMonitor monitor) throws JavaModelException { setRawClasspath(entries, referencedEntries, outputLocation, true, monitor); } protected void setRawClasspath(IClasspathEntry[] newRawClasspath, IClasspathEntry[] referencedEntries, IPath newOutputLocation, boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException { try { if (newRawClasspath == null) //are we already with the default classpath newRawClasspath = defaultClasspath(); SetClasspathOperation op = new SetClasspathOperation( this, newRawClasspath, referencedEntries, newOutputLocation, canModifyResources); op.runOperation(monitor); } catch (JavaModelException e) { JavaModelManager.getJavaModelManager().getDeltaProcessor().flush(); throw e; } }
See Also:
  • IJavaProject
/** * @see IJavaProject */
@Override public void setRawClasspath( IClasspathEntry[] entries, IProgressMonitor monitor) throws JavaModelException { setRawClasspath( entries, getOutputLocation()/*don't change output*/, true/*can change resource (as per API contract)*/, monitor); }
Record a shared persistent property onto a project. Note that it is orthogonal to IResource persistent properties, and client code has to decide which form of storage to use appropriately. Shared properties produce real resource files which can be shared through a VCM onto a server. Persistent properties are not shareable.

Shared properties end up in resource files, and thus cannot be modified during delta notifications (a CoreException would then be thrown).

Params:
  • key – String
  • value – String
Throws:
See Also:
/** * Record a shared persistent property onto a project. * Note that it is orthogonal to IResource persistent properties, and client code has to decide * which form of storage to use appropriately. Shared properties produce real resource files which * can be shared through a VCM onto a server. Persistent properties are not shareable. * <p> * Shared properties end up in resource files, and thus cannot be modified during * delta notifications (a CoreException would then be thrown). * * @param key String * @param value String * @see JavaProject#getSharedProperty(String key) * @throws CoreException */
public void setSharedProperty(String key, String value) throws CoreException { IFile rscFile = this.project.getFile(key); byte[] bytes = null; try { bytes = value.getBytes(org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8 } catch (UnsupportedEncodingException e) { Util.log(e, "Could not write .classpath with UTF-8 encoding "); //$NON-NLS-1$ // fallback to default bytes = value.getBytes(); } InputStream inputStream = new ByteArrayInputStream(bytes); // update the resource content if (rscFile.exists()) { if (rscFile.isReadOnly()) { // provide opportunity to checkout read-only .classpath file (23984) ResourcesPlugin.getWorkspace().validateEdit(new IFile[]{rscFile}, IWorkspace.VALIDATE_PROMPT); } rscFile.setContents(inputStream, IResource.FORCE, null); } else { rscFile.create(inputStream, IResource.FORCE, null); } }
internal structure for detected build path cycles.
/** internal structure for detected build path cycles. */
static class CycleInfo { private List<IPath> pathToCycle; public final List<IPath> cycle; public CycleInfo(List<IPath> pathToCycle, List<IPath> cycle) { this.pathToCycle = new ArrayList<>(pathToCycle); this.cycle = new ArrayList<>(cycle); } public static Optional<CycleInfo> findCycleContaining(Collection<List<CycleInfo>> infos, IPath path) { return infos.stream().flatMap(l -> l.stream()).filter(c -> c.cycle.contains(path)).findAny(); } public static void add(IPath project, List<IPath> prefix, List<IPath> cycle, Map<IPath, List<CycleInfo>> cyclesPerProject) { List<CycleInfo> list = cyclesPerProject.get(project); if (list == null) { cyclesPerProject.put(project, list = new ArrayList<>()); } else { for (CycleInfo cycleInfo: list) { if (cycleInfo.cycle.equals(cycle)) { // same cycle: use the shorter prefix: if (cycleInfo.pathToCycle.size() > prefix.size()) { cycleInfo.pathToCycle.clear(); cycleInfo.pathToCycle.addAll(prefix); } return; } } } list.add(new CycleInfo(prefix, cycle)); } public String pathToCycleAsString() { return this.pathToCycle.stream().map(IPath::lastSegment).collect(Collectors.joining(", ")); //$NON-NLS-1$ } public String cycleAsString() { return this.cycle.stream().map(IPath::lastSegment).collect(Collectors.joining(", ")); //$NON-NLS-1$ } }
If a cycle is detected, then cycleParticipants contains all the paths of projects involved in this cycle (directly and indirectly), no cycle if the set is empty (and started empty)
Params:
  • prereqChain – ArrayList
  • cycleParticipants – HashSet
  • workspaceRoot – IWorkspaceRoot
  • traversed – HashSet
  • preferredClasspaths – Map
/** * If a cycle is detected, then cycleParticipants contains all the paths of projects involved in this cycle (directly and indirectly), * no cycle if the set is empty (and started empty) * @param prereqChain ArrayList * @param cycleParticipants HashSet * @param workspaceRoot IWorkspaceRoot * @param traversed HashSet * @param preferredClasspaths Map */
public void updateCycleParticipants( List<IPath> prereqChain, LinkedHashSet cycleParticipants, Map<IPath,List<CycleInfo>> cyclesPerProject, IWorkspaceRoot workspaceRoot, HashSet traversed, Map preferredClasspaths){ IPath path = getPath(); prereqChain.add(path); traversed.add(path); try { IClasspathEntry[] classpath = null; if (preferredClasspaths != null) classpath = (IClasspathEntry[])preferredClasspaths.get(this); if (classpath == null) classpath = getResolvedClasspath(); for (int i = 0, length = classpath.length; i < length; i++) { IClasspathEntry entry = classpath[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT){ IPath prereqProjectPath = entry.getPath(); int prereqIndex = prereqChain.indexOf(prereqProjectPath); if (prereqIndex > -1) { // record a new cycle: List<IPath> cycle = prereqChain.subList(prereqIndex, prereqChain.size()); // empty-prefix CycleInfo for all members of the cycle: List<IPath> prefix = Collections.emptyList(); for (IPath prjInCycle : cycle) { CycleInfo.add(prjInCycle, prefix, cycle, cyclesPerProject); } // also record with all members of the prereqChain with transitive dependency on the cycle: for (int j = 0; j < prereqIndex; j++) { CycleInfo.add(prereqChain.get(j), prereqChain.subList(j, prereqIndex), cycle, cyclesPerProject); } } else if (cycleParticipants.contains(prereqProjectPath)) { // record existing cycle as dependency of each project in prereqChain: Optional<CycleInfo> cycle = CycleInfo.findCycleContaining(cyclesPerProject.values(), prereqProjectPath); if (cycle.isPresent()) { List<IPath> theCycle = cycle.get().cycle; for (int j = 0; j < prereqChain.size(); j++) { IPath prereq = prereqChain.get(j); List<IPath> prereqSubList = prereqChain.subList(j, prereqChain.size()); int joinIndex1 = theCycle.indexOf(prereq); if (joinIndex1 != -1) { // prereqSubList -> prereqProjectPath + theCycle create a new cycle List<IPath> newCycle = new ArrayList<>(prereqSubList); int joinIndex2 = theCycle.indexOf(prereqProjectPath); // always != -1 since that's how we found 'cycle' while (joinIndex2 != joinIndex1) { newCycle.add(theCycle.get(joinIndex2++)); if (joinIndex2 == theCycle.size()) joinIndex2 = 0; // it's a cycle :) } for (IPath newMember : newCycle) { CycleInfo.add(newMember, Collections.emptyList(), newCycle, cyclesPerProject); } break; // the rest of prereqChain is already included via newCycle } else { CycleInfo.add(prereq, prereqSubList, theCycle, cyclesPerProject); } } } prereqIndex = 0; } else { if (!traversed.contains(prereqProjectPath)) { IResource member = workspaceRoot.findMember(prereqProjectPath); if (member != null && member.getType() == IResource.PROJECT){ JavaProject javaProject = (JavaProject)JavaCore.create((IProject)member); javaProject.updateCycleParticipants(prereqChain, cycleParticipants, cyclesPerProject, workspaceRoot, traversed, preferredClasspaths); } } continue; } // fall through from both positive branches above for (int index = prereqIndex, size = prereqChain.size(); index < size; index++) { cycleParticipants.add(prereqChain.get(index)); } } } } catch(JavaModelException e){ // project doesn't exist: ignore } prereqChain.remove(path); } /* * Update eclipse preferences from old preferences. */ private void updatePreferences(IEclipsePreferences preferences) { IEclipsePreferences oldPreferences = loadPreferences(); if (oldPreferences != null) { try { String[] propertyNames = oldPreferences.childrenNames(); for (int i = 0; i < propertyNames.length; i++){ String propertyName = propertyNames[i]; String propertyValue = oldPreferences.get(propertyName, ""); //$NON-NLS-1$ if (!"".equals(propertyValue)) { //$NON-NLS-1$ preferences.put(propertyName, propertyValue); } } // save immediately new preferences preferences.flush(); } catch (BackingStoreException e) { // fails silently } } } @Override protected IStatus validateExistence(IResource underlyingResource) { // check whether the java project can be opened try { if (!((IProject) underlyingResource).hasNature(JavaCore.NATURE_ID)) return newDoesNotExistStatus(); } catch (CoreException e) { return newDoesNotExistStatus(); } return JavaModelStatus.VERIFIED_OK; } @Override public IModuleDescription getModuleDescription() throws JavaModelException { JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo(); IModuleDescription module = info.getModule(); if (module != null) return module; for(IClasspathEntry entry : getRawClasspath()) { List<String> patchedModules = getPatchedModules(entry); if (patchedModules.size() == 1) { // > 1 is malformed, 0 means not affecting this project String mainModule = patchedModules.get(0); switch (entry.getEntryKind()) { case IClasspathEntry.CPE_PROJECT: IJavaProject referencedProject = getJavaModel().getJavaProject(entry.getPath().toString()); module = referencedProject.getModuleDescription(); if (module != null && module.getElementName().equals(mainModule)) return module; break; case IClasspathEntry.CPE_LIBRARY: case IClasspathEntry.CPE_CONTAINER: for (IPackageFragmentRoot root : findPackageFragmentRoots(entry)) { module = root.getModuleDescription(); if (module != null && module.getElementName().equals(mainModule)) return module; } } } } return null; } @Override public IModuleDescription getOwnModuleDescription() throws JavaModelException { JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo(); return info.getModule(); } public List<String> getPatchedModules(IClasspathEntry cpEntry) { String patchModules = ClasspathEntry.getExtraAttribute(cpEntry, IClasspathAttribute.PATCH_MODULE); if (patchModules != null) { List<String> result = new ArrayList<>(); IPath prjPath = getPath(); for (String patchModule : patchModules.split("::")) { //$NON-NLS-1$ int equalsIdx = patchModule.indexOf('='); if (equalsIdx != -1) { if (equalsIdx < patchModule.length()-1) { // otherwise malformed? String locations = patchModule.substring(equalsIdx + 1); for (String location : locations.split(File.pathSeparator)) { if (prjPath.isPrefixOf(new Path(location))) { result.add(patchModule.substring(0, equalsIdx)); break; } } } } else { result.add(patchModule); // old format not specifying a location } } return result; } return Collections.emptyList(); } public IModuleDescription getAutomaticModuleDescription() throws JavaModelException { boolean nameFromManifest = true; char[] moduleName = AutomaticModuleNaming.determineAutomaticModuleNameFromManifest(getManifest()); if (moduleName == null) { nameFromManifest = false; moduleName = AutomaticModuleNaming.determineAutomaticModuleNameFromFileName(getElementName(), true, false); } return new AbstractModule.AutoModule(this, String.valueOf(moduleName), nameFromManifest); } public void setModuleDescription(IModuleDescription module) throws JavaModelException { JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo(); IModuleDescription current = info.getModule(); if (current != null) { IPackageFragmentRoot root = (IPackageFragmentRoot) current.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); IPackageFragmentRoot newRoot = (IPackageFragmentRoot) module.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); if (!root.equals(newRoot)) throw new JavaModelException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Messages.bind(Messages.classpath_duplicateEntryPath, TypeConstants.MODULE_INFO_FILE_NAME_STRING, getElementName()))); } info.setModule(module); } private boolean isUnNamedModule() throws JavaModelException { JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo(); IModuleDescription module = info.getModule(); if (module != null) return false; for(IClasspathEntry entry : getRawClasspath()) { if (!getPatchedModules(entry).isEmpty()) return false; } return true; } public Manifest getManifest() { IFile file = getProject().getFile(new Path(TypeConstants.META_INF_MANIFEST_MF)); if (file.exists()) { try (InputStream contents = file.getContents()) { return new Manifest(contents); } catch (IOException | CoreException e) { // unusable manifest } } return null; } @Override public Set<String> determineModulesOfProjectsWithNonEmptyClasspath() throws JavaModelException { return ModuleUpdater.determineModulesOfProjectsWithNonEmptyClasspath(this, getExpandedClasspath()); } }