1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
13 import java.io.BufferedInputStream;
14 import java.io.BufferedOutputStream;
15 import java.io.ByteArrayInputStream;
16 import java.io.ByteArrayOutputStream;
18 import java.io.FileInputStream;
19 import java.io.FileOutputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.io.OutputStreamWriter;
24 import java.io.StringReader;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Hashtable;
29 import java.util.Iterator;
30 import java.util.List;
33 import javax.xml.parsers.DocumentBuilder;
34 import javax.xml.parsers.DocumentBuilderFactory;
35 import javax.xml.parsers.ParserConfigurationException;
36 import javax.xml.parsers.SAXParserFactory;
38 import net.sourceforge.phpdt.core.IClasspathEntry;
39 import net.sourceforge.phpdt.core.ICompilationUnit;
40 import net.sourceforge.phpdt.core.IJavaElement;
41 import net.sourceforge.phpdt.core.IJavaModelMarker;
42 import net.sourceforge.phpdt.core.IJavaModelStatus;
43 import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
44 import net.sourceforge.phpdt.core.IJavaProject;
45 import net.sourceforge.phpdt.core.IPackageFragment;
46 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
47 import net.sourceforge.phpdt.core.JavaCore;
48 import net.sourceforge.phpdt.core.JavaModelException;
49 import net.sourceforge.phpdt.core.WorkingCopyOwner;
50 import net.sourceforge.phpdt.internal.codeassist.ISearchableNameEnvironment;
51 import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
52 import net.sourceforge.phpdt.internal.core.util.MementoTokenizer;
53 import net.sourceforge.phpdt.internal.core.util.Util;
55 //import net.sourceforge.phpdt.internal.corext.Assert;
56 import org.eclipse.core.runtime.Assert;
57 import net.sourceforge.phpeclipse.LoadPathEntry;
58 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
60 import org.eclipse.core.resources.ICommand;
61 import org.eclipse.core.resources.IFile;
62 import org.eclipse.core.resources.IFolder;
63 import org.eclipse.core.resources.IMarker;
64 import org.eclipse.core.resources.IProject;
65 import org.eclipse.core.resources.IProjectDescription;
66 import org.eclipse.core.resources.IProjectNature;
67 import org.eclipse.core.resources.IResource;
68 import org.eclipse.core.resources.IWorkspace;
69 import org.eclipse.core.resources.IWorkspaceRoot;
70 import org.eclipse.core.resources.ResourcesPlugin;
71 import org.eclipse.core.runtime.AssertionFailedException;
72 import org.eclipse.core.runtime.CoreException;
73 import org.eclipse.core.runtime.IPath;
74 import org.eclipse.core.runtime.IProgressMonitor;
75 import org.eclipse.core.runtime.Path;
76 import org.eclipse.core.runtime.Preferences;
77 import org.eclipse.core.runtime.QualifiedName;
78 import org.w3c.dom.Element;
79 import org.w3c.dom.Node;
80 import org.w3c.dom.NodeList;
81 import org.xml.sax.Attributes;
82 import org.xml.sax.ContentHandler;
83 import org.xml.sax.InputSource;
84 import org.xml.sax.Locator;
85 import org.xml.sax.SAXException;
86 import org.xml.sax.XMLReader;
89 * Handle for a Java Project.
92 * A Java Project internally maintains a devpath that corresponds to the
93 * project's classpath. The classpath may include source folders from the
94 * current project; jars in the current project, other projects, and the local
95 * file system; and binary folders (output location) of other projects. The Java
96 * Model presents source elements corresponding to output .class files in other
97 * projects, and thus uses the devpath rather than the classpath (which is
98 * really a compilation path). The devpath mimics the classpath, except has
99 * source folder entries in place of output locations in external projects.
102 * Each JavaProject has a NameLookup facility that locates elements on by name,
103 * based on the devpath.
107 public class JavaProject extends Openable implements IJavaProject,
111 * Whether the underlying file system is case sensitive.
113 protected static final boolean IS_CASE_SENSITIVE = !new File("Temp").equals(new File("temp")); //$NON-NLS-1$ //$NON-NLS-2$
116 * An empty array of strings indicating that a project doesn't have any
117 * prerequesite projects.
119 protected static final String[] NO_PREREQUISITES = new String[0];
122 * The platform project this <code>IJavaProject</code> is based on
124 protected IProject project;
126 protected List fLoadPathEntries;
128 protected boolean fScratched;
131 * Name of file containing project classpath
133 public static final String CLASSPATH_FILENAME = ".classpath"; //$NON-NLS-1$
136 * Name of file containing custom project preferences
138 public static final String PREF_FILENAME = ".jprefs"; //$NON-NLS-1$
141 * Value of the project's raw classpath if the .classpath file contains
144 public static final IClasspathEntry[] INVALID_CLASSPATH = new IClasspathEntry[0];
146 private static final String CUSTOM_DEFAULT_OPTION_VALUE = "#\r\n\r#custom-non-empty-default-value#\r\n\r#"; //$NON-NLS-1$
149 * Value of project's resolved classpath while it is being resolved
151 private static final IClasspathEntry[] RESOLUTION_IN_PROGRESS = new IClasspathEntry[0];
154 * Returns a canonicalized path from the given external path. Note that the
155 * return path contains the same number of segments and it contains a device
156 * only if the given path contained one.
158 * @see java.io.File for the definition of a canonicalized path
160 public static IPath canonicalizedPath(IPath externalPath) {
162 if (externalPath == null)
165 if (JavaModelManager.VERBOSE) {
167 .println("JAVA MODEL - Canonicalizing " + externalPath.toString()); //$NON-NLS-1$
170 if (IS_CASE_SENSITIVE) {
171 if (JavaModelManager.VERBOSE) {
173 .println("JAVA MODEL - Canonical path is original path (file system is case sensitive)"); //$NON-NLS-1$
178 // if not external path, return original path
179 IWorkspace workspace = ResourcesPlugin.getWorkspace();
180 if (workspace == null)
181 return externalPath; // protection during shutdown (30487)
182 if (workspace.getRoot().findMember(externalPath) != null) {
183 if (JavaModelManager.VERBOSE) {
185 .println("JAVA MODEL - Canonical path is original path (member of workspace)"); //$NON-NLS-1$
190 IPath canonicalPath = null;
192 canonicalPath = new Path(new File(externalPath.toOSString())
193 .getCanonicalPath());
194 } catch (IOException e) {
195 // default to original path
196 if (JavaModelManager.VERBOSE) {
198 .println("JAVA MODEL - Canonical path is original path (IOException)"); //$NON-NLS-1$
204 int canonicalLength = canonicalPath.segmentCount();
205 if (canonicalLength == 0) {
206 // the java.io.File canonicalization failed
207 if (JavaModelManager.VERBOSE) {
209 .println("JAVA MODEL - Canonical path is original path (canonical path is empty)"); //$NON-NLS-1$
212 } else if (externalPath.isAbsolute()) {
213 result = canonicalPath;
215 // if path is relative, remove the first segments that were added by
216 // the java.io.File canonicalization
217 // e.g. 'lib/classes.zip' was converted to
218 // 'd:/myfolder/lib/classes.zip'
219 int externalLength = externalPath.segmentCount();
220 if (canonicalLength >= externalLength) {
221 result = canonicalPath.removeFirstSegments(canonicalLength
224 if (JavaModelManager.VERBOSE) {
226 .println("JAVA MODEL - Canonical path is original path (canonical path is " + canonicalPath.toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
232 // keep device only if it was specified (this is because
233 // File.getCanonicalPath() converts '/lib/classed.zip' to
234 // 'd:/lib/classes/zip')
235 if (externalPath.getDevice() == null) {
236 result = result.setDevice(null);
238 if (JavaModelManager.VERBOSE) {
240 .println("JAVA MODEL - Canonical path is " + result.toString()); //$NON-NLS-1$
246 * Constructor needed for <code>IProject.getNature()</code> and
247 * <code>IProject.addNature()</code>.
249 * @see #setProject(IProject)
251 public JavaProject() {
255 public JavaProject(IProject project, JavaElement parent) {
256 super(parent, project.getName());
257 this.project = project;
260 public void addLoadPathEntry(IProject anotherPHPProject) {
263 LoadPathEntry newEntry = new LoadPathEntry(anotherPHPProject);
264 getLoadPathEntries().add(newEntry);
267 public void configure() throws CoreException {
268 // get project description and then the associated build commands
269 IProjectDescription desc = project.getDescription();
270 ICommand[] commands = desc.getBuildSpec();
272 // determine if builder already associated
273 boolean found = false;
274 for (int i = 0; i < commands.length; ++i) {
275 if (commands[i].getBuilderName().equals(
276 PHPeclipsePlugin.BUILDER_PARSER_ID)) {
282 // add builder if not already in project
284 ICommand command = desc.newCommand();
285 command.setBuilderName(PHPeclipsePlugin.BUILDER_PARSER_ID);
286 ICommand[] newCommands = new ICommand[commands.length + 1];
288 // Add it before other builders.
289 System.arraycopy(commands, 0, newCommands, 1, commands.length);
290 newCommands[0] = command;
291 desc.setBuildSpec(newCommands);
292 project.setDescription(desc, null);
296 protected void loadLoadPathEntries() {
297 fLoadPathEntries = new ArrayList();
299 IFile loadPathsFile = getLoadPathEntriesFile();
301 XMLReader reader = null;
303 reader = SAXParserFactory.newInstance().newSAXParser()
305 reader.setContentHandler(getLoadPathEntriesContentHandler());
306 reader.parse(new InputSource(loadPathsFile.getContents()));
307 } catch (Exception e) {
308 // the file is nonextant or unreadable
312 public List getLoadPathEntries() {
313 if (fLoadPathEntries == null) {
314 loadLoadPathEntries();
317 return fLoadPathEntries;
320 protected ContentHandler getLoadPathEntriesContentHandler() {
321 return new ContentHandler() {
322 public void characters(char[] arg0, int arg1, int arg2)
323 throws SAXException {
326 public void endDocument() throws SAXException {
329 public void endElement(String arg0, String arg1, String arg2)
330 throws SAXException {
333 public void endPrefixMapping(String arg0) throws SAXException {
336 public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
337 throws SAXException {
340 public void processingInstruction(String arg0, String arg1)
341 throws SAXException {
344 public void setDocumentLocator(Locator arg0) {
347 public void skippedEntity(String arg0) throws SAXException {
350 public void startDocument() throws SAXException {
353 public void startElement(String namespaceURI, String localName,
354 String qName, Attributes atts) throws SAXException {
355 if ("pathentry".equals(qName))
356 if ("project".equals(atts.getValue("type"))) {
357 IPath referencedProjectPath = new Path(atts
359 IProject referencedProject = getProject(referencedProjectPath
361 fLoadPathEntries.add(new LoadPathEntry(
366 public void startPrefixMapping(String arg0, String arg1)
367 throws SAXException {
372 protected IFile getLoadPathEntriesFile() {
373 return project.getFile(".loadpath");
376 protected String getLoadPathXML() {
377 StringBuffer buffer = new StringBuffer();
378 buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><loadpath>");
380 Iterator pathEntriesIterator = fLoadPathEntries.iterator();
382 while (pathEntriesIterator.hasNext()) {
383 LoadPathEntry entry = (LoadPathEntry) pathEntriesIterator.next();
384 buffer.append(entry.toXML());
387 buffer.append("</loadpath>");
388 return buffer.toString();
392 * Adds a builder to the build spec for the given project.
394 protected void addToBuildSpec(String builderID) throws CoreException {
396 IProjectDescription description = getProject().getDescription();
397 ICommand javaCommand = getJavaCommand(description);
399 if (javaCommand == null) {
401 // Add a Java command to the build spec
402 ICommand command = description.newCommand();
403 command.setBuilderName(builderID);
404 setJavaCommand(description, command);
411 protected boolean buildStructure(OpenableElementInfo info,
412 IProgressMonitor pm, Map newElements, IResource underlyingResource)
413 throws JavaModelException {
415 // check whether the java project can be opened
416 if (!underlyingResource.isAccessible()) {
417 throw newNotPresentException();
420 //IWorkspace workspace = ResourcesPlugin.getWorkspace();
421 //IWorkspaceRoot wRoot = workspace.getRoot();
422 // cannot refresh cp markers on opening (emulate cp check on startup)
423 // since can create deadlocks (see bug 37274)
424 // IClasspathEntry[] resolvedClasspath =
425 // getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't
426 // generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
428 // // compute the pkg fragment roots
429 // info.setChildren(computePackageFragmentRoots(resolvedClasspath,
432 // // remember the timestamps of external libraries the first time they
434 // for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
435 // IClasspathEntry entry = resolvedClasspath[i];
436 // if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
437 // IPath path = entry.getPath();
438 // Object target = JavaModel.getTarget(wRoot, path, true);
439 // if (target instanceof java.io.File) {
440 // Map externalTimeStamps =
441 // JavaModelManager.getJavaModelManager().deltaState.externalTimeStamps;
442 // if (externalTimeStamps.get(path) == null) {
443 // long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
444 // externalTimeStamps.put(path, new Long(timestamp));
453 protected void closing(Object info) {
455 // // forget source attachment recommendations
456 // Object[] children = ((JavaElementInfo)info).children;
457 // for (int i = 0, length = children.length; i < length; i++) {
458 // Object child = children[i];
459 // if (child instanceof JarPackageFragmentRoot){
460 // ((JarPackageFragmentRoot)child).setSourceAttachmentProperty(null);
467 // protected void closing(Object info) throws JavaModelException {
469 // // forget source attachment recommendations
470 // IPackageFragmentRoot[] roots = this.getPackageFragmentRoots();
471 // // for (int i = 0; i < roots.length; i++) {
472 // // if (roots[i] instanceof JarPackageFragmentRoot){
473 // // ((JarPackageFragmentRoot) roots[i]).setSourceAttachmentProperty(null);
477 // super.closing(info);
481 * Internal computation of an expanded classpath. It will eliminate
482 * duplicates, and produce copies of exported classpath entries to avoid
483 * possible side-effects ever after.
485 private void computeExpandedClasspath(JavaProject initialProject,
486 boolean ignoreUnresolvedVariable, boolean generateMarkerOnError,
487 HashSet rootIDs, ObjectVector accumulatedEntries,
488 Map preferredClasspaths, Map preferredOutputs)
489 throws JavaModelException {
491 String projectRootId = this.rootID();
492 if (rootIDs.contains(projectRootId)) {
493 return; // break cycles if any
495 rootIDs.add(projectRootId);
497 IClasspathEntry[] preferredClasspath = preferredClasspaths != null ? (IClasspathEntry[]) preferredClasspaths
500 IPath preferredOutput = preferredOutputs != null ? (IPath) preferredOutputs
503 IClasspathEntry[] immediateClasspath = preferredClasspath != null ? getResolvedClasspath(
504 preferredClasspath, preferredOutput, ignoreUnresolvedVariable,
505 generateMarkerOnError, null)
506 : getResolvedClasspath(ignoreUnresolvedVariable,
507 generateMarkerOnError, false/*
509 * returnResolutionInProgress
512 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
513 boolean isInitialProject = this.equals(initialProject);
514 for (int i = 0, length = immediateClasspath.length; i < length; i++) {
515 ClasspathEntry entry = (ClasspathEntry) immediateClasspath[i];
516 if (isInitialProject || entry.isExported()) {
517 String rootID = entry.rootID();
518 if (rootIDs.contains(rootID)) {
522 accumulatedEntries.add(entry);
524 // recurse in project to get all its indirect exports (only
525 // consider exported entries from there on)
526 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
527 IResource member = workspaceRoot
528 .findMember(entry.getPath());
529 if (member != null && member.getType() == IResource.PROJECT) { // double
536 IProject projRsc = (IProject) member;
537 if (JavaProject.hasJavaNature(projRsc)) {
538 JavaProject javaProject = (JavaProject) JavaCore
541 .computeExpandedClasspath(
543 ignoreUnresolvedVariable,
545 * no marker when recursing
548 rootIDs, accumulatedEntries,
561 * Internal computation of an expanded classpath. It will eliminate
562 * duplicates, and produce copies of exported classpath entries to avoid
563 * possible side-effects ever after.
565 // private void computeExpandedClasspath(
566 // JavaProject initialProject,
567 // boolean ignoreUnresolvedVariable,
568 // boolean generateMarkerOnError,
569 // HashSet visitedProjects,
570 // ObjectVector accumulatedEntries) throws JavaModelException {
572 // if (visitedProjects.contains(this)){
573 // return; // break cycles if any
575 // visitedProjects.add(this);
577 // if (generateMarkerOnError && !this.equals(initialProject)){
578 // generateMarkerOnError = false;
580 // IClasspathEntry[] immediateClasspath =
581 // getResolvedClasspath(ignoreUnresolvedVariable, generateMarkerOnError);
583 // IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
584 // for (int i = 0, length = immediateClasspath.length; i < length; i++){
585 // IClasspathEntry entry = immediateClasspath[i];
587 // boolean isInitialProject = this.equals(initialProject);
588 // if (isInitialProject || entry.isExported()){
590 // accumulatedEntries.add(entry);
592 // // recurse in project to get all its indirect exports (only consider
593 // exported entries from there on)
594 // if (entry.getEntryKind() == ClasspathEntry.CPE_PROJECT) {
595 // IResource member = workspaceRoot.findMember(entry.getPath());
596 // if (member != null && member.getType() == IResource.PROJECT){ // double
597 // check if bound to project (23977)
598 // IProject projRsc = (IProject) member;
599 // if (JavaProject.hasJavaNature(projRsc)) {
600 // JavaProject project = (JavaProject) JavaCore.create(projRsc);
601 // project.computeExpandedClasspath(
603 // ignoreUnresolvedVariable,
604 // generateMarkerOnError,
606 // accumulatedEntries);
614 * Returns (local/all) the package fragment roots identified by the given
615 * project's classpath. Note: this follows project classpath references to
616 * find required project contributions, eliminating duplicates silently.
617 * Only works with resolved entries
619 public IPackageFragmentRoot[] computePackageFragmentRoots(
620 IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots)
621 throws JavaModelException {
623 ObjectVector accumulatedRoots = new ObjectVector();
624 computePackageFragmentRoots(resolvedClasspath, accumulatedRoots,
625 new HashSet(5), // rootIDs
626 true, // inside original project
627 true, // check existency
628 retrieveExportedRoots);
629 IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots
631 accumulatedRoots.copyInto(rootArray);
636 * Computes the package fragment roots identified by the given entry. Only
637 * works with resolved entry
639 public IPackageFragmentRoot[] computePackageFragmentRoots(
640 IClasspathEntry resolvedEntry) {
642 return computePackageFragmentRoots(
643 new IClasspathEntry[] { resolvedEntry }, false // don't
648 } catch (JavaModelException e) {
649 return new IPackageFragmentRoot[] {};
654 * Returns the package fragment roots identified by the given entry. In case
655 * it refers to a project, it will follow its classpath so as to find
656 * exported roots as well. Only works with resolved entry
658 public void computePackageFragmentRoots(IClasspathEntry resolvedEntry,
659 ObjectVector accumulatedRoots, HashSet rootIDs,
660 boolean insideOriginalProject, boolean checkExistency,
661 boolean retrieveExportedRoots) throws JavaModelException {
663 String rootID = ((ClasspathEntry) resolvedEntry).rootID();
664 if (rootIDs.contains(rootID))
667 IPath projectPath = getProject().getFullPath();
668 IPath entryPath = resolvedEntry.getPath();
669 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
671 switch (resolvedEntry.getEntryKind()) {
674 case IClasspathEntry.CPE_SOURCE:
676 if (projectPath.isPrefixOf(entryPath)) {
677 if (checkExistency) {
678 Object target = JavaModel.getTarget(workspaceRoot,
679 entryPath, checkExistency);
683 if (target instanceof IFolder || target instanceof IProject) {
685 .add(getPackageFragmentRoot((IResource) target));
689 IPackageFragmentRoot root = getFolderPackageFragmentRoot(entryPath);
691 accumulatedRoots.add(root);
698 // internal/external JAR or folder
699 case IClasspathEntry.CPE_LIBRARY:
701 if (!insideOriginalProject && !resolvedEntry.isExported())
704 if (checkExistency) {
705 Object target = JavaModel.getTarget(workspaceRoot, entryPath,
710 if (target instanceof IResource) {
712 IResource resource = (IResource) target;
713 IPackageFragmentRoot root = getPackageFragmentRoot(resource);
715 accumulatedRoots.add(root);
719 // external target - only JARs allowed
720 // if (((java.io.File)target).isFile() &&
721 // (ProjectPrefUtil.isArchiveFileName(entryPath.lastSegment())))
723 // accumulatedRoots.add(
724 // new JarPackageFragmentRoot(entryPath, this));
725 // rootIDs.add(rootID);
729 IPackageFragmentRoot root = getPackageFragmentRoot(entryPath);
731 accumulatedRoots.add(root);
737 // recurse into required project
738 case IClasspathEntry.CPE_PROJECT:
740 if (!retrieveExportedRoots)
742 if (!insideOriginalProject && !resolvedEntry.isExported())
745 IResource member = workspaceRoot.findMember(entryPath);
746 if (member != null && member.getType() == IResource.PROJECT) {// double
753 IProject requiredProjectRsc = (IProject) member;
754 if (JavaProject.hasJavaNature(requiredProjectRsc)) { // special
759 JavaProject requiredProject = (JavaProject) JavaCore
760 .create(requiredProjectRsc);
761 requiredProject.computePackageFragmentRoots(requiredProject
762 .getResolvedClasspath(true), accumulatedRoots,
763 rootIDs, false, checkExistency,
764 retrieveExportedRoots);
772 * Returns (local/all) the package fragment roots identified by the given
773 * project's classpath. Note: this follows project classpath references to
774 * find required project contributions, eliminating duplicates silently.
775 * Only works with resolved entries
777 public void computePackageFragmentRoots(
778 IClasspathEntry[] resolvedClasspath, ObjectVector accumulatedRoots,
779 HashSet rootIDs, boolean insideOriginalProject,
780 boolean checkExistency, boolean retrieveExportedRoots)
781 throws JavaModelException {
783 if (insideOriginalProject) {
784 rootIDs.add(rootID());
786 for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
787 computePackageFragmentRoots(resolvedClasspath[i], accumulatedRoots,
788 rootIDs, insideOriginalProject, checkExistency,
789 retrieveExportedRoots);
794 * Compute the file name to use for a given shared property
796 public String computeSharedPropertyFileName(QualifiedName qName) {
798 return '.' + qName.getLocalName();
802 * Returns whether the given resource is accessible through the children or
803 * the non-Java resources of this project. Returns true if the resource is
804 * not in the project. Assumes that the resource is a folder or a file.
806 public boolean contains(IResource resource) {
808 IClasspathEntry[] classpath;
811 classpath = getResolvedClasspath(true);
812 output = getOutputLocation();
813 } catch (JavaModelException e) {
817 IPath fullPath = resource.getFullPath();
818 IPath innerMostOutput = output.isPrefixOf(fullPath) ? output : null;
819 IClasspathEntry innerMostEntry = null;
820 for (int j = 0, cpLength = classpath.length; j < cpLength; j++) {
821 IClasspathEntry entry = classpath[j];
823 IPath entryPath = entry.getPath();
824 if ((innerMostEntry == null || innerMostEntry.getPath().isPrefixOf(
826 && entryPath.isPrefixOf(fullPath)) {
827 innerMostEntry = entry;
829 IPath entryOutput = classpath[j].getOutputLocation();
830 if (entryOutput != null && entryOutput.isPrefixOf(fullPath)) {
831 innerMostOutput = entryOutput;
834 if (innerMostEntry != null) {
835 // special case prj==src and nested output location
836 if (innerMostOutput != null && innerMostOutput.segmentCount() > 1 // output
839 && innerMostEntry.getPath().segmentCount() == 1) { // 1
847 if (resource instanceof IFolder) {
848 // folders are always included in src/lib entries
851 switch (innerMostEntry.getEntryKind()) {
852 case IClasspathEntry.CPE_SOURCE:
853 // .class files are not visible in source folders
854 return true; // !net.sourceforge.phpdt.internal.compiler.util.ProjectPrefUtil.isClassFileName(fullPath.lastSegment());
855 case IClasspathEntry.CPE_LIBRARY:
856 // .java files are not visible in library folders
857 return !net.sourceforge.phpdt.internal.compiler.util.Util
858 .isJavaFileName(fullPath.lastSegment());
861 if (innerMostOutput != null) {
868 * Record a new marker denoting a classpath problem
870 IMarker createClasspathProblemMarker(IJavaModelStatus status) {
872 IMarker marker = null;
874 String[] arguments = new String[0];
875 boolean isCycleProblem = false, isClasspathFileFormatProblem = false;
876 switch (status.getCode()) {
878 case IJavaModelStatusConstants.CLASSPATH_CYCLE:
879 isCycleProblem = true;
880 if (JavaCore.ERROR.equals(getOption(
881 JavaCore.CORE_CIRCULAR_CLASSPATH, true))) {
882 severity = IMarker.SEVERITY_ERROR;
884 severity = IMarker.SEVERITY_WARNING;
888 case IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT:
889 isClasspathFileFormatProblem = true;
890 severity = IMarker.SEVERITY_ERROR;
894 IPath path = status.getPath();
896 arguments = new String[] { path.toString() };
897 if (JavaCore.ERROR.equals(getOption(
898 JavaCore.CORE_INCOMPLETE_CLASSPATH, true))) {
899 severity = IMarker.SEVERITY_ERROR;
901 severity = IMarker.SEVERITY_WARNING;
907 marker = getProject().createMarker(
908 IJavaModelMarker.BUILDPATH_PROBLEM_MARKER);
909 marker.setAttributes(new String[] { IMarker.MESSAGE,
910 IMarker.SEVERITY, IMarker.LOCATION,
911 IJavaModelMarker.CYCLE_DETECTED,
912 IJavaModelMarker.CLASSPATH_FILE_FORMAT,
913 IJavaModelMarker.ID, IJavaModelMarker.ARGUMENTS, },
914 new Object[] { status.getMessage(),
915 new Integer(severity),
916 Util.bind("classpath.buildPath"),//$NON-NLS-1$
917 isCycleProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
918 isClasspathFileFormatProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
919 new Integer(status.getCode()),
920 Util.getProblemArgumentsForMarker(arguments), });
921 } catch (CoreException e) {
927 * Returns a new element info for this element.
929 protected Object createElementInfo() {
930 return new JavaProjectElementInfo();
934 * Returns a new search name environment for this project. This name
935 * environment first looks in the given working copies.
937 // public ISearchableNameEnvironment
938 // newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws
939 // JavaModelException {
940 // return new SearchableEnvironment(this, workingCopies);
943 * Returns a new search name environment for this project. This name
944 * environment first looks in the working copies of the given owner.
946 public ISearchableNameEnvironment newSearchableNameEnvironment(
947 WorkingCopyOwner owner) throws JavaModelException {
948 return new SearchableEnvironment(this, owner);
952 * Reads and decode an XML classpath string
954 protected IClasspathEntry[] decodeClasspath(String xmlClasspath,
955 boolean createMarker, boolean logProblems) {
957 ArrayList paths = new ArrayList();
958 IClasspathEntry defaultOutput = null;
960 if (xmlClasspath == null)
962 StringReader reader = new StringReader(xmlClasspath);
966 DocumentBuilder parser = DocumentBuilderFactory.newInstance()
967 .newDocumentBuilder();
968 cpElement = parser.parse(new InputSource(reader))
969 .getDocumentElement();
970 } catch (SAXException e) {
971 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
972 } catch (ParserConfigurationException e) {
973 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
978 if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$
979 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
981 NodeList list = cpElement.getElementsByTagName("classpathentry"); //$NON-NLS-1$
982 int length = list.getLength();
984 for (int i = 0; i < length; ++i) {
985 Node node = list.item(i);
986 if (node.getNodeType() == Node.ELEMENT_NODE) {
987 IClasspathEntry entry = ClasspathEntry.elementDecode(
988 (Element) node, this);
990 if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
991 defaultOutput = entry; // separate output
998 } catch (IOException e) {
1000 if (createMarker && this.getProject().isAccessible()) {
1002 .createClasspathProblemMarker(new JavaModelStatus(
1003 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1006 "classpath.xmlFormatError", this.getElementName(), e.getMessage()))); //$NON-NLS-1$
1009 Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$
1010 + "/.classpath, will mark classpath as invalid"); //$NON-NLS-1$
1012 return INVALID_CLASSPATH;
1013 } catch (/*Assert.*/AssertionFailedException e) {
1014 // failed creating CP entries from file
1015 if (createMarker && this.getProject().isAccessible()) {
1017 .createClasspathProblemMarker(new JavaModelStatus(
1018 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1021 "classpath.illegalEntryInClasspathFile", this.getElementName(), e.getMessage()))); //$NON-NLS-1$
1024 Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$
1025 + "/.classpath, will mark classpath as invalid"); //$NON-NLS-1$
1027 return INVALID_CLASSPATH;
1029 int pathSize = paths.size();
1030 if (pathSize > 0 || defaultOutput != null) {
1031 IClasspathEntry[] entries = new IClasspathEntry[pathSize
1032 + (defaultOutput == null ? 0 : 1)];
1033 paths.toArray(entries);
1034 if (defaultOutput != null)
1035 entries[pathSize] = defaultOutput; // ensure output is last
1044 * /** Removes the Java nature from the project.
1046 public void deconfigure() throws CoreException {
1048 // deregister Java builder
1049 removeFromBuildSpec(PHPeclipsePlugin.BUILDER_PARSER_ID);
1053 * Returns a default class path. This is the root of the project
1055 protected IClasspathEntry[] defaultClasspath() throws JavaModelException {
1057 return new IClasspathEntry[] { JavaCore.newSourceEntry(getProject()
1062 * Returns a default output location. This is the project bin folder
1064 protected IPath defaultOutputLocation() throws JavaModelException {
1065 return null; // getProject().getFullPath().append("bin");
1070 * Returns the XML String encoding of the class path.
1072 protected String encodeClasspath(IClasspathEntry[] classpath,
1073 IPath outputLocation, boolean indent) throws JavaModelException {
1075 ByteArrayOutputStream s = new ByteArrayOutputStream();
1076 OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
1077 XMLWriter xmlWriter = new XMLWriter(writer);
1079 xmlWriter.startTag("classpath", indent); //$NON-NLS-1$
1080 for (int i = 0; i < classpath.length; ++i) {
1081 ((ClasspathEntry) classpath[i]).elementEncode(xmlWriter,
1082 this.project.getFullPath(), indent, true);
1085 if (outputLocation != null) {
1086 outputLocation = outputLocation.removeFirstSegments(1);
1087 outputLocation = outputLocation.makeRelative();
1088 HashMap parameters = new HashMap();
1091 "kind", ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT));//$NON-NLS-1$
1092 parameters.put("path", String.valueOf(outputLocation));//$NON-NLS-1$
1094 "classpathentry", parameters, indent, true, true);//$NON-NLS-1$
1097 xmlWriter.endTag("classpath", indent);//$NON-NLS-1$
1100 return s.toString("UTF8");//$NON-NLS-1$
1101 } catch (IOException e) {
1102 throw new JavaModelException(e,
1103 IJavaModelStatusConstants.IO_EXCEPTION);
1108 * Returns the XML String encoding of the class path.
1110 // protected String encodeClasspath(IClasspathEntry[] classpath, IPath
1111 // outputLocation, boolean useLineSeparator) throws JavaModelException {
1113 // Document document = new DocumentImpl();
1114 // Element cpElement = document.createElement("classpath"); //$NON-NLS-1$
1115 // document.appendChild(cpElement);
1117 // for (int i = 0; i < classpath.length; ++i) {
1118 // cpElement.appendChild(((ClasspathEntry)classpath[i]).elementEncode(document,
1119 // getProject().getFullPath()));
1122 // if (outputLocation != null) {
1123 // outputLocation = outputLocation.removeFirstSegments(1);
1124 // outputLocation = outputLocation.makeRelative();
1125 // Element oElement = document.createElement("classpathentry");
1127 // oElement.setAttribute("kind",
1128 // ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT)); //$NON-NLS-1$
1129 // oElement.setAttribute("path", outputLocation.toString()); //$NON-NLS-1$
1130 // cpElement.appendChild(oElement);
1133 // // produce a String output
1135 // ByteArrayOutputStream s = new ByteArrayOutputStream();
1136 // OutputFormat format = new OutputFormat();
1137 // if (useLineSeparator) {
1138 // format.setIndenting(true);
1139 // format.setLineSeparator(System.getProperty("line.separator"));
1142 // format.setPreserveSpace(true);
1144 // Serializer serializer =
1145 // SerializerFactory.getSerializerFactory(Method.XML).makeSerializer(
1146 // new OutputStreamWriter(s, "UTF8"), //$NON-NLS-1$
1148 // serializer.asDOMSerializer().serialize(document);
1149 // return s.toString("UTF8"); //$NON-NLS-1$
1150 // } catch (IOException e) {
1151 // throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
1155 * Returns true if this handle represents the same Java project as the given
1156 * handle. Two handles represent the same project if they are identical or
1157 * if they represent a project with the same underlying resource and
1158 * occurrence counts.
1160 * @see JavaElement#equals
1162 public boolean equals(Object o) {
1167 if (!(o instanceof JavaProject))
1170 JavaProject other = (JavaProject) o;
1171 return getProject().equals(other.getProject())
1172 && occurrenceCount == other.occurrenceCount;
1175 public boolean exists() {
1176 if (!hasJavaNature(project))
1178 return super.exists();
1184 public IJavaElement findElement(IPath path) throws JavaModelException {
1186 if (path == null || path.isAbsolute()) {
1187 throw new JavaModelException(new JavaModelStatus(
1188 IJavaModelStatusConstants.INVALID_PATH, path));
1192 String extension = path.getFileExtension();
1193 if (extension == null) {
1194 //String packageName = path.toString().replace(IPath.SEPARATOR, '.');
1196 // IPackageFragment[] pkgFragments =
1197 // getNameLookup().findPackageFragments(packageName, false);
1198 // if (pkgFragments == null) {
1202 // // try to return one that is a child of this project
1203 // for (int i = 0, length = pkgFragments.length; i < length; i++) {
1205 // IPackageFragment pkgFragment = pkgFragments[i];
1206 // if (this.equals(pkgFragment.getParent().getParent())) {
1207 // return pkgFragment;
1210 // // default to the first one
1211 // return pkgFragments[0];
1213 } else if (extension.equalsIgnoreCase("java") //$NON-NLS-1$
1214 || extension.equalsIgnoreCase("class")) { //$NON-NLS-1$
1215 IPath packagePath = path.removeLastSegments(1);
1216 String packageName = packagePath.toString().replace(
1217 IPath.SEPARATOR, '.');
1218 String typeName = path.lastSegment();
1219 typeName = typeName.substring(0, typeName.length()
1220 - extension.length() - 1);
1221 String qualifiedName = null;
1222 if (packageName.length() > 0) {
1223 qualifiedName = packageName + "." + typeName; //$NON-NLS-1$
1225 qualifiedName = typeName;
1228 // getNameLookup().findType(
1231 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1232 // if (type != null) {
1233 // return type.getParent();
1238 // unsupported extension
1241 // } catch (JavaModelException e) {
1242 // if (e.getStatus().getCode()
1243 // == IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST) {
1254 // public IPackageFragment findPackageFragment(IPath path)
1255 // throws JavaModelException {
1257 // return findPackageFragment0(JavaProject.canonicalizedPath(path));
1261 // * non path canonicalizing version
1263 // public IPackageFragment findPackageFragment0(IPath path)
1264 // throws JavaModelException {
1266 // return getNameLookup().findPackageFragment(path);
1271 public IPackageFragmentRoot findPackageFragmentRoot(IPath path)
1272 throws JavaModelException {
1274 return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path));
1278 * no path canonicalization
1280 public IPackageFragmentRoot findPackageFragmentRoot0(IPath path)
1281 throws JavaModelException {
1283 IPackageFragmentRoot[] allRoots = this.getAllPackageFragmentRoots();
1284 if (!path.isAbsolute()) {
1285 throw new IllegalArgumentException(Util.bind("path.mustBeAbsolute")); //$NON-NLS-1$
1287 for (int i = 0; i < allRoots.length; i++) {
1288 IPackageFragmentRoot classpathRoot = allRoots[i];
1289 if (classpathRoot.getPath().equals(path)) {
1290 return classpathRoot;
1299 public IPackageFragmentRoot[] findPackageFragmentRoots(IClasspathEntry entry) {
1301 IClasspathEntry[] classpath = this.getRawClasspath();
1302 for (int i = 0, length = classpath.length; i < length; i++) {
1303 if (classpath[i].equals(entry)) { // entry may need to be
1305 return computePackageFragmentRoots(getResolvedClasspath(
1306 new IClasspathEntry[] { entry }, null, true, false,
1307 null/* no reverse map */), false); // don't
1313 } catch (JavaModelException e) {
1315 return new IPackageFragmentRoot[] {};
1319 * @see IJavaProject#findType(String)
1321 // public IType findType(String fullyQualifiedName) throws
1322 // JavaModelException {
1324 // this.getNameLookup().findType(
1325 // fullyQualifiedName,
1327 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1328 // if (type == null) {
1329 // // try to find enclosing type
1330 // int lastDot = fullyQualifiedName.lastIndexOf('.');
1331 // if (lastDot == -1) return null;
1332 // type = this.findType(fullyQualifiedName.substring(0, lastDot));
1333 // if (type != null) {
1334 // type = type.getType(fullyQualifiedName.substring(lastDot+1));
1335 // if (!type.exists()) {
1343 * @see IJavaProject#findType(String, String)
1345 // public IType findType(String packageName, String typeQualifiedName)
1346 // throws JavaModelException {
1348 // this.getNameLookup().findType(
1349 // typeQualifiedName,
1352 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1356 * Remove all markers denoting classpath problems
1358 protected void flushClasspathProblemMarkers(boolean flushCycleMarkers,
1359 boolean flushClasspathFormatMarkers) {
1361 IProject project = getProject();
1362 if (project.exists()) {
1363 IMarker[] markers = project.findMarkers(
1364 IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false,
1365 IResource.DEPTH_ZERO);
1366 for (int i = 0, length = markers.length; i < length; i++) {
1367 IMarker marker = markers[i];
1368 if (flushCycleMarkers && flushClasspathFormatMarkers) {
1371 String cycleAttr = (String) marker
1372 .getAttribute(IJavaModelMarker.CYCLE_DETECTED);
1373 String classpathFileFormatAttr = (String) marker
1374 .getAttribute(IJavaModelMarker.CLASSPATH_FILE_FORMAT);
1375 if ((flushCycleMarkers == (cycleAttr != null && cycleAttr
1376 .equals("true"))) //$NON-NLS-1$
1377 && (flushClasspathFormatMarkers == (classpathFileFormatAttr != null && classpathFileFormatAttr
1378 .equals("true")))) { //$NON-NLS-1$
1384 } catch (CoreException e) {
1391 // protected boolean generateInfos(
1392 // OpenableElementInfo info,
1393 // IProgressMonitor pm,
1395 // IResource underlyingResource) throws JavaModelException {
1397 // boolean validInfo = false;
1399 // if (getProject().isOpen()) {
1400 // // put the info now, because computing the roots requires it
1401 // JavaModelManager.getJavaModelManager().putInfo(this, info);
1403 // // compute the pkg fragment roots
1404 // updatePackageFragmentRoots();
1406 // // remember the timestamps of external libraries the first time they are
1408 // IClasspathEntry[] resolvedClasspath = getResolvedClasspath(true/*ignore
1409 // unresolved variable*/);
1410 // for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
1411 // IClasspathEntry entry = resolvedClasspath[i];
1412 // if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
1413 // IPath path = entry.getPath();
1415 // JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path,
1417 // if (target instanceof java.io.File) {
1418 // Map externalTimeStamps =
1419 // JavaModelManager.getJavaModelManager().deltaProcessor.externalTimeStamps;
1420 // if (externalTimeStamps.get(path) == null) {
1421 // long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
1422 // externalTimeStamps.put(path, new Long(timestamp));
1428 // // only valid if reaches here
1429 // validInfo = true;
1433 // JavaModelManager.getJavaModelManager().removeInfo(this);
1435 // return validInfo;
1441 public IPackageFragmentRoot[] getAllPackageFragmentRoots()
1442 throws JavaModelException {
1444 return computePackageFragmentRoots(getResolvedClasspath(true), true);
1448 * Returns the classpath entry that refers to the given path or
1449 * <code>null</code> if there is no reference to the path.
1451 public IClasspathEntry getClasspathEntryFor(IPath path)
1452 throws JavaModelException {
1454 IClasspathEntry[] entries = getExpandedClasspath(true);
1455 for (int i = 0; i < entries.length; i++) {
1456 if (entries[i].getPath().equals(path)) {
1464 * Returns the cycle marker associated with this project or null if none.
1466 public IMarker getCycleMarker() {
1468 IProject project = getProject();
1469 if (project.exists()) {
1470 IMarker[] markers = project.findMarkers(
1471 IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false,
1472 IResource.DEPTH_ZERO);
1473 for (int i = 0, length = markers.length; i < length; i++) {
1474 IMarker marker = markers[i];
1475 String cycleAttr = (String) marker
1476 .getAttribute(IJavaModelMarker.CYCLE_DETECTED);
1477 if (cycleAttr != null && cycleAttr.equals("true")) { //$NON-NLS-1$
1482 } catch (CoreException e) {
1490 public int getElementType() {
1491 return JAVA_PROJECT;
1495 * This is a helper method returning the expanded classpath for the project,
1496 * as a list of classpath entries, where all classpath variable entries have
1497 * been resolved and substituted with their final target entries. All
1498 * project exports have been appended to project entries.
1500 * @param ignoreUnresolvedVariable
1502 * @return IClasspathEntry[]
1503 * @throws JavaModelException
1505 public IClasspathEntry[] getExpandedClasspath(
1506 boolean ignoreUnresolvedVariable) throws JavaModelException {
1508 return getExpandedClasspath(ignoreUnresolvedVariable,
1509 false/* don't create markers */, null, null);
1515 public IJavaElement getHandleFromMemento(String token,
1516 MementoTokenizer memento, WorkingCopyOwner owner) {
1517 switch (token.charAt(0)) {
1519 return getHandleUpdatingCountFromMemento(memento, owner);
1520 case JEM_PACKAGEFRAGMENTROOT:
1521 String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
1523 while (memento.hasMoreTokens()) {
1524 token = memento.nextToken();
1525 char firstChar = token.charAt(0);
1526 if (firstChar != JEM_PACKAGEFRAGMENT && firstChar != JEM_COUNT) {
1532 JavaElement root = (JavaElement) getPackageFragmentRoot(new Path(
1534 if (token != null && token.charAt(0) == JEM_PACKAGEFRAGMENT) {
1535 return root.getHandleFromMemento(token, memento, owner);
1537 return root.getHandleFromMemento(memento, owner);
1544 * Returns the <code>char</code> that marks the start of this handles
1545 * contribution to a memento.
1547 protected char getHandleMementoDelimiter() {
1549 return JEM_JAVAPROJECT;
1553 * Internal variant which can create marker on project for invalid entries,
1554 * it will also perform classpath expansion in presence of project
1555 * prerequisites exporting their entries.
1557 * @param ignoreUnresolvedVariable
1559 * @param generateMarkerOnError
1561 * @param preferredClasspaths
1563 * @param preferredOutputs
1565 * @return IClasspathEntry[]
1566 * @throws JavaModelException
1568 public IClasspathEntry[] getExpandedClasspath(
1569 boolean ignoreUnresolvedVariable, boolean generateMarkerOnError,
1570 Map preferredClasspaths, Map preferredOutputs)
1571 throws JavaModelException {
1573 ObjectVector accumulatedEntries = new ObjectVector();
1574 computeExpandedClasspath(this, ignoreUnresolvedVariable,
1575 generateMarkerOnError, new HashSet(5), accumulatedEntries,
1576 preferredClasspaths, preferredOutputs);
1578 IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries
1580 accumulatedEntries.copyInto(expandedPath);
1582 return expandedPath;
1586 // * Internal variant which can create marker on project for invalid
1588 // * it will also perform classpath expansion in presence of project
1590 // * exporting their entries.
1592 // public IClasspathEntry[] getExpandedClasspath(
1593 // boolean ignoreUnresolvedVariable,
1594 // boolean generateMarkerOnError) throws JavaModelException {
1596 // ObjectVector accumulatedEntries = new ObjectVector();
1597 // computeExpandedClasspath(this, ignoreUnresolvedVariable,
1598 // generateMarkerOnError, new HashSet(5), accumulatedEntries);
1600 // IClasspathEntry[] expandedPath = new
1601 // IClasspathEntry[accumulatedEntries.size()];
1602 // accumulatedEntries.copyInto(expandedPath);
1604 // return expandedPath;
1608 * Find the specific Java command amongst the build spec of a given
1611 private ICommand getJavaCommand(IProjectDescription description)
1612 throws CoreException {
1614 ICommand[] commands = description.getBuildSpec();
1615 for (int i = 0; i < commands.length; ++i) {
1616 if (commands[i].getBuilderName().equals(
1617 PHPeclipsePlugin.BUILDER_PARSER_ID)) {
1625 * Convenience method that returns the specific type of info for a Java
1628 protected JavaProjectElementInfo getJavaProjectElementInfo()
1629 throws JavaModelException {
1631 return (JavaProjectElementInfo) getElementInfo();
1637 public NameLookup getNameLookup() throws JavaModelException {
1639 JavaProjectElementInfo info = getJavaProjectElementInfo();
1640 // lock on the project info to avoid race condition
1641 synchronized (info) {
1642 NameLookup nameLookup;
1643 if ((nameLookup = info.getNameLookup()) == null) {
1644 info.setNameLookup(nameLookup = new NameLookup(this));
1651 * Returns a new name lookup. This name lookup first looks in the given
1654 public NameLookup newNameLookup(ICompilationUnit[] workingCopies)
1655 throws JavaModelException {
1657 //JavaProjectElementInfo info = getJavaProjectElementInfo();
1658 // lock on the project info to avoid race condition while computing the
1659 // pkg fragment roots and package fragment caches
1660 // synchronized(info){
1661 // return new NameLookup(info.getAllPackageFragmentRoots(this),
1662 // info.getAllPackageFragments(this), workingCopies);
1668 * Returns a new name lookup. This name lookup first looks in the working
1669 * copies of the given owner.
1671 public NameLookup newNameLookup(WorkingCopyOwner owner)
1672 throws JavaModelException {
1674 JavaModelManager manager = JavaModelManager.getJavaModelManager();
1675 ICompilationUnit[] workingCopies = owner == null ? null : manager
1676 .getWorkingCopies(owner, true/* add primary WCs */);
1677 return newNameLookup(workingCopies);
1682 // * Returns an array of non-java resources contained in the receiver.
1684 // public Object[] getNonJavaResources() throws JavaModelException {
1686 // return ((JavaProjectElementInfo)
1687 // getElementInfo()).getNonJavaResources(this);
1691 * @see net.sourceforge.phpdt.core.IJavaProject#getOption(String, boolean)
1693 public String getOption(String optionName, boolean inheritJavaCoreOptions) {
1695 if (JavaModelManager.OptionNames.contains(optionName)) {
1697 Preferences preferences = getPreferences();
1698 if (preferences == null || preferences.isDefault(optionName)) {
1699 return inheritJavaCoreOptions ? JavaCore.getOption(optionName)
1702 return preferences.getString(optionName).trim();
1708 * @see net.sourceforge.phpdt.core.IJavaProject#getOptions(boolean)
1710 public Map getOptions(boolean inheritJavaCoreOptions) {
1712 // initialize to the defaults from JavaCore options pool
1713 Map options = inheritJavaCoreOptions ? JavaCore.getOptions()
1716 Preferences preferences = getPreferences();
1717 if (preferences == null)
1718 return options; // cannot do better (non-Java project)
1719 HashSet optionNames = JavaModelManager.OptionNames;
1721 // get preferences set to their default
1722 if (inheritJavaCoreOptions) {
1723 String[] defaultPropertyNames = preferences.defaultPropertyNames();
1724 for (int i = 0; i < defaultPropertyNames.length; i++) {
1725 String propertyName = defaultPropertyNames[i];
1726 if (optionNames.contains(propertyName)) {
1727 options.put(propertyName, preferences.getDefaultString(
1728 propertyName).trim());
1732 // get custom preferences not set to their default
1733 String[] propertyNames = preferences.propertyNames();
1734 for (int i = 0; i < propertyNames.length; i++) {
1735 String propertyName = propertyNames[i];
1736 if (optionNames.contains(propertyName)) {
1737 options.put(propertyName, preferences.getString(propertyName)
1747 // public IPath getOutputLocation() throws JavaModelException {
1749 // JavaModelManager.PerProjectInfo perProjectInfo =
1750 // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
1751 // IPath outputLocation = perProjectInfo.outputLocation;
1752 // if (outputLocation != null) return outputLocation;
1754 // // force to read classpath - will position output location as well
1755 // this.getRawClasspath();
1756 // outputLocation = perProjectInfo.outputLocation;
1757 // if (outputLocation == null) {
1758 // return defaultOutputLocation();
1760 // return outputLocation;
1765 public IPath getOutputLocation() throws JavaModelException {
1766 // Do not create marker but log problems while getting output location
1767 return this.getOutputLocation(false, true);
1771 * @param createMarkers
1773 * @param logProblems
1776 * @throws JavaModelException
1778 public IPath getOutputLocation(boolean createMarkers, boolean logProblems)
1779 throws JavaModelException {
1781 JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo();
1782 IPath outputLocation = perProjectInfo.outputLocation;
1783 if (outputLocation != null)
1784 return outputLocation;
1786 // force to read classpath - will position output location as well
1787 this.getRawClasspath(createMarkers, logProblems);
1788 outputLocation = perProjectInfo.outputLocation;
1789 if (outputLocation == null) {
1790 return defaultOutputLocation();
1792 return outputLocation;
1796 * @return A handle to the package fragment root identified by the given
1797 * path. This method is handle-only and the element may or may not
1798 * exist. Returns <code>null</code> if unable to generate a handle
1799 * from the path (for example, an absolute path that has less than 1
1800 * segment. The path may be relative or absolute.
1802 public IPackageFragmentRoot getPackageFragmentRoot(IPath path) {
1803 if (!path.isAbsolute()) {
1804 path = getPath().append(path);
1806 int segmentCount = path.segmentCount();
1807 switch (segmentCount) {
1812 return getPackageFragmentRoot(getProject());
1814 // a path ending with .jar/.zip is still ambiguous and could still
1815 // resolve to a source/lib folder
1816 // thus will try to guess based on existing resource
1817 // if (ProjectPrefUtil.isArchiveFileName(path.lastSegment())) {
1818 // IResource resource =
1819 // getProject().getWorkspace().getRoot().findMember(path);
1820 // if (resource != null && resource.getType() == IResource.FOLDER){
1821 // return getPackageFragmentRoot(resource);
1823 // return getPackageFragmentRoot0(path);
1825 return getPackageFragmentRoot(getProject().getWorkspace().getRoot()
1832 * The path is known to match a source/library folder entry.
1834 public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) {
1835 if (path.segmentCount() == 1) { // default project root
1836 return getPackageFragmentRoot(getProject());
1838 return getPackageFragmentRoot(getProject().getWorkspace().getRoot()
1845 public IPackageFragmentRoot getPackageFragmentRoot(IResource resource) {
1847 switch (resource.getType()) {
1848 case IResource.FILE:
1849 // if (ProjectPrefUtil.isArchiveFileName(resource.getName())) {
1850 // return new JarPackageFragmentRoot(resource, this);
1854 case IResource.FOLDER:
1855 return new PackageFragmentRoot(resource, this, resource.getName());
1856 case IResource.PROJECT:
1857 return new PackageFragmentRoot(resource, this, ""); //$NON-NLS-1$
1866 // public IPackageFragmentRoot getPackageFragmentRoot(String jarPath) {
1868 // return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new
1873 // * no path canonicalization
1875 // public IPackageFragmentRoot getPackageFragmentRoot0(IPath jarPath) {
1877 // return new JarPackageFragmentRoot(jarPath, this);
1882 public IPackageFragmentRoot[] getPackageFragmentRoots()
1883 throws JavaModelException {
1887 IPackageFragmentRoot[] roots;
1889 System.arraycopy(children = getChildren(), 0,
1890 roots = new IPackageFragmentRoot[length = children.length], 0,
1900 public IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry) {
1901 return findPackageFragmentRoots(entry);
1905 * Returns the package fragment root prefixed by the given path, or an empty
1906 * collection if there are no such elements in the model.
1908 protected IPackageFragmentRoot[] getPackageFragmentRoots(IPath path)
1910 throws JavaModelException {
1911 IPackageFragmentRoot[] roots = getAllPackageFragmentRoots();
1912 ArrayList matches = new ArrayList();
1914 for (int i = 0; i < roots.length; ++i) {
1915 if (path.isPrefixOf(roots[i].getPath())) {
1916 matches.add(roots[i]);
1919 IPackageFragmentRoot[] copy = new IPackageFragmentRoot[matches.size()];
1920 matches.toArray(copy);
1927 public IPackageFragment[] getPackageFragments() throws JavaModelException {
1929 IPackageFragmentRoot[] roots = getPackageFragmentRoots();
1930 return getPackageFragmentsInRoots(roots);
1934 * Returns all the package fragments found in the specified package fragment
1937 public IPackageFragment[] getPackageFragmentsInRoots(
1938 IPackageFragmentRoot[] roots) {
1940 ArrayList frags = new ArrayList();
1941 for (int i = 0; i < roots.length; i++) {
1942 IPackageFragmentRoot root = roots[i];
1944 IJavaElement[] rootFragments = root.getChildren();
1945 for (int j = 0; j < rootFragments.length; j++) {
1946 frags.add(rootFragments[j]);
1948 } catch (JavaModelException e) {
1952 IPackageFragment[] fragments = new IPackageFragment[frags.size()];
1953 frags.toArray(fragments);
1960 public IPath getPath() {
1961 return this.getProject().getFullPath();
1964 public JavaModelManager.PerProjectInfo getPerProjectInfo()
1965 throws JavaModelException {
1966 return JavaModelManager.getJavaModelManager()
1967 .getPerProjectInfoCheckExistence(this.project);
1973 public IProject getProject() {
1979 * Sets the underlying kernel project of this Java project, and fills in its
1980 * parent and name. Called by IProject.getNature().
1982 * @see IProjectNature#setProject(IProject)
1984 public void setProject(IProject project) {
1986 this.project = project;
1987 this.parent = JavaModelManager.getJavaModelManager().getJavaModel();
1988 this.name = project.getName();
1991 protected IProject getProject(String name) {
1992 return PHPeclipsePlugin.getWorkspace().getRoot().getProject(name);
1995 public List getReferencedProjects() {
1996 List referencedProjects = new ArrayList();
1998 Iterator iterator = getLoadPathEntries().iterator();
1999 while (iterator.hasNext()) {
2000 LoadPathEntry pathEntry = (LoadPathEntry) iterator.next();
2001 if (pathEntry.getType() == LoadPathEntry.TYPE_PROJECT)
2002 referencedProjects.add(pathEntry.getProject());
2005 return referencedProjects;
2009 * Returns the project custom preference pool. Project preferences may
2010 * include custom encoding.
2012 public Preferences getPreferences() {
2013 IProject project = getProject();
2014 if (!JavaProject.hasJavaNature(project))
2016 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager
2017 .getJavaModelManager().getPerProjectInfo(project, true);
2018 Preferences preferences = perProjectInfo.preferences;
2019 if (preferences != null)
2021 preferences = loadPreferences();
2022 if (preferences == null)
2023 preferences = new Preferences();
2024 perProjectInfo.preferences = preferences;
2031 // public IClasspathEntry[] getRawClasspath() throws JavaModelException {
2033 // JavaModelManager.PerProjectInfo perProjectInfo =
2034 // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
2035 // IClasspathEntry[] classpath = perProjectInfo.classpath;
2036 // if (classpath != null) return classpath;
2037 // classpath = this.readClasspathFile(false/*don't create markers*/,
2038 // true/*log problems*/);
2040 // // extract out the output location
2041 // IPath outputLocation = null;
2042 // if (classpath != null && classpath.length > 0) {
2043 // IClasspathEntry entry = classpath[classpath.length - 1];
2044 // if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
2045 // outputLocation = entry.getPath();
2046 // IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
2047 // System.arraycopy(classpath, 0, copy, 0, copy.length);
2048 // classpath = copy;
2051 // if (classpath == null) {
2052 // return defaultClasspath();
2054 // /* Disable validate: classpath can contain CP variables and container
2055 // that need to be resolved
2056 // if (classpath != INVALID_CLASSPATH
2057 // && !JavaConventions.validateClasspath(this, classpath,
2058 // outputLocation).isOK()) {
2059 // classpath = INVALID_CLASSPATH;
2062 // perProjectInfo.classpath = classpath;
2063 // perProjectInfo.outputLocation = outputLocation;
2064 // return classpath;
2069 public IClasspathEntry[] getRawClasspath() throws JavaModelException {
2070 // Do not create marker but log problems while getting raw classpath
2071 return getRawClasspath(false, true);
2075 * Internal variant allowing to parameterize problem creation/logging
2077 public IClasspathEntry[] getRawClasspath(boolean createMarkers,
2078 boolean logProblems) throws JavaModelException {
2080 JavaModelManager.PerProjectInfo perProjectInfo = null;
2081 IClasspathEntry[] classpath;
2082 if (createMarkers) {
2083 this.flushClasspathProblemMarkers(false/* cycle */, true/* format */);
2084 classpath = this.readClasspathFile(createMarkers, logProblems);
2086 perProjectInfo = getPerProjectInfo();
2087 classpath = perProjectInfo.rawClasspath;
2088 if (classpath != null)
2090 classpath = this.readClasspathFile(createMarkers, logProblems);
2092 // extract out the output location
2093 IPath outputLocation = null;
2094 if (classpath != null && classpath.length > 0) {
2095 IClasspathEntry entry = classpath[classpath.length - 1];
2096 if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
2097 outputLocation = entry.getPath();
2098 IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
2099 System.arraycopy(classpath, 0, copy, 0, copy.length);
2103 if (classpath == null) {
2104 return defaultClasspath();
2107 * Disable validate: classpath can contain CP variables and container
2108 * that need to be resolved if (classpath != INVALID_CLASSPATH &&
2109 * !JavaConventions.validateClasspath(this, classpath,
2110 * outputLocation).isOK()) { classpath = INVALID_CLASSPATH; }
2112 if (!createMarkers) {
2113 perProjectInfo.rawClasspath = classpath;
2114 perProjectInfo.outputLocation = outputLocation;
2120 * @see IJavaProject#getRequiredProjectNames
2122 public String[] getRequiredProjectNames() throws JavaModelException {
2124 return this.projectPrerequisites(getResolvedClasspath(true));
2130 public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry)
2131 throws JavaModelException {
2133 return this.getResolvedClasspath(ignoreUnresolvedEntry, false); // generateMarkerOnError
2137 * Internal variant which can create marker on project for invalid entries
2138 * and caches the resolved classpath on perProjectInfo
2140 public IClasspathEntry[] getResolvedClasspath(
2141 boolean ignoreUnresolvedEntry, boolean generateMarkerOnError)
2142 throws JavaModelException {
2143 return getResolvedClasspath(ignoreUnresolvedEntry,
2144 generateMarkerOnError, true // returnResolutionInProgress
2146 // JavaModelManager manager = JavaModelManager.getJavaModelManager();
2147 // JavaModelManager.PerProjectInfo perProjectInfo =
2148 // manager.getPerProjectInfoCheckExistence(project);
2150 // // reuse cache if not needing to refresh markers or checking bound
2152 // if (ignoreUnresolvedEntry && !generateMarkerOnError && perProjectInfo
2154 // // resolved path is cached on its info
2155 // IClasspathEntry[] infoPath = perProjectInfo.lastResolvedClasspath;
2156 // if (infoPath != null) return infoPath;
2158 // Map reverseMap = perProjectInfo == null ? null : new HashMap(5);
2159 // IClasspathEntry[] resolvedPath = getResolvedClasspath(
2160 // getRawClasspath(),
2161 // generateMarkerOnError ? getOutputLocation() : null,
2162 // ignoreUnresolvedEntry,
2163 // generateMarkerOnError,
2166 // if (perProjectInfo != null){
2167 // if (perProjectInfo.classpath == null // .classpath file could not be
2169 // && generateMarkerOnError
2170 // && JavaProject.hasJavaNature(project)) {
2171 // this.createClasspathProblemMarker(new JavaModelStatus(
2172 // IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
2173 // Util.bind("classpath.cannotReadClasspathFile",
2174 // this.getElementName()))); //$NON-NLS-1$
2177 // perProjectInfo.lastResolvedClasspath = resolvedPath;
2178 // perProjectInfo.resolvedPathToRawEntries = reverseMap;
2180 // return resolvedPath;
2184 * Internal variant which can create marker on project for invalid entries
2185 * and caches the resolved classpath on perProjectInfo. If requested, return
2186 * a special classpath (RESOLUTION_IN_PROGRESS) if the classpath is being
2189 public IClasspathEntry[] getResolvedClasspath(
2190 boolean ignoreUnresolvedEntry, boolean generateMarkerOnError,
2191 boolean returnResolutionInProgress) throws JavaModelException {
2193 JavaModelManager manager = JavaModelManager.getJavaModelManager();
2194 JavaModelManager.PerProjectInfo perProjectInfo = null;
2195 if (ignoreUnresolvedEntry && !generateMarkerOnError) {
2196 perProjectInfo = getPerProjectInfo();
2197 if (perProjectInfo != null) {
2198 // resolved path is cached on its info
2199 IClasspathEntry[] infoPath = perProjectInfo.resolvedClasspath;
2200 if (infoPath != null) {
2202 } else if (returnResolutionInProgress
2203 && manager.isClasspathBeingResolved(this)) {
2204 if (JavaModelManager.CP_RESOLVE_VERBOSE) {
2206 .verbose("CPResolution: reentering raw classpath resolution, will use empty classpath instead" + //$NON-NLS-1$
2207 " project: " + getElementName() + '\n' + //$NON-NLS-1$
2208 " invocation stack trace:"); //$NON-NLS-1$
2209 new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
2211 return RESOLUTION_IN_PROGRESS;
2215 Map reverseMap = perProjectInfo == null ? null : new HashMap(5);
2216 IClasspathEntry[] resolvedPath = null;
2217 boolean nullOldResolvedCP = perProjectInfo != null
2218 && perProjectInfo.resolvedClasspath == null;
2220 // protect against misbehaving clients (see
2221 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=61040)
2222 if (nullOldResolvedCP)
2223 manager.setClasspathBeingResolved(this, true);
2224 resolvedPath = getResolvedClasspath(getRawClasspath(
2225 generateMarkerOnError, !generateMarkerOnError),
2226 generateMarkerOnError ? getOutputLocation() : null,
2227 ignoreUnresolvedEntry, generateMarkerOnError, reverseMap);
2229 if (nullOldResolvedCP)
2230 perProjectInfo.resolvedClasspath = null;
2233 if (perProjectInfo != null) {
2234 if (perProjectInfo.rawClasspath == null // .classpath file could not
2236 && generateMarkerOnError
2237 && JavaProject.hasJavaNature(this.project)) {
2238 // flush .classpath format markers (bug 39877), but only when
2239 // file cannot be read (bug 42366)
2240 this.flushClasspathProblemMarkers(false, true);
2242 .createClasspathProblemMarker(new JavaModelStatus(
2243 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
2246 "classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
2249 perProjectInfo.resolvedClasspath = resolvedPath;
2250 perProjectInfo.resolvedPathToRawEntries = reverseMap;
2251 manager.setClasspathBeingResolved(this, false);
2253 return resolvedPath;
2257 * Internal variant which can process any arbitrary classpath
2259 public IClasspathEntry[] getResolvedClasspath(
2260 IClasspathEntry[] classpathEntries, IPath projectOutputLocation, // only
2269 boolean ignoreUnresolvedEntry, // if unresolved entries are met,
2270 // should it trigger initializations
2271 boolean generateMarkerOnError, Map reverseMap) // can be null if
2272 // not interested in
2274 throws JavaModelException {
2276 IJavaModelStatus status;
2277 if (generateMarkerOnError) {
2278 flushClasspathProblemMarkers(false, false);
2281 int length = classpathEntries.length;
2282 ArrayList resolvedEntries = new ArrayList();
2284 for (int i = 0; i < length; i++) {
2286 IClasspathEntry rawEntry = classpathEntries[i];
2290 /* validation if needed */
2291 // if (generateMarkerOnError || !ignoreUnresolvedEntry) {
2292 // status = JavaConventions.validateClasspathEntry(this, rawEntry,
2294 // if (generateMarkerOnError && !status.isOK())
2295 // createClasspathProblemMarker(status);
2297 switch (rawEntry.getEntryKind()) {
2299 case IClasspathEntry.CPE_VARIABLE:
2301 IClasspathEntry resolvedEntry = JavaCore
2302 .getResolvedClasspathEntry(rawEntry);
2303 if (resolvedEntry == null) {
2304 if (!ignoreUnresolvedEntry)
2305 throw new JavaModelException(status);
2307 if (reverseMap != null
2308 && reverseMap.get(resolvedPath = resolvedEntry
2309 .getPath()) == null)
2310 reverseMap.put(resolvedPath, rawEntry);
2311 resolvedEntries.add(resolvedEntry);
2315 // case IClasspathEntry.CPE_CONTAINER :
2317 // IClasspathContainer container =
2318 // PHPCore.getClasspathContainer(rawEntry.getPath(), this);
2319 // if (container == null){
2320 // if (!ignoreUnresolvedEntry) throw new JavaModelException(status);
2324 // IClasspathEntry[] containerEntries =
2325 // container.getClasspathEntries();
2326 // if (containerEntries == null) break;
2328 // // container was bound
2329 // for (int j = 0, containerLength = containerEntries.length; j <
2330 // containerLength; j++){
2331 // IClasspathEntry cEntry = containerEntries[j];
2333 // if (generateMarkerOnError) {
2334 // IJavaModelStatus containerStatus =
2335 // JavaConventions.validateClasspathEntry(this, cEntry, false);
2336 // if (!containerStatus.isOK())
2337 // createClasspathProblemMarker(containerStatus);
2339 // // if container is exported, then its nested entries must in turn
2340 // be exported (21749)
2341 // if (rawEntry.isExported()){
2342 // cEntry = new ClasspathEntry(cEntry.getContentKind(),
2343 // cEntry.getEntryKind(), cEntry.getPath(),
2344 // cEntry.getExclusionPatterns(), cEntry.getSourceAttachmentPath(),
2345 // cEntry.getSourceAttachmentRootPath(), cEntry.getOutputLocation(),
2346 // true); // duplicate container entry for tagging it as exported
2348 // if (reverseMap != null && reverseMap.get(resolvedPath =
2349 // cEntry.getPath()) == null) reverseMap.put(resolvedPath,
2351 // resolvedEntries.add(cEntry);
2357 if (reverseMap != null
2358 && reverseMap.get(resolvedPath = rawEntry.getPath()) == null)
2359 reverseMap.put(resolvedPath, rawEntry);
2360 resolvedEntries.add(rawEntry);
2365 IClasspathEntry[] resolvedPath = new IClasspathEntry[resolvedEntries
2367 resolvedEntries.toArray(resolvedPath);
2369 // if (generateMarkerOnError && projectOutputLocation != null) {
2370 // status = JavaConventions.validateClasspath(this, resolvedPath,
2371 // projectOutputLocation);
2372 // if (!status.isOK()) createClasspathProblemMarker(status);
2374 return resolvedPath;
2380 public IResource getResource() {
2381 return this.getProject();
2387 public ISearchableNameEnvironment getSearchableNameEnvironment()
2388 throws JavaModelException {
2390 // JavaProjectElementInfo info = getJavaProjectElementInfo();
2391 // if (info.getSearchableEnvironment() == null) {
2392 // info.setSearchableEnvironment(new SearchableEnvironment(this));
2394 // return info.getSearchableEnvironment();
2399 * Retrieve a shared property on a project. If the property is not defined,
2400 * answers null. Note that it is orthogonal to IResource persistent
2401 * properties, and client code has to decide which form of storage to use
2402 * appropriately. Shared properties produce real resource files which can be
2403 * shared through a VCM onto a server. Persistent properties are not
2406 * @see JavaProject#setSharedProperty(String, String)
2408 public String getSharedProperty(String key) throws CoreException {
2410 String property = null;
2411 IFile rscFile = getProject().getFile(key);
2412 if (rscFile.exists()) {
2413 property = new String(Util.getResourceContentsAsByteArray(rscFile));
2421 // public SourceMapper getSourceMapper() {
2428 public IResource getUnderlyingResource() throws JavaModelException {
2430 throw newNotPresentException();
2431 return getProject();
2437 public boolean hasBuildState() {
2439 return JavaModelManager.getJavaModelManager().getLastBuiltState(
2440 this.getProject(), null) != null;
2446 public boolean hasClasspathCycle(IClasspathEntry[] preferredClasspath) {
2447 HashSet cycleParticipants = new HashSet();
2448 updateCycleParticipants(preferredClasspath, new ArrayList(2),
2449 cycleParticipants, ResourcesPlugin.getWorkspace().getRoot(),
2451 return !cycleParticipants.isEmpty();
2454 public boolean hasCycleMarker() {
2455 return this.getCycleMarker() != null;
2458 public int hashCode() {
2459 return project.hashCode();
2463 * Returns true if the given project is accessible and it has a java nature,
2466 public static boolean hasJavaNature(IProject project) {
2468 return project.hasNature(PHPeclipsePlugin.PHP_NATURE_ID);
2469 } catch (CoreException e) {
2470 // project does not exist or is not open
2476 * Answers true if the project potentially contains any source. A project
2477 * which has no source is immutable.
2479 public boolean hasSource() {
2481 // look if any source folder on the classpath
2482 // no need for resolved path given source folder cannot be abstracted
2483 IClasspathEntry[] entries;
2485 entries = this.getRawClasspath();
2486 } catch (JavaModelException e) {
2487 return true; // unsure
2489 for (int i = 0, max = entries.length; i < max; i++) {
2490 if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
2498 * Compare current classpath with given one to see if any different. Note
2499 * that the argument classpath contains its binary output.
2501 public boolean isClasspathEqualsTo(IClasspathEntry[] newClasspath,
2502 IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput)
2503 throws JavaModelException {
2505 if (otherClasspathWithOutput != null
2506 && otherClasspathWithOutput.length > 0) {
2508 int length = otherClasspathWithOutput.length;
2509 if (length == newClasspath.length + 1) {
2510 // output is amongst file entries (last one)
2512 // compare classpath entries
2513 for (int i = 0; i < length - 1; i++) {
2514 if (!otherClasspathWithOutput[i].equals(newClasspath[i]))
2517 // compare binary outputs
2518 IClasspathEntry output = otherClasspathWithOutput[length - 1];
2519 if (output.getContentKind() == ClasspathEntry.K_OUTPUT
2520 && output.getPath().equals(newOutputLocation))
2530 public boolean isOnClasspath(IJavaElement element) {
2531 IPath path = element.getPath();
2532 switch (element.getElementType()) {
2533 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
2534 if (!((IPackageFragmentRoot) element).isArchive()) {
2535 // ensure that folders are only excluded if all of their
2536 // children are excluded
2537 path = path.append("*"); //$NON-NLS-1$
2540 case IJavaElement.PACKAGE_FRAGMENT:
2541 if (!((IPackageFragmentRoot) element.getParent()).isArchive()) {
2542 // ensure that folders are only excluded if all of their
2543 // children are excluded
2544 path = path.append("*"); //$NON-NLS-1$
2548 return this.isOnClasspath(path);
2551 private boolean isOnClasspath(IPath path) {
2552 IClasspathEntry[] classpath;
2555 .getResolvedClasspath(true/* ignore unresolved variable */);
2556 } catch (JavaModelException e) {
2557 return false; // not a Java project
2559 for (int i = 0; i < classpath.length; i++) {
2560 IClasspathEntry entry = classpath[i];
2561 if (entry.getPath().isPrefixOf(path)
2562 && !Util.isExcluded(path, null, ((ClasspathEntry) entry)
2563 .fullExclusionPatternChars(), true)) {
2573 public boolean isOnClasspath(IResource resource) {
2574 IPath path = resource.getFullPath();
2576 // ensure that folders are only excluded if all of their children are
2578 if (resource.getType() == IResource.FOLDER) {
2579 path = path.append("*"); //$NON-NLS-1$
2582 return this.isOnClasspath(path);
2585 private IPath getPluginWorkingLocation() {
2586 return this.project.getWorkingLocation(JavaCore.PLUGIN_ID);
2590 * load preferences from a shareable format (VCM-wise)
2592 public Preferences loadPreferences() {
2594 Preferences preferences = new Preferences();
2597 // getProject().getLocation().append(PREF_FILENAME).toFile();
2598 IPath projectMetaLocation = getPluginWorkingLocation();
2599 if (projectMetaLocation != null) {
2600 File prefFile = projectMetaLocation.append(PREF_FILENAME).toFile();
2601 if (prefFile.exists()) { // load preferences from file
2602 InputStream in = null;
2604 in = new BufferedInputStream(new FileInputStream(prefFile));
2605 preferences.load(in);
2607 } catch (IOException e) { // problems loading preference store
2613 } catch (IOException e) { // ignore problems with
2624 * @see IJavaProject#newEvaluationContext
2626 // public IEvaluationContext newEvaluationContext() {
2628 // return new EvaluationContextWrapper(new EvaluationContext(), this);
2633 // public ITypeHierarchy newTypeHierarchy(
2635 // IProgressMonitor monitor)
2636 // throws JavaModelException {
2638 // if (region == null) {
2640 // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullRegion"));//$NON-NLS-1$
2642 // CreateTypeHierarchyOperation op =
2643 // new CreateTypeHierarchyOperation(null, region, this, true);
2644 // runOperation(op, monitor);
2645 // return op.getResult();
2650 // public ITypeHierarchy newTypeHierarchy(
2653 // IProgressMonitor monitor)
2654 // throws JavaModelException {
2656 // if (type == null) {
2658 // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullFocusType"));//$NON-NLS-1$
2660 // if (region == null) {
2662 // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullRegion"));//$NON-NLS-1$
2664 // CreateTypeHierarchyOperation op =
2665 // new CreateTypeHierarchyOperation(type, region, this, true);
2666 // runOperation(op, monitor);
2667 // return op.getResult();
2670 // * Open project if resource isn't closed
2672 // protected void openWhenClosed(IProgressMonitor pm) throws
2673 // JavaModelException {
2675 // if (!this.fProject.isOpen()) {
2676 // throw newNotPresentException();
2678 // super.openWhenClosed(pm);
2681 public String[] projectPrerequisites(IClasspathEntry[] entries)
2682 throws JavaModelException {
2684 ArrayList prerequisites = new ArrayList();
2686 entries = getResolvedClasspath(entries, null, true, false, null/*
2691 for (int i = 0, length = entries.length; i < length; i++) {
2692 IClasspathEntry entry = entries[i];
2693 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
2694 prerequisites.add(entry.getPath().lastSegment());
2697 int size = prerequisites.size();
2699 return NO_PREREQUISITES;
2701 String[] result = new String[size];
2702 prerequisites.toArray(result);
2708 * Reads the .classpath file from disk and returns the list of entries it
2709 * contains (including output location entry) Returns null if .classfile is
2710 * not present. Returns INVALID_CLASSPATH if it has a format problem.
2712 protected IClasspathEntry[] readClasspathFile(boolean createMarker,
2713 boolean logProblems) {
2716 String xmlClasspath = getSharedProperty(CLASSPATH_FILENAME);
2717 if (xmlClasspath == null)
2719 return decodeClasspath(xmlClasspath, createMarker, logProblems);
2720 } catch (CoreException e) {
2721 // file does not exist (or not accessible)
2722 if (createMarker && this.getProject().isAccessible()) {
2724 .createClasspathProblemMarker(new JavaModelStatus(
2725 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
2728 "classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
2731 Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$
2732 + "/.classpath, will revert to default classpath"); //$NON-NLS-1$
2739 * Removes the given builder from the build spec for the given project.
2741 protected void removeFromBuildSpec(String builderID) throws CoreException {
2743 IProjectDescription description = getProject().getDescription();
2744 ICommand[] commands = description.getBuildSpec();
2745 for (int i = 0; i < commands.length; ++i) {
2746 if (commands[i].getBuilderName().equals(builderID)) {
2747 ICommand[] newCommands = new ICommand[commands.length - 1];
2748 System.arraycopy(commands, 0, newCommands, 0, i);
2749 System.arraycopy(commands, i + 1, newCommands, i,
2750 commands.length - i - 1);
2751 description.setBuildSpec(newCommands);
2752 getProject().setDescription(description, null);
2759 * @see JavaElement#rootedAt(IJavaProject)
2761 public IJavaElement rootedAt(IJavaProject project) {
2767 * Answers an ID which is used to distinguish project/entries during package
2768 * fragment root computations
2770 public String rootID() {
2771 return "[PRJ]" + this.getProject().getFullPath(); //$NON-NLS-1$
2775 * Saves the classpath in a shareable format (VCM-wise) only when necessary,
2776 * that is, if it is semantically different from the existing one in file.
2777 * Will never write an identical one.
2779 * @return Return whether the .classpath file was modified.
2781 public boolean saveClasspath(IClasspathEntry[] newClasspath,
2782 IPath newOutputLocation) throws JavaModelException {
2784 if (!getProject().exists())
2787 IClasspathEntry[] fileEntries = readClasspathFile(
2788 false /* don't create markers */, false/* don't log problems */);
2789 if (fileEntries != null
2790 && isClasspathEqualsTo(newClasspath, newOutputLocation,
2792 // no need to save it, it is the same
2796 // actual file saving
2798 setSharedProperty(CLASSPATH_FILENAME, encodeClasspath(newClasspath,
2799 newOutputLocation, true));
2801 } catch (CoreException e) {
2802 throw new JavaModelException(e);
2807 * Save project custom preferences to shareable file (.jprefs)
2809 private void savePreferences(Preferences preferences) {
2811 if (!JavaProject.hasJavaNature(this.project))
2814 if (preferences == null
2815 || (!preferences.needsSaving() && preferences.propertyNames().length != 0)) {
2820 // preferences need to be saved
2821 // the preferences file is located in the plug-in's state area
2822 // at a well-known name (.jprefs)
2824 // this.project.getLocation().append(PREF_FILENAME).toFile();
2825 File prefFile = getPluginWorkingLocation().append(PREF_FILENAME)
2827 if (preferences.propertyNames().length == 0) {
2828 // there are no preference settings
2829 // rather than write an empty file, just delete any existing file
2830 if (prefFile.exists()) {
2831 prefFile.delete(); // don't worry if delete unsuccessful
2836 // write file, overwriting an existing one
2837 OutputStream out = null;
2839 // do it as carefully as we know how so that we don't lose/mangle
2840 // the setting in times of stress
2841 out = new BufferedOutputStream(new FileOutputStream(prefFile));
2842 preferences.store(out, null);
2843 } catch (IOException e) { // problems saving preference store -
2849 } catch (IOException e) { // ignore problems with close
2856 * Update the Java command in the build spec (replace existing one if
2857 * present, add one first if none).
2859 private void setJavaCommand(IProjectDescription description,
2860 ICommand newCommand) throws CoreException {
2862 ICommand[] oldCommands = description.getBuildSpec();
2863 ICommand oldJavaCommand = getJavaCommand(description);
2864 ICommand[] newCommands;
2866 if (oldJavaCommand == null) {
2867 // Add a Java build spec before other builders (1FWJK7I)
2868 newCommands = new ICommand[oldCommands.length + 1];
2870 .arraycopy(oldCommands, 0, newCommands, 1,
2871 oldCommands.length);
2872 newCommands[0] = newCommand;
2874 for (int i = 0, max = oldCommands.length; i < max; i++) {
2875 if (oldCommands[i] == oldJavaCommand) {
2876 oldCommands[i] = newCommand;
2880 newCommands = oldCommands;
2883 // Commit the spec change into the project
2884 description.setBuildSpec(newCommands);
2885 getProject().setDescription(description, null);
2889 * @see net.sourceforge.phpdt.core.IJavaProject#setOptions(Map)
2891 public void setOptions(Map newOptions) {
2893 Preferences preferences;
2894 setPreferences(preferences = new Preferences()); // always reset
2896 if (newOptions != null) {
2897 Iterator keys = newOptions.keySet().iterator();
2898 while (keys.hasNext()) {
2899 String key = (String) keys.next();
2900 if (!JavaModelManager.OptionNames.contains(key))
2901 continue; // unrecognized option
2902 // no filtering for encoding (custom encoding for project is
2904 String value = (String) newOptions.get(key);
2905 preferences.setDefault(key, CUSTOM_DEFAULT_OPTION_VALUE); // empty
2911 preferences.setValue(key, value);
2916 savePreferences(preferences);
2922 public void setOutputLocation(IPath path, IProgressMonitor monitor)
2923 throws JavaModelException {
2926 throw new IllegalArgumentException(Util.bind("path.nullpath")); //$NON-NLS-1$
2928 if (path.equals(getOutputLocation())) {
2931 this.setRawClasspath(SetClasspathOperation.ReuseClasspath, path,
2936 * Set cached preferences, no preference file is saved, only info is updated
2938 public void setPreferences(Preferences preferences) {
2939 IProject project = getProject();
2940 if (!JavaProject.hasJavaNature(project))
2942 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager
2943 .getJavaModelManager().getPerProjectInfo(project, true);
2944 perProjectInfo.preferences = preferences;
2950 public void setRawClasspath(IClasspathEntry[] entries,
2951 IPath outputLocation, IProgressMonitor monitor)
2952 throws JavaModelException {
2954 setRawClasspath(entries, outputLocation, monitor, true, // canChangeResource
2957 getResolvedClasspath(true), // ignoreUnresolvedVariable
2958 true, // needValidation
2959 true); // need to save
2962 public void setRawClasspath(IClasspathEntry[] newEntries,
2963 IPath newOutputLocation, IProgressMonitor monitor,
2964 boolean canChangeResource, IClasspathEntry[] oldResolvedPath,
2965 boolean needValidation, boolean needSave) throws JavaModelException {
2967 JavaModelManager manager = (JavaModelManager) JavaModelManager
2968 .getJavaModelManager();
2970 IClasspathEntry[] newRawPath = newEntries;
2971 if (newRawPath == null) { // are we already with the default
2973 newRawPath = defaultClasspath();
2975 SetClasspathOperation op = new SetClasspathOperation(this,
2976 oldResolvedPath, newRawPath, newOutputLocation,
2977 canChangeResource, needValidation, needSave);
2978 runOperation(op, monitor);
2980 } catch (JavaModelException e) {
2989 public void setRawClasspath(IClasspathEntry[] entries,
2990 IProgressMonitor monitor) throws JavaModelException {
2992 setRawClasspath(entries, SetClasspathOperation.ReuseOutputLocation,
2993 monitor, true, // canChangeResource (as per API contract)
2994 getResolvedClasspath(true), // ignoreUnresolvedVariable
2995 true, // needValidation
2996 true); // need to save
3000 * NOTE: <code>null</code> specifies default classpath, and an empty array
3001 * specifies an empty classpath.
3003 * @exception NotPresentException
3004 * if this project does not exist.
3006 // protected void setRawClasspath0(IClasspathEntry[] rawEntries)
3007 // throws JavaModelException {
3009 // JavaModelManager.PerProjectInfo info =
3010 // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
3012 // synchronized (info) {
3013 // if (rawEntries != null) {
3014 // info.classpath = rawEntries;
3017 // // clear cache of resolved classpath
3018 // info.lastResolvedClasspath = null;
3019 // info.resolvedPathToRawEntries = null;
3023 * Record a shared persistent property onto a project. Note that it is
3024 * orthogonal to IResource persistent properties, and client code has to
3025 * decide which form of storage to use appropriately. Shared properties
3026 * produce real resource files which can be shared through a VCM onto a
3027 * server. Persistent properties are not shareable.
3029 * shared properties end up in resource files, and thus cannot be modified
3030 * during delta notifications (a CoreException would then be thrown).
3032 * @see JavaProject#getSharedProperty(String key)
3034 public void setSharedProperty(String key, String value)
3035 throws CoreException {
3037 IFile rscFile = getProject().getFile(key);
3038 InputStream inputStream = new ByteArrayInputStream(value.getBytes());
3039 // update the resource content
3040 if (rscFile.exists()) {
3041 if (rscFile.isReadOnly()) {
3042 // provide opportunity to checkout read-only .classpath file
3044 ResourcesPlugin.getWorkspace().validateEdit(
3045 new IFile[] { rscFile }, null);
3047 rscFile.setContents(inputStream, IResource.FORCE, null);
3049 rscFile.create(inputStream, IResource.FORCE, null);
3054 * Update cycle markers for all java projects
3056 public static void updateAllCycleMarkers() throws JavaModelException {
3058 // long start = System.currentTimeMillis();
3060 JavaModelManager manager = JavaModelManager.getJavaModelManager();
3061 IJavaProject[] projects = manager.getJavaModel().getJavaProjects();
3062 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
3064 HashSet cycleParticipants = new HashSet();
3065 HashSet traversed = new HashSet();
3066 int length = projects.length;
3068 // compute cycle participants
3069 ArrayList prereqChain = new ArrayList();
3070 for (int i = 0; i < length; i++) {
3071 JavaProject project = (JavaProject) projects[i];
3072 if (!traversed.contains(project.getPath())) {
3073 prereqChain.clear();
3074 project.updateCycleParticipants(null, prereqChain,
3075 cycleParticipants, workspaceRoot, traversed);
3078 // System.out.println("updateAllCycleMarkers: " +
3079 // (System.currentTimeMillis() - start) + " ms");
3081 for (int i = 0; i < length; i++) {
3082 JavaProject project = (JavaProject) projects[i];
3084 if (cycleParticipants.contains(project.getPath())) {
3085 IMarker cycleMarker = project.getCycleMarker();
3086 String circularCPOption = project.getOption(
3087 JavaCore.CORE_CIRCULAR_CLASSPATH, true);
3088 int circularCPSeverity = JavaCore.ERROR
3089 .equals(circularCPOption) ? IMarker.SEVERITY_ERROR
3090 : IMarker.SEVERITY_WARNING;
3091 if (cycleMarker != null) {
3092 // update existing cycle marker if needed
3094 int existingSeverity = ((Integer) cycleMarker
3095 .getAttribute(IMarker.SEVERITY)).intValue();
3096 if (existingSeverity != circularCPSeverity) {
3097 cycleMarker.setAttribute(IMarker.SEVERITY,
3098 circularCPSeverity);
3100 } catch (CoreException e) {
3101 throw new JavaModelException(e);
3104 // create new marker
3106 .createClasspathProblemMarker(new JavaModelStatus(
3107 IJavaModelStatusConstants.CLASSPATH_CYCLE,
3111 project.flushClasspathProblemMarkers(true, false);
3117 * If a cycle is detected, then cycleParticipants contains all the paths of
3118 * projects involved in this cycle (directly and indirectly), no cycle if
3119 * the set is empty (and started empty)
3121 public void updateCycleParticipants(IClasspathEntry[] preferredClasspath,
3122 ArrayList prereqChain, HashSet cycleParticipants,
3123 IWorkspaceRoot workspaceRoot, HashSet traversed) {
3125 IPath path = this.getPath();
3126 prereqChain.add(path);
3127 traversed.add(path);
3129 IClasspathEntry[] classpath = preferredClasspath == null ? getResolvedClasspath(true)
3130 : preferredClasspath;
3131 for (int i = 0, length = classpath.length; i < length; i++) {
3132 IClasspathEntry entry = classpath[i];
3134 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
3135 IPath prereqProjectPath = entry.getPath();
3136 int index = cycleParticipants.contains(prereqProjectPath) ? 0
3137 : prereqChain.indexOf(prereqProjectPath);
3138 if (index >= 0) { // refer to cycle, or in cycle itself
3139 for (int size = prereqChain.size(); index < size; index++) {
3140 cycleParticipants.add(prereqChain.get(index));
3143 if (!traversed.contains(prereqProjectPath)) {
3144 IResource member = workspaceRoot
3145 .findMember(prereqProjectPath);
3147 && member.getType() == IResource.PROJECT) {
3148 JavaProject project = (JavaProject) JavaCore
3149 .create((IProject) member);
3150 project.updateCycleParticipants(null,
3151 prereqChain, cycleParticipants,
3152 workspaceRoot, traversed);
3158 } catch (JavaModelException e) {
3160 prereqChain.remove(path);
3164 * Reset the collection of package fragment roots (local ones) - only if
3165 * opened. Need to check *all* package fragment roots in order to reset
3168 public void updatePackageFragmentRoots() {
3170 if (this.isOpen()) {
3172 JavaProjectElementInfo info = getJavaProjectElementInfo();
3174 IClasspathEntry[] classpath = getResolvedClasspath(true);
3175 // NameLookup lookup = info.getNameLookup();
3176 // if (lookup != null){
3177 // IPackageFragmentRoot[] oldRoots =
3178 // lookup.fPackageFragmentRoots;
3179 // IPackageFragmentRoot[] newRoots =
3180 // computePackageFragmentRoots(classpath, true);
3181 // checkIdentical: { // compare all pkg fragment root lists
3182 // if (oldRoots.length == newRoots.length){
3183 // for (int i = 0, length = oldRoots.length; i < length; i++){
3184 // if (!oldRoots[i].equals(newRoots[i])){
3185 // break checkIdentical;
3188 // return; // no need to update
3191 // info.setNameLookup(null); // discard name lookup (hold onto
3194 info.setNonJavaResources(null);
3195 info.setChildren(computePackageFragmentRoots(classpath, false));
3197 } catch (JavaModelException e) {
3199 close(); // could not do better
3200 } catch (JavaModelException ex) {
3206 public void removeLoadPathEntry(IProject anotherPHPProject) {
3207 Iterator entries = getLoadPathEntries().iterator();
3208 while (entries.hasNext()) {
3209 LoadPathEntry entry = (LoadPathEntry) entries.next();
3210 if (entry.getType() == LoadPathEntry.TYPE_PROJECT
3211 && entry.getProject().getName().equals(
3212 anotherPHPProject.getName())) {
3213 getLoadPathEntries().remove(entry);
3220 public void save() throws CoreException {
3222 InputStream xmlPath = new ByteArrayInputStream(getLoadPathXML()
3224 IFile loadPathsFile = getLoadPathEntriesFile();
3225 if (!loadPathsFile.exists())
3226 loadPathsFile.create(xmlPath, true, null);
3228 loadPathsFile.setContents(xmlPath, true, false, null);