Refactory: removed unnecessary imports.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / JavaProject.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
13 import java.io.BufferedInputStream;
14 import java.io.BufferedOutputStream;
15 import java.io.ByteArrayInputStream;
16 import java.io.ByteArrayOutputStream;
17 import java.io.File;
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;
31 import java.util.Map;
32
33 import javax.xml.parsers.DocumentBuilder;
34 import javax.xml.parsers.DocumentBuilderFactory;
35 import javax.xml.parsers.ParserConfigurationException;
36 import javax.xml.parsers.SAXParserFactory;
37
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 //incastrix
55 //import net.sourceforge.phpdt.internal.corext.Assert;
56 //import org.eclipse.core.runtime.Assert;
57 import net.sourceforge.phpeclipse.LoadPathEntry;
58 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
59
60 import org.eclipse.core.resources.ICommand;
61 import org.eclipse.core.resources.IFile;
62 import org.eclipse.core.resources.IFolder;
63 import org.eclipse.core.resources.IMarker;
64 import org.eclipse.core.resources.IProject;
65 import org.eclipse.core.resources.IProjectDescription;
66 import org.eclipse.core.resources.IProjectNature;
67 import org.eclipse.core.resources.IResource;
68 import org.eclipse.core.resources.IWorkspace;
69 import org.eclipse.core.resources.IWorkspaceRoot;
70 import org.eclipse.core.resources.ResourcesPlugin;
71 import org.eclipse.core.runtime.AssertionFailedException;
72 import org.eclipse.core.runtime.CoreException;
73 import org.eclipse.core.runtime.IPath;
74 import org.eclipse.core.runtime.IProgressMonitor;
75 import org.eclipse.core.runtime.Path;
76 import org.eclipse.core.runtime.Preferences;
77 import org.eclipse.core.runtime.QualifiedName;
78 import org.w3c.dom.Element;
79 import org.w3c.dom.Node;
80 import org.w3c.dom.NodeList;
81 import org.xml.sax.Attributes;
82 import org.xml.sax.ContentHandler;
83 import org.xml.sax.InputSource;
84 import org.xml.sax.Locator;
85 import org.xml.sax.SAXException;
86 import org.xml.sax.XMLReader;
87
88 /**
89  * Handle for a Java Project.
90  * 
91  * <p>
92  * A Java Project internally maintains a devpath that corresponds to the
93  * project's classpath. The classpath may include source folders from the
94  * current project; jars in the current project, other projects, and the local
95  * file system; and binary folders (output location) of other projects. The Java
96  * Model presents source elements corresponding to output .class files in other
97  * projects, and thus uses the devpath rather than the classpath (which is
98  * really a compilation path). The devpath mimics the classpath, except has
99  * source folder entries in place of output locations in external projects.
100  * 
101  * <p>
102  * Each JavaProject has a NameLookup facility that locates elements on by name,
103  * based on the devpath.
104  * 
105  * @see IJavaProject
106  */
107 public class JavaProject extends Openable implements IJavaProject,
108                 IProjectNature {
109
110         /**
111          * Whether the underlying file system is case sensitive.
112          */
113         protected static final boolean IS_CASE_SENSITIVE = !new File("Temp").equals(new File("temp")); //$NON-NLS-1$ //$NON-NLS-2$
114
115         /**
116          * An empty array of strings indicating that a project doesn't have any
117          * prerequesite projects.
118          */
119         protected static final String[] NO_PREREQUISITES = new String[0];
120
121         /**
122          * The platform project this <code>IJavaProject</code> is based on
123          */
124         protected IProject project;
125
126         protected List fLoadPathEntries;
127
128         protected boolean fScratched;
129
130         /**
131          * Name of file containing project classpath
132          */
133         public static final String CLASSPATH_FILENAME = ".classpath"; //$NON-NLS-1$
134
135         /**
136          * Name of file containing custom project preferences
137          */
138         public static final String PREF_FILENAME = ".jprefs"; //$NON-NLS-1$
139
140         /**
141          * Value of the project's raw classpath if the .classpath file contains
142          * invalid entries.
143          */
144         public static final IClasspathEntry[] INVALID_CLASSPATH = new IClasspathEntry[0];
145
146         private static final String CUSTOM_DEFAULT_OPTION_VALUE = "#\r\n\r#custom-non-empty-default-value#\r\n\r#"; //$NON-NLS-1$
147
148         /*
149          * Value of project's resolved classpath while it is being resolved
150          */
151         private static final IClasspathEntry[] RESOLUTION_IN_PROGRESS = new IClasspathEntry[0];
152
153         /**
154          * Returns a canonicalized path from the given external path. Note that the
155          * return path contains the same number of segments and it contains a device
156          * only if the given path contained one.
157          * 
158          * @see java.io.File for the definition of a canonicalized path
159          */
160         public static IPath canonicalizedPath(IPath externalPath) {
161
162                 if (externalPath == null)
163                         return null;
164
165                 if (JavaModelManager.VERBOSE) {
166                         System.out
167                                         .println("JAVA MODEL - Canonicalizing " + externalPath.toString()); //$NON-NLS-1$
168                 }
169
170                 if (IS_CASE_SENSITIVE) {
171                         if (JavaModelManager.VERBOSE) {
172                                 System.out
173                                                 .println("JAVA MODEL - Canonical path is original path (file system is case sensitive)"); //$NON-NLS-1$
174                         }
175                         return externalPath;
176                 }
177
178                 // if not external path, return original path
179                 IWorkspace workspace = ResourcesPlugin.getWorkspace();
180                 if (workspace == null)
181                         return externalPath; // protection during shutdown (30487)
182                 if (workspace.getRoot().findMember(externalPath) != null) {
183                         if (JavaModelManager.VERBOSE) {
184                                 System.out
185                                                 .println("JAVA MODEL - Canonical path is original path (member of workspace)"); //$NON-NLS-1$
186                         }
187                         return externalPath;
188                 }
189
190                 IPath canonicalPath = null;
191                 try {
192                         canonicalPath = new Path(new File(externalPath.toOSString())
193                                         .getCanonicalPath());
194                 } catch (IOException e) {
195                         // default to original path
196                         if (JavaModelManager.VERBOSE) {
197                                 System.out
198                                                 .println("JAVA MODEL - Canonical path is original path (IOException)"); //$NON-NLS-1$
199                         }
200                         return externalPath;
201                 }
202
203                 IPath result;
204                 int canonicalLength = canonicalPath.segmentCount();
205                 if (canonicalLength == 0) {
206                         // the java.io.File canonicalization failed
207                         if (JavaModelManager.VERBOSE) {
208                                 System.out
209                                                 .println("JAVA MODEL - Canonical path is original path (canonical path is empty)"); //$NON-NLS-1$
210                         }
211                         return externalPath;
212                 } else if (externalPath.isAbsolute()) {
213                         result = canonicalPath;
214                 } else {
215                         // if path is relative, remove the first segments that were added by
216                         // the java.io.File canonicalization
217                         // e.g. 'lib/classes.zip' was converted to
218                         // 'd:/myfolder/lib/classes.zip'
219                         int externalLength = externalPath.segmentCount();
220                         if (canonicalLength >= externalLength) {
221                                 result = canonicalPath.removeFirstSegments(canonicalLength
222                                                 - externalLength);
223                         } else {
224                                 if (JavaModelManager.VERBOSE) {
225                                         System.out
226                                                         .println("JAVA MODEL - Canonical path is original path (canonical path is " + canonicalPath.toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
227                                 }
228                                 return externalPath;
229                         }
230                 }
231
232                 // keep device only if it was specified (this is because
233                 // File.getCanonicalPath() converts '/lib/classed.zip' to
234                 // 'd:/lib/classes/zip')
235                 if (externalPath.getDevice() == null) {
236                         result = result.setDevice(null);
237                 }
238                 if (JavaModelManager.VERBOSE) {
239                         System.out
240                                         .println("JAVA MODEL - Canonical path is " + result.toString()); //$NON-NLS-1$
241                 }
242                 return result;
243         }
244
245         /**
246          * Constructor needed for <code>IProject.getNature()</code> and
247          * <code>IProject.addNature()</code>.
248          * 
249          * @see #setProject(IProject)
250          */
251         public JavaProject() {
252                 super(null, null);
253         }
254
255         public JavaProject(IProject project, JavaElement parent) {
256                 super(parent, project.getName());
257                 this.project = project;
258         }
259
260         public void addLoadPathEntry(IProject anotherPHPProject) {
261                 fScratched = true;
262
263                 LoadPathEntry newEntry = new LoadPathEntry(anotherPHPProject);
264                 getLoadPathEntries().add(newEntry);
265         }
266
267         public void configure() throws CoreException {
268                 // get project description and then the associated build commands
269                 IProjectDescription desc = project.getDescription();
270                 ICommand[] commands = desc.getBuildSpec();
271
272                 // determine if builder already associated
273                 boolean found = false;
274                 for (int i = 0; i < commands.length; ++i) {
275                         if (commands[i].getBuilderName().equals(
276                                         PHPeclipsePlugin.BUILDER_PARSER_ID)) {
277                                 found = true;
278                                 break;
279                         }
280                 }
281
282                 // add builder if not already in project
283                 if (!found) {
284                         ICommand command = desc.newCommand();
285                         command.setBuilderName(PHPeclipsePlugin.BUILDER_PARSER_ID);
286                         ICommand[] newCommands = new ICommand[commands.length + 1];
287
288                         // Add it before other builders.
289                         System.arraycopy(commands, 0, newCommands, 1, commands.length);
290                         newCommands[0] = command;
291                         desc.setBuildSpec(newCommands);
292                         project.setDescription(desc, null);
293                 }
294         }
295
296         protected void loadLoadPathEntries() {
297                 fLoadPathEntries = new ArrayList();
298
299                 IFile loadPathsFile = getLoadPathEntriesFile();
300
301                 XMLReader reader = null;
302                 try {
303                         reader = SAXParserFactory.newInstance().newSAXParser()
304                                         .getXMLReader();
305                         reader.setContentHandler(getLoadPathEntriesContentHandler());
306                         reader.parse(new InputSource(loadPathsFile.getContents()));
307                 } catch (Exception e) {
308                         // the file is nonextant or unreadable
309                 }
310         }
311
312         public List getLoadPathEntries() {
313                 if (fLoadPathEntries == null) {
314                         loadLoadPathEntries();
315                 }
316
317                 return fLoadPathEntries;
318         }
319
320         protected ContentHandler getLoadPathEntriesContentHandler() {
321                 return new ContentHandler() {
322                         public void characters(char[] arg0, int arg1, int arg2)
323                                         throws SAXException {
324                         }
325
326                         public void endDocument() throws SAXException {
327                         }
328
329                         public void endElement(String arg0, String arg1, String arg2)
330                                         throws SAXException {
331                         }
332
333                         public void endPrefixMapping(String arg0) throws SAXException {
334                         }
335
336                         public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
337                                         throws SAXException {
338                         }
339
340                         public void processingInstruction(String arg0, String arg1)
341                                         throws SAXException {
342                         }
343
344                         public void setDocumentLocator(Locator arg0) {
345                         }
346
347                         public void skippedEntity(String arg0) throws SAXException {
348                         }
349
350                         public void startDocument() throws SAXException {
351                         }
352
353                         public void startElement(String namespaceURI, String localName,
354                                         String qName, Attributes atts) throws SAXException {
355                                 if ("pathentry".equals(qName))
356                                         if ("project".equals(atts.getValue("type"))) {
357                                                 IPath referencedProjectPath = new Path(atts
358                                                                 .getValue("path"));
359                                                 IProject referencedProject = getProject(referencedProjectPath
360                                                                 .lastSegment());
361                                                 fLoadPathEntries.add(new LoadPathEntry(
362                                                                 referencedProject));
363                                         }
364                         }
365
366                         public void startPrefixMapping(String arg0, String arg1)
367                                         throws SAXException {
368                         }
369                 };
370         }
371
372         protected IFile getLoadPathEntriesFile() {
373                 return project.getFile(".loadpath");
374         }
375
376         protected String getLoadPathXML() {
377                 StringBuffer buffer = new StringBuffer();
378                 buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><loadpath>");
379
380                 Iterator pathEntriesIterator = fLoadPathEntries.iterator();
381
382                 while (pathEntriesIterator.hasNext()) {
383                         LoadPathEntry entry = (LoadPathEntry) pathEntriesIterator.next();
384                         buffer.append(entry.toXML());
385                 }
386
387                 buffer.append("</loadpath>");
388                 return buffer.toString();
389         }
390
391         /**
392          * Adds a builder to the build spec for the given project.
393          */
394         protected void addToBuildSpec(String builderID) throws CoreException {
395
396                 IProjectDescription description = getProject().getDescription();
397                 ICommand javaCommand = getJavaCommand(description);
398
399                 if (javaCommand == null) {
400
401                         // Add a Java command to the build spec
402                         ICommand command = description.newCommand();
403                         command.setBuilderName(builderID);
404                         setJavaCommand(description, command);
405                 }
406         }
407
408         /**
409          * @see Openable
410          */
411         protected boolean buildStructure(OpenableElementInfo info,
412                         IProgressMonitor pm, Map newElements, IResource underlyingResource)
413                         throws JavaModelException {
414
415                 // check whether the java project can be opened
416                 if (!underlyingResource.isAccessible()) {
417                         throw newNotPresentException();
418                 }
419
420                 //IWorkspace workspace = ResourcesPlugin.getWorkspace();
421                 //IWorkspaceRoot wRoot = workspace.getRoot();
422                 // cannot refresh cp markers on opening (emulate cp check on startup)
423                 // since can create deadlocks (see bug 37274)
424                 // IClasspathEntry[] resolvedClasspath =
425                 // getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't
426                 // generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
427
428                 // // compute the pkg fragment roots
429                 // info.setChildren(computePackageFragmentRoots(resolvedClasspath,
430                 // false));
431                 //              
432                 // // remember the timestamps of external libraries the first time they
433                 // are looked up
434                 // for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
435                 // IClasspathEntry entry = resolvedClasspath[i];
436                 // if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
437                 // IPath path = entry.getPath();
438                 // Object target = JavaModel.getTarget(wRoot, path, true);
439                 // if (target instanceof java.io.File) {
440                 // Map externalTimeStamps =
441                 // JavaModelManager.getJavaModelManager().deltaState.externalTimeStamps;
442                 // if (externalTimeStamps.get(path) == null) {
443                 // long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
444                 // externalTimeStamps.put(path, new Long(timestamp));
445                 // }
446                 // }
447                 // }
448                 // }
449
450                 return true;
451         }
452
453         protected void closing(Object info) {
454
455                 // // forget source attachment recommendations
456                 // Object[] children = ((JavaElementInfo)info).children;
457                 // for (int i = 0, length = children.length; i < length; i++) {
458                 // Object child = children[i];
459                 // if (child instanceof JarPackageFragmentRoot){
460                 // ((JarPackageFragmentRoot)child).setSourceAttachmentProperty(null);
461                 // }
462                 // }
463
464                 super.closing(info);
465         }
466
467         // protected void closing(Object info) throws JavaModelException {
468         //              
469         // // forget source attachment recommendations
470         // IPackageFragmentRoot[] roots = this.getPackageFragmentRoots();
471         // // for (int i = 0; i < roots.length; i++) {
472         // // if (roots[i] instanceof JarPackageFragmentRoot){
473         // // ((JarPackageFragmentRoot) roots[i]).setSourceAttachmentProperty(null);
474         // // }
475         // // }
476         //              
477         // super.closing(info);
478         // }
479
480         /**
481          * Internal computation of an expanded classpath. It will eliminate
482          * duplicates, and produce copies of exported classpath entries to avoid
483          * possible side-effects ever after.
484          */
485         private void computeExpandedClasspath(JavaProject initialProject,
486                         boolean ignoreUnresolvedVariable, boolean generateMarkerOnError,
487                         HashSet rootIDs, ObjectVector accumulatedEntries,
488                         Map preferredClasspaths, Map preferredOutputs)
489                         throws JavaModelException {
490
491                 String projectRootId = this.rootID();
492                 if (rootIDs.contains(projectRootId)) {
493                         return; // break cycles if any
494                 }
495                 rootIDs.add(projectRootId);
496
497                 IClasspathEntry[] preferredClasspath = preferredClasspaths != null ? (IClasspathEntry[]) preferredClasspaths
498                                 .get(this)
499                                 : null;
500                 IPath preferredOutput = preferredOutputs != null ? (IPath) preferredOutputs
501                                 .get(this)
502                                 : null;
503                 IClasspathEntry[] immediateClasspath = preferredClasspath != null ? getResolvedClasspath(
504                                 preferredClasspath, preferredOutput, ignoreUnresolvedVariable,
505                                 generateMarkerOnError, null)
506                                 : getResolvedClasspath(ignoreUnresolvedVariable,
507                                                 generateMarkerOnError, false/*
508                                                                                                          * don't
509                                                                                                          * returnResolutionInProgress
510                                                                                                          */);
511
512                 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
513                 boolean isInitialProject = this.equals(initialProject);
514                 for (int i = 0, length = immediateClasspath.length; i < length; i++) {
515                         ClasspathEntry entry = (ClasspathEntry) immediateClasspath[i];
516                         if (isInitialProject || entry.isExported()) {
517                                 String rootID = entry.rootID();
518                                 if (rootIDs.contains(rootID)) {
519                                         continue;
520                                 }
521
522                                 accumulatedEntries.add(entry);
523
524                                 // recurse in project to get all its indirect exports (only
525                                 // consider exported entries from there on)
526                                 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
527                                         IResource member = workspaceRoot
528                                                         .findMember(entry.getPath());
529                                         if (member != null && member.getType() == IResource.PROJECT) { // double
530                                                                                                                                                                         // check
531                                                                                                                                                                         // if
532                                                                                                                                                                         // bound
533                                                                                                                                                                         // to
534                                                                                                                                                                         // project
535                                                                                                                                                                         // (23977)
536                                                 IProject projRsc = (IProject) member;
537                                                 if (JavaProject.hasJavaNature(projRsc)) {
538                                                         JavaProject javaProject = (JavaProject) JavaCore
539                                                                         .create(projRsc);
540                                                         javaProject
541                                                                         .computeExpandedClasspath(
542                                                                                         initialProject,
543                                                                                         ignoreUnresolvedVariable,
544                                                                                         false /*
545                                                                                                          * no marker when recursing
546                                                                                                          * in prereq
547                                                                                                          */,
548                                                                                         rootIDs, accumulatedEntries,
549                                                                                         preferredClasspaths,
550                                                                                         preferredOutputs);
551                                                 }
552                                         }
553                                 } else {
554                                         rootIDs.add(rootID);
555                                 }
556                         }
557                 }
558         }
559
560         /**
561          * Internal computation of an expanded classpath. It will eliminate
562          * duplicates, and produce copies of exported classpath entries to avoid
563          * possible side-effects ever after.
564          */
565         // private void computeExpandedClasspath(
566         // JavaProject initialProject,
567         // boolean ignoreUnresolvedVariable,
568         // boolean generateMarkerOnError,
569         // HashSet visitedProjects,
570         // ObjectVector accumulatedEntries) throws JavaModelException {
571         //              
572         // if (visitedProjects.contains(this)){
573         // return; // break cycles if any
574         // }
575         // visitedProjects.add(this);
576         //
577         // if (generateMarkerOnError && !this.equals(initialProject)){
578         // generateMarkerOnError = false;
579         // }
580         // IClasspathEntry[] immediateClasspath =
581         // getResolvedClasspath(ignoreUnresolvedVariable, generateMarkerOnError);
582         //                      
583         // IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
584         // for (int i = 0, length = immediateClasspath.length; i < length; i++){
585         // IClasspathEntry entry = immediateClasspath[i];
586         //
587         // boolean isInitialProject = this.equals(initialProject);
588         // if (isInitialProject || entry.isExported()){
589         //                              
590         // accumulatedEntries.add(entry);
591         //                              
592         // // recurse in project to get all its indirect exports (only consider
593         // exported entries from there on)
594         // if (entry.getEntryKind() == ClasspathEntry.CPE_PROJECT) {
595         // IResource member = workspaceRoot.findMember(entry.getPath());
596         // if (member != null && member.getType() == IResource.PROJECT){ // double
597         // check if bound to project (23977)
598         // IProject projRsc = (IProject) member;
599         // if (JavaProject.hasJavaNature(projRsc)) {
600         // JavaProject project = (JavaProject) JavaCore.create(projRsc);
601         // project.computeExpandedClasspath(
602         // initialProject,
603         // ignoreUnresolvedVariable,
604         // generateMarkerOnError,
605         // visitedProjects,
606         // accumulatedEntries);
607         // }
608         // }
609         // }
610         // }
611         // }
612         // }
613         /**
614          * Returns (local/all) the package fragment roots identified by the given
615          * project's classpath. Note: this follows project classpath references to
616          * find required project contributions, eliminating duplicates silently.
617          * Only works with resolved entries
618          */
619         public IPackageFragmentRoot[] computePackageFragmentRoots(
620                         IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots)
621                         throws JavaModelException {
622
623                 ObjectVector accumulatedRoots = new ObjectVector();
624                 computePackageFragmentRoots(resolvedClasspath, accumulatedRoots,
625                                 new HashSet(5), // rootIDs
626                                 true, // inside original project
627                                 true, // check existency
628                                 retrieveExportedRoots);
629                 IPackageFragmentRoot[] rootArray = new IPackageFragmentRoot[accumulatedRoots
630                                 .size()];
631                 accumulatedRoots.copyInto(rootArray);
632                 return rootArray;
633         }
634
635         /**
636          * Computes the package fragment roots identified by the given entry. Only
637          * works with resolved entry
638          */
639         public IPackageFragmentRoot[] computePackageFragmentRoots(
640                         IClasspathEntry resolvedEntry) {
641                 try {
642                         return computePackageFragmentRoots(
643                                         new IClasspathEntry[] { resolvedEntry }, false // don't
644                                                                                                                                         // retrieve
645                                                                                                                                         // exported
646                                                                                                                                         // roots
647                         );
648                 } catch (JavaModelException e) {
649                         return new IPackageFragmentRoot[] {};
650                 }
651         }
652
653         /**
654          * Returns the package fragment roots identified by the given entry. In case
655          * it refers to a project, it will follow its classpath so as to find
656          * exported roots as well. Only works with resolved entry
657          */
658         public void computePackageFragmentRoots(IClasspathEntry resolvedEntry,
659                         ObjectVector accumulatedRoots, HashSet rootIDs,
660                         boolean insideOriginalProject, boolean checkExistency,
661                         boolean retrieveExportedRoots) throws JavaModelException {
662
663                 String rootID = ((ClasspathEntry) resolvedEntry).rootID();
664                 if (rootIDs.contains(rootID))
665                         return;
666
667                 IPath projectPath = getProject().getFullPath();
668                 IPath entryPath = resolvedEntry.getPath();
669                 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
670
671                 switch (resolvedEntry.getEntryKind()) {
672
673                 // source folder
674                 case IClasspathEntry.CPE_SOURCE:
675
676                         if (projectPath.isPrefixOf(entryPath)) {
677                                 if (checkExistency) {
678                                         Object target = JavaModel.getTarget(workspaceRoot,
679                                                         entryPath, checkExistency);
680                                         if (target == null)
681                                                 return;
682
683                                         if (target instanceof IFolder || target instanceof IProject) {
684                                                 accumulatedRoots
685                                                                 .add(getPackageFragmentRoot((IResource) target));
686                                                 rootIDs.add(rootID);
687                                         }
688                                 } else {
689                                         IPackageFragmentRoot root = getFolderPackageFragmentRoot(entryPath);
690                                         if (root != null) {
691                                                 accumulatedRoots.add(root);
692                                                 rootIDs.add(rootID);
693                                         }
694                                 }
695                         }
696                         break;
697
698                 // internal/external JAR or folder
699                 case IClasspathEntry.CPE_LIBRARY:
700
701                         if (!insideOriginalProject && !resolvedEntry.isExported())
702                                 return;
703
704                         if (checkExistency) {
705                                 Object target = JavaModel.getTarget(workspaceRoot, entryPath,
706                                                 checkExistency);
707                                 if (target == null)
708                                         return;
709
710                                 if (target instanceof IResource) {
711                                         // internal target
712                                         IResource resource = (IResource) target;
713                                         IPackageFragmentRoot root = getPackageFragmentRoot(resource);
714                                         if (root != null) {
715                                                 accumulatedRoots.add(root);
716                                                 rootIDs.add(rootID);
717                                         }
718                                 } else {
719                                         // external target - only JARs allowed
720                                         // if (((java.io.File)target).isFile() &&
721                                         // (ProjectPrefUtil.isArchiveFileName(entryPath.lastSegment())))
722                                         // {
723                                         // accumulatedRoots.add(
724                                         // new JarPackageFragmentRoot(entryPath, this));
725                                         // rootIDs.add(rootID);
726                                         // }
727                                 }
728                         } else {
729                                 IPackageFragmentRoot root = getPackageFragmentRoot(entryPath);
730                                 if (root != null) {
731                                         accumulatedRoots.add(root);
732                                         rootIDs.add(rootID);
733                                 }
734                         }
735                         break;
736
737                 // recurse into required project
738                 case IClasspathEntry.CPE_PROJECT:
739
740                         if (!retrieveExportedRoots)
741                                 return;
742                         if (!insideOriginalProject && !resolvedEntry.isExported())
743                                 return;
744
745                         IResource member = workspaceRoot.findMember(entryPath);
746                         if (member != null && member.getType() == IResource.PROJECT) {// double
747                                                                                                                                                         // check
748                                                                                                                                                         // if
749                                                                                                                                                         // bound
750                                                                                                                                                         // to
751                                                                                                                                                         // project
752                                                                                                                                                         // (23977)
753                                 IProject requiredProjectRsc = (IProject) member;
754                                 if (JavaProject.hasJavaNature(requiredProjectRsc)) { // special
755                                                                                                                                                 // builder
756                                                                                                                                                 // binary
757                                                                                                                                                 // output
758                                         rootIDs.add(rootID);
759                                         JavaProject requiredProject = (JavaProject) JavaCore
760                                                         .create(requiredProjectRsc);
761                                         requiredProject.computePackageFragmentRoots(requiredProject
762                                                         .getResolvedClasspath(true), accumulatedRoots,
763                                                         rootIDs, false, checkExistency,
764                                                         retrieveExportedRoots);
765                                 }
766                                 break;
767                         }
768                 }
769         }
770
771         /**
772          * Returns (local/all) the package fragment roots identified by the given
773          * project's classpath. Note: this follows project classpath references to
774          * find required project contributions, eliminating duplicates silently.
775          * Only works with resolved entries
776          */
777         public void computePackageFragmentRoots(
778                         IClasspathEntry[] resolvedClasspath, ObjectVector accumulatedRoots,
779                         HashSet rootIDs, boolean insideOriginalProject,
780                         boolean checkExistency, boolean retrieveExportedRoots)
781                         throws JavaModelException {
782
783                 if (insideOriginalProject) {
784                         rootIDs.add(rootID());
785                 }
786                 for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
787                         computePackageFragmentRoots(resolvedClasspath[i], accumulatedRoots,
788                                         rootIDs, insideOriginalProject, checkExistency,
789                                         retrieveExportedRoots);
790                 }
791         }
792
793         /**
794          * Compute the file name to use for a given shared property
795          */
796         public String computeSharedPropertyFileName(QualifiedName qName) {
797
798                 return '.' + qName.getLocalName();
799         }
800
801         /*
802          * Returns whether the given resource is accessible through the children or
803          * the non-Java resources of this project. Returns true if the resource is
804          * not in the project. Assumes that the resource is a folder or a file.
805          */
806         public boolean contains(IResource resource) {
807
808                 IClasspathEntry[] classpath;
809                 IPath output;
810                 try {
811                         classpath = getResolvedClasspath(true);
812                         output = getOutputLocation();
813                 } catch (JavaModelException e) {
814                         return false;
815                 }
816
817                 IPath fullPath = resource.getFullPath();
818                 IPath innerMostOutput = output.isPrefixOf(fullPath) ? output : null;
819                 IClasspathEntry innerMostEntry = null;
820                 for (int j = 0, cpLength = classpath.length; j < cpLength; j++) {
821                         IClasspathEntry entry = classpath[j];
822
823                         IPath entryPath = entry.getPath();
824                         if ((innerMostEntry == null || innerMostEntry.getPath().isPrefixOf(
825                                         entryPath))
826                                         && entryPath.isPrefixOf(fullPath)) {
827                                 innerMostEntry = entry;
828                         }
829                         IPath entryOutput = classpath[j].getOutputLocation();
830                         if (entryOutput != null && entryOutput.isPrefixOf(fullPath)) {
831                                 innerMostOutput = entryOutput;
832                         }
833                 }
834                 if (innerMostEntry != null) {
835                         // special case prj==src and nested output location
836                         if (innerMostOutput != null && innerMostOutput.segmentCount() > 1 // output
837                                                                                                                                                                 // isn't
838                                                                                                                                                                 // project
839                                         && innerMostEntry.getPath().segmentCount() == 1) { // 1
840                                                                                                                                                 // segment
841                                                                                                                                                 // must
842                                                                                                                                                 // be
843                                                                                                                                                 // project
844                                                                                                                                                 // name
845                                 return false;
846                         }
847                         if (resource instanceof IFolder) {
848                                 // folders are always included in src/lib entries
849                                 return true;
850                         }
851                         switch (innerMostEntry.getEntryKind()) {
852                         case IClasspathEntry.CPE_SOURCE:
853                                 // .class files are not visible in source folders
854                                 return true; // !net.sourceforge.phpdt.internal.compiler.util.ProjectPrefUtil.isClassFileName(fullPath.lastSegment());
855                         case IClasspathEntry.CPE_LIBRARY:
856                                 // .java files are not visible in library folders
857                                 return !net.sourceforge.phpdt.internal.compiler.util.Util
858                                                 .isJavaFileName(fullPath.lastSegment());
859                         }
860                 }
861                 if (innerMostOutput != null) {
862                         return false;
863                 }
864                 return true;
865         }
866
867         /**
868          * Record a new marker denoting a classpath problem
869          */
870         IMarker createClasspathProblemMarker(IJavaModelStatus status) {
871
872                 IMarker marker = null;
873                 int severity;
874                 String[] arguments = new String[0];
875                 boolean isCycleProblem = false, isClasspathFileFormatProblem = false;
876                 switch (status.getCode()) {
877
878                 case IJavaModelStatusConstants.CLASSPATH_CYCLE:
879                         isCycleProblem = true;
880                         if (JavaCore.ERROR.equals(getOption(
881                                         JavaCore.CORE_CIRCULAR_CLASSPATH, true))) {
882                                 severity = IMarker.SEVERITY_ERROR;
883                         } else {
884                                 severity = IMarker.SEVERITY_WARNING;
885                         }
886                         break;
887
888                 case IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT:
889                         isClasspathFileFormatProblem = true;
890                         severity = IMarker.SEVERITY_ERROR;
891                         break;
892
893                 default:
894                         IPath path = status.getPath();
895                         if (path != null)
896                                 arguments = new String[] { path.toString() };
897                         if (JavaCore.ERROR.equals(getOption(
898                                         JavaCore.CORE_INCOMPLETE_CLASSPATH, true))) {
899                                 severity = IMarker.SEVERITY_ERROR;
900                         } else {
901                                 severity = IMarker.SEVERITY_WARNING;
902                         }
903                         break;
904                 }
905
906                 try {
907                         marker = getProject().createMarker(
908                                         IJavaModelMarker.BUILDPATH_PROBLEM_MARKER);
909                         marker.setAttributes(new String[] { IMarker.MESSAGE,
910                                         IMarker.SEVERITY, IMarker.LOCATION,
911                                         IJavaModelMarker.CYCLE_DETECTED,
912                                         IJavaModelMarker.CLASSPATH_FILE_FORMAT,
913                                         IJavaModelMarker.ID, IJavaModelMarker.ARGUMENTS, },
914                                         new Object[] { status.getMessage(),
915                                                         new Integer(severity),
916                                                         Util.bind("classpath.buildPath"),//$NON-NLS-1$
917                                                         isCycleProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
918                                                         isClasspathFileFormatProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
919                                                         new Integer(status.getCode()),
920                                                         Util.getProblemArgumentsForMarker(arguments), });
921                 } catch (CoreException e) {
922                 }
923                 return marker;
924         }
925
926         /**
927          * Returns a new element info for this element.
928          */
929         protected Object createElementInfo() {
930                 return new JavaProjectElementInfo();
931         }
932
933         /*
934          * Returns a new search name environment for this project. This name
935          * environment first looks in the given working copies.
936          */
937         // public ISearchableNameEnvironment
938         // newSearchableNameEnvironment(ICompilationUnit[] workingCopies) throws
939         // JavaModelException {
940         // return new SearchableEnvironment(this, workingCopies);
941         // }
942         /*
943          * Returns a new search name environment for this project. This name
944          * environment first looks in the working copies of the given owner.
945          */
946         public ISearchableNameEnvironment newSearchableNameEnvironment(
947                         WorkingCopyOwner owner) throws JavaModelException {
948                 return new SearchableEnvironment(this, owner);
949         }
950
951         /**
952          * Reads and decode an XML classpath string
953          */
954         protected IClasspathEntry[] decodeClasspath(String xmlClasspath,
955                         boolean createMarker, boolean logProblems) {
956
957                 ArrayList paths = new ArrayList();
958                 IClasspathEntry defaultOutput = null;
959                 try {
960                         if (xmlClasspath == null)
961                                 return null;
962                         StringReader reader = new StringReader(xmlClasspath);
963                         Element cpElement;
964
965                         try {
966                                 DocumentBuilder parser = DocumentBuilderFactory.newInstance()
967                                                 .newDocumentBuilder();
968                                 cpElement = parser.parse(new InputSource(reader))
969                                                 .getDocumentElement();
970                         } catch (SAXException e) {
971                                 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
972                         } catch (ParserConfigurationException e) {
973                                 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
974                         } finally {
975                                 reader.close();
976                         }
977
978                         if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$
979                                 throw new IOException(Util.bind("file.badFormat")); //$NON-NLS-1$
980                         }
981                         NodeList list = cpElement.getElementsByTagName("classpathentry"); //$NON-NLS-1$
982                         int length = list.getLength();
983
984                         for (int i = 0; i < length; ++i) {
985                                 Node node = list.item(i);
986                                 if (node.getNodeType() == Node.ELEMENT_NODE) {
987                                         IClasspathEntry entry = ClasspathEntry.elementDecode(
988                                                         (Element) node, this);
989                                         if (entry != null) {
990                                                 if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
991                                                         defaultOutput = entry; // separate output
992                                                 } else {
993                                                         paths.add(entry);
994                                                 }
995                                         }
996                                 }
997                         }
998                 } catch (IOException e) {
999                         // bad format
1000                         if (createMarker && this.getProject().isAccessible()) {
1001                                 this
1002                                                 .createClasspathProblemMarker(new JavaModelStatus(
1003                                                                 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1004                                                                 Util
1005                                                                                 .bind(
1006                                                                                                 "classpath.xmlFormatError", this.getElementName(), e.getMessage()))); //$NON-NLS-1$
1007                         }
1008                         if (logProblems) {
1009                                 Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$
1010                                                 + "/.classpath, will mark classpath as invalid"); //$NON-NLS-1$
1011                         }
1012                         return INVALID_CLASSPATH;
1013                 } catch (/*Assert.*/AssertionFailedException e) {
1014                         // failed creating CP entries from file
1015                         if (createMarker && this.getProject().isAccessible()) {
1016                                 this
1017                                                 .createClasspathProblemMarker(new JavaModelStatus(
1018                                                                 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
1019                                                                 Util
1020                                                                                 .bind(
1021                                                                                                 "classpath.illegalEntryInClasspathFile", this.getElementName(), e.getMessage()))); //$NON-NLS-1$
1022                         }
1023                         if (logProblems) {
1024                                 Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$
1025                                                 + "/.classpath, will mark classpath as invalid"); //$NON-NLS-1$
1026                         }
1027                         return INVALID_CLASSPATH;
1028                 }
1029                 int pathSize = paths.size();
1030                 if (pathSize > 0 || defaultOutput != null) {
1031                         IClasspathEntry[] entries = new IClasspathEntry[pathSize
1032                                         + (defaultOutput == null ? 0 : 1)];
1033                         paths.toArray(entries);
1034                         if (defaultOutput != null)
1035                                 entries[pathSize] = defaultOutput; // ensure output is last
1036                                                                                                         // item
1037                         return entries;
1038                 } else {
1039                         return null;
1040                 }
1041         }
1042
1043         /**
1044          * /** Removes the Java nature from the project.
1045          */
1046         public void deconfigure() throws CoreException {
1047
1048                 // deregister Java builder
1049                 removeFromBuildSpec(PHPeclipsePlugin.BUILDER_PARSER_ID);
1050         }
1051
1052         /**
1053          * Returns a default class path. This is the root of the project
1054          */
1055         protected IClasspathEntry[] defaultClasspath() throws JavaModelException {
1056
1057                 return new IClasspathEntry[] { JavaCore.newSourceEntry(getProject()
1058                                 .getFullPath()) };
1059         }
1060
1061         /**
1062          * Returns a default output location. This is the project bin folder
1063          */
1064         protected IPath defaultOutputLocation() throws JavaModelException {
1065                 return null; // getProject().getFullPath().append("bin");
1066                                                 // //$NON-NLS-1$
1067         }
1068
1069         /**
1070          * Returns the XML String encoding of the class path.
1071          */
1072         protected String encodeClasspath(IClasspathEntry[] classpath,
1073                         IPath outputLocation, boolean indent) throws JavaModelException {
1074                 try {
1075                         ByteArrayOutputStream s = new ByteArrayOutputStream();
1076                         OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
1077                         XMLWriter xmlWriter = new XMLWriter(writer);
1078
1079                         xmlWriter.startTag("classpath", indent); //$NON-NLS-1$
1080                         for (int i = 0; i < classpath.length; ++i) {
1081                                 ((ClasspathEntry) classpath[i]).elementEncode(xmlWriter,
1082                                                 this.project.getFullPath(), indent, true);
1083                         }
1084
1085                         if (outputLocation != null) {
1086                                 outputLocation = outputLocation.removeFirstSegments(1);
1087                                 outputLocation = outputLocation.makeRelative();
1088                                 HashMap parameters = new HashMap();
1089                                 parameters
1090                                                 .put(
1091                                                                 "kind", ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT));//$NON-NLS-1$
1092                                 parameters.put("path", String.valueOf(outputLocation));//$NON-NLS-1$
1093                                 xmlWriter.printTag(
1094                                                 "classpathentry", parameters, indent, true, true);//$NON-NLS-1$
1095                         }
1096
1097                         xmlWriter.endTag("classpath", indent);//$NON-NLS-1$
1098                         writer.flush();
1099                         writer.close();
1100                         return s.toString("UTF8");//$NON-NLS-1$
1101                 } catch (IOException e) {
1102                         throw new JavaModelException(e,
1103                                         IJavaModelStatusConstants.IO_EXCEPTION);
1104                 }
1105         }
1106
1107         /**
1108          * Returns the XML String encoding of the class path.
1109          */
1110         // protected String encodeClasspath(IClasspathEntry[] classpath, IPath
1111         // outputLocation, boolean useLineSeparator) throws JavaModelException {
1112         //
1113         // Document document = new DocumentImpl();
1114         // Element cpElement = document.createElement("classpath"); //$NON-NLS-1$
1115         // document.appendChild(cpElement);
1116         //
1117         // for (int i = 0; i < classpath.length; ++i) {
1118         // cpElement.appendChild(((ClasspathEntry)classpath[i]).elementEncode(document,
1119         // getProject().getFullPath()));
1120         // }
1121         //
1122         // if (outputLocation != null) {
1123         // outputLocation = outputLocation.removeFirstSegments(1);
1124         // outputLocation = outputLocation.makeRelative();
1125         // Element oElement = document.createElement("classpathentry");
1126         // //$NON-NLS-1$
1127         // oElement.setAttribute("kind",
1128         // ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT)); //$NON-NLS-1$
1129         // oElement.setAttribute("path", outputLocation.toString()); //$NON-NLS-1$
1130         // cpElement.appendChild(oElement);
1131         // }
1132         //
1133         // // produce a String output
1134         // try {
1135         // ByteArrayOutputStream s = new ByteArrayOutputStream();
1136         // OutputFormat format = new OutputFormat();
1137         // if (useLineSeparator) {
1138         // format.setIndenting(true);
1139         // format.setLineSeparator(System.getProperty("line.separator"));
1140         // //$NON-NLS-1$
1141         // } else {
1142         // format.setPreserveSpace(true);
1143         // }
1144         // Serializer serializer =
1145         // SerializerFactory.getSerializerFactory(Method.XML).makeSerializer(
1146         // new OutputStreamWriter(s, "UTF8"), //$NON-NLS-1$
1147         // format);
1148         // serializer.asDOMSerializer().serialize(document);
1149         // return s.toString("UTF8"); //$NON-NLS-1$
1150         // } catch (IOException e) {
1151         // throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
1152         // }
1153         // }
1154         /**
1155          * Returns true if this handle represents the same Java project as the given
1156          * handle. Two handles represent the same project if they are identical or
1157          * if they represent a project with the same underlying resource and
1158          * occurrence counts.
1159          * 
1160          * @see JavaElement#equals
1161          */
1162         public boolean equals(Object o) {
1163
1164                 if (this == o)
1165                         return true;
1166
1167                 if (!(o instanceof JavaProject))
1168                         return false;
1169
1170                 JavaProject other = (JavaProject) o;
1171                 return getProject().equals(other.getProject())
1172                                 && occurrenceCount == other.occurrenceCount;
1173         }
1174
1175         public boolean exists() {
1176                 if (!hasJavaNature(project))
1177                         return false;
1178                 return super.exists();
1179         }
1180
1181         /**
1182          * @see IJavaProject
1183          */
1184         public IJavaElement findElement(IPath path) throws JavaModelException {
1185
1186                 if (path == null || path.isAbsolute()) {
1187                         throw new JavaModelException(new JavaModelStatus(
1188                                         IJavaModelStatusConstants.INVALID_PATH, path));
1189                 }
1190                 // try {
1191
1192                 String extension = path.getFileExtension();
1193                 if (extension == null) {
1194                         //String packageName = path.toString().replace(IPath.SEPARATOR, '.');
1195
1196                         // IPackageFragment[] pkgFragments =
1197                         // getNameLookup().findPackageFragments(packageName, false);
1198                         // if (pkgFragments == null) {
1199                         return null;
1200
1201                         // } else {
1202                         // // try to return one that is a child of this project
1203                         // for (int i = 0, length = pkgFragments.length; i < length; i++) {
1204                         //
1205                         // IPackageFragment pkgFragment = pkgFragments[i];
1206                         // if (this.equals(pkgFragment.getParent().getParent())) {
1207                         // return pkgFragment;
1208                         // }
1209                         // }
1210                         // // default to the first one
1211                         // return pkgFragments[0];
1212                         // }
1213                 } else if (extension.equalsIgnoreCase("java") //$NON-NLS-1$
1214                                 || extension.equalsIgnoreCase("class")) { //$NON-NLS-1$
1215                         IPath packagePath = path.removeLastSegments(1);
1216                         String packageName = packagePath.toString().replace(
1217                                         IPath.SEPARATOR, '.');
1218                         String typeName = path.lastSegment();
1219                         typeName = typeName.substring(0, typeName.length()
1220                                         - extension.length() - 1);
1221                         String qualifiedName = null;
1222                         if (packageName.length() > 0) {
1223                                 qualifiedName = packageName + "." + typeName; //$NON-NLS-1$
1224                         } else {
1225                                 qualifiedName = typeName;
1226                         }
1227                         // IType type =
1228                         // getNameLookup().findType(
1229                         // qualifiedName,
1230                         // false,
1231                         // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1232                         // if (type != null) {
1233                         // return type.getParent();
1234                         // } else {
1235                         return null;
1236                         // }
1237                 } else {
1238                         // unsupported extension
1239                         return null;
1240                 }
1241                 // } catch (JavaModelException e) {
1242                 // if (e.getStatus().getCode()
1243                 // == IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST) {
1244                 // return null;
1245                 // } else {
1246                 // throw e;
1247                 // }
1248                 // }
1249         }
1250
1251         /**
1252          * @see IJavaProject
1253          */
1254         // public IPackageFragment findPackageFragment(IPath path)
1255         // throws JavaModelException {
1256         //
1257         // return findPackageFragment0(JavaProject.canonicalizedPath(path));
1258         // }
1259         //
1260         // /**
1261         // * non path canonicalizing version
1262         // */
1263         // public IPackageFragment findPackageFragment0(IPath path)
1264         // throws JavaModelException {
1265         //
1266         // return getNameLookup().findPackageFragment(path);
1267         // }
1268         /**
1269          * @see IJavaProject
1270          */
1271         public IPackageFragmentRoot findPackageFragmentRoot(IPath path)
1272                         throws JavaModelException {
1273
1274                 return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path));
1275         }
1276
1277         /**
1278          * no path canonicalization
1279          */
1280         public IPackageFragmentRoot findPackageFragmentRoot0(IPath path)
1281                         throws JavaModelException {
1282
1283                 IPackageFragmentRoot[] allRoots = this.getAllPackageFragmentRoots();
1284                 if (!path.isAbsolute()) {
1285                         throw new IllegalArgumentException(Util.bind("path.mustBeAbsolute")); //$NON-NLS-1$
1286                 }
1287                 for (int i = 0; i < allRoots.length; i++) {
1288                         IPackageFragmentRoot classpathRoot = allRoots[i];
1289                         if (classpathRoot.getPath().equals(path)) {
1290                                 return classpathRoot;
1291                         }
1292                 }
1293                 return null;
1294         }
1295
1296         /**
1297          * @see IJavaProject
1298          */
1299         public IPackageFragmentRoot[] findPackageFragmentRoots(IClasspathEntry entry) {
1300                 try {
1301                         IClasspathEntry[] classpath = this.getRawClasspath();
1302                         for (int i = 0, length = classpath.length; i < length; i++) {
1303                                 if (classpath[i].equals(entry)) { // entry may need to be
1304                                                                                                         // resolved
1305                                         return computePackageFragmentRoots(getResolvedClasspath(
1306                                                         new IClasspathEntry[] { entry }, null, true, false,
1307                                                         null/* no reverse map */), false); // don't
1308                                                                                                                                 // retrieve
1309                                                                                                                                 // exported
1310                                                                                                                                 // roots
1311                                 }
1312                         }
1313                 } catch (JavaModelException e) {
1314                 }
1315                 return new IPackageFragmentRoot[] {};
1316         }
1317
1318         /**
1319          * @see IJavaProject#findType(String)
1320          */
1321         // public IType findType(String fullyQualifiedName) throws
1322         // JavaModelException {
1323         // IType type =
1324         // this.getNameLookup().findType(
1325         // fullyQualifiedName,
1326         // false,
1327         // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1328         // if (type == null) {
1329         // // try to find enclosing type
1330         // int lastDot = fullyQualifiedName.lastIndexOf('.');
1331         // if (lastDot == -1) return null;
1332         // type = this.findType(fullyQualifiedName.substring(0, lastDot));
1333         // if (type != null) {
1334         // type = type.getType(fullyQualifiedName.substring(lastDot+1));
1335         // if (!type.exists()) {
1336         // return null;
1337         // }
1338         // }
1339         // }
1340         // return type;
1341         // }
1342         /**
1343          * @see IJavaProject#findType(String, String)
1344          */
1345         // public IType findType(String packageName, String typeQualifiedName)
1346         // throws JavaModelException {
1347         // return
1348         // this.getNameLookup().findType(
1349         // typeQualifiedName,
1350         // packageName,
1351         // false,
1352         // NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
1353         // }
1354         //      
1355         /**
1356          * Remove all markers denoting classpath problems
1357          */
1358         protected void flushClasspathProblemMarkers(boolean flushCycleMarkers,
1359                         boolean flushClasspathFormatMarkers) {
1360                 try {
1361                         IProject project = getProject();
1362                         if (project.exists()) {
1363                                 IMarker[] markers = project.findMarkers(
1364                                                 IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false,
1365                                                 IResource.DEPTH_ZERO);
1366                                 for (int i = 0, length = markers.length; i < length; i++) {
1367                                         IMarker marker = markers[i];
1368                                         if (flushCycleMarkers && flushClasspathFormatMarkers) {
1369                                                 marker.delete();
1370                                         } else {
1371                                                 String cycleAttr = (String) marker
1372                                                                 .getAttribute(IJavaModelMarker.CYCLE_DETECTED);
1373                                                 String classpathFileFormatAttr = (String) marker
1374                                                                 .getAttribute(IJavaModelMarker.CLASSPATH_FILE_FORMAT);
1375                                                 if ((flushCycleMarkers == (cycleAttr != null && cycleAttr
1376                                                                 .equals("true"))) //$NON-NLS-1$
1377                                                                 && (flushClasspathFormatMarkers == (classpathFileFormatAttr != null && classpathFileFormatAttr
1378                                                                                 .equals("true")))) { //$NON-NLS-1$
1379                                                         marker.delete();
1380                                                 }
1381                                         }
1382                                 }
1383                         }
1384                 } catch (CoreException e) {
1385                 }
1386         }
1387
1388         // /**
1389         // * @see Openable
1390         // */
1391         // protected boolean generateInfos(
1392         // OpenableElementInfo info,
1393         // IProgressMonitor pm,
1394         // Map newElements,
1395         // IResource underlyingResource) throws JavaModelException {
1396         //
1397         // boolean validInfo = false;
1398         // try {
1399         // if (getProject().isOpen()) {
1400         // // put the info now, because computing the roots requires it
1401         // JavaModelManager.getJavaModelManager().putInfo(this, info);
1402         //
1403         // // compute the pkg fragment roots
1404         // updatePackageFragmentRoots();
1405         //      
1406         // // remember the timestamps of external libraries the first time they are
1407         // looked up
1408         // IClasspathEntry[] resolvedClasspath = getResolvedClasspath(true/*ignore
1409         // unresolved variable*/);
1410         // for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
1411         // IClasspathEntry entry = resolvedClasspath[i];
1412         // if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
1413         // IPath path = entry.getPath();
1414         // Object target =
1415         // JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path,
1416         // true);
1417         // if (target instanceof java.io.File) {
1418         // Map externalTimeStamps =
1419         // JavaModelManager.getJavaModelManager().deltaProcessor.externalTimeStamps;
1420         // if (externalTimeStamps.get(path) == null) {
1421         // long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
1422         // externalTimeStamps.put(path, new Long(timestamp));
1423         // }
1424         // }
1425         // }
1426         // }
1427         //
1428         // // only valid if reaches here
1429         // validInfo = true;
1430         // }
1431         // } finally {
1432         // if (!validInfo)
1433         // JavaModelManager.getJavaModelManager().removeInfo(this);
1434         // }
1435         // return validInfo;
1436         // }
1437
1438         /**
1439          * @see IJavaProject
1440          */
1441         public IPackageFragmentRoot[] getAllPackageFragmentRoots()
1442                         throws JavaModelException {
1443
1444                 return computePackageFragmentRoots(getResolvedClasspath(true), true);
1445         }
1446
1447         /**
1448          * Returns the classpath entry that refers to the given path or
1449          * <code>null</code> if there is no reference to the path.
1450          */
1451         public IClasspathEntry getClasspathEntryFor(IPath path)
1452                         throws JavaModelException {
1453
1454                 IClasspathEntry[] entries = getExpandedClasspath(true);
1455                 for (int i = 0; i < entries.length; i++) {
1456                         if (entries[i].getPath().equals(path)) {
1457                                 return entries[i];
1458                         }
1459                 }
1460                 return null;
1461         }
1462
1463         /*
1464          * Returns the cycle marker associated with this project or null if none.
1465          */
1466         public IMarker getCycleMarker() {
1467                 try {
1468                         IProject project = getProject();
1469                         if (project.exists()) {
1470                                 IMarker[] markers = project.findMarkers(
1471                                                 IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false,
1472                                                 IResource.DEPTH_ZERO);
1473                                 for (int i = 0, length = markers.length; i < length; i++) {
1474                                         IMarker marker = markers[i];
1475                                         String cycleAttr = (String) marker
1476                                                         .getAttribute(IJavaModelMarker.CYCLE_DETECTED);
1477                                         if (cycleAttr != null && cycleAttr.equals("true")) { //$NON-NLS-1$
1478                                                 return marker;
1479                                         }
1480                                 }
1481                         }
1482                 } catch (CoreException e) {
1483                 }
1484                 return null;
1485         }
1486
1487         /**
1488          * @see IJavaElement
1489          */
1490         public int getElementType() {
1491                 return JAVA_PROJECT;
1492         }
1493
1494         /**
1495          * This is a helper method returning the expanded classpath for the project,
1496          * as a list of classpath entries, where all classpath variable entries have
1497          * been resolved and substituted with their final target entries. All
1498          * project exports have been appended to project entries.
1499          * 
1500          * @param ignoreUnresolvedVariable
1501          *            boolean
1502          * @return IClasspathEntry[]
1503          * @throws JavaModelException
1504          */
1505         public IClasspathEntry[] getExpandedClasspath(
1506                         boolean ignoreUnresolvedVariable) throws JavaModelException {
1507
1508                 return getExpandedClasspath(ignoreUnresolvedVariable,
1509                                 false/* don't create markers */, null, null);
1510         }
1511
1512         /*
1513          * @see JavaElement
1514          */
1515         public IJavaElement getHandleFromMemento(String token,
1516                         MementoTokenizer memento, WorkingCopyOwner owner) {
1517                 switch (token.charAt(0)) {
1518                 case JEM_COUNT:
1519                         return getHandleUpdatingCountFromMemento(memento, owner);
1520                 case JEM_PACKAGEFRAGMENTROOT:
1521                         String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
1522                         token = null;
1523                         while (memento.hasMoreTokens()) {
1524                                 token = memento.nextToken();
1525                                 char firstChar = token.charAt(0);
1526                                 if (firstChar != JEM_PACKAGEFRAGMENT && firstChar != JEM_COUNT) {
1527                                         rootPath += token;
1528                                 } else {
1529                                         break;
1530                                 }
1531                         }
1532                         JavaElement root = (JavaElement) getPackageFragmentRoot(new Path(
1533                                         rootPath));
1534                         if (token != null && token.charAt(0) == JEM_PACKAGEFRAGMENT) {
1535                                 return root.getHandleFromMemento(token, memento, owner);
1536                         } else {
1537                                 return root.getHandleFromMemento(memento, owner);
1538                         }
1539                 }
1540                 return null;
1541         }
1542
1543         /**
1544          * Returns the <code>char</code> that marks the start of this handles
1545          * contribution to a memento.
1546          */
1547         protected char getHandleMementoDelimiter() {
1548
1549                 return JEM_JAVAPROJECT;
1550         }
1551
1552         /**
1553          * Internal variant which can create marker on project for invalid entries,
1554          * it will also perform classpath expansion in presence of project
1555          * prerequisites exporting their entries.
1556          * 
1557          * @param ignoreUnresolvedVariable
1558          *            boolean
1559          * @param generateMarkerOnError
1560          *            boolean
1561          * @param preferredClasspaths
1562          *            Map
1563          * @param preferredOutputs
1564          *            Map
1565          * @return IClasspathEntry[]
1566          * @throws JavaModelException
1567          */
1568         public IClasspathEntry[] getExpandedClasspath(
1569                         boolean ignoreUnresolvedVariable, boolean generateMarkerOnError,
1570                         Map preferredClasspaths, Map preferredOutputs)
1571                         throws JavaModelException {
1572
1573                 ObjectVector accumulatedEntries = new ObjectVector();
1574                 computeExpandedClasspath(this, ignoreUnresolvedVariable,
1575                                 generateMarkerOnError, new HashSet(5), accumulatedEntries,
1576                                 preferredClasspaths, preferredOutputs);
1577
1578                 IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries
1579                                 .size()];
1580                 accumulatedEntries.copyInto(expandedPath);
1581
1582                 return expandedPath;
1583         }
1584
1585         // /**
1586         // * Internal variant which can create marker on project for invalid
1587         // entries,
1588         // * it will also perform classpath expansion in presence of project
1589         // prerequisites
1590         // * exporting their entries.
1591         // */
1592         // public IClasspathEntry[] getExpandedClasspath(
1593         // boolean ignoreUnresolvedVariable,
1594         // boolean generateMarkerOnError) throws JavaModelException {
1595         //      
1596         // ObjectVector accumulatedEntries = new ObjectVector();
1597         // computeExpandedClasspath(this, ignoreUnresolvedVariable,
1598         // generateMarkerOnError, new HashSet(5), accumulatedEntries);
1599         //              
1600         // IClasspathEntry[] expandedPath = new
1601         // IClasspathEntry[accumulatedEntries.size()];
1602         // accumulatedEntries.copyInto(expandedPath);
1603         //
1604         // return expandedPath;
1605         // }
1606
1607         /**
1608          * Find the specific Java command amongst the build spec of a given
1609          * description
1610          */
1611         private ICommand getJavaCommand(IProjectDescription description)
1612                         throws CoreException {
1613
1614                 ICommand[] commands = description.getBuildSpec();
1615                 for (int i = 0; i < commands.length; ++i) {
1616                         if (commands[i].getBuilderName().equals(
1617                                         PHPeclipsePlugin.BUILDER_PARSER_ID)) {
1618                                 return commands[i];
1619                         }
1620                 }
1621                 return null;
1622         }
1623
1624         /**
1625          * Convenience method that returns the specific type of info for a Java
1626          * project.
1627          */
1628         protected JavaProjectElementInfo getJavaProjectElementInfo()
1629                         throws JavaModelException {
1630
1631                 return (JavaProjectElementInfo) getElementInfo();
1632         }
1633
1634         /**
1635          * @see IJavaProject
1636          */
1637         public NameLookup getNameLookup() throws JavaModelException {
1638
1639                 JavaProjectElementInfo info = getJavaProjectElementInfo();
1640                 // lock on the project info to avoid race condition
1641                 synchronized (info) {
1642                         NameLookup nameLookup;
1643                         if ((nameLookup = info.getNameLookup()) == null) {
1644                                 info.setNameLookup(nameLookup = new NameLookup(this));
1645                         }
1646                         return nameLookup;
1647                 }
1648         }
1649
1650         /*
1651          * Returns a new name lookup. This name lookup first looks in the given
1652          * working copies.
1653          */
1654         public NameLookup newNameLookup(ICompilationUnit[] workingCopies)
1655                         throws JavaModelException {
1656
1657                 //JavaProjectElementInfo info = getJavaProjectElementInfo();
1658                 // lock on the project info to avoid race condition while computing the
1659                 // pkg fragment roots and package fragment caches
1660                 // synchronized(info){
1661                 // return new NameLookup(info.getAllPackageFragmentRoots(this),
1662                 // info.getAllPackageFragments(this), workingCopies);
1663                 // }
1664                 return null;
1665         }
1666
1667         /*
1668          * Returns a new name lookup. This name lookup first looks in the working
1669          * copies of the given owner.
1670          */
1671         public NameLookup newNameLookup(WorkingCopyOwner owner)
1672                         throws JavaModelException {
1673
1674                 JavaModelManager manager = JavaModelManager.getJavaModelManager();
1675                 ICompilationUnit[] workingCopies = owner == null ? null : manager
1676                                 .getWorkingCopies(owner, true/* add primary WCs */);
1677                 return newNameLookup(workingCopies);
1678         }
1679
1680         //
1681         // /**
1682         // * Returns an array of non-java resources contained in the receiver.
1683         // */
1684         // public Object[] getNonJavaResources() throws JavaModelException {
1685         //
1686         // return ((JavaProjectElementInfo)
1687         // getElementInfo()).getNonJavaResources(this);
1688         // }
1689
1690         /**
1691          * @see net.sourceforge.phpdt.core.IJavaProject#getOption(String, boolean)
1692          */
1693         public String getOption(String optionName, boolean inheritJavaCoreOptions) {
1694
1695                 if (JavaModelManager.OptionNames.contains(optionName)) {
1696
1697                         Preferences preferences = getPreferences();
1698                         if (preferences == null || preferences.isDefault(optionName)) {
1699                                 return inheritJavaCoreOptions ? JavaCore.getOption(optionName)
1700                                                 : null;
1701                         }
1702                         return preferences.getString(optionName).trim();
1703                 }
1704                 return null;
1705         }
1706
1707         /**
1708          * @see net.sourceforge.phpdt.core.IJavaProject#getOptions(boolean)
1709          */
1710         public Map getOptions(boolean inheritJavaCoreOptions) {
1711
1712                 // initialize to the defaults from JavaCore options pool
1713                 Map options = inheritJavaCoreOptions ? JavaCore.getOptions()
1714                                 : new Hashtable(5);
1715
1716                 Preferences preferences = getPreferences();
1717                 if (preferences == null)
1718                         return options; // cannot do better (non-Java project)
1719                 HashSet optionNames = JavaModelManager.OptionNames;
1720
1721                 // get preferences set to their default
1722                 if (inheritJavaCoreOptions) {
1723                         String[] defaultPropertyNames = preferences.defaultPropertyNames();
1724                         for (int i = 0; i < defaultPropertyNames.length; i++) {
1725                                 String propertyName = defaultPropertyNames[i];
1726                                 if (optionNames.contains(propertyName)) {
1727                                         options.put(propertyName, preferences.getDefaultString(
1728                                                         propertyName).trim());
1729                                 }
1730                         }
1731                 }
1732                 // get custom preferences not set to their default
1733                 String[] propertyNames = preferences.propertyNames();
1734                 for (int i = 0; i < propertyNames.length; i++) {
1735                         String propertyName = propertyNames[i];
1736                         if (optionNames.contains(propertyName)) {
1737                                 options.put(propertyName, preferences.getString(propertyName)
1738                                                 .trim());
1739                         }
1740                 }
1741                 return options;
1742         }
1743
1744         /**
1745          * @see IJavaProject
1746          */
1747         // public IPath getOutputLocation() throws JavaModelException {
1748         //
1749         // JavaModelManager.PerProjectInfo perProjectInfo =
1750         // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
1751         // IPath outputLocation = perProjectInfo.outputLocation;
1752         // if (outputLocation != null) return outputLocation;
1753         //
1754         // // force to read classpath - will position output location as well
1755         // this.getRawClasspath();
1756         // outputLocation = perProjectInfo.outputLocation;
1757         // if (outputLocation == null) {
1758         // return defaultOutputLocation();
1759         // }
1760         // return outputLocation;
1761         // }
1762         /**
1763          * @see IJavaProject
1764          */
1765         public IPath getOutputLocation() throws JavaModelException {
1766                 // Do not create marker but log problems while getting output location
1767                 return this.getOutputLocation(false, true);
1768         }
1769
1770         /**
1771          * @param createMarkers
1772          *            boolean
1773          * @param logProblems
1774          *            boolean
1775          * @return IPath
1776          * @throws JavaModelException
1777          */
1778         public IPath getOutputLocation(boolean createMarkers, boolean logProblems)
1779                         throws JavaModelException {
1780
1781                 JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo();
1782                 IPath outputLocation = perProjectInfo.outputLocation;
1783                 if (outputLocation != null)
1784                         return outputLocation;
1785
1786                 // force to read classpath - will position output location as well
1787                 this.getRawClasspath(createMarkers, logProblems);
1788                 outputLocation = perProjectInfo.outputLocation;
1789                 if (outputLocation == null) {
1790                         return defaultOutputLocation();
1791                 }
1792                 return outputLocation;
1793         }
1794
1795         /**
1796          * @return A handle to the package fragment root identified by the given
1797          *         path. This method is handle-only and the element may or may not
1798          *         exist. Returns <code>null</code> if unable to generate a handle
1799          *         from the path (for example, an absolute path that has less than 1
1800          *         segment. The path may be relative or absolute.
1801          */
1802         public IPackageFragmentRoot getPackageFragmentRoot(IPath path) {
1803                 if (!path.isAbsolute()) {
1804                         path = getPath().append(path);
1805                 }
1806                 int segmentCount = path.segmentCount();
1807                 switch (segmentCount) {
1808                 case 0:
1809                         return null;
1810                 case 1:
1811                         // default root
1812                         return getPackageFragmentRoot(getProject());
1813                 default:
1814                         // a path ending with .jar/.zip is still ambiguous and could still
1815                         // resolve to a source/lib folder
1816                         // thus will try to guess based on existing resource
1817                         // if (ProjectPrefUtil.isArchiveFileName(path.lastSegment())) {
1818                         // IResource resource =
1819                         // getProject().getWorkspace().getRoot().findMember(path);
1820                         // if (resource != null && resource.getType() == IResource.FOLDER){
1821                         // return getPackageFragmentRoot(resource);
1822                         // }
1823                         // return getPackageFragmentRoot0(path);
1824                         // } else {
1825                         return getPackageFragmentRoot(getProject().getWorkspace().getRoot()
1826                                         .getFolder(path));
1827                         // }
1828                 }
1829         }
1830
1831         /**
1832          * The path is known to match a source/library folder entry.
1833          */
1834         public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) {
1835                 if (path.segmentCount() == 1) { // default project root
1836                         return getPackageFragmentRoot(getProject());
1837                 }
1838                 return getPackageFragmentRoot(getProject().getWorkspace().getRoot()
1839                                 .getFolder(path));
1840         }
1841
1842         /**
1843          * @see IJavaProject
1844          */
1845         public IPackageFragmentRoot getPackageFragmentRoot(IResource resource) {
1846
1847                 switch (resource.getType()) {
1848                 case IResource.FILE:
1849                         // if (ProjectPrefUtil.isArchiveFileName(resource.getName())) {
1850                         // return new JarPackageFragmentRoot(resource, this);
1851                         // } else {
1852                         return null;
1853                         // }
1854                 case IResource.FOLDER:
1855                         return new PackageFragmentRoot(resource, this, resource.getName());
1856                 case IResource.PROJECT:
1857                         return new PackageFragmentRoot(resource, this, ""); //$NON-NLS-1$
1858                 default:
1859                         return null;
1860                 }
1861         }
1862
1863         /**
1864          * @see IJavaProject
1865          */
1866         // public IPackageFragmentRoot getPackageFragmentRoot(String jarPath) {
1867         //
1868         // return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new
1869         // Path(jarPath)));
1870         // }
1871         //      
1872         // /**
1873         // * no path canonicalization
1874         // */
1875         // public IPackageFragmentRoot getPackageFragmentRoot0(IPath jarPath) {
1876         //
1877         // return new JarPackageFragmentRoot(jarPath, this);
1878         // }
1879         /**
1880          * @see IJavaProject
1881          */
1882         public IPackageFragmentRoot[] getPackageFragmentRoots()
1883                         throws JavaModelException {
1884
1885                 Object[] children;
1886                 int length;
1887                 IPackageFragmentRoot[] roots;
1888
1889                 System.arraycopy(children = getChildren(), 0,
1890                                 roots = new IPackageFragmentRoot[length = children.length], 0,
1891                                 length);
1892
1893                 return roots;
1894         }
1895
1896         /**
1897          * @see IJavaProject
1898          * @deprecated
1899          */
1900         public IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry) {
1901                 return findPackageFragmentRoots(entry);
1902         }
1903
1904         /**
1905          * Returns the package fragment root prefixed by the given path, or an empty
1906          * collection if there are no such elements in the model.
1907          */
1908         protected IPackageFragmentRoot[] getPackageFragmentRoots(IPath path)
1909
1910         throws JavaModelException {
1911                 IPackageFragmentRoot[] roots = getAllPackageFragmentRoots();
1912                 ArrayList matches = new ArrayList();
1913
1914                 for (int i = 0; i < roots.length; ++i) {
1915                         if (path.isPrefixOf(roots[i].getPath())) {
1916                                 matches.add(roots[i]);
1917                         }
1918                 }
1919                 IPackageFragmentRoot[] copy = new IPackageFragmentRoot[matches.size()];
1920                 matches.toArray(copy);
1921                 return copy;
1922         }
1923
1924         /**
1925          * @see IJavaProject
1926          */
1927         public IPackageFragment[] getPackageFragments() throws JavaModelException {
1928
1929                 IPackageFragmentRoot[] roots = getPackageFragmentRoots();
1930                 return getPackageFragmentsInRoots(roots);
1931         }
1932
1933         /**
1934          * Returns all the package fragments found in the specified package fragment
1935          * roots.
1936          */
1937         public IPackageFragment[] getPackageFragmentsInRoots(
1938                         IPackageFragmentRoot[] roots) {
1939
1940                 ArrayList frags = new ArrayList();
1941                 for (int i = 0; i < roots.length; i++) {
1942                         IPackageFragmentRoot root = roots[i];
1943                         try {
1944                                 IJavaElement[] rootFragments = root.getChildren();
1945                                 for (int j = 0; j < rootFragments.length; j++) {
1946                                         frags.add(rootFragments[j]);
1947                                 }
1948                         } catch (JavaModelException e) {
1949                                 // do nothing
1950                         }
1951                 }
1952                 IPackageFragment[] fragments = new IPackageFragment[frags.size()];
1953                 frags.toArray(fragments);
1954                 return fragments;
1955         }
1956
1957         /*
1958          * @see IJavaElement
1959          */
1960         public IPath getPath() {
1961                 return this.getProject().getFullPath();
1962         }
1963
1964         public JavaModelManager.PerProjectInfo getPerProjectInfo()
1965                         throws JavaModelException {
1966                 return JavaModelManager.getJavaModelManager()
1967                                 .getPerProjectInfoCheckExistence(this.project);
1968         }
1969
1970         /**
1971          * @see IJavaProject
1972          */
1973         public IProject getProject() {
1974
1975                 return project;
1976         }
1977
1978         /**
1979          * Sets the underlying kernel project of this Java project, and fills in its
1980          * parent and name. Called by IProject.getNature().
1981          * 
1982          * @see IProjectNature#setProject(IProject)
1983          */
1984         public void setProject(IProject project) {
1985
1986                 this.project = project;
1987                 this.parent = JavaModelManager.getJavaModelManager().getJavaModel();
1988                 this.name = project.getName();
1989         }
1990
1991         protected IProject getProject(String name) {
1992                 return PHPeclipsePlugin.getWorkspace().getRoot().getProject(name);
1993         }
1994
1995         public List getReferencedProjects() {
1996                 List referencedProjects = new ArrayList();
1997
1998                 Iterator iterator = getLoadPathEntries().iterator();
1999                 while (iterator.hasNext()) {
2000                         LoadPathEntry pathEntry = (LoadPathEntry) iterator.next();
2001                         if (pathEntry.getType() == LoadPathEntry.TYPE_PROJECT)
2002                                 referencedProjects.add(pathEntry.getProject());
2003                 }
2004
2005                 return referencedProjects;
2006         }
2007
2008         /**
2009          * Returns the project custom preference pool. Project preferences may
2010          * include custom encoding.
2011          */
2012         public Preferences getPreferences() {
2013                 IProject project = getProject();
2014                 if (!JavaProject.hasJavaNature(project))
2015                         return null;
2016                 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager
2017                                 .getJavaModelManager().getPerProjectInfo(project, true);
2018                 Preferences preferences = perProjectInfo.preferences;
2019                 if (preferences != null)
2020                         return preferences;
2021                 preferences = loadPreferences();
2022                 if (preferences == null)
2023                         preferences = new Preferences();
2024                 perProjectInfo.preferences = preferences;
2025                 return preferences;
2026         }
2027
2028         /**
2029          * @see IJavaProject
2030          */
2031         // public IClasspathEntry[] getRawClasspath() throws JavaModelException {
2032         //
2033         // JavaModelManager.PerProjectInfo perProjectInfo =
2034         // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
2035         // IClasspathEntry[] classpath = perProjectInfo.classpath;
2036         // if (classpath != null) return classpath;
2037         // classpath = this.readClasspathFile(false/*don't create markers*/,
2038         // true/*log problems*/);
2039         //              
2040         // // extract out the output location
2041         // IPath outputLocation = null;
2042         // if (classpath != null && classpath.length > 0) {
2043         // IClasspathEntry entry = classpath[classpath.length - 1];
2044         // if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
2045         // outputLocation = entry.getPath();
2046         // IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
2047         // System.arraycopy(classpath, 0, copy, 0, copy.length);
2048         // classpath = copy;
2049         // }
2050         // }
2051         // if (classpath == null) {
2052         // return defaultClasspath();
2053         // }
2054         // /* Disable validate: classpath can contain CP variables and container
2055         // that need to be resolved
2056         // if (classpath != INVALID_CLASSPATH
2057         // && !JavaConventions.validateClasspath(this, classpath,
2058         // outputLocation).isOK()) {
2059         // classpath = INVALID_CLASSPATH;
2060         // }
2061         // */
2062         // perProjectInfo.classpath = classpath;
2063         // perProjectInfo.outputLocation = outputLocation;
2064         // return classpath;
2065         // }
2066         /**
2067          * @see IJavaProject
2068          */
2069         public IClasspathEntry[] getRawClasspath() throws JavaModelException {
2070                 // Do not create marker but log problems while getting raw classpath
2071                 return getRawClasspath(false, true);
2072         }
2073
2074         /*
2075          * Internal variant allowing to parameterize problem creation/logging
2076          */
2077         public IClasspathEntry[] getRawClasspath(boolean createMarkers,
2078                         boolean logProblems) throws JavaModelException {
2079
2080                 JavaModelManager.PerProjectInfo perProjectInfo = null;
2081                 IClasspathEntry[] classpath;
2082                 if (createMarkers) {
2083                         this.flushClasspathProblemMarkers(false/* cycle */, true/* format */);
2084                         classpath = this.readClasspathFile(createMarkers, logProblems);
2085                 } else {
2086                         perProjectInfo = getPerProjectInfo();
2087                         classpath = perProjectInfo.rawClasspath;
2088                         if (classpath != null)
2089                                 return classpath;
2090                         classpath = this.readClasspathFile(createMarkers, logProblems);
2091                 }
2092                 // extract out the output location
2093                 IPath outputLocation = null;
2094                 if (classpath != null && classpath.length > 0) {
2095                         IClasspathEntry entry = classpath[classpath.length - 1];
2096                         if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
2097                                 outputLocation = entry.getPath();
2098                                 IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
2099                                 System.arraycopy(classpath, 0, copy, 0, copy.length);
2100                                 classpath = copy;
2101                         }
2102                 }
2103                 if (classpath == null) {
2104                         return defaultClasspath();
2105                 }
2106                 /*
2107                  * Disable validate: classpath can contain CP variables and container
2108                  * that need to be resolved if (classpath != INVALID_CLASSPATH &&
2109                  * !JavaConventions.validateClasspath(this, classpath,
2110                  * outputLocation).isOK()) { classpath = INVALID_CLASSPATH; }
2111                  */
2112                 if (!createMarkers) {
2113                         perProjectInfo.rawClasspath = classpath;
2114                         perProjectInfo.outputLocation = outputLocation;
2115                 }
2116                 return classpath;
2117         }
2118
2119         /**
2120          * @see IJavaProject#getRequiredProjectNames
2121          */
2122         public String[] getRequiredProjectNames() throws JavaModelException {
2123
2124                 return this.projectPrerequisites(getResolvedClasspath(true));
2125         }
2126
2127         /**
2128          * @see IJavaProject
2129          */
2130         public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry)
2131                         throws JavaModelException {
2132
2133                 return this.getResolvedClasspath(ignoreUnresolvedEntry, false); // generateMarkerOnError
2134         }
2135
2136         /**
2137          * Internal variant which can create marker on project for invalid entries
2138          * and caches the resolved classpath on perProjectInfo
2139          */
2140         public IClasspathEntry[] getResolvedClasspath(
2141                         boolean ignoreUnresolvedEntry, boolean generateMarkerOnError)
2142                         throws JavaModelException {
2143                 return getResolvedClasspath(ignoreUnresolvedEntry,
2144                                 generateMarkerOnError, true // returnResolutionInProgress
2145                 );
2146                 // JavaModelManager manager = JavaModelManager.getJavaModelManager();
2147                 // JavaModelManager.PerProjectInfo perProjectInfo =
2148                 // manager.getPerProjectInfoCheckExistence(project);
2149                 //              
2150                 // // reuse cache if not needing to refresh markers or checking bound
2151                 // variables
2152                 // if (ignoreUnresolvedEntry && !generateMarkerOnError && perProjectInfo
2153                 // != null){
2154                 // // resolved path is cached on its info
2155                 // IClasspathEntry[] infoPath = perProjectInfo.lastResolvedClasspath;
2156                 // if (infoPath != null) return infoPath;
2157                 // }
2158                 // Map reverseMap = perProjectInfo == null ? null : new HashMap(5);
2159                 // IClasspathEntry[] resolvedPath = getResolvedClasspath(
2160                 // getRawClasspath(),
2161                 // generateMarkerOnError ? getOutputLocation() : null,
2162                 // ignoreUnresolvedEntry,
2163                 // generateMarkerOnError,
2164                 // reverseMap);
2165                 //
2166                 // if (perProjectInfo != null){
2167                 // if (perProjectInfo.classpath == null // .classpath file could not be
2168                 // read
2169                 // && generateMarkerOnError
2170                 // && JavaProject.hasJavaNature(project)) {
2171                 // this.createClasspathProblemMarker(new JavaModelStatus(
2172                 // IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
2173                 // Util.bind("classpath.cannotReadClasspathFile",
2174                 // this.getElementName()))); //$NON-NLS-1$
2175                 // }
2176                 //
2177                 // perProjectInfo.lastResolvedClasspath = resolvedPath;
2178                 // perProjectInfo.resolvedPathToRawEntries = reverseMap;
2179                 // }
2180                 // return resolvedPath;
2181         }
2182
2183         /*
2184          * Internal variant which can create marker on project for invalid entries
2185          * and caches the resolved classpath on perProjectInfo. If requested, return
2186          * a special classpath (RESOLUTION_IN_PROGRESS) if the classpath is being
2187          * resolved.
2188          */
2189         public IClasspathEntry[] getResolvedClasspath(
2190                         boolean ignoreUnresolvedEntry, boolean generateMarkerOnError,
2191                         boolean returnResolutionInProgress) throws JavaModelException {
2192
2193                 JavaModelManager manager = JavaModelManager.getJavaModelManager();
2194                 JavaModelManager.PerProjectInfo perProjectInfo = null;
2195                 if (ignoreUnresolvedEntry && !generateMarkerOnError) {
2196                         perProjectInfo = getPerProjectInfo();
2197                         if (perProjectInfo != null) {
2198                                 // resolved path is cached on its info
2199                                 IClasspathEntry[] infoPath = perProjectInfo.resolvedClasspath;
2200                                 if (infoPath != null) {
2201                                         return infoPath;
2202                                 } else if (returnResolutionInProgress
2203                                                 && manager.isClasspathBeingResolved(this)) {
2204                                         if (JavaModelManager.CP_RESOLVE_VERBOSE) {
2205                                                 Util
2206                                                                 .verbose("CPResolution: reentering raw classpath resolution, will use empty classpath instead" + //$NON-NLS-1$
2207                                                                                 "       project: " + getElementName() + '\n' + //$NON-NLS-1$
2208                                                                                 "       invocation stack trace:"); //$NON-NLS-1$
2209                                                 new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
2210                                         }
2211                                         return RESOLUTION_IN_PROGRESS;
2212                                 }
2213                         }
2214                 }
2215                 Map reverseMap = perProjectInfo == null ? null : new HashMap(5);
2216                 IClasspathEntry[] resolvedPath = null;
2217                 boolean nullOldResolvedCP = perProjectInfo != null
2218                                 && perProjectInfo.resolvedClasspath == null;
2219                 try {
2220                         // protect against misbehaving clients (see
2221                         // https://bugs.eclipse.org/bugs/show_bug.cgi?id=61040)
2222                         if (nullOldResolvedCP)
2223                                 manager.setClasspathBeingResolved(this, true);
2224                         resolvedPath = getResolvedClasspath(getRawClasspath(
2225                                         generateMarkerOnError, !generateMarkerOnError),
2226                                         generateMarkerOnError ? getOutputLocation() : null,
2227                                         ignoreUnresolvedEntry, generateMarkerOnError, reverseMap);
2228                 } finally {
2229                         if (nullOldResolvedCP)
2230                                 perProjectInfo.resolvedClasspath = null;
2231                 }
2232
2233                 if (perProjectInfo != null) {
2234                         if (perProjectInfo.rawClasspath == null // .classpath file could not
2235                                                                                                         // be read
2236                                         && generateMarkerOnError
2237                                         && JavaProject.hasJavaNature(this.project)) {
2238                                 // flush .classpath format markers (bug 39877), but only when
2239                                 // file cannot be read (bug 42366)
2240                                 this.flushClasspathProblemMarkers(false, true);
2241                                 this
2242                                                 .createClasspathProblemMarker(new JavaModelStatus(
2243                                                                 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
2244                                                                 Util
2245                                                                                 .bind(
2246                                                                                                 "classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
2247                         }
2248
2249                         perProjectInfo.resolvedClasspath = resolvedPath;
2250                         perProjectInfo.resolvedPathToRawEntries = reverseMap;
2251                         manager.setClasspathBeingResolved(this, false);
2252                 }
2253                 return resolvedPath;
2254         }
2255
2256         /**
2257          * Internal variant which can process any arbitrary classpath
2258          */
2259         public IClasspathEntry[] getResolvedClasspath(
2260                         IClasspathEntry[] classpathEntries, IPath projectOutputLocation, // only
2261                                                                                                                                                                 // set
2262                                                                                                                                                                 // if
2263                                                                                                                                                                 // needing
2264                                                                                                                                                                 // full
2265                                                                                                                                                                 // classpath
2266                                                                                                                                                                 // validation
2267                                                                                                                                                                 // (and
2268                                                                                                                                                                 // markers)
2269                         boolean ignoreUnresolvedEntry, // if unresolved entries are met,
2270                                                                                         // should it trigger initializations
2271                         boolean generateMarkerOnError, Map reverseMap) // can be null if
2272                                                                                                                         // not interested in
2273                                                                                                                         // reverse mapping
2274                         throws JavaModelException {
2275
2276                 IJavaModelStatus status;
2277                 if (generateMarkerOnError) {
2278                         flushClasspathProblemMarkers(false, false);
2279                 }
2280
2281                 int length = classpathEntries.length;
2282                 ArrayList resolvedEntries = new ArrayList();
2283
2284                 for (int i = 0; i < length; i++) {
2285
2286                         IClasspathEntry rawEntry = classpathEntries[i];
2287                         IPath resolvedPath;
2288                         status = null;
2289
2290                         /* validation if needed */
2291                         // if (generateMarkerOnError || !ignoreUnresolvedEntry) {
2292                         // status = JavaConventions.validateClasspathEntry(this, rawEntry,
2293                         // false);
2294                         // if (generateMarkerOnError && !status.isOK())
2295                         // createClasspathProblemMarker(status);
2296                         // }
2297                         switch (rawEntry.getEntryKind()) {
2298
2299                         case IClasspathEntry.CPE_VARIABLE:
2300
2301                                 IClasspathEntry resolvedEntry = JavaCore
2302                                                 .getResolvedClasspathEntry(rawEntry);
2303                                 if (resolvedEntry == null) {
2304                                         if (!ignoreUnresolvedEntry)
2305                                                 throw new JavaModelException(status);
2306                                 } else {
2307                                         if (reverseMap != null
2308                                                         && reverseMap.get(resolvedPath = resolvedEntry
2309                                                                         .getPath()) == null)
2310                                                 reverseMap.put(resolvedPath, rawEntry);
2311                                         resolvedEntries.add(resolvedEntry);
2312                                 }
2313                                 break;
2314
2315                         // case IClasspathEntry.CPE_CONTAINER :
2316                         //                              
2317                         // IClasspathContainer container =
2318                         // PHPCore.getClasspathContainer(rawEntry.getPath(), this);
2319                         // if (container == null){
2320                         // if (!ignoreUnresolvedEntry) throw new JavaModelException(status);
2321                         // break;
2322                         // }
2323                         //
2324                         // IClasspathEntry[] containerEntries =
2325                         // container.getClasspathEntries();
2326                         // if (containerEntries == null) break;
2327                         //
2328                         // // container was bound
2329                         // for (int j = 0, containerLength = containerEntries.length; j <
2330                         // containerLength; j++){
2331                         // IClasspathEntry cEntry = containerEntries[j];
2332                         //                                              
2333                         // if (generateMarkerOnError) {
2334                         // IJavaModelStatus containerStatus =
2335                         // JavaConventions.validateClasspathEntry(this, cEntry, false);
2336                         // if (!containerStatus.isOK())
2337                         // createClasspathProblemMarker(containerStatus);
2338                         // }
2339                         // // if container is exported, then its nested entries must in turn
2340                         // be exported (21749)
2341                         // if (rawEntry.isExported()){
2342                         // cEntry = new ClasspathEntry(cEntry.getContentKind(),
2343                         // cEntry.getEntryKind(), cEntry.getPath(),
2344                         // cEntry.getExclusionPatterns(), cEntry.getSourceAttachmentPath(),
2345                         // cEntry.getSourceAttachmentRootPath(), cEntry.getOutputLocation(),
2346                         // true); // duplicate container entry for tagging it as exported
2347                         // }
2348                         // if (reverseMap != null && reverseMap.get(resolvedPath =
2349                         // cEntry.getPath()) == null) reverseMap.put(resolvedPath,
2350                         // rawEntry);
2351                         // resolvedEntries.add(cEntry);
2352                         // }
2353                         // break;
2354
2355                         default:
2356
2357                                 if (reverseMap != null
2358                                                 && reverseMap.get(resolvedPath = rawEntry.getPath()) == null)
2359                                         reverseMap.put(resolvedPath, rawEntry);
2360                                 resolvedEntries.add(rawEntry);
2361
2362                         }
2363                 }
2364
2365                 IClasspathEntry[] resolvedPath = new IClasspathEntry[resolvedEntries
2366                                 .size()];
2367                 resolvedEntries.toArray(resolvedPath);
2368
2369                 // if (generateMarkerOnError && projectOutputLocation != null) {
2370                 // status = JavaConventions.validateClasspath(this, resolvedPath,
2371                 // projectOutputLocation);
2372                 // if (!status.isOK()) createClasspathProblemMarker(status);
2373                 // }
2374                 return resolvedPath;
2375         }
2376
2377         /*
2378          * @see IJavaElement
2379          */
2380         public IResource getResource() {
2381                 return this.getProject();
2382         }
2383
2384         /**
2385          * @see IJavaProject
2386          */
2387         public ISearchableNameEnvironment getSearchableNameEnvironment()
2388                         throws JavaModelException {
2389
2390                 // JavaProjectElementInfo info = getJavaProjectElementInfo();
2391                 // if (info.getSearchableEnvironment() == null) {
2392                 // info.setSearchableEnvironment(new SearchableEnvironment(this));
2393                 // }
2394                 // return info.getSearchableEnvironment();
2395                 return null;
2396         }
2397
2398         /**
2399          * Retrieve a shared property on a project. If the property is not defined,
2400          * answers null. Note that it is orthogonal to IResource persistent
2401          * properties, and client code has to decide which form of storage to use
2402          * appropriately. Shared properties produce real resource files which can be
2403          * shared through a VCM onto a server. Persistent properties are not
2404          * shareable.
2405          * 
2406          * @see JavaProject#setSharedProperty(String, String)
2407          */
2408         public String getSharedProperty(String key) throws CoreException {
2409
2410                 String property = null;
2411                 IFile rscFile = getProject().getFile(key);
2412                 if (rscFile.exists()) {
2413                         property = new String(Util.getResourceContentsAsByteArray(rscFile));
2414                 }
2415                 return property;
2416         }
2417
2418         /**
2419          * @see JavaElement
2420          */
2421         // public SourceMapper getSourceMapper() {
2422         //
2423         // return null;
2424         // }
2425         /**
2426          * @see IJavaElement
2427          */
2428         public IResource getUnderlyingResource() throws JavaModelException {
2429                 if (!exists())
2430                         throw newNotPresentException();
2431                 return getProject();
2432         }
2433
2434         /**
2435          * @see IJavaProject
2436          */
2437         public boolean hasBuildState() {
2438
2439                 return JavaModelManager.getJavaModelManager().getLastBuiltState(
2440                                 this.getProject(), null) != null;
2441         }
2442
2443         /**
2444          * @see IJavaProject
2445          */
2446         public boolean hasClasspathCycle(IClasspathEntry[] preferredClasspath) {
2447                 HashSet cycleParticipants = new HashSet();
2448                 updateCycleParticipants(preferredClasspath, new ArrayList(2),
2449                                 cycleParticipants, ResourcesPlugin.getWorkspace().getRoot(),
2450                                 new HashSet(2));
2451                 return !cycleParticipants.isEmpty();
2452         }
2453
2454         public boolean hasCycleMarker() {
2455                 return this.getCycleMarker() != null;
2456         }
2457
2458         public int hashCode() {
2459                 return project.hashCode();
2460         }
2461
2462         /**
2463          * Returns true if the given project is accessible and it has a java nature,
2464          * otherwise false.
2465          */
2466         public static boolean hasJavaNature(IProject project) {
2467                 try {
2468                         return project.hasNature(PHPeclipsePlugin.PHP_NATURE_ID);
2469                 } catch (CoreException e) {
2470                         // project does not exist or is not open
2471                 }
2472                 return false;
2473         }
2474
2475         /**
2476          * Answers true if the project potentially contains any source. A project
2477          * which has no source is immutable.
2478          */
2479         public boolean hasSource() {
2480
2481                 // look if any source folder on the classpath
2482                 // no need for resolved path given source folder cannot be abstracted
2483                 IClasspathEntry[] entries;
2484                 try {
2485                         entries = this.getRawClasspath();
2486                 } catch (JavaModelException e) {
2487                         return true; // unsure
2488                 }
2489                 for (int i = 0, max = entries.length; i < max; i++) {
2490                         if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
2491                                 return true;
2492                         }
2493                 }
2494                 return false;
2495         }
2496
2497         /**
2498          * Compare current classpath with given one to see if any different. Note
2499          * that the argument classpath contains its binary output.
2500          */
2501         public boolean isClasspathEqualsTo(IClasspathEntry[] newClasspath,
2502                         IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput)
2503                         throws JavaModelException {
2504
2505                 if (otherClasspathWithOutput != null
2506                                 && otherClasspathWithOutput.length > 0) {
2507
2508                         int length = otherClasspathWithOutput.length;
2509                         if (length == newClasspath.length + 1) {
2510                                 // output is amongst file entries (last one)
2511
2512                                 // compare classpath entries
2513                                 for (int i = 0; i < length - 1; i++) {
2514                                         if (!otherClasspathWithOutput[i].equals(newClasspath[i]))
2515                                                 return false;
2516                                 }
2517                                 // compare binary outputs
2518                                 IClasspathEntry output = otherClasspathWithOutput[length - 1];
2519                                 if (output.getContentKind() == ClasspathEntry.K_OUTPUT
2520                                                 && output.getPath().equals(newOutputLocation))
2521                                         return true;
2522                         }
2523                 }
2524                 return false;
2525         }
2526
2527         /*
2528          * @see IJavaProject
2529          */
2530         public boolean isOnClasspath(IJavaElement element) {
2531                 IPath path = element.getPath();
2532                 switch (element.getElementType()) {
2533                 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
2534                         if (!((IPackageFragmentRoot) element).isArchive()) {
2535                                 // ensure that folders are only excluded if all of their
2536                                 // children are excluded
2537                                 path = path.append("*"); //$NON-NLS-1$
2538                         }
2539                         break;
2540                 case IJavaElement.PACKAGE_FRAGMENT:
2541                         if (!((IPackageFragmentRoot) element.getParent()).isArchive()) {
2542                                 // ensure that folders are only excluded if all of their
2543                                 // children are excluded
2544                                 path = path.append("*"); //$NON-NLS-1$
2545                         }
2546                         break;
2547                 }
2548                 return this.isOnClasspath(path);
2549         }
2550
2551         private boolean isOnClasspath(IPath path) {
2552                 IClasspathEntry[] classpath;
2553                 try {
2554                         classpath = this
2555                                         .getResolvedClasspath(true/* ignore unresolved variable */);
2556                 } catch (JavaModelException e) {
2557                         return false; // not a Java project
2558                 }
2559                 for (int i = 0; i < classpath.length; i++) {
2560                         IClasspathEntry entry = classpath[i];
2561                         if (entry.getPath().isPrefixOf(path)
2562                                         && !Util.isExcluded(path, null, ((ClasspathEntry) entry)
2563                                                         .fullExclusionPatternChars(), true)) {
2564                                 return true;
2565                         }
2566                 }
2567                 return false;
2568         }
2569
2570         /*
2571          * @see IJavaProject
2572          */
2573         public boolean isOnClasspath(IResource resource) {
2574                 IPath path = resource.getFullPath();
2575
2576                 // ensure that folders are only excluded if all of their children are
2577                 // excluded
2578                 if (resource.getType() == IResource.FOLDER) {
2579                         path = path.append("*"); //$NON-NLS-1$
2580                 }
2581
2582                 return this.isOnClasspath(path);
2583         }
2584
2585         private IPath getPluginWorkingLocation() {
2586                 return this.project.getWorkingLocation(JavaCore.PLUGIN_ID);
2587         }
2588
2589         /*
2590          * load preferences from a shareable format (VCM-wise)
2591          */
2592         public Preferences loadPreferences() {
2593
2594                 Preferences preferences = new Preferences();
2595
2596                 // File prefFile =
2597                 // getProject().getLocation().append(PREF_FILENAME).toFile();
2598                 IPath projectMetaLocation = getPluginWorkingLocation();
2599                 if (projectMetaLocation != null) {
2600                         File prefFile = projectMetaLocation.append(PREF_FILENAME).toFile();
2601                         if (prefFile.exists()) { // load preferences from file
2602                                 InputStream in = null;
2603                                 try {
2604                                         in = new BufferedInputStream(new FileInputStream(prefFile));
2605                                         preferences.load(in);
2606                                         return preferences;
2607                                 } catch (IOException e) { // problems loading preference store
2608                                                                                         // - quietly ignore
2609                                 } finally {
2610                                         if (in != null) {
2611                                                 try {
2612                                                         in.close();
2613                                                 } catch (IOException e) { // ignore problems with
2614                                                                                                         // close
2615                                                 }
2616                                         }
2617                                 }
2618                         }
2619                 }
2620                 return null;
2621         }
2622
2623         /**
2624          * @see IJavaProject#newEvaluationContext
2625          */
2626         // public IEvaluationContext newEvaluationContext() {
2627         //
2628         // return new EvaluationContextWrapper(new EvaluationContext(), this);
2629         // }
2630         /**
2631          * @see IJavaProject
2632          */
2633         // public ITypeHierarchy newTypeHierarchy(
2634         // IRegion region,
2635         // IProgressMonitor monitor)
2636         // throws JavaModelException {
2637         //
2638         // if (region == null) {
2639         // throw new
2640         // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullRegion"));//$NON-NLS-1$
2641         // }
2642         // CreateTypeHierarchyOperation op =
2643         // new CreateTypeHierarchyOperation(null, region, this, true);
2644         // runOperation(op, monitor);
2645         // return op.getResult();
2646         // }
2647         /**
2648          * @see IJavaProject
2649          */
2650         // public ITypeHierarchy newTypeHierarchy(
2651         // IType type,
2652         // IRegion region,
2653         // IProgressMonitor monitor)
2654         // throws JavaModelException {
2655         //
2656         // if (type == null) {
2657         // throw new
2658         // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullFocusType"));//$NON-NLS-1$
2659         // }
2660         // if (region == null) {
2661         // throw new
2662         // IllegalArgumentException(ProjectPrefUtil.bind("hierarchy.nullRegion"));//$NON-NLS-1$
2663         // }
2664         // CreateTypeHierarchyOperation op =
2665         // new CreateTypeHierarchyOperation(type, region, this, true);
2666         // runOperation(op, monitor);
2667         // return op.getResult();
2668         // }
2669         // /**
2670         // * Open project if resource isn't closed
2671         // */
2672         // protected void openWhenClosed(IProgressMonitor pm) throws
2673         // JavaModelException {
2674         //
2675         // if (!this.fProject.isOpen()) {
2676         // throw newNotPresentException();
2677         // } else {
2678         // super.openWhenClosed(pm);
2679         // }
2680         // }
2681         public String[] projectPrerequisites(IClasspathEntry[] entries)
2682                         throws JavaModelException {
2683
2684                 ArrayList prerequisites = new ArrayList();
2685                 // need resolution
2686                 entries = getResolvedClasspath(entries, null, true, false, null/*
2687                                                                                                                                                  * no
2688                                                                                                                                                  * reverse
2689                                                                                                                                                  * map
2690                                                                                                                                                  */);
2691                 for (int i = 0, length = entries.length; i < length; i++) {
2692                         IClasspathEntry entry = entries[i];
2693                         if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
2694                                 prerequisites.add(entry.getPath().lastSegment());
2695                         }
2696                 }
2697                 int size = prerequisites.size();
2698                 if (size == 0) {
2699                         return NO_PREREQUISITES;
2700                 } else {
2701                         String[] result = new String[size];
2702                         prerequisites.toArray(result);
2703                         return result;
2704                 }
2705         }
2706
2707         /**
2708          * Reads the .classpath file from disk and returns the list of entries it
2709          * contains (including output location entry) Returns null if .classfile is
2710          * not present. Returns INVALID_CLASSPATH if it has a format problem.
2711          */
2712         protected IClasspathEntry[] readClasspathFile(boolean createMarker,
2713                         boolean logProblems) {
2714
2715                 try {
2716                         String xmlClasspath = getSharedProperty(CLASSPATH_FILENAME);
2717                         if (xmlClasspath == null)
2718                                 return null;
2719                         return decodeClasspath(xmlClasspath, createMarker, logProblems);
2720                 } catch (CoreException e) {
2721                         // file does not exist (or not accessible)
2722                         if (createMarker && this.getProject().isAccessible()) {
2723                                 this
2724                                                 .createClasspathProblemMarker(new JavaModelStatus(
2725                                                                 IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
2726                                                                 Util
2727                                                                                 .bind(
2728                                                                                                 "classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
2729                         }
2730                         if (logProblems) {
2731                                 Util.log(e, "Exception while retrieving " + this.getPath() //$NON-NLS-1$
2732                                                 + "/.classpath, will revert to default classpath"); //$NON-NLS-1$
2733                         }
2734                 }
2735                 return null;
2736         }
2737
2738         /**
2739          * Removes the given builder from the build spec for the given project.
2740          */
2741         protected void removeFromBuildSpec(String builderID) throws CoreException {
2742
2743                 IProjectDescription description = getProject().getDescription();
2744                 ICommand[] commands = description.getBuildSpec();
2745                 for (int i = 0; i < commands.length; ++i) {
2746                         if (commands[i].getBuilderName().equals(builderID)) {
2747                                 ICommand[] newCommands = new ICommand[commands.length - 1];
2748                                 System.arraycopy(commands, 0, newCommands, 0, i);
2749                                 System.arraycopy(commands, i + 1, newCommands, i,
2750                                                 commands.length - i - 1);
2751                                 description.setBuildSpec(newCommands);
2752                                 getProject().setDescription(description, null);
2753                                 return;
2754                         }
2755                 }
2756         }
2757
2758         /**
2759          * @see JavaElement#rootedAt(IJavaProject)
2760          */
2761         public IJavaElement rootedAt(IJavaProject project) {
2762                 return project;
2763
2764         }
2765
2766         /**
2767          * Answers an ID which is used to distinguish project/entries during package
2768          * fragment root computations
2769          */
2770         public String rootID() {
2771                 return "[PRJ]" + this.getProject().getFullPath(); //$NON-NLS-1$
2772         }
2773
2774         /**
2775          * Saves the classpath in a shareable format (VCM-wise) only when necessary,
2776          * that is, if it is semantically different from the existing one in file.
2777          * Will never write an identical one.
2778          * 
2779          * @return Return whether the .classpath file was modified.
2780          */
2781         public boolean saveClasspath(IClasspathEntry[] newClasspath,
2782                         IPath newOutputLocation) throws JavaModelException {
2783
2784                 if (!getProject().exists())
2785                         return false;
2786
2787                 IClasspathEntry[] fileEntries = readClasspathFile(
2788                                 false /* don't create markers */, false/* don't log problems */);
2789                 if (fileEntries != null
2790                                 && isClasspathEqualsTo(newClasspath, newOutputLocation,
2791                                                 fileEntries)) {
2792                         // no need to save it, it is the same
2793                         return false;
2794                 }
2795
2796                 // actual file saving
2797                 try {
2798                         setSharedProperty(CLASSPATH_FILENAME, encodeClasspath(newClasspath,
2799                                         newOutputLocation, true));
2800                         return true;
2801                 } catch (CoreException e) {
2802                         throw new JavaModelException(e);
2803                 }
2804         }
2805
2806         /**
2807          * Save project custom preferences to shareable file (.jprefs)
2808          */
2809         private void savePreferences(Preferences preferences) {
2810
2811                 if (!JavaProject.hasJavaNature(this.project))
2812                         return; // ignore
2813
2814                 if (preferences == null
2815                                 || (!preferences.needsSaving() && preferences.propertyNames().length != 0)) {
2816                         // nothing to save
2817                         return;
2818                 }
2819
2820                 // preferences need to be saved
2821                 // the preferences file is located in the plug-in's state area
2822                 // at a well-known name (.jprefs)
2823                 // File prefFile =
2824                 // this.project.getLocation().append(PREF_FILENAME).toFile();
2825                 File prefFile = getPluginWorkingLocation().append(PREF_FILENAME)
2826                                 .toFile();
2827                 if (preferences.propertyNames().length == 0) {
2828                         // there are no preference settings
2829                         // rather than write an empty file, just delete any existing file
2830                         if (prefFile.exists()) {
2831                                 prefFile.delete(); // don't worry if delete unsuccessful
2832                         }
2833                         return;
2834                 }
2835
2836                 // write file, overwriting an existing one
2837                 OutputStream out = null;
2838                 try {
2839                         // do it as carefully as we know how so that we don't lose/mangle
2840                         // the setting in times of stress
2841                         out = new BufferedOutputStream(new FileOutputStream(prefFile));
2842                         preferences.store(out, null);
2843                 } catch (IOException e) { // problems saving preference store -
2844                                                                         // quietly ignore
2845                 } finally {
2846                         if (out != null) {
2847                                 try {
2848                                         out.close();
2849                                 } catch (IOException e) { // ignore problems with close
2850                                 }
2851                         }
2852                 }
2853         }
2854
2855         /**
2856          * Update the Java command in the build spec (replace existing one if
2857          * present, add one first if none).
2858          */
2859         private void setJavaCommand(IProjectDescription description,
2860                         ICommand newCommand) throws CoreException {
2861
2862                 ICommand[] oldCommands = description.getBuildSpec();
2863                 ICommand oldJavaCommand = getJavaCommand(description);
2864                 ICommand[] newCommands;
2865
2866                 if (oldJavaCommand == null) {
2867                         // Add a Java build spec before other builders (1FWJK7I)
2868                         newCommands = new ICommand[oldCommands.length + 1];
2869                         System
2870                                         .arraycopy(oldCommands, 0, newCommands, 1,
2871                                                         oldCommands.length);
2872                         newCommands[0] = newCommand;
2873                 } else {
2874                         for (int i = 0, max = oldCommands.length; i < max; i++) {
2875                                 if (oldCommands[i] == oldJavaCommand) {
2876                                         oldCommands[i] = newCommand;
2877                                         break;
2878                                 }
2879                         }
2880                         newCommands = oldCommands;
2881                 }
2882
2883                 // Commit the spec change into the project
2884                 description.setBuildSpec(newCommands);
2885                 getProject().setDescription(description, null);
2886         }
2887
2888         /**
2889          * @see net.sourceforge.phpdt.core.IJavaProject#setOptions(Map)
2890          */
2891         public void setOptions(Map newOptions) {
2892
2893                 Preferences preferences;
2894                 setPreferences(preferences = new Preferences()); // always reset
2895                                                                                                                         // (26255)
2896                 if (newOptions != null) {
2897                         Iterator keys = newOptions.keySet().iterator();
2898                         while (keys.hasNext()) {
2899                                 String key = (String) keys.next();
2900                                 if (!JavaModelManager.OptionNames.contains(key))
2901                                         continue; // unrecognized option
2902                                 // no filtering for encoding (custom encoding for project is
2903                                 // allowed)
2904                                 String value = (String) newOptions.get(key);
2905                                 preferences.setDefault(key, CUSTOM_DEFAULT_OPTION_VALUE); // empty
2906                                                                                                                                                         // string
2907                                                                                                                                                         // isn't
2908                                                                                                                                                         // the
2909                                                                                                                                                         // default
2910                                                                                                                                                         // (26251)
2911                                 preferences.setValue(key, value);
2912                         }
2913                 }
2914
2915                 // persist options
2916                 savePreferences(preferences);
2917         }
2918
2919         /**
2920          * @see IJavaProject
2921          */
2922         public void setOutputLocation(IPath path, IProgressMonitor monitor)
2923                         throws JavaModelException {
2924
2925                 if (path == null) {
2926                         throw new IllegalArgumentException(Util.bind("path.nullpath")); //$NON-NLS-1$
2927                 }
2928                 if (path.equals(getOutputLocation())) {
2929                         return;
2930                 }
2931                 this.setRawClasspath(SetClasspathOperation.ReuseClasspath, path,
2932                                 monitor);
2933         }
2934
2935         /*
2936          * Set cached preferences, no preference file is saved, only info is updated
2937          */
2938         public void setPreferences(Preferences preferences) {
2939                 IProject project = getProject();
2940                 if (!JavaProject.hasJavaNature(project))
2941                         return; // ignore
2942                 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager
2943                                 .getJavaModelManager().getPerProjectInfo(project, true);
2944                 perProjectInfo.preferences = preferences;
2945         }
2946
2947         /**
2948          * @see IJavaProject
2949          */
2950         public void setRawClasspath(IClasspathEntry[] entries,
2951                         IPath outputLocation, IProgressMonitor monitor)
2952                         throws JavaModelException {
2953
2954                 setRawClasspath(entries, outputLocation, monitor, true, // canChangeResource
2955                                                                                                                                 // (as per API
2956                                                                                                                                 // contract)
2957                                 getResolvedClasspath(true), // ignoreUnresolvedVariable
2958                                 true, // needValidation
2959                                 true); // need to save
2960         }
2961
2962         public void setRawClasspath(IClasspathEntry[] newEntries,
2963                         IPath newOutputLocation, IProgressMonitor monitor,
2964                         boolean canChangeResource, IClasspathEntry[] oldResolvedPath,
2965                         boolean needValidation, boolean needSave) throws JavaModelException {
2966
2967                 JavaModelManager manager = (JavaModelManager) JavaModelManager
2968                                 .getJavaModelManager();
2969                 try {
2970                         IClasspathEntry[] newRawPath = newEntries;
2971                         if (newRawPath == null) { // are we already with the default
2972                                                                                 // classpath
2973                                 newRawPath = defaultClasspath();
2974                         }
2975                         SetClasspathOperation op = new SetClasspathOperation(this,
2976                                         oldResolvedPath, newRawPath, newOutputLocation,
2977                                         canChangeResource, needValidation, needSave);
2978                         runOperation(op, monitor);
2979
2980                 } catch (JavaModelException e) {
2981                         manager.flush();
2982                         throw e;
2983                 }
2984         }
2985
2986         /**
2987          * @see IJavaProject
2988          */
2989         public void setRawClasspath(IClasspathEntry[] entries,
2990                         IProgressMonitor monitor) throws JavaModelException {
2991
2992                 setRawClasspath(entries, SetClasspathOperation.ReuseOutputLocation,
2993                                 monitor, true, // canChangeResource (as per API contract)
2994                                 getResolvedClasspath(true), // ignoreUnresolvedVariable
2995                                 true, // needValidation
2996                                 true); // need to save
2997         }
2998
2999         /**
3000          * NOTE: <code>null</code> specifies default classpath, and an empty array
3001          * specifies an empty classpath.
3002          * 
3003          * @exception NotPresentException
3004          *                if this project does not exist.
3005          */
3006         // protected void setRawClasspath0(IClasspathEntry[] rawEntries)
3007         // throws JavaModelException {
3008         //
3009         // JavaModelManager.PerProjectInfo info =
3010         // JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project);
3011         //      
3012         // synchronized (info) {
3013         // if (rawEntries != null) {
3014         // info.classpath = rawEntries;
3015         // }
3016         //                      
3017         // // clear cache of resolved classpath
3018         // info.lastResolvedClasspath = null;
3019         // info.resolvedPathToRawEntries = null;
3020         // }
3021         // }
3022         /**
3023          * Record a shared persistent property onto a project. Note that it is
3024          * orthogonal to IResource persistent properties, and client code has to
3025          * decide which form of storage to use appropriately. Shared properties
3026          * produce real resource files which can be shared through a VCM onto a
3027          * server. Persistent properties are not shareable.
3028          * 
3029          * shared properties end up in resource files, and thus cannot be modified
3030          * during delta notifications (a CoreException would then be thrown).
3031          * 
3032          * @see JavaProject#getSharedProperty(String key)
3033          */
3034         public void setSharedProperty(String key, String value)
3035                         throws CoreException {
3036
3037                 IFile rscFile = getProject().getFile(key);
3038                 InputStream inputStream = new ByteArrayInputStream(value.getBytes());
3039                 // update the resource content
3040                 if (rscFile.exists()) {
3041                         if (rscFile.isReadOnly()) {
3042                                 // provide opportunity to checkout read-only .classpath file
3043                                 // (23984)
3044                                 ResourcesPlugin.getWorkspace().validateEdit(
3045                                                 new IFile[] { rscFile }, null);
3046                         }
3047                         rscFile.setContents(inputStream, IResource.FORCE, null);
3048                 } else {
3049                         rscFile.create(inputStream, IResource.FORCE, null);
3050                 }
3051         }
3052
3053         /**
3054          * Update cycle markers for all java projects
3055          */
3056         public static void updateAllCycleMarkers() throws JavaModelException {
3057
3058                 // long start = System.currentTimeMillis();
3059
3060                 JavaModelManager manager = JavaModelManager.getJavaModelManager();
3061                 IJavaProject[] projects = manager.getJavaModel().getJavaProjects();
3062                 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
3063
3064                 HashSet cycleParticipants = new HashSet();
3065                 HashSet traversed = new HashSet();
3066                 int length = projects.length;
3067
3068                 // compute cycle participants
3069                 ArrayList prereqChain = new ArrayList();
3070                 for (int i = 0; i < length; i++) {
3071                         JavaProject project = (JavaProject) projects[i];
3072                         if (!traversed.contains(project.getPath())) {
3073                                 prereqChain.clear();
3074                                 project.updateCycleParticipants(null, prereqChain,
3075                                                 cycleParticipants, workspaceRoot, traversed);
3076                         }
3077                 }
3078                 // System.out.println("updateAllCycleMarkers: " +
3079                 // (System.currentTimeMillis() - start) + " ms");
3080
3081                 for (int i = 0; i < length; i++) {
3082                         JavaProject project = (JavaProject) projects[i];
3083
3084                         if (cycleParticipants.contains(project.getPath())) {
3085                                 IMarker cycleMarker = project.getCycleMarker();
3086                                 String circularCPOption = project.getOption(
3087                                                 JavaCore.CORE_CIRCULAR_CLASSPATH, true);
3088                                 int circularCPSeverity = JavaCore.ERROR
3089                                                 .equals(circularCPOption) ? IMarker.SEVERITY_ERROR
3090                                                 : IMarker.SEVERITY_WARNING;
3091                                 if (cycleMarker != null) {
3092                                         // update existing cycle marker if needed
3093                                         try {
3094                                                 int existingSeverity = ((Integer) cycleMarker
3095                                                                 .getAttribute(IMarker.SEVERITY)).intValue();
3096                                                 if (existingSeverity != circularCPSeverity) {
3097                                                         cycleMarker.setAttribute(IMarker.SEVERITY,
3098                                                                         circularCPSeverity);
3099                                                 }
3100                                         } catch (CoreException e) {
3101                                                 throw new JavaModelException(e);
3102                                         }
3103                                 } else {
3104                                         // create new marker
3105                                         project
3106                                                         .createClasspathProblemMarker(new JavaModelStatus(
3107                                                                         IJavaModelStatusConstants.CLASSPATH_CYCLE,
3108                                                                         project));
3109                                 }
3110                         } else {
3111                                 project.flushClasspathProblemMarkers(true, false);
3112                         }
3113                 }
3114         }
3115
3116         /**
3117          * If a cycle is detected, then cycleParticipants contains all the paths of
3118          * projects involved in this cycle (directly and indirectly), no cycle if
3119          * the set is empty (and started empty)
3120          */
3121         public void updateCycleParticipants(IClasspathEntry[] preferredClasspath,
3122                         ArrayList prereqChain, HashSet cycleParticipants,
3123                         IWorkspaceRoot workspaceRoot, HashSet traversed) {
3124
3125                 IPath path = this.getPath();
3126                 prereqChain.add(path);
3127                 traversed.add(path);
3128                 try {
3129                         IClasspathEntry[] classpath = preferredClasspath == null ? getResolvedClasspath(true)
3130                                         : preferredClasspath;
3131                         for (int i = 0, length = classpath.length; i < length; i++) {
3132                                 IClasspathEntry entry = classpath[i];
3133
3134                                 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
3135                                         IPath prereqProjectPath = entry.getPath();
3136                                         int index = cycleParticipants.contains(prereqProjectPath) ? 0
3137                                                         : prereqChain.indexOf(prereqProjectPath);
3138                                         if (index >= 0) { // refer to cycle, or in cycle itself
3139                                                 for (int size = prereqChain.size(); index < size; index++) {
3140                                                         cycleParticipants.add(prereqChain.get(index));
3141                                                 }
3142                                         } else {
3143                                                 if (!traversed.contains(prereqProjectPath)) {
3144                                                         IResource member = workspaceRoot
3145                                                                         .findMember(prereqProjectPath);
3146                                                         if (member != null
3147                                                                         && member.getType() == IResource.PROJECT) {
3148                                                                 JavaProject project = (JavaProject) JavaCore
3149                                                                                 .create((IProject) member);
3150                                                                 project.updateCycleParticipants(null,
3151                                                                                 prereqChain, cycleParticipants,
3152                                                                                 workspaceRoot, traversed);
3153                                                         }
3154                                                 }
3155                                         }
3156                                 }
3157                         }
3158                 } catch (JavaModelException e) {
3159                 }
3160                 prereqChain.remove(path);
3161         }
3162
3163         /**
3164          * Reset the collection of package fragment roots (local ones) - only if
3165          * opened. Need to check *all* package fragment roots in order to reset
3166          * NameLookup
3167          */
3168         public void updatePackageFragmentRoots() {
3169
3170                 if (this.isOpen()) {
3171                         try {
3172                                 JavaProjectElementInfo info = getJavaProjectElementInfo();
3173
3174                                 IClasspathEntry[] classpath = getResolvedClasspath(true);
3175                                 // NameLookup lookup = info.getNameLookup();
3176                                 // if (lookup != null){
3177                                 // IPackageFragmentRoot[] oldRoots =
3178                                 // lookup.fPackageFragmentRoots;
3179                                 // IPackageFragmentRoot[] newRoots =
3180                                 // computePackageFragmentRoots(classpath, true);
3181                                 // checkIdentical: { // compare all pkg fragment root lists
3182                                 // if (oldRoots.length == newRoots.length){
3183                                 // for (int i = 0, length = oldRoots.length; i < length; i++){
3184                                 // if (!oldRoots[i].equals(newRoots[i])){
3185                                 // break checkIdentical;
3186                                 // }
3187                                 // }
3188                                 // return; // no need to update
3189                                 // }
3190                                 // }
3191                                 // info.setNameLookup(null); // discard name lookup (hold onto
3192                                 // roots)
3193                                 // }
3194                                 info.setNonJavaResources(null);
3195                                 info.setChildren(computePackageFragmentRoots(classpath, false));
3196
3197                         } catch (JavaModelException e) {
3198                                 try {
3199                                         close(); // could not do better
3200                                 } catch (JavaModelException ex) {
3201                                 }
3202                         }
3203                 }
3204         }
3205
3206         public void removeLoadPathEntry(IProject anotherPHPProject) {
3207                 Iterator entries = getLoadPathEntries().iterator();
3208                 while (entries.hasNext()) {
3209                         LoadPathEntry entry = (LoadPathEntry) entries.next();
3210                         if (entry.getType() == LoadPathEntry.TYPE_PROJECT
3211                                         && entry.getProject().getName().equals(
3212                                                         anotherPHPProject.getName())) {
3213                                 getLoadPathEntries().remove(entry);
3214                                 fScratched = true;
3215                                 break;
3216                         }
3217                 }
3218         }
3219
3220         public void save() throws CoreException {
3221                 if (fScratched) {
3222                         InputStream xmlPath = new ByteArrayInputStream(getLoadPathXML()
3223                                         .getBytes());
3224                         IFile loadPathsFile = getLoadPathEntriesFile();
3225                         if (!loadPathsFile.exists())
3226                                 loadPathsFile.create(xmlPath, true, null);
3227                         else
3228                                 loadPathsFile.setContents(xmlPath, true, false, null);
3229
3230                         fScratched = false;
3231                 }
3232         }
3233
3234 }