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.builder;
13 import java.io.DataInputStream;
14 import java.io.DataOutputStream;
15 import java.io.IOException;
16 import java.util.ArrayList;
17 import java.util.Date;
18 import java.util.HashSet;
19 import java.util.Iterator;
22 import net.sourceforge.phpdt.core.IClasspathEntry;
23 import net.sourceforge.phpdt.core.IJavaModelMarker;
24 import net.sourceforge.phpdt.core.JavaCore;
25 import net.sourceforge.phpdt.core.JavaModelException;
26 import net.sourceforge.phpdt.core.compiler.CharOperation;
27 import net.sourceforge.phpdt.internal.core.JavaModel;
28 import net.sourceforge.phpdt.internal.core.JavaModelManager;
29 import net.sourceforge.phpdt.internal.core.JavaProject;
30 import net.sourceforge.phpdt.internal.core.util.SimpleLookupTable;
31 import net.sourceforge.phpdt.internal.core.util.Util;
32 import net.sourceforge.phpdt.internal.core.util.PHPFileUtil;
33 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
34 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
36 import org.eclipse.core.resources.IFile;
37 import org.eclipse.core.resources.IMarker;
38 import org.eclipse.core.resources.IProject;
39 import org.eclipse.core.resources.IResource;
40 //import org.eclipse.core.resources.IResourceChangeEvent;
41 import org.eclipse.core.resources.IResourceDelta;
42 import org.eclipse.core.resources.IResourceVisitor;
43 import org.eclipse.core.resources.IWorkspaceRoot;
44 import org.eclipse.core.resources.IncrementalProjectBuilder;
45 import org.eclipse.core.runtime.CoreException;
46 import org.eclipse.core.runtime.IPath;
47 import org.eclipse.core.runtime.IProgressMonitor;
48 import org.eclipse.core.runtime.OperationCanceledException;
50 public class PHPBuilder extends IncrementalProjectBuilder {
51 IProject currentProject;
53 JavaProject javaProject;
55 IWorkspaceRoot workspaceRoot;
57 NameEnvironment nameEnvironment;
59 SimpleLookupTable binaryLocationsPerProject; // maps a project to its
62 // resources (output folders,
63 // class folders, zip/jar files)
66 BuildNotifier notifier;
68 char[][] extraResourceFileFilters;
70 String[] extraResourceFolderFilters;
72 public static final String CLASS_EXTENSION = "class"; //$NON-NLS-1$
74 public static boolean DEBUG = false;
77 * A list of project names that have been built. This list is used to reset
78 * the JavaModel.existingExternalFiles cache when a build cycle begins so
79 * that deleted external jars are discovered.
81 static ArrayList builtProjects = null;
83 public static IMarker[] getProblemsFor(IResource resource) {
85 if (resource != null && resource.exists())
86 return resource.findMarkers(
87 IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false,
88 IResource.DEPTH_INFINITE);
89 } catch (CoreException e) {
90 } // assume there are no problems
91 return new IMarker[0];
94 public static IMarker[] getTasksFor(IResource resource) {
96 if (resource != null && resource.exists())
97 return resource.findMarkers(IJavaModelMarker.TASK_MARKER,
98 false, IResource.DEPTH_INFINITE);
99 } catch (CoreException e) {
100 } // assume there are no tasks
101 return new IMarker[0];
104 // public static void finishedBuilding(IResourceChangeEvent event) {
105 // BuildNotifier.resetProblemCounters();
109 * Hook allowing to initialize some static state before a complete build
110 * iteration. This hook is invoked during PRE_AUTO_BUILD notification
112 public static void buildStarting() {
114 // TODO (philippe) is it still needed?
118 * Hook allowing to reset some static state after a complete build
119 * iteration. This hook is invoked during POST_AUTO_BUILD notification
121 public static void buildFinished() {
122 BuildNotifier.resetProblemCounters();
125 public static void removeProblemsFor(IResource resource) {
127 if (resource != null && resource.exists())
128 resource.deleteMarkers(
129 IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false,
130 IResource.DEPTH_INFINITE);
131 } catch (CoreException e) {
132 } // assume there were no problems
135 public static void removeTasksFor(IResource resource) {
137 if (resource != null && resource.exists())
138 resource.deleteMarkers(IJavaModelMarker.TASK_MARKER, false,
139 IResource.DEPTH_INFINITE);
140 } catch (CoreException e) {
141 } // assume there were no problems
144 public static void removeProblemsAndTasksFor(IResource resource) {
146 if (resource != null && resource.exists()) {
147 resource.deleteMarkers(
148 IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false,
149 IResource.DEPTH_INFINITE);
150 resource.deleteMarkers(IJavaModelMarker.TASK_MARKER, false,
151 IResource.DEPTH_INFINITE);
153 } catch (CoreException e) {
154 } // assume there were no problems
157 public static State readState(IProject project, DataInputStream in)
159 return State.read(project, in);
162 public static void writeState(Object state, DataOutputStream out)
164 ((State) state).write(out);
167 public PHPBuilder() {
170 protected IProject[] build(int kind, Map ignored, IProgressMonitor monitor)
171 throws CoreException {
172 this.currentProject = getProject();
173 if (currentProject == null || !currentProject.isAccessible())
174 return new IProject[0];
177 .println("\nStarting build of " + currentProject.getName() //$NON-NLS-1$
178 + " @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$
179 this.notifier = new BuildNotifier(monitor, currentProject);
183 notifier.checkCancel();
185 if (isWorthBuilding()) {
186 if (kind == FULL_BUILD) {
187 processFullPHPIndex(currentProject, monitor);
190 if ((this.lastState = getLastState(currentProject)) == null) {
193 .println("Performing full build since last saved state was not found"); //$NON-NLS-1$
194 processFullPHPIndex(currentProject, monitor);
196 // } else if (hasClasspathChanged()) {
197 // // if the output location changes, do not delete the
199 // // from old location
200 // // the user may be trying something
202 } else if (nameEnvironment.sourceLocations.length > 0) {
203 // if there is no source to compile & no classpath
206 SimpleLookupTable deltas = findDeltas();
209 else if (deltas.elementSize > 0)
213 .println("Nothing to build since deltas were empty"); //$NON-NLS-1$
215 if (hasStructuralDelta()) { // double check that a jar
217 // get replaced in a binary project
218 processFullPHPIndex(currentProject, monitor);
223 .println("Nothing to build since there are no source folders and no deltas"); //$NON-NLS-1$
224 lastState.tagAsNoopBuild();
230 } catch (CoreException e) {
231 Util.log(e, "JavaBuilder handling CoreException"); //$NON-NLS-1$
232 IMarker marker = currentProject
233 .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
234 marker.setAttribute(IMarker.MESSAGE, Util.bind(
235 "build.inconsistentProject", e.getLocalizedMessage())); //$NON-NLS-1$
236 marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
237 } catch (ImageBuilderInternalException e) {
238 Util.log(e.getThrowable(),
239 "JavaBuilder handling ImageBuilderInternalException"); //$NON-NLS-1$
240 IMarker marker = currentProject
241 .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
247 "build.inconsistentProject", e.coreException.getLocalizedMessage())); //$NON-NLS-1$
248 marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
249 } catch (MissingClassFileException e) {
250 // do not log this exception since its thrown to handle aborted
252 // because of missing class files
254 System.out.println(Util.bind("build.incompleteClassPath",
255 e.missingClassFile)); //$NON-NLS-1$
256 IMarker marker = currentProject
257 .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
258 marker.setAttribute(IMarker.MESSAGE, Util.bind(
259 "build.incompleteClassPath", e.missingClassFile)); //$NON-NLS-1$
260 marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
261 } catch (MissingSourceFileException e) {
262 // do not log this exception since its thrown to handle aborted
264 // because of missing source files
266 System.out.println(Util.bind("build.missingSourceFile",
267 e.missingSourceFile)); //$NON-NLS-1$
268 removeProblemsAndTasksFor(currentProject); // make this the only
271 IMarker marker = currentProject
272 .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
273 marker.setAttribute(IMarker.MESSAGE, Util.bind(
274 "build.missingSourceFile", e.missingSourceFile)); //$NON-NLS-1$
275 marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
276 } catch (Exception e) {
280 // If the build failed, clear the previously built state,
282 // full build next time.
287 IProject[] requiredProjects = getRequiredProjects(true);
289 System.out.println("Finished build of " + currentProject.getName() //$NON-NLS-1$
290 + " @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$
291 return requiredProjects;
295 * Performs a <code>FULL_BUILD</code> by visiting all nodes in the
296 * resource tree under the specified project.
300 private void processFullPHPIndex(final IProject iProject,
301 final IProgressMonitor monitor) {
302 final IdentifierIndexManager indexManager = PHPeclipsePlugin
303 .getDefault().getIndexManager(iProject);
304 // Create resource visitor logic
305 IResourceVisitor myVisitor = new IResourceVisitor() {
306 public boolean visit(IResource resource) throws CoreException {
307 if (resource.getType() == IResource.FILE) {
308 if (monitor.isCanceled()) {
309 throw new OperationCanceledException();
311 if ((resource.getFileExtension() != null)
312 && PHPFileUtil.isPHPFile((IFile) resource)) {
314 monitor.subTask("Parsing: " + resource.getFullPath());
315 // update indexfile for the project:
316 // PHPProject nature = (PHPProject) iProject
317 // .getNature(PHPeclipsePlugin.PHP_NATURE_ID);
318 indexManager.addFile((IFile) resource);
324 // Process the project using the visitor just created
326 // if (iProject.hasNature(PHPeclipsePlugin.PHP_NATURE_ID)) {
327 // thePHPProject = new PHPProject();
328 // thePHPProject.setProject(iProject);
330 indexManager.initialize();
331 iProject.accept(myVisitor);
332 indexManager.writeFile();
333 } catch (CoreException e) {
338 private void buildAll() {
339 notifier.checkCancel();
340 notifier.subTask(Util.bind("build.preparingBuild")); //$NON-NLS-1$
341 if (DEBUG && lastState != null)
342 System.out.println("Clearing last state : " + lastState); //$NON-NLS-1$
344 BatchImageBuilder imageBuilder = new BatchImageBuilder(this);
345 imageBuilder.build();
346 recordNewState(imageBuilder.newState);
349 private void buildDeltas(SimpleLookupTable deltas) {
350 notifier.checkCancel();
351 notifier.subTask(Util.bind("build.preparingBuild")); //$NON-NLS-1$
352 if (DEBUG && lastState != null)
353 System.out.println("Clearing last state : " + lastState); //$NON-NLS-1$
354 clearLastState(); // clear the previously built state so if the build
355 // fails, a full build will occur next time
356 IncrementalImageBuilder imageBuilder = new IncrementalImageBuilder(this);
357 if (imageBuilder.build(deltas))
358 recordNewState(imageBuilder.newState);
360 processFullPHPIndex(currentProject, notifier.monitor);
365 private void cleanup() {
366 this.nameEnvironment = null;
367 this.binaryLocationsPerProject = null;
368 this.lastState = null;
369 this.notifier = null;
370 this.extraResourceFileFilters = null;
371 this.extraResourceFolderFilters = null;
374 private void clearLastState() {
375 JavaModelManager.getJavaModelManager().setLastBuiltState(
376 currentProject, null);
379 boolean filterExtraResource(IResource resource) {
380 if (extraResourceFileFilters != null) {
381 char[] name = resource.getName().toCharArray();
382 for (int i = 0, l = extraResourceFileFilters.length; i < l; i++)
384 .match(extraResourceFileFilters[i], name, true))
387 if (extraResourceFolderFilters != null) {
388 IPath path = resource.getProjectRelativePath();
389 String pathName = path.toString();
390 int count = path.segmentCount();
391 if (resource.getType() == IResource.FILE)
393 for (int i = 0, l = extraResourceFolderFilters.length; i < l; i++)
394 if (pathName.indexOf(extraResourceFolderFilters[i]) != -1)
395 for (int j = 0; j < count; j++)
396 if (extraResourceFolderFilters[i].equals(path
403 private SimpleLookupTable findDeltas() {
404 notifier.subTask(Util.bind(
405 "build.readingDelta", currentProject.getName())); //$NON-NLS-1$
406 IResourceDelta delta = getDelta(currentProject);
407 SimpleLookupTable deltas = new SimpleLookupTable(3);
409 if (delta.getKind() != IResourceDelta.NO_CHANGE) {
411 System.out.println("Found source delta for: "
412 + currentProject.getName()); //$NON-NLS-1$
413 deltas.put(currentProject, delta);
418 .println("Missing delta for: " + currentProject.getName()); //$NON-NLS-1$
419 notifier.subTask(""); //$NON-NLS-1$
422 Object[] keyTable = binaryLocationsPerProject.keyTable;
423 //Object[] valueTable = binaryLocationsPerProject.valueTable;
424 nextProject: for (int i = 0, l = keyTable.length; i < l; i++) {
425 IProject p = (IProject) keyTable[i];
426 if (p != null && p != currentProject) {
427 State s = getLastState(p);
428 if (!lastState.wasStructurallyChanged(p, s)) { // see if we can
431 if (s.wasNoopBuild())
432 continue nextProject; // project has no source folders
435 // ClasspathLocation[] classFoldersAndJars =
436 // (ClasspathLocation[])
438 boolean canSkip = true;
439 // for (int j = 0, m = classFoldersAndJars.length; j < m;
441 // if (classFoldersAndJars[j].isOutputFolder())
442 // classFoldersAndJars[j] = null; // can ignore output
444 // project was not structurally changed
449 continue nextProject; // project has no structural
453 notifier.subTask(Util.bind("build.readingDelta", p.getName())); //$NON-NLS-1$
456 if (delta.getKind() != IResourceDelta.NO_CHANGE) {
459 .println("Found binary delta for: " + p.getName()); //$NON-NLS-1$
460 deltas.put(p, delta);
464 System.out.println("Missing delta for: " + p.getName()); //$NON-NLS-1$
465 notifier.subTask(""); //$NON-NLS-1$
470 notifier.subTask(""); //$NON-NLS-1$
474 private State getLastState(IProject project) {
475 return (State) JavaModelManager.getJavaModelManager()
476 .getLastBuiltState(project, notifier.monitor);
480 * Return the list of projects for which it requires a resource delta. This
481 * builder's project is implicitly included and need not be specified.
482 * Builders must re-specify the list of interesting projects every time they
483 * are run as this is not carried forward beyond the next build. Missing
484 * projects should be specified but will be ignored until they are added to
487 private IProject[] getRequiredProjects(boolean includeBinaryPrerequisites) {
488 if (javaProject == null || workspaceRoot == null)
489 return new IProject[0];
490 ArrayList projects = new ArrayList();
492 IClasspathEntry[] entries = javaProject.getExpandedClasspath(true);
493 for (int i = 0, l = entries.length; i < l; i++) {
494 IClasspathEntry entry = entries[i];
495 IPath path = entry.getPath();
497 switch (entry.getEntryKind()) {
498 case IClasspathEntry.CPE_PROJECT:
499 p = workspaceRoot.getProject(path.lastSegment()); // missing
503 case IClasspathEntry.CPE_LIBRARY:
504 if (includeBinaryPrerequisites && path.segmentCount() > 1) {
505 // some binary resources on the class path can come from
507 // that are not included in the project references
508 IResource resource = workspaceRoot.findMember(path
510 if (resource instanceof IProject)
511 p = (IProject) resource;
514 if (p != null && !projects.contains(p))
517 } catch (JavaModelException e) {
518 return new IProject[0];
520 IProject[] result = new IProject[projects.size()];
521 projects.toArray(result);
525 // private boolean hasClasspathChanged() {
526 // ClasspathMultiDirectory[] newSourceLocations =
527 // nameEnvironment.sourceLocations;
528 // ClasspathMultiDirectory[] oldSourceLocations = lastState.sourceLocations;
529 // int newLength = newSourceLocations.length;
530 // int oldLength = oldSourceLocations.length;
532 // for (n = o = 0; n < newLength && o < oldLength; n++, o++) {
533 // if (newSourceLocations[n].equals(oldSourceLocations[o]))
534 // continue; // checks source & output folders
536 // if (newSourceLocations[n].sourceFolder.members().length == 0) { // added
544 // } catch (CoreException ignore) {
547 // System.out.println(newSourceLocations[n] + " != "
548 // + oldSourceLocations[o]); //$NON-NLS-1$
551 // while (n < newLength) {
553 // if (newSourceLocations[n].sourceFolder.members().length == 0) { // added
561 // } catch (CoreException ignore) {
564 // System.out.println("Added non-empty source folder"); //$NON-NLS-1$
567 // if (o < oldLength) {
569 // System.out.println("Removed source folder"); //$NON-NLS-1$
572 // // ClasspathLocation[] newBinaryLocations =
573 // // nameEnvironment.binaryLocations;
574 // // ClasspathLocation[] oldBinaryLocations = lastState.binaryLocations;
575 // // newLength = newBinaryLocations.length;
576 // // oldLength = oldBinaryLocations.length;
577 // // for (n = o = 0; n < newLength && o < oldLength; n++, o++) {
578 // // if (newBinaryLocations[n].equals(oldBinaryLocations[o])) continue;
580 // // System.out.println(newBinaryLocations[n] + " != " +
581 // // oldBinaryLocations[o]); //$NON-NLS-1$
584 // // if (n < newLength || o < oldLength) {
586 // // System.out.println("Number of binary folders/jar files has changed");
592 private boolean hasStructuralDelta() {
593 // handle case when currentProject has only .class file folders and/or
595 // files... no source/output folders
596 IResourceDelta delta = getDelta(currentProject);
597 if (delta != null && delta.getKind() != IResourceDelta.NO_CHANGE) {
598 // ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[])
599 // binaryLocationsPerProject.get(currentProject);
600 // if (classFoldersAndJars != null) {
601 // for (int i = 0, l = classFoldersAndJars.length; i < l; i++) {
602 // ClasspathLocation classFolderOrJar = classFoldersAndJars[i]; //
604 // a .class file folder or a zip/jar file
605 // if (classFolderOrJar != null) {
606 // IPath p = classFolderOrJar.getProjectRelativePath();
608 // IResourceDelta binaryDelta = delta.findMember(p);
609 // if (binaryDelta != null && binaryDelta.getKind() !=
610 // IResourceDelta.NO_CHANGE)
620 private void initializeBuilder() throws CoreException {
621 this.javaProject = (JavaProject) JavaCore.create(currentProject);
622 this.workspaceRoot = currentProject.getWorkspace().getRoot();
623 // Flush the existing external files cache if this is the beginning of a
625 String projectName = currentProject.getName();
626 if (builtProjects == null || builtProjects.contains(projectName)) {
627 JavaModel.flushExternalFileCache();
628 builtProjects = new ArrayList();
630 builtProjects.add(projectName);
631 this.binaryLocationsPerProject = new SimpleLookupTable(3);
632 this.nameEnvironment = new NameEnvironment(workspaceRoot, javaProject,
633 binaryLocationsPerProject);
634 String filterSequence = javaProject.getOption(
635 JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, true);
636 char[][] filters = filterSequence != null
637 && filterSequence.length() > 0 ? CharOperation.splitAndTrimOn(
638 ',', filterSequence.toCharArray()) : null;
639 if (filters == null) {
640 this.extraResourceFileFilters = null;
641 this.extraResourceFolderFilters = null;
643 int fileCount = 0, folderCount = 0;
644 for (int i = 0, l = filters.length; i < l; i++) {
645 char[] f = filters[i];
648 if (f[f.length - 1] == '/')
653 this.extraResourceFileFilters = new char[fileCount][];
654 this.extraResourceFolderFilters = new String[folderCount];
655 for (int i = 0, l = filters.length; i < l; i++) {
656 char[] f = filters[i];
659 if (f[f.length - 1] == '/')
660 extraResourceFolderFilters[--folderCount] = new String(
661 CharOperation.subarray(f, 0, f.length - 1));
663 extraResourceFileFilters[--fileCount] = f;
668 private boolean isClasspathBroken(IClasspathEntry[] classpath, IProject p)
669 throws CoreException {
670 if (classpath == JavaProject.INVALID_CLASSPATH) // the .classpath file
673 IMarker[] markers = p.findMarkers(
674 IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false,
675 IResource.DEPTH_ZERO);
676 for (int i = 0, l = markers.length; i < l; i++)
677 if (((Integer) markers[i].getAttribute(IMarker.SEVERITY))
678 .intValue() == IMarker.SEVERITY_ERROR)
683 private boolean isWorthBuilding() throws CoreException {
684 boolean abortBuilds = JavaCore.ABORT.equals(javaProject.getOption(
685 JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH, true));
688 // Abort build only if there are classpath errors
689 // if (isClasspathBroken(javaProject.getRawClasspath(), currentProject))
692 // System.out.println("Aborted build because project has classpath
694 // (incomplete or involved in cycle)"); //$NON-NLS-1$
696 // JavaModelManager.getJavaModelManager().deltaProcessor.addForRefresh(javaProject);
698 // removeProblemsAndTasksFor(currentProject); // remove all compilation
702 // currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
703 // marker.setAttribute(IMarker.MESSAGE,
704 // ProjectPrefUtil.bind("build.abortDueToClasspathProblems"));
706 // marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
709 // make sure all prereq projects have valid build states... only when
710 // aborting builds since projects in cycles do not have build states
711 // except for projects involved in a 'warning' cycle (see below)
712 IProject[] requiredProjects = getRequiredProjects(false);
713 next: for (int i = 0, l = requiredProjects.length; i < l; i++) {
714 IProject p = requiredProjects[i];
715 if (getLastState(p) == null) {
716 // The prereq project has no build state: if this prereq project
718 // 'warning' cycle marker then allow build (see bug id 23357)
719 JavaProject prereq = (JavaProject) JavaCore.create(p);
720 if (prereq.hasCycleMarker()
721 && JavaCore.WARNING.equals(javaProject.getOption(
722 JavaCore.CORE_CIRCULAR_CLASSPATH, true)))
725 System.out.println("Aborted build because prereq project "
726 + p.getName() //$NON-NLS-1$
727 + " was not built"); //$NON-NLS-1$
728 removeProblemsAndTasksFor(currentProject); // make this the
730 // problem for this project
731 IMarker marker = currentProject
732 .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
736 isClasspathBroken(prereq.getRawClasspath(), p) ? Util
738 "build.prereqProjectHasClasspathProblems", p.getName()) //$NON-NLS-1$
741 "build.prereqProjectMustBeRebuilt", p.getName())); //$NON-NLS-1$
742 marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
750 * Instruct the build manager that this project is involved in a cycle and
751 * needs to propagate structural changes to the other projects in the cycle.
753 void mustPropagateStructuralChanges() {
754 HashSet cycleParticipants = new HashSet(3);
755 javaProject.updateCycleParticipants(null, new ArrayList(),
756 cycleParticipants, workspaceRoot, new HashSet(3));
757 IPath currentPath = javaProject.getPath();
758 Iterator i = cycleParticipants.iterator();
759 while (i.hasNext()) {
760 IPath participantPath = (IPath) i.next();
761 if (participantPath != currentPath) {
762 IProject project = this.workspaceRoot
763 .getProject(participantPath.segment(0));
764 if (hasBeenBuilt(project)) {
767 .println("Requesting another build iteration since cycle participant "
768 + project.getName() //$NON-NLS-1$
769 + " has not yet seen some structural changes"); //$NON-NLS-1$
777 private void recordNewState(State state) {
778 Object[] keyTable = binaryLocationsPerProject.keyTable;
779 for (int i = 0, l = keyTable.length; i < l; i++) {
780 IProject prereqProject = (IProject) keyTable[i];
781 if (prereqProject != null && prereqProject != currentProject)
782 state.recordStructuralDependency(prereqProject,
783 getLastState(prereqProject));
786 System.out.println("Recording new state : " + state); //$NON-NLS-1$
788 JavaModelManager.getJavaModelManager().setLastBuiltState(
789 currentProject, state);
793 * String representation for debugging purposes
795 public String toString() {
796 return currentProject == null ? "JavaBuilder for unknown project" //$NON-NLS-1$
797 : "JavaBuilder for " + currentProject.getName(); //$NON-NLS-1$