1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Iterator;
20 import net.sourceforge.phpdt.core.IClasspathEntry;
21 import net.sourceforge.phpdt.core.IJavaElement;
22 import net.sourceforge.phpdt.core.IJavaElementDelta;
23 import net.sourceforge.phpdt.core.IJavaModel;
24 import net.sourceforge.phpdt.core.IJavaModelStatus;
25 import net.sourceforge.phpdt.core.IJavaProject;
26 import net.sourceforge.phpdt.core.IPackageFragment;
27 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
28 import net.sourceforge.phpdt.core.JavaModelException;
29 import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
31 import org.eclipse.core.resources.IFolder;
32 import org.eclipse.core.resources.IProject;
33 import org.eclipse.core.resources.IProjectDescription;
34 import org.eclipse.core.resources.IResource;
35 import org.eclipse.core.resources.IWorkspace;
36 import org.eclipse.core.resources.IWorkspaceRoot;
37 import org.eclipse.core.resources.ResourcesPlugin;
38 import org.eclipse.core.runtime.CoreException;
39 import org.eclipse.core.runtime.IPath;
40 import org.eclipse.core.runtime.Path;
43 * This operation sets an <code>IJavaProject</code>'s classpath.
47 public class SetClasspathOperation extends JavaModelOperation {
49 IClasspathEntry[] oldResolvedPath, newResolvedPath;
50 IClasspathEntry[] newRawPath;
51 boolean canChangeResource;
52 boolean needCycleCheck;
53 boolean needValidation;
55 IPath newOutputLocation;
57 public static final IClasspathEntry[] ReuseClasspath = new IClasspathEntry[0];
58 public static final IClasspathEntry[] UpdateClasspath = new IClasspathEntry[0];
59 // if reusing output location, then also reuse clean flag
60 public static final IPath ReuseOutputLocation = new Path("Reuse Existing Output Location"); //$NON-NLS-1$
63 * When executed, this operation sets the classpath of the given project.
65 public SetClasspathOperation(
67 IClasspathEntry[] oldResolvedPath,
68 IClasspathEntry[] newRawPath,
69 IPath newOutputLocation,
70 boolean canChangeResource,
71 boolean needValidation,
74 super(new IJavaElement[] { project });
75 this.oldResolvedPath = oldResolvedPath;
76 this.newRawPath = newRawPath;
77 this.newOutputLocation = newOutputLocation;
78 this.canChangeResource = canChangeResource;
79 this.needValidation = needValidation;
80 this.needSave = needSave;
84 * Adds deltas for the given roots, with the specified change flag,
85 * and closes the root. Helper method for #setClasspath
87 protected void addClasspathDeltas(
88 IPackageFragmentRoot[] roots,
90 JavaElementDelta delta) {
92 for (int i = 0; i < roots.length; i++) {
93 IPackageFragmentRoot root = roots[i];
94 delta.changed(root, flag);
95 if ((flag & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0
96 || (flag & IJavaElementDelta.F_SOURCEATTACHED) != 0
97 || (flag & IJavaElementDelta.F_SOURCEDETACHED) != 0){
100 } catch (JavaModelException e) {
102 // force detach source on jar package fragment roots (source will be lazily computed when needed)
103 ((PackageFragmentRoot) root).setSourceAttachmentProperty(null);// loose info - will be recomputed
111 * Returns the index of the item in the list if the given list contains the specified entry. If the list does
112 * not contain the entry, -1 is returned.
113 * A helper method for #setClasspath
115 protected int classpathContains(
116 IClasspathEntry[] list,
117 IClasspathEntry entry) {
119 IPath[] exclusionPatterns = entry.getExclusionPatterns();
120 nextEntry: for (int i = 0; i < list.length; i++) {
121 IClasspathEntry other = list[i];
122 if (other.getContentKind() == entry.getContentKind()
123 && other.getEntryKind() == entry.getEntryKind()
124 && other.isExported() == entry.isExported()
125 && other.getPath().equals(entry.getPath())) {
126 // check custom outputs
127 IPath entryOutput = entry.getOutputLocation();
128 IPath otherOutput = other.getOutputLocation();
129 if (entryOutput == null) {
130 if (otherOutput != null)
133 if (!entryOutput.equals(otherOutput))
137 // check exclusion patterns
138 IPath[] otherExcludes = other.getExclusionPatterns();
139 if (exclusionPatterns != otherExcludes) {
140 int excludeLength = exclusionPatterns.length;
141 if (otherExcludes.length != excludeLength)
143 for (int j = 0; j < excludeLength; j++) {
144 // compare toStrings instead of IPaths
145 // since IPath.equals is specified to ignore trailing separators
146 if (!exclusionPatterns[j].toString().equals(otherExcludes[j].toString()))
157 * Recursively adds all subfolders of <code>folder</code> to the given collection.
159 protected void collectAllSubfolders(IFolder folder, ArrayList collection) throws JavaModelException {
161 IResource[] members= folder.members();
162 for (int i = 0, max = members.length; i < max; i++) {
163 IResource r= members[i];
164 if (r.getType() == IResource.FOLDER) {
166 collectAllSubfolders((IFolder)r, collection);
169 } catch (CoreException e) {
170 throw new JavaModelException(e);
175 * Returns a collection of package fragments that have been added/removed
176 * as the result of changing the output location to/from the given
177 * location. The collection is empty if no package fragments are
180 // protected ArrayList determineAffectedPackageFragments(IPath location) throws JavaModelException {
181 // ArrayList fragments = new ArrayList();
182 // JavaProject project =getProject();
184 // // see if this will cause any package fragments to be affected
185 // IWorkspace workspace = ResourcesPlugin.getWorkspace();
186 // IResource resource = null;
187 // if (location != null) {
188 // resource = workspace.getRoot().findMember(location);
190 // if (resource != null && resource.getType() == IResource.FOLDER) {
191 // IFolder folder = (IFolder) resource;
192 // // only changes if it actually existed
193 // IClasspathEntry[] classpath = project.getExpandedClasspath(true);
194 // for (int i = 0; i < classpath.length; i++) {
195 // IClasspathEntry entry = classpath[i];
196 // IPath path = classpath[i].getPath();
197 // if (entry.getEntryKind() != IClasspathEntry.CPE_PROJECT && path.isPrefixOf(location) && !path.equals(location)) {
198 // IPackageFragmentRoot[] roots = project.computePackageFragmentRoots(classpath[i]);
199 // IPackageFragmentRoot root = roots[0];
200 // // now the output location becomes a package fragment - along with any subfolders
201 // ArrayList folders = new ArrayList();
202 // folders.add(folder);
203 // collectAllSubfolders(folder, folders);
204 // Iterator elements = folders.iterator();
205 // int segments = path.segmentCount();
206 // while (elements.hasNext()) {
207 // IFolder f = (IFolder) elements.next();
208 // IPath relativePath = f.getFullPath().removeFirstSegments(segments);
209 // String name = relativePath.toOSString();
210 // name = name.replace(File.pathSeparatorChar, '.');
211 // if (name.endsWith(".")) { //$NON-NLS-1$
212 // name = name.substring(0, name.length() - 1);
214 // IPackageFragment pkg = root.getPackageFragment(name);
215 // fragments.add(pkg);
224 * Sets the classpath of the pre-specified project.
226 protected void executeOperation() throws JavaModelException {
227 // project reference updated - may throw an exception if unable to write .project file
228 updateProjectReferencesIfNecessary();
230 // classpath file updated - may throw an exception if unable to write .classpath file
231 saveClasspathIfNecessary();
233 // perform classpath and output location updates, if exception occurs in classpath update,
234 // make sure the output location is updated before surfacing the exception (in case the output
235 // location update also throws an exception, give priority to the classpath update one).
236 JavaModelException originalException = null;
239 JavaProject project = getProject();
240 if (this.newRawPath == UpdateClasspath) this.newRawPath = project.getRawClasspath();
241 if (this.newRawPath != ReuseClasspath){
243 // project.updatePackageFragmentRoots();
244 JavaModelManager.getJavaModelManager().deltaProcessor.addForRefresh(project);
247 } catch(JavaModelException e){
248 originalException = e;
251 } finally { // if traversed by an exception we still need to update the output location when necessary
254 if (this.newOutputLocation != ReuseOutputLocation) updateOutputLocation();
256 } catch(JavaModelException e){
257 if (originalException != null) throw originalException;
265 * Generates the delta of removed/added/reordered roots.
266 * Use three deltas in case the same root is removed/added/reordered (for
267 * instance, if it is changed from K_SOURCE to K_BINARY or vice versa)
269 // protected void generateClasspathChangeDeltas(
270 // IClasspathEntry[] oldResolvedPath,
271 // IClasspathEntry[] newResolvedPath,
272 // final JavaProject project) {
274 // JavaModelManager manager = JavaModelManager.getJavaModelManager();
275 // boolean needToUpdateDependents = false;
276 // JavaElementDelta delta = new JavaElementDelta(getJavaModel());
277 // boolean hasDelta = false;
278 // int oldLength = oldResolvedPath.length;
279 // int newLength = newResolvedPath.length;
281 // final IndexManager indexManager = manager.getIndexManager();
282 // Map oldRoots = null;
283 // IPackageFragmentRoot[] roots = null;
284 // if (project.isOpen()) {
286 // roots = project.getPackageFragmentRoots();
287 // } catch (JavaModelException e) {
290 // Map allRemovedRoots ;
291 // if ((allRemovedRoots = manager.deltaProcessor.removedRoots) != null) {
292 // roots = (IPackageFragmentRoot[]) allRemovedRoots.get(project);
295 // if (roots != null) {
296 // oldRoots = new HashMap();
297 // for (int i = 0; i < roots.length; i++) {
298 // IPackageFragmentRoot root = roots[i];
299 // oldRoots.put(root.getPath(), root);
302 // for (int i = 0; i < oldLength; i++) {
304 // int index = classpathContains(newResolvedPath, oldResolvedPath[i]);
305 // if (index == -1) {
306 // // do not notify remote project changes
307 // if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
308 // needToUpdateDependents = true;
309 // this.needCycleCheck = true;
313 // IPackageFragmentRoot[] pkgFragmentRoots = null;
314 // if (oldRoots != null) {
315 // IPackageFragmentRoot oldRoot = (IPackageFragmentRoot) oldRoots.get(oldResolvedPath[i].getPath());
316 // if (oldRoot != null) { // use old root if any (could be none if entry wasn't bound)
317 // pkgFragmentRoots = new IPackageFragmentRoot[] { oldRoot };
320 // if (pkgFragmentRoots == null) {
322 // ObjectVector accumulatedRoots = new ObjectVector();
323 // HashSet rootIDs = new HashSet(5);
324 // rootIDs.add(project.rootID());
325 // project.computePackageFragmentRoots(
326 // oldResolvedPath[i],
329 // true, // inside original project
330 // false, // don't check existency
331 // false); // don't retrieve exported roots
332 // pkgFragmentRoots = new IPackageFragmentRoot[accumulatedRoots.size()];
333 // accumulatedRoots.copyInto(pkgFragmentRoots);
334 // } catch (JavaModelException e) {
335 // pkgFragmentRoots = new IPackageFragmentRoot[] {};
338 // addClasspathDeltas(pkgFragmentRoots, IJavaElementDelta.F_REMOVED_FROM_CLASSPATH, delta);
340 // int changeKind = oldResolvedPath[i].getEntryKind();
341 // needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE) || oldResolvedPath[i].isExported();
343 // // Remove the .java files from the index for a source folder
344 // // For a lib folder or a .jar file, remove the corresponding index if not shared.
345 // if (indexManager != null) {
346 // IClasspathEntry oldEntry = oldResolvedPath[i];
347 // final IPath path = oldEntry.getPath();
348 // switch (changeKind) {
349 // case IClasspathEntry.CPE_SOURCE:
350 // final char[][] exclusionPatterns = ((ClasspathEntry)oldEntry).fullExclusionPatternChars();
351 // postAction(new IPostAction() {
352 // public String getID() {
353 // return path.toString();
355 // public void run() throws JavaModelException {
356 // indexManager.removeSourceFolderFromIndex(project, path, exclusionPatterns);
359 // REMOVEALL_APPEND);
361 // case IClasspathEntry.CPE_LIBRARY:
362 // final DeltaProcessor deltaProcessor = manager.deltaProcessor;
363 // postAction(new IPostAction() {
364 // public String getID() {
365 // return path.toString();
367 // public void run() throws JavaModelException {
368 // if (deltaProcessor.otherRoots.get(path) == null) { // if root was not shared
369 // indexManager.discardJobs(path.toString());
370 // indexManager.removeIndex(path);
371 // // TODO: we could just remove the in-memory index and have the indexing check for timestamps
375 // REMOVEALL_APPEND);
382 // // do not notify remote project changes
383 // if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
384 // this.needCycleCheck |= (oldResolvedPath[i].isExported() != newResolvedPath[index].isExported());
387 // needToUpdateDependents |= (oldResolvedPath[i].isExported() != newResolvedPath[index].isExported());
388 // if (index != i) { //reordering of the classpath
389 // addClasspathDeltas(
390 // project.computePackageFragmentRoots(oldResolvedPath[i]),
391 // IJavaElementDelta.F_REORDER,
393 // int changeKind = oldResolvedPath[i].getEntryKind();
394 // needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE);
399 // // check source attachment
400 // IPath newSourcePath = newResolvedPath[index].getSourceAttachmentPath();
401 // int sourceAttachmentFlags =
402 // this.getSourceAttachmentDeltaFlag(
403 // oldResolvedPath[i].getSourceAttachmentPath(),
405 // null/*not a source root path*/);
406 // int sourceAttachmentRootFlags =
407 // this.getSourceAttachmentDeltaFlag(
408 // oldResolvedPath[i].getSourceAttachmentRootPath(),
409 // newResolvedPath[index].getSourceAttachmentRootPath(),
410 // newSourcePath/*in case both root paths are null*/);
411 // int flags = sourceAttachmentFlags | sourceAttachmentRootFlags;
413 // addClasspathDeltas(
414 // project.computePackageFragmentRoots(oldResolvedPath[i]),
422 // for (int i = 0; i < newLength; i++) {
424 // int index = classpathContains(oldResolvedPath, newResolvedPath[i]);
425 // if (index == -1) {
426 // // do not notify remote project changes
427 // if (newResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
428 // needToUpdateDependents = true;
429 // this.needCycleCheck = true;
432 // addClasspathDeltas(
433 // project.computePackageFragmentRoots(newResolvedPath[i]),
434 // IJavaElementDelta.F_ADDED_TO_CLASSPATH,
436 // int changeKind = newResolvedPath[i].getEntryKind();
438 // // Request indexing
439 // if (indexManager != null) {
440 // switch (changeKind) {
441 // case IClasspathEntry.CPE_LIBRARY:
442 // boolean pathHasChanged = true;
443 // final IPath newPath = newResolvedPath[i].getPath();
444 // for (int j = 0; j < oldLength; j++) {
445 // IClasspathEntry oldEntry = oldResolvedPath[j];
446 // if (oldEntry.getPath().equals(newPath)) {
447 // pathHasChanged = false;
451 // if (pathHasChanged) {
452 // postAction(new IPostAction() {
453 // public String getID() {
454 // return newPath.toString();
456 // public void run() throws JavaModelException {
457 // indexManager.indexLibrary(newPath, project.getProject());
460 // REMOVEALL_APPEND);
463 // case IClasspathEntry.CPE_SOURCE:
464 // IClasspathEntry entry = newResolvedPath[i];
465 // final IPath path = entry.getPath();
466 // final char[][] exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
467 // postAction(new IPostAction() {
468 // public String getID() {
469 // return path.toString();
471 // public void run() throws JavaModelException {
472 // indexManager.indexSourceFolder(project, path, exclusionPatterns);
475 // APPEND); // append so that a removeSourceFolder action is not removed
480 // needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE) || newResolvedPath[i].isExported();
483 // } // classpath reordering has already been generated in previous loop
487 // this.addDelta(delta);
489 // if (needToUpdateDependents){
490 // updateAffectedProjects(project.getProject().getFullPath());
494 protected JavaProject getProject() {
495 return ((JavaProject) getElementsToProcess()[0]);
499 * Returns the source attachment flag for the delta between the 2 give source paths.
500 * Returns either F_SOURCEATTACHED, F_SOURCEDETACHED, F_SOURCEATTACHED | F_SOURCEDETACHED
501 * or 0 if there is no difference.
503 private int getSourceAttachmentDeltaFlag(IPath oldPath, IPath newPath, IPath sourcePath) {
504 if (oldPath == null) {
505 if (newPath != null) {
506 return IJavaElementDelta.F_SOURCEATTACHED;
508 if (sourcePath != null) {
509 // if source path is specified and no root path, it needs to be recomputed dynamically
510 return IJavaElementDelta.F_SOURCEATTACHED | IJavaElementDelta.F_SOURCEDETACHED;
515 } else if (newPath == null) {
516 return IJavaElementDelta.F_SOURCEDETACHED;
517 } else if (!oldPath.equals(newPath)) {
518 return IJavaElementDelta.F_SOURCEATTACHED | IJavaElementDelta.F_SOURCEDETACHED;
525 * Returns <code>true</code> if this operation performs no resource modifications,
526 * otherwise <code>false</code>. Subclasses must override.
528 public boolean isReadOnly() {
529 return !this.canChangeResource;
532 protected void saveClasspathIfNecessary() throws JavaModelException {
534 if (!this.canChangeResource || !this.needSave) return;
536 IClasspathEntry[] classpathForSave;
537 JavaProject project = getProject();
538 if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath){
539 classpathForSave = project.getRawClasspath();
541 classpathForSave = this.newRawPath;
543 IPath outputLocationForSave;
544 if (this.newOutputLocation == ReuseOutputLocation){
545 outputLocationForSave = project.getOutputLocation();
547 outputLocationForSave = this.newOutputLocation;
549 // if read-only .classpath, then the classpath setting will never been performed completely
550 if (project.saveClasspath(classpathForSave, outputLocationForSave)) {
551 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
555 public String toString(){
556 StringBuffer buffer = new StringBuffer(20);
557 buffer.append("SetClasspathOperation\n"); //$NON-NLS-1$
558 buffer.append(" - classpath : "); //$NON-NLS-1$
559 if (this.newRawPath == ReuseClasspath){
560 buffer.append("<Reuse Existing Classpath>"); //$NON-NLS-1$
562 buffer.append("{"); //$NON-NLS-1$
563 for (int i = 0; i < this.newRawPath.length; i++) {
564 if (i > 0) buffer.append(","); //$NON-NLS-1$
565 IClasspathEntry element = this.newRawPath[i];
566 buffer.append(" ").append(element.toString()); //$NON-NLS-1$
569 buffer.append("\n - output location : "); //$NON-NLS-1$
570 if (this.newOutputLocation == ReuseOutputLocation){
571 buffer.append("<Reuse Existing Output Location>"); //$NON-NLS-1$
573 buffer.append(this.newOutputLocation.toString()); //$NON-NLS-1$
575 return buffer.toString();
578 private void updateClasspath() throws JavaModelException {
580 JavaProject project = ((JavaProject) getElementsToProcess()[0]);
582 beginTask(Util.bind("classpath.settingProgress", project.getElementName()), 2); //$NON-NLS-1$
584 // SIDE-EFFECT: from thereon, the classpath got modified
585 project.setRawClasspath0(this.newRawPath);
587 // resolve new path (asking for marker creation if problems)
588 if (this.newResolvedPath == null) {
589 this.newResolvedPath = project.getResolvedClasspath(true, this.canChangeResource);
592 // if (this.oldResolvedPath != null) {
593 // generateClasspathChangeDeltas(
594 // this.oldResolvedPath,
595 // this.newResolvedPath,
598 this.needCycleCheck = true;
599 updateAffectedProjects(project.getProject().getFullPath());
602 updateCycleMarkersIfNecessary(newResolvedPath);
606 * Update projects which are affected by this classpath change:
607 * those which refers to the current project as source
609 protected void updateAffectedProjects(IPath prerequisiteProjectPath) {
612 IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
613 IJavaProject originatingProject = getProject();
614 IJavaProject[] projects = model.getJavaProjects();
615 for (int i = 0, projectCount = projects.length; i < projectCount; i++) {
617 JavaProject project = (JavaProject) projects[i];
618 if (project.equals(originatingProject)) continue; // skip itself
620 // consider ALL dependents (even indirect ones), since they may need to
621 // flush their respective namelookup caches (all pkg fragment roots).
623 IClasspathEntry[] classpath = project.getExpandedClasspath(true);
624 for (int j = 0, entryCount = classpath.length; j < entryCount; j++) {
625 IClasspathEntry entry = classpath[j];
626 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
627 && entry.getPath().equals(prerequisiteProjectPath)) {
628 project.setRawClasspath(
630 SetClasspathOperation.ReuseOutputLocation,
632 this.canChangeResource,
633 project.getResolvedClasspath(true),
634 false, // updating only - no validation
635 false); // updating only - no need to save
639 } catch (JavaModelException e) {
642 } catch (JavaModelException e) {
648 * Update cycle markers
650 protected void updateCycleMarkersIfNecessary(IClasspathEntry[] newResolvedPath) {
652 if (!this.needCycleCheck) return;
653 if (!this.canChangeResource) return;
656 JavaProject project = getProject();
657 if (!project.hasCycleMarker() && !project.hasClasspathCycle(project.getResolvedClasspath(true))){
663 public String getID() {
664 return "updateCycleMarkers"; //$NON-NLS-1$
666 public void run() throws JavaModelException {
667 JavaProject.updateAllCycleMarkers();
671 } catch(JavaModelException e){
676 * Sets the output location of the pre-specified project.
678 * <p>This can cause changes in package fragments, in case either the
679 * old or new output location folder are considered as a package fragment.
681 protected void updateOutputLocation() throws JavaModelException {
683 JavaProject project= ((JavaProject) getElementsToProcess()[0]);
685 beginTask(Util.bind("classpath.settingOutputLocationProgress", project.getElementName()), 2); //$NON-NLS-1$
687 IPath oldLocation= project.getOutputLocation();
689 // see if this will cause any package fragments to be added
690 boolean deltaToFire= false;
691 JavaElementDelta delta = newJavaElementDelta();
692 // ArrayList added= determineAffectedPackageFragments(oldLocation);
693 // Iterator iter = added.iterator();
694 // while (iter.hasNext()){
695 // IPackageFragment frag= (IPackageFragment)iter.next();
696 // ((IPackageFragmentRoot)frag.getParent()).close();
697 // if (!Util.isExcluded(frag)) {
698 // delta.added(frag);
699 // deltaToFire = true;
703 // see if this will cause any package fragments to be removed
704 // ArrayList removed= determineAffectedPackageFragments(this.newOutputLocation);
705 // iter = removed.iterator();
706 // while (iter.hasNext()){
707 // IPackageFragment frag= (IPackageFragment)iter.next();
708 // ((IPackageFragmentRoot)frag.getParent()).close();
709 // if (!Util.isExcluded(frag)) {
710 // delta.removed(frag);
711 // deltaToFire = true;
715 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
716 synchronized (perProjectInfo) {
717 perProjectInfo.outputLocation = this.newOutputLocation;
727 * Update projects references so that the build order is consistent with the classpath
729 protected void updateProjectReferencesIfNecessary() throws JavaModelException {
731 if (!this.canChangeResource) return;
732 if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath) return;
734 JavaProject jproject = getProject();
735 String[] oldRequired = jproject.projectPrerequisites(this.oldResolvedPath);
737 if (this.newResolvedPath == null) {
738 this.newResolvedPath = jproject.getResolvedClasspath(this.newRawPath, null, true, this.needValidation, null /*no reverse map*/);
740 String[] newRequired = jproject.projectPrerequisites(this.newResolvedPath);
743 IProject project = jproject.getProject();
744 IProjectDescription description = project.getDescription();
746 IProject[] projectReferences = description.getReferencedProjects();
748 HashSet oldReferences = new HashSet(projectReferences.length);
749 for (int i = 0; i < projectReferences.length; i++){
750 String projectName = projectReferences[i].getName();
751 oldReferences.add(projectName);
753 HashSet newReferences = (HashSet)oldReferences.clone();
755 for (int i = 0; i < oldRequired.length; i++){
756 String projectName = oldRequired[i];
757 newReferences.remove(projectName);
759 for (int i = 0; i < newRequired.length; i++){
760 String projectName = newRequired[i];
761 newReferences.add(projectName);
765 int newSize = newReferences.size();
768 if (oldReferences.size() == newSize){
769 iter = newReferences.iterator();
770 while (iter.hasNext()){
771 if (!oldReferences.contains(iter.next())){
778 String[] requiredProjectNames = new String[newSize];
780 iter = newReferences.iterator();
781 while (iter.hasNext()){
782 requiredProjectNames[index++] = (String)iter.next();
784 Util.sort(requiredProjectNames); // ensure that if changed, the order is consistent
786 IProject[] requiredProjectArray = new IProject[newSize];
787 IWorkspaceRoot wksRoot = project.getWorkspace().getRoot();
788 for (int i = 0; i < newSize; i++){
789 requiredProjectArray[i] = wksRoot.getProject(requiredProjectNames[i]);
792 description.setReferencedProjects(requiredProjectArray);
793 project.setDescription(description, this.fMonitor);
795 } catch(CoreException e){
796 throw new JavaModelException(e);
800 public IJavaModelStatus verify() {
802 IJavaModelStatus status = super.verify();
803 if (!status.isOK()) {
807 if (needValidation) {
808 IJavaProject project = (IJavaProject) getElementToProcess();
809 // retrieve classpath
810 IClasspathEntry[] entries = this.newRawPath;
811 if (entries == ReuseClasspath){
813 entries = project.getRawClasspath();
814 } catch (JavaModelException e) {
815 return e.getJavaModelStatus();
818 // retrieve output location
819 IPath outputLocation = this.newOutputLocation;
820 if (outputLocation == ReuseOutputLocation){
822 outputLocation = project.getOutputLocation();
823 } catch (JavaModelException e) {
824 return e.getJavaModelStatus();
828 // perform validation
829 // return JavaConventions.validateClasspath(
835 return JavaModelStatus.VERIFIED_OK;