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;
@SuppressWarnings({ "rawtypes", "unchecked" })
public class JavaProject
extends Openable
implements IJavaProject, IProjectNature, SuffixConstants {
public static final String CLASSPATH_FILENAME = IJavaProject.CLASSPATH_FILE_NAME;
public static final IClasspathEntry[] INVALID_CLASSPATH = new IClasspathEntry[0];
protected static final boolean IS_CASE_SENSITIVE = !new File("Temp").equals(new File("temp"));
protected static final String[] NO_PREREQUISITES = CharOperation.NO_STRINGS;
private static final String PREF_FILENAME = ".jprefs";
public static final String DEFAULT_PREFERENCES_DIRNAME = ".settings";
public static final String JAVA_CORE_PREFS_FILE = JavaCore.PLUGIN_ID+".prefs";
private static final IClasspathEntry[] RESOLUTION_IN_PROGRESS = new IClasspathEntry[0];
private static ArrayList CP_RESOLUTION_BP_LISTENERS;
public static class ClasspathResolutionBreakpointListener {
public void breakpoint(int bp) {
}
}
protected IProject project;
private IEclipsePreferences.INodeChangeListener preferencesNodeListener;
private IEclipsePreferences.IPreferenceChangeListener preferencesChangeListener;
public JavaProject() {
super(null);
}
public JavaProject(IProject project, JavaElement parent) {
super(parent);
this.project = project;
}
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);
}
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);
}
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)
return false;
for (int i = 0; i < length - 1; i++) {
if (!otherClasspathWithOutput[i].equals(newClasspath[i]))
return false;
}
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;
}
public static IPath canonicalizedPath(IPath externalPath) {
if (externalPath == null)
return null;
if (IS_CASE_SENSITIVE) {
return externalPath;
}
IWorkspace workspace = ResourcesPlugin.getWorkspace();
if (workspace == null) return externalPath;
if (workspace.getRoot().findMember(externalPath) != null) {
return externalPath;
}
IPath canonicalPath = null;
try {
canonicalPath =
new Path(new File(externalPath.toOSString()).getCanonicalPath());
} catch (IOException e) {
return externalPath;
}
IPath result;
int canonicalLength = canonicalPath.segmentCount();
if (canonicalLength == 0) {
return externalPath;
} else if (externalPath.isAbsolute()) {
result = canonicalPath;
} else {
int externalLength = externalPath.segmentCount();
if (canonicalLength >= externalLength) {
result = canonicalPath.removeFirstSegments(canonicalLength - externalLength);
} else {
return externalPath;
}
}
if (externalPath.getDevice() == null) {
result = result.setDevice(null);
}
if (externalPath.hasTrailingSeparator()) {
result = result.addTrailingSeparator();
}
return result;
}
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;
}
return false;
}
public static void validateCycles(Map preferredClasspaths) throws JavaModelException {
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();
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);
}
}
}
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("->{");
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) {
try {
int existingSeverity = ((Integer)cycleMarker.getAttribute(IMarker.SEVERITY)).intValue();
if (existingSeverity != circularCPSeverity) {
cycleMarker.setAttribute(IMarker.SEVERITY, circularCPSeverity);
}
String existingMessage = cycleMarker.getAttribute(IMarker.MESSAGE, "");
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 {
project.createClasspathProblemMarker(
new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE, project, cycleString.toString()));
}
} else {
project.flushClasspathProblemMarkers(true, false, false);
}
}
}
}
protected void addToBuildSpec(String builderID) throws CoreException {
IProjectDescription description = this.project.getDescription();
int javaCommandIndex = getJavaCommandIndex(description.getBuildSpec());
if (javaCommandIndex == -1) {
ICommand command = description.newCommand();
command.setBuilderName(builderID);
setJavaCommand(description, command);
}
}
@Override
protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
IClasspathEntry[] resolvedClasspath = getResolvedClasspath();
IPackageFragmentRoot[] roots = computePackageFragmentRoots(resolvedClasspath, false, true, null );
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);
info.setModule(module);
}
}
return true;
}
@Override
public void close() throws JavaModelException {
if (JavaProject.hasJavaNature(this.project)) {
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();
}
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();
if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
boolean nestedWithoutTestCode = excludeTestCode || entry.isWithoutTestCode();
Boolean previousValue = rootIDs.get(rootID);
ClasspathEntry combinedEntry;
if (previousValue == Boolean.FALSE) {
continue;
} else if (previousValue == Boolean.TRUE) {
if (nestedWithoutTestCode) {
continue;
} else {
rootIDs.put(rootID, Boolean.FALSE);
for (int j = 0; j < accumulatedEntries.size(); j++) {
ClasspathEntry oldEntry = accumulatedEntries.get(j);
if (oldEntry.rootID().equals(rootID)) {
accumulatedEntries.set(j, oldEntry.withExtraAttributeRemoved(IClasspathAttribute.WITHOUT_TEST_CODE));
break;
}
}
combinedEntry = entry.combineWith(referringEntry);
}
} else {
rootIDs.put(rootID, nestedWithoutTestCode);
combinedEntry = entry.combineWith(referringEntry);
accumulatedEntries.add(combinedEntry);
}
IResource member = workspaceRoot.findMember(entry.getPath());
if (member != null && member.getType() == IResource.PROJECT){
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)) {
ClasspathEntry combinedEntry = entry.combineWith(referringEntry);
accumulatedEntries.add(combinedEntry);
rootIDs.put(rootID, excludeTestCode);
}
}
}
}
}
public IPackageFragmentRoot[] computePackageFragmentRoots(IClasspathEntry resolvedEntry) {
try {
return
computePackageFragmentRoots(
new IClasspathEntry[]{ resolvedEntry },
false,
true,
null
);
} 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);
}
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);
}
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()){
case IClasspathEntry.CPE_SOURCE :
if (projectPath.isPrefixOf(entryPath)){
Object target = JavaModel.getTarget(entryPath, true);
if (target == null) return;
if (target instanceof IFolder || target instanceof IProject){
root = getPackageFragmentRoot((IResource)target);
}
}
break;
case IClasspathEntry.CPE_LIBRARY :
if (referringEntry != null && !resolvedEntry.isExported())
return;
Object target = JavaModel.getTarget(entryPath, true);
if (target == null)
return;
if (target instanceof IResource){
root = getPackageFragmentRoot((IResource) target, entryPath, resolvedEntry.getExtraAttributes());
} else if (target instanceof File) {
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);
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(","));
} 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;
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){
IProject requiredProjectRsc = (IProject) member;
if (JavaProject.hasJavaNature(requiredProjectRsc)){
rootIDs.add(rootID);
JavaProject requiredProject = (JavaProject)JavaCore.create(requiredProjectRsc);
requiredProject.computePackageFragmentRoots(
requiredProject.getResolvedClasspath(),
accumulatedRoots,
rootIDs,
rootToResolvedEntries == null ? resolvedEntry : ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry),
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));
}
}
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)) {
result.add(moduleName);
hasJavaDotSE = true;
break;
}
}
for (T mod : allSystemModules) {
String moduleName = getModuleName.apply(mod);
boolean isJavaDotStart = moduleName.startsWith("java.");
boolean isPotentialRoot = !isJavaDotStart;
if (!hasJavaDotSE)
isPotentialRoot |= isJavaDotStart;
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());
for (int i = 0; i < imageRoots.size(); i++) {
lookup.recordRoot((JrtPackageFragmentRoot) imageRoots.elementAt(i));
}
for (int i = 0; i < imageRoots.size(); i++) {
String moduleName = ((JrtPackageFragmentRoot) imageRoots.elementAt(i)).moduleName;
if (limitModulesSet.contains(moduleName))
lookup.addTransitive(moduleName);
}
ObjectVector result = new ObjectVector(lookup.resultModuleSet.size());
for (IModule mod : lookup.resultModuleSet) {
result.add(lookup.getRoot(mod));
}
return result;
}
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));
}
}
}
return result;
}
JrtPackageFragmentRoot getRoot(IModule module) {
return this.modNames2Roots.get(String.valueOf(module.name()));
}
}
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 {
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());
}
}
@Override
public IPackageFragmentRoot[] findUnfilteredPackageFragmentRoots(IClasspathEntry entry) {
try {
IClasspathEntry[] resolvedEntries = resolveClasspath(new IClasspathEntry[]{ entry });
return computePackageFragmentRoots(resolvedEntries, false , false , null );
} catch (JavaModelException e) {
return new IPackageFragmentRoot[] {};
}
}
public IPackageFragmentRoot[] computePackageFragmentRoots(
IClasspathEntry[] resolvedClasspath,
boolean retrieveExportedRoots,
boolean filterModuleRoots,
Map rootToResolvedEntries) throws JavaModelException {
return computePackageFragmentRoots(resolvedClasspath, retrieveExportedRoots, filterModuleRoots, rootToResolvedEntries, false);
}
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),
null,
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);
}
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);
}
}
public String computeSharedPropertyFileName(QualifiedName qName) {
return '.' + qName.getLocalName();
}
@Override
public void configure() throws CoreException {
addToBuildSpec(JavaCore.BUILDER_ID);
}
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) {
if (innerMostOutput != null && innerMostOutput.segmentCount() > 1
&& innerMostEntry.getPath().segmentCount() == 1) {
return false;
}
if (resource instanceof IFolder) {
return true;
}
switch (innerMostEntry.getEntryKind()) {
case IClasspathEntry.CPE_SOURCE:
return !org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(fullPath.lastSegment());
case IClasspathEntry.CPE_LIBRARY:
return !org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(fullPath.lastSegment());
}
}
if (innerMostOutput != null) {
return false;
}
return true;
}
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;
}
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;
}
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;
}
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",
isClasspathFileFormatProblem ? "true" : "false",
isOutputOverlapping ? "true" : "false",
Integer.valueOf(status.getCode()),
Util.getProblemArgumentsForMarker(arguments) ,
Integer.valueOf(CategorizedProblem.CAT_BUILDPATH),
JavaBuilder.SOURCE_ID,
}
);
} catch (CoreException e) {
if (JavaModelManager.VERBOSE) {
e.printStackTrace();
}
}
}
@Override
protected Object createElementInfo() {
return new JavaProjectElementInfo();
}
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")) {
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;
} 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;
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);
} catch (IOException e) {
return null;
}
}
@Override
public void deconfigure() throws CoreException {
removeFromBuildSpec(JavaCore.BUILDER_ID);
}
protected IClasspathEntry[] defaultClasspath() {
return new IClasspathEntry[] {
JavaCore.newSourceEntry(this.project.getFullPath())};
}
protected IPath defaultOutputLocation() {
return this.project.getFullPath().append("bin");
}
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");
XMLWriter xmlWriter = new XMLWriter(writer, this, true);
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);
writer.flush();
writer.close();
return s.toString("UTF8");
} 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");
XMLWriter xmlWriter = new XMLWriter(writer, this, false);
((ClasspathEntry)classpathEntry).elementEncode(xmlWriter, this.project.getFullPath(), true, true, null, (classpathEntry.getReferencingEntry() != null));
writer.flush();
writer.close();
return s.toString("UTF8");
} catch (IOException e) {
return null;
}
}
@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());
}
@Override
public IJavaElement findElement(IPath path) throws JavaModelException {
return findElement(path, DefaultWorkingCopyOwner.PRIMARY);
}
@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;
} else {
qualifiedName = typeName;
}
NameLookup lookup = newNameLookup(owner);
NameLookup.Answer answer = lookup.findType(
qualifiedName,
false,
NameLookup.ACCEPT_ALL,
true,
false,
false,
null);
if (answer != null) {
return answer.type.getParent();
} else {
return null;
}
} else {
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);
IPackageFragment[] pkgFragments = lookup.findPackageFragments(packageName, false);
if (pkgFragments == null) {
return null;
} else {
for (int i = 0, length = pkgFragments.length; i < length; i++) {
IPackageFragment pkgFragment = pkgFragments[i];
if (equals(pkgFragment.getParent().getParent())) {
return pkgFragment;
}
}
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;
}
@Override
public IPackageFragment findPackageFragment(IPath path)
throws JavaModelException {
return findPackageFragment0(JavaProject.canonicalizedPath(path));
}
private IPackageFragment findPackageFragment0(IPath path)
throws JavaModelException {
NameLookup lookup = newNameLookup((WorkingCopyOwner)null);
return lookup.findPackageFragment(path);
}
@Override
public IPackageFragmentRoot findPackageFragmentRoot(IPath path)
throws JavaModelException {
return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path));
}
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;
}
@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)) {
return
computePackageFragmentRoots(
resolveClasspath(new IClasspathEntry[] {entry}),
false,
true,
null);
}
}
} catch (JavaModelException e) {
}
return new IPackageFragmentRoot[] {};
}
@Override
public IType findType(String fullyQualifiedName) throws JavaModelException {
return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
}
@Override
public IType findType(String fullyQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException {
return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY, progressMonitor);
}
IType findType(String fullyQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException {
NameLookup.Answer answer = lookup.findType(
fullyQualifiedName,
false,
NameLookup.ACCEPT_ALL,
considerSecondaryTypes,
true,
false,
progressMonitor);
if (answer == null) {
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;
}
@Override
public IType findType(String packageName, String typeQualifiedName) throws JavaModelException {
return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
}
@Override
public IType findType(String packageName, String typeQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException {
return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY, progressMonitor);
}
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,
false,
progressMonitor);
return answer == null ? null : answer.type;
}
@Override
public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
NameLookup lookup = newNameLookup(owner);
return findType(
packageName,
typeQualifiedName,
lookup,
false,
null);
}
@Override
public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException {
NameLookup lookup = newNameLookup(owner);
return findType(
packageName,
typeQualifiedName,
lookup,
true,
progressMonitor);
}
@Override
public IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
NameLookup lookup = newNameLookup(owner);
return findType(fullyQualifiedName, lookup, false, null);
}
@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);
}
IModuleDescription findModule(String moduleName, NameLookup lookup) throws JavaModelException {
NameLookup.Answer answer = lookup.findModule(moduleName.toCharArray());
if (answer != null)
return answer.module;
return null;
}
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")))
&& (flushOverlappingOutputMarkers == (overlappingOutputAttr != null && overlappingOutputAttr.equals("true")))
&& (flushClasspathFormatMarkers == (classpathFileFormatAttr != null && classpathFileFormatAttr.equals("true")))){
marker.delete();
}
}
}
}
} catch (CoreException e) {
if (JavaModelManager.VERBOSE) {
e.printStackTrace();
}
}
}
public IPath[] getAccessRestrictions(String optionName) {
String sequence = getOption(optionName, true);
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;
}
@Override
public IPackageFragmentRoot[] getAllPackageFragmentRoots()
throws JavaModelException {
return getAllPackageFragmentRoots(null , 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, true, rootToResolvedEntries, excludeTestCode);
}
@Override
public IClasspathEntry getClasspathEntryFor(IPath path) throws JavaModelException {
getResolvedClasspath();
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;
}
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")){
return marker;
}
}
}
} catch (CoreException e) {
}
return null;
}
public IEclipsePreferences getEclipsePreferences() {
if (!JavaProject.hasJavaNature(this.project)) return null;
JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, true);
if (perProjectInfo.preferences != null) return perProjectInfo.preferences;
IScopeContext context = new ProjectScope(getProject());
final IEclipsePreferences eclipsePreferences = context.getNode(JavaCore.PLUGIN_ID);
updatePreferences(eclipsePreferences);
perProjectInfo.preferences = eclipsePreferences;
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) {
}
@Override
public void removed(IEclipsePreferences.NodeChangeEvent event) {
if (event.getChild() == eclipsePreferences) {
JavaModelManager.getJavaModelManager().resetProjectPreferences(JavaProject.this);
}
}
};
eclipseParentPreferences.addNodeChangeListener(this.preferencesNodeListener);
}
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();
}
}
};
eclipsePreferences.addPreferenceChangeListener(this.preferencesChangeListener);
return eclipsePreferences;
}
@Override
public String getElementName() {
return this.project.getName();
}
@Override
public int getElementType() {
return JAVA_PROJECT;
}
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;
}
public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) {
if (path.segmentCount() == 1) {
return getPackageFragmentRoot(this.project);
}
return getPackageFragmentRoot(this.project.getWorkspace().getRoot().getFolder(path));
}
@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();
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) {
String name = memento.getStringDelimitedBy(MementoTokenizer.CLASSPATH_ATTRIBUTE);
String value = memento.getStringDelimitedBy(MementoTokenizer.CLASSPATH_ATTRIBUTE);
attributes.add(new ClasspathAttribute(name, value));
token = null;
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;
}
@Override
protected char getHandleMementoDelimiter() {
return JEM_JAVAPROJECT;
}
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;
}
protected JavaProjectElementInfo getJavaProjectElementInfo()
throws JavaModelException {
return (JavaProjectElementInfo) getElementInfo();
}
@Override
public Object[] getNonJavaResources() throws JavaModelException {
return ((JavaProjectElementInfo) getElementInfo()).getNonJavaResources(this);
}
@Override
public String getOption(String optionName, boolean inheritJavaCoreOptions) {
return JavaModelManager.getJavaModelManager().getOption(optionName, inheritJavaCoreOptions, getEclipsePreferences());
}
@Override
public Map<String, String> getOptions(boolean inheritJavaCoreOptions) {
Map<String, String> options = inheritJavaCoreOptions ? JavaCore.getOptions() : new Hashtable<String, String>(5);
JavaModelManager.PerProjectInfo perProjectInfo = null;
Hashtable projectOptions = null;
JavaModelManager javaModelManager = JavaModelManager.getJavaModelManager();
HashSet optionNames = javaModelManager.optionNames;
try {
perProjectInfo = getPerProjectInfo();
projectOptions = perProjectInfo.options;
if (projectOptions == null) {
IEclipsePreferences projectPreferences= getEclipsePreferences();
if (projectPreferences == null) return 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();
projectOptions.put(propertyName, value);
if (!optionNames.contains(propertyName)) {
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);
}
}
}
}
}
perProjectInfo.options = projectOptions;
}
} catch (JavaModelException | BackingStoreException e) {
projectOptions = new Hashtable();
}
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;
}
@Override
public IPath getOutputLocation() throws JavaModelException {
JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo();
IPath outputLocation = perProjectInfo.outputLocation;
if (outputLocation != null) return outputLocation;
getRawClasspath();
outputLocation = perProjectInfo.outputLocation;
if (outputLocation == null) {
return defaultOutputLocation();
}
return outputLocation;
}
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) != null) {
return getPackageFragmentRoot0(path, extraAttributes);
}
IWorkspaceRoot workspaceRoot = this.project.getWorkspace().getRoot();
IResource resource = workspaceRoot.findMember(path);
if (resource == null) {
if (path.getFileExtension() != null) {
if (!workspaceRoot.getProject(path.segment(0)).exists()) {
return getPackageFragmentRoot0(path, extraAttributes);
} else {
resource = workspaceRoot.getFile(path);
}
} else if (segmentCount == 1) {
String projectName = path.segment(0);
if (getElementName().equals(projectName)) {
resource = this.project;
} else {
resource = workspaceRoot.getProject(projectName);
}
} else {
resource = workspaceRoot.getFolder(path);
}
}
return getPackageFragmentRoot(resource, null, extraAttributes);
}
@Override
public IPackageFragmentRoot getPackageFragmentRoot(IResource resource) {
return getPackageFragmentRoot(resource, null, null);
}
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;
}
}
@Override
public IPackageFragmentRoot getPackageFragmentRoot(String externalLibraryPath) {
return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new Path(externalLibraryPath)), null);
}
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);
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);
}
@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;
}
@Override
public IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry) {
return findPackageFragmentRoots(entry);
}
@Override
public IPackageFragment[] getPackageFragments() throws JavaModelException {
IPackageFragmentRoot[] roots = getPackageFragmentRoots();
return getPackageFragmentsInRoots(roots);
}
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) {
}
}
IPackageFragment[] fragments = new IPackageFragment[frags.size()];
frags.toArray(fragments);
return fragments;
}
@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);
}
@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);
}
@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;
}
@Override
public IClasspathEntry[] getReferencedClasspathEntries() throws JavaModelException {
return getPerProjectInfo().referencedEntries;
}
@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, true);
resolvedClasspath = perProjectInfo.getResolvedClasspath();
if (resolvedClasspath == null) {
PerProjectInfo temporaryInfo = newTemporaryInfo();
resolveClasspath(temporaryInfo, false, true);
resolvedClasspath = temporaryInfo.getResolvedClasspath();
}
}
return resolvedClasspath;
}
@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();
IClasspathEntry[] resolvedClasspath;
IJavaModelStatus unresolvedEntryStatus;
synchronized (perProjectInfo) {
resolvedClasspath = perProjectInfo.getResolvedClasspath();
unresolvedEntryStatus = perProjectInfo.unresolvedEntryStatus;
}
if (resolvedClasspath == null
|| (unresolvedEntryStatus != null && !unresolvedEntryStatus.isOK())) {
resolveClasspath(perProjectInfo, false, true);
synchronized (perProjectInfo) {
resolvedClasspath = perProjectInfo.getResolvedClasspath();
unresolvedEntryStatus = perProjectInfo.unresolvedEntryStatus;
}
if (resolvedClasspath == null) {
PerProjectInfo temporaryInfo = newTemporaryInfo();
resolveClasspath(temporaryInfo, false, true);
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" +
" project: " + getElementName() + '\n' +
" invocation stack trace:");
new Exception("<Fake exception>").printStackTrace(System.out);
}
@Override
public IResource resource(PackageFragmentRoot root) {
return this.project;
}
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);
} catch (UnsupportedEncodingException e) {
Util.log(e, "Could not read .classpath with UTF-8 encoding");
property = new String(bytes);
}
} else {
URI location = rscFile.getLocationURI();
if (location != null) {
File file = Util.toLocalFile(location, null);
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);
} catch (UnsupportedEncodingException e) {
Util.log(e, "Could not read .classpath with UTF-8 encoding");
property = new String(bytes);
}
}
}
}
return property;
}
@Override
public SourceMapper getSourceMapper() {
return null;
}
@Override
public IResource getUnderlyingResource() throws JavaModelException {
if (!exists()) throw newNotPresentException();
return this.project;
}
@Override
public boolean hasBuildState() {
return JavaModelManager.getJavaModelManager().getLastBuiltState(this.project, null) != null;
}
@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;
}
public boolean hasSource() {
IClasspathEntry[] entries;
try {
entries = getRawClasspath();
} catch (JavaModelException e) {
return true;
}
for (int i = 0, max = entries.length; i < max; i++) {
if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
return true;
}
}
return false;
}
@Override
public boolean isOnClasspath(IJavaElement element) {
IClasspathEntry[] rawClasspath;
try {
rawClasspath = getRawClasspath();
} catch(JavaModelException e){
return false;
}
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();
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;
}
}
if (isSource)
return false;
IClasspathEntry[] resolvedClasspath = null;
try {
resolvedClasspath = getResolvedClasspath();
} catch (JavaModelException e) {
return false;
}
for (int index = 0; index < resolvedClasspath.length; index++) {
if (isOnClasspathEntry(elementPath, isFolderPath, isPackageFragmentRoot, resolvedClasspath[index]))
return true;
}
return false;
}
@Override
public boolean isOnClasspath(IResource resource) {
IPath exactPath = resource.getFullPath();
IPath path = exactPath;
int resourceType = resource.getType();
boolean isFolderPath = resourceType == IResource.FOLDER || resourceType == IResource.PROJECT;
IClasspathEntry[] classpath;
try {
classpath = this.getResolvedClasspath();
} catch(JavaModelException e){
return false;
}
for (int i = 0; i < classpath.length; i++) {
IClasspathEntry entry = classpath[i];
IPath entryPath = entry.getPath();
if (entryPath.equals(exactPath)) {
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) {
if (entryPath.equals(elementPath))
return true;
} else {
if (entryPath.isPrefixOf(elementPath)
&& !Util.isExcluded(elementPath, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), isFolderPath))
return true;
}
if (entryPath.isAbsolute()
&& entryPath.equals(ResourcesPlugin.getWorkspace().getRoot().getLocation().append(elementPath))) {
return true;
}
return false;
}
private IEclipsePreferences loadPreferences() {
IEclipsePreferences preferences = null;
IPath projectMetaLocation = getPluginWorkingLocation();
if (projectMetaLocation != null) {
File prefFile = projectMetaLocation.append(PREF_FILENAME).toFile();
if (prefFile.exists()) {
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(prefFile));
preferences = Platform.getPreferencesService().readPreferences(in);
} catch (CoreException | IOException e) {
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
prefFile.delete();
return preferences;
}
}
return null;
}
@Override
public IEvaluationContext newEvaluationContext() {
EvaluationContext context = new EvaluationContext();
context.setLineSeparator(Util.getLineSeparator(null, this));
return new EvaluationContextWrapper(context, this);
}
public NameLookup newNameLookup(ICompilationUnit[] workingCopies) throws JavaModelException {
return newNameLookup(workingCopies, false);
}
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);
}
public NameLookup newNameLookup(WorkingCopyOwner owner, boolean excludeTestCode) throws JavaModelException {
JavaModelManager manager = JavaModelManager.getJavaModelManager();
ICompilationUnit[] workingCopies = owner == null ? null : manager.getWorkingCopies(owner, true);
return newNameLookup(workingCopies);
}
public SearchableEnvironment newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws JavaModelException {
return newSearchableNameEnvironment(workingCopies, false);
}
public SearchableEnvironment newSearchableNameEnvironment(ICompilationUnit[] workingCopies, boolean excludeTestCode) throws JavaModelException {
return new SearchableEnvironment(this, workingCopies, excludeTestCode);
}
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);
}
public PerProjectInfo newTemporaryInfo() {
return
new PerProjectInfo(this.project.getProject()) {
@Override
protected ClasspathChange addClasspathChange() {
return null;
}
};
}
@Override
public ITypeHierarchy newTypeHierarchy(
IRegion region,
IProgressMonitor monitor)
throws JavaModelException {
return newTypeHierarchy(region, DefaultWorkingCopyOwner.PRIMARY, monitor);
}
@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);
CreateTypeHierarchyOperation op =
new CreateTypeHierarchyOperation(region, workingCopies, null, true);
op.runOperation(monitor);
return op.getResult();
}
@Override
public ITypeHierarchy newTypeHierarchy(
IType type,
IRegion region,
IProgressMonitor monitor)
throws JavaModelException {
return newTypeHierarchy(type, region, DefaultWorkingCopyOwner.PRIMARY, monitor);
}
@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);
CreateTypeHierarchyOperation op =
new CreateTypeHierarchyOperation(region, workingCopies, type, true);
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;
}
}
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 {
URI location = rscFile.getLocationURI();
if (location == null)
throw new IOException("Cannot obtain a location URI for " + rscFile);
File file = Util.toLocalFile(location, null);
if (file == null)
throw new IOException("Unable to fetch file from " + location);
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)) {
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);
} catch (UnsupportedEncodingException e) {
Util.log(e, "Could not read .classpath with UTF-8 encoding");
xmlClasspath = new String(bytes);
}
return decodeClasspath(xmlClasspath, unknownElements);
}
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));
return new IClasspathEntry[][]{JavaProject.INVALID_CLASSPATH, ClasspathEntry.NO_ENTRIES};
}
}
@Override
public IPath readOutputLocation() {
IClasspathEntry[][] classpath = readFileEntries(null);
if (classpath[0] == JavaProject.INVALID_CLASSPATH)
return defaultOutputLocation();
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;
}
@Override
public IClasspathEntry[] readRawClasspath() {
IClasspathEntry[][] classpath = readFileEntries(null);
if (classpath[0] == JavaProject.INVALID_CLASSPATH)
return defaultClasspath();
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];
}
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;
}
}
}
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) {
return null;
}
}
public IClasspathEntry[] resolveClasspath(IClasspathEntry[] rawClasspath) throws JavaModelException {
return resolveClasspath(rawClasspath, false, true).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) {
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) {
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 (resolveChainedLibraries && resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY
&& result.rawReverseMap.get(resolvedEntry.getPath()) == null) {
ClasspathEntry[] extraEntries = ((ClasspathEntry) resolvedEntry).resolvedChainedLibraries();
for (int j = 0, length2 = extraEntries.length; j < length2; j++) {
if (!rawLibrariesPath.contains(extraEntries[j].getPath())) {
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;
}
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;
}
cEntry = cEntry.combineWith((ClasspathEntry) rawEntry);
if (cEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
cEntry = cEntry.resolvedDotDot(getProject().getLocation());
if (resolveChainedLibraries
&& JavaModelManager.getJavaModelManager().resolveReferencedLibrariesForContainers
&& result.rawReverseMap.get(cEntry.getPath()) == null) {
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:
resolvedEntry = ((ClasspathEntry) rawEntry).resolvedDotDot(getProject().getLocation());
if (resolveChainedLibraries && result.rawReverseMap.get(resolvedEntry.getPath()) == null) {
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 (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) {
copyFromOldChainedEntry((ClasspathEntry) resolvedEntry, (ClasspathEntry) chainedEntry);
}
}
}
if (resolvedEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY && ExternalFoldersManager.isExternalFolderPath(resolvedPath)) {
externalFoldersManager.addFolder(resolvedPath, true);
}
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;
}
}
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();
}
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);
}
IClasspathEntry[][] classpath = new IClasspathEntry[2][];
int timeStamp;
synchronized (perProjectInfo) {
classpath[0] = perProjectInfo.rawClasspath;
classpath[1] = perProjectInfo.referencedEntries;
if (classpath[0] == null)
classpath = perProjectInfo.readAndCacheClasspath(this);
timeStamp = perProjectInfo.rawTimeStamp;
}
ResolvedClasspath result = resolveClasspath(classpath[0], classpath[1], usePreviousSession, true);
if (CP_RESOLUTION_BP_LISTENERS != null)
breakpoint(2, this);
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);
}
}
public String rootID(){
return "[PRJ]"+this.project.getFullPath();
}
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])) ) {
return false;
}
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);
}
private void setJavaCommand(
IProjectDescription description,
ICommand newCommand)
throws CoreException {
ICommand[] oldBuildSpec = description.getBuildSpec();
int oldJavaCommandIndex = getJavaCommandIndex(oldBuildSpec);
ICommand[] newCommands;
if (oldJavaCommandIndex == -1) {
newCommands = new ICommand[oldBuildSpec.length + 1];
System.arraycopy(oldBuildSpec, 0, newCommands, 1, oldBuildSpec.length);
newCommands[0] = newCommand;
} else {
oldBuildSpec[oldJavaCommandIndex] = newCommand;
newCommands = oldBuildSpec;
}
description.setBuildSpec(newCommands);
this.project.setDescription(description, null);
}
@Override
public void setOption(String optionName, String optionValue) {
IEclipsePreferences projectPreferences = getEclipsePreferences();
boolean modified = JavaModelManager.getJavaModelManager().storePreference(optionName, optionValue, projectPreferences, null);
if (modified) {
try {
projectPreferences.flush();
} catch (BackingStoreException e) {
}
}
}
@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);
}
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);
}
}
}
projectPreferences.flush();
try {
getPerProjectInfo().options = null;
} catch (JavaModelException e) {
}
} catch (BackingStoreException e) {
}
}
@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);
}
@Override
public void setProject(IProject project) {
this.project = project;
this.parent = JavaModelManager.getJavaModelManager().getJavaModel();
}
@Override
public void setRawClasspath(
IClasspathEntry[] entries,
boolean canModifyResources,
IProgressMonitor monitor)
throws JavaModelException {
setRawClasspath(
entries,
getOutputLocation(),
canModifyResources,
monitor);
}
@Override
public void setRawClasspath(
IClasspathEntry[] newRawClasspath,
IPath newOutputLocation,
boolean canModifyResources,
IProgressMonitor monitor)
throws JavaModelException {
setRawClasspath(newRawClasspath, null, newOutputLocation, canModifyResources, monitor);
}
@Override
public void setRawClasspath(
IClasspathEntry[] entries,
IPath outputLocation,
IProgressMonitor monitor)
throws JavaModelException {
setRawClasspath(
entries,
outputLocation,
true,
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)
newRawClasspath = defaultClasspath();
SetClasspathOperation op =
new SetClasspathOperation(
this,
newRawClasspath,
referencedEntries,
newOutputLocation,
canModifyResources);
op.runOperation(monitor);
} catch (JavaModelException e) {
JavaModelManager.getJavaModelManager().getDeltaProcessor().flush();
throw e;
}
}
@Override
public void setRawClasspath(
IClasspathEntry[] entries,
IProgressMonitor monitor)
throws JavaModelException {
setRawClasspath(
entries,
getOutputLocation(),
true,
monitor);
}
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);
} catch (UnsupportedEncodingException e) {
Util.log(e, "Could not write .classpath with UTF-8 encoding ");
bytes = value.getBytes();
}
InputStream inputStream = new ByteArrayInputStream(bytes);
if (rscFile.exists()) {
if (rscFile.isReadOnly()) {
ResourcesPlugin.getWorkspace().validateEdit(new IFile[]{rscFile}, IWorkspace.VALIDATE_PROMPT);
}
rscFile.setContents(inputStream, IResource.FORCE, null);
} else {
rscFile.create(inputStream, IResource.FORCE, null);
}
}
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)) {
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(", "));
}
public String cycleAsString() {
return this.cycle.stream().map(IPath::lastSegment).collect(Collectors.joining(", "));
}
}
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) {
List<IPath> cycle = prereqChain.subList(prereqIndex, prereqChain.size());
List<IPath> prefix = Collections.emptyList();
for (IPath prjInCycle : cycle) {
CycleInfo.add(prjInCycle, prefix, cycle, cyclesPerProject);
}
for (int j = 0; j < prereqIndex; j++) {
CycleInfo.add(prereqChain.get(j), prereqChain.subList(j, prereqIndex), cycle, cyclesPerProject);
}
} else if (cycleParticipants.contains(prereqProjectPath)) {
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) {
List<IPath> newCycle = new ArrayList<>(prereqSubList);
int joinIndex2 = theCycle.indexOf(prereqProjectPath);
while (joinIndex2 != joinIndex1) {
newCycle.add(theCycle.get(joinIndex2++));
if (joinIndex2 == theCycle.size())
joinIndex2 = 0;
}
for (IPath newMember : newCycle) {
CycleInfo.add(newMember, Collections.emptyList(), newCycle, cyclesPerProject);
}
break;
} 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;
}
for (int index = prereqIndex, size = prereqChain.size(); index < size; index++) {
cycleParticipants.add(prereqChain.get(index));
}
}
}
} catch(JavaModelException e){
}
prereqChain.remove(path);
}
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, "");
if (!"".equals(propertyValue)) {
preferences.put(propertyName, propertyValue);
}
}
preferences.flush();
} catch (BackingStoreException e) {
}
}
}
@Override
protected IStatus validateExistence(IResource underlyingResource) {
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) {
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("::")) {
int equalsIdx = patchModule.indexOf('=');
if (equalsIdx != -1) {
if (equalsIdx < patchModule.length()-1) {
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);
}
}
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) {
}
}
return null;
}
@Override
public Set<String> determineModulesOfProjectsWithNonEmptyClasspath() throws JavaModelException {
return ModuleUpdater.determineModulesOfProjectsWithNonEmptyClasspath(this, getExpandedClasspath());
}
}