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;
54 import net.sourceforge.phpdt.internal.corext.Assert;
55 import net.sourceforge.phpeclipse.LoadPathEntry;
56 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
58 import org.eclipse.core.resources.ICommand;
59 import org.eclipse.core.resources.IFile;
60 import org.eclipse.core.resources.IFolder;
61 import org.eclipse.core.resources.IMarker;
62 import org.eclipse.core.resources.IProject;
63 import org.eclipse.core.resources.IProjectDescription;
64 import org.eclipse.core.resources.IProjectNature;
65 import org.eclipse.core.resources.IResource;
66 import org.eclipse.core.resources.IWorkspace;
67 import org.eclipse.core.resources.IWorkspaceRoot;
68 import org.eclipse.core.resources.ResourcesPlugin;
69 import org.eclipse.core.runtime.CoreException;
70 import org.eclipse.core.runtime.IPath;
71 import org.eclipse.core.runtime.IProgressMonitor;
72 import org.eclipse.core.runtime.Path;
73 import org.eclipse.core.runtime.Preferences;
74 import org.eclipse.core.runtime.QualifiedName;
75 import org.w3c.dom.Element;
76 import org.w3c.dom.Node;
77 import org.w3c.dom.NodeList;
78 import org.xml.sax.Attributes;
79 import org.xml.sax.ContentHandler;
80 import org.xml.sax.InputSource;
81 import org.xml.sax.Locator;
82 import org.xml.sax.SAXException;
83 import org.xml.sax.XMLReader;
86 * Handle for a Java Project.
89 * A Java Project internally maintains a devpath that corresponds to the
90 * project's classpath. The classpath may include source folders from the
91 * current project; jars in the current project, other projects, and the local
92 * file system; and binary folders (output location) of other projects. The Java
93 * Model presents source elements corresponding to output .class files in other
94 * projects, and thus uses the devpath rather than the classpath (which is
95 * really a compilation path). The devpath mimics the classpath, except has
96 * source folder entries in place of output locations in external projects.
99 * Each JavaProject has a NameLookup facility that locates elements on by name,
100 * based on the devpath.
104 public class JavaProject extends Openable implements IJavaProject,
108 * Whether the underlying file system is case sensitive.
110 protected static final boolean IS_CASE_SENSITIVE = !new File("Temp").equals(new File("temp")); //$NON-NLS-1$ //$NON-NLS-2$
113 * An empty array of strings indicating that a project doesn't have any
114 * prerequesite projects.
116 protected static final String[] NO_PREREQUISITES = new String[0];
119 * The platform project this <code>IJavaProject</code> is based on
121 protected IProject project;
123 protected List fLoadPathEntries;
125 protected boolean fScratched;
128 * Name of file containing project classpath
130 public static final String CLASSPATH_FILENAME = ".classpath"; //$NON-NLS-1$
133 * Name of file containing custom project preferences
135 public static final String PREF_FILENAME = ".jprefs"; //$NON-NLS-1$
138 * Value of the project's raw classpath if the .classpath file contains
141 public static final IClasspathEntry[] INVALID_CLASSPATH = new IClasspathEntry[0];
143 private static final String CUSTOM_DEFAULT_OPTION_VALUE = "#\r\n\r#custom-non-empty-default-value#\r\n\r#"; //$NON-NLS-1$
146 * Value of project's resolved classpath while it is being resolved
148 private static final IClasspathEntry[] RESOLUTION_IN_PROGRESS = new IClasspathEntry[0];
151 * Returns a canonicalized path from the given external path. Note that the
152 * return path contains the same number of segments and it contains a device
153 * only if the given path contained one.
155 * @see java.io.File for the definition of a canonicalized path
157 public static IPath canonicalizedPath(IPath externalPath) {
159 if (externalPath == null)
162 if (JavaModelManager.VERBOSE) {
164 .println("JAVA MODEL - Canonicalizing " + externalPath.toString()); //$NON-NLS-1$
167 if (IS_CASE_SENSITIVE) {
168 if (JavaModelManager.VERBOSE) {
170 .println("JAVA MODEL - Canonical path is original path (file system is case sensitive)"); //$NON-NLS-1$
175 // if not external path, return original path
176 IWorkspace workspace = ResourcesPlugin.getWorkspace();
177 if (workspace == null)
178 return externalPath; // protection during shutdown (30487)
179 if (workspace.getRoot().findMember(externalPath) != null) {
180 if (JavaModelManager.VERBOSE) {
182 .println("JAVA MODEL - Canonical path is original path (member of workspace)"); //$NON-NLS-1$
187 IPath canonicalPath = null;
189 canonicalPath = new Path(new File(externalPath.toOSString())
190 .getCanonicalPath());
191 } catch (IOException e) {
192 // default to original path
193 if (JavaModelManager.VERBOSE) {
195 .println("JAVA MODEL - Canonical path is original path (IOException)"); //$NON-NLS-1$
201 int canonicalLength = canonicalPath.segmentCount();
202 if (canonicalLength == 0) {
203 // the java.io.File canonicalization failed
204 if (JavaModelManager.VERBOSE) {
206 .println("JAVA MODEL - Canonical path is original path (canonical path is empty)"); //$NON-NLS-1$
209 } else if (externalPath.isAbsolute()) {
210 result = canonicalPath;
212 // if path is relative, remove the first segments that were added by
213 // the java.io.File canonicalization
214 // e.g. 'lib/classes.zip' was converted to
215 // 'd:/myfolder/lib/classes.zip'
216 int externalLength = externalPath.segmentCount();
217 if (canonicalLength >= externalLength) {
218 result = canonicalPath.removeFirstSegments(canonicalLength
221 if (JavaModelManager.VERBOSE) {
223 .println("JAVA MODEL - Canonical path is original path (canonical path is " + canonicalPath.toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
229 // keep device only if it was specified (this is because
230 // File.getCanonicalPath() converts '/lib/classed.zip' to
231 // 'd:/lib/classes/zip')
232 if (externalPath.getDevice() == null) {
233 result = result.setDevice(null);
235 if (JavaModelManager.VERBOSE) {
237 .println("JAVA MODEL - Canonical path is " + result.toString()); //$NON-NLS-1$
243 * Constructor needed for <code>IProject.getNature()</code> and
244 * <code>IProject.addNature()</code>.
246 * @see #setProject(IProject)
248 public JavaProject() {
252 public JavaProject(IProject project, JavaElement parent) {
253 super(parent, project.getName());
254 this.project = project;
257 public void addLoadPathEntry(IProject anotherPHPProject) {
260 LoadPathEntry newEntry = new LoadPathEntry(anotherPHPProject);
261 getLoadPathEntries().add(newEntry);
264 public void configure() throws CoreException {
265 // get project description and then the associated build commands
266 IProjectDescription desc = project.getDescription();
267 ICommand[] commands = desc.getBuildSpec();
269 // determine if builder already associated
270 boolean found = false;
271 for (int i = 0; i < commands.length; ++i) {
272 if (commands[i].getBuilderName().equals(
273 PHPeclipsePlugin.BUILDER_PARSER_ID)) {
279 // add builder if not already in project
281 ICommand command = desc.newCommand();
282 command.setBuilderName(PHPeclipsePlugin.BUILDER_PARSER_ID);
283 ICommand[] newCommands = new ICommand[commands.length + 1];
285 // Add it before other builders.
286 System.arraycopy(commands, 0, newCommands, 1, commands.length);
287 newCommands[0] = command;
288 desc.setBuildSpec(newCommands);
289 project.setDescription(desc, null);
293 protected void loadLoadPathEntries() {
294 fLoadPathEntries = new ArrayList();
296 IFile loadPathsFile = getLoadPathEntriesFile();
298 XMLReader reader = null;
300 reader = SAXParserFactory.newInstance().newSAXParser()
302 reader.setContentHandler(getLoadPathEntriesContentHandler());
303 reader.parse(new InputSource(loadPathsFile.getContents()));
304 } catch (Exception e) {
305 // the file is nonextant or unreadable
309 public List getLoadPathEntries() {
310 if (fLoadPathEntries == null) {
311 loadLoadPathEntries();
314 return fLoadPathEntries;
317 protected ContentHandler getLoadPathEntriesContentHandler() {
318 return new ContentHandler() {
319 public void characters(char[] arg0, int arg1, int arg2)
320 throws SAXException {
323 public void endDocument() throws SAXException {
326 public void endElement(String arg0, String arg1, String arg2)
327 throws SAXException {
330 public void endPrefixMapping(String arg0) throws SAXException {
333 public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
334 throws SAXException {
337 public void processingInstruction(String arg0, String arg1)
338 throws SAXException {
341 public void setDocumentLocator(Locator arg0) {
344 public void skippedEntity(String arg0) throws SAXException {
347 public void startDocument() throws SAXException {
350 public void startElement(String namespaceURI, String localName,
351 String qName, Attributes atts) throws SAXException {
352 if ("pathentry".equals(qName))
353 if ("project".equals(atts.getValue("type"))) {
354 IPath referencedProjectPath = new Path(atts
356 IProject referencedProject = getProject(referencedProjectPath
358 fLoadPathEntries.add(new LoadPathEntry(
363 public void startPrefixMapping(String arg0, String arg1)
364 throws SAXException {
369 protected IFile getLoadPathEntriesFile() {
370 return project.getFile(".loadpath");
373 protected String getLoadPathXML() {
374 StringBuffer buffer = new StringBuffer();
375 buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><loadpath>");
377 Iterator pathEntriesIterator = fLoadPathEntries.iterator();
379 while (pathEntriesIterator.hasNext()) {
380 LoadPathEntry entry = (LoadPathEntry) pathEntriesIterator.next();
381 buffer.append(entry.toXML());
384 buffer.append("</loadpath>");
385 return buffer.toString();
389 * Adds a builder to the build spec for the given project.
391 protected void addToBuildSpec(String builderID) throws CoreException {
393 IProjectDescription description = getProject().getDescription();
394 ICommand javaCommand = getJavaCommand(description);
396 if (javaCommand == null) {
398 // Add a Java command to the build spec
399 ICommand command = description.newCommand();
400 command.setBuilderName(builderID);
401 setJavaCommand(description, command);
408 protected boolean buildStructure(OpenableElementInfo info,
409 IProgressMonitor pm, Map newElements, IResource underlyingResource)
410 throws JavaModelException {
412 // check whether the java project can be opened
413 if (!underlyingResource.isAccessible()) {
414 throw newNotPresentException();
417 //IWorkspace workspace = ResourcesPlugin.getWorkspace();
418 //IWorkspaceRoot wRoot = workspace.getRoot();
419 // cannot refresh cp markers on opening (emulate cp check on startup)
420 // since can create deadlocks (see bug 37274)
421 // IClasspathEntry[] resolvedClasspath =
422 // getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't
423 // generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
425 // // compute the pkg fragment roots
426 // info.setChildren(computePackageFragmentRoots(resolvedClasspath,
429 // // remember the timestamps of external libraries the first time they
431 // for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
432 // IClasspathEntry entry = resolvedClasspath[i];
433 // if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
434 // IPath path = entry.getPath();
435 // Object target = JavaModel.getTarget(wRoot, path, true);
436 // if (target instanceof java.io.File) {
437 // Map externalTimeStamps =
438 // JavaModelManager.getJavaModelManager().deltaState.externalTimeStamps;
439 // if (externalTimeStamps.get(path) == null) {
440 // long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
441 // externalTimeStamps.put(path, new Long(timestamp));
450 protected void closing(Object info) {
452 // // forget source attachment recommendations
453 // Object[] children = ((JavaElementInfo)info).children;
454 // for (int i = 0, length = children.length; i < length; i++) {
455 // Object child = children[i];
456 // if (child instanceof JarPackageFragmentRoot){
457 // ((JarPackageFragmentRoot)child).setSourceAttachmentProperty(null);
464 // protected void closing(Object info) throws JavaModelException {
466 // // forget source attachment recommendations
467 // IPackageFragmentRoot[] roots = this.getPackageFragmentRoots();
468 // // for (int i = 0; i < roots.length; i++) {
469 // // if (roots[i] instanceof JarPackageFragmentRoot){
470 // // ((JarPackageFragmentRoot) roots[i]).setSourceAttachmentProperty(null);
474 // super.closing(info);
478 * Internal computation of an expanded classpath. It will eliminate
479 * duplicates, and produce copies of exported classpath entries to avoid
480 * possible side-effects ever after.
482 private void computeExpandedClasspath(JavaProject initialProject,
483 boolean ignoreUnresolvedVariable, boolean generateMarkerOnError,
484 HashSet rootIDs, ObjectVector accumulatedEntries,
485 Map preferredClasspaths, Map preferredOutputs)
486 throws JavaModelException {
488 String projectRootId = this.rootID();
489 if (rootIDs.contains(projectRootId)) {
490 return; // break cycles if any
492 rootIDs.add(projectRootId);
494 IClasspathEntry[] preferredClasspath = preferredClasspaths != null ? (IClasspathEntry[]) preferredClasspaths
497 IPath preferredOutput = preferredOutputs != null ? (IPath) preferredOutputs
500 IClasspathEntry[] immediateClasspath = preferredClasspath != null ? getResolvedClasspath(
501 preferredClasspath, preferredOutput, ignoreUnresolvedVariable,
502 generateMarkerOnError, null)
503 : getResolvedClasspath(ignoreUnresolvedVariable,
504 generateMarkerOnError, false/*
506 * returnResolutionInProgress
509 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
510 boolean isInitialProject = this.equals(initialProject);
511 for (int i = 0, length = immediateClasspath.length; i < length; i++) {
512 ClasspathEntry entry = (ClasspathEntry) immediateClasspath[i];
513 if (isInitialProject || entry.isExported()) {
514 String rootID = entry.rootID();
515 if (rootIDs.contains(rootID)) {
519 accumulatedEntries.add(entry);
521 // recurse in project to get all its indirect exports (only
522 // consider exported entries from there on)
523 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
524 IResource member = workspaceRoot
525 .findMember(entry.getPath());
526 if (member != null && member.getType() == IResource.PROJECT) { // double
533 IProject projRsc = (IProject) member;
534 if (JavaProject.hasJavaNature(projRsc)) {
535 JavaProject javaProject = (JavaProject) JavaCore
538 .computeExpandedClasspath(
540 ignoreUnresolvedVariable,
542 * no marker when recursing
545 rootIDs, accumulatedEntries,
558 * Internal computation of an expanded classpath. It will eliminate
559 * duplicates, and produce copies of exported classpath entries to avoid
560 * possible side-effects ever after.
562 // private void computeExpandedClasspath(
563 // JavaProject initialProject,
564 // boolean ignoreUnresolvedVariable,
565 // boolean generateMarkerOnError,
566 // HashSet visitedProjects,
567 // ObjectVector accumulatedEntries) throws JavaModelException {
569 // if (visitedProjects.contains(this)){
570 // return; // break cycles if any
572 // visitedProjects.add(this);
574 // if (generateMarkerOnError && !this.equals(initialProject)){
575 // generateMarkerOnError = false;
577 // IClasspathEntry[] immediateClasspath =
578 // getResolvedClasspath(ignoreUnresolvedVariable, generateMarkerOnError);
580 // IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
581 // for (int i = 0, length = immediateClasspath.length; i < length; i++){
582 // IClasspathEntry entry = immediateClasspath[i];
584 // boolean isInitialProject = this.equals(initialProject);
585 // if (isInitialProject || entry.isExported()){
587 // accumulatedEntries.add(entry);
589 // // recurse in project to get all its indirect exports (only consider
590 // exported entries from there on)
591 // if (entry.getEntryKind() == ClasspathEntry.CPE_PROJECT) {
592 // IResource member = workspaceRoot.findMember(entry.getPath());
593 // if (member != null && member.getType() == IResource.PROJECT){ // double
594 // check if bound to project (23977)
595 // IProject projRsc = (IProject) member;
596 // if (JavaProject.hasJavaNature(projRsc)) {
597 // JavaProject project = (JavaProject) JavaCore.create(projRsc);
598 // project.computeExpandedClasspath(
600 // ignoreUnresolvedVariable,
601 // generateMarkerOnError,
603 // accumulatedEntries);
611 * Returns (local/all) the package fragment roots identified by the given
612 * project's classpath. Note: this follows project classpath references to
613 * find required project contributions, eliminating duplicates silently.
614 * Only works with resolved entries
616 public IPackageFragmentRoot[] computePackageFragmentRoots(
617 IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots)
618 throws JavaModelException {
620 ObjectVector accumulatedRoots = new ObjectVector();
621 computePackageFragmentRoots(resolvedClasspath, accumulatedRoots,
622 new HashSet(5), // rootIDs
623 true, // inside original project
624 true, // check existency
625 retrieveExportedRoots);
626 IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots
628 accumulatedRoots.copyInto(rootArray);
633 * Computes the package fragment roots identified by the given entry. Only
634 * works with resolved entry
636 public IPackageFragmentRoot[] computePackageFragmentRoots(
637 IClasspathEntry resolvedEntry) {
639 return computePackageFragmentRoots(
640 new IClasspathEntry[] { resolvedEntry }, false // don't
645 } catch (JavaModelException e) {
646 return new IPackageFragmentRoot[] {};
651 * Returns the package fragment roots identified by the given entry. In case
652 * it refers to a project, it will follow its classpath so as to find
653 * exported roots as well. Only works with resolved entry
655 public void computePackageFragmentRoots(IClasspathEntry resolvedEntry,
656 ObjectVector accumulatedRoots, HashSet rootIDs,
657 boolean insideOriginalProject, boolean checkExistency,
658 boolean retrieveExportedRoots) throws JavaModelException {
660 String rootID = ((ClasspathEntry) resolvedEntry).rootID();
661 if (rootIDs.contains(rootID))
664 IPath projectPath = getProject().getFullPath();
665 IPath entryPath = resolvedEntry.getPath();
666 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
668 switch (resolvedEntry.getEntryKind()) {
671 case IClasspathEntry.CPE_SOURCE:
673 if (projectPath.isPrefixOf(entryPath)) {
674 if (checkExistency) {
675 Object target = JavaModel.getTarget(workspaceRoot,
676 entryPath, checkExistency);
680 if (target instanceof IFolder || target instanceof IProject) {
682 .add(getPackageFragmentRoot((IResource) target));
686 IPackageFragmentRoot root = getFolderPackageFragmentRoot(entryPath);
688 accumulatedRoots.add(root);
695 // internal/external JAR or folder
696 case IClasspathEntry.CPE_LIBRARY:
698 if (!insideOriginalProject && !resolvedEntry.isExported())
701 if (checkExistency) {
702 Object target = JavaModel.getTarget(workspaceRoot, entryPath,
707 if (target instanceof IResource) {
709 IResource resource = (IResource) target;
710 IPackageFragmentRoot root = getPackageFragmentRoot(resource);
712 accumulatedRoots.add(root);
716 // external target - only JARs allowed
717 // if (((java.io.File)target).isFile() &&
718 // (ProjectPrefUtil.isArchiveFileName(entryPath.lastSegment())))
720 // accumulatedRoots.add(
721 // new JarPackageFragmentRoot(entryPath, this));
722 // rootIDs.add(rootID);
726 IPackageFragmentRoot root = getPackageFragmentRoot(entryPath);
728 accumulatedRoots.add(root);
734 // recurse into required project
735 case IClasspathEntry.CPE_PROJECT:
737 if (!retrieveExportedRoots)
739 if (!insideOriginalProject && !resolvedEntry.isExported())
742 IResource member = workspaceRoot.findMember(entryPath);
743 if (member != null && member.getType() == IResource.PROJECT) {// double
750 IProject requiredProjectRsc = (IProject) member;
751 if (JavaProject.hasJavaNature(requiredProjectRsc)) { // special
756 JavaProject requiredProject = (JavaProject) JavaCore
757 .create(requiredProjectRsc);
758 requiredProject.computePackageFragmentRoots(requiredProject
759 .getResolvedClasspath(true), accumulatedRoots,
760 rootIDs, false, checkExistency,
761 retrieveExportedRoots);
769 * Returns (local/all) the package fragment roots identified by the given
770 * project's classpath. Note: this follows project classpath references to
771 * find required project contributions, eliminating duplicates silently.
772 * Only works with resolved entries
774 public void computePackageFragmentRoots(
775 IClasspathEntry[] resolvedClasspath, ObjectVector accumulatedRoots,
776 HashSet rootIDs, boolean insideOriginalProject,
777 boolean checkExistency, boolean retrieveExportedRoots)
778 throws JavaModelException {
780 if (insideOriginalProject) {
781 rootIDs.add(rootID());
783 for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
784 computePackageFragmentRoots(resolvedClasspath[i], accumulatedRoots,
785 rootIDs, insideOriginalProject, checkExistency,
786 retrieveExportedRoots);
791 * Compute the file name to use for a given shared property
793 public String computeSharedPropertyFileName(QualifiedName qName) {
795 return '.' + qName.getLocalName();
799 * Returns whether the given resource is accessible through the children or
800 * the non-Java resources of this project. Returns true if the resource is
801 * not in the project. Assumes that the resource is a folder or a file.
803 public boolean contains(IResource resource) {
805 IClasspathEntry[] classpath;
808 classpath = getResolvedClasspath(true);
809 output = getOutputLocation();
810 } catch (JavaModelException e) {
814 IPath fullPath = resource.getFullPath();
815 IPath innerMostOutput = output.isPrefixOf(fullPath) ? output : null;
816 IClasspathEntry innerMostEntry = null;
817 for (int j = 0, cpLength = classpath.length; j < cpLength; j++) {
818 IClasspathEntry entry = classpath[j];
820 IPath entryPath = entry.getPath();
821 if ((innerMostEntry == null || innerMostEntry.getPath().isPrefixOf(
823 && entryPath.isPrefixOf(fullPath)) {
824 innerMostEntry = entry;
826 IPath entryOutput = classpath[j].getOutputLocation();
827 if (entryOutput != null && entryOutput.isPrefixOf(fullPath)) {
828 innerMostOutput = entryOutput;
831 if (innerMostEntry != null) {
832 // special case prj==src and nested output location
833 if (innerMostOutput != null && innerMostOutput.segmentCount() > 1 // output
836 && innerMostEntry.getPath().segmentCount() == 1) { // 1
844 if (resource instanceof IFolder) {
845 // folders are always included in src/lib entries
848 switch (innerMostEntry.getEntryKind()) {
849 case IClasspathEntry.CPE_SOURCE:
850 // .class files are not visible in source folders
851 return true; // !net.sourceforge.phpdt.internal.compiler.util.ProjectPrefUtil.isClassFileName(fullPath.lastSegment());
852 case IClasspathEntry.CPE_LIBRARY:
853 // .java files are not visible in library folders
854 return !net.sourceforge.phpdt.internal.compiler.util.Util
855 .isJavaFileName(fullPath.lastSegment());
858 if (innerMostOutput != null) {
865 * Record a new marker denoting a classpath problem
867 IMarker createClasspathProblemMarker(IJavaModelStatus status) {
869 IMarker marker = null;
871 String[] arguments = new String[0];
872 boolean isCycleProblem = false, isClasspathFileFormatProblem = false;
873 switch (status.getCode()) {
875 case IJavaModelStatusConstants.CLASSPATH_CYCLE:
876 isCycleProblem = true;
877 if (JavaCore.ERROR.equals(getOption(
878 JavaCore.CORE_CIRCULAR_CLASSPATH, true))) {
879 severity = IMarker.SEVERITY_ERROR;
881 severity = IMarker.SEVERITY_WARNING;
885 case IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT:
886 isClasspathFileFormatProblem = true;
887 severity = IMarker.SEVERITY_ERROR;
891 IPath path = status.getPath();
893 arguments = new String[] { path.toString() };
894 if (JavaCore.ERROR.equals(getOption(
895 JavaCore.CORE_INCOMPLETE_CLASSPATH, true))) {
896 severity = IMarker.SEVERITY_ERROR;
898 severity = IMarker.SEVERITY_WARNING;
904 marker = getProject().createMarker(
905 IJavaModelMarker.BUILDPATH_PROBLEM_MARKER);
906 marker.setAttributes(new String[] { IMarker.MESSAGE,
907 IMarker.SEVERITY, IMarker.LOCATION,
908 IJavaModelMarker.CYCLE_DETECTED,
909 IJavaModelMarker.CLASSPATH_FILE_FORMAT,
910 IJavaModelMarker.ID, IJavaModelMarker.ARGUMENTS, },
911 new Object[] { status.getMessage(),
912 new Integer(severity),
913 Util.bind("classpath.buildPath"),//$NON-NLS-1$
914 isCycleProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
915 isClasspathFileFormatProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
916 new Integer(status.getCode()),
917 Util.getProblemArgumentsForMarker(arguments), });
918 } catch (CoreException e) {
924 * Returns a new element info for this element.
926 protected Object createElementInfo() {
927 return new JavaProjectElementInfo();
931 * Returns a new search name environment for this project. This name
932 * environment first looks in the given working copies.
934 // public ISearchableNameEnvironment
935 // newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws
936 // JavaModelException {
937 // return new SearchableEnvironment(this, workingCopies);
940 * Returns a new search name environment for this project. This name
941 * environment first looks in the working copies of the given owner.
943 public ISearchableNameEnvironment newSearchableNameEnvironment(
944 WorkingCopyOwner owner) throws JavaModelException {
945 return new SearchableEnvironment(this, owner);
949 * Reads and decode an XML classpath string
951 protected IClasspathEntry[] decodeClasspath(String xmlClasspath,
952 boolean createMarker, boolean logProblems) {
954 ArrayList paths = new ArrayList();
955 IClasspathEntry defaultOutput = null;
957 if (xmlClasspath == null)
959 StringReader reader = new StringReader(xmlClasspath);
963 DocumentBuilder parser = DocumentBuilderFactory.newInstance()
964 .newDocumentBuilder();
965 cpElement = parser.parse(new InputSource(reader))
966 .getDocumentElement();
967 } catch (SAXException e) {
968 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
969 } catch (ParserConfigurationException e) {
970 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
975 if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$
976 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
978 NodeList list = cpElement.getElementsByTagName("classpathentry"); //$NON-NLS-1$
979 int length = list.getLength();
981 for (int i = 0; i < length; ++i) {
982 Node node = list.item(i);
983 if (node.getNodeType() == Node.ELEMENT_NODE) {
984 IClasspathEntry entry = ClasspathEntry.elementDecode(
985 (Element) node, this);
987 if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
988 defaultOutput = entry; // separate output
995 } catch (IOException e) {
997 if (createMarker && this.getProject().isAccessible()) {
999 .createClasspathProblemMarker(new JavaModelStatus(
1000 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1003 "classpath.xmlFormatError", this.getElementName(), e.getMessage()))); //$NON-NLS-1$
1006 Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$
1007 + "/.classpath, will mark classpath as invalid"); //$NON-NLS-1$
1009 return INVALID_CLASSPATH;
1010 } catch (Assert.AssertionFailedException e) {
1011 // failed creating CP entries from file
1012 if (createMarker && this.getProject().isAccessible()) {
1014 .createClasspathProblemMarker(new JavaModelStatus(
1015 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1018 "classpath.illegalEntryInClasspathFile", this.getElementName(), e.getMessage()))); //$NON-NLS-1$
1021 Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$
1022 + "/.classpath, will mark classpath as invalid"); //$NON-NLS-1$
1024 return INVALID_CLASSPATH;
1026 int pathSize = paths.size();
1027 if (pathSize > 0 || defaultOutput != null) {
1028 IClasspathEntry[] entries = new IClasspathEntry[pathSize
1029 + (defaultOutput == null ? 0 : 1)];
1030 paths.toArray(entries);
1031 if (defaultOutput != null)
1032 entries[pathSize] = defaultOutput; // ensure output is last
1041 * /** Removes the Java nature from the project.
1043 public void deconfigure() throws CoreException {
1045 // deregister Java builder
1046 removeFromBuildSpec(PHPeclipsePlugin.BUILDER_PARSER_ID);
1050 * Returns a default class path. This is the root of the project
1052 protected IClasspathEntry[] defaultClasspath() throws JavaModelException {
1054 return new IClasspathEntry[] { JavaCore.newSourceEntry(getProject()
1059 * Returns a default output location. This is the project bin folder
1061 protected IPath defaultOutputLocation() throws JavaModelException {
1062 return null; // getProject().getFullPath().append("bin");
1067 * Returns the XML String encoding of the class path.
1069 protected String encodeClasspath(IClasspathEntry[] classpath,
1070 IPath outputLocation, boolean indent) throws JavaModelException {
1072 ByteArrayOutputStream s = new ByteArrayOutputStream();
1073 OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
1074 XMLWriter xmlWriter = new XMLWriter(writer);
1076 xmlWriter.startTag("classpath", indent); //$NON-NLS-1$
1077 for (int i = 0; i < classpath.length; ++i) {
1078 ((ClasspathEntry) classpath[i]).elementEncode(xmlWriter,
1079 this.project.getFullPath(), indent, true);
1082 if (outputLocation != null) {
1083 outputLocation = outputLocation.removeFirstSegments(1);
1084 outputLocation = outputLocation.makeRelative();
1085 HashMap parameters = new HashMap();
1088 "kind", ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT));//$NON-NLS-1$
1089 parameters.put("path", String.valueOf(outputLocation));//$NON-NLS-1$
1091 "classpathentry", parameters, indent, true, true);//$NON-NLS-1$
1094 xmlWriter.endTag("classpath", indent);//$NON-NLS-1$
1097 return s.toString("UTF8");//$NON-NLS-1$
1098 } catch (IOException e) {
1099 throw new JavaModelException(e,
1100 IJavaModelStatusConstants.IO_EXCEPTION);
1105 * Returns the XML String encoding of the class path.
1107 // protected String encodeClasspath(IClasspathEntry[] classpath, IPath
1108 // outputLocation, boolean useLineSeparator) throws JavaModelException {
1110 // Document document = new DocumentImpl();
1111 // Element cpElement = document.createElement("classpath"); //$NON-NLS-1$
1112 // document.appendChild(cpElement);
1114 // for (int i = 0; i < classpath.length; ++i) {
1115 // cpElement.appendChild(((ClasspathEntry)classpath[i]).elementEncode(document,
1116 // getProject().getFullPath()));
1119 // if (outputLocation != null) {
1120 // outputLocation = outputLocation.removeFirstSegments(1);
1121 // outputLocation = outputLocation.makeRelative();
1122 // Element oElement = document.createElement("classpathentry");
1124 // oElement.setAttribute("kind",
1125 // ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT)); //$NON-NLS-1$
1126 // oElement.setAttribute("path", outputLocation.toString()); //$NON-NLS-1$
1127 // cpElement.appendChild(oElement);
1130 // // produce a String output
1132 // ByteArrayOutputStream s = new ByteArrayOutputStream();
1133 // OutputFormat format = new OutputFormat();
1134 // if (useLineSeparator) {
1135 // format.setIndenting(true);
1136 // format.setLineSeparator(System.getProperty("line.separator"));
1139 // format.setPreserveSpace(true);
1141 // Serializer serializer =
1142 // SerializerFactory.getSerializerFactory(Method.XML).makeSerializer(
1143 // new OutputStreamWriter(s, "UTF8"), //$NON-NLS-1$
1145 // serializer.asDOMSerializer().serialize(document);
1146 // return s.toString("UTF8"); //$NON-NLS-1$
1147 // } catch (IOException e) {
1148 // throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
1152 * Returns true if this handle represents the same Java project as the given
1153 * handle. Two handles represent the same project if they are identical or
1154 * if they represent a project with the same underlying resource and
1155 * occurrence counts.
1157 * @see JavaElement#equals
1159 public boolean equals(Object o) {
1164 if (!(o instanceof JavaProject))
1167 JavaProject other = (JavaProject) o;
1168 return getProject().equals(other.getProject())
1169 && occurrenceCount == other.occurrenceCount;
1172 public boolean exists() {
1173 if (!hasJavaNature(project))
1175 return super.exists();
1181 public IJavaElement findElement(IPath path) throws JavaModelException {
1183 if (path == null || path.isAbsolute()) {
1184 throw new JavaModelException(new JavaModelStatus(
1185 IJavaModelStatusConstants.INVALID_PATH, path));
1189 String extension = path.getFileExtension();
1190 if (extension == null) {
1191 //String packageName = path.toString().replace(IPath.SEPARATOR, '.');
1193 // IPackageFragment[] pkgFragments =
1194 // getNameLookup().findPackageFragments(packageName, false);
1195 // if (pkgFragments == null) {
1199 // // try to return one that is a child of this project
1200 // for (int i = 0, length = pkgFragments.length; i < length; i++) {
1202 // IPackageFragment pkgFragment = pkgFragments[i];
1203 // if (this.equals(pkgFragment.getParent().getParent())) {
1204 // return pkgFragment;
1207 // // default to the first one
1208 // return pkgFragments[0];
1210 } else if (extension.equalsIgnoreCase("java") //$NON-NLS-1$
1211 || extension.equalsIgnoreCase("class")) { //$NON-NLS-1$
1212 IPath packagePath = path.removeLastSegments(1);
1213 String packageName = packagePath.toString().replace(
1214 IPath.SEPARATOR, '.');
1215 String typeName = path.lastSegment();
1216 typeName = typeName.substring(0, typeName.length()
1217 - extension.length() - 1);
1218 String qualifiedName = null;
1219 if (packageName.length() > 0) {
1220 qualifiedName = packageName + "." + typeName; //$NON-NLS-1$
1222 qualifiedName = typeName;
1225 // getNameLookup().findType(
1228 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1229 // if (type != null) {
1230 // return type.getParent();
1235 // unsupported extension
1238 // } catch (JavaModelException e) {
1239 // if (e.getStatus().getCode()
1240 // == IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST) {
1251 // public IPackageFragment findPackageFragment(IPath path)
1252 // throws JavaModelException {
1254 // return findPackageFragment0(JavaProject.canonicalizedPath(path));
1258 // * non path canonicalizing version
1260 // public IPackageFragment findPackageFragment0(IPath path)
1261 // throws JavaModelException {
1263 // return getNameLookup().findPackageFragment(path);
1268 public IPackageFragmentRoot findPackageFragmentRoot(IPath path)
1269 throws JavaModelException {
1271 return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path));
1275 * no path canonicalization
1277 public IPackageFragmentRoot findPackageFragmentRoot0(IPath path)
1278 throws JavaModelException {
1280 IPackageFragmentRoot[] allRoots = this.getAllPackageFragmentRoots();
1281 if (!path.isAbsolute()) {
1282 throw new IllegalArgumentException(Util.bind("path.mustBeAbsolute")); //$NON-NLS-1$
1284 for (int i = 0; i < allRoots.length; i++) {
1285 IPackageFragmentRoot classpathRoot = allRoots[i];
1286 if (classpathRoot.getPath().equals(path)) {
1287 return classpathRoot;
1296 public IPackageFragmentRoot[] findPackageFragmentRoots(IClasspathEntry entry) {
1298 IClasspathEntry[] classpath = this.getRawClasspath();
1299 for (int i = 0, length = classpath.length; i < length; i++) {
1300 if (classpath[i].equals(entry)) { // entry may need to be
1302 return computePackageFragmentRoots(getResolvedClasspath(
1303 new IClasspathEntry[] { entry }, null, true, false,
1304 null/* no reverse map */), false); // don't
1310 } catch (JavaModelException e) {
1312 return new IPackageFragmentRoot[] {};
1316 * @see IJavaProject#findType(String)
1318 // public IType findType(String fullyQualifiedName) throws
1319 // JavaModelException {
1321 // this.getNameLookup().findType(
1322 // fullyQualifiedName,
1324 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1325 // if (type == null) {
1326 // // try to find enclosing type
1327 // int lastDot = fullyQualifiedName.lastIndexOf('.');
1328 // if (lastDot == -1) return null;
1329 // type = this.findType(fullyQualifiedName.substring(0, lastDot));
1330 // if (type != null) {
1331 // type = type.getType(fullyQualifiedName.substring(lastDot+1));
1332 // if (!type.exists()) {
1340 * @see IJavaProject#findType(String, String)
1342 // public IType findType(String packageName, String typeQualifiedName)
1343 // throws JavaModelException {
1345 // this.getNameLookup().findType(
1346 // typeQualifiedName,
1349 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1353 * Remove all markers denoting classpath problems
1355 protected void flushClasspathProblemMarkers(boolean flushCycleMarkers,
1356 boolean flushClasspathFormatMarkers) {
1358 IProject project = getProject();
1359 if (project.exists()) {
1360 IMarker[] markers = project.findMarkers(
1361 IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false,
1362 IResource.DEPTH_ZERO);
1363 for (int i = 0, length = markers.length; i < length; i++) {
1364 IMarker marker = markers[i];
1365 if (flushCycleMarkers && flushClasspathFormatMarkers) {
1368 String cycleAttr = (String) marker
1369 .getAttribute(IJavaModelMarker.CYCLE_DETECTED);
1370 String classpathFileFormatAttr = (String) marker
1371 .getAttribute(IJavaModelMarker.CLASSPATH_FILE_FORMAT);
1372 if ((flushCycleMarkers == (cycleAttr != null && cycleAttr
1373 .equals("true"))) //$NON-NLS-1$
1374 && (flushClasspathFormatMarkers == (classpathFileFormatAttr != null && classpathFileFormatAttr
1375 .equals("true")))) { //$NON-NLS-1$
1381 } catch (CoreException e) {
1388 // protected boolean generateInfos(
1389 // OpenableElementInfo info,
1390 // IProgressMonitor pm,
1392 // IResource underlyingResource) throws JavaModelException {
1394 // boolean validInfo = false;
1396 // if (getProject().isOpen()) {
1397 // // put the info now, because computing the roots requires it
1398 // JavaModelManager.getJavaModelManager().putInfo(this, info);
1400 // // compute the pkg fragment roots
1401 // updatePackageFragmentRoots();
1403 // // remember the timestamps of external libraries the first time they are
1405 // IClasspathEntry[] resolvedClasspath = getResolvedClasspath(true/*ignore
1406 // unresolved variable*/);
1407 // for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
1408 // IClasspathEntry entry = resolvedClasspath[i];
1409 // if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
1410 // IPath path = entry.getPath();
1412 // JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path,
1414 // if (target instanceof java.io.File) {
1415 // Map externalTimeStamps =
1416 // JavaModelManager.getJavaModelManager().deltaProcessor.externalTimeStamps;
1417 // if (externalTimeStamps.get(path) == null) {
1418 // long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
1419 // externalTimeStamps.put(path, new Long(timestamp));
1425 // // only valid if reaches here
1426 // validInfo = true;
1430 // JavaModelManager.getJavaModelManager().removeInfo(this);
1432 // return validInfo;
1438 public IPackageFragmentRoot[] getAllPackageFragmentRoots()
1439 throws JavaModelException {
1441 return computePackageFragmentRoots(getResolvedClasspath(true), true);
1445 * Returns the classpath entry that refers to the given path or
1446 * <code>null</code> if there is no reference to the path.
1448 public IClasspathEntry getClasspathEntryFor(IPath path)
1449 throws JavaModelException {
1451 IClasspathEntry[] entries = getExpandedClasspath(true);
1452 for (int i = 0; i < entries.length; i++) {
1453 if (entries[i].getPath().equals(path)) {
1461 * Returns the cycle marker associated with this project or null if none.
1463 public IMarker getCycleMarker() {
1465 IProject project = getProject();
1466 if (project.exists()) {
1467 IMarker[] markers = project.findMarkers(
1468 IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false,
1469 IResource.DEPTH_ZERO);
1470 for (int i = 0, length = markers.length; i < length; i++) {
1471 IMarker marker = markers[i];
1472 String cycleAttr = (String) marker
1473 .getAttribute(IJavaModelMarker.CYCLE_DETECTED);
1474 if (cycleAttr != null && cycleAttr.equals("true")) { //$NON-NLS-1$
1479 } catch (CoreException e) {
1487 public int getElementType() {
1488 return JAVA_PROJECT;
1492 * This is a helper method returning the expanded classpath for the project,
1493 * as a list of classpath entries, where all classpath variable entries have
1494 * been resolved and substituted with their final target entries. All
1495 * project exports have been appended to project entries.
1497 * @param ignoreUnresolvedVariable
1499 * @return IClasspathEntry[]
1500 * @throws JavaModelException
1502 public IClasspathEntry[] getExpandedClasspath(
1503 boolean ignoreUnresolvedVariable) throws JavaModelException {
1505 return getExpandedClasspath(ignoreUnresolvedVariable,
1506 false/* don't create markers */, null, null);
1512 public IJavaElement getHandleFromMemento(String token,
1513 MementoTokenizer memento, WorkingCopyOwner owner) {
1514 switch (token.charAt(0)) {
1516 return getHandleUpdatingCountFromMemento(memento, owner);
1517 case JEM_PACKAGEFRAGMENTROOT:
1518 String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
1520 while (memento.hasMoreTokens()) {
1521 token = memento.nextToken();
1522 char firstChar = token.charAt(0);
1523 if (firstChar != JEM_PACKAGEFRAGMENT && firstChar != JEM_COUNT) {
1529 JavaElement root = (JavaElement) getPackageFragmentRoot(new Path(
1531 if (token != null && token.charAt(0) == JEM_PACKAGEFRAGMENT) {
1532 return root.getHandleFromMemento(token, memento, owner);
1534 return root.getHandleFromMemento(memento, owner);
1541 * Returns the <code>char</code> that marks the start of this handles
1542 * contribution to a memento.
1544 protected char getHandleMementoDelimiter() {
1546 return JEM_JAVAPROJECT;
1550 * Internal variant which can create marker on project for invalid entries,
1551 * it will also perform classpath expansion in presence of project
1552 * prerequisites exporting their entries.
1554 * @param ignoreUnresolvedVariable
1556 * @param generateMarkerOnError
1558 * @param preferredClasspaths
1560 * @param preferredOutputs
1562 * @return IClasspathEntry[]
1563 * @throws JavaModelException
1565 public IClasspathEntry[] getExpandedClasspath(
1566 boolean ignoreUnresolvedVariable, boolean generateMarkerOnError,
1567 Map preferredClasspaths, Map preferredOutputs)
1568 throws JavaModelException {
1570 ObjectVector accumulatedEntries = new ObjectVector();
1571 computeExpandedClasspath(this, ignoreUnresolvedVariable,
1572 generateMarkerOnError, new HashSet(5), accumulatedEntries,
1573 preferredClasspaths, preferredOutputs);
1575 IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries
1577 accumulatedEntries.copyInto(expandedPath);
1579 return expandedPath;
1583 // * Internal variant which can create marker on project for invalid
1585 // * it will also perform classpath expansion in presence of project
1587 // * exporting their entries.
1589 // public IClasspathEntry[] getExpandedClasspath(
1590 // boolean ignoreUnresolvedVariable,
1591 // boolean generateMarkerOnError) throws JavaModelException {
1593 // ObjectVector accumulatedEntries = new ObjectVector();
1594 // computeExpandedClasspath(this, ignoreUnresolvedVariable,
1595 // generateMarkerOnError, new HashSet(5), accumulatedEntries);
1597 // IClasspathEntry[] expandedPath = new
1598 // IClasspathEntry[accumulatedEntries.size()];
1599 // accumulatedEntries.copyInto(expandedPath);
1601 // return expandedPath;
1605 * Find the specific Java command amongst the build spec of a given
1608 private ICommand getJavaCommand(IProjectDescription description)
1609 throws CoreException {
1611 ICommand[] commands = description.getBuildSpec();
1612 for (int i = 0; i < commands.length; ++i) {
1613 if (commands[i].getBuilderName().equals(
1614 PHPeclipsePlugin.BUILDER_PARSER_ID)) {
1622 * Convenience method that returns the specific type of info for a Java
1625 protected JavaProjectElementInfo getJavaProjectElementInfo()
1626 throws JavaModelException {
1628 return (JavaProjectElementInfo) getElementInfo();
1634 public NameLookup getNameLookup() throws JavaModelException {
1636 JavaProjectElementInfo info = getJavaProjectElementInfo();
1637 // lock on the project info to avoid race condition
1638 synchronized (info) {
1639 NameLookup nameLookup;
1640 if ((nameLookup = info.getNameLookup()) == null) {
1641 info.setNameLookup(nameLookup = new NameLookup(this));
1648 * Returns a new name lookup. This name lookup first looks in the given
1651 public NameLookup newNameLookup(ICompilationUnit[] workingCopies)
1652 throws JavaModelException {
1654 //JavaProjectElementInfo info = getJavaProjectElementInfo();
1655 // lock on the project info to avoid race condition while computing the
1656 // pkg fragment roots and package fragment caches
1657 // synchronized(info){
1658 // return new NameLookup(info.getAllPackageFragmentRoots(this),
1659 // info.getAllPackageFragments(this), workingCopies);
1665 * Returns a new name lookup. This name lookup first looks in the working
1666 * copies of the given owner.
1668 public NameLookup newNameLookup(WorkingCopyOwner owner)
1669 throws JavaModelException {
1671 JavaModelManager manager = JavaModelManager.getJavaModelManager();
1672 ICompilationUnit[] workingCopies = owner == null ? null : manager
1673 .getWorkingCopies(owner, true/* add primary WCs */);
1674 return newNameLookup(workingCopies);
1679 // * Returns an array of non-java resources contained in the receiver.
1681 // public Object[] getNonJavaResources() throws JavaModelException {
1683 // return ((JavaProjectElementInfo)
1684 // getElementInfo()).getNonJavaResources(this);
1688 * @see net.sourceforge.phpdt.core.IJavaProject#getOption(String, boolean)
1690 public String getOption(String optionName, boolean inheritJavaCoreOptions) {
1692 if (JavaModelManager.OptionNames.contains(optionName)) {
1694 Preferences preferences = getPreferences();
1695 if (preferences == null || preferences.isDefault(optionName)) {
1696 return inheritJavaCoreOptions ? JavaCore.getOption(optionName)
1699 return preferences.getString(optionName).trim();
1705 * @see net.sourceforge.phpdt.core.IJavaProject#getOptions(boolean)
1707 public Map getOptions(boolean inheritJavaCoreOptions) {
1709 // initialize to the defaults from JavaCore options pool
1710 Map options = inheritJavaCoreOptions ? JavaCore.getOptions()
1713 Preferences preferences = getPreferences();
1714 if (preferences == null)
1715 return options; // cannot do better (non-Java project)
1716 HashSet optionNames = JavaModelManager.OptionNames;
1718 // get preferences set to their default
1719 if (inheritJavaCoreOptions) {
1720 String[] defaultPropertyNames = preferences.defaultPropertyNames();
1721 for (int i = 0; i < defaultPropertyNames.length; i++) {
1722 String propertyName = defaultPropertyNames[i];
1723 if (optionNames.contains(propertyName)) {
1724 options.put(propertyName, preferences.getDefaultString(
1725 propertyName).trim());
1729 // get custom preferences not set to their default
1730 String[] propertyNames = preferences.propertyNames();
1731 for (int i = 0; i < propertyNames.length; i++) {
1732 String propertyName = propertyNames[i];
1733 if (optionNames.contains(propertyName)) {
1734 options.put(propertyName, preferences.getString(propertyName)
1744 // public IPath getOutputLocation() throws JavaModelException {
1746 // JavaModelManager.PerProjectInfo perProjectInfo =
1747 // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
1748 // IPath outputLocation = perProjectInfo.outputLocation;
1749 // if (outputLocation != null) return outputLocation;
1751 // // force to read classpath - will position output location as well
1752 // this.getRawClasspath();
1753 // outputLocation = perProjectInfo.outputLocation;
1754 // if (outputLocation == null) {
1755 // return defaultOutputLocation();
1757 // return outputLocation;
1762 public IPath getOutputLocation() throws JavaModelException {
1763 // Do not create marker but log problems while getting output location
1764 return this.getOutputLocation(false, true);
1768 * @param createMarkers
1770 * @param logProblems
1773 * @throws JavaModelException
1775 public IPath getOutputLocation(boolean createMarkers, boolean logProblems)
1776 throws JavaModelException {
1778 JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo();
1779 IPath outputLocation = perProjectInfo.outputLocation;
1780 if (outputLocation != null)
1781 return outputLocation;
1783 // force to read classpath - will position output location as well
1784 this.getRawClasspath(createMarkers, logProblems);
1785 outputLocation = perProjectInfo.outputLocation;
1786 if (outputLocation == null) {
1787 return defaultOutputLocation();
1789 return outputLocation;
1793 * @return A handle to the package fragment root identified by the given
1794 * path. This method is handle-only and the element may or may not
1795 * exist. Returns <code>null</code> if unable to generate a handle
1796 * from the path (for example, an absolute path that has less than 1
1797 * segment. The path may be relative or absolute.
1799 public IPackageFragmentRoot getPackageFragmentRoot(IPath path) {
1800 if (!path.isAbsolute()) {
1801 path = getPath().append(path);
1803 int segmentCount = path.segmentCount();
1804 switch (segmentCount) {
1809 return getPackageFragmentRoot(getProject());
1811 // a path ending with .jar/.zip is still ambiguous and could still
1812 // resolve to a source/lib folder
1813 // thus will try to guess based on existing resource
1814 // if (ProjectPrefUtil.isArchiveFileName(path.lastSegment())) {
1815 // IResource resource =
1816 // getProject().getWorkspace().getRoot().findMember(path);
1817 // if (resource != null && resource.getType() == IResource.FOLDER){
1818 // return getPackageFragmentRoot(resource);
1820 // return getPackageFragmentRoot0(path);
1822 return getPackageFragmentRoot(getProject().getWorkspace().getRoot()
1829 * The path is known to match a source/library folder entry.
1831 public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) {
1832 if (path.segmentCount() == 1) { // default project root
1833 return getPackageFragmentRoot(getProject());
1835 return getPackageFragmentRoot(getProject().getWorkspace().getRoot()
1842 public IPackageFragmentRoot getPackageFragmentRoot(IResource resource) {
1844 switch (resource.getType()) {
1845 case IResource.FILE:
1846 // if (ProjectPrefUtil.isArchiveFileName(resource.getName())) {
1847 // return new JarPackageFragmentRoot(resource, this);
1851 case IResource.FOLDER:
1852 return new PackageFragmentRoot(resource, this, resource.getName());
1853 case IResource.PROJECT:
1854 return new PackageFragmentRoot(resource, this, ""); //$NON-NLS-1$
1863 // public IPackageFragmentRoot getPackageFragmentRoot(String jarPath) {
1865 // return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new
1870 // * no path canonicalization
1872 // public IPackageFragmentRoot getPackageFragmentRoot0(IPath jarPath) {
1874 // return new JarPackageFragmentRoot(jarPath, this);
1879 public IPackageFragmentRoot[] getPackageFragmentRoots()
1880 throws JavaModelException {
1884 IPackageFragmentRoot[] roots;
1886 System.arraycopy(children = getChildren(), 0,
1887 roots = new IPackageFragmentRoot[length = children.length], 0,
1897 public IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry) {
1898 return findPackageFragmentRoots(entry);
1902 * Returns the package fragment root prefixed by the given path, or an empty
1903 * collection if there are no such elements in the model.
1905 protected IPackageFragmentRoot[] getPackageFragmentRoots(IPath path)
1907 throws JavaModelException {
1908 IPackageFragmentRoot[] roots = getAllPackageFragmentRoots();
1909 ArrayList matches = new ArrayList();
1911 for (int i = 0; i < roots.length; ++i) {
1912 if (path.isPrefixOf(roots[i].getPath())) {
1913 matches.add(roots[i]);
1916 IPackageFragmentRoot[] copy = new IPackageFragmentRoot[matches.size()];
1917 matches.toArray(copy);
1924 public IPackageFragment[] getPackageFragments() throws JavaModelException {
1926 IPackageFragmentRoot[] roots = getPackageFragmentRoots();
1927 return getPackageFragmentsInRoots(roots);
1931 * Returns all the package fragments found in the specified package fragment
1934 public IPackageFragment[] getPackageFragmentsInRoots(
1935 IPackageFragmentRoot[] roots) {
1937 ArrayList frags = new ArrayList();
1938 for (int i = 0; i < roots.length; i++) {
1939 IPackageFragmentRoot root = roots[i];
1941 IJavaElement[] rootFragments = root.getChildren();
1942 for (int j = 0; j < rootFragments.length; j++) {
1943 frags.add(rootFragments[j]);
1945 } catch (JavaModelException e) {
1949 IPackageFragment[] fragments = new IPackageFragment[frags.size()];
1950 frags.toArray(fragments);
1957 public IPath getPath() {
1958 return this.getProject().getFullPath();
1961 public JavaModelManager.PerProjectInfo getPerProjectInfo()
1962 throws JavaModelException {
1963 return JavaModelManager.getJavaModelManager()
1964 .getPerProjectInfoCheckExistence(this.project);
1970 public IProject getProject() {
1976 * Sets the underlying kernel project of this Java project, and fills in its
1977 * parent and name. Called by IProject.getNature().
1979 * @see IProjectNature#setProject(IProject)
1981 public void setProject(IProject project) {
1983 this.project = project;
1984 this.parent = JavaModelManager.getJavaModelManager().getJavaModel();
1985 this.name = project.getName();
1988 protected IProject getProject(String name) {
1989 return PHPeclipsePlugin.getWorkspace().getRoot().getProject(name);
1992 public List getReferencedProjects() {
1993 List referencedProjects = new ArrayList();
1995 Iterator iterator = getLoadPathEntries().iterator();
1996 while (iterator.hasNext()) {
1997 LoadPathEntry pathEntry = (LoadPathEntry) iterator.next();
1998 if (pathEntry.getType() == LoadPathEntry.TYPE_PROJECT)
1999 referencedProjects.add(pathEntry.getProject());
2002 return referencedProjects;
2006 * Returns the project custom preference pool. Project preferences may
2007 * include custom encoding.
2009 public Preferences getPreferences() {
2010 IProject project = getProject();
2011 if (!JavaProject.hasJavaNature(project))
2013 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager
2014 .getJavaModelManager().getPerProjectInfo(project, true);
2015 Preferences preferences = perProjectInfo.preferences;
2016 if (preferences != null)
2018 preferences = loadPreferences();
2019 if (preferences == null)
2020 preferences = new Preferences();
2021 perProjectInfo.preferences = preferences;
2028 // public IClasspathEntry[] getRawClasspath() throws JavaModelException {
2030 // JavaModelManager.PerProjectInfo perProjectInfo =
2031 // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
2032 // IClasspathEntry[] classpath = perProjectInfo.classpath;
2033 // if (classpath != null) return classpath;
2034 // classpath = this.readClasspathFile(false/*don't create markers*/,
2035 // true/*log problems*/);
2037 // // extract out the output location
2038 // IPath outputLocation = null;
2039 // if (classpath != null && classpath.length > 0) {
2040 // IClasspathEntry entry = classpath[classpath.length - 1];
2041 // if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
2042 // outputLocation = entry.getPath();
2043 // IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
2044 // System.arraycopy(classpath, 0, copy, 0, copy.length);
2045 // classpath = copy;
2048 // if (classpath == null) {
2049 // return defaultClasspath();
2051 // /* Disable validate: classpath can contain CP variables and container
2052 // that need to be resolved
2053 // if (classpath != INVALID_CLASSPATH
2054 // && !JavaConventions.validateClasspath(this, classpath,
2055 // outputLocation).isOK()) {
2056 // classpath = INVALID_CLASSPATH;
2059 // perProjectInfo.classpath = classpath;
2060 // perProjectInfo.outputLocation = outputLocation;
2061 // return classpath;
2066 public IClasspathEntry[] getRawClasspath() throws JavaModelException {
2067 // Do not create marker but log problems while getting raw classpath
2068 return getRawClasspath(false, true);
2072 * Internal variant allowing to parameterize problem creation/logging
2074 public IClasspathEntry[] getRawClasspath(boolean createMarkers,
2075 boolean logProblems) throws JavaModelException {
2077 JavaModelManager.PerProjectInfo perProjectInfo = null;
2078 IClasspathEntry[] classpath;
2079 if (createMarkers) {
2080 this.flushClasspathProblemMarkers(false/* cycle */, true/* format */);
2081 classpath = this.readClasspathFile(createMarkers, logProblems);
2083 perProjectInfo = getPerProjectInfo();
2084 classpath = perProjectInfo.rawClasspath;
2085 if (classpath != null)
2087 classpath = this.readClasspathFile(createMarkers, logProblems);
2089 // extract out the output location
2090 IPath outputLocation = null;
2091 if (classpath != null && classpath.length > 0) {
2092 IClasspathEntry entry = classpath[classpath.length - 1];
2093 if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
2094 outputLocation = entry.getPath();
2095 IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
2096 System.arraycopy(classpath, 0, copy, 0, copy.length);
2100 if (classpath == null) {
2101 return defaultClasspath();
2104 * Disable validate: classpath can contain CP variables and container
2105 * that need to be resolved if (classpath != INVALID_CLASSPATH &&
2106 * !JavaConventions.validateClasspath(this, classpath,
2107 * outputLocation).isOK()) { classpath = INVALID_CLASSPATH; }
2109 if (!createMarkers) {
2110 perProjectInfo.rawClasspath = classpath;
2111 perProjectInfo.outputLocation = outputLocation;
2117 * @see IJavaProject#getRequiredProjectNames
2119 public String[] getRequiredProjectNames() throws JavaModelException {
2121 return this.projectPrerequisites(getResolvedClasspath(true));
2127 public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry)
2128 throws JavaModelException {
2130 return this.getResolvedClasspath(ignoreUnresolvedEntry, false); // generateMarkerOnError
2134 * Internal variant which can create marker on project for invalid entries
2135 * and caches the resolved classpath on perProjectInfo
2137 public IClasspathEntry[] getResolvedClasspath(
2138 boolean ignoreUnresolvedEntry, boolean generateMarkerOnError)
2139 throws JavaModelException {
2140 return getResolvedClasspath(ignoreUnresolvedEntry,
2141 generateMarkerOnError, true // returnResolutionInProgress
2143 // JavaModelManager manager = JavaModelManager.getJavaModelManager();
2144 // JavaModelManager.PerProjectInfo perProjectInfo =
2145 // manager.getPerProjectInfoCheckExistence(project);
2147 // // reuse cache if not needing to refresh markers or checking bound
2149 // if (ignoreUnresolvedEntry && !generateMarkerOnError && perProjectInfo
2151 // // resolved path is cached on its info
2152 // IClasspathEntry[] infoPath = perProjectInfo.lastResolvedClasspath;
2153 // if (infoPath != null) return infoPath;
2155 // Map reverseMap = perProjectInfo == null ? null : new HashMap(5);
2156 // IClasspathEntry[] resolvedPath = getResolvedClasspath(
2157 // getRawClasspath(),
2158 // generateMarkerOnError ? getOutputLocation() : null,
2159 // ignoreUnresolvedEntry,
2160 // generateMarkerOnError,
2163 // if (perProjectInfo != null){
2164 // if (perProjectInfo.classpath == null // .classpath file could not be
2166 // && generateMarkerOnError
2167 // && JavaProject.hasJavaNature(project)) {
2168 // this.createClasspathProblemMarker(new JavaModelStatus(
2169 // IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
2170 // Util.bind("classpath.cannotReadClasspathFile",
2171 // this.getElementName()))); //$NON-NLS-1$
2174 // perProjectInfo.lastResolvedClasspath = resolvedPath;
2175 // perProjectInfo.resolvedPathToRawEntries = reverseMap;
2177 // return resolvedPath;
2181 * Internal variant which can create marker on project for invalid entries
2182 * and caches the resolved classpath on perProjectInfo. If requested, return
2183 * a special classpath (RESOLUTION_IN_PROGRESS) if the classpath is being
2186 public IClasspathEntry[] getResolvedClasspath(
2187 boolean ignoreUnresolvedEntry, boolean generateMarkerOnError,
2188 boolean returnResolutionInProgress) throws JavaModelException {
2190 JavaModelManager manager = JavaModelManager.getJavaModelManager();
2191 JavaModelManager.PerProjectInfo perProjectInfo = null;
2192 if (ignoreUnresolvedEntry && !generateMarkerOnError) {
2193 perProjectInfo = getPerProjectInfo();
2194 if (perProjectInfo != null) {
2195 // resolved path is cached on its info
2196 IClasspathEntry[] infoPath = perProjectInfo.resolvedClasspath;
2197 if (infoPath != null) {
2199 } else if (returnResolutionInProgress
2200 && manager.isClasspathBeingResolved(this)) {
2201 if (JavaModelManager.CP_RESOLVE_VERBOSE) {
2203 .verbose("CPResolution: reentering raw classpath resolution, will use empty classpath instead" + //$NON-NLS-1$
2204 " project: " + getElementName() + '\n' + //$NON-NLS-1$
2205 " invocation stack trace:"); //$NON-NLS-1$
2206 new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
2208 return RESOLUTION_IN_PROGRESS;
2212 Map reverseMap = perProjectInfo == null ? null : new HashMap(5);
2213 IClasspathEntry[] resolvedPath = null;
2214 boolean nullOldResolvedCP = perProjectInfo != null
2215 && perProjectInfo.resolvedClasspath == null;
2217 // protect against misbehaving clients (see
2218 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=61040)
2219 if (nullOldResolvedCP)
2220 manager.setClasspathBeingResolved(this, true);
2221 resolvedPath = getResolvedClasspath(getRawClasspath(
2222 generateMarkerOnError, !generateMarkerOnError),
2223 generateMarkerOnError ? getOutputLocation() : null,
2224 ignoreUnresolvedEntry, generateMarkerOnError, reverseMap);
2226 if (nullOldResolvedCP)
2227 perProjectInfo.resolvedClasspath = null;
2230 if (perProjectInfo != null) {
2231 if (perProjectInfo.rawClasspath == null // .classpath file could not
2233 && generateMarkerOnError
2234 && JavaProject.hasJavaNature(this.project)) {
2235 // flush .classpath format markers (bug 39877), but only when
2236 // file cannot be read (bug 42366)
2237 this.flushClasspathProblemMarkers(false, true);
2239 .createClasspathProblemMarker(new JavaModelStatus(
2240 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
2243 "classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
2246 perProjectInfo.resolvedClasspath = resolvedPath;
2247 perProjectInfo.resolvedPathToRawEntries = reverseMap;
2248 manager.setClasspathBeingResolved(this, false);
2250 return resolvedPath;
2254 * Internal variant which can process any arbitrary classpath
2256 public IClasspathEntry[] getResolvedClasspath(
2257 IClasspathEntry[] classpathEntries, IPath projectOutputLocation, // only
2266 boolean ignoreUnresolvedEntry, // if unresolved entries are met,
2267 // should it trigger initializations
2268 boolean generateMarkerOnError, Map reverseMap) // can be null if
2269 // not interested in
2271 throws JavaModelException {
2273 IJavaModelStatus status;
2274 if (generateMarkerOnError) {
2275 flushClasspathProblemMarkers(false, false);
2278 int length = classpathEntries.length;
2279 ArrayList resolvedEntries = new ArrayList();
2281 for (int i = 0; i < length; i++) {
2283 IClasspathEntry rawEntry = classpathEntries[i];
2287 /* validation if needed */
2288 // if (generateMarkerOnError || !ignoreUnresolvedEntry) {
2289 // status = JavaConventions.validateClasspathEntry(this, rawEntry,
2291 // if (generateMarkerOnError && !status.isOK())
2292 // createClasspathProblemMarker(status);
2294 switch (rawEntry.getEntryKind()) {
2296 case IClasspathEntry.CPE_VARIABLE:
2298 IClasspathEntry resolvedEntry = JavaCore
2299 .getResolvedClasspathEntry(rawEntry);
2300 if (resolvedEntry == null) {
2301 if (!ignoreUnresolvedEntry)
2302 throw new JavaModelException(status);
2304 if (reverseMap != null
2305 && reverseMap.get(resolvedPath = resolvedEntry
2306 .getPath()) == null)
2307 reverseMap.put(resolvedPath, rawEntry);
2308 resolvedEntries.add(resolvedEntry);
2312 // case IClasspathEntry.CPE_CONTAINER :
2314 // IClasspathContainer container =
2315 // PHPCore.getClasspathContainer(rawEntry.getPath(), this);
2316 // if (container == null){
2317 // if (!ignoreUnresolvedEntry) throw new JavaModelException(status);
2321 // IClasspathEntry[] containerEntries =
2322 // container.getClasspathEntries();
2323 // if (containerEntries == null) break;
2325 // // container was bound
2326 // for (int j = 0, containerLength = containerEntries.length; j <
2327 // containerLength; j++){
2328 // IClasspathEntry cEntry = containerEntries[j];
2330 // if (generateMarkerOnError) {
2331 // IJavaModelStatus containerStatus =
2332 // JavaConventions.validateClasspathEntry(this, cEntry, false);
2333 // if (!containerStatus.isOK())
2334 // createClasspathProblemMarker(containerStatus);
2336 // // if container is exported, then its nested entries must in turn
2337 // be exported (21749)
2338 // if (rawEntry.isExported()){
2339 // cEntry = new ClasspathEntry(cEntry.getContentKind(),
2340 // cEntry.getEntryKind(), cEntry.getPath(),
2341 // cEntry.getExclusionPatterns(), cEntry.getSourceAttachmentPath(),
2342 // cEntry.getSourceAttachmentRootPath(), cEntry.getOutputLocation(),
2343 // true); // duplicate container entry for tagging it as exported
2345 // if (reverseMap != null && reverseMap.get(resolvedPath =
2346 // cEntry.getPath()) == null) reverseMap.put(resolvedPath,
2348 // resolvedEntries.add(cEntry);
2354 if (reverseMap != null
2355 && reverseMap.get(resolvedPath = rawEntry.getPath()) == null)
2356 reverseMap.put(resolvedPath, rawEntry);
2357 resolvedEntries.add(rawEntry);
2362 IClasspathEntry[] resolvedPath = new IClasspathEntry[resolvedEntries
2364 resolvedEntries.toArray(resolvedPath);
2366 // if (generateMarkerOnError && projectOutputLocation != null) {
2367 // status = JavaConventions.validateClasspath(this, resolvedPath,
2368 // projectOutputLocation);
2369 // if (!status.isOK()) createClasspathProblemMarker(status);
2371 return resolvedPath;
2377 public IResource getResource() {
2378 return this.getProject();
2384 public ISearchableNameEnvironment getSearchableNameEnvironment()
2385 throws JavaModelException {
2387 // JavaProjectElementInfo info = getJavaProjectElementInfo();
2388 // if (info.getSearchableEnvironment() == null) {
2389 // info.setSearchableEnvironment(new SearchableEnvironment(this));
2391 // return info.getSearchableEnvironment();
2396 * Retrieve a shared property on a project. If the property is not defined,
2397 * answers null. Note that it is orthogonal to IResource persistent
2398 * properties, and client code has to decide which form of storage to use
2399 * appropriately. Shared properties produce real resource files which can be
2400 * shared through a VCM onto a server. Persistent properties are not
2403 * @see JavaProject#setSharedProperty(String, String)
2405 public String getSharedProperty(String key) throws CoreException {
2407 String property = null;
2408 IFile rscFile = getProject().getFile(key);
2409 if (rscFile.exists()) {
2410 property = new String(Util.getResourceContentsAsByteArray(rscFile));
2418 // public SourceMapper getSourceMapper() {
2425 public IResource getUnderlyingResource() throws JavaModelException {
2427 throw newNotPresentException();
2428 return getProject();
2434 public boolean hasBuildState() {
2436 return JavaModelManager.getJavaModelManager().getLastBuiltState(
2437 this.getProject(), null) != null;
2443 public boolean hasClasspathCycle(IClasspathEntry[] preferredClasspath) {
2444 HashSet cycleParticipants = new HashSet();
2445 updateCycleParticipants(preferredClasspath, new ArrayList(2),
2446 cycleParticipants, ResourcesPlugin.getWorkspace().getRoot(),
2448 return !cycleParticipants.isEmpty();
2451 public boolean hasCycleMarker() {
2452 return this.getCycleMarker() != null;
2455 public int hashCode() {
2456 return project.hashCode();
2460 * Returns true if the given project is accessible and it has a java nature,
2463 public static boolean hasJavaNature(IProject project) {
2465 return project.hasNature(PHPeclipsePlugin.PHP_NATURE_ID);
2466 } catch (CoreException e) {
2467 // project does not exist or is not open
2473 * Answers true if the project potentially contains any source. A project
2474 * which has no source is immutable.
2476 public boolean hasSource() {
2478 // look if any source folder on the classpath
2479 // no need for resolved path given source folder cannot be abstracted
2480 IClasspathEntry[] entries;
2482 entries = this.getRawClasspath();
2483 } catch (JavaModelException e) {
2484 return true; // unsure
2486 for (int i = 0, max = entries.length; i < max; i++) {
2487 if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
2495 * Compare current classpath with given one to see if any different. Note
2496 * that the argument classpath contains its binary output.
2498 public boolean isClasspathEqualsTo(IClasspathEntry[] newClasspath,
2499 IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput)
2500 throws JavaModelException {
2502 if (otherClasspathWithOutput != null
2503 && otherClasspathWithOutput.length > 0) {
2505 int length = otherClasspathWithOutput.length;
2506 if (length == newClasspath.length + 1) {
2507 // output is amongst file entries (last one)
2509 // compare classpath entries
2510 for (int i = 0; i < length - 1; i++) {
2511 if (!otherClasspathWithOutput[i].equals(newClasspath[i]))
2514 // compare binary outputs
2515 IClasspathEntry output = otherClasspathWithOutput[length - 1];
2516 if (output.getContentKind() == ClasspathEntry.K_OUTPUT
2517 && output.getPath().equals(newOutputLocation))
2527 public boolean isOnClasspath(IJavaElement element) {
2528 IPath path = element.getPath();
2529 switch (element.getElementType()) {
2530 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
2531 if (!((IPackageFragmentRoot) element).isArchive()) {
2532 // ensure that folders are only excluded if all of their
2533 // children are excluded
2534 path = path.append("*"); //$NON-NLS-1$
2537 case IJavaElement.PACKAGE_FRAGMENT:
2538 if (!((IPackageFragmentRoot) element.getParent()).isArchive()) {
2539 // ensure that folders are only excluded if all of their
2540 // children are excluded
2541 path = path.append("*"); //$NON-NLS-1$
2545 return this.isOnClasspath(path);
2548 private boolean isOnClasspath(IPath path) {
2549 IClasspathEntry[] classpath;
2552 .getResolvedClasspath(true/* ignore unresolved variable */);
2553 } catch (JavaModelException e) {
2554 return false; // not a Java project
2556 for (int i = 0; i < classpath.length; i++) {
2557 IClasspathEntry entry = classpath[i];
2558 if (entry.getPath().isPrefixOf(path)
2559 && !Util.isExcluded(path, null, ((ClasspathEntry) entry)
2560 .fullExclusionPatternChars(), true)) {
2570 public boolean isOnClasspath(IResource resource) {
2571 IPath path = resource.getFullPath();
2573 // ensure that folders are only excluded if all of their children are
2575 if (resource.getType() == IResource.FOLDER) {
2576 path = path.append("*"); //$NON-NLS-1$
2579 return this.isOnClasspath(path);
2582 private IPath getPluginWorkingLocation() {
2583 return this.project.getWorkingLocation(JavaCore.PLUGIN_ID);
2587 * load preferences from a shareable format (VCM-wise)
2589 public Preferences loadPreferences() {
2591 Preferences preferences = new Preferences();
2594 // getProject().getLocation().append(PREF_FILENAME).toFile();
2595 IPath projectMetaLocation = getPluginWorkingLocation();
2596 if (projectMetaLocation != null) {
2597 File prefFile = projectMetaLocation.append(PREF_FILENAME).toFile();
2598 if (prefFile.exists()) { // load preferences from file
2599 InputStream in = null;
2601 in = new BufferedInputStream(new FileInputStream(prefFile));
2602 preferences.load(in);
2604 } catch (IOException e) { // problems loading preference store
2610 } catch (IOException e) { // ignore problems with
2621 * @see IJavaProject#newEvaluationContext
2623 // public IEvaluationContext newEvaluationContext() {
2625 // return new EvaluationContextWrapper(new EvaluationContext(), this);
2630 // public ITypeHierarchy newTypeHierarchy(
2632 // IProgressMonitor monitor)
2633 // throws JavaModelException {
2635 // if (region == null) {
2637 // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullRegion"));//$NON-NLS-1$
2639 // CreateTypeHierarchyOperation op =
2640 // new CreateTypeHierarchyOperation(null, region, this, true);
2641 // runOperation(op, monitor);
2642 // return op.getResult();
2647 // public ITypeHierarchy newTypeHierarchy(
2650 // IProgressMonitor monitor)
2651 // throws JavaModelException {
2653 // if (type == null) {
2655 // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullFocusType"));//$NON-NLS-1$
2657 // if (region == null) {
2659 // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullRegion"));//$NON-NLS-1$
2661 // CreateTypeHierarchyOperation op =
2662 // new CreateTypeHierarchyOperation(type, region, this, true);
2663 // runOperation(op, monitor);
2664 // return op.getResult();
2667 // * Open project if resource isn't closed
2669 // protected void openWhenClosed(IProgressMonitor pm) throws
2670 // JavaModelException {
2672 // if (!this.fProject.isOpen()) {
2673 // throw newNotPresentException();
2675 // super.openWhenClosed(pm);
2678 public String[] projectPrerequisites(IClasspathEntry[] entries)
2679 throws JavaModelException {
2681 ArrayList prerequisites = new ArrayList();
2683 entries = getResolvedClasspath(entries, null, true, false, null/*
2688 for (int i = 0, length = entries.length; i < length; i++) {
2689 IClasspathEntry entry = entries[i];
2690 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
2691 prerequisites.add(entry.getPath().lastSegment());
2694 int size = prerequisites.size();
2696 return NO_PREREQUISITES;
2698 String[] result = new String[size];
2699 prerequisites.toArray(result);
2705 * Reads the .classpath file from disk and returns the list of entries it
2706 * contains (including output location entry) Returns null if .classfile is
2707 * not present. Returns INVALID_CLASSPATH if it has a format problem.
2709 protected IClasspathEntry[] readClasspathFile(boolean createMarker,
2710 boolean logProblems) {
2713 String xmlClasspath = getSharedProperty(CLASSPATH_FILENAME);
2714 if (xmlClasspath == null)
2716 return decodeClasspath(xmlClasspath, createMarker, logProblems);
2717 } catch (CoreException e) {
2718 // file does not exist (or not accessible)
2719 if (createMarker && this.getProject().isAccessible()) {
2721 .createClasspathProblemMarker(new JavaModelStatus(
2722 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
2725 "classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
2728 Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$
2729 + "/.classpath, will revert to default classpath"); //$NON-NLS-1$
2736 * Removes the given builder from the build spec for the given project.
2738 protected void removeFromBuildSpec(String builderID) throws CoreException {
2740 IProjectDescription description = getProject().getDescription();
2741 ICommand[] commands = description.getBuildSpec();
2742 for (int i = 0; i < commands.length; ++i) {
2743 if (commands[i].getBuilderName().equals(builderID)) {
2744 ICommand[] newCommands = new ICommand[commands.length - 1];
2745 System.arraycopy(commands, 0, newCommands, 0, i);
2746 System.arraycopy(commands, i + 1, newCommands, i,
2747 commands.length - i - 1);
2748 description.setBuildSpec(newCommands);
2749 getProject().setDescription(description, null);
2756 * @see JavaElement#rootedAt(IJavaProject)
2758 public IJavaElement rootedAt(IJavaProject project) {
2764 * Answers an ID which is used to distinguish project/entries during package
2765 * fragment root computations
2767 public String rootID() {
2768 return "[PRJ]" + this.getProject().getFullPath(); //$NON-NLS-1$
2772 * Saves the classpath in a shareable format (VCM-wise) only when necessary,
2773 * that is, if it is semantically different from the existing one in file.
2774 * Will never write an identical one.
2776 * @return Return whether the .classpath file was modified.
2778 public boolean saveClasspath(IClasspathEntry[] newClasspath,
2779 IPath newOutputLocation) throws JavaModelException {
2781 if (!getProject().exists())
2784 IClasspathEntry[] fileEntries = readClasspathFile(
2785 false /* don't create markers */, false/* don't log problems */);
2786 if (fileEntries != null
2787 && isClasspathEqualsTo(newClasspath, newOutputLocation,
2789 // no need to save it, it is the same
2793 // actual file saving
2795 setSharedProperty(CLASSPATH_FILENAME, encodeClasspath(newClasspath,
2796 newOutputLocation, true));
2798 } catch (CoreException e) {
2799 throw new JavaModelException(e);
2804 * Save project custom preferences to shareable file (.jprefs)
2806 private void savePreferences(Preferences preferences) {
2808 if (!JavaProject.hasJavaNature(this.project))
2811 if (preferences == null
2812 || (!preferences.needsSaving() && preferences.propertyNames().length != 0)) {
2817 // preferences need to be saved
2818 // the preferences file is located in the plug-in's state area
2819 // at a well-known name (.jprefs)
2821 // this.project.getLocation().append(PREF_FILENAME).toFile();
2822 File prefFile = getPluginWorkingLocation().append(PREF_FILENAME)
2824 if (preferences.propertyNames().length == 0) {
2825 // there are no preference settings
2826 // rather than write an empty file, just delete any existing file
2827 if (prefFile.exists()) {
2828 prefFile.delete(); // don't worry if delete unsuccessful
2833 // write file, overwriting an existing one
2834 OutputStream out = null;
2836 // do it as carefully as we know how so that we don't lose/mangle
2837 // the setting in times of stress
2838 out = new BufferedOutputStream(new FileOutputStream(prefFile));
2839 preferences.store(out, null);
2840 } catch (IOException e) { // problems saving preference store -
2846 } catch (IOException e) { // ignore problems with close
2853 * Update the Java command in the build spec (replace existing one if
2854 * present, add one first if none).
2856 private void setJavaCommand(IProjectDescription description,
2857 ICommand newCommand) throws CoreException {
2859 ICommand[] oldCommands = description.getBuildSpec();
2860 ICommand oldJavaCommand = getJavaCommand(description);
2861 ICommand[] newCommands;
2863 if (oldJavaCommand == null) {
2864 // Add a Java build spec before other builders (1FWJK7I)
2865 newCommands = new ICommand[oldCommands.length + 1];
2867 .arraycopy(oldCommands, 0, newCommands, 1,
2868 oldCommands.length);
2869 newCommands[0] = newCommand;
2871 for (int i = 0, max = oldCommands.length; i < max; i++) {
2872 if (oldCommands[i] == oldJavaCommand) {
2873 oldCommands[i] = newCommand;
2877 newCommands = oldCommands;
2880 // Commit the spec change into the project
2881 description.setBuildSpec(newCommands);
2882 getProject().setDescription(description, null);
2886 * @see net.sourceforge.phpdt.core.IJavaProject#setOptions(Map)
2888 public void setOptions(Map newOptions) {
2890 Preferences preferences;
2891 setPreferences(preferences = new Preferences()); // always reset
2893 if (newOptions != null) {
2894 Iterator keys = newOptions.keySet().iterator();
2895 while (keys.hasNext()) {
2896 String key = (String) keys.next();
2897 if (!JavaModelManager.OptionNames.contains(key))
2898 continue; // unrecognized option
2899 // no filtering for encoding (custom encoding for project is
2901 String value = (String) newOptions.get(key);
2902 preferences.setDefault(key, CUSTOM_DEFAULT_OPTION_VALUE); // empty
2908 preferences.setValue(key, value);
2913 savePreferences(preferences);
2919 public void setOutputLocation(IPath path, IProgressMonitor monitor)
2920 throws JavaModelException {
2923 throw new IllegalArgumentException(Util.bind("path.nullpath")); //$NON-NLS-1$
2925 if (path.equals(getOutputLocation())) {
2928 this.setRawClasspath(SetClasspathOperation.ReuseClasspath, path,
2933 * Set cached preferences, no preference file is saved, only info is updated
2935 public void setPreferences(Preferences preferences) {
2936 IProject project = getProject();
2937 if (!JavaProject.hasJavaNature(project))
2939 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager
2940 .getJavaModelManager().getPerProjectInfo(project, true);
2941 perProjectInfo.preferences = preferences;
2947 public void setRawClasspath(IClasspathEntry[] entries,
2948 IPath outputLocation, IProgressMonitor monitor)
2949 throws JavaModelException {
2951 setRawClasspath(entries, outputLocation, monitor, true, // canChangeResource
2954 getResolvedClasspath(true), // ignoreUnresolvedVariable
2955 true, // needValidation
2956 true); // need to save
2959 public void setRawClasspath(IClasspathEntry[] newEntries,
2960 IPath newOutputLocation, IProgressMonitor monitor,
2961 boolean canChangeResource, IClasspathEntry[] oldResolvedPath,
2962 boolean needValidation, boolean needSave) throws JavaModelException {
2964 JavaModelManager manager = (JavaModelManager) JavaModelManager
2965 .getJavaModelManager();
2967 IClasspathEntry[] newRawPath = newEntries;
2968 if (newRawPath == null) { // are we already with the default
2970 newRawPath = defaultClasspath();
2972 SetClasspathOperation op = new SetClasspathOperation(this,
2973 oldResolvedPath, newRawPath, newOutputLocation,
2974 canChangeResource, needValidation, needSave);
2975 runOperation(op, monitor);
2977 } catch (JavaModelException e) {
2986 public void setRawClasspath(IClasspathEntry[] entries,
2987 IProgressMonitor monitor) throws JavaModelException {
2989 setRawClasspath(entries, SetClasspathOperation.ReuseOutputLocation,
2990 monitor, true, // canChangeResource (as per API contract)
2991 getResolvedClasspath(true), // ignoreUnresolvedVariable
2992 true, // needValidation
2993 true); // need to save
2997 * NOTE: <code>null</code> specifies default classpath, and an empty array
2998 * specifies an empty classpath.
3000 * @exception NotPresentException
3001 * if this project does not exist.
3003 // protected void setRawClasspath0(IClasspathEntry[] rawEntries)
3004 // throws JavaModelException {
3006 // JavaModelManager.PerProjectInfo info =
3007 // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
3009 // synchronized (info) {
3010 // if (rawEntries != null) {
3011 // info.classpath = rawEntries;
3014 // // clear cache of resolved classpath
3015 // info.lastResolvedClasspath = null;
3016 // info.resolvedPathToRawEntries = null;
3020 * Record a shared persistent property onto a project. Note that it is
3021 * orthogonal to IResource persistent properties, and client code has to
3022 * decide which form of storage to use appropriately. Shared properties
3023 * produce real resource files which can be shared through a VCM onto a
3024 * server. Persistent properties are not shareable.
3026 * shared properties end up in resource files, and thus cannot be modified
3027 * during delta notifications (a CoreException would then be thrown).
3029 * @see JavaProject#getSharedProperty(String key)
3031 public void setSharedProperty(String key, String value)
3032 throws CoreException {
3034 IFile rscFile = getProject().getFile(key);
3035 InputStream inputStream = new ByteArrayInputStream(value.getBytes());
3036 // update the resource content
3037 if (rscFile.exists()) {
3038 if (rscFile.isReadOnly()) {
3039 // provide opportunity to checkout read-only .classpath file
3041 ResourcesPlugin.getWorkspace().validateEdit(
3042 new IFile[] { rscFile }, null);
3044 rscFile.setContents(inputStream, IResource.FORCE, null);
3046 rscFile.create(inputStream, IResource.FORCE, null);
3051 * Update cycle markers for all java projects
3053 public static void updateAllCycleMarkers() throws JavaModelException {
3055 // long start = System.currentTimeMillis();
3057 JavaModelManager manager = JavaModelManager.getJavaModelManager();
3058 IJavaProject[] projects = manager.getJavaModel().getJavaProjects();
3059 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
3061 HashSet cycleParticipants = new HashSet();
3062 HashSet traversed = new HashSet();
3063 int length = projects.length;
3065 // compute cycle participants
3066 ArrayList prereqChain = new ArrayList();
3067 for (int i = 0; i < length; i++) {
3068 JavaProject project = (JavaProject) projects[i];
3069 if (!traversed.contains(project.getPath())) {
3070 prereqChain.clear();
3071 project.updateCycleParticipants(null, prereqChain,
3072 cycleParticipants, workspaceRoot, traversed);
3075 // System.out.println("updateAllCycleMarkers: " +
3076 // (System.currentTimeMillis() - start) + " ms");
3078 for (int i = 0; i < length; i++) {
3079 JavaProject project = (JavaProject) projects[i];
3081 if (cycleParticipants.contains(project.getPath())) {
3082 IMarker cycleMarker = project.getCycleMarker();
3083 String circularCPOption = project.getOption(
3084 JavaCore.CORE_CIRCULAR_CLASSPATH, true);
3085 int circularCPSeverity = JavaCore.ERROR
3086 .equals(circularCPOption) ? IMarker.SEVERITY_ERROR
3087 : IMarker.SEVERITY_WARNING;
3088 if (cycleMarker != null) {
3089 // update existing cycle marker if needed
3091 int existingSeverity = ((Integer) cycleMarker
3092 .getAttribute(IMarker.SEVERITY)).intValue();
3093 if (existingSeverity != circularCPSeverity) {
3094 cycleMarker.setAttribute(IMarker.SEVERITY,
3095 circularCPSeverity);
3097 } catch (CoreException e) {
3098 throw new JavaModelException(e);
3101 // create new marker
3103 .createClasspathProblemMarker(new JavaModelStatus(
3104 IJavaModelStatusConstants.CLASSPATH_CYCLE,
3108 project.flushClasspathProblemMarkers(true, false);
3114 * If a cycle is detected, then cycleParticipants contains all the paths of
3115 * projects involved in this cycle (directly and indirectly), no cycle if
3116 * the set is empty (and started empty)
3118 public void updateCycleParticipants(IClasspathEntry[] preferredClasspath,
3119 ArrayList prereqChain, HashSet cycleParticipants,
3120 IWorkspaceRoot workspaceRoot, HashSet traversed) {
3122 IPath path = this.getPath();
3123 prereqChain.add(path);
3124 traversed.add(path);
3126 IClasspathEntry[] classpath = preferredClasspath == null ? getResolvedClasspath(true)
3127 : preferredClasspath;
3128 for (int i = 0, length = classpath.length; i < length; i++) {
3129 IClasspathEntry entry = classpath[i];
3131 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
3132 IPath prereqProjectPath = entry.getPath();
3133 int index = cycleParticipants.contains(prereqProjectPath) ? 0
3134 : prereqChain.indexOf(prereqProjectPath);
3135 if (index >= 0) { // refer to cycle, or in cycle itself
3136 for (int size = prereqChain.size(); index < size; index++) {
3137 cycleParticipants.add(prereqChain.get(index));
3140 if (!traversed.contains(prereqProjectPath)) {
3141 IResource member = workspaceRoot
3142 .findMember(prereqProjectPath);
3144 && member.getType() == IResource.PROJECT) {
3145 JavaProject project = (JavaProject) JavaCore
3146 .create((IProject) member);
3147 project.updateCycleParticipants(null,
3148 prereqChain, cycleParticipants,
3149 workspaceRoot, traversed);
3155 } catch (JavaModelException e) {
3157 prereqChain.remove(path);
3161 * Reset the collection of package fragment roots (local ones) - only if
3162 * opened. Need to check *all* package fragment roots in order to reset
3165 public void updatePackageFragmentRoots() {
3167 if (this.isOpen()) {
3169 JavaProjectElementInfo info = getJavaProjectElementInfo();
3171 IClasspathEntry[] classpath = getResolvedClasspath(true);
3172 // NameLookup lookup = info.getNameLookup();
3173 // if (lookup != null){
3174 // IPackageFragmentRoot[] oldRoots =
3175 // lookup.fPackageFragmentRoots;
3176 // IPackageFragmentRoot[] newRoots =
3177 // computePackageFragmentRoots(classpath, true);
3178 // checkIdentical: { // compare all pkg fragment root lists
3179 // if (oldRoots.length == newRoots.length){
3180 // for (int i = 0, length = oldRoots.length; i < length; i++){
3181 // if (!oldRoots[i].equals(newRoots[i])){
3182 // break checkIdentical;
3185 // return; // no need to update
3188 // info.setNameLookup(null); // discard name lookup (hold onto
3191 info.setNonJavaResources(null);
3192 info.setChildren(computePackageFragmentRoots(classpath, false));
3194 } catch (JavaModelException e) {
3196 close(); // could not do better
3197 } catch (JavaModelException ex) {
3203 public void removeLoadPathEntry(IProject anotherPHPProject) {
3204 Iterator entries = getLoadPathEntries().iterator();
3205 while (entries.hasNext()) {
3206 LoadPathEntry entry = (LoadPathEntry) entries.next();
3207 if (entry.getType() == LoadPathEntry.TYPE_PROJECT
3208 && entry.getProject().getName().equals(
3209 anotherPHPProject.getName())) {
3210 getLoadPathEntries().remove(entry);
3217 public void save() throws CoreException {
3219 InputStream xmlPath = new ByteArrayInputStream(getLoadPathXML()
3221 IFile loadPathsFile = getLoadPathEntriesFile();
3222 if (!loadPathsFile.exists())
3223 loadPathsFile.create(xmlPath, true, null);
3225 loadPathsFile.setContents(xmlPath, true, false, null);