/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.internal.core; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import net.sourceforge.phpdt.core.IClasspathEntry; import net.sourceforge.phpdt.core.ICompilationUnit; import net.sourceforge.phpdt.core.IJavaElement; import net.sourceforge.phpdt.core.IJavaModelMarker; import net.sourceforge.phpdt.core.IJavaModelStatus; import net.sourceforge.phpdt.core.IJavaModelStatusConstants; import net.sourceforge.phpdt.core.IJavaProject; import net.sourceforge.phpdt.core.IPackageFragment; import net.sourceforge.phpdt.core.IPackageFragmentRoot; import net.sourceforge.phpdt.core.JavaCore; import net.sourceforge.phpdt.core.JavaModelException; import net.sourceforge.phpdt.core.WorkingCopyOwner; import net.sourceforge.phpdt.internal.codeassist.ISearchableNameEnvironment; import net.sourceforge.phpdt.internal.compiler.util.ObjectVector; import net.sourceforge.phpdt.internal.core.util.MementoTokenizer; import net.sourceforge.phpdt.internal.core.util.Util; //incastrix //import net.sourceforge.phpdt.internal.corext.Assert; //import org.eclipse.core.runtime.Assert; import net.sourceforge.phpeclipse.LoadPathEntry; import net.sourceforge.phpeclipse.PHPeclipsePlugin; 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.ResourcesPlugin; import org.eclipse.core.runtime.AssertionFailedException; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.QualifiedName; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; /** * Handle for a Java Project. * *

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

* Each JavaProject has a NameLookup facility that locates elements on by name, * based on the devpath. * * @see IJavaProject */ public class JavaProject extends Openable implements IJavaProject, IProjectNature { /** * Whether the underlying file system is case sensitive. */ protected static final boolean IS_CASE_SENSITIVE = !new File("Temp").equals(new File("temp")); //$NON-NLS-1$ //$NON-NLS-2$ /** * An empty array of strings indicating that a project doesn't have any * prerequesite projects. */ protected static final String[] NO_PREREQUISITES = new String[0]; /** * The platform project this IJavaProject is based on */ protected IProject project; protected List fLoadPathEntries; protected boolean fScratched; /** * Name of file containing project classpath */ public static final String CLASSPATH_FILENAME = ".classpath"; //$NON-NLS-1$ /** * Name of file containing custom project preferences */ public static final String PREF_FILENAME = ".jprefs"; //$NON-NLS-1$ /** * 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 String CUSTOM_DEFAULT_OPTION_VALUE = "#\r\n\r#custom-non-empty-default-value#\r\n\r#"; //$NON-NLS-1$ /* * Value of project's resolved classpath while it is being resolved */ private static final IClasspathEntry[] RESOLUTION_IN_PROGRESS = new IClasspathEntry[0]; /** * Returns a canonicalized path from the given external path. Note that the * return path contains the same number of segments and it contains a device * only if the given path contained one. * * @see java.io.File for the definition of a canonicalized path */ public static IPath canonicalizedPath(IPath externalPath) { if (externalPath == null) return null; if (JavaModelManager.VERBOSE) { System.out .println("JAVA MODEL - Canonicalizing " + externalPath.toString()); //$NON-NLS-1$ } if (IS_CASE_SENSITIVE) { if (JavaModelManager.VERBOSE) { System.out .println("JAVA MODEL - Canonical path is original path (file system is case sensitive)"); //$NON-NLS-1$ } return externalPath; } // if not external path, return original path IWorkspace workspace = ResourcesPlugin.getWorkspace(); if (workspace == null) return externalPath; // protection during shutdown (30487) if (workspace.getRoot().findMember(externalPath) != null) { if (JavaModelManager.VERBOSE) { System.out .println("JAVA MODEL - Canonical path is original path (member of workspace)"); //$NON-NLS-1$ } return externalPath; } IPath canonicalPath = null; try { canonicalPath = new Path(new File(externalPath.toOSString()) .getCanonicalPath()); } catch (IOException e) { // default to original path if (JavaModelManager.VERBOSE) { System.out .println("JAVA MODEL - Canonical path is original path (IOException)"); //$NON-NLS-1$ } return externalPath; } IPath result; int canonicalLength = canonicalPath.segmentCount(); if (canonicalLength == 0) { // the java.io.File canonicalization failed if (JavaModelManager.VERBOSE) { System.out .println("JAVA MODEL - Canonical path is original path (canonical path is empty)"); //$NON-NLS-1$ } return externalPath; } else if (externalPath.isAbsolute()) { result = canonicalPath; } else { // if path is relative, remove the first segments that were added by // the java.io.File canonicalization // e.g. 'lib/classes.zip' was converted to // 'd:/myfolder/lib/classes.zip' int externalLength = externalPath.segmentCount(); if (canonicalLength >= externalLength) { result = canonicalPath.removeFirstSegments(canonicalLength - externalLength); } else { if (JavaModelManager.VERBOSE) { System.out .println("JAVA MODEL - Canonical path is original path (canonical path is " + canonicalPath.toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ } return externalPath; } } // keep device only if it was specified (this is because // File.getCanonicalPath() converts '/lib/classed.zip' to // 'd:/lib/classes/zip') if (externalPath.getDevice() == null) { result = result.setDevice(null); } if (JavaModelManager.VERBOSE) { System.out .println("JAVA MODEL - Canonical path is " + result.toString()); //$NON-NLS-1$ } return result; } /** * Constructor needed for IProject.getNature() and * IProject.addNature(). * * @see #setProject(IProject) */ public JavaProject() { super(null, null); } public JavaProject(IProject project, JavaElement parent) { super(parent, project.getName()); this.project = project; } public void addLoadPathEntry(IProject anotherPHPProject) { fScratched = true; LoadPathEntry newEntry = new LoadPathEntry(anotherPHPProject); getLoadPathEntries().add(newEntry); } public void configure() throws CoreException { // get project description and then the associated build commands IProjectDescription desc = project.getDescription(); ICommand[] commands = desc.getBuildSpec(); // determine if builder already associated boolean found = false; for (int i = 0; i < commands.length; ++i) { if (commands[i].getBuilderName().equals( PHPeclipsePlugin.BUILDER_PARSER_ID)) { found = true; break; } } // add builder if not already in project if (!found) { ICommand command = desc.newCommand(); command.setBuilderName(PHPeclipsePlugin.BUILDER_PARSER_ID); ICommand[] newCommands = new ICommand[commands.length + 1]; // Add it before other builders. System.arraycopy(commands, 0, newCommands, 1, commands.length); newCommands[0] = command; desc.setBuildSpec(newCommands); project.setDescription(desc, null); } } protected void loadLoadPathEntries() { fLoadPathEntries = new ArrayList(); IFile loadPathsFile = getLoadPathEntriesFile(); XMLReader reader = null; try { reader = SAXParserFactory.newInstance().newSAXParser() .getXMLReader(); reader.setContentHandler(getLoadPathEntriesContentHandler()); reader.parse(new InputSource(loadPathsFile.getContents())); } catch (Exception e) { // the file is nonextant or unreadable } } public List getLoadPathEntries() { if (fLoadPathEntries == null) { loadLoadPathEntries(); } return fLoadPathEntries; } protected ContentHandler getLoadPathEntriesContentHandler() { return new ContentHandler() { public void characters(char[] arg0, int arg1, int arg2) throws SAXException { } public void endDocument() throws SAXException { } public void endElement(String arg0, String arg1, String arg2) throws SAXException { } public void endPrefixMapping(String arg0) throws SAXException { } public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException { } public void processingInstruction(String arg0, String arg1) throws SAXException { } public void setDocumentLocator(Locator arg0) { } public void skippedEntity(String arg0) throws SAXException { } public void startDocument() throws SAXException { } public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { if ("pathentry".equals(qName)) if ("project".equals(atts.getValue("type"))) { IPath referencedProjectPath = new Path(atts .getValue("path")); IProject referencedProject = getProject(referencedProjectPath .lastSegment()); fLoadPathEntries.add(new LoadPathEntry( referencedProject)); } } public void startPrefixMapping(String arg0, String arg1) throws SAXException { } }; } protected IFile getLoadPathEntriesFile() { return project.getFile(".loadpath"); } protected String getLoadPathXML() { StringBuffer buffer = new StringBuffer(); buffer.append(""); Iterator pathEntriesIterator = fLoadPathEntries.iterator(); while (pathEntriesIterator.hasNext()) { LoadPathEntry entry = (LoadPathEntry) pathEntriesIterator.next(); buffer.append(entry.toXML()); } buffer.append(""); return buffer.toString(); } /** * Adds a builder to the build spec for the given project. */ protected void addToBuildSpec(String builderID) throws CoreException { IProjectDescription description = getProject().getDescription(); ICommand javaCommand = getJavaCommand(description); if (javaCommand == null) { // Add a Java command to the build spec ICommand command = description.newCommand(); command.setBuilderName(builderID); setJavaCommand(description, command); } } /** * @see Openable */ protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException { // check whether the java project can be opened if (!underlyingResource.isAccessible()) { throw newNotPresentException(); } //IWorkspace workspace = ResourcesPlugin.getWorkspace(); //IWorkspaceRoot wRoot = workspace.getRoot(); // cannot refresh cp markers on opening (emulate cp check on startup) // since can create deadlocks (see bug 37274) // IClasspathEntry[] resolvedClasspath = // getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't // generateMarkerOnError*/, false/*don't returnResolutionInProgress*/); // // compute the pkg fragment roots // info.setChildren(computePackageFragmentRoots(resolvedClasspath, // false)); // // // remember the timestamps of external libraries the first time they // are looked up // for (int i = 0, length = resolvedClasspath.length; i < length; i++) { // IClasspathEntry entry = resolvedClasspath[i]; // if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { // IPath path = entry.getPath(); // Object target = JavaModel.getTarget(wRoot, path, true); // if (target instanceof java.io.File) { // Map externalTimeStamps = // JavaModelManager.getJavaModelManager().deltaState.externalTimeStamps; // if (externalTimeStamps.get(path) == null) { // long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target); // externalTimeStamps.put(path, new Long(timestamp)); // } // } // } // } return true; } protected void closing(Object info) { // // forget source attachment recommendations // Object[] children = ((JavaElementInfo)info).children; // for (int i = 0, length = children.length; i < length; i++) { // Object child = children[i]; // if (child instanceof JarPackageFragmentRoot){ // ((JarPackageFragmentRoot)child).setSourceAttachmentProperty(null); // } // } super.closing(info); } // protected void closing(Object info) throws JavaModelException { // // // forget source attachment recommendations // IPackageFragmentRoot[] roots = this.getPackageFragmentRoots(); // // for (int i = 0; i < roots.length; i++) { // // if (roots[i] instanceof JarPackageFragmentRoot){ // // ((JarPackageFragmentRoot) roots[i]).setSourceAttachmentProperty(null); // // } // // } // // super.closing(info); // } /** * Internal computation of an expanded classpath. It will eliminate * duplicates, and produce copies of exported classpath entries to avoid * possible side-effects ever after. */ private void computeExpandedClasspath(JavaProject initialProject, boolean ignoreUnresolvedVariable, boolean generateMarkerOnError, HashSet rootIDs, ObjectVector accumulatedEntries, Map preferredClasspaths, Map preferredOutputs) throws JavaModelException { String projectRootId = this.rootID(); if (rootIDs.contains(projectRootId)) { return; // break cycles if any } rootIDs.add(projectRootId); IClasspathEntry[] preferredClasspath = preferredClasspaths != null ? (IClasspathEntry[]) preferredClasspaths .get(this) : null; IPath preferredOutput = preferredOutputs != null ? (IPath) preferredOutputs .get(this) : null; IClasspathEntry[] immediateClasspath = preferredClasspath != null ? getResolvedClasspath( preferredClasspath, preferredOutput, ignoreUnresolvedVariable, generateMarkerOnError, null) : getResolvedClasspath(ignoreUnresolvedVariable, generateMarkerOnError, false/* * don't * returnResolutionInProgress */); IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); boolean isInitialProject = this.equals(initialProject); for (int i = 0, length = immediateClasspath.length; i < length; i++) { ClasspathEntry entry = (ClasspathEntry) immediateClasspath[i]; if (isInitialProject || entry.isExported()) { String rootID = entry.rootID(); if (rootIDs.contains(rootID)) { continue; } accumulatedEntries.add(entry); // recurse in project to get all its indirect exports (only // consider exported entries from there on) if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { IResource member = workspaceRoot .findMember(entry.getPath()); if (member != null && member.getType() == IResource.PROJECT) { // double // check // if // bound // to // project // (23977) IProject projRsc = (IProject) member; if (JavaProject.hasJavaNature(projRsc)) { JavaProject javaProject = (JavaProject) JavaCore .create(projRsc); javaProject .computeExpandedClasspath( initialProject, ignoreUnresolvedVariable, false /* * no marker when recursing * in prereq */, rootIDs, accumulatedEntries, preferredClasspaths, preferredOutputs); } } } else { rootIDs.add(rootID); } } } } /** * Internal computation of an expanded classpath. It will eliminate * duplicates, and produce copies of exported classpath entries to avoid * possible side-effects ever after. */ // private void computeExpandedClasspath( // JavaProject initialProject, // boolean ignoreUnresolvedVariable, // boolean generateMarkerOnError, // HashSet visitedProjects, // ObjectVector accumulatedEntries) throws JavaModelException { // // if (visitedProjects.contains(this)){ // return; // break cycles if any // } // visitedProjects.add(this); // // if (generateMarkerOnError && !this.equals(initialProject)){ // generateMarkerOnError = false; // } // IClasspathEntry[] immediateClasspath = // getResolvedClasspath(ignoreUnresolvedVariable, generateMarkerOnError); // // IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); // for (int i = 0, length = immediateClasspath.length; i < length; i++){ // IClasspathEntry entry = immediateClasspath[i]; // // boolean isInitialProject = this.equals(initialProject); // if (isInitialProject || entry.isExported()){ // // accumulatedEntries.add(entry); // // // recurse in project to get all its indirect exports (only consider // exported entries from there on) // if (entry.getEntryKind() == ClasspathEntry.CPE_PROJECT) { // IResource member = workspaceRoot.findMember(entry.getPath()); // if (member != null && member.getType() == IResource.PROJECT){ // double // check if bound to project (23977) // IProject projRsc = (IProject) member; // if (JavaProject.hasJavaNature(projRsc)) { // JavaProject project = (JavaProject) JavaCore.create(projRsc); // project.computeExpandedClasspath( // initialProject, // ignoreUnresolvedVariable, // generateMarkerOnError, // visitedProjects, // accumulatedEntries); // } // } // } // } // } // } /** * 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 */ public IPackageFragmentRoot[] computePackageFragmentRoots( IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots) throws JavaModelException { ObjectVector accumulatedRoots = new ObjectVector(); computePackageFragmentRoots(resolvedClasspath, accumulatedRoots, new HashSet(5), // rootIDs true, // inside original project true, // check existency retrieveExportedRoots); IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots .size()]; accumulatedRoots.copyInto(rootArray); return rootArray; } /** * Computes the package fragment roots identified by the given entry. Only * works with resolved entry */ public IPackageFragmentRoot[] computePackageFragmentRoots( IClasspathEntry resolvedEntry) { try { return computePackageFragmentRoots( new IClasspathEntry[] { resolvedEntry }, false // don't // retrieve // exported // roots ); } catch (JavaModelException e) { return new IPackageFragmentRoot[] {}; } } /** * 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 */ public void computePackageFragmentRoots(IClasspathEntry resolvedEntry, ObjectVector accumulatedRoots, HashSet rootIDs, boolean insideOriginalProject, boolean checkExistency, boolean retrieveExportedRoots) throws JavaModelException { String rootID = ((ClasspathEntry) resolvedEntry).rootID(); if (rootIDs.contains(rootID)) return; IPath projectPath = getProject().getFullPath(); IPath entryPath = resolvedEntry.getPath(); IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); switch (resolvedEntry.getEntryKind()) { // source folder case IClasspathEntry.CPE_SOURCE: if (projectPath.isPrefixOf(entryPath)) { if (checkExistency) { Object target = JavaModel.getTarget(workspaceRoot, entryPath, checkExistency); if (target == null) return; if (target instanceof IFolder || target instanceof IProject) { accumulatedRoots .add(getPackageFragmentRoot((IResource) target)); rootIDs.add(rootID); } } else { IPackageFragmentRoot root = getFolderPackageFragmentRoot(entryPath); if (root != null) { accumulatedRoots.add(root); rootIDs.add(rootID); } } } break; // internal/external JAR or folder case IClasspathEntry.CPE_LIBRARY: if (!insideOriginalProject && !resolvedEntry.isExported()) return; if (checkExistency) { Object target = JavaModel.getTarget(workspaceRoot, entryPath, checkExistency); if (target == null) return; if (target instanceof IResource) { // internal target IResource resource = (IResource) target; IPackageFragmentRoot root = getPackageFragmentRoot(resource); if (root != null) { accumulatedRoots.add(root); rootIDs.add(rootID); } } else { // external target - only JARs allowed // if (((java.io.File)target).isFile() && // (ProjectPrefUtil.isArchiveFileName(entryPath.lastSegment()))) // { // accumulatedRoots.add( // new JarPackageFragmentRoot(entryPath, this)); // rootIDs.add(rootID); // } } } else { IPackageFragmentRoot root = getPackageFragmentRoot(entryPath); if (root != null) { accumulatedRoots.add(root); rootIDs.add(rootID); } } break; // recurse into required project case IClasspathEntry.CPE_PROJECT: if (!retrieveExportedRoots) return; if (!insideOriginalProject && !resolvedEntry.isExported()) return; IResource member = workspaceRoot.findMember(entryPath); if (member != null && member.getType() == IResource.PROJECT) {// double // check // if // bound // to // project // (23977) IProject requiredProjectRsc = (IProject) member; if (JavaProject.hasJavaNature(requiredProjectRsc)) { // special // builder // binary // output rootIDs.add(rootID); JavaProject requiredProject = (JavaProject) JavaCore .create(requiredProjectRsc); requiredProject.computePackageFragmentRoots(requiredProject .getResolvedClasspath(true), accumulatedRoots, rootIDs, false, checkExistency, retrieveExportedRoots); } break; } } } /** * 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 */ public void computePackageFragmentRoots( IClasspathEntry[] resolvedClasspath, ObjectVector accumulatedRoots, HashSet rootIDs, boolean insideOriginalProject, boolean checkExistency, boolean retrieveExportedRoots) throws JavaModelException { if (insideOriginalProject) { rootIDs.add(rootID()); } for (int i = 0, length = resolvedClasspath.length; i < length; i++) { computePackageFragmentRoots(resolvedClasspath[i], accumulatedRoots, rootIDs, insideOriginalProject, checkExistency, retrieveExportedRoots); } } /** * Compute the file name to use for a given shared property */ public String computeSharedPropertyFileName(QualifiedName qName) { return '.' + qName.getLocalName(); } /* * Returns whether the given resource is accessible through the children or * the non-Java resources of this project. Returns true if the resource is * not in the project. Assumes that the resource is a folder or a file. */ public boolean contains(IResource resource) { IClasspathEntry[] classpath; IPath output; try { classpath = getResolvedClasspath(true); output = getOutputLocation(); } catch (JavaModelException e) { return false; } IPath fullPath = resource.getFullPath(); IPath innerMostOutput = output.isPrefixOf(fullPath) ? output : null; IClasspathEntry innerMostEntry = null; for (int j = 0, cpLength = classpath.length; j < cpLength; j++) { IClasspathEntry entry = classpath[j]; IPath entryPath = entry.getPath(); if ((innerMostEntry == null || innerMostEntry.getPath().isPrefixOf( entryPath)) && entryPath.isPrefixOf(fullPath)) { innerMostEntry = entry; } IPath entryOutput = classpath[j].getOutputLocation(); if (entryOutput != null && entryOutput.isPrefixOf(fullPath)) { innerMostOutput = entryOutput; } } if (innerMostEntry != null) { // special case prj==src and nested output location if (innerMostOutput != null && innerMostOutput.segmentCount() > 1 // output // isn't // project && innerMostEntry.getPath().segmentCount() == 1) { // 1 // segment // must // be // project // name return false; } if (resource instanceof IFolder) { // folders are always included in src/lib entries return true; } switch (innerMostEntry.getEntryKind()) { case IClasspathEntry.CPE_SOURCE: // .class files are not visible in source folders return true; // !net.sourceforge.phpdt.internal.compiler.util.ProjectPrefUtil.isClassFileName(fullPath.lastSegment()); case IClasspathEntry.CPE_LIBRARY: // .java files are not visible in library folders return !net.sourceforge.phpdt.internal.compiler.util.Util .isJavaFileName(fullPath.lastSegment()); } } if (innerMostOutput != null) { return false; } return true; } /** * Record a new marker denoting a classpath problem */ IMarker createClasspathProblemMarker(IJavaModelStatus status) { IMarker marker = null; int severity; String[] arguments = new String[0]; boolean isCycleProblem = false, isClasspathFileFormatProblem = 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; default: IPath path = status.getPath(); if (path != null) arguments = new String[] { path.toString() }; if (JavaCore.ERROR.equals(getOption( JavaCore.CORE_INCOMPLETE_CLASSPATH, true))) { severity = IMarker.SEVERITY_ERROR; } else { severity = IMarker.SEVERITY_WARNING; } break; } try { marker = getProject().createMarker( IJavaModelMarker.BUILDPATH_PROBLEM_MARKER); marker.setAttributes(new String[] { IMarker.MESSAGE, IMarker.SEVERITY, IMarker.LOCATION, IJavaModelMarker.CYCLE_DETECTED, IJavaModelMarker.CLASSPATH_FILE_FORMAT, IJavaModelMarker.ID, IJavaModelMarker.ARGUMENTS, }, new Object[] { status.getMessage(), new Integer(severity), Util.bind("classpath.buildPath"),//$NON-NLS-1$ isCycleProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$ isClasspathFileFormatProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$ new Integer(status.getCode()), Util.getProblemArgumentsForMarker(arguments), }); } catch (CoreException e) { } return marker; } /** * Returns a new element info for this element. */ protected Object createElementInfo() { return new JavaProjectElementInfo(); } /* * Returns a new search name environment for this project. This name * environment first looks in the given working copies. */ // public ISearchableNameEnvironment // newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws // JavaModelException { // return new SearchableEnvironment(this, workingCopies); // } /* * Returns a new search name environment for this project. This name * environment first looks in the working copies of the given owner. */ public ISearchableNameEnvironment newSearchableNameEnvironment( WorkingCopyOwner owner) throws JavaModelException { return new SearchableEnvironment(this, owner); } /** * Reads and decode an XML classpath string */ protected IClasspathEntry[] decodeClasspath(String xmlClasspath, boolean createMarker, boolean logProblems) { ArrayList paths = new ArrayList(); IClasspathEntry defaultOutput = null; try { if (xmlClasspath == null) return null; StringReader reader = new StringReader(xmlClasspath); Element cpElement; try { DocumentBuilder parser = DocumentBuilderFactory.newInstance() .newDocumentBuilder(); cpElement = parser.parse(new InputSource(reader)) .getDocumentElement(); } catch (SAXException e) { throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$ } catch (ParserConfigurationException e) { throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$ } finally { reader.close(); } if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$ throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$ } NodeList list = cpElement.getElementsByTagName("classpathentry"); //$NON-NLS-1$ 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); if (entry != null) { if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { defaultOutput = entry; // separate output } else { paths.add(entry); } } } } } catch (IOException e) { // bad format if (createMarker && this.getProject().isAccessible()) { this .createClasspathProblemMarker(new JavaModelStatus( IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT, Util .bind( "classpath.xmlFormatError", this.getElementName(), e.getMessage()))); //$NON-NLS-1$ } if (logProblems) { Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$ + "/.classpath, will mark classpath as invalid"); //$NON-NLS-1$ } return INVALID_CLASSPATH; } catch (/*Assert.*/AssertionFailedException e) { // failed creating CP entries from file if (createMarker && this.getProject().isAccessible()) { this .createClasspathProblemMarker(new JavaModelStatus( IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT, Util .bind( "classpath.illegalEntryInClasspathFile", this.getElementName(), e.getMessage()))); //$NON-NLS-1$ } if (logProblems) { Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$ + "/.classpath, will mark classpath as invalid"); //$NON-NLS-1$ } return INVALID_CLASSPATH; } int pathSize = paths.size(); if (pathSize > 0 || defaultOutput != null) { IClasspathEntry[] entries = new IClasspathEntry[pathSize + (defaultOutput == null ? 0 : 1)]; paths.toArray(entries); if (defaultOutput != null) entries[pathSize] = defaultOutput; // ensure output is last // item return entries; } else { return null; } } /** * /** Removes the Java nature from the project. */ public void deconfigure() throws CoreException { // deregister Java builder removeFromBuildSpec(PHPeclipsePlugin.BUILDER_PARSER_ID); } /** * Returns a default class path. This is the root of the project */ protected IClasspathEntry[] defaultClasspath() throws JavaModelException { return new IClasspathEntry[] { JavaCore.newSourceEntry(getProject() .getFullPath()) }; } /** * Returns a default output location. This is the project bin folder */ protected IPath defaultOutputLocation() throws JavaModelException { return null; // getProject().getFullPath().append("bin"); // //$NON-NLS-1$ } /** * Returns the XML String encoding of the class path. */ protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean indent) throws JavaModelException { try { ByteArrayOutputStream s = new ByteArrayOutputStream(); OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$ XMLWriter xmlWriter = new XMLWriter(writer); xmlWriter.startTag("classpath", indent); //$NON-NLS-1$ for (int i = 0; i < classpath.length; ++i) { ((ClasspathEntry) classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true); } if (outputLocation != null) { outputLocation = outputLocation.removeFirstSegments(1); outputLocation = outputLocation.makeRelative(); HashMap parameters = new HashMap(); parameters .put( "kind", ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT));//$NON-NLS-1$ parameters.put("path", String.valueOf(outputLocation));//$NON-NLS-1$ xmlWriter.printTag( "classpathentry", parameters, indent, true, true);//$NON-NLS-1$ } xmlWriter.endTag("classpath", indent);//$NON-NLS-1$ writer.flush(); writer.close(); return s.toString("UTF8");//$NON-NLS-1$ } catch (IOException e) { throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); } } /** * Returns the XML String encoding of the class path. */ // protected String encodeClasspath(IClasspathEntry[] classpath, IPath // outputLocation, boolean useLineSeparator) throws JavaModelException { // // Document document = new DocumentImpl(); // Element cpElement = document.createElement("classpath"); //$NON-NLS-1$ // document.appendChild(cpElement); // // for (int i = 0; i < classpath.length; ++i) { // cpElement.appendChild(((ClasspathEntry)classpath[i]).elementEncode(document, // getProject().getFullPath())); // } // // if (outputLocation != null) { // outputLocation = outputLocation.removeFirstSegments(1); // outputLocation = outputLocation.makeRelative(); // Element oElement = document.createElement("classpathentry"); // //$NON-NLS-1$ // oElement.setAttribute("kind", // ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT)); //$NON-NLS-1$ // oElement.setAttribute("path", outputLocation.toString()); //$NON-NLS-1$ // cpElement.appendChild(oElement); // } // // // produce a String output // try { // ByteArrayOutputStream s = new ByteArrayOutputStream(); // OutputFormat format = new OutputFormat(); // if (useLineSeparator) { // format.setIndenting(true); // format.setLineSeparator(System.getProperty("line.separator")); // //$NON-NLS-1$ // } else { // format.setPreserveSpace(true); // } // Serializer serializer = // SerializerFactory.getSerializerFactory(Method.XML).makeSerializer( // new OutputStreamWriter(s, "UTF8"), //$NON-NLS-1$ // format); // serializer.asDOMSerializer().serialize(document); // return s.toString("UTF8"); //$NON-NLS-1$ // } catch (IOException e) { // throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); // } // } /** * Returns true if this handle represents the same Java project as the given * handle. Two handles represent the same project if they are identical or * if they represent a project with the same underlying resource and * occurrence counts. * * @see JavaElement#equals */ public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof JavaProject)) return false; JavaProject other = (JavaProject) o; return getProject().equals(other.getProject()) && occurrenceCount == other.occurrenceCount; } public boolean exists() { if (!hasJavaNature(project)) return false; return super.exists(); } /** * @see IJavaProject */ public IJavaElement findElement(IPath path) 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, '.'); // IPackageFragment[] pkgFragments = // getNameLookup().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 (this.equals(pkgFragment.getParent().getParent())) { // return pkgFragment; // } // } // // default to the first one // return pkgFragments[0]; // } } else if (extension.equalsIgnoreCase("java") //$NON-NLS-1$ || extension.equalsIgnoreCase("class")) { //$NON-NLS-1$ IPath packagePath = path.removeLastSegments(1); String packageName = packagePath.toString().replace( IPath.SEPARATOR, '.'); String typeName = path.lastSegment(); typeName = typeName.substring(0, typeName.length() - extension.length() - 1); String qualifiedName = null; if (packageName.length() > 0) { qualifiedName = packageName + "." + typeName; //$NON-NLS-1$ } else { qualifiedName = typeName; } // IType type = // getNameLookup().findType( // qualifiedName, // false, // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES); // if (type != null) { // return type.getParent(); // } else { return null; // } } else { // unsupported extension return null; } // } catch (JavaModelException e) { // if (e.getStatus().getCode() // == IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST) { // return null; // } else { // throw e; // } // } } /** * @see IJavaProject */ // public IPackageFragment findPackageFragment(IPath path) // throws JavaModelException { // // return findPackageFragment0(JavaProject.canonicalizedPath(path)); // } // // /** // * non path canonicalizing version // */ // public IPackageFragment findPackageFragment0(IPath path) // throws JavaModelException { // // return getNameLookup().findPackageFragment(path); // } /** * @see IJavaProject */ public IPackageFragmentRoot findPackageFragmentRoot(IPath path) throws JavaModelException { return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path)); } /** * no path canonicalization */ public IPackageFragmentRoot findPackageFragmentRoot0(IPath path) throws JavaModelException { IPackageFragmentRoot[] allRoots = this.getAllPackageFragmentRoots(); if (!path.isAbsolute()) { throw new IllegalArgumentException(Util.bind("path.mustBeAbsolute")); //$NON-NLS-1$ } for (int i = 0; i < allRoots.length; i++) { IPackageFragmentRoot classpathRoot = allRoots[i]; if (classpathRoot.getPath().equals(path)) { return classpathRoot; } } return null; } /** * @see IJavaProject */ public IPackageFragmentRoot[] findPackageFragmentRoots(IClasspathEntry entry) { try { IClasspathEntry[] classpath = this.getRawClasspath(); for (int i = 0, length = classpath.length; i < length; i++) { if (classpath[i].equals(entry)) { // entry may need to be // resolved return computePackageFragmentRoots(getResolvedClasspath( new IClasspathEntry[] { entry }, null, true, false, null/* no reverse map */), false); // don't // retrieve // exported // roots } } } catch (JavaModelException e) { } return new IPackageFragmentRoot[] {}; } /** * @see IJavaProject#findType(String) */ // public IType findType(String fullyQualifiedName) throws // JavaModelException { // IType type = // this.getNameLookup().findType( // fullyQualifiedName, // false, // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES); // if (type == null) { // // try to find enclosing type // int lastDot = fullyQualifiedName.lastIndexOf('.'); // if (lastDot == -1) return null; // type = this.findType(fullyQualifiedName.substring(0, lastDot)); // if (type != null) { // type = type.getType(fullyQualifiedName.substring(lastDot+1)); // if (!type.exists()) { // return null; // } // } // } // return type; // } /** * @see IJavaProject#findType(String, String) */ // public IType findType(String packageName, String typeQualifiedName) // throws JavaModelException { // return // this.getNameLookup().findType( // typeQualifiedName, // packageName, // false, // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES); // } // /** * Remove all markers denoting classpath problems */ protected void flushClasspathProblemMarkers(boolean flushCycleMarkers, boolean flushClasspathFormatMarkers) { try { IProject project = getProject(); if (project.exists()) { IMarker[] markers = 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) { marker.delete(); } else { String cycleAttr = (String) marker .getAttribute(IJavaModelMarker.CYCLE_DETECTED); String classpathFileFormatAttr = (String) marker .getAttribute(IJavaModelMarker.CLASSPATH_FILE_FORMAT); if ((flushCycleMarkers == (cycleAttr != null && cycleAttr .equals("true"))) //$NON-NLS-1$ && (flushClasspathFormatMarkers == (classpathFileFormatAttr != null && classpathFileFormatAttr .equals("true")))) { //$NON-NLS-1$ marker.delete(); } } } } } catch (CoreException e) { } } // /** // * @see Openable // */ // protected boolean generateInfos( // OpenableElementInfo info, // IProgressMonitor pm, // Map newElements, // IResource underlyingResource) throws JavaModelException { // // boolean validInfo = false; // try { // if (getProject().isOpen()) { // // put the info now, because computing the roots requires it // JavaModelManager.getJavaModelManager().putInfo(this, info); // // // compute the pkg fragment roots // updatePackageFragmentRoots(); // // // remember the timestamps of external libraries the first time they are // looked up // IClasspathEntry[] resolvedClasspath = getResolvedClasspath(true/*ignore // unresolved variable*/); // for (int i = 0, length = resolvedClasspath.length; i < length; i++) { // IClasspathEntry entry = resolvedClasspath[i]; // if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { // IPath path = entry.getPath(); // Object target = // JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, // true); // if (target instanceof java.io.File) { // Map externalTimeStamps = // JavaModelManager.getJavaModelManager().deltaProcessor.externalTimeStamps; // if (externalTimeStamps.get(path) == null) { // long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target); // externalTimeStamps.put(path, new Long(timestamp)); // } // } // } // } // // // only valid if reaches here // validInfo = true; // } // } finally { // if (!validInfo) // JavaModelManager.getJavaModelManager().removeInfo(this); // } // return validInfo; // } /** * @see IJavaProject */ public IPackageFragmentRoot[] getAllPackageFragmentRoots() throws JavaModelException { return computePackageFragmentRoots(getResolvedClasspath(true), true); } /** * Returns the classpath entry that refers to the given path or * null if there is no reference to the path. */ public IClasspathEntry getClasspathEntryFor(IPath path) throws JavaModelException { IClasspathEntry[] entries = getExpandedClasspath(true); for (int i = 0; i < entries.length; i++) { if (entries[i].getPath().equals(path)) { return entries[i]; } } return null; } /* * Returns the cycle marker associated with this project or null if none. */ public IMarker getCycleMarker() { try { IProject project = getProject(); if (project.exists()) { IMarker[] markers = project.findMarkers( IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); for (int i = 0, length = markers.length; i < length; i++) { IMarker marker = markers[i]; String cycleAttr = (String) marker .getAttribute(IJavaModelMarker.CYCLE_DETECTED); if (cycleAttr != null && cycleAttr.equals("true")) { //$NON-NLS-1$ return marker; } } } } catch (CoreException e) { } return null; } /** * @see IJavaElement */ public int getElementType() { return JAVA_PROJECT; } /** * This is a helper method returning the expanded classpath for the project, * as a list of classpath entries, where all classpath variable entries have * been resolved and substituted with their final target entries. All * project exports have been appended to project entries. * * @param ignoreUnresolvedVariable * boolean * @return IClasspathEntry[] * @throws JavaModelException */ public IClasspathEntry[] getExpandedClasspath( boolean ignoreUnresolvedVariable) throws JavaModelException { return getExpandedClasspath(ignoreUnresolvedVariable, false/* don't create markers */, null, null); } /* * @see JavaElement */ public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) { switch (token.charAt(0)) { case JEM_COUNT: return getHandleUpdatingCountFromMemento(memento, owner); case JEM_PACKAGEFRAGMENTROOT: String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH; token = null; while (memento.hasMoreTokens()) { token = memento.nextToken(); char firstChar = token.charAt(0); if (firstChar != JEM_PACKAGEFRAGMENT && firstChar != JEM_COUNT) { rootPath += token; } else { break; } } JavaElement root = (JavaElement) getPackageFragmentRoot(new Path( rootPath)); if (token != null && token.charAt(0) == JEM_PACKAGEFRAGMENT) { return root.getHandleFromMemento(token, memento, owner); } else { return root.getHandleFromMemento(memento, owner); } } return null; } /** * Returns the char that marks the start of this handles * contribution to a memento. */ protected char getHandleMementoDelimiter() { return JEM_JAVAPROJECT; } /** * Internal variant which can create marker on project for invalid entries, * it will also perform classpath expansion in presence of project * prerequisites exporting their entries. * * @param ignoreUnresolvedVariable * boolean * @param generateMarkerOnError * boolean * @param preferredClasspaths * Map * @param preferredOutputs * Map * @return IClasspathEntry[] * @throws JavaModelException */ public IClasspathEntry[] getExpandedClasspath( boolean ignoreUnresolvedVariable, boolean generateMarkerOnError, Map preferredClasspaths, Map preferredOutputs) throws JavaModelException { ObjectVector accumulatedEntries = new ObjectVector(); computeExpandedClasspath(this, ignoreUnresolvedVariable, generateMarkerOnError, new HashSet(5), accumulatedEntries, preferredClasspaths, preferredOutputs); IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries .size()]; accumulatedEntries.copyInto(expandedPath); return expandedPath; } // /** // * Internal variant which can create marker on project for invalid // entries, // * it will also perform classpath expansion in presence of project // prerequisites // * exporting their entries. // */ // public IClasspathEntry[] getExpandedClasspath( // boolean ignoreUnresolvedVariable, // boolean generateMarkerOnError) throws JavaModelException { // // ObjectVector accumulatedEntries = new ObjectVector(); // computeExpandedClasspath(this, ignoreUnresolvedVariable, // generateMarkerOnError, new HashSet(5), accumulatedEntries); // // IClasspathEntry[] expandedPath = new // IClasspathEntry[accumulatedEntries.size()]; // accumulatedEntries.copyInto(expandedPath); // // return expandedPath; // } /** * Find the specific Java command amongst the build spec of a given * description */ private ICommand getJavaCommand(IProjectDescription description) throws CoreException { ICommand[] commands = description.getBuildSpec(); for (int i = 0; i < commands.length; ++i) { if (commands[i].getBuilderName().equals( PHPeclipsePlugin.BUILDER_PARSER_ID)) { return commands[i]; } } return null; } /** * Convenience method that returns the specific type of info for a Java * project. */ protected JavaProjectElementInfo getJavaProjectElementInfo() throws JavaModelException { return (JavaProjectElementInfo) getElementInfo(); } /** * @see IJavaProject */ public NameLookup getNameLookup() throws JavaModelException { JavaProjectElementInfo info = getJavaProjectElementInfo(); // lock on the project info to avoid race condition synchronized (info) { NameLookup nameLookup; if ((nameLookup = info.getNameLookup()) == null) { info.setNameLookup(nameLookup = new NameLookup(this)); } return nameLookup; } } /* * Returns a new name lookup. This name lookup first looks in the given * working copies. */ public NameLookup newNameLookup(ICompilationUnit[] workingCopies) throws JavaModelException { //JavaProjectElementInfo info = getJavaProjectElementInfo(); // lock on the project info to avoid race condition while computing the // pkg fragment roots and package fragment caches // synchronized(info){ // return new NameLookup(info.getAllPackageFragmentRoots(this), // info.getAllPackageFragments(this), workingCopies); // } return null; } /* * 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 = JavaModelManager.getJavaModelManager(); ICompilationUnit[] workingCopies = owner == null ? null : manager .getWorkingCopies(owner, true/* add primary WCs */); return newNameLookup(workingCopies); } // // /** // * Returns an array of non-java resources contained in the receiver. // */ // public Object[] getNonJavaResources() throws JavaModelException { // // return ((JavaProjectElementInfo) // getElementInfo()).getNonJavaResources(this); // } /** * @see net.sourceforge.phpdt.core.IJavaProject#getOption(String, boolean) */ public String getOption(String optionName, boolean inheritJavaCoreOptions) { if (JavaModelManager.OptionNames.contains(optionName)) { Preferences preferences = getPreferences(); if (preferences == null || preferences.isDefault(optionName)) { return inheritJavaCoreOptions ? JavaCore.getOption(optionName) : null; } return preferences.getString(optionName).trim(); } return null; } /** * @see net.sourceforge.phpdt.core.IJavaProject#getOptions(boolean) */ public Map getOptions(boolean inheritJavaCoreOptions) { // initialize to the defaults from JavaCore options pool Map options = inheritJavaCoreOptions ? JavaCore.getOptions() : new Hashtable(5); Preferences preferences = getPreferences(); if (preferences == null) return options; // cannot do better (non-Java project) HashSet optionNames = JavaModelManager.OptionNames; // get preferences set to their default if (inheritJavaCoreOptions) { String[] defaultPropertyNames = preferences.defaultPropertyNames(); for (int i = 0; i < defaultPropertyNames.length; i++) { String propertyName = defaultPropertyNames[i]; if (optionNames.contains(propertyName)) { options.put(propertyName, preferences.getDefaultString( propertyName).trim()); } } } // get custom preferences not set to their default String[] propertyNames = preferences.propertyNames(); for (int i = 0; i < propertyNames.length; i++) { String propertyName = propertyNames[i]; if (optionNames.contains(propertyName)) { options.put(propertyName, preferences.getString(propertyName) .trim()); } } return options; } /** * @see IJavaProject */ // public IPath getOutputLocation() throws JavaModelException { // // JavaModelManager.PerProjectInfo perProjectInfo = // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project); // IPath outputLocation = perProjectInfo.outputLocation; // if (outputLocation != null) return outputLocation; // // // force to read classpath - will position output location as well // this.getRawClasspath(); // outputLocation = perProjectInfo.outputLocation; // if (outputLocation == null) { // return defaultOutputLocation(); // } // return outputLocation; // } /** * @see IJavaProject */ public IPath getOutputLocation() throws JavaModelException { // Do not create marker but log problems while getting output location return this.getOutputLocation(false, true); } /** * @param createMarkers * boolean * @param logProblems * boolean * @return IPath * @throws JavaModelException */ public IPath getOutputLocation(boolean createMarkers, boolean logProblems) throws JavaModelException { JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo(); IPath outputLocation = perProjectInfo.outputLocation; if (outputLocation != null) return outputLocation; // force to read classpath - will position output location as well this.getRawClasspath(createMarkers, logProblems); outputLocation = perProjectInfo.outputLocation; if (outputLocation == null) { return defaultOutputLocation(); } return outputLocation; } /** * @return A handle to the package fragment root identified by the given * path. This method is handle-only and the element may or may not * exist. Returns null if unable to generate a handle * from the path (for example, an absolute path that has less than 1 * segment. The path may be relative or absolute. */ public IPackageFragmentRoot getPackageFragmentRoot(IPath path) { if (!path.isAbsolute()) { path = getPath().append(path); } int segmentCount = path.segmentCount(); switch (segmentCount) { case 0: return null; case 1: // default root return getPackageFragmentRoot(getProject()); default: // a path ending with .jar/.zip is still ambiguous and could still // resolve to a source/lib folder // thus will try to guess based on existing resource // if (ProjectPrefUtil.isArchiveFileName(path.lastSegment())) { // IResource resource = // getProject().getWorkspace().getRoot().findMember(path); // if (resource != null && resource.getType() == IResource.FOLDER){ // return getPackageFragmentRoot(resource); // } // return getPackageFragmentRoot0(path); // } else { return getPackageFragmentRoot(getProject().getWorkspace().getRoot() .getFolder(path)); // } } } /** * The path is known to match a source/library folder entry. */ public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) { if (path.segmentCount() == 1) { // default project root return getPackageFragmentRoot(getProject()); } return getPackageFragmentRoot(getProject().getWorkspace().getRoot() .getFolder(path)); } /** * @see IJavaProject */ public IPackageFragmentRoot getPackageFragmentRoot(IResource resource) { switch (resource.getType()) { case IResource.FILE: // if (ProjectPrefUtil.isArchiveFileName(resource.getName())) { // return new JarPackageFragmentRoot(resource, this); // } else { return null; // } case IResource.FOLDER: return new PackageFragmentRoot(resource, this, resource.getName()); case IResource.PROJECT: return new PackageFragmentRoot(resource, this, ""); //$NON-NLS-1$ default: return null; } } /** * @see IJavaProject */ // public IPackageFragmentRoot getPackageFragmentRoot(String jarPath) { // // return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new // Path(jarPath))); // } // // /** // * no path canonicalization // */ // public IPackageFragmentRoot getPackageFragmentRoot0(IPath jarPath) { // // return new JarPackageFragmentRoot(jarPath, this); // } /** * @see IJavaProject */ public IPackageFragmentRoot[] getPackageFragmentRoots() throws JavaModelException { Object[] children; int length; IPackageFragmentRoot[] roots; System.arraycopy(children = getChildren(), 0, roots = new IPackageFragmentRoot[length = children.length], 0, length); return roots; } /** * @see IJavaProject * @deprecated */ public IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry) { return findPackageFragmentRoots(entry); } /** * Returns the package fragment root prefixed by the given path, or an empty * collection if there are no such elements in the model. */ protected IPackageFragmentRoot[] getPackageFragmentRoots(IPath path) throws JavaModelException { IPackageFragmentRoot[] roots = getAllPackageFragmentRoots(); ArrayList matches = new ArrayList(); for (int i = 0; i < roots.length; ++i) { if (path.isPrefixOf(roots[i].getPath())) { matches.add(roots[i]); } } IPackageFragmentRoot[] copy = new IPackageFragmentRoot[matches.size()]; matches.toArray(copy); return copy; } /** * @see IJavaProject */ public IPackageFragment[] getPackageFragments() throws JavaModelException { IPackageFragmentRoot[] roots = getPackageFragmentRoots(); return getPackageFragmentsInRoots(roots); } /** * Returns all the package fragments found in the specified package fragment * 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(); for (int j = 0; j < rootFragments.length; j++) { frags.add(rootFragments[j]); } } catch (JavaModelException e) { // do nothing } } IPackageFragment[] fragments = new IPackageFragment[frags.size()]; frags.toArray(fragments); return fragments; } /* * @see IJavaElement */ public IPath getPath() { return this.getProject().getFullPath(); } public JavaModelManager.PerProjectInfo getPerProjectInfo() throws JavaModelException { return JavaModelManager.getJavaModelManager() .getPerProjectInfoCheckExistence(this.project); } /** * @see IJavaProject */ public IProject getProject() { return project; } /** * Sets the underlying kernel project of this Java project, and fills in its * parent and name. Called by IProject.getNature(). * * @see IProjectNature#setProject(IProject) */ public void setProject(IProject project) { this.project = project; this.parent = JavaModelManager.getJavaModelManager().getJavaModel(); this.name = project.getName(); } protected IProject getProject(String name) { return PHPeclipsePlugin.getWorkspace().getRoot().getProject(name); } public List getReferencedProjects() { List referencedProjects = new ArrayList(); Iterator iterator = getLoadPathEntries().iterator(); while (iterator.hasNext()) { LoadPathEntry pathEntry = (LoadPathEntry) iterator.next(); if (pathEntry.getType() == LoadPathEntry.TYPE_PROJECT) referencedProjects.add(pathEntry.getProject()); } return referencedProjects; } /** * Returns the project custom preference pool. Project preferences may * include custom encoding. */ public Preferences getPreferences() { IProject project = getProject(); if (!JavaProject.hasJavaNature(project)) return null; JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager .getJavaModelManager().getPerProjectInfo(project, true); Preferences preferences = perProjectInfo.preferences; if (preferences != null) return preferences; preferences = loadPreferences(); if (preferences == null) preferences = new Preferences(); perProjectInfo.preferences = preferences; return preferences; } /** * @see IJavaProject */ // public IClasspathEntry[] getRawClasspath() throws JavaModelException { // // JavaModelManager.PerProjectInfo perProjectInfo = // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project); // IClasspathEntry[] classpath = perProjectInfo.classpath; // if (classpath != null) return classpath; // classpath = this.readClasspathFile(false/*don't create markers*/, // true/*log problems*/); // // // extract out the output location // IPath outputLocation = null; // if (classpath != null && classpath.length > 0) { // IClasspathEntry entry = classpath[classpath.length - 1]; // if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { // outputLocation = entry.getPath(); // IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1]; // System.arraycopy(classpath, 0, copy, 0, copy.length); // classpath = copy; // } // } // if (classpath == null) { // return defaultClasspath(); // } // /* Disable validate: classpath can contain CP variables and container // that need to be resolved // if (classpath != INVALID_CLASSPATH // && !JavaConventions.validateClasspath(this, classpath, // outputLocation).isOK()) { // classpath = INVALID_CLASSPATH; // } // */ // perProjectInfo.classpath = classpath; // perProjectInfo.outputLocation = outputLocation; // return classpath; // } /** * @see IJavaProject */ public IClasspathEntry[] getRawClasspath() throws JavaModelException { // Do not create marker but log problems while getting raw classpath return getRawClasspath(false, true); } /* * Internal variant allowing to parameterize problem creation/logging */ public IClasspathEntry[] getRawClasspath(boolean createMarkers, boolean logProblems) throws JavaModelException { JavaModelManager.PerProjectInfo perProjectInfo = null; IClasspathEntry[] classpath; if (createMarkers) { this.flushClasspathProblemMarkers(false/* cycle */, true/* format */); classpath = this.readClasspathFile(createMarkers, logProblems); } else { perProjectInfo = getPerProjectInfo(); classpath = perProjectInfo.rawClasspath; if (classpath != null) return classpath; classpath = this.readClasspathFile(createMarkers, logProblems); } // extract out the output location IPath outputLocation = null; if (classpath != null && classpath.length > 0) { IClasspathEntry entry = classpath[classpath.length - 1]; if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { outputLocation = entry.getPath(); IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1]; System.arraycopy(classpath, 0, copy, 0, copy.length); classpath = copy; } } if (classpath == null) { return defaultClasspath(); } /* * Disable validate: classpath can contain CP variables and container * that need to be resolved if (classpath != INVALID_CLASSPATH && * !JavaConventions.validateClasspath(this, classpath, * outputLocation).isOK()) { classpath = INVALID_CLASSPATH; } */ if (!createMarkers) { perProjectInfo.rawClasspath = classpath; perProjectInfo.outputLocation = outputLocation; } return classpath; } /** * @see IJavaProject#getRequiredProjectNames */ public String[] getRequiredProjectNames() throws JavaModelException { return this.projectPrerequisites(getResolvedClasspath(true)); } /** * @see IJavaProject */ public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry) throws JavaModelException { return this.getResolvedClasspath(ignoreUnresolvedEntry, false); // generateMarkerOnError } /** * Internal variant which can create marker on project for invalid entries * and caches the resolved classpath on perProjectInfo */ public IClasspathEntry[] getResolvedClasspath( boolean ignoreUnresolvedEntry, boolean generateMarkerOnError) throws JavaModelException { return getResolvedClasspath(ignoreUnresolvedEntry, generateMarkerOnError, true // returnResolutionInProgress ); // JavaModelManager manager = JavaModelManager.getJavaModelManager(); // JavaModelManager.PerProjectInfo perProjectInfo = // manager.getPerProjectInfoCheckExistence(project); // // // reuse cache if not needing to refresh markers or checking bound // variables // if (ignoreUnresolvedEntry && !generateMarkerOnError && perProjectInfo // != null){ // // resolved path is cached on its info // IClasspathEntry[] infoPath = perProjectInfo.lastResolvedClasspath; // if (infoPath != null) return infoPath; // } // Map reverseMap = perProjectInfo == null ? null : new HashMap(5); // IClasspathEntry[] resolvedPath = getResolvedClasspath( // getRawClasspath(), // generateMarkerOnError ? getOutputLocation() : null, // ignoreUnresolvedEntry, // generateMarkerOnError, // reverseMap); // // if (perProjectInfo != null){ // if (perProjectInfo.classpath == null // .classpath file could not be // read // && generateMarkerOnError // && JavaProject.hasJavaNature(project)) { // this.createClasspathProblemMarker(new JavaModelStatus( // IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT, // Util.bind("classpath.cannotReadClasspathFile", // this.getElementName()))); //$NON-NLS-1$ // } // // perProjectInfo.lastResolvedClasspath = resolvedPath; // perProjectInfo.resolvedPathToRawEntries = reverseMap; // } // return resolvedPath; } /* * Internal variant which can create marker on project for invalid entries * and caches the resolved classpath on perProjectInfo. If requested, return * a special classpath (RESOLUTION_IN_PROGRESS) if the classpath is being * resolved. */ public IClasspathEntry[] getResolvedClasspath( boolean ignoreUnresolvedEntry, boolean generateMarkerOnError, boolean returnResolutionInProgress) throws JavaModelException { JavaModelManager manager = JavaModelManager.getJavaModelManager(); JavaModelManager.PerProjectInfo perProjectInfo = null; if (ignoreUnresolvedEntry && !generateMarkerOnError) { perProjectInfo = getPerProjectInfo(); if (perProjectInfo != null) { // resolved path is cached on its info IClasspathEntry[] infoPath = perProjectInfo.resolvedClasspath; if (infoPath != null) { return infoPath; } else if (returnResolutionInProgress && manager.isClasspathBeingResolved(this)) { if (JavaModelManager.CP_RESOLVE_VERBOSE) { Util .verbose("CPResolution: reentering raw classpath resolution, will use empty classpath instead" + //$NON-NLS-1$ " project: " + getElementName() + '\n' + //$NON-NLS-1$ " invocation stack trace:"); //$NON-NLS-1$ new Exception("").printStackTrace(System.out); //$NON-NLS-1$ } return RESOLUTION_IN_PROGRESS; } } } Map reverseMap = perProjectInfo == null ? null : new HashMap(5); IClasspathEntry[] resolvedPath = null; boolean nullOldResolvedCP = perProjectInfo != null && perProjectInfo.resolvedClasspath == null; try { // protect against misbehaving clients (see // https://bugs.eclipse.org/bugs/show_bug.cgi?id=61040) if (nullOldResolvedCP) manager.setClasspathBeingResolved(this, true); resolvedPath = getResolvedClasspath(getRawClasspath( generateMarkerOnError, !generateMarkerOnError), generateMarkerOnError ? getOutputLocation() : null, ignoreUnresolvedEntry, generateMarkerOnError, reverseMap); } finally { if (nullOldResolvedCP) perProjectInfo.resolvedClasspath = null; } if (perProjectInfo != null) { if (perProjectInfo.rawClasspath == null // .classpath file could not // be read && generateMarkerOnError && JavaProject.hasJavaNature(this.project)) { // flush .classpath format markers (bug 39877), but only when // file cannot be read (bug 42366) this.flushClasspathProblemMarkers(false, true); this .createClasspathProblemMarker(new JavaModelStatus( IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT, Util .bind( "classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$ } perProjectInfo.resolvedClasspath = resolvedPath; perProjectInfo.resolvedPathToRawEntries = reverseMap; manager.setClasspathBeingResolved(this, false); } return resolvedPath; } /** * Internal variant which can process any arbitrary classpath */ public IClasspathEntry[] getResolvedClasspath( IClasspathEntry[] classpathEntries, IPath projectOutputLocation, // only // set // if // needing // full // classpath // validation // (and // markers) boolean ignoreUnresolvedEntry, // if unresolved entries are met, // should it trigger initializations boolean generateMarkerOnError, Map reverseMap) // can be null if // not interested in // reverse mapping throws JavaModelException { IJavaModelStatus status; if (generateMarkerOnError) { flushClasspathProblemMarkers(false, false); } int length = classpathEntries.length; ArrayList resolvedEntries = new ArrayList(); for (int i = 0; i < length; i++) { IClasspathEntry rawEntry = classpathEntries[i]; IPath resolvedPath; status = null; /* validation if needed */ // if (generateMarkerOnError || !ignoreUnresolvedEntry) { // status = JavaConventions.validateClasspathEntry(this, rawEntry, // false); // if (generateMarkerOnError && !status.isOK()) // createClasspathProblemMarker(status); // } switch (rawEntry.getEntryKind()) { case IClasspathEntry.CPE_VARIABLE: IClasspathEntry resolvedEntry = JavaCore .getResolvedClasspathEntry(rawEntry); if (resolvedEntry == null) { if (!ignoreUnresolvedEntry) throw new JavaModelException(status); } else { if (reverseMap != null && reverseMap.get(resolvedPath = resolvedEntry .getPath()) == null) reverseMap.put(resolvedPath, rawEntry); resolvedEntries.add(resolvedEntry); } break; // case IClasspathEntry.CPE_CONTAINER : // // IClasspathContainer container = // PHPCore.getClasspathContainer(rawEntry.getPath(), this); // if (container == null){ // if (!ignoreUnresolvedEntry) throw new JavaModelException(status); // break; // } // // IClasspathEntry[] containerEntries = // container.getClasspathEntries(); // if (containerEntries == null) break; // // // container was bound // for (int j = 0, containerLength = containerEntries.length; j < // containerLength; j++){ // IClasspathEntry cEntry = containerEntries[j]; // // if (generateMarkerOnError) { // IJavaModelStatus containerStatus = // JavaConventions.validateClasspathEntry(this, cEntry, false); // if (!containerStatus.isOK()) // createClasspathProblemMarker(containerStatus); // } // // if container is exported, then its nested entries must in turn // be exported (21749) // if (rawEntry.isExported()){ // cEntry = new ClasspathEntry(cEntry.getContentKind(), // cEntry.getEntryKind(), cEntry.getPath(), // cEntry.getExclusionPatterns(), cEntry.getSourceAttachmentPath(), // cEntry.getSourceAttachmentRootPath(), cEntry.getOutputLocation(), // true); // duplicate container entry for tagging it as exported // } // if (reverseMap != null && reverseMap.get(resolvedPath = // cEntry.getPath()) == null) reverseMap.put(resolvedPath, // rawEntry); // resolvedEntries.add(cEntry); // } // break; default: if (reverseMap != null && reverseMap.get(resolvedPath = rawEntry.getPath()) == null) reverseMap.put(resolvedPath, rawEntry); resolvedEntries.add(rawEntry); } } IClasspathEntry[] resolvedPath = new IClasspathEntry[resolvedEntries .size()]; resolvedEntries.toArray(resolvedPath); // if (generateMarkerOnError && projectOutputLocation != null) { // status = JavaConventions.validateClasspath(this, resolvedPath, // projectOutputLocation); // if (!status.isOK()) createClasspathProblemMarker(status); // } return resolvedPath; } /* * @see IJavaElement */ public IResource getResource() { return this.getProject(); } /** * @see IJavaProject */ public ISearchableNameEnvironment getSearchableNameEnvironment() throws JavaModelException { // JavaProjectElementInfo info = getJavaProjectElementInfo(); // if (info.getSearchableEnvironment() == null) { // info.setSearchableEnvironment(new SearchableEnvironment(this)); // } // return info.getSearchableEnvironment(); return null; } /** * Retrieve a shared property on a project. If the property is not defined, * answers null. Note that it is orthogonal to IResource persistent * properties, and client code has to decide which form of storage to use * appropriately. Shared properties produce real resource files which can be * shared through a VCM onto a server. Persistent properties are not * shareable. * * @see JavaProject#setSharedProperty(String, String) */ public String getSharedProperty(String key) throws CoreException { String property = null; IFile rscFile = getProject().getFile(key); if (rscFile.exists()) { property = new String(Util.getResourceContentsAsByteArray(rscFile)); } return property; } /** * @see JavaElement */ // public SourceMapper getSourceMapper() { // // return null; // } /** * @see IJavaElement */ public IResource getUnderlyingResource() throws JavaModelException { if (!exists()) throw newNotPresentException(); return getProject(); } /** * @see IJavaProject */ public boolean hasBuildState() { return JavaModelManager.getJavaModelManager().getLastBuiltState( this.getProject(), null) != null; } /** * @see IJavaProject */ public boolean hasClasspathCycle(IClasspathEntry[] preferredClasspath) { HashSet cycleParticipants = new HashSet(); updateCycleParticipants(preferredClasspath, new ArrayList(2), cycleParticipants, ResourcesPlugin.getWorkspace().getRoot(), new HashSet(2)); return !cycleParticipants.isEmpty(); } public boolean hasCycleMarker() { return this.getCycleMarker() != null; } public int hashCode() { return project.hashCode(); } /** * Returns true if the given project is accessible and it has a java nature, * otherwise false. */ public static boolean hasJavaNature(IProject project) { try { return project.hasNature(PHPeclipsePlugin.PHP_NATURE_ID); } catch (CoreException e) { // project does not exist or is not open } return false; } /** * Answers true if the project potentially contains any source. A project * which has no source is immutable. */ public boolean hasSource() { // look if any source folder on the classpath // no need for resolved path given source folder cannot be abstracted IClasspathEntry[] entries; try { entries = this.getRawClasspath(); } catch (JavaModelException e) { return true; // unsure } for (int i = 0, max = entries.length; i < max; i++) { if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) { return true; } } return false; } /** * Compare current classpath with given one to see if any different. Note * that the argument classpath contains its binary output. */ public boolean isClasspathEqualsTo(IClasspathEntry[] newClasspath, IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput) throws JavaModelException { if (otherClasspathWithOutput != null && otherClasspathWithOutput.length > 0) { int length = otherClasspathWithOutput.length; if (length == newClasspath.length + 1) { // output is amongst file entries (last one) // compare classpath entries for (int i = 0; i < length - 1; i++) { if (!otherClasspathWithOutput[i].equals(newClasspath[i])) return false; } // compare binary outputs IClasspathEntry output = otherClasspathWithOutput[length - 1]; if (output.getContentKind() == ClasspathEntry.K_OUTPUT && output.getPath().equals(newOutputLocation)) return true; } } return false; } /* * @see IJavaProject */ public boolean isOnClasspath(IJavaElement element) { IPath path = element.getPath(); switch (element.getElementType()) { case IJavaElement.PACKAGE_FRAGMENT_ROOT: if (!((IPackageFragmentRoot) element).isArchive()) { // ensure that folders are only excluded if all of their // children are excluded path = path.append("*"); //$NON-NLS-1$ } break; case IJavaElement.PACKAGE_FRAGMENT: if (!((IPackageFragmentRoot) element.getParent()).isArchive()) { // ensure that folders are only excluded if all of their // children are excluded path = path.append("*"); //$NON-NLS-1$ } break; } return this.isOnClasspath(path); } private boolean isOnClasspath(IPath path) { IClasspathEntry[] classpath; try { classpath = this .getResolvedClasspath(true/* ignore unresolved variable */); } catch (JavaModelException e) { return false; // not a Java project } for (int i = 0; i < classpath.length; i++) { IClasspathEntry entry = classpath[i]; if (entry.getPath().isPrefixOf(path) && !Util.isExcluded(path, null, ((ClasspathEntry) entry) .fullExclusionPatternChars(), true)) { return true; } } return false; } /* * @see IJavaProject */ public boolean isOnClasspath(IResource resource) { IPath path = resource.getFullPath(); // ensure that folders are only excluded if all of their children are // excluded if (resource.getType() == IResource.FOLDER) { path = path.append("*"); //$NON-NLS-1$ } return this.isOnClasspath(path); } private IPath getPluginWorkingLocation() { return this.project.getWorkingLocation(JavaCore.PLUGIN_ID); } /* * load preferences from a shareable format (VCM-wise) */ public Preferences loadPreferences() { Preferences preferences = new Preferences(); // File prefFile = // getProject().getLocation().append(PREF_FILENAME).toFile(); IPath projectMetaLocation = getPluginWorkingLocation(); if (projectMetaLocation != null) { File prefFile = projectMetaLocation.append(PREF_FILENAME).toFile(); if (prefFile.exists()) { // load preferences from file InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(prefFile)); preferences.load(in); return preferences; } catch (IOException e) { // problems loading preference store // - quietly ignore } finally { if (in != null) { try { in.close(); } catch (IOException e) { // ignore problems with // close } } } } } return null; } /** * @see IJavaProject#newEvaluationContext */ // public IEvaluationContext newEvaluationContext() { // // return new EvaluationContextWrapper(new EvaluationContext(), this); // } /** * @see IJavaProject */ // public ITypeHierarchy newTypeHierarchy( // IRegion region, // IProgressMonitor monitor) // throws JavaModelException { // // if (region == null) { // throw new // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullRegion"));//$NON-NLS-1$ // } // CreateTypeHierarchyOperation op = // new CreateTypeHierarchyOperation(null, region, this, true); // runOperation(op, monitor); // return op.getResult(); // } /** * @see IJavaProject */ // public ITypeHierarchy newTypeHierarchy( // IType type, // IRegion region, // IProgressMonitor monitor) // throws JavaModelException { // // if (type == null) { // throw new // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullFocusType"));//$NON-NLS-1$ // } // if (region == null) { // throw new // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullRegion"));//$NON-NLS-1$ // } // CreateTypeHierarchyOperation op = // new CreateTypeHierarchyOperation(type, region, this, true); // runOperation(op, monitor); // return op.getResult(); // } // /** // * Open project if resource isn't closed // */ // protected void openWhenClosed(IProgressMonitor pm) throws // JavaModelException { // // if (!this.fProject.isOpen()) { // throw newNotPresentException(); // } else { // super.openWhenClosed(pm); // } // } public String[] projectPrerequisites(IClasspathEntry[] entries) throws JavaModelException { ArrayList prerequisites = new ArrayList(); // need resolution entries = getResolvedClasspath(entries, null, true, false, null/* * no * reverse * map */); for (int i = 0, length = entries.length; i < length; i++) { IClasspathEntry entry = entries[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { prerequisites.add(entry.getPath().lastSegment()); } } int size = prerequisites.size(); if (size == 0) { return NO_PREREQUISITES; } else { String[] result = new String[size]; prerequisites.toArray(result); return result; } } /** * Reads the .classpath file from disk and returns the list of entries it * contains (including output location entry) Returns null if .classfile is * not present. Returns INVALID_CLASSPATH if it has a format problem. */ protected IClasspathEntry[] readClasspathFile(boolean createMarker, boolean logProblems) { try { String xmlClasspath = getSharedProperty(CLASSPATH_FILENAME); if (xmlClasspath == null) return null; return decodeClasspath(xmlClasspath, createMarker, logProblems); } catch (CoreException e) { // file does not exist (or not accessible) if (createMarker && this.getProject().isAccessible()) { this .createClasspathProblemMarker(new JavaModelStatus( IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT, Util .bind( "classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$ } if (logProblems) { Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$ + "/.classpath, will revert to default classpath"); //$NON-NLS-1$ } } return null; } /** * Removes the given builder from the build spec for the given project. */ protected void removeFromBuildSpec(String builderID) throws CoreException { IProjectDescription description = getProject().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); getProject().setDescription(description, null); return; } } } /** * @see JavaElement#rootedAt(IJavaProject) */ public IJavaElement rootedAt(IJavaProject project) { return project; } /** * Answers an ID which is used to distinguish project/entries during package * fragment root computations */ public String rootID() { return "[PRJ]" + this.getProject().getFullPath(); //$NON-NLS-1$ } /** * Saves the classpath in a shareable format (VCM-wise) only when necessary, * that is, if it is semantically different from the existing one in file. * Will never write an identical one. * * @return Return whether the .classpath file was modified. */ public boolean saveClasspath(IClasspathEntry[] newClasspath, IPath newOutputLocation) throws JavaModelException { if (!getProject().exists()) return false; IClasspathEntry[] fileEntries = readClasspathFile( false /* don't create markers */, false/* don't log problems */); if (fileEntries != null && isClasspathEqualsTo(newClasspath, newOutputLocation, fileEntries)) { // no need to save it, it is the same return false; } // actual file saving try { setSharedProperty(CLASSPATH_FILENAME, encodeClasspath(newClasspath, newOutputLocation, true)); return true; } catch (CoreException e) { throw new JavaModelException(e); } } /** * Save project custom preferences to shareable file (.jprefs) */ private void savePreferences(Preferences preferences) { if (!JavaProject.hasJavaNature(this.project)) return; // ignore if (preferences == null || (!preferences.needsSaving() && preferences.propertyNames().length != 0)) { // nothing to save return; } // preferences need to be saved // the preferences file is located in the plug-in's state area // at a well-known name (.jprefs) // File prefFile = // this.project.getLocation().append(PREF_FILENAME).toFile(); File prefFile = getPluginWorkingLocation().append(PREF_FILENAME) .toFile(); if (preferences.propertyNames().length == 0) { // there are no preference settings // rather than write an empty file, just delete any existing file if (prefFile.exists()) { prefFile.delete(); // don't worry if delete unsuccessful } return; } // write file, overwriting an existing one OutputStream out = null; try { // do it as carefully as we know how so that we don't lose/mangle // the setting in times of stress out = new BufferedOutputStream(new FileOutputStream(prefFile)); preferences.store(out, null); } catch (IOException e) { // problems saving preference store - // quietly ignore } finally { if (out != null) { try { out.close(); } catch (IOException e) { // ignore problems with close } } } } /** * Update the Java command in the build spec (replace existing one if * present, add one first if none). */ private void setJavaCommand(IProjectDescription description, ICommand newCommand) throws CoreException { ICommand[] oldCommands = description.getBuildSpec(); ICommand oldJavaCommand = getJavaCommand(description); ICommand[] newCommands; if (oldJavaCommand == null) { // Add a Java build spec before other builders (1FWJK7I) newCommands = new ICommand[oldCommands.length + 1]; System .arraycopy(oldCommands, 0, newCommands, 1, oldCommands.length); newCommands[0] = newCommand; } else { for (int i = 0, max = oldCommands.length; i < max; i++) { if (oldCommands[i] == oldJavaCommand) { oldCommands[i] = newCommand; break; } } newCommands = oldCommands; } // Commit the spec change into the project description.setBuildSpec(newCommands); getProject().setDescription(description, null); } /** * @see net.sourceforge.phpdt.core.IJavaProject#setOptions(Map) */ public void setOptions(Map newOptions) { Preferences preferences; setPreferences(preferences = new Preferences()); // always reset // (26255) if (newOptions != null) { Iterator keys = newOptions.keySet().iterator(); while (keys.hasNext()) { String key = (String) keys.next(); if (!JavaModelManager.OptionNames.contains(key)) continue; // unrecognized option // no filtering for encoding (custom encoding for project is // allowed) String value = (String) newOptions.get(key); preferences.setDefault(key, CUSTOM_DEFAULT_OPTION_VALUE); // empty // string // isn't // the // default // (26251) preferences.setValue(key, value); } } // persist options savePreferences(preferences); } /** * @see IJavaProject */ public void setOutputLocation(IPath path, IProgressMonitor monitor) throws JavaModelException { if (path == null) { throw new IllegalArgumentException(Util.bind("path.nullpath")); //$NON-NLS-1$ } if (path.equals(getOutputLocation())) { return; } this.setRawClasspath(SetClasspathOperation.ReuseClasspath, path, monitor); } /* * Set cached preferences, no preference file is saved, only info is updated */ public void setPreferences(Preferences preferences) { IProject project = getProject(); if (!JavaProject.hasJavaNature(project)) return; // ignore JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager .getJavaModelManager().getPerProjectInfo(project, true); perProjectInfo.preferences = preferences; } /** * @see IJavaProject */ public void setRawClasspath(IClasspathEntry[] entries, IPath outputLocation, IProgressMonitor monitor) throws JavaModelException { setRawClasspath(entries, outputLocation, monitor, true, // canChangeResource // (as per API // contract) getResolvedClasspath(true), // ignoreUnresolvedVariable true, // needValidation true); // need to save } public void setRawClasspath(IClasspathEntry[] newEntries, IPath newOutputLocation, IProgressMonitor monitor, boolean canChangeResource, IClasspathEntry[] oldResolvedPath, boolean needValidation, boolean needSave) throws JavaModelException { JavaModelManager manager = (JavaModelManager) JavaModelManager .getJavaModelManager(); try { IClasspathEntry[] newRawPath = newEntries; if (newRawPath == null) { // are we already with the default // classpath newRawPath = defaultClasspath(); } SetClasspathOperation op = new SetClasspathOperation(this, oldResolvedPath, newRawPath, newOutputLocation, canChangeResource, needValidation, needSave); runOperation(op, monitor); } catch (JavaModelException e) { manager.flush(); throw e; } } /** * @see IJavaProject */ public void setRawClasspath(IClasspathEntry[] entries, IProgressMonitor monitor) throws JavaModelException { setRawClasspath(entries, SetClasspathOperation.ReuseOutputLocation, monitor, true, // canChangeResource (as per API contract) getResolvedClasspath(true), // ignoreUnresolvedVariable true, // needValidation true); // need to save } /** * NOTE: null specifies default classpath, and an empty array * specifies an empty classpath. * * @exception NotPresentException * if this project does not exist. */ // protected void setRawClasspath0(IClasspathEntry[] rawEntries) // throws JavaModelException { // // JavaModelManager.PerProjectInfo info = // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project); // // synchronized (info) { // if (rawEntries != null) { // info.classpath = rawEntries; // } // // // clear cache of resolved classpath // info.lastResolvedClasspath = null; // info.resolvedPathToRawEntries = null; // } // } /** * Record a shared persistent property onto a project. Note that it is * orthogonal to IResource persistent properties, and client code has to * decide which form of storage to use appropriately. Shared properties * produce real resource files which can be shared through a VCM onto a * server. Persistent properties are not shareable. * * shared properties end up in resource files, and thus cannot be modified * during delta notifications (a CoreException would then be thrown). * * @see JavaProject#getSharedProperty(String key) */ public void setSharedProperty(String key, String value) throws CoreException { IFile rscFile = getProject().getFile(key); InputStream inputStream = new ByteArrayInputStream(value.getBytes()); // update the resource content if (rscFile.exists()) { if (rscFile.isReadOnly()) { // provide opportunity to checkout read-only .classpath file // (23984) ResourcesPlugin.getWorkspace().validateEdit( new IFile[] { rscFile }, null); } rscFile.setContents(inputStream, IResource.FORCE, null); } else { rscFile.create(inputStream, IResource.FORCE, null); } } /** * Update cycle markers for all java projects */ public static void updateAllCycleMarkers() throws JavaModelException { // long start = System.currentTimeMillis(); JavaModelManager manager = JavaModelManager.getJavaModelManager(); IJavaProject[] projects = manager.getJavaModel().getJavaProjects(); IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); HashSet cycleParticipants = new HashSet(); HashSet traversed = new HashSet(); int length = projects.length; // compute cycle participants ArrayList prereqChain = new ArrayList(); for (int i = 0; i < length; i++) { JavaProject project = (JavaProject) projects[i]; if (!traversed.contains(project.getPath())) { prereqChain.clear(); project.updateCycleParticipants(null, prereqChain, cycleParticipants, workspaceRoot, traversed); } } // System.out.println("updateAllCycleMarkers: " + // (System.currentTimeMillis() - start) + " ms"); for (int i = 0; i < length; i++) { JavaProject project = (JavaProject) projects[i]; if (cycleParticipants.contains(project.getPath())) { IMarker cycleMarker = project.getCycleMarker(); String circularCPOption = project.getOption( JavaCore.CORE_CIRCULAR_CLASSPATH, true); int circularCPSeverity = JavaCore.ERROR .equals(circularCPOption) ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING; if (cycleMarker != null) { // update existing cycle marker if needed try { int existingSeverity = ((Integer) cycleMarker .getAttribute(IMarker.SEVERITY)).intValue(); if (existingSeverity != circularCPSeverity) { cycleMarker.setAttribute(IMarker.SEVERITY, circularCPSeverity); } } catch (CoreException e) { throw new JavaModelException(e); } } else { // create new marker project .createClasspathProblemMarker(new JavaModelStatus( IJavaModelStatusConstants.CLASSPATH_CYCLE, project)); } } else { project.flushClasspathProblemMarkers(true, false); } } } /** * If a cycle is detected, then cycleParticipants contains all the paths of * projects involved in this cycle (directly and indirectly), no cycle if * the set is empty (and started empty) */ public void updateCycleParticipants(IClasspathEntry[] preferredClasspath, ArrayList prereqChain, HashSet cycleParticipants, IWorkspaceRoot workspaceRoot, HashSet traversed) { IPath path = this.getPath(); prereqChain.add(path); traversed.add(path); try { IClasspathEntry[] classpath = preferredClasspath == null ? getResolvedClasspath(true) : preferredClasspath; 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 index = cycleParticipants.contains(prereqProjectPath) ? 0 : prereqChain.indexOf(prereqProjectPath); if (index >= 0) { // refer to cycle, or in cycle itself for (int size = prereqChain.size(); index < size; index++) { cycleParticipants.add(prereqChain.get(index)); } } else { if (!traversed.contains(prereqProjectPath)) { IResource member = workspaceRoot .findMember(prereqProjectPath); if (member != null && member.getType() == IResource.PROJECT) { JavaProject project = (JavaProject) JavaCore .create((IProject) member); project.updateCycleParticipants(null, prereqChain, cycleParticipants, workspaceRoot, traversed); } } } } } } catch (JavaModelException e) { } prereqChain.remove(path); } /** * Reset the collection of package fragment roots (local ones) - only if * opened. Need to check *all* package fragment roots in order to reset * NameLookup */ public void updatePackageFragmentRoots() { if (this.isOpen()) { try { JavaProjectElementInfo info = getJavaProjectElementInfo(); IClasspathEntry[] classpath = getResolvedClasspath(true); // NameLookup lookup = info.getNameLookup(); // if (lookup != null){ // IPackageFragmentRoot[] oldRoots = // lookup.fPackageFragmentRoots; // IPackageFragmentRoot[] newRoots = // computePackageFragmentRoots(classpath, true); // checkIdentical: { // compare all pkg fragment root lists // if (oldRoots.length == newRoots.length){ // for (int i = 0, length = oldRoots.length; i < length; i++){ // if (!oldRoots[i].equals(newRoots[i])){ // break checkIdentical; // } // } // return; // no need to update // } // } // info.setNameLookup(null); // discard name lookup (hold onto // roots) // } info.setNonJavaResources(null); info.setChildren(computePackageFragmentRoots(classpath, false)); } catch (JavaModelException e) { try { close(); // could not do better } catch (JavaModelException ex) { } } } } public void removeLoadPathEntry(IProject anotherPHPProject) { Iterator entries = getLoadPathEntries().iterator(); while (entries.hasNext()) { LoadPathEntry entry = (LoadPathEntry) entries.next(); if (entry.getType() == LoadPathEntry.TYPE_PROJECT && entry.getProject().getName().equals( anotherPHPProject.getName())) { getLoadPathEntries().remove(entry); fScratched = true; break; } } } public void save() throws CoreException { if (fScratched) { InputStream xmlPath = new ByteArrayInputStream(getLoadPathXML() .getBytes()); IFile loadPathsFile = getLoadPathEntriesFile(); if (!loadPathsFile.exists()) loadPathsFile.create(xmlPath, true, null); else loadPathsFile.setContents(xmlPath, true, false, null); fScratched = false; } } }