1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
13 import java.util.ArrayList;
14 import java.util.HashSet;
15 import java.util.Iterator;
17 import net.sourceforge.phpdt.core.IClasspathEntry;
18 import net.sourceforge.phpdt.core.IJavaElement;
19 import net.sourceforge.phpdt.core.IJavaElementDelta;
20 import net.sourceforge.phpdt.core.IJavaModel;
21 import net.sourceforge.phpdt.core.IJavaModelStatus;
22 import net.sourceforge.phpdt.core.IJavaProject;
23 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
24 import net.sourceforge.phpdt.core.JavaModelException;
25 import net.sourceforge.phpdt.internal.core.util.Util;
27 import org.eclipse.core.resources.IFolder;
28 import org.eclipse.core.resources.IProject;
29 import org.eclipse.core.resources.IProjectDescription;
30 import org.eclipse.core.resources.IResource;
31 import org.eclipse.core.resources.IWorkspaceRoot;
32 import org.eclipse.core.runtime.CoreException;
33 import org.eclipse.core.runtime.IPath;
34 import org.eclipse.core.runtime.Path;
37 * This operation sets an <code>IJavaProject</code>'s classpath.
41 public class SetClasspathOperation extends JavaModelOperation {
43 IClasspathEntry[] oldResolvedPath, newResolvedPath;
44 IClasspathEntry[] newRawPath;
45 boolean canChangeResources;
46 boolean needCycleCheck;
47 boolean needValidation;
49 IPath newOutputLocation;
51 boolean identicalRoots;
53 public static final IClasspathEntry[] ReuseClasspath = new IClasspathEntry[0];
54 public static final IClasspathEntry[] UpdateClasspath = new IClasspathEntry[0];
55 // if reusing output location, then also reuse clean flag
56 public static final IPath ReuseOutputLocation = new Path("Reuse Existing Output Location"); //$NON-NLS-1$
59 * When executed, this operation sets the classpath of the given project.
61 public SetClasspathOperation(
63 IClasspathEntry[] oldResolvedPath,
64 IClasspathEntry[] newRawPath,
65 IPath newOutputLocation,
66 boolean canChangeResource,
67 boolean needValidation,
70 super(new IJavaElement[] { project });
71 this.oldResolvedPath = oldResolvedPath;
72 this.newRawPath = newRawPath;
73 this.newOutputLocation = newOutputLocation;
74 this.canChangeResources = canChangeResource;
75 this.needValidation = needValidation;
76 this.needSave = needSave;
77 this.project = project;
81 * Adds deltas for the given roots, with the specified change flag,
82 * and closes the root. Helper method for #setClasspath
84 protected void addClasspathDeltas(
85 IPackageFragmentRoot[] roots,
87 JavaElementDelta delta) {
89 for (int i = 0; i < roots.length; i++) {
90 IPackageFragmentRoot root = roots[i];
91 delta.changed(root, flag);
92 if ((flag & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0
93 || (flag & IJavaElementDelta.F_SOURCEATTACHED) != 0
94 || (flag & IJavaElementDelta.F_SOURCEDETACHED) != 0){
97 } catch (JavaModelException e) {
99 // force detach source on jar package fragment roots (source will be lazily computed when needed)
100 ((PackageFragmentRoot) root).setSourceAttachmentProperty(null);// loose info - will be recomputed
108 * Returns the index of the item in the list if the given list contains the specified entry. If the list does
109 * not contain the entry, -1 is returned.
110 * A helper method for #setClasspath
112 protected int classpathContains(
113 IClasspathEntry[] list,
114 IClasspathEntry entry) {
116 IPath[] exclusionPatterns = entry.getExclusionPatterns();
117 nextEntry: for (int i = 0; i < list.length; i++) {
118 IClasspathEntry other = list[i];
119 if (other.getContentKind() == entry.getContentKind()
120 && other.getEntryKind() == entry.getEntryKind()
121 && other.isExported() == entry.isExported()
122 && other.getPath().equals(entry.getPath())) {
123 // check custom outputs
124 IPath entryOutput = entry.getOutputLocation();
125 IPath otherOutput = other.getOutputLocation();
126 if (entryOutput == null) {
127 if (otherOutput != null)
130 if (!entryOutput.equals(otherOutput))
134 // check exclusion patterns
135 IPath[] otherExcludes = other.getExclusionPatterns();
136 if (exclusionPatterns != otherExcludes) {
137 int excludeLength = exclusionPatterns.length;
138 if (otherExcludes.length != excludeLength)
140 for (int j = 0; j < excludeLength; j++) {
141 // compare toStrings instead of IPaths
142 // since IPath.equals is specified to ignore trailing separators
143 if (!exclusionPatterns[j].toString().equals(otherExcludes[j].toString()))
154 * Recursively adds all subfolders of <code>folder</code> to the given collection.
156 protected void collectAllSubfolders(IFolder folder, ArrayList collection) throws JavaModelException {
158 IResource[] members= folder.members();
159 for (int i = 0, max = members.length; i < max; i++) {
160 IResource r= members[i];
161 if (r.getType() == IResource.FOLDER) {
163 collectAllSubfolders((IFolder)r, collection);
166 } catch (CoreException e) {
167 throw new JavaModelException(e);
172 * Returns a collection of package fragments that have been added/removed
173 * as the result of changing the output location to/from the given
174 * location. The collection is empty if no package fragments are
177 // protected ArrayList determineAffectedPackageFragments(IPath location) throws JavaModelException {
178 // ArrayList fragments = new ArrayList();
179 // JavaProject project =getProject();
181 // // see if this will cause any package fragments to be affected
182 // IWorkspace workspace = ResourcesPlugin.getWorkspace();
183 // IResource resource = null;
184 // if (location != null) {
185 // resource = workspace.getRoot().findMember(location);
187 // if (resource != null && resource.getType() == IResource.FOLDER) {
188 // IFolder folder = (IFolder) resource;
189 // // only changes if it actually existed
190 // IClasspathEntry[] classpath = project.getExpandedClasspath(true);
191 // for (int i = 0; i < classpath.length; i++) {
192 // IClasspathEntry entry = classpath[i];
193 // IPath path = classpath[i].getPath();
194 // if (entry.getEntryKind() != IClasspathEntry.CPE_PROJECT && path.isPrefixOf(location) && !path.equals(location)) {
195 // IPackageFragmentRoot[] roots = project.computePackageFragmentRoots(classpath[i]);
196 // IPackageFragmentRoot root = roots[0];
197 // // now the output location becomes a package fragment - along with any subfolders
198 // ArrayList folders = new ArrayList();
199 // folders.add(folder);
200 // collectAllSubfolders(folder, folders);
201 // Iterator elements = folders.iterator();
202 // int segments = path.segmentCount();
203 // while (elements.hasNext()) {
204 // IFolder f = (IFolder) elements.next();
205 // IPath relativePath = f.getFullPath().removeFirstSegments(segments);
206 // String name = relativePath.toOSString();
207 // name = name.replace(File.pathSeparatorChar, '.');
208 // if (name.endsWith(".")) { //$NON-NLS-1$
209 // name = name.substring(0, name.length() - 1);
211 // IPackageFragment pkg = root.getPackageFragment(name);
212 // fragments.add(pkg);
220 * Sets the classpath of the pre-specified project.
222 protected void executeOperation() throws JavaModelException {
223 // project reference updated - may throw an exception if unable to write .project file
224 updateProjectReferencesIfNecessary();
226 // classpath file updated - may throw an exception if unable to write .classpath file
227 saveClasspathIfNecessary();
229 // perform classpath and output location updates, if exception occurs in classpath update,
230 // make sure the output location is updated before surfacing the exception (in case the output
231 // location update also throws an exception, give priority to the classpath update one).
232 JavaModelException originalException = null;
235 if (this.newRawPath == UpdateClasspath) this.newRawPath = project.getRawClasspath();
236 if (this.newRawPath != ReuseClasspath){
238 project.updatePackageFragmentRoots();
239 JavaModelManager.getJavaModelManager().getDeltaProcessor().addForRefresh(project);
242 } catch(JavaModelException e){
243 originalException = e;
246 } finally { // if traversed by an exception we still need to update the output location when necessary
249 if (this.newOutputLocation != ReuseOutputLocation) updateOutputLocation();
251 } catch(JavaModelException e){
252 if (originalException != null) throw originalException;
255 // ensures the project is getting rebuilt if only variable is modified
256 if (!this.identicalRoots && this.canChangeResources) {
258 this.project.getProject().touch(this.progressMonitor);
259 } catch (CoreException e) {
260 if (JavaModelManager.CP_RESOLVE_VERBOSE){
261 Util.verbose("CPContainer INIT - FAILED to touch project: "+ this.project.getElementName(), System.err); //$NON-NLS-1$
272 * Generates the delta of removed/added/reordered roots.
273 * Use three deltas in case the same root is removed/added/reordered (for
274 * instance, if it is changed from K_SOURCE to K_BINARY or vice versa)
276 // protected void generateClasspathChangeDeltas(
277 // IClasspathEntry[] oldResolvedPath,
278 // IClasspathEntry[] newResolvedPath,
279 // final JavaProject project) {
281 // JavaModelManager manager = JavaModelManager.getJavaModelManager();
282 // boolean needToUpdateDependents = false;
283 // JavaElementDelta delta = new JavaElementDelta(getJavaModel());
284 // boolean hasDelta = false;
285 // int oldLength = oldResolvedPath.length;
286 // int newLength = newResolvedPath.length;
288 // final IndexManager indexManager = manager.getIndexManager();
289 // Map oldRoots = null;
290 // IPackageFragmentRoot[] roots = null;
291 // if (project.isOpen()) {
293 // roots = project.getPackageFragmentRoots();
294 // } catch (JavaModelException e) {
297 // Map allRemovedRoots ;
298 // if ((allRemovedRoots = manager.deltaProcessor.removedRoots) != null) {
299 // roots = (IPackageFragmentRoot[]) allRemovedRoots.get(project);
302 // if (roots != null) {
303 // oldRoots = new HashMap();
304 // for (int i = 0; i < roots.length; i++) {
305 // IPackageFragmentRoot root = roots[i];
306 // oldRoots.put(root.getPath(), root);
309 // for (int i = 0; i < oldLength; i++) {
311 // int index = classpathContains(newResolvedPath, oldResolvedPath[i]);
312 // if (index == -1) {
313 // // do not notify remote project changes
314 // if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
315 // needToUpdateDependents = true;
316 // this.needCycleCheck = true;
320 // IPackageFragmentRoot[] pkgFragmentRoots = null;
321 // if (oldRoots != null) {
322 // IPackageFragmentRoot oldRoot = (IPackageFragmentRoot) oldRoots.get(oldResolvedPath[i].getPath());
323 // if (oldRoot != null) { // use old root if any (could be none if entry wasn't bound)
324 // pkgFragmentRoots = new IPackageFragmentRoot[] { oldRoot };
327 // if (pkgFragmentRoots == null) {
329 // ObjectVector accumulatedRoots = new ObjectVector();
330 // HashSet rootIDs = new HashSet(5);
331 // rootIDs.add(project.rootID());
332 // project.computePackageFragmentRoots(
333 // oldResolvedPath[i],
336 // true, // inside original project
337 // false, // don't check existency
338 // false); // don't retrieve exported roots
339 // pkgFragmentRoots = new IPackageFragmentRoot[accumulatedRoots.size()];
340 // accumulatedRoots.copyInto(pkgFragmentRoots);
341 // } catch (JavaModelException e) {
342 // pkgFragmentRoots = new IPackageFragmentRoot[] {};
345 // addClasspathDeltas(pkgFragmentRoots, IJavaElementDelta.F_REMOVED_FROM_CLASSPATH, delta);
347 // int changeKind = oldResolvedPath[i].getEntryKind();
348 // needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE) || oldResolvedPath[i].isExported();
350 // // Remove the .java files from the index for a source folder
351 // // For a lib folder or a .jar file, remove the corresponding index if not shared.
352 // if (indexManager != null) {
353 // IClasspathEntry oldEntry = oldResolvedPath[i];
354 // final IPath path = oldEntry.getPath();
355 // switch (changeKind) {
356 // case IClasspathEntry.CPE_SOURCE:
357 // final char[][] exclusionPatterns = ((ClasspathEntry)oldEntry).fullExclusionPatternChars();
358 // postAction(new IPostAction() {
359 // public String getID() {
360 // return path.toString();
362 // public void run() throws JavaModelException {
363 // indexManager.removeSourceFolderFromIndex(project, path, exclusionPatterns);
366 // REMOVEALL_APPEND);
368 // case IClasspathEntry.CPE_LIBRARY:
369 // final DeltaProcessor deltaProcessor = manager.deltaProcessor;
370 // postAction(new IPostAction() {
371 // public String getID() {
372 // return path.toString();
374 // public void run() throws JavaModelException {
375 // if (deltaProcessor.otherRoots.get(path) == null) { // if root was not shared
376 // indexManager.discardJobs(path.toString());
377 // indexManager.removeIndex(path);
378 // // TODO: we could just remove the in-memory index and have the indexing check for timestamps
382 // REMOVEALL_APPEND);
389 // // do not notify remote project changes
390 // if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
391 // this.needCycleCheck |= (oldResolvedPath[i].isExported() != newResolvedPath[index].isExported());
394 // needToUpdateDependents |= (oldResolvedPath[i].isExported() != newResolvedPath[index].isExported());
395 // if (index != i) { //reordering of the classpath
396 // addClasspathDeltas(
397 // project.computePackageFragmentRoots(oldResolvedPath[i]),
398 // IJavaElementDelta.F_REORDER,
400 // int changeKind = oldResolvedPath[i].getEntryKind();
401 // needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE);
406 // // check source attachment
407 // IPath newSourcePath = newResolvedPath[index].getSourceAttachmentPath();
408 // int sourceAttachmentFlags =
409 // this.getSourceAttachmentDeltaFlag(
410 // oldResolvedPath[i].getSourceAttachmentPath(),
412 // null/*not a source root path*/);
413 // int sourceAttachmentRootFlags =
414 // this.getSourceAttachmentDeltaFlag(
415 // oldResolvedPath[i].getSourceAttachmentRootPath(),
416 // newResolvedPath[index].getSourceAttachmentRootPath(),
417 // newSourcePath/*in case both root paths are null*/);
418 // int flags = sourceAttachmentFlags | sourceAttachmentRootFlags;
420 // addClasspathDeltas(
421 // project.computePackageFragmentRoots(oldResolvedPath[i]),
429 // for (int i = 0; i < newLength; i++) {
431 // int index = classpathContains(oldResolvedPath, newResolvedPath[i]);
432 // if (index == -1) {
433 // // do not notify remote project changes
434 // if (newResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
435 // needToUpdateDependents = true;
436 // this.needCycleCheck = true;
439 // addClasspathDeltas(
440 // project.computePackageFragmentRoots(newResolvedPath[i]),
441 // IJavaElementDelta.F_ADDED_TO_CLASSPATH,
443 // int changeKind = newResolvedPath[i].getEntryKind();
445 // // Request indexing
446 // if (indexManager != null) {
447 // switch (changeKind) {
448 // case IClasspathEntry.CPE_LIBRARY:
449 // boolean pathHasChanged = true;
450 // final IPath newPath = newResolvedPath[i].getPath();
451 // for (int j = 0; j < oldLength; j++) {
452 // IClasspathEntry oldEntry = oldResolvedPath[j];
453 // if (oldEntry.getPath().equals(newPath)) {
454 // pathHasChanged = false;
458 // if (pathHasChanged) {
459 // postAction(new IPostAction() {
460 // public String getID() {
461 // return newPath.toString();
463 // public void run() throws JavaModelException {
464 // indexManager.indexLibrary(newPath, project.getProject());
467 // REMOVEALL_APPEND);
470 // case IClasspathEntry.CPE_SOURCE:
471 // IClasspathEntry entry = newResolvedPath[i];
472 // final IPath path = entry.getPath();
473 // final char[][] exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
474 // postAction(new IPostAction() {
475 // public String getID() {
476 // return path.toString();
478 // public void run() throws JavaModelException {
479 // indexManager.indexSourceFolder(project, path, exclusionPatterns);
482 // APPEND); // append so that a removeSourceFolder action is not removed
487 // needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE) || newResolvedPath[i].isExported();
490 // } // classpath reordering has already been generated in previous loop
494 // this.addDelta(delta);
496 // if (needToUpdateDependents){
497 // updateAffectedProjects(project.getProject().getFullPath());
501 protected JavaProject getProject() {
502 return ((JavaProject) getElementsToProcess()[0]);
506 * Returns the source attachment flag for the delta between the 2 give source paths.
507 * Returns either F_SOURCEATTACHED, F_SOURCEDETACHED, F_SOURCEATTACHED | F_SOURCEDETACHED
508 * or 0 if there is no difference.
510 private int getSourceAttachmentDeltaFlag(IPath oldPath, IPath newPath, IPath sourcePath) {
511 if (oldPath == null) {
512 if (newPath != null) {
513 return IJavaElementDelta.F_SOURCEATTACHED;
515 if (sourcePath != null) {
516 // if source path is specified and no root path, it needs to be recomputed dynamically
517 return IJavaElementDelta.F_SOURCEATTACHED | IJavaElementDelta.F_SOURCEDETACHED;
522 } else if (newPath == null) {
523 return IJavaElementDelta.F_SOURCEDETACHED;
524 } else if (!oldPath.equals(newPath)) {
525 return IJavaElementDelta.F_SOURCEATTACHED | IJavaElementDelta.F_SOURCEDETACHED;
532 * Returns <code>true</code> if this operation performs no resource modifications,
533 * otherwise <code>false</code>. Subclasses must override.
535 public boolean isReadOnly() {
536 return !this.canChangeResources;
539 protected void saveClasspathIfNecessary() throws JavaModelException {
541 if (!this.canChangeResources || !this.needSave) return;
543 IClasspathEntry[] classpathForSave;
544 JavaProject project = getProject();
545 if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath){
546 classpathForSave = project.getRawClasspath();
548 classpathForSave = this.newRawPath;
550 IPath outputLocationForSave;
551 if (this.newOutputLocation == ReuseOutputLocation){
552 outputLocationForSave = project.getOutputLocation();
554 outputLocationForSave = this.newOutputLocation;
556 // if read-only .classpath, then the classpath setting will never been performed completely
557 if (project.saveClasspath(classpathForSave, outputLocationForSave)) {
558 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
562 public String toString(){
563 StringBuffer buffer = new StringBuffer(20);
564 buffer.append("SetClasspathOperation\n"); //$NON-NLS-1$
565 buffer.append(" - classpath : "); //$NON-NLS-1$
566 if (this.newRawPath == ReuseClasspath){
567 buffer.append("<Reuse Existing Classpath>"); //$NON-NLS-1$
569 buffer.append("{"); //$NON-NLS-1$
570 for (int i = 0; i < this.newRawPath.length; i++) {
571 if (i > 0) buffer.append(","); //$NON-NLS-1$
572 IClasspathEntry element = this.newRawPath[i];
573 buffer.append(" ").append(element.toString()); //$NON-NLS-1$
576 buffer.append("\n - output location : "); //$NON-NLS-1$
577 if (this.newOutputLocation == ReuseOutputLocation){
578 buffer.append("<Reuse Existing Output Location>"); //$NON-NLS-1$
580 buffer.append(this.newOutputLocation.toString()); //$NON-NLS-1$
582 return buffer.toString();
585 private void updateClasspath() throws JavaModelException {
587 JavaProject project = ((JavaProject) getElementsToProcess()[0]);
589 beginTask(Util.bind("classpath.settingProgress", project.getElementName()), 2); //$NON-NLS-1$
591 // SIDE-EFFECT: from thereon, the classpath got modified
592 project.setRawClasspath0(this.newRawPath);
594 // resolve new path (asking for marker creation if problems)
595 if (this.newResolvedPath == null) {
596 this.newResolvedPath = project.getResolvedClasspath(true, this.canChangeResources);
599 // if (this.oldResolvedPath != null) {
600 // generateClasspathChangeDeltas(
601 // this.oldResolvedPath,
602 // this.newResolvedPath,
605 this.needCycleCheck = true;
606 updateAffectedProjects(project.getProject().getFullPath());
609 updateCycleMarkersIfNecessary(newResolvedPath);
613 * Update projects which are affected by this classpath change:
614 * those which refers to the current project as source
616 protected void updateAffectedProjects(IPath prerequisiteProjectPath) {
619 IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
620 IJavaProject originatingProject = getProject();
621 IJavaProject[] projects = model.getJavaProjects();
622 for (int i = 0, projectCount = projects.length; i < projectCount; i++) {
624 JavaProject project = (JavaProject) projects[i];
625 if (project.equals(originatingProject)) continue; // skip itself
627 // consider ALL dependents (even indirect ones), since they may need to
628 // flush their respective namelookup caches (all pkg fragment roots).
630 IClasspathEntry[] classpath = project.getExpandedClasspath(true);
631 for (int j = 0, entryCount = classpath.length; j < entryCount; j++) {
632 IClasspathEntry entry = classpath[j];
633 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
634 && entry.getPath().equals(prerequisiteProjectPath)) {
635 project.setRawClasspath(
637 SetClasspathOperation.ReuseOutputLocation,
638 this.progressMonitor,
639 this.canChangeResources,
640 project.getResolvedClasspath(true),
641 false, // updating only - no validation
642 false); // updating only - no need to save
646 } catch (JavaModelException e) {
649 } catch (JavaModelException e) {
655 * Update cycle markers
657 protected void updateCycleMarkersIfNecessary(IClasspathEntry[] newResolvedPath) {
659 if (!this.needCycleCheck) return;
660 if (!this.canChangeResources) return;
663 JavaProject project = getProject();
664 if (!project.hasCycleMarker() && !project.hasClasspathCycle(project.getResolvedClasspath(true))){
670 public String getID() {
671 return "updateCycleMarkers"; //$NON-NLS-1$
673 public void run() throws JavaModelException {
674 JavaProject.updateAllCycleMarkers();
678 } catch(JavaModelException e){
683 * Sets the output location of the pre-specified project.
685 * <p>This can cause changes in package fragments, in case either the
686 * old or new output location folder are considered as a package fragment.
688 protected void updateOutputLocation() throws JavaModelException {
690 JavaProject project= ((JavaProject) getElementsToProcess()[0]);
692 beginTask(Util.bind("classpath.settingOutputLocationProgress", project.getElementName()), 2); //$NON-NLS-1$
694 IPath oldLocation= project.getOutputLocation();
696 // see if this will cause any package fragments to be added
697 boolean deltaToFire= false;
698 JavaElementDelta delta = newJavaElementDelta();
699 // ArrayList added= determineAffectedPackageFragments(oldLocation);
700 // Iterator iter = added.iterator();
701 // while (iter.hasNext()){
702 // IPackageFragment frag= (IPackageFragment)iter.next();
703 // ((IPackageFragmentRoot)frag.getParent()).close();
704 // if (!ProjectPrefUtil.isExcluded(frag)) {
705 // delta.added(frag);
706 // deltaToFire = true;
710 // see if this will cause any package fragments to be removed
711 // ArrayList removed= determineAffectedPackageFragments(this.newOutputLocation);
712 // iter = removed.iterator();
713 // while (iter.hasNext()){
714 // IPackageFragment frag= (IPackageFragment)iter.next();
715 // ((IPackageFragmentRoot)frag.getParent()).close();
716 // if (!ProjectPrefUtil.isExcluded(frag)) {
717 // delta.removed(frag);
718 // deltaToFire = true;
722 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
723 synchronized (perProjectInfo) {
724 perProjectInfo.outputLocation = this.newOutputLocation;
734 * Update projects references so that the build order is consistent with the classpath
736 protected void updateProjectReferencesIfNecessary() throws JavaModelException {
738 if (!this.canChangeResources) return;
739 if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath) return;
741 JavaProject jproject = getProject();
742 String[] oldRequired = jproject.projectPrerequisites(this.oldResolvedPath);
744 if (this.newResolvedPath == null) {
745 this.newResolvedPath = jproject.getResolvedClasspath(this.newRawPath, null, true, this.needValidation, null /*no reverse map*/);
747 String[] newRequired = jproject.projectPrerequisites(this.newResolvedPath);
750 IProject project = jproject.getProject();
751 IProjectDescription description = project.getDescription();
753 IProject[] projectReferences = description.getReferencedProjects();
755 HashSet oldReferences = new HashSet(projectReferences.length);
756 for (int i = 0; i < projectReferences.length; i++){
757 String projectName = projectReferences[i].getName();
758 oldReferences.add(projectName);
760 HashSet newReferences = (HashSet)oldReferences.clone();
762 for (int i = 0; i < oldRequired.length; i++){
763 String projectName = oldRequired[i];
764 newReferences.remove(projectName);
766 for (int i = 0; i < newRequired.length; i++){
767 String projectName = newRequired[i];
768 newReferences.add(projectName);
772 int newSize = newReferences.size();
775 if (oldReferences.size() == newSize){
776 iter = newReferences.iterator();
777 while (iter.hasNext()){
778 if (!oldReferences.contains(iter.next())){
785 String[] requiredProjectNames = new String[newSize];
787 iter = newReferences.iterator();
788 while (iter.hasNext()){
789 requiredProjectNames[index++] = (String)iter.next();
791 Util.sort(requiredProjectNames); // ensure that if changed, the order is consistent
793 IProject[] requiredProjectArray = new IProject[newSize];
794 IWorkspaceRoot wksRoot = project.getWorkspace().getRoot();
795 for (int i = 0; i < newSize; i++){
796 requiredProjectArray[i] = wksRoot.getProject(requiredProjectNames[i]);
799 description.setReferencedProjects(requiredProjectArray);
800 project.setDescription(description, this.progressMonitor);
802 } catch(CoreException e){
803 throw new JavaModelException(e);
807 public IJavaModelStatus verify() {
809 IJavaModelStatus status = super.verify();
810 if (!status.isOK()) {
814 if (needValidation) {
815 IJavaProject project = (IJavaProject) getElementToProcess();
816 // retrieve classpath
817 IClasspathEntry[] entries = this.newRawPath;
818 if (entries == ReuseClasspath){
820 entries = project.getRawClasspath();
821 } catch (JavaModelException e) {
822 return e.getJavaModelStatus();
825 // retrieve output location
826 IPath outputLocation = this.newOutputLocation;
827 if (outputLocation == ReuseOutputLocation){
829 outputLocation = project.getOutputLocation();
830 } catch (JavaModelException e) {
831 return e.getJavaModelStatus();
835 // perform validation
836 // return JavaConventions.validateClasspath(
842 return JavaModelStatus.VERIFIED_OK;