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.Util;
53 import net.sourceforge.phpdt.internal.corext.Assert;
54 import net.sourceforge.phpeclipse.LoadPathEntry;
55 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
57 import javax.xml.parsers.DocumentBuilder;
58 import javax.xml.parsers.DocumentBuilderFactory;
59 import javax.xml.parsers.ParserConfigurationException;
60 import org.w3c.dom.Element;
61 import org.w3c.dom.Node;
62 import org.w3c.dom.NodeList;
63 import org.xml.sax.InputSource;
64 import org.xml.sax.SAXException;
66 import org.eclipse.core.resources.ICommand;
67 import org.eclipse.core.resources.IFile;
68 import org.eclipse.core.resources.IFolder;
69 import org.eclipse.core.resources.IMarker;
70 import org.eclipse.core.resources.IProject;
71 import org.eclipse.core.resources.IProjectDescription;
72 import org.eclipse.core.resources.IProjectNature;
73 import org.eclipse.core.resources.IResource;
74 import org.eclipse.core.resources.IWorkspace;
75 import org.eclipse.core.resources.IWorkspaceRoot;
76 import org.eclipse.core.resources.ResourcesPlugin;
77 import org.eclipse.core.runtime.CoreException;
78 import org.eclipse.core.runtime.IPath;
79 import org.eclipse.core.runtime.IProgressMonitor;
80 import org.eclipse.core.runtime.Path;
81 import org.eclipse.core.runtime.Preferences;
82 import org.eclipse.core.runtime.QualifiedName;
84 import net.sourceforge.phpdt.internal.core.ClasspathEntry;
85 import net.sourceforge.phpdt.internal.core.XMLWriter;
86 import org.w3c.dom.Document;
87 import org.w3c.dom.Element;
88 import org.w3c.dom.Node;
89 import org.w3c.dom.NodeList;
90 import org.xml.sax.Attributes;
91 import org.xml.sax.ContentHandler;
92 import org.xml.sax.InputSource;
93 import org.xml.sax.Locator;
94 import org.xml.sax.SAXException;
95 import org.xml.sax.XMLReader;
98 * Handle for a Java Project.
100 * <p>A Java Project internally maintains a devpath that corresponds
101 * to the project's classpath. The classpath may include source folders
102 * from the current project; jars in the current project, other projects,
103 * and the local file system; and binary folders (output location) of other
104 * projects. The Java Model presents source elements corresponding to output
105 * .class files in other projects, and thus uses the devpath rather than
106 * the classpath (which is really a compilation path). The devpath mimics
107 * the classpath, except has source folder entries in place of output
108 * locations in external projects.
110 * <p>Each JavaProject has a NameLookup facility that locates elements
111 * on by name, based on the devpath.
115 public class JavaProject
117 implements IJavaProject , IProjectNature {
120 * Whether the underlying file system is case sensitive.
122 protected static final boolean IS_CASE_SENSITIVE = !new File("Temp").equals(new File("temp")); //$NON-NLS-1$ //$NON-NLS-2$
125 * An empty array of strings indicating that a project doesn't have any prerequesite projects.
127 protected static final String[] NO_PREREQUISITES = new String[0];
130 * The platform project this <code>IJavaProject</code> is based on
132 protected IProject project;
133 protected List fLoadPathEntries;
134 protected boolean fScratched;
137 * Name of file containing project classpath
139 public static final String CLASSPATH_FILENAME = ".classpath"; //$NON-NLS-1$
142 * Name of file containing custom project preferences
144 public static final String PREF_FILENAME = ".jprefs"; //$NON-NLS-1$
147 * Value of the project's raw classpath if the .classpath file contains invalid entries.
149 public static final IClasspathEntry[] INVALID_CLASSPATH = new IClasspathEntry[0];
151 private static final String CUSTOM_DEFAULT_OPTION_VALUE = "#\r\n\r#custom-non-empty-default-value#\r\n\r#"; //$NON-NLS-1$
154 * Returns a canonicalized path from the given external path.
155 * Note that the return path contains the same number of segments
156 * and it contains a device only if the given path contained one.
157 * @see java.io.File for the definition of a canonicalized path
159 public static IPath canonicalizedPath(IPath externalPath) {
161 if (externalPath == null)
164 if (JavaModelManager.VERBOSE) {
165 System.out.println("JAVA MODEL - Canonicalizing " + externalPath.toString()); //$NON-NLS-1$
168 if (IS_CASE_SENSITIVE) {
169 if (JavaModelManager.VERBOSE) {
170 System.out.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) return externalPath; // protection during shutdown (30487)
178 if (workspace.getRoot().findMember(externalPath) != null) {
179 if (JavaModelManager.VERBOSE) {
180 System.out.println("JAVA MODEL - Canonical path is original path (member of workspace)"); //$NON-NLS-1$
185 IPath canonicalPath = null;
188 new Path(new File(externalPath.toOSString()).getCanonicalPath());
189 } catch (IOException e) {
190 // default to original path
191 if (JavaModelManager.VERBOSE) {
192 System.out.println("JAVA MODEL - Canonical path is original path (IOException)"); //$NON-NLS-1$
198 int canonicalLength = canonicalPath.segmentCount();
199 if (canonicalLength == 0) {
200 // the java.io.File canonicalization failed
201 if (JavaModelManager.VERBOSE) {
202 System.out.println("JAVA MODEL - Canonical path is original path (canonical path is empty)"); //$NON-NLS-1$
205 } else if (externalPath.isAbsolute()) {
206 result = canonicalPath;
208 // if path is relative, remove the first segments that were added by the java.io.File canonicalization
209 // e.g. 'lib/classes.zip' was converted to 'd:/myfolder/lib/classes.zip'
210 int externalLength = externalPath.segmentCount();
211 if (canonicalLength >= externalLength) {
212 result = canonicalPath.removeFirstSegments(canonicalLength - externalLength);
214 if (JavaModelManager.VERBOSE) {
215 System.out.println("JAVA MODEL - Canonical path is original path (canonical path is " + canonicalPath.toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
221 // keep device only if it was specified (this is because File.getCanonicalPath() converts '/lib/classed.zip' to 'd:/lib/classes/zip')
222 if (externalPath.getDevice() == null) {
223 result = result.setDevice(null);
225 if (JavaModelManager.VERBOSE) {
226 System.out.println("JAVA MODEL - Canonical path is " + result.toString()); //$NON-NLS-1$
232 * Constructor needed for <code>IProject.getNature()</code> and <code>IProject.addNature()</code>.
234 * @see #setProject(IProject)
236 public JavaProject() {
240 public JavaProject(IProject project, JavaElement parent) {
241 super(parent, project.getName());
242 this.project = project;
244 public void addLoadPathEntry(IProject anotherPHPProject) {
247 LoadPathEntry newEntry = new LoadPathEntry(anotherPHPProject);
248 getLoadPathEntries().add(newEntry);
251 public void configure() throws CoreException {
252 // get project description and then the associated build commands
253 IProjectDescription desc = project.getDescription();
254 ICommand[] commands = desc.getBuildSpec();
256 // determine if builder already associated
257 boolean found = false;
258 for (int i = 0; i < commands.length; ++i) {
259 if (commands[i].getBuilderName().equals(PHPeclipsePlugin.BUILDER_PARSER_ID)) {
265 // add builder if not already in project
267 ICommand command = desc.newCommand();
268 command.setBuilderName(PHPeclipsePlugin.BUILDER_PARSER_ID);
269 ICommand[] newCommands = new ICommand[commands.length + 1];
271 // Add it before other builders.
272 System.arraycopy(commands, 0, newCommands, 1, commands.length);
273 newCommands[0] = command;
274 desc.setBuildSpec(newCommands);
275 project.setDescription(desc, null);
279 protected void loadLoadPathEntries() {
280 fLoadPathEntries = new ArrayList();
282 IFile loadPathsFile = getLoadPathEntriesFile();
284 XMLReader reader = null;
286 reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
287 reader.setContentHandler(getLoadPathEntriesContentHandler());
288 reader.parse(new InputSource(loadPathsFile.getContents()));
289 } catch (Exception e) {
290 //the file is nonextant or unreadable
294 public List getLoadPathEntries() {
295 if (fLoadPathEntries == null) {
296 loadLoadPathEntries();
299 return fLoadPathEntries;
302 protected ContentHandler getLoadPathEntriesContentHandler() {
303 return new ContentHandler() {
304 public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
307 public void endDocument() throws SAXException {
310 public void endElement(String arg0, String arg1, String arg2) throws SAXException {
313 public void endPrefixMapping(String arg0) throws SAXException {
316 public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException {
319 public void processingInstruction(String arg0, String arg1) throws SAXException {
322 public void setDocumentLocator(Locator arg0) {
325 public void skippedEntity(String arg0) throws SAXException {
328 public void startDocument() throws SAXException {
331 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
332 if ("pathentry".equals(qName))
333 if ("project".equals(atts.getValue("type"))) {
334 IPath referencedProjectPath = new Path(atts.getValue("path"));
335 IProject referencedProject = getProject(referencedProjectPath.lastSegment());
336 fLoadPathEntries.add(new LoadPathEntry(referencedProject));
340 public void startPrefixMapping(String arg0, String arg1) throws SAXException {
345 protected IFile getLoadPathEntriesFile() {
346 return project.getFile(".loadpath");
349 protected String getLoadPathXML() {
350 StringBuffer buffer = new StringBuffer();
351 buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><loadpath>");
353 Iterator pathEntriesIterator = fLoadPathEntries.iterator();
355 while (pathEntriesIterator.hasNext()) {
356 LoadPathEntry entry = (LoadPathEntry) pathEntriesIterator.next();
357 buffer.append(entry.toXML());
360 buffer.append("</loadpath>");
361 return buffer.toString();
364 * Adds a builder to the build spec for the given project.
366 protected void addToBuildSpec(String builderID) throws CoreException {
368 IProjectDescription description = getProject().getDescription();
369 ICommand javaCommand = getJavaCommand(description);
371 if (javaCommand == null) {
373 // Add a Java command to the build spec
374 ICommand command = description.newCommand();
375 command.setBuilderName(builderID);
376 setJavaCommand(description, command);
382 protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
384 // check whether the java project can be opened
385 if (!underlyingResource.isAccessible()) {
386 throw newNotPresentException();
389 IWorkspace workspace = ResourcesPlugin.getWorkspace();
390 IWorkspaceRoot wRoot = workspace.getRoot();
391 // cannot refresh cp markers on opening (emulate cp check on startup) since can create deadlocks (see bug 37274)
392 // IClasspathEntry[] resolvedClasspath = getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
394 // // compute the pkg fragment roots
395 // info.setChildren(computePackageFragmentRoots(resolvedClasspath, false));
397 // // remember the timestamps of external libraries the first time they are looked up
398 // for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
399 // IClasspathEntry entry = resolvedClasspath[i];
400 // if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
401 // IPath path = entry.getPath();
402 // Object target = JavaModel.getTarget(wRoot, path, true);
403 // if (target instanceof java.io.File) {
404 // Map externalTimeStamps = JavaModelManager.getJavaModelManager().deltaState.externalTimeStamps;
405 // if (externalTimeStamps.get(path) == null) {
406 // long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
407 // externalTimeStamps.put(path, new Long(timestamp));
415 protected void closing(Object info) {
417 // // forget source attachment recommendations
418 // Object[] children = ((JavaElementInfo)info).children;
419 // for (int i = 0, length = children.length; i < length; i++) {
420 // Object child = children[i];
421 // if (child instanceof JarPackageFragmentRoot){
422 // ((JarPackageFragmentRoot)child).setSourceAttachmentProperty(null);
428 // protected void closing(Object info) throws JavaModelException {
430 // // forget source attachment recommendations
431 // IPackageFragmentRoot[] roots = this.getPackageFragmentRoots();
432 //// for (int i = 0; i < roots.length; i++) {
433 //// if (roots[i] instanceof JarPackageFragmentRoot){
434 //// ((JarPackageFragmentRoot) roots[i]).setSourceAttachmentProperty(null);
438 // super.closing(info);
444 * Internal computation of an expanded classpath. It will eliminate duplicates, and produce copies
445 * of exported classpath entries to avoid possible side-effects ever after.
447 private void computeExpandedClasspath(
448 JavaProject initialProject,
449 boolean ignoreUnresolvedVariable,
450 boolean generateMarkerOnError,
451 HashSet visitedProjects,
452 ObjectVector accumulatedEntries) throws JavaModelException {
454 if (visitedProjects.contains(this)){
455 return; // break cycles if any
457 visitedProjects.add(this);
459 if (generateMarkerOnError && !this.equals(initialProject)){
460 generateMarkerOnError = false;
462 IClasspathEntry[] immediateClasspath =
463 getResolvedClasspath(ignoreUnresolvedVariable, generateMarkerOnError);
465 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
466 for (int i = 0, length = immediateClasspath.length; i < length; i++){
467 IClasspathEntry entry = immediateClasspath[i];
469 boolean isInitialProject = this.equals(initialProject);
470 if (isInitialProject || entry.isExported()){
472 accumulatedEntries.add(entry);
474 // recurse in project to get all its indirect exports (only consider exported entries from there on)
475 if (entry.getEntryKind() == ClasspathEntry.CPE_PROJECT) {
476 IResource member = workspaceRoot.findMember(entry.getPath());
477 if (member != null && member.getType() == IResource.PROJECT){ // double check if bound to project (23977)
478 IProject projRsc = (IProject) member;
479 if (JavaProject.hasJavaNature(projRsc)) {
480 JavaProject project = (JavaProject) JavaCore.create(projRsc);
481 project.computeExpandedClasspath(
483 ignoreUnresolvedVariable,
484 generateMarkerOnError,
495 * Returns (local/all) the package fragment roots identified by the given project's classpath.
496 * Note: this follows project classpath references to find required project contributions,
497 * eliminating duplicates silently.
498 * Only works with resolved entries
500 public IPackageFragmentRoot[] computePackageFragmentRoots(IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots) throws JavaModelException {
502 ObjectVector accumulatedRoots = new ObjectVector();
503 computePackageFragmentRoots(
506 new HashSet(5), // rootIDs
507 true, // inside original project
508 true, // check existency
509 retrieveExportedRoots);
510 IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots.size()];
511 accumulatedRoots.copyInto(rootArray);
516 * Computes the package fragment roots identified by the given entry.
517 * Only works with resolved entry
519 public IPackageFragmentRoot[] computePackageFragmentRoots(IClasspathEntry resolvedEntry) {
522 computePackageFragmentRoots(
523 new IClasspathEntry[]{ resolvedEntry },
524 false // don't retrieve exported roots
526 } catch (JavaModelException e) {
527 return new IPackageFragmentRoot[] {};
532 * Returns the package fragment roots identified by the given entry. In case it refers to
533 * a project, it will follow its classpath so as to find exported roots as well.
534 * Only works with resolved entry
536 public void computePackageFragmentRoots(
537 IClasspathEntry resolvedEntry,
538 ObjectVector accumulatedRoots,
540 boolean insideOriginalProject,
541 boolean checkExistency,
542 boolean retrieveExportedRoots) throws JavaModelException {
544 String rootID = ((ClasspathEntry)resolvedEntry).rootID();
545 if (rootIDs.contains(rootID)) return;
547 IPath projectPath = getProject().getFullPath();
548 IPath entryPath = resolvedEntry.getPath();
549 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
551 switch(resolvedEntry.getEntryKind()){
554 case IClasspathEntry.CPE_SOURCE :
556 if (projectPath.isPrefixOf(entryPath)){
557 if (checkExistency) {
558 Object target = JavaModel.getTarget(workspaceRoot, entryPath, checkExistency);
559 if (target == null) return;
561 if (target instanceof IFolder || target instanceof IProject){
562 accumulatedRoots.add(
563 getPackageFragmentRoot((IResource)target));
567 IPackageFragmentRoot root = getFolderPackageFragmentRoot(entryPath);
569 accumulatedRoots.add(root);
576 // internal/external JAR or folder
577 case IClasspathEntry.CPE_LIBRARY :
579 if (!insideOriginalProject && !resolvedEntry.isExported()) return;
581 if (checkExistency) {
582 Object target = JavaModel.getTarget(workspaceRoot, entryPath, checkExistency);
583 if (target == null) return;
585 if (target instanceof IResource){
587 IResource resource = (IResource) target;
588 IPackageFragmentRoot root = getPackageFragmentRoot(resource);
590 accumulatedRoots.add(root);
594 // external target - only JARs allowed
595 // if (((java.io.File)target).isFile() && (Util.isArchiveFileName(entryPath.lastSegment()))) {
596 // accumulatedRoots.add(
597 // new JarPackageFragmentRoot(entryPath, this));
598 // rootIDs.add(rootID);
602 IPackageFragmentRoot root = getPackageFragmentRoot(entryPath);
604 accumulatedRoots.add(root);
610 // recurse into required project
611 case IClasspathEntry.CPE_PROJECT :
613 if (!retrieveExportedRoots) return;
614 if (!insideOriginalProject && !resolvedEntry.isExported()) return;
616 IResource member = workspaceRoot.findMember(entryPath);
617 if (member != null && member.getType() == IResource.PROJECT){// double check if bound to project (23977)
618 IProject requiredProjectRsc = (IProject) member;
619 if (JavaProject.hasJavaNature(requiredProjectRsc)){ // special builder binary output
621 JavaProject requiredProject = (JavaProject)JavaCore.create(requiredProjectRsc);
622 requiredProject.computePackageFragmentRoots(
623 requiredProject.getResolvedClasspath(true),
628 retrieveExportedRoots);
636 * Returns (local/all) the package fragment roots identified by the given project's classpath.
637 * Note: this follows project classpath references to find required project contributions,
638 * eliminating duplicates silently.
639 * Only works with resolved entries
641 public void computePackageFragmentRoots(
642 IClasspathEntry[] resolvedClasspath,
643 ObjectVector accumulatedRoots,
645 boolean insideOriginalProject,
646 boolean checkExistency,
647 boolean retrieveExportedRoots) throws JavaModelException {
649 if (insideOriginalProject){
650 rootIDs.add(rootID());
652 for (int i = 0, length = resolvedClasspath.length; i < length; i++){
653 computePackageFragmentRoots(
654 resolvedClasspath[i],
657 insideOriginalProject,
659 retrieveExportedRoots);
664 * Compute the file name to use for a given shared property
666 public String computeSharedPropertyFileName(QualifiedName qName) {
668 return '.' + qName.getLocalName();
672 * Returns whether the given resource is accessible through the children or the non-Java resources of this project.
673 * Returns true if the resource is not in the project.
674 * Assumes that the resource is a folder or a file.
676 public boolean contains(IResource resource) {
678 IClasspathEntry[] classpath;
681 classpath = getResolvedClasspath(true);
682 output = getOutputLocation();
683 } catch (JavaModelException e) {
687 IPath fullPath = resource.getFullPath();
688 IPath innerMostOutput = output.isPrefixOf(fullPath) ? output : null;
689 IClasspathEntry innerMostEntry = null;
690 for (int j = 0, cpLength = classpath.length; j < cpLength; j++) {
691 IClasspathEntry entry = classpath[j];
693 IPath entryPath = entry.getPath();
694 if ((innerMostEntry == null || innerMostEntry.getPath().isPrefixOf(entryPath))
695 && entryPath.isPrefixOf(fullPath)) {
696 innerMostEntry = entry;
698 IPath entryOutput = classpath[j].getOutputLocation();
699 if (entryOutput != null && entryOutput.isPrefixOf(fullPath)) {
700 innerMostOutput = entryOutput;
703 if (innerMostEntry != null) {
704 // special case prj==src and nested output location
705 if (innerMostOutput != null && innerMostOutput.segmentCount() > 1 // output isn't project
706 && innerMostEntry.getPath().segmentCount() == 1) { // 1 segment must be project name
709 if (resource instanceof IFolder) {
710 // folders are always included in src/lib entries
713 switch (innerMostEntry.getEntryKind()) {
714 case IClasspathEntry.CPE_SOURCE:
715 // .class files are not visible in source folders
716 return true; //!net.sourceforge.phpdt.internal.compiler.util.Util.isClassFileName(fullPath.lastSegment());
717 case IClasspathEntry.CPE_LIBRARY:
718 // .java files are not visible in library folders
719 return !net.sourceforge.phpdt.internal.compiler.util.Util.isJavaFileName(fullPath.lastSegment());
722 if (innerMostOutput != null) {
729 * Record a new marker denoting a classpath problem
731 IMarker createClasspathProblemMarker(IJavaModelStatus status) {
733 IMarker marker = null;
735 String[] arguments = new String[0];
736 boolean isCycleProblem = false, isClasspathFileFormatProblem = false;
737 switch (status.getCode()) {
739 case IJavaModelStatusConstants.CLASSPATH_CYCLE :
740 isCycleProblem = true;
741 if (JavaCore.ERROR.equals(getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true))) {
742 severity = IMarker.SEVERITY_ERROR;
744 severity = IMarker.SEVERITY_WARNING;
748 case IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT :
749 isClasspathFileFormatProblem = true;
750 severity = IMarker.SEVERITY_ERROR;
754 IPath path = status.getPath();
755 if (path != null) arguments = new String[] { path.toString() };
756 if (JavaCore.ERROR.equals(getOption(JavaCore.CORE_INCOMPLETE_CLASSPATH, true))) {
757 severity = IMarker.SEVERITY_ERROR;
759 severity = IMarker.SEVERITY_WARNING;
765 marker = getProject().createMarker(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER);
766 marker.setAttributes(
771 IJavaModelMarker.CYCLE_DETECTED,
772 IJavaModelMarker.CLASSPATH_FILE_FORMAT,
774 IJavaModelMarker.ARGUMENTS ,
778 new Integer(severity),
779 Util.bind("classpath.buildPath"),//$NON-NLS-1$
780 isCycleProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
781 isClasspathFileFormatProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
782 new Integer(status.getCode()),
783 Util.getProblemArgumentsForMarker(arguments) ,
786 } catch (CoreException e) {
792 * Returns a new element info for this element.
794 protected Object createElementInfo() {
795 return new JavaProjectElementInfo();
800 * Returns a new search name environment for this project. This name environment first looks in the given working copies.
802 // public ISearchableNameEnvironment newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws JavaModelException {
803 // return new SearchableEnvironment(this, workingCopies);
807 * Returns a new search name environment for this project. This name environment first looks in the working copies
808 * of the given owner.
810 public ISearchableNameEnvironment newSearchableNameEnvironment(WorkingCopyOwner owner) throws JavaModelException {
811 return new SearchableEnvironment(this, owner);
814 * Reads and decode an XML classpath string
816 protected IClasspathEntry[] decodeClasspath(String xmlClasspath, boolean createMarker, boolean logProblems) {
818 ArrayList paths = new ArrayList();
819 IClasspathEntry defaultOutput = null;
821 if (xmlClasspath == null) return null;
822 StringReader reader = new StringReader(xmlClasspath);
826 DocumentBuilder parser =
827 DocumentBuilderFactory.newInstance().newDocumentBuilder();
828 cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
829 } catch (SAXException e) {
830 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
831 } catch (ParserConfigurationException e) {
832 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
837 if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$
838 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
840 NodeList list = cpElement.getElementsByTagName("classpathentry"); //$NON-NLS-1$
841 int length = list.getLength();
843 for (int i = 0; i < length; ++i) {
844 Node node = list.item(i);
845 if (node.getNodeType() == Node.ELEMENT_NODE) {
846 IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this);
848 if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
849 defaultOutput = entry; // separate output
856 } catch (IOException e) {
858 if (createMarker && this.getProject().isAccessible()) {
859 this.createClasspathProblemMarker(new JavaModelStatus(
860 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
861 Util.bind("classpath.xmlFormatError", this.getElementName(), e.getMessage()))); //$NON-NLS-1$
865 "Exception while retrieving "+ this.getPath() //$NON-NLS-1$
866 +"/.classpath, will mark classpath as invalid"); //$NON-NLS-1$
868 return INVALID_CLASSPATH;
869 } catch (Assert.AssertionFailedException e) {
870 // failed creating CP entries from file
871 if (createMarker && this.getProject().isAccessible()) {
872 this.createClasspathProblemMarker(new JavaModelStatus(
873 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
874 Util.bind("classpath.illegalEntryInClasspathFile", this.getElementName(), e.getMessage()))); //$NON-NLS-1$
878 "Exception while retrieving "+ this.getPath() //$NON-NLS-1$
879 +"/.classpath, will mark classpath as invalid"); //$NON-NLS-1$
881 return INVALID_CLASSPATH;
883 int pathSize = paths.size();
884 if (pathSize > 0 || defaultOutput != null) {
885 IClasspathEntry[] entries = new IClasspathEntry[pathSize + (defaultOutput == null ? 0 : 1)];
886 paths.toArray(entries);
887 if (defaultOutput != null) entries[pathSize] = defaultOutput; // ensure output is last item
896 * Removes the Java nature from the project.
898 public void deconfigure() throws CoreException {
900 // deregister Java builder
901 removeFromBuildSpec(PHPeclipsePlugin.BUILDER_PARSER_ID);
905 * Returns a default class path.
906 * This is the root of the project
908 protected IClasspathEntry[] defaultClasspath() throws JavaModelException {
910 return new IClasspathEntry[] {
911 JavaCore.newSourceEntry(getProject().getFullPath())};
915 * Returns a default output location.
916 * This is the project bin folder
918 protected IPath defaultOutputLocation() throws JavaModelException {
919 return null; //getProject().getFullPath().append("bin"); //$NON-NLS-1$
923 * Returns the XML String encoding of the class path.
925 protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean indent) throws JavaModelException {
927 ByteArrayOutputStream s = new ByteArrayOutputStream();
928 OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
929 XMLWriter xmlWriter = new XMLWriter(writer);
931 xmlWriter.startTag("classpath", indent); //$NON-NLS-1$
932 for (int i = 0; i < classpath.length; ++i) {
933 ((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true);
936 if (outputLocation != null) {
937 outputLocation = outputLocation.removeFirstSegments(1);
938 outputLocation = outputLocation.makeRelative();
939 HashMap parameters = new HashMap();
940 parameters.put("kind", ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT));//$NON-NLS-1$
941 parameters.put("path", String.valueOf(outputLocation));//$NON-NLS-1$
942 xmlWriter.printTag("classpathentry", parameters, indent, true, true);//$NON-NLS-1$
945 xmlWriter.endTag("classpath", indent);//$NON-NLS-1$
948 return s.toString("UTF8");//$NON-NLS-1$
949 } catch (IOException e) {
950 throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
954 * Returns the XML String encoding of the class path.
956 // protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean useLineSeparator) throws JavaModelException {
958 // Document document = new DocumentImpl();
959 // Element cpElement = document.createElement("classpath"); //$NON-NLS-1$
960 // document.appendChild(cpElement);
962 // for (int i = 0; i < classpath.length; ++i) {
963 // cpElement.appendChild(((ClasspathEntry)classpath[i]).elementEncode(document, getProject().getFullPath()));
966 // if (outputLocation != null) {
967 // outputLocation = outputLocation.removeFirstSegments(1);
968 // outputLocation = outputLocation.makeRelative();
969 // Element oElement = document.createElement("classpathentry"); //$NON-NLS-1$
970 // oElement.setAttribute("kind", ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT)); //$NON-NLS-1$
971 // oElement.setAttribute("path", outputLocation.toString()); //$NON-NLS-1$
972 // cpElement.appendChild(oElement);
975 // // produce a String output
977 // ByteArrayOutputStream s = new ByteArrayOutputStream();
978 // OutputFormat format = new OutputFormat();
979 // if (useLineSeparator) {
980 // format.setIndenting(true);
981 // format.setLineSeparator(System.getProperty("line.separator")); //$NON-NLS-1$
983 // format.setPreserveSpace(true);
985 // Serializer serializer =
986 // SerializerFactory.getSerializerFactory(Method.XML).makeSerializer(
987 // new OutputStreamWriter(s, "UTF8"), //$NON-NLS-1$
989 // serializer.asDOMSerializer().serialize(document);
990 // return s.toString("UTF8"); //$NON-NLS-1$
991 // } catch (IOException e) {
992 // throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
997 * Returns true if this handle represents the same Java project
998 * as the given handle. Two handles represent the same
999 * project if they are identical or if they represent a project with
1000 * the same underlying resource and occurrence counts.
1002 * @see JavaElement#equals
1004 public boolean equals(Object o) {
1009 if (!(o instanceof JavaProject))
1012 JavaProject other = (JavaProject) o;
1013 return getProject().equals(other.getProject())
1014 && occurrenceCount == other.occurrenceCount;
1017 public boolean exists() {
1018 if (!hasJavaNature(project)) return false;
1019 return super.exists();
1025 public IJavaElement findElement(IPath path) throws JavaModelException {
1027 if (path == null || path.isAbsolute()) {
1028 throw new JavaModelException(
1029 new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, path));
1033 String extension = path.getFileExtension();
1034 if (extension == null) {
1035 String packageName = path.toString().replace(IPath.SEPARATOR, '.');
1037 // IPackageFragment[] pkgFragments =
1038 // getNameLookup().findPackageFragments(packageName, false);
1039 // if (pkgFragments == null) {
1043 // // try to return one that is a child of this project
1044 // for (int i = 0, length = pkgFragments.length; i < length; i++) {
1046 // IPackageFragment pkgFragment = pkgFragments[i];
1047 // if (this.equals(pkgFragment.getParent().getParent())) {
1048 // return pkgFragment;
1051 // // default to the first one
1052 // return pkgFragments[0];
1055 extension.equalsIgnoreCase("java") //$NON-NLS-1$
1056 || extension.equalsIgnoreCase("class")) { //$NON-NLS-1$
1057 IPath packagePath = path.removeLastSegments(1);
1058 String packageName = packagePath.toString().replace(IPath.SEPARATOR, '.');
1059 String typeName = path.lastSegment();
1060 typeName = typeName.substring(0, typeName.length() - extension.length() - 1);
1061 String qualifiedName = null;
1062 if (packageName.length() > 0) {
1063 qualifiedName = packageName + "." + typeName; //$NON-NLS-1$
1065 qualifiedName = typeName;
1068 // getNameLookup().findType(
1071 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1072 // if (type != null) {
1073 // return type.getParent();
1078 // unsupported extension
1081 // } catch (JavaModelException e) {
1082 // if (e.getStatus().getCode()
1083 // == IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST) {
1094 // public IPackageFragment findPackageFragment(IPath path)
1095 // throws JavaModelException {
1097 // return findPackageFragment0(JavaProject.canonicalizedPath(path));
1101 // * non path canonicalizing version
1103 // public IPackageFragment findPackageFragment0(IPath path)
1104 // throws JavaModelException {
1106 // return getNameLookup().findPackageFragment(path);
1112 public IPackageFragmentRoot findPackageFragmentRoot(IPath path)
1113 throws JavaModelException {
1115 return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path));
1119 * no path canonicalization
1121 public IPackageFragmentRoot findPackageFragmentRoot0(IPath path)
1122 throws JavaModelException {
1124 IPackageFragmentRoot[] allRoots = this.getAllPackageFragmentRoots();
1125 if (!path.isAbsolute()) {
1126 throw new IllegalArgumentException(Util.bind("path.mustBeAbsolute")); //$NON-NLS-1$
1128 for (int i= 0; i < allRoots.length; i++) {
1129 IPackageFragmentRoot classpathRoot= allRoots[i];
1130 if (classpathRoot.getPath().equals(path)) {
1131 return classpathRoot;
1139 public IPackageFragmentRoot[] findPackageFragmentRoots(IClasspathEntry entry) {
1141 IClasspathEntry[] classpath = this.getRawClasspath();
1142 for (int i = 0, length = classpath.length; i < length; i++) {
1143 if (classpath[i].equals(entry)) { // entry may need to be resolved
1145 computePackageFragmentRoots(
1146 getResolvedClasspath(new IClasspathEntry[] {entry}, null, true, false, null/*no reverse map*/),
1147 false); // don't retrieve exported roots
1150 } catch (JavaModelException e) {
1152 return new IPackageFragmentRoot[] {};
1156 * @see IJavaProject#findType(String)
1158 // public IType findType(String fullyQualifiedName) throws JavaModelException {
1160 // this.getNameLookup().findType(
1161 // fullyQualifiedName,
1163 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1164 // if (type == null) {
1165 // // try to find enclosing type
1166 // int lastDot = fullyQualifiedName.lastIndexOf('.');
1167 // if (lastDot == -1) return null;
1168 // type = this.findType(fullyQualifiedName.substring(0, lastDot));
1169 // if (type != null) {
1170 // type = type.getType(fullyQualifiedName.substring(lastDot+1));
1171 // if (!type.exists()) {
1180 * @see IJavaProject#findType(String, String)
1182 // public IType findType(String packageName, String typeQualifiedName) throws JavaModelException {
1184 // this.getNameLookup().findType(
1185 // typeQualifiedName,
1188 // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1192 * Remove all markers denoting classpath problems
1194 protected void flushClasspathProblemMarkers(boolean flushCycleMarkers, boolean flushClasspathFormatMarkers) {
1196 IProject project = getProject();
1197 if (project.exists()) {
1198 IMarker[] markers = project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
1199 for (int i = 0, length = markers.length; i < length; i++) {
1200 IMarker marker = markers[i];
1201 if (flushCycleMarkers && flushClasspathFormatMarkers) {
1204 String cycleAttr = (String)marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED);
1205 String classpathFileFormatAttr = (String)marker.getAttribute(IJavaModelMarker.CLASSPATH_FILE_FORMAT);
1206 if ((flushCycleMarkers == (cycleAttr != null && cycleAttr.equals("true"))) //$NON-NLS-1$
1207 && (flushClasspathFormatMarkers == (classpathFileFormatAttr != null && classpathFileFormatAttr.equals("true")))){ //$NON-NLS-1$
1213 } catch (CoreException e) {
1220 // protected boolean generateInfos(
1221 // OpenableElementInfo info,
1222 // IProgressMonitor pm,
1224 // IResource underlyingResource) throws JavaModelException {
1226 // boolean validInfo = false;
1228 // if (getProject().isOpen()) {
1229 // // put the info now, because computing the roots requires it
1230 // JavaModelManager.getJavaModelManager().putInfo(this, info);
1232 // // compute the pkg fragment roots
1233 // updatePackageFragmentRoots();
1235 // // remember the timestamps of external libraries the first time they are looked up
1236 // IClasspathEntry[] resolvedClasspath = getResolvedClasspath(true/*ignore unresolved variable*/);
1237 // for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
1238 // IClasspathEntry entry = resolvedClasspath[i];
1239 // if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
1240 // IPath path = entry.getPath();
1241 // Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
1242 // if (target instanceof java.io.File) {
1243 // Map externalTimeStamps = JavaModelManager.getJavaModelManager().deltaProcessor.externalTimeStamps;
1244 // if (externalTimeStamps.get(path) == null) {
1245 // long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
1246 // externalTimeStamps.put(path, new Long(timestamp));
1252 // // only valid if reaches here
1253 // validInfo = true;
1257 // JavaModelManager.getJavaModelManager().removeInfo(this);
1259 // return validInfo;
1265 public IPackageFragmentRoot[] getAllPackageFragmentRoots()
1266 throws JavaModelException {
1268 return computePackageFragmentRoots(getResolvedClasspath(true), true);
1272 * Returns the classpath entry that refers to the given path
1273 * or <code>null</code> if there is no reference to the path.
1275 public IClasspathEntry getClasspathEntryFor(IPath path)
1276 throws JavaModelException {
1278 IClasspathEntry[] entries = getExpandedClasspath(true);
1279 for (int i = 0; i < entries.length; i++) {
1280 if (entries[i].getPath().equals(path)) {
1288 * Returns the cycle marker associated with this project or null if none.
1290 public IMarker getCycleMarker(){
1292 IProject project = getProject();
1293 if (project.exists()) {
1294 IMarker[] markers = project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
1295 for (int i = 0, length = markers.length; i < length; i++) {
1296 IMarker marker = markers[i];
1297 String cycleAttr = (String)marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED);
1298 if (cycleAttr != null && cycleAttr.equals("true")){ //$NON-NLS-1$
1303 } catch (CoreException e) {
1310 public int getElementType() {
1311 return JAVA_PROJECT;
1314 * This is a helper method returning the expanded classpath for the project, as a list of classpath entries,
1315 * where all classpath variable entries have been resolved and substituted with their final target entries.
1316 * All project exports have been appended to project entries.
1318 public IClasspathEntry[] getExpandedClasspath(boolean ignoreUnresolvedVariable) throws JavaModelException {
1320 return getExpandedClasspath(ignoreUnresolvedVariable, false);
1324 * Internal variant which can create marker on project for invalid entries,
1325 * it will also perform classpath expansion in presence of project prerequisites
1326 * exporting their entries.
1328 public IClasspathEntry[] getExpandedClasspath(
1329 boolean ignoreUnresolvedVariable,
1330 boolean generateMarkerOnError) throws JavaModelException {
1332 ObjectVector accumulatedEntries = new ObjectVector();
1333 computeExpandedClasspath(this, ignoreUnresolvedVariable, generateMarkerOnError, new HashSet(5), accumulatedEntries);
1335 IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries.size()];
1336 accumulatedEntries.copyInto(expandedPath);
1338 return expandedPath;
1342 * Returns the <code>char</code> that marks the start of this handles
1343 * contribution to a memento.
1345 protected char getHandleMementoDelimiter() {
1347 return JEM_JAVAPROJECT;
1351 * Find the specific Java command amongst the build spec of a given description
1353 private ICommand getJavaCommand(IProjectDescription description)
1354 throws CoreException {
1356 ICommand[] commands = description.getBuildSpec();
1357 for (int i = 0; i < commands.length; ++i) {
1358 if (commands[i].getBuilderName().equals(PHPeclipsePlugin.BUILDER_PARSER_ID)) {
1366 * Convenience method that returns the specific type of info for a Java project.
1368 protected JavaProjectElementInfo getJavaProjectElementInfo()
1369 throws JavaModelException {
1371 return (JavaProjectElementInfo) getElementInfo();
1377 public NameLookup getNameLookup() throws JavaModelException {
1379 JavaProjectElementInfo info = getJavaProjectElementInfo();
1380 // lock on the project info to avoid race condition
1382 NameLookup nameLookup;
1383 if ((nameLookup = info.getNameLookup()) == null){
1384 info.setNameLookup(nameLookup = new NameLookup(this));
1390 * Returns a new name lookup. This name lookup first looks in the given working copies.
1392 public NameLookup newNameLookup(ICompilationUnit[] workingCopies) throws JavaModelException {
1394 JavaProjectElementInfo info = getJavaProjectElementInfo();
1395 // lock on the project info to avoid race condition while computing the pkg fragment roots and package fragment caches
1396 // synchronized(info){
1397 // return new NameLookup(info.getAllPackageFragmentRoots(this), info.getAllPackageFragments(this), workingCopies);
1403 * Returns a new name lookup. This name lookup first looks in the working copies of the given owner.
1405 public NameLookup newNameLookup(WorkingCopyOwner owner) throws JavaModelException {
1407 JavaModelManager manager = JavaModelManager.getJavaModelManager();
1408 ICompilationUnit[] workingCopies = owner == null ? null : manager.getWorkingCopies(owner, true/*add primary WCs*/);
1409 return newNameLookup(workingCopies);
1413 // * Returns an array of non-java resources contained in the receiver.
1415 // public Object[] getNonJavaResources() throws JavaModelException {
1417 // return ((JavaProjectElementInfo) getElementInfo()).getNonJavaResources(this);
1421 * @see org.eclipse.jdt.core.IJavaProject#getOption(String, boolean)
1423 public String getOption(String optionName, boolean inheritJavaCoreOptions) {
1425 if (JavaModelManager.OptionNames.contains(optionName)){
1427 Preferences preferences = getPreferences();
1428 if (preferences == null || preferences.isDefault(optionName)) {
1429 return inheritJavaCoreOptions ? JavaCore.getOption(optionName) : null;
1431 return preferences.getString(optionName).trim();
1437 * @see org.eclipse.jdt.core.IJavaProject#getOptions(boolean)
1439 public Map getOptions(boolean inheritJavaCoreOptions) {
1441 // initialize to the defaults from JavaCore options pool
1442 Map options = inheritJavaCoreOptions ? JavaCore.getOptions() : new Hashtable(5);
1444 Preferences preferences = getPreferences();
1445 if (preferences == null) return options; // cannot do better (non-Java project)
1446 HashSet optionNames = JavaModelManager.OptionNames;
1448 // get preferences set to their default
1449 if (inheritJavaCoreOptions){
1450 String[] defaultPropertyNames = preferences.defaultPropertyNames();
1451 for (int i = 0; i < defaultPropertyNames.length; i++){
1452 String propertyName = defaultPropertyNames[i];
1453 if (optionNames.contains(propertyName)){
1454 options.put(propertyName, preferences.getDefaultString(propertyName).trim());
1458 // get custom preferences not set to their default
1459 String[] propertyNames = preferences.propertyNames();
1460 for (int i = 0; i < propertyNames.length; i++){
1461 String propertyName = propertyNames[i];
1462 if (optionNames.contains(propertyName)){
1463 options.put(propertyName, preferences.getString(propertyName).trim());
1472 public IPath getOutputLocation() throws JavaModelException {
1474 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
1475 IPath outputLocation = perProjectInfo.outputLocation;
1476 if (outputLocation != null) return outputLocation;
1478 // force to read classpath - will position output location as well
1479 this.getRawClasspath();
1480 outputLocation = perProjectInfo.outputLocation;
1481 if (outputLocation == null) {
1482 return defaultOutputLocation();
1484 return outputLocation;
1488 * @return A handle to the package fragment root identified by the given path.
1489 * This method is handle-only and the element may or may not exist. Returns
1490 * <code>null</code> if unable to generate a handle from the path (for example,
1491 * an absolute path that has less than 1 segment. The path may be relative or
1494 public IPackageFragmentRoot getPackageFragmentRoot(IPath path) {
1495 if (!path.isAbsolute()) {
1496 path = getPath().append(path);
1498 int segmentCount = path.segmentCount();
1499 switch (segmentCount) {
1504 return getPackageFragmentRoot(getProject());
1506 // a path ending with .jar/.zip is still ambiguous and could still resolve to a source/lib folder
1507 // thus will try to guess based on existing resource
1508 // if (Util.isArchiveFileName(path.lastSegment())) {
1509 // IResource resource = getProject().getWorkspace().getRoot().findMember(path);
1510 // if (resource != null && resource.getType() == IResource.FOLDER){
1511 // return getPackageFragmentRoot(resource);
1513 // return getPackageFragmentRoot0(path);
1515 return getPackageFragmentRoot(getProject().getWorkspace().getRoot().getFolder(path));
1521 * The path is known to match a source/library folder entry.
1523 public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) {
1524 if (path.segmentCount() == 1) { // default project root
1525 return getPackageFragmentRoot(getProject());
1527 return getPackageFragmentRoot(getProject().getWorkspace().getRoot().getFolder(path));
1533 public IPackageFragmentRoot getPackageFragmentRoot(IResource resource) {
1535 switch (resource.getType()) {
1536 case IResource.FILE:
1537 // if (Util.isArchiveFileName(resource.getName())) {
1538 // return new JarPackageFragmentRoot(resource, this);
1542 case IResource.FOLDER:
1543 return new PackageFragmentRoot(resource, this, resource.getName());
1544 case IResource.PROJECT:
1545 return new PackageFragmentRoot(resource, this, ""); //$NON-NLS-1$
1554 // public IPackageFragmentRoot getPackageFragmentRoot(String jarPath) {
1556 // return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new Path(jarPath)));
1560 // * no path canonicalization
1562 // public IPackageFragmentRoot getPackageFragmentRoot0(IPath jarPath) {
1564 // return new JarPackageFragmentRoot(jarPath, this);
1570 public IPackageFragmentRoot[] getPackageFragmentRoots()
1571 throws JavaModelException {
1575 IPackageFragmentRoot[] roots;
1578 children = getChildren(),
1580 roots = new IPackageFragmentRoot[length = children.length],
1591 public IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry) {
1592 return findPackageFragmentRoots(entry);
1596 * Returns the package fragment root prefixed by the given path, or
1597 * an empty collection if there are no such elements in the model.
1599 protected IPackageFragmentRoot[] getPackageFragmentRoots(IPath path)
1601 throws JavaModelException {
1602 IPackageFragmentRoot[] roots = getAllPackageFragmentRoots();
1603 ArrayList matches = new ArrayList();
1605 for (int i = 0; i < roots.length; ++i) {
1606 if (path.isPrefixOf(roots[i].getPath())) {
1607 matches.add(roots[i]);
1610 IPackageFragmentRoot[] copy = new IPackageFragmentRoot[matches.size()];
1611 matches.toArray(copy);
1618 public IPackageFragment[] getPackageFragments() throws JavaModelException {
1620 IPackageFragmentRoot[] roots = getPackageFragmentRoots();
1621 return getPackageFragmentsInRoots(roots);
1625 * Returns all the package fragments found in the specified
1626 * package fragment roots.
1628 public IPackageFragment[] getPackageFragmentsInRoots(IPackageFragmentRoot[] roots) {
1630 ArrayList frags = new ArrayList();
1631 for (int i = 0; i < roots.length; i++) {
1632 IPackageFragmentRoot root = roots[i];
1634 IJavaElement[] rootFragments = root.getChildren();
1635 for (int j = 0; j < rootFragments.length; j++) {
1636 frags.add(rootFragments[j]);
1638 } catch (JavaModelException e) {
1642 IPackageFragment[] fragments = new IPackageFragment[frags.size()];
1643 frags.toArray(fragments);
1650 public IPath getPath() {
1651 return this.getProject().getFullPath();
1657 public IProject getProject() {
1662 * Sets the underlying kernel project of this Java project,
1663 * and fills in its parent and name.
1664 * Called by IProject.getNature().
1666 * @see IProjectNature#setProject(IProject)
1668 public void setProject(IProject project) {
1670 this.project = project;
1671 this.parent = JavaModelManager.getJavaModelManager().getJavaModel();
1672 this.name = project.getName();
1674 protected IProject getProject(String name) {
1675 return PHPeclipsePlugin.getWorkspace().getRoot().getProject(name);
1678 public List getReferencedProjects() {
1679 List referencedProjects = new ArrayList();
1681 Iterator iterator = getLoadPathEntries().iterator();
1682 while (iterator.hasNext()) {
1683 LoadPathEntry pathEntry = (LoadPathEntry) iterator.next();
1684 if (pathEntry.getType() == LoadPathEntry.TYPE_PROJECT)
1685 referencedProjects.add(pathEntry.getProject());
1688 return referencedProjects;
1692 * Returns the project custom preference pool.
1693 * Project preferences may include custom encoding.
1695 public Preferences getPreferences(){
1696 IProject project = getProject();
1697 if (!JavaProject.hasJavaNature(project)) return null;
1698 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(project, true);
1699 Preferences preferences = perProjectInfo.preferences;
1700 if (preferences != null) return preferences;
1701 preferences = loadPreferences();
1702 if (preferences == null) preferences = new Preferences();
1703 perProjectInfo.preferences = preferences;
1710 public IClasspathEntry[] getRawClasspath() throws JavaModelException {
1712 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
1713 IClasspathEntry[] classpath = perProjectInfo.classpath;
1714 if (classpath != null) return classpath;
1715 classpath = this.readClasspathFile(false/*don't create markers*/, true/*log problems*/);
1717 // extract out the output location
1718 IPath outputLocation = null;
1719 if (classpath != null && classpath.length > 0) {
1720 IClasspathEntry entry = classpath[classpath.length - 1];
1721 if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
1722 outputLocation = entry.getPath();
1723 IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
1724 System.arraycopy(classpath, 0, copy, 0, copy.length);
1728 if (classpath == null) {
1729 return defaultClasspath();
1731 /* Disable validate: classpath can contain CP variables and container that need to be resolved
1732 if (classpath != INVALID_CLASSPATH
1733 && !JavaConventions.validateClasspath(this, classpath, outputLocation).isOK()) {
1734 classpath = INVALID_CLASSPATH;
1737 perProjectInfo.classpath = classpath;
1738 perProjectInfo.outputLocation = outputLocation;
1743 * @see IJavaProject#getRequiredProjectNames
1745 public String[] getRequiredProjectNames() throws JavaModelException {
1747 return this.projectPrerequisites(getResolvedClasspath(true));
1753 public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry)
1754 throws JavaModelException {
1757 this.getResolvedClasspath(
1758 ignoreUnresolvedEntry,
1759 false); // generateMarkerOnError
1763 * Internal variant which can create marker on project for invalid entries
1764 * and caches the resolved classpath on perProjectInfo
1766 public IClasspathEntry[] getResolvedClasspath(
1767 boolean ignoreUnresolvedEntry,
1768 boolean generateMarkerOnError)
1769 throws JavaModelException {
1771 JavaModelManager manager = JavaModelManager.getJavaModelManager();
1772 JavaModelManager.PerProjectInfo perProjectInfo = manager.getPerProjectInfoCheckExistence(project);
1774 // reuse cache if not needing to refresh markers or checking bound variables
1775 if (ignoreUnresolvedEntry && !generateMarkerOnError && perProjectInfo != null){
1776 // resolved path is cached on its info
1777 IClasspathEntry[] infoPath = perProjectInfo.lastResolvedClasspath;
1778 if (infoPath != null) return infoPath;
1780 Map reverseMap = perProjectInfo == null ? null : new HashMap(5);
1781 IClasspathEntry[] resolvedPath = getResolvedClasspath(
1783 generateMarkerOnError ? getOutputLocation() : null,
1784 ignoreUnresolvedEntry,
1785 generateMarkerOnError,
1788 if (perProjectInfo != null){
1789 if (perProjectInfo.classpath == null // .classpath file could not be read
1790 && generateMarkerOnError
1791 && JavaProject.hasJavaNature(project)) {
1792 this.createClasspathProblemMarker(new JavaModelStatus(
1793 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1794 Util.bind("classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
1797 perProjectInfo.lastResolvedClasspath = resolvedPath;
1798 perProjectInfo.resolvedPathToRawEntries = reverseMap;
1800 return resolvedPath;
1804 * Internal variant which can process any arbitrary classpath
1806 public IClasspathEntry[] getResolvedClasspath(
1807 IClasspathEntry[] classpathEntries,
1808 IPath projectOutputLocation, // only set if needing full classpath validation (and markers)
1809 boolean ignoreUnresolvedEntry, // if unresolved entries are met, should it trigger initializations
1810 boolean generateMarkerOnError,
1811 Map reverseMap) // can be null if not interested in reverse mapping
1812 throws JavaModelException {
1814 IJavaModelStatus status;
1815 if (generateMarkerOnError){
1816 flushClasspathProblemMarkers(false, false);
1819 int length = classpathEntries.length;
1820 ArrayList resolvedEntries = new ArrayList();
1822 for (int i = 0; i < length; i++) {
1824 IClasspathEntry rawEntry = classpathEntries[i];
1828 /* validation if needed */
1829 // if (generateMarkerOnError || !ignoreUnresolvedEntry) {
1830 // status = JavaConventions.validateClasspathEntry(this, rawEntry, false);
1831 // if (generateMarkerOnError && !status.isOK()) createClasspathProblemMarker(status);
1834 switch (rawEntry.getEntryKind()){
1836 case IClasspathEntry.CPE_VARIABLE :
1838 IClasspathEntry resolvedEntry = JavaCore.getResolvedClasspathEntry(rawEntry);
1839 if (resolvedEntry == null) {
1840 if (!ignoreUnresolvedEntry) throw new JavaModelException(status);
1842 if (reverseMap != null && reverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) reverseMap.put(resolvedPath , rawEntry);
1843 resolvedEntries.add(resolvedEntry);
1847 // case IClasspathEntry.CPE_CONTAINER :
1849 // IClasspathContainer container = PHPCore.getClasspathContainer(rawEntry.getPath(), this);
1850 // if (container == null){
1851 // if (!ignoreUnresolvedEntry) throw new JavaModelException(status);
1855 // IClasspathEntry[] containerEntries = container.getClasspathEntries();
1856 // if (containerEntries == null) break;
1858 // // container was bound
1859 // for (int j = 0, containerLength = containerEntries.length; j < containerLength; j++){
1860 // IClasspathEntry cEntry = containerEntries[j];
1862 // if (generateMarkerOnError) {
1863 // IJavaModelStatus containerStatus = JavaConventions.validateClasspathEntry(this, cEntry, false);
1864 // if (!containerStatus.isOK()) createClasspathProblemMarker(containerStatus);
1866 // // if container is exported, then its nested entries must in turn be exported (21749)
1867 // if (rawEntry.isExported()){
1868 // cEntry = new ClasspathEntry(cEntry.getContentKind(),
1869 // cEntry.getEntryKind(), cEntry.getPath(),
1870 // cEntry.getExclusionPatterns(), cEntry.getSourceAttachmentPath(),
1871 // cEntry.getSourceAttachmentRootPath(), cEntry.getOutputLocation(),
1872 // true); // duplicate container entry for tagging it as exported
1874 // if (reverseMap != null && reverseMap.get(resolvedPath = cEntry.getPath()) == null) reverseMap.put(resolvedPath, rawEntry);
1875 // resolvedEntries.add(cEntry);
1881 if (reverseMap != null && reverseMap.get(resolvedPath = rawEntry.getPath()) == null) reverseMap.put(resolvedPath, rawEntry);
1882 resolvedEntries.add(rawEntry);
1887 IClasspathEntry[] resolvedPath = new IClasspathEntry[resolvedEntries.size()];
1888 resolvedEntries.toArray(resolvedPath);
1890 // if (generateMarkerOnError && projectOutputLocation != null) {
1891 // status = JavaConventions.validateClasspath(this, resolvedPath, projectOutputLocation);
1892 // if (!status.isOK()) createClasspathProblemMarker(status);
1894 return resolvedPath;
1900 public IResource getResource() {
1901 return this.getProject();
1907 public ISearchableNameEnvironment getSearchableNameEnvironment()
1908 throws JavaModelException {
1910 JavaProjectElementInfo info = getJavaProjectElementInfo();
1911 if (info.getSearchableEnvironment() == null) {
1912 info.setSearchableEnvironment(new SearchableEnvironment(this));
1914 return info.getSearchableEnvironment();
1918 * Retrieve a shared property on a project. If the property is not defined, answers null.
1919 * Note that it is orthogonal to IResource persistent properties, and client code has to decide
1920 * which form of storage to use appropriately. Shared properties produce real resource files which
1921 * can be shared through a VCM onto a server. Persistent properties are not shareable.
1923 * @see JavaProject#setSharedProperty(String, String)
1925 public String getSharedProperty(String key) throws CoreException {
1927 String property = null;
1928 IFile rscFile = getProject().getFile(key);
1929 if (rscFile.exists()) {
1930 property = new String(Util.getResourceContentsAsByteArray(rscFile));
1938 // public SourceMapper getSourceMapper() {
1946 public IResource getUnderlyingResource() throws JavaModelException {
1947 if (!exists()) throw newNotPresentException();
1948 return getProject();
1954 public boolean hasBuildState() {
1956 return JavaModelManager.getJavaModelManager().getLastBuiltState(this.getProject(), null) != null;
1962 public boolean hasClasspathCycle(IClasspathEntry[] preferredClasspath) {
1963 HashSet cycleParticipants = new HashSet();
1964 updateCycleParticipants(preferredClasspath, new ArrayList(2), cycleParticipants, ResourcesPlugin.getWorkspace().getRoot(), new HashSet(2));
1965 return !cycleParticipants.isEmpty();
1968 public boolean hasCycleMarker(){
1969 return this.getCycleMarker() != null;
1972 public int hashCode() {
1973 return project.hashCode();
1977 * Returns true if the given project is accessible and it has
1978 * a java nature, otherwise false.
1980 public static boolean hasJavaNature(IProject project) {
1982 return project.hasNature(PHPeclipsePlugin.PHP_NATURE_ID);
1983 } catch (CoreException e) {
1984 // project does not exist or is not open
1990 * Answers true if the project potentially contains any source. A project which has no source is immutable.
1992 public boolean hasSource() {
1994 // look if any source folder on the classpath
1995 // no need for resolved path given source folder cannot be abstracted
1996 IClasspathEntry[] entries;
1998 entries = this.getRawClasspath();
1999 } catch (JavaModelException e) {
2000 return true; // unsure
2002 for (int i = 0, max = entries.length; i < max; i++) {
2003 if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
2011 * Compare current classpath with given one to see if any different.
2012 * Note that the argument classpath contains its binary output.
2014 public boolean isClasspathEqualsTo(IClasspathEntry[] newClasspath, IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput)
2015 throws JavaModelException {
2017 if (otherClasspathWithOutput != null && otherClasspathWithOutput.length > 0) {
2019 int length = otherClasspathWithOutput.length;
2020 if (length == newClasspath.length + 1) {
2021 // output is amongst file entries (last one)
2023 // compare classpath entries
2024 for (int i = 0; i < length - 1; i++) {
2025 if (!otherClasspathWithOutput[i].equals(newClasspath[i]))
2028 // compare binary outputs
2029 IClasspathEntry output = otherClasspathWithOutput[length - 1];
2030 if (output.getContentKind() == ClasspathEntry.K_OUTPUT
2031 && output.getPath().equals(newOutputLocation))
2043 public boolean isOnClasspath(IJavaElement element) {
2044 IPath path = element.getPath();
2045 switch (element.getElementType()) {
2046 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
2047 if (!((IPackageFragmentRoot)element).isArchive()) {
2048 // ensure that folders are only excluded if all of their children are excluded
2049 path = path.append("*"); //$NON-NLS-1$
2052 case IJavaElement.PACKAGE_FRAGMENT:
2053 if (!((IPackageFragmentRoot)element.getParent()).isArchive()) {
2054 // ensure that folders are only excluded if all of their children are excluded
2055 path = path.append("*"); //$NON-NLS-1$
2059 return this.isOnClasspath(path);
2061 private boolean isOnClasspath(IPath path) {
2062 IClasspathEntry[] classpath;
2064 classpath = this.getResolvedClasspath(true/*ignore unresolved variable*/);
2065 } catch(JavaModelException e){
2066 return false; // not a Java project
2068 for (int i = 0; i < classpath.length; i++) {
2069 IClasspathEntry entry = classpath[i];
2070 if (entry.getPath().isPrefixOf(path)
2071 && !Util.isExcluded(path, ((ClasspathEntry)entry).fullExclusionPatternChars())) {
2080 public boolean isOnClasspath(IResource resource) {
2081 IPath path = resource.getFullPath();
2083 // ensure that folders are only excluded if all of their children are excluded
2084 if (resource.getType() == IResource.FOLDER) {
2085 path = path.append("*"); //$NON-NLS-1$
2088 return this.isOnClasspath(path);
2093 * load preferences from a shareable format (VCM-wise)
2095 public Preferences loadPreferences() {
2097 Preferences preferences = new Preferences();
2099 // File prefFile = getProject().getLocation().append(PREF_FILENAME).toFile();
2100 IPath projectMetaLocation = getProject().getPluginWorkingLocation(JavaCore.getPlugin().getDescriptor());
2101 if (projectMetaLocation != null) {
2102 File prefFile = projectMetaLocation.append(PREF_FILENAME).toFile();
2103 if (prefFile.exists()) { // load preferences from file
2104 InputStream in = null;
2106 in = new BufferedInputStream(new FileInputStream(prefFile));
2107 preferences.load(in);
2109 } catch (IOException e) { // problems loading preference store - quietly ignore
2114 } catch (IOException e) { // ignore problems with close
2124 * @see IJavaProject#newEvaluationContext
2126 // public IEvaluationContext newEvaluationContext() {
2128 // return new EvaluationContextWrapper(new EvaluationContext(), this);
2134 // public ITypeHierarchy newTypeHierarchy(
2136 // IProgressMonitor monitor)
2137 // throws JavaModelException {
2139 // if (region == null) {
2140 // throw new IllegalArgumentException(Util.bind("hierarchy.nullRegion"));//$NON-NLS-1$
2142 // CreateTypeHierarchyOperation op =
2143 // new CreateTypeHierarchyOperation(null, region, this, true);
2144 // runOperation(op, monitor);
2145 // return op.getResult();
2151 // public ITypeHierarchy newTypeHierarchy(
2154 // IProgressMonitor monitor)
2155 // throws JavaModelException {
2157 // if (type == null) {
2158 // throw new IllegalArgumentException(Util.bind("hierarchy.nullFocusType"));//$NON-NLS-1$
2160 // if (region == null) {
2161 // throw new IllegalArgumentException(Util.bind("hierarchy.nullRegion"));//$NON-NLS-1$
2163 // CreateTypeHierarchyOperation op =
2164 // new CreateTypeHierarchyOperation(type, region, this, true);
2165 // runOperation(op, monitor);
2166 // return op.getResult();
2170 // * Open project if resource isn't closed
2172 // protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
2174 // if (!this.fProject.isOpen()) {
2175 // throw newNotPresentException();
2177 // super.openWhenClosed(pm);
2181 public String[] projectPrerequisites(IClasspathEntry[] entries)
2182 throws JavaModelException {
2184 ArrayList prerequisites = new ArrayList();
2186 entries = getResolvedClasspath(entries, null, true, false, null/*no reverse map*/);
2187 for (int i = 0, length = entries.length; i < length; i++) {
2188 IClasspathEntry entry = entries[i];
2189 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
2190 prerequisites.add(entry.getPath().lastSegment());
2193 int size = prerequisites.size();
2195 return NO_PREREQUISITES;
2197 String[] result = new String[size];
2198 prerequisites.toArray(result);
2205 * Reads the .classpath file from disk and returns the list of entries it contains (including output location entry)
2206 * Returns null if .classfile is not present.
2207 * Returns INVALID_CLASSPATH if it has a format problem.
2209 protected IClasspathEntry[] readClasspathFile(boolean createMarker, boolean logProblems) {
2212 String xmlClasspath = getSharedProperty(CLASSPATH_FILENAME);
2213 if (xmlClasspath == null) return null;
2214 return decodeClasspath(xmlClasspath, createMarker, logProblems);
2215 } catch(CoreException e) {
2216 // file does not exist (or not accessible)
2217 if (createMarker && this.getProject().isAccessible()) {
2218 this.createClasspathProblemMarker(new JavaModelStatus(
2219 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
2220 Util.bind("classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
2224 "Exception while retrieving "+ this.getPath() //$NON-NLS-1$
2225 +"/.classpath, will revert to default classpath"); //$NON-NLS-1$
2232 * Removes the given builder from the build spec for the given project.
2234 protected void removeFromBuildSpec(String builderID) throws CoreException {
2236 IProjectDescription description = getProject().getDescription();
2237 ICommand[] commands = description.getBuildSpec();
2238 for (int i = 0; i < commands.length; ++i) {
2239 if (commands[i].getBuilderName().equals(builderID)) {
2240 ICommand[] newCommands = new ICommand[commands.length - 1];
2241 System.arraycopy(commands, 0, newCommands, 0, i);
2242 System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1);
2243 description.setBuildSpec(newCommands);
2244 getProject().setDescription(description, null);
2252 * @see JavaElement#rootedAt(IJavaProject)
2254 public IJavaElement rootedAt(IJavaProject project) {
2260 * Answers an ID which is used to distinguish project/entries during package
2261 * fragment root computations
2263 public String rootID(){
2264 return "[PRJ]"+this.getProject().getFullPath(); //$NON-NLS-1$
2268 * Saves the classpath in a shareable format (VCM-wise) only when necessary, that is, if it is semantically different
2269 * from the existing one in file. Will never write an identical one.
2271 * @return Return whether the .classpath file was modified.
2273 public boolean saveClasspath(IClasspathEntry[] newClasspath, IPath newOutputLocation) throws JavaModelException {
2275 if (!getProject().exists()) return false;
2277 IClasspathEntry[] fileEntries = readClasspathFile(false /*don't create markers*/, false/*don't log problems*/);
2278 if (fileEntries != null && isClasspathEqualsTo(newClasspath, newOutputLocation, fileEntries)) {
2279 // no need to save it, it is the same
2283 // actual file saving
2285 setSharedProperty(CLASSPATH_FILENAME, encodeClasspath(newClasspath, newOutputLocation, true));
2287 } catch (CoreException e) {
2288 throw new JavaModelException(e);
2293 * Save project custom preferences to shareable file (.jprefs)
2295 private void savePreferences(Preferences preferences) {
2297 IProject project = getProject();
2298 if (!JavaProject.hasJavaNature(project)) return; // ignore
2300 if (preferences == null || (!preferences.needsSaving() && preferences.propertyNames().length != 0)) {
2305 // preferences need to be saved
2306 // the preferences file is located in the plug-in's state area
2307 // at a well-known name (.jprefs)
2308 // File prefFile = getProject().getLocation().append(PREF_FILENAME).toFile();
2309 File prefFile = project.getPluginWorkingLocation(JavaCore.getPlugin().getDescriptor()).append(PREF_FILENAME).toFile();
2310 if (preferences.propertyNames().length == 0) {
2311 // there are no preference settings
2312 // rather than write an empty file, just delete any existing file
2313 if (prefFile.exists()) {
2314 prefFile.delete(); // don't worry if delete unsuccessful
2319 // write file, overwriting an existing one
2320 OutputStream out = null;
2322 // do it as carefully as we know how so that we don't lose/mangle
2323 // the setting in times of stress
2324 out = new BufferedOutputStream(new FileOutputStream(prefFile));
2325 preferences.store(out, null);
2326 } catch (IOException e) { // problems saving preference store - quietly ignore
2331 } catch (IOException e) { // ignore problems with close
2338 * Update the Java command in the build spec (replace existing one if present,
2339 * add one first if none).
2341 private void setJavaCommand(
2342 IProjectDescription description,
2343 ICommand newCommand)
2344 throws CoreException {
2346 ICommand[] oldCommands = description.getBuildSpec();
2347 ICommand oldJavaCommand = getJavaCommand(description);
2348 ICommand[] newCommands;
2350 if (oldJavaCommand == null) {
2351 // Add a Java build spec before other builders (1FWJK7I)
2352 newCommands = new ICommand[oldCommands.length + 1];
2353 System.arraycopy(oldCommands, 0, newCommands, 1, oldCommands.length);
2354 newCommands[0] = newCommand;
2356 for (int i = 0, max = oldCommands.length; i < max; i++) {
2357 if (oldCommands[i] == oldJavaCommand) {
2358 oldCommands[i] = newCommand;
2362 newCommands = oldCommands;
2365 // Commit the spec change into the project
2366 description.setBuildSpec(newCommands);
2367 getProject().setDescription(description, null);
2371 * @see org.eclipse.jdt.core.IJavaProject#setOptions(Map)
2373 public void setOptions(Map newOptions) {
2375 Preferences preferences;
2376 setPreferences(preferences = new Preferences()); // always reset (26255)
2377 if (newOptions != null){
2378 Iterator keys = newOptions.keySet().iterator();
2379 while (keys.hasNext()){
2380 String key = (String)keys.next();
2381 if (!JavaModelManager.OptionNames.contains(key)) continue; // unrecognized option
2382 // no filtering for encoding (custom encoding for project is allowed)
2383 String value = (String)newOptions.get(key);
2384 preferences.setDefault(key, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251)
2385 preferences.setValue(key, value);
2390 savePreferences(preferences);
2396 public void setOutputLocation(IPath path, IProgressMonitor monitor)
2397 throws JavaModelException {
2400 throw new IllegalArgumentException(Util.bind("path.nullpath")); //$NON-NLS-1$
2402 if (path.equals(getOutputLocation())) {
2405 this.setRawClasspath(SetClasspathOperation.ReuseClasspath, path, monitor);
2409 * Set cached preferences, no preference file is saved, only info is updated
2411 public void setPreferences(Preferences preferences) {
2412 IProject project = getProject();
2413 if (!JavaProject.hasJavaNature(project)) return; // ignore
2414 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(project, true);
2415 perProjectInfo.preferences = preferences;
2421 public void setRawClasspath(
2422 IClasspathEntry[] entries,
2423 IPath outputLocation,
2424 IProgressMonitor monitor)
2425 throws JavaModelException {
2431 true, // canChangeResource (as per API contract)
2432 getResolvedClasspath(true), // ignoreUnresolvedVariable
2433 true, // needValidation
2434 true); // need to save
2437 public void setRawClasspath(
2438 IClasspathEntry[] newEntries,
2439 IPath newOutputLocation,
2440 IProgressMonitor monitor,
2441 boolean canChangeResource,
2442 IClasspathEntry[] oldResolvedPath,
2443 boolean needValidation,
2445 throws JavaModelException {
2447 JavaModelManager manager =
2448 (JavaModelManager) JavaModelManager.getJavaModelManager();
2450 IClasspathEntry[] newRawPath = newEntries;
2451 if (newRawPath == null) { //are we already with the default classpath
2452 newRawPath = defaultClasspath();
2454 SetClasspathOperation op =
2455 new SetClasspathOperation(
2463 runOperation(op, monitor);
2465 } catch (JavaModelException e) {
2474 public void setRawClasspath(
2475 IClasspathEntry[] entries,
2476 IProgressMonitor monitor)
2477 throws JavaModelException {
2481 SetClasspathOperation.ReuseOutputLocation,
2483 true, // canChangeResource (as per API contract)
2484 getResolvedClasspath(true), // ignoreUnresolvedVariable
2485 true, // needValidation
2486 true); // need to save
2490 * NOTE: <code>null</code> specifies default classpath, and an empty
2491 * array specifies an empty classpath.
2493 * @exception NotPresentException if this project does not exist.
2495 protected void setRawClasspath0(IClasspathEntry[] rawEntries)
2496 throws JavaModelException {
2498 JavaModelManager.PerProjectInfo info = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
2500 synchronized (info) {
2501 if (rawEntries != null) {
2502 info.classpath = rawEntries;
2505 // clear cache of resolved classpath
2506 info.lastResolvedClasspath = null;
2507 info.resolvedPathToRawEntries = null;
2512 * Record a shared persistent property onto a project.
2513 * Note that it is orthogonal to IResource persistent properties, and client code has to decide
2514 * which form of storage to use appropriately. Shared properties produce real resource files which
2515 * can be shared through a VCM onto a server. Persistent properties are not shareable.
2517 * shared properties end up in resource files, and thus cannot be modified during
2518 * delta notifications (a CoreException would then be thrown).
2520 * @see JavaProject#getSharedProperty(String key)
2522 public void setSharedProperty(String key, String value) throws CoreException {
2524 IFile rscFile = getProject().getFile(key);
2525 InputStream inputStream = new ByteArrayInputStream(value.getBytes());
2526 // update the resource content
2527 if (rscFile.exists()) {
2528 if (rscFile.isReadOnly()) {
2529 // provide opportunity to checkout read-only .classpath file (23984)
2530 ResourcesPlugin.getWorkspace().validateEdit(new IFile[]{rscFile}, null);
2532 rscFile.setContents(inputStream, IResource.FORCE, null);
2534 rscFile.create(inputStream, IResource.FORCE, null);
2539 * Update cycle markers for all java projects
2541 public static void updateAllCycleMarkers() throws JavaModelException {
2543 //long start = System.currentTimeMillis();
2545 JavaModelManager manager = JavaModelManager.getJavaModelManager();
2546 IJavaProject[] projects = manager.getJavaModel().getJavaProjects();
2547 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
2549 HashSet cycleParticipants = new HashSet();
2550 HashSet traversed = new HashSet();
2551 int length = projects.length;
2553 // compute cycle participants
2554 ArrayList prereqChain = new ArrayList();
2555 for (int i = 0; i < length; i++){
2556 JavaProject project = (JavaProject)projects[i];
2557 if (!traversed.contains(project.getPath())){
2558 prereqChain.clear();
2559 project.updateCycleParticipants(null, prereqChain, cycleParticipants, workspaceRoot, traversed);
2562 //System.out.println("updateAllCycleMarkers: " + (System.currentTimeMillis() - start) + " ms");
2564 for (int i = 0; i < length; i++){
2565 JavaProject project = (JavaProject)projects[i];
2567 if (cycleParticipants.contains(project.getPath())){
2568 IMarker cycleMarker = project.getCycleMarker();
2569 String circularCPOption = project.getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true);
2570 int circularCPSeverity = JavaCore.ERROR.equals(circularCPOption) ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING;
2571 if (cycleMarker != null) {
2572 // update existing cycle marker if needed
2574 int existingSeverity = ((Integer)cycleMarker.getAttribute(IMarker.SEVERITY)).intValue();
2575 if (existingSeverity != circularCPSeverity) {
2576 cycleMarker.setAttribute(IMarker.SEVERITY, circularCPSeverity);
2578 } catch (CoreException e) {
2579 throw new JavaModelException(e);
2582 // create new marker
2583 project.createClasspathProblemMarker(
2584 new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE, project));
2587 project.flushClasspathProblemMarkers(true, false);
2593 * If a cycle is detected, then cycleParticipants contains all the paths of projects involved in this cycle (directly and indirectly),
2594 * no cycle if the set is empty (and started empty)
2596 public void updateCycleParticipants(
2597 IClasspathEntry[] preferredClasspath,
2598 ArrayList prereqChain,
2599 HashSet cycleParticipants,
2600 IWorkspaceRoot workspaceRoot,
2603 IPath path = this.getPath();
2604 prereqChain.add(path);
2605 traversed.add(path);
2607 IClasspathEntry[] classpath = preferredClasspath == null ? getResolvedClasspath(true) : preferredClasspath;
2608 for (int i = 0, length = classpath.length; i < length; i++) {
2609 IClasspathEntry entry = classpath[i];
2611 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT){
2612 IPath prereqProjectPath = entry.getPath();
2613 int index = cycleParticipants.contains(prereqProjectPath) ? 0 : prereqChain.indexOf(prereqProjectPath);
2614 if (index >= 0) { // refer to cycle, or in cycle itself
2615 for (int size = prereqChain.size(); index < size; index++) {
2616 cycleParticipants.add(prereqChain.get(index));
2619 if (!traversed.contains(prereqProjectPath)) {
2620 IResource member = workspaceRoot.findMember(prereqProjectPath);
2621 if (member != null && member.getType() == IResource.PROJECT){
2622 JavaProject project = (JavaProject)JavaCore.create((IProject)member);
2623 project.updateCycleParticipants(null, prereqChain, cycleParticipants, workspaceRoot, traversed);
2629 } catch(JavaModelException e){
2631 prereqChain.remove(path);
2634 * Reset the collection of package fragment roots (local ones) - only if opened.
2635 * Need to check *all* package fragment roots in order to reset NameLookup
2637 public void updatePackageFragmentRoots(){
2639 if (this.isOpen()) {
2641 JavaProjectElementInfo info = getJavaProjectElementInfo();
2643 IClasspathEntry[] classpath = getResolvedClasspath(true);
2644 // NameLookup lookup = info.getNameLookup();
2645 // if (lookup != null){
2646 // IPackageFragmentRoot[] oldRoots = lookup.fPackageFragmentRoots;
2647 // IPackageFragmentRoot[] newRoots = computePackageFragmentRoots(classpath, true);
2648 // checkIdentical: { // compare all pkg fragment root lists
2649 // if (oldRoots.length == newRoots.length){
2650 // for (int i = 0, length = oldRoots.length; i < length; i++){
2651 // if (!oldRoots[i].equals(newRoots[i])){
2652 // break checkIdentical;
2655 // return; // no need to update
2658 // info.setNameLookup(null); // discard name lookup (hold onto roots)
2660 info.setNonJavaResources(null);
2662 computePackageFragmentRoots(classpath, false));
2664 } catch(JavaModelException e){
2666 close(); // could not do better
2667 } catch(JavaModelException ex){
2673 public void removeLoadPathEntry(IProject anotherPHPProject) {
2674 Iterator entries = getLoadPathEntries().iterator();
2675 while (entries.hasNext()) {
2676 LoadPathEntry entry = (LoadPathEntry) entries.next();
2677 if (entry.getType() == LoadPathEntry.TYPE_PROJECT && entry.getProject().getName().equals(anotherPHPProject.getName())) {
2678 getLoadPathEntries().remove(entry);
2685 public void save() throws CoreException {
2687 InputStream xmlPath = new ByteArrayInputStream(getLoadPathXML().getBytes());
2688 IFile loadPathsFile = getLoadPathEntriesFile();
2689 if (!loadPathsFile.exists())
2690 loadPathsFile.create(xmlPath, true, null);
2692 loadPathsFile.setContents(xmlPath, true, false, null);