/******************************************************************************* * Copyright (c) 2004, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.che.jdt.internal.core; import org.eclipse.che.api.project.server.Constants; import org.eclipse.che.api.project.server.ProjectJson; import org.eclipse.che.api.project.shared.Builders; import org.eclipse.che.ide.ant.tools.AntUtils; import org.eclipse.che.jdt.core.JavaCore; import org.eclipse.che.jdt.internal.core.search.indexing.IndexManager; import org.eclipse.che.jdt.internal.core.util.JavaElementFinder; import org.eclipse.che.ide.maven.tools.MavenUtils; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; 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.jobs.ISchedulingRule; import org.eclipse.jdt.core.IBuffer; 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.IJavaModel; import org.eclipse.jdt.core.IJavaModelStatus; import org.eclipse.jdt.core.IJavaProject; 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.JavaModelException; import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.core.eval.IEvaluationContext; import org.eclipse.jdt.internal.compiler.util.ObjectVector; import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner; import org.eclipse.jdt.internal.core.JavaModelStatus; import org.eclipse.jdt.internal.core.util.MementoTokenizer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * @author Evgen Vidolob */ public class JavaProject extends Openable implements IJavaProject { /** * Value of the project's raw classpath if the .classpath file contains invalid entries. */ public static final IClasspathEntry[] INVALID_CLASSPATH = new IClasspathEntry[0]; private static final Logger LOG = LoggerFactory.getLogger(JavaProject.class); private final DirectoryStream.Filter<java.nio.file.Path> jarFilter = new DirectoryStream.Filter<java.nio.file.Path>() { @Override public boolean accept(java.nio.file.Path entry) throws IOException { return entry.getFileName().toString().endsWith("jar"); } }; private final String workspacePath; private volatile SearchableEnvironment nameEnvironment; private String projectPath; private String tempDir; private String wsId; private String projectName; private File projectDir; private Map<String, String> options; private IClasspathEntry[] rawClassPath; private ResolvedClasspath resolvedClasspath; private IndexManager indexManager; public JavaProject(File root, String projectPath, String tempDir, String ws, Map<String, String> options) { super(null, new JavaModelManager()); manager.setJavaProject(this); this.projectPath = projectPath; this.tempDir = tempDir; wsId = ws; workspacePath = root.getPath(); int index = projectPath.lastIndexOf('/'); projectName = index < 0 ? projectPath : projectPath.substring(index + 1); this.projectDir = new File(root, projectPath); this.options = options; List<IClasspathEntry> paths = new LinkedList<>(); try { if (index <= 0) { // project in root folder addSources(projectDir, paths); } else { // module of project - add this module and all modules in parent projects index = projectPath.indexOf('/', 1); File parent = new File(root, projectPath.substring(1, index)); LinkedList<File> q = new LinkedList<>(); q.add(parent); while (!q.isEmpty()) { File f = q.poll(); addSources(f, paths); File[] l = f.listFiles(); for (File c : l) { if (c.isDirectory() && new File(c, Constants.CODENVY_PROJECT_FILE_RELATIVE_PATH).exists()) { q.add(c); } } } } } catch (IOException e) { LOG.error("Can't find sources folder attribute", e); } paths.add(JavaCore.newContainerEntry(new Path("codenvy:Jre"))); File depDir = new File(tempDir, wsId + projectPath); try { if (depDir.exists()) { try (DirectoryStream<java.nio.file.Path> deps = Files.newDirectoryStream(depDir.toPath(), jarFilter)) { for (java.nio.file.Path dep : deps) { String name = dep.getFileName().toString(); File srcJar = new File(dep.getParent().toFile(), "sources/" + name.substring(0, name.lastIndexOf('.')) + "-sources.jar"); IPath srcPath = null; if (srcJar.exists()) { srcPath = new Path(srcJar.getAbsolutePath()); } paths.add(JavaCore.newLibraryEntry(new Path(dep.toAbsolutePath().toString()), srcPath, null)); } } } } catch (IOException e) { LOG.error("Can't find jar dependency's: ", e); } rawClassPath = paths.toArray(new IClasspathEntry[paths.size()]); indexManager = new IndexManager(tempDir + "/indexes/" + ws + projectPath + "/", this); indexManager.reset(); indexManager.indexAll(this); indexManager.saveIndexes(); manager.setIndexManager(indexManager); creteNewNameEnvironment(); } /** * Returns true if the given project is accessible and it has * a java nature, otherwise false. * * @param project * IProject * @return boolean */ public static boolean hasJavaNature(IProject project) { // try { // return project.hasNature(JavaCore.NATURE_ID); // } catch (CoreException e) { // if (ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(project.getName())) // return true; // // project does not exist or is not open // } // return false; return true; } public SearchableEnvironment getNameEnvironment() { return nameEnvironment; } private void addSources(File projectDir, List<IClasspathEntry> paths) throws IOException { File codenvy = new File(projectDir, Constants.CODENVY_PROJECT_FILE_RELATIVE_PATH); List<File> sources = new LinkedList<>(); final ProjectJson projectJson; try (FileInputStream in = new FileInputStream(codenvy)) { projectJson = ProjectJson.load(in); } Builders defBuilder = projectJson.getBuilders(); if (defBuilder != null) { if ("maven".equals(defBuilder.getDefault())) { File pom = new File(projectDir, "pom.xml"); if (pom.exists()) { for (String src : MavenUtils.getSourceDirectories(pom)) { sources.add(new File(projectDir, src)); } } } else if ("ant".equals(defBuilder.getDefault())) { File build = new File(projectDir, "build.xml"); if (build.exists()) { for (String src : AntUtils.getSourceDirectories(build)) { sources.add(new File(projectDir, src)); } } } } if (sources.isEmpty()) { sources.add(projectDir); } for (File source : sources) { if (source.exists()) { paths.add(JavaCore.newSourceEntry(new Path(source.getAbsolutePath()))); } } } /** * Returns the raw classpath for the project, as a list of classpath * entries. This corresponds to the exact set of entries which were assigned * using <code>setRawClasspath</code>, in particular such a classpath may * contain classpath variable and classpath container entries. Classpath * variable and classpath container entries can be resolved using the * helper method <code>getResolvedClasspath</code>; classpath variable * entries also can be resolved individually using * <code>JavaCore#getClasspathVariable</code>). * <p> * Both classpath containers and classpath variables provides a level of * indirection that can make the <code>.classpath</code> file stable across * workspaces. * As an example, classpath variables allow a classpath to no longer refer * directly to external JARs located in some user specific location. * The classpath can simply refer to some variables defining the proper * locations of these external JARs. Similarly, classpath containers * allows classpath entries to be computed dynamically by the plug-in that * defines that kind of classpath container. * </p> * <p> * Note that in case the project isn't yet opened, the classpath will * be read directly from the associated <tt>.classpath</tt> file. * </p> * * @return the raw classpath for the project, as a list of classpath entries * @throws org.eclipse.jdt.core.JavaModelException * if this element does not exist or if an * exception occurs while accessing its corresponding resource * @see org.eclipse.jdt.core.IClasspathEntry */ public IClasspathEntry[] getRawClasspath() throws JavaModelException { return rawClassPath; } @Override public String[] getRequiredProjectNames() throws JavaModelException { return new String[0]; } @Override public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry) throws JavaModelException { return new IClasspathEntry[0]; } @Override public boolean hasBuildState() { return false; } @Override public boolean hasClasspathCycle(IClasspathEntry[] entries) { return false; } @Override public boolean isOnClasspath(IJavaElement element) { return false; } @Override public boolean isOnClasspath(IResource resource) { return false; } @Override public IEvaluationContext newEvaluationContext() { return null; } @Override public ITypeHierarchy newTypeHierarchy(IRegion region, IProgressMonitor monitor) throws JavaModelException { return null; } @Override public ITypeHierarchy newTypeHierarchy(IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException { return null; } @Override public ITypeHierarchy newTypeHierarchy(IType type, IRegion region, IProgressMonitor monitor) throws JavaModelException { return null; } @Override public ITypeHierarchy newTypeHierarchy(IType type, IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException { return null; } @Override public IPath readOutputLocation() { return null; } @Override public IClasspathEntry[] readRawClasspath() { return new IClasspathEntry[0]; } @Override public void setOption(String optionName, String optionValue) { } @Override public void setOptions(Map newOptions) { } @Override public void setOutputLocation(IPath path, IProgressMonitor monitor) throws JavaModelException { } @Override public void setRawClasspath(IClasspathEntry[] entries, IPath outputLocation, boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException { } @Override public void setRawClasspath(IClasspathEntry[] entries, boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException { } @Override public void setRawClasspath(IClasspathEntry[] entries, IClasspathEntry[] referencedEntries, IPath outputLocation, IProgressMonitor monitor) throws JavaModelException { } @Override public IClasspathEntry[] getReferencedClasspathEntries() throws JavaModelException { return new IClasspathEntry[0]; } @Override public void setRawClasspath(IClasspathEntry[] entries, IProgressMonitor monitor) throws JavaModelException { } @Override public void setRawClasspath(IClasspathEntry[] entries, IPath outputLocation, IProgressMonitor monitor) throws JavaModelException { } /** * This is a helper method returning the resolved classpath for the project * as a list of simple (non-variable, non-container) classpath entries. * All classpath variable and classpath container entries in the project's * raw classpath will be replaced by the simple classpath entries they * resolve to. * <p> * The resulting resolved classpath is accurate for the given point in time. * If the project's raw classpath is later modified, or if classpath * variables are changed, the resolved classpath can become out of date. * Because of this, hanging on resolved classpath is not recommended. * </p> * <p> * Note that if the resolution creates duplicate entries * (i.e. {@link IClasspathEntry entries} which are {@link Object#equals(Object)}), * only the first one is added to the resolved classpath. * </p> * * @see IClasspathEntry */ public IClasspathEntry[] getResolvedClasspath() throws JavaModelException { if (resolvedClasspath == null) { ResolvedClasspath result = new ResolvedClasspath(); LinkedHashSet<IClasspathEntry> resolvedEntries = new LinkedHashSet<>(); for (IClasspathEntry entry : getRawClasspath()) { switch (entry.getEntryKind()) { case IClasspathEntry.CPE_LIBRARY: case IClasspathEntry.CPE_SOURCE: addToResult(entry, entry, result, resolvedEntries); break; case IClasspathEntry.CPE_CONTAINER: IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), this); for (IClasspathEntry classpathEntry : container.getClasspathEntries()) { addToResult(entry, classpathEntry, result, resolvedEntries); } break; } } result.resolvedClasspath = new IClasspathEntry[resolvedEntries.size()]; resolvedEntries.toArray(result.resolvedClasspath); resolvedClasspath = result; } return resolvedClasspath.resolvedClasspath; } public ResolvedClasspath resolvedClasspath() { return resolvedClasspath; } /** * Returns the classpath entry that refers to the given path * or <code>null</code> if there is no reference to the path. * * @param path * IPath * @return IClasspathEntry * @throws JavaModelException */ public IClasspathEntry getClasspathEntryFor(IPath path) throws JavaModelException { getResolvedClasspath(); // force resolution if (resolvedClasspath == null) { return null; } Map rootPathToResolvedEntries = resolvedClasspath.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 String getName() { return projectName; } public IPath getFullPath() { return new Path(projectDir.getPath()); } @Override public IClasspathEntry decodeClasspathEntry(String encodedEntry) { return null; } @Override public String encodeClasspathEntry(IClasspathEntry classpathEntry) { return null; } @Override public IJavaElement findElement(IPath path) throws JavaModelException { return null; } @Override public IJavaElement findElement(IPath path, WorkingCopyOwner owner) throws JavaModelException { return null; } @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; } public IJavaElement findPackageFragment(String packageName) throws JavaModelException { NameLookup lookup = newNameLookup((WorkingCopyOwner)null/*no need to look at working copies for pkgs*/); IPackageFragment[] pkgFragments = lookup.findPackageFragments(packageName, false); if (pkgFragments == null) { return null; } else { // try to return one that is a child of this project for (int i = 0, length = pkgFragments.length; i < length; i++) { IPackageFragment pkgFragment = pkgFragments[i]; if (equals(pkgFragment.getParent().getParent())) { return pkgFragment; } } // default to the first one return pkgFragments[0]; } } @Override public IPackageFragment findPackageFragment(IPath path) throws JavaModelException { return null; } @Override public IPackageFragmentRoot findPackageFragmentRoot(IPath path) throws JavaModelException { return null; } @Override public IPackageFragmentRoot[] findPackageFragmentRoots(IClasspathEntry entry) { return new IPackageFragmentRoot[0]; } @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); } /* * Internal findType with instanciated name lookup */ IType findType(String fullyQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException { NameLookup.Answer answer = lookup.findType( fullyQualifiedName, false, org.eclipse.jdt.internal.core.NameLookup.ACCEPT_ALL, considerSecondaryTypes, true, /* wait for indexes (only if consider secondary types)*/ false/*don't check restrictions*/, progressMonitor); if (answer == null) { // try to find enclosing type int lastDot = fullyQualifiedName.lastIndexOf('.'); if (lastDot == -1) return null; IType type = findType(fullyQualifiedName.substring(0, lastDot), lookup, considerSecondaryTypes, progressMonitor); if (type != null) { type = type.getType(fullyQualifiedName.substring(lastDot + 1)); if (!type.exists()) { return null; } } return type; } return answer.type; } @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 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); } @Override public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException { NameLookup lookup = newNameLookup(owner); return findType( packageName, typeQualifiedName, lookup, false, // do not consider secondary types null); } @Override public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException { NameLookup lookup = newNameLookup(owner); return findType( packageName, typeQualifiedName, lookup, true, // consider secondary types progressMonitor); } /* * Internal findType with instanciated name lookup */ IType findType(String packageName, String typeQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException { NameLookup.Answer answer = lookup.findType( typeQualifiedName, packageName, false, NameLookup.ACCEPT_ALL, considerSecondaryTypes, true, // wait for indexes (in case we need to consider secondary types) false/*don't check restrictions*/, progressMonitor); return answer == null ? null : answer.type; } /* * Returns a new name lookup. This name lookup first looks in the working copies of the given owner. */ public NameLookup newNameLookup(WorkingCopyOwner owner) throws JavaModelException { // JavaModelManager manager = org.eclipse.jdt.internal.core.JavaModelManager.getJavaModelManager(); ICompilationUnit[] workingCopies = owner == null ? null : manager.getWorkingCopies(owner, true/*add primary WCs*/); return newNameLookup(workingCopies); } @Override public IPackageFragmentRoot[] getAllPackageFragmentRoots() throws JavaModelException { return getAllPackageFragmentRoots(null /*no reverse map*/); } public IPackageFragmentRoot[] getAllPackageFragmentRoots(Map rootToResolvedEntries) throws JavaModelException { return computePackageFragmentRoots(getResolvedClasspath(), true/*retrieveExportedRoots*/, rootToResolvedEntries); } /** * Returns (local/all) the package fragment roots identified by the given project's classpath. * Note: this follows project classpath references to find required project contributions, * eliminating duplicates silently. * Only works with resolved entries * * @param resolvedClasspath * IClasspathEntry[] * @param retrieveExportedRoots * boolean * @return IPackageFragmentRoot[] * @throws JavaModelException */ public IPackageFragmentRoot[] computePackageFragmentRoots( IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots, Map rootToResolvedEntries) throws JavaModelException { ObjectVector accumulatedRoots = new ObjectVector(); computePackageFragmentRoots( resolvedClasspath, accumulatedRoots, new HashSet(5), // rootIDs null, // inside original project retrieveExportedRoots, rootToResolvedEntries); IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots.size()]; accumulatedRoots.copyInto(rootArray); return rootArray; } /** * Returns (local/all) the package fragment roots identified by the given project's classpath. * Note: this follows project classpath references to find required project contributions, * eliminating duplicates silently. * Only works with resolved entries * * @param resolvedClasspath * IClasspathEntry[] * @param accumulatedRoots * ObjectVector * @param rootIDs * HashSet * @param referringEntry * project entry referring to this CP or null if initial project * @param retrieveExportedRoots * boolean * @throws JavaModelException */ public void computePackageFragmentRoots( IClasspathEntry[] resolvedClasspath, ObjectVector accumulatedRoots, HashSet rootIDs, IClasspathEntry referringEntry, boolean retrieveExportedRoots, Map rootToResolvedEntries) 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, rootToResolvedEntries); } } /** * Returns the package fragment roots identified by the given entry. In case it refers to * a project, it will follow its classpath so as to find exported roots as well. * Only works with resolved entry * * @param resolvedEntry * IClasspathEntry * @param accumulatedRoots * ObjectVector * @param rootIDs * HashSet * @param referringEntry * the CP entry (project) referring to this entry, or null if initial project * @param retrieveExportedRoots * boolean * @throws JavaModelException */ public void computePackageFragmentRoots( IClasspathEntry resolvedEntry, ObjectVector accumulatedRoots, HashSet rootIDs, IClasspathEntry referringEntry, boolean retrieveExportedRoots, Map rootToResolvedEntries) throws JavaModelException { String rootID = ((ClasspathEntry)resolvedEntry).rootID(); if (rootIDs.contains(rootID)) return; IPath projectPath = this.getFullPath(); IPath entryPath = resolvedEntry.getPath(); // IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); IPackageFragmentRoot root = null; switch (resolvedEntry.getEntryKind()) { // source folder case IClasspathEntry.CPE_SOURCE: // if (projectPath.isPrefixOf(entryPath)) { Object target1 = JavaModelManager.getTarget(entryPath, true/*check existency*/); if (target1 == null) return; if (target1 instanceof File && ((File)target1).isDirectory()) { root = getPackageFragmentRoot((File)target1); } // } break; // internal/external JAR or folder case IClasspathEntry.CPE_LIBRARY: if (referringEntry != null && !resolvedEntry.isExported()) return; Object target = JavaModelManager.getTarget(entryPath, true/*check existency*/); if (target == null) return; // if (target instanceof IResource){ // // internal target // } else if (target instanceof File) { // external target if (JavaModelManager.isFile(target)) { root = new JarPackageFragmentRoot((File)target, this, manager); } else if (((File)target).isDirectory()) { root = getPackageFragmentRoot((File)target, entryPath); // root = new ExternalPackageFragmentRoot(entryPath, this); } } break; // recurse into required project case IClasspathEntry.CPE_PROJECT: if (!retrieveExportedRoots) return; if (referringEntry != null && !resolvedEntry.isExported()) return; //todo multiproject // IResource member = workspaceRoot.findMember(entryPath); // if (member != null && member.getType() == IResource.PROJECT) {// double check if bound to project (23977) // IProject requiredProjectRsc = (IProject)member; // if (JavaProject.hasJavaNature(requiredProjectRsc)) { // special builder binary output // rootIDs.add(rootID); // JavaProject requiredProject = (JavaProject)JavaCore.create(requiredProjectRsc); // requiredProject.computePackageFragmentRoots( // requiredProject.getResolvedClasspath(), // accumulatedRoots, // rootIDs, // rootToResolvedEntries == null ? resolvedEntry // : ((org.eclipse.jdt.internal.core.ClasspathEntry)resolvedEntry) // .combineWith((org.eclipse.jdt.internal.core.ClasspathEntry)referringEntry), // // only combine if need to build the reverse map // retrieveExportedRoots, // rootToResolvedEntries); // } // break; // } } if (root != null) { accumulatedRoots.add(root); rootIDs.add(rootID); if (rootToResolvedEntries != null) rootToResolvedEntries .put(root, ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry)referringEntry)); } } /** * @see IJavaProject */ public IPackageFragmentRoot getPackageFragmentRoot(File resource) { return getPackageFragmentRoot(resource, null/*no entry path*/); } private IPackageFragmentRoot getPackageFragmentRoot(File resource, IPath entryPath) { if (resource.isDirectory()) { // if (ExternalFoldersManager.isInternalPathForExternalFolder(resource.getFullPath())) // return new ExternalPackageFragmentRoot(resource, entryPath, this); return new PackageFragmentRoot(resource, this, manager); } else { return new JarPackageFragmentRoot(resource, this, manager); } // return null; } /** * Answers an ID which is used to distinguish project/entries during package * fragment root computations * * @return String */ public String rootID() { return "[PRJ]" + this.getFullPath(); //$NON-NLS-1$ } @Override public Object[] getNonJavaResources() throws JavaModelException { return new Object[0]; } @Override public String getOption(String optionName, boolean inheritJavaCoreOptions) { return options.get(optionName); } public Map getOptions(boolean b) { return options; } @Override public IPath getOutputLocation() throws JavaModelException { return null; } @Override public IPackageFragmentRoot getPackageFragmentRoot(String externalLibraryPath) { // return new JarPackageFragmentRoot(new Path(externalLibraryPath), this); throw new UnsupportedOperationException(); } @Override public IPackageFragmentRoot getPackageFragmentRoot(IResource resource) { throw new UnsupportedOperationException(); } @Override public IPackageFragmentRoot[] getPackageFragmentRoots() throws JavaModelException { throw new UnsupportedOperationException(); } @Override public IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry) { throw new UnsupportedOperationException(); } @Override public IPackageFragment[] getPackageFragments() throws JavaModelException { throw new UnsupportedOperationException(); } @Override public IProject getProject() { return null; } @Override protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, File underlyingResource) throws JavaModelException { // cannot refresh cp markers on opening (emulate cp check on startup) since can create deadlocks (see bug 37274) IClasspathEntry[] resolvedClasspath = getResolvedClasspath(); // compute the pkg fragment roots info.setChildren(computePackageFragmentRoots(resolvedClasspath, false, null /*no reverse map*/)); return true; } /* * Returns whether the given resource is accessible through the children or the non-Java resources of this project. * Returns true if the resource is not in the project. * Assumes that the resource is a folder or a file. */ public boolean contains(File resource) { return true; } // @Override // public IJavaElement getAncestor(int ancestorType) { // return null; // } @Override public boolean exists() { return false; } @Override public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException { return null; } @Override public IResource getCorrespondingResource() throws JavaModelException { throw new UnsupportedOperationException(); } @Override public String getElementName() { return projectName; } @Override public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) { switch (token.charAt(0)) { case JEM_PACKAGEFRAGMENTROOT: String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH; token = null; while (memento.hasMoreTokens()) { token = memento.nextToken(); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=331821 if (token == MementoTokenizer.PACKAGEFRAGMENT || token == MementoTokenizer.COUNT) { break; } rootPath += token; } JavaElement root = (JavaElement)getPackageFragmentRoot(new File(rootPath)); if (token != null && token.charAt(0) == JEM_PACKAGEFRAGMENT) { return root.getHandleFromMemento(token, memento, owner); } else { return root.getHandleFromMemento(memento, owner); } } return null; } @Override public int getElementType() { return IJavaElement.JAVA_PROJECT; } @Override protected char getHandleMementoDelimiter() { return JEM_JAVAPROJECT; } @Override public IJavaModel getJavaModel() { return null; } public IPath getPath() { return new Path(projectDir.getAbsolutePath()); } public String getProjectPath(){ return projectPath; } @Override public IJavaElement getPrimaryElement() { return null; } @Override public IResource getResource() { return null; } @Override protected File resource(PackageFragmentRoot root) { return projectDir; } @Override public ISchedulingRule getSchedulingRule() { return null; } @Override public IResource getUnderlyingResource() throws JavaModelException { return null; } @Override public boolean isReadOnly() { return false; } @Override public boolean isStructureKnown() throws JavaModelException { return false; } @Override public Object getAdapter(Class aClass) { return null; } @Override public void close() throws JavaModelException { indexManager.shutdown(); indexManager.deleteIndexFiles(); nameEnvironment.cleanup(); File file = new File(tempDir + "/indexes/" + wsId); String[] list = file.list(); if (list == null || list.length == 0) { file.delete(); } super.close(); } @Override public String findRecommendedLineSeparator() throws JavaModelException { return null; } @Override public IBuffer getBuffer() throws JavaModelException { return null; } @Override public boolean hasUnsavedChanges() throws JavaModelException { return false; } @Override public boolean isConsistent() { return false; } @Override public boolean isOpen() { return false; } @Override public void makeConsistent(IProgressMonitor progress) throws JavaModelException { } @Override public void open(IProgressMonitor progress) throws JavaModelException { } @Override public void save(IProgressMonitor progress, boolean force) throws JavaModelException { } /** * The path is known to match a source/library folder entry. * * @param path * IPath * @return IPackageFragmentRoot */ public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) { if (path.segmentCount() == 1) { // default project root return getPackageFragmentRoot(); } return getPackageFragmentRoot(path.toFile()); } public JavaProjectElementInfo.ProjectCache getProjectCache() throws JavaModelException { return ((JavaProjectElementInfo)getElementInfo()).getProjectCache(this); } /** * Returns a new element info for this element. */ protected Object createElementInfo() { return new JavaProjectElementInfo(); } @Override protected IStatus validateExistence(File underlyingResource) { return JavaModelStatus.VERIFIED_OK; } /** * @see org.eclipse.jdt.internal.core.JavaElement#getHandleMemento(StringBuffer) */ protected void getHandleMemento(StringBuffer buff) { // buff.append(getElementName()); } /* * Resets this project's caches */ public void resetCaches() { JavaProjectElementInfo info = (JavaProjectElementInfo) manager.peekAtInfo(this); if (info != null){ info.resetCaches(); } } private void addToResult(IClasspathEntry rawEntry, IClasspathEntry resolvedEntry, ResolvedClasspath result, LinkedHashSet<IClasspathEntry> resolvedEntries) { IPath resolvedPath; // If it's already been resolved, do not add to resolvedEntries if (result.rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) { result.rawReverseMap.put(resolvedPath, rawEntry); result.rootPathToResolvedEntries.put(resolvedPath, resolvedEntry); resolvedEntries.add(resolvedEntry); } } public IndexManager getIndexManager() { return indexManager; } /** * Convenience method that returns the specific type of info for a Java project. */ protected JavaProjectElementInfo getJavaProjectElementInfo() throws JavaModelException { return (JavaProjectElementInfo)getElementInfo(); } public NameLookup newNameLookup(ICompilationUnit[] workingCopies) throws JavaModelException { return getJavaProjectElementInfo().newNameLookup(this, workingCopies); } public SearchableEnvironment newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws JavaModelException { return new SearchableEnvironment(this, workingCopies); } /** * Returns true if this handle represents the same Java project * as the given handle. Two handles represent the same * project if they are identical or if they represent a project with * the same underlying resource and occurrence counts. * * @see org.eclipse.jdt.internal.core.JavaElement#equals(Object) */ public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof JavaProject)) return false; JavaProject other = (JavaProject)o; return this.getFullPath().equals(other.getFullPath()); } /* * Returns a new search name environment for this project. This name environment first looks in the working copies * of the given owner. */ public SearchableEnvironment newSearchableNameEnvironment(WorkingCopyOwner owner) throws JavaModelException { return new SearchableEnvironment(this, owner); } public String getWsId() { return wsId; } public JavaModelManager getJavaModelManager() { return manager; } public String getWorkspacePath() { return workspacePath; } public synchronized void creteNewNameEnvironment() { try { nameEnvironment = new SearchableEnvironment(this, (ICompilationUnit[])null); } catch (JavaModelException e) { LOG.error("Can't create SearchableEnvironment", e); } } public static class ResolvedClasspath { IClasspathEntry[] resolvedClasspath; IJavaModelStatus unresolvedEntryStatus = JavaModelStatus.VERIFIED_OK; HashMap<IPath, IClasspathEntry> rawReverseMap = new HashMap<>(); Map<IPath, IClasspathEntry> rootPathToResolvedEntries = new HashMap<>(); IClasspathEntry[] referencedEntries = null; } }