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;
30 import net.sourceforge.phpdt.internal.core.util.Util;
32 import org.eclipse.core.resources.IFolder;
33 import org.eclipse.core.resources.IProject;
34 import org.eclipse.core.resources.IProjectDescription;
35 import org.eclipse.core.resources.IResource;
36 import org.eclipse.core.resources.IWorkspace;
37 import org.eclipse.core.resources.IWorkspaceRoot;
38 import org.eclipse.core.resources.ResourcesPlugin;
39 import org.eclipse.core.runtime.CoreException;
40 import org.eclipse.core.runtime.IPath;
41 import org.eclipse.core.runtime.Path;
42 import net.sourceforge.phpdt.internal.core.JavaModelManager;
43 import net.sourceforge.phpdt.internal.core.JavaProject;
46 * This operation sets an <code>IJavaProject</code>'s classpath.
50 public class SetClasspathOperation extends JavaModelOperation {
52 IClasspathEntry[] oldResolvedPath, newResolvedPath;
53 IClasspathEntry[] newRawPath;
54 boolean canChangeResources;
55 boolean needCycleCheck;
56 boolean needValidation;
58 IPath newOutputLocation;
60 boolean identicalRoots;
62 public static final IClasspathEntry[] ReuseClasspath = new IClasspathEntry[0];
63 public static final IClasspathEntry[] UpdateClasspath = new IClasspathEntry[0];
64 // if reusing output location, then also reuse clean flag
65 public static final IPath ReuseOutputLocation = new Path("Reuse Existing Output Location"); //$NON-NLS-1$
68 * When executed, this operation sets the classpath of the given project.
70 public SetClasspathOperation(
72 IClasspathEntry[] oldResolvedPath,
73 IClasspathEntry[] newRawPath,
74 IPath newOutputLocation,
75 boolean canChangeResource,
76 boolean needValidation,
79 super(new IJavaElement[] { project });
80 this.oldResolvedPath = oldResolvedPath;
81 this.newRawPath = newRawPath;
82 this.newOutputLocation = newOutputLocation;
83 this.canChangeResources = canChangeResource;
84 this.needValidation = needValidation;
85 this.needSave = needSave;
86 this.project = project;
90 * Adds deltas for the given roots, with the specified change flag,
91 * and closes the root. Helper method for #setClasspath
93 protected void addClasspathDeltas(
94 IPackageFragmentRoot[] roots,
96 JavaElementDelta delta) {
98 for (int i = 0; i < roots.length; i++) {
99 IPackageFragmentRoot root = roots[i];
100 delta.changed(root, flag);
101 if ((flag & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0
102 || (flag & IJavaElementDelta.F_SOURCEATTACHED) != 0
103 || (flag & IJavaElementDelta.F_SOURCEDETACHED) != 0){
106 } catch (JavaModelException e) {
108 // force detach source on jar package fragment roots (source will be lazily computed when needed)
109 ((PackageFragmentRoot) root).setSourceAttachmentProperty(null);// loose info - will be recomputed
117 * Returns the index of the item in the list if the given list contains the specified entry. If the list does
118 * not contain the entry, -1 is returned.
119 * A helper method for #setClasspath
121 protected int classpathContains(
122 IClasspathEntry[] list,
123 IClasspathEntry entry) {
125 IPath[] exclusionPatterns = entry.getExclusionPatterns();
126 nextEntry: for (int i = 0; i < list.length; i++) {
127 IClasspathEntry other = list[i];
128 if (other.getContentKind() == entry.getContentKind()
129 && other.getEntryKind() == entry.getEntryKind()
130 && other.isExported() == entry.isExported()
131 && other.getPath().equals(entry.getPath())) {
132 // check custom outputs
133 IPath entryOutput = entry.getOutputLocation();
134 IPath otherOutput = other.getOutputLocation();
135 if (entryOutput == null) {
136 if (otherOutput != null)
139 if (!entryOutput.equals(otherOutput))
143 // check exclusion patterns
144 IPath[] otherExcludes = other.getExclusionPatterns();
145 if (exclusionPatterns != otherExcludes) {
146 int excludeLength = exclusionPatterns.length;
147 if (otherExcludes.length != excludeLength)
149 for (int j = 0; j < excludeLength; j++) {
150 // compare toStrings instead of IPaths
151 // since IPath.equals is specified to ignore trailing separators
152 if (!exclusionPatterns[j].toString().equals(otherExcludes[j].toString()))
163 * Recursively adds all subfolders of <code>folder</code> to the given collection.
165 protected void collectAllSubfolders(IFolder folder, ArrayList collection) throws JavaModelException {
167 IResource[] members= folder.members();
168 for (int i = 0, max = members.length; i < max; i++) {
169 IResource r= members[i];
170 if (r.getType() == IResource.FOLDER) {
172 collectAllSubfolders((IFolder)r, collection);
175 } catch (CoreException e) {
176 throw new JavaModelException(e);
181 * Returns a collection of package fragments that have been added/removed
182 * as the result of changing the output location to/from the given
183 * location. The collection is empty if no package fragments are
186 // protected ArrayList determineAffectedPackageFragments(IPath location) throws JavaModelException {
187 // ArrayList fragments = new ArrayList();
188 // JavaProject project =getProject();
190 // // see if this will cause any package fragments to be affected
191 // IWorkspace workspace = ResourcesPlugin.getWorkspace();
192 // IResource resource = null;
193 // if (location != null) {
194 // resource = workspace.getRoot().findMember(location);
196 // if (resource != null && resource.getType() == IResource.FOLDER) {
197 // IFolder folder = (IFolder) resource;
198 // // only changes if it actually existed
199 // IClasspathEntry[] classpath = project.getExpandedClasspath(true);
200 // for (int i = 0; i < classpath.length; i++) {
201 // IClasspathEntry entry = classpath[i];
202 // IPath path = classpath[i].getPath();
203 // if (entry.getEntryKind() != IClasspathEntry.CPE_PROJECT && path.isPrefixOf(location) && !path.equals(location)) {
204 // IPackageFragmentRoot[] roots = project.computePackageFragmentRoots(classpath[i]);
205 // IPackageFragmentRoot root = roots[0];
206 // // now the output location becomes a package fragment - along with any subfolders
207 // ArrayList folders = new ArrayList();
208 // folders.add(folder);
209 // collectAllSubfolders(folder, folders);
210 // Iterator elements = folders.iterator();
211 // int segments = path.segmentCount();
212 // while (elements.hasNext()) {
213 // IFolder f = (IFolder) elements.next();
214 // IPath relativePath = f.getFullPath().removeFirstSegments(segments);
215 // String name = relativePath.toOSString();
216 // name = name.replace(File.pathSeparatorChar, '.');
217 // if (name.endsWith(".")) { //$NON-NLS-1$
218 // name = name.substring(0, name.length() - 1);
220 // IPackageFragment pkg = root.getPackageFragment(name);
221 // fragments.add(pkg);
229 * Sets the classpath of the pre-specified project.
231 protected void executeOperation() throws JavaModelException {
232 // project reference updated - may throw an exception if unable to write .project file
233 updateProjectReferencesIfNecessary();
235 // classpath file updated - may throw an exception if unable to write .classpath file
236 saveClasspathIfNecessary();
238 // perform classpath and output location updates, if exception occurs in classpath update,
239 // make sure the output location is updated before surfacing the exception (in case the output
240 // location update also throws an exception, give priority to the classpath update one).
241 JavaModelException originalException = null;
244 if (this.newRawPath == UpdateClasspath) this.newRawPath = project.getRawClasspath();
245 if (this.newRawPath != ReuseClasspath){
247 project.updatePackageFragmentRoots();
248 JavaModelManager.getJavaModelManager().getDeltaProcessor().addForRefresh(project);
251 } catch(JavaModelException e){
252 originalException = e;
255 } finally { // if traversed by an exception we still need to update the output location when necessary
258 if (this.newOutputLocation != ReuseOutputLocation) updateOutputLocation();
260 } catch(JavaModelException e){
261 if (originalException != null) throw originalException;
264 // ensures the project is getting rebuilt if only variable is modified
265 if (!this.identicalRoots && this.canChangeResources) {
267 this.project.getProject().touch(this.progressMonitor);
268 } catch (CoreException e) {
269 if (JavaModelManager.CP_RESOLVE_VERBOSE){
270 Util.verbose("CPContainer INIT - FAILED to touch project: "+ this.project.getElementName(), System.err); //$NON-NLS-1$
281 * Generates the delta of removed/added/reordered roots.
282 * Use three deltas in case the same root is removed/added/reordered (for
283 * instance, if it is changed from K_SOURCE to K_BINARY or vice versa)
285 // protected void generateClasspathChangeDeltas(
286 // IClasspathEntry[] oldResolvedPath,
287 // IClasspathEntry[] newResolvedPath,
288 // final JavaProject project) {
290 // JavaModelManager manager = JavaModelManager.getJavaModelManager();
291 // boolean needToUpdateDependents = false;
292 // JavaElementDelta delta = new JavaElementDelta(getJavaModel());
293 // boolean hasDelta = false;
294 // int oldLength = oldResolvedPath.length;
295 // int newLength = newResolvedPath.length;
297 // final IndexManager indexManager = manager.getIndexManager();
298 // Map oldRoots = null;
299 // IPackageFragmentRoot[] roots = null;
300 // if (project.isOpen()) {
302 // roots = project.getPackageFragmentRoots();
303 // } catch (JavaModelException e) {
306 // Map allRemovedRoots ;
307 // if ((allRemovedRoots = manager.deltaProcessor.removedRoots) != null) {
308 // roots = (IPackageFragmentRoot[]) allRemovedRoots.get(project);
311 // if (roots != null) {
312 // oldRoots = new HashMap();
313 // for (int i = 0; i < roots.length; i++) {
314 // IPackageFragmentRoot root = roots[i];
315 // oldRoots.put(root.getPath(), root);
318 // for (int i = 0; i < oldLength; i++) {
320 // int index = classpathContains(newResolvedPath, oldResolvedPath[i]);
321 // if (index == -1) {
322 // // do not notify remote project changes
323 // if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
324 // needToUpdateDependents = true;
325 // this.needCycleCheck = true;
329 // IPackageFragmentRoot[] pkgFragmentRoots = null;
330 // if (oldRoots != null) {
331 // IPackageFragmentRoot oldRoot = (IPackageFragmentRoot) oldRoots.get(oldResolvedPath[i].getPath());
332 // if (oldRoot != null) { // use old root if any (could be none if entry wasn't bound)
333 // pkgFragmentRoots = new IPackageFragmentRoot[] { oldRoot };
336 // if (pkgFragmentRoots == null) {
338 // ObjectVector accumulatedRoots = new ObjectVector();
339 // HashSet rootIDs = new HashSet(5);
340 // rootIDs.add(project.rootID());
341 // project.computePackageFragmentRoots(
342 // oldResolvedPath[i],
345 // true, // inside original project
346 // false, // don't check existency
347 // false); // don't retrieve exported roots
348 // pkgFragmentRoots = new IPackageFragmentRoot[accumulatedRoots.size()];
349 // accumulatedRoots.copyInto(pkgFragmentRoots);
350 // } catch (JavaModelException e) {
351 // pkgFragmentRoots = new IPackageFragmentRoot[] {};
354 // addClasspathDeltas(pkgFragmentRoots, IJavaElementDelta.F_REMOVED_FROM_CLASSPATH, delta);
356 // int changeKind = oldResolvedPath[i].getEntryKind();
357 // needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE) || oldResolvedPath[i].isExported();
359 // // Remove the .java files from the index for a source folder
360 // // For a lib folder or a .jar file, remove the corresponding index if not shared.
361 // if (indexManager != null) {
362 // IClasspathEntry oldEntry = oldResolvedPath[i];
363 // final IPath path = oldEntry.getPath();
364 // switch (changeKind) {
365 // case IClasspathEntry.CPE_SOURCE:
366 // final char[][] exclusionPatterns = ((ClasspathEntry)oldEntry).fullExclusionPatternChars();
367 // postAction(new IPostAction() {
368 // public String getID() {
369 // return path.toString();
371 // public void run() throws JavaModelException {
372 // indexManager.removeSourceFolderFromIndex(project, path, exclusionPatterns);
375 // REMOVEALL_APPEND);
377 // case IClasspathEntry.CPE_LIBRARY:
378 // final DeltaProcessor deltaProcessor = manager.deltaProcessor;
379 // postAction(new IPostAction() {
380 // public String getID() {
381 // return path.toString();
383 // public void run() throws JavaModelException {
384 // if (deltaProcessor.otherRoots.get(path) == null) { // if root was not shared
385 // indexManager.discardJobs(path.toString());
386 // indexManager.removeIndex(path);
387 // // TODO: we could just remove the in-memory index and have the indexing check for timestamps
391 // REMOVEALL_APPEND);
398 // // do not notify remote project changes
399 // if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
400 // this.needCycleCheck |= (oldResolvedPath[i].isExported() != newResolvedPath[index].isExported());
403 // needToUpdateDependents |= (oldResolvedPath[i].isExported() != newResolvedPath[index].isExported());
404 // if (index != i) { //reordering of the classpath
405 // addClasspathDeltas(
406 // project.computePackageFragmentRoots(oldResolvedPath[i]),
407 // IJavaElementDelta.F_REORDER,
409 // int changeKind = oldResolvedPath[i].getEntryKind();
410 // needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE);
415 // // check source attachment
416 // IPath newSourcePath = newResolvedPath[index].getSourceAttachmentPath();
417 // int sourceAttachmentFlags =
418 // this.getSourceAttachmentDeltaFlag(
419 // oldResolvedPath[i].getSourceAttachmentPath(),
421 // null/*not a source root path*/);
422 // int sourceAttachmentRootFlags =
423 // this.getSourceAttachmentDeltaFlag(
424 // oldResolvedPath[i].getSourceAttachmentRootPath(),
425 // newResolvedPath[index].getSourceAttachmentRootPath(),
426 // newSourcePath/*in case both root paths are null*/);
427 // int flags = sourceAttachmentFlags | sourceAttachmentRootFlags;
429 // addClasspathDeltas(
430 // project.computePackageFragmentRoots(oldResolvedPath[i]),
438 // for (int i = 0; i < newLength; i++) {
440 // int index = classpathContains(oldResolvedPath, newResolvedPath[i]);
441 // if (index == -1) {
442 // // do not notify remote project changes
443 // if (newResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
444 // needToUpdateDependents = true;
445 // this.needCycleCheck = true;
448 // addClasspathDeltas(
449 // project.computePackageFragmentRoots(newResolvedPath[i]),
450 // IJavaElementDelta.F_ADDED_TO_CLASSPATH,
452 // int changeKind = newResolvedPath[i].getEntryKind();
454 // // Request indexing
455 // if (indexManager != null) {
456 // switch (changeKind) {
457 // case IClasspathEntry.CPE_LIBRARY:
458 // boolean pathHasChanged = true;
459 // final IPath newPath = newResolvedPath[i].getPath();
460 // for (int j = 0; j < oldLength; j++) {
461 // IClasspathEntry oldEntry = oldResolvedPath[j];
462 // if (oldEntry.getPath().equals(newPath)) {
463 // pathHasChanged = false;
467 // if (pathHasChanged) {
468 // postAction(new IPostAction() {
469 // public String getID() {
470 // return newPath.toString();
472 // public void run() throws JavaModelException {
473 // indexManager.indexLibrary(newPath, project.getProject());
476 // REMOVEALL_APPEND);
479 // case IClasspathEntry.CPE_SOURCE:
480 // IClasspathEntry entry = newResolvedPath[i];
481 // final IPath path = entry.getPath();
482 // final char[][] exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
483 // postAction(new IPostAction() {
484 // public String getID() {
485 // return path.toString();
487 // public void run() throws JavaModelException {
488 // indexManager.indexSourceFolder(project, path, exclusionPatterns);
491 // APPEND); // append so that a removeSourceFolder action is not removed
496 // needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE) || newResolvedPath[i].isExported();
499 // } // classpath reordering has already been generated in previous loop
503 // this.addDelta(delta);
505 // if (needToUpdateDependents){
506 // updateAffectedProjects(project.getProject().getFullPath());
510 protected JavaProject getProject() {
511 return ((JavaProject) getElementsToProcess()[0]);
515 * Returns the source attachment flag for the delta between the 2 give source paths.
516 * Returns either F_SOURCEATTACHED, F_SOURCEDETACHED, F_SOURCEATTACHED | F_SOURCEDETACHED
517 * or 0 if there is no difference.
519 private int getSourceAttachmentDeltaFlag(IPath oldPath, IPath newPath, IPath sourcePath) {
520 if (oldPath == null) {
521 if (newPath != null) {
522 return IJavaElementDelta.F_SOURCEATTACHED;
524 if (sourcePath != null) {
525 // if source path is specified and no root path, it needs to be recomputed dynamically
526 return IJavaElementDelta.F_SOURCEATTACHED | IJavaElementDelta.F_SOURCEDETACHED;
531 } else if (newPath == null) {
532 return IJavaElementDelta.F_SOURCEDETACHED;
533 } else if (!oldPath.equals(newPath)) {
534 return IJavaElementDelta.F_SOURCEATTACHED | IJavaElementDelta.F_SOURCEDETACHED;
541 * Returns <code>true</code> if this operation performs no resource modifications,
542 * otherwise <code>false</code>. Subclasses must override.
544 public boolean isReadOnly() {
545 return !this.canChangeResources;
548 protected void saveClasspathIfNecessary() throws JavaModelException {
550 if (!this.canChangeResources || !this.needSave) return;
552 IClasspathEntry[] classpathForSave;
553 JavaProject project = getProject();
554 if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath){
555 classpathForSave = project.getRawClasspath();
557 classpathForSave = this.newRawPath;
559 IPath outputLocationForSave;
560 if (this.newOutputLocation == ReuseOutputLocation){
561 outputLocationForSave = project.getOutputLocation();
563 outputLocationForSave = this.newOutputLocation;
565 // if read-only .classpath, then the classpath setting will never been performed completely
566 if (project.saveClasspath(classpathForSave, outputLocationForSave)) {
567 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
571 public String toString(){
572 StringBuffer buffer = new StringBuffer(20);
573 buffer.append("SetClasspathOperation\n"); //$NON-NLS-1$
574 buffer.append(" - classpath : "); //$NON-NLS-1$
575 if (this.newRawPath == ReuseClasspath){
576 buffer.append("<Reuse Existing Classpath>"); //$NON-NLS-1$
578 buffer.append("{"); //$NON-NLS-1$
579 for (int i = 0; i < this.newRawPath.length; i++) {
580 if (i > 0) buffer.append(","); //$NON-NLS-1$
581 IClasspathEntry element = this.newRawPath[i];
582 buffer.append(" ").append(element.toString()); //$NON-NLS-1$
585 buffer.append("\n - output location : "); //$NON-NLS-1$
586 if (this.newOutputLocation == ReuseOutputLocation){
587 buffer.append("<Reuse Existing Output Location>"); //$NON-NLS-1$
589 buffer.append(this.newOutputLocation.toString()); //$NON-NLS-1$
591 return buffer.toString();
594 private void updateClasspath() throws JavaModelException {
596 JavaProject project = ((JavaProject) getElementsToProcess()[0]);
598 beginTask(Util.bind("classpath.settingProgress", project.getElementName()), 2); //$NON-NLS-1$
600 // SIDE-EFFECT: from thereon, the classpath got modified
601 project.setRawClasspath0(this.newRawPath);
603 // resolve new path (asking for marker creation if problems)
604 if (this.newResolvedPath == null) {
605 this.newResolvedPath = project.getResolvedClasspath(true, this.canChangeResources);
608 // if (this.oldResolvedPath != null) {
609 // generateClasspathChangeDeltas(
610 // this.oldResolvedPath,
611 // this.newResolvedPath,
614 this.needCycleCheck = true;
615 updateAffectedProjects(project.getProject().getFullPath());
618 updateCycleMarkersIfNecessary(newResolvedPath);
622 * Update projects which are affected by this classpath change:
623 * those which refers to the current project as source
625 protected void updateAffectedProjects(IPath prerequisiteProjectPath) {
628 IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
629 IJavaProject originatingProject = getProject();
630 IJavaProject[] projects = model.getJavaProjects();
631 for (int i = 0, projectCount = projects.length; i < projectCount; i++) {
633 JavaProject project = (JavaProject) projects[i];
634 if (project.equals(originatingProject)) continue; // skip itself
636 // consider ALL dependents (even indirect ones), since they may need to
637 // flush their respective namelookup caches (all pkg fragment roots).
639 IClasspathEntry[] classpath = project.getExpandedClasspath(true);
640 for (int j = 0, entryCount = classpath.length; j < entryCount; j++) {
641 IClasspathEntry entry = classpath[j];
642 if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
643 && entry.getPath().equals(prerequisiteProjectPath)) {
644 project.setRawClasspath(
646 SetClasspathOperation.ReuseOutputLocation,
647 this.progressMonitor,
648 this.canChangeResources,
649 project.getResolvedClasspath(true),
650 false, // updating only - no validation
651 false); // updating only - no need to save
655 } catch (JavaModelException e) {
658 } catch (JavaModelException e) {
664 * Update cycle markers
666 protected void updateCycleMarkersIfNecessary(IClasspathEntry[] newResolvedPath) {
668 if (!this.needCycleCheck) return;
669 if (!this.canChangeResources) return;
672 JavaProject project = getProject();
673 if (!project.hasCycleMarker() && !project.hasClasspathCycle(project.getResolvedClasspath(true))){
679 public String getID() {
680 return "updateCycleMarkers"; //$NON-NLS-1$
682 public void run() throws JavaModelException {
683 JavaProject.updateAllCycleMarkers();
687 } catch(JavaModelException e){
692 * Sets the output location of the pre-specified project.
694 * <p>This can cause changes in package fragments, in case either the
695 * old or new output location folder are considered as a package fragment.
697 protected void updateOutputLocation() throws JavaModelException {
699 JavaProject project= ((JavaProject) getElementsToProcess()[0]);
701 beginTask(Util.bind("classpath.settingOutputLocationProgress", project.getElementName()), 2); //$NON-NLS-1$
703 IPath oldLocation= project.getOutputLocation();
705 // see if this will cause any package fragments to be added
706 boolean deltaToFire= false;
707 JavaElementDelta delta = newJavaElementDelta();
708 // ArrayList added= determineAffectedPackageFragments(oldLocation);
709 // Iterator iter = added.iterator();
710 // while (iter.hasNext()){
711 // IPackageFragment frag= (IPackageFragment)iter.next();
712 // ((IPackageFragmentRoot)frag.getParent()).close();
713 // if (!Util.isExcluded(frag)) {
714 // delta.added(frag);
715 // deltaToFire = true;
719 // see if this will cause any package fragments to be removed
720 // ArrayList removed= determineAffectedPackageFragments(this.newOutputLocation);
721 // iter = removed.iterator();
722 // while (iter.hasNext()){
723 // IPackageFragment frag= (IPackageFragment)iter.next();
724 // ((IPackageFragmentRoot)frag.getParent()).close();
725 // if (!Util.isExcluded(frag)) {
726 // delta.removed(frag);
727 // deltaToFire = true;
731 JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
732 synchronized (perProjectInfo) {
733 perProjectInfo.outputLocation = this.newOutputLocation;
743 * Update projects references so that the build order is consistent with the classpath
745 protected void updateProjectReferencesIfNecessary() throws JavaModelException {
747 if (!this.canChangeResources) return;
748 if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath) return;
750 JavaProject jproject = getProject();
751 String[] oldRequired = jproject.projectPrerequisites(this.oldResolvedPath);
753 if (this.newResolvedPath == null) {
754 this.newResolvedPath = jproject.getResolvedClasspath(this.newRawPath, null, true, this.needValidation, null /*no reverse map*/);
756 String[] newRequired = jproject.projectPrerequisites(this.newResolvedPath);
759 IProject project = jproject.getProject();
760 IProjectDescription description = project.getDescription();
762 IProject[] projectReferences = description.getReferencedProjects();
764 HashSet oldReferences = new HashSet(projectReferences.length);
765 for (int i = 0; i < projectReferences.length; i++){
766 String projectName = projectReferences[i].getName();
767 oldReferences.add(projectName);
769 HashSet newReferences = (HashSet)oldReferences.clone();
771 for (int i = 0; i < oldRequired.length; i++){
772 String projectName = oldRequired[i];
773 newReferences.remove(projectName);
775 for (int i = 0; i < newRequired.length; i++){
776 String projectName = newRequired[i];
777 newReferences.add(projectName);
781 int newSize = newReferences.size();
784 if (oldReferences.size() == newSize){
785 iter = newReferences.iterator();
786 while (iter.hasNext()){
787 if (!oldReferences.contains(iter.next())){
794 String[] requiredProjectNames = new String[newSize];
796 iter = newReferences.iterator();
797 while (iter.hasNext()){
798 requiredProjectNames[index++] = (String)iter.next();
800 Util.sort(requiredProjectNames); // ensure that if changed, the order is consistent
802 IProject[] requiredProjectArray = new IProject[newSize];
803 IWorkspaceRoot wksRoot = project.getWorkspace().getRoot();
804 for (int i = 0; i < newSize; i++){
805 requiredProjectArray[i] = wksRoot.getProject(requiredProjectNames[i]);
808 description.setReferencedProjects(requiredProjectArray);
809 project.setDescription(description, this.progressMonitor);
811 } catch(CoreException e){
812 throw new JavaModelException(e);
816 public IJavaModelStatus verify() {
818 IJavaModelStatus status = super.verify();
819 if (!status.isOK()) {
823 if (needValidation) {
824 IJavaProject project = (IJavaProject) getElementToProcess();
825 // retrieve classpath
826 IClasspathEntry[] entries = this.newRawPath;
827 if (entries == ReuseClasspath){
829 entries = project.getRawClasspath();
830 } catch (JavaModelException e) {
831 return e.getJavaModelStatus();
834 // retrieve output location
835 IPath outputLocation = this.newOutputLocation;
836 if (outputLocation == ReuseOutputLocation){
838 outputLocation = project.getOutputLocation();
839 } catch (JavaModelException e) {
840 return e.getJavaModelStatus();
844 // perform validation
845 // return JavaConventions.validateClasspath(
851 return JavaModelStatus.VERIFIED_OK;