1 11 package org.eclipse.core.internal.events; 12 13 import java.util.*; 14 import org.eclipse.core.internal.dtree.DeltaDataTree; 15 import org.eclipse.core.internal.resources.*; 16 import org.eclipse.core.internal.utils.Messages; 17 import org.eclipse.core.internal.utils.Policy; 18 import org.eclipse.core.internal.watson.ElementTree; 19 import org.eclipse.core.resources.*; 20 import org.eclipse.core.runtime.*; 21 import org.eclipse.core.runtime.jobs.ILock; 22 import org.eclipse.osgi.util.NLS; 23 import org.osgi.framework.Bundle; 24 25 public class BuildManager implements ICoreConstants, IManager, ILifecycleListener { 26 27 32 class DeltaCache { 33 private Object delta; 34 private ElementTree newTree; 35 private ElementTree oldTree; 36 private IPath projectPath; 37 38 public void cache(IPath project, ElementTree anOldTree, ElementTree aNewTree, Object aDelta) { 39 this.projectPath = project; 40 this.oldTree = anOldTree; 41 this.newTree = aNewTree; 42 this.delta = aDelta; 43 } 44 45 public void flush() { 46 this.projectPath = null; 47 this.oldTree = null; 48 this.newTree = null; 49 this.delta = null; 50 } 51 52 56 public Object getDelta(IPath project, ElementTree anOldTree, ElementTree aNewTree) { 57 if (delta == null) 58 return null; 59 boolean pathsEqual = projectPath == null ? project == null : projectPath.equals(project); 60 if (pathsEqual && this.oldTree == anOldTree && this.newTree == aNewTree) 61 return delta; 62 return null; 63 } 64 } 65 66 69 class MissingBuilder extends IncrementalProjectBuilder { 70 private boolean hasBeenBuilt = false; 71 private String name; 72 73 MissingBuilder(String name) { 74 this.name = name; 75 } 76 77 80 protected IProject[] build(int kind, Map args, IProgressMonitor monitor) { 81 if (!hasBeenBuilt) { 82 hasBeenBuilt = true; 83 String msg = NLS.bind(Messages.events_skippingBuilder, name, getProject().getName()); 84 Policy.log(IStatus.WARNING, msg, null); 85 } 86 return null; 87 } 88 } 89 90 private static final int TOTAL_BUILD_WORK = Policy.totalWork * 1000; 91 92 final AutoBuildJob autoBuildJob; 94 private boolean building = false; 95 private final ArrayList builtProjects = new ArrayList(); 96 97 protected InternalBuilder currentBuilder; 99 private DeltaDataTree currentDelta; 100 private ElementTree currentLastBuiltTree; 101 private ElementTree currentTree; 102 103 106 final private DeltaCache deltaCache = new DeltaCache(); 107 110 final private DeltaCache deltaTreeCache = new DeltaCache(); 111 112 private ILock lock; 113 114 private boolean rebuildRequested = false; 116 117 private final Bundle systemBundle = Platform.getBundle("org.eclipse.osgi"); 119 private long timeStamp = -1; 121 private Workspace workspace; 122 123 public BuildManager(Workspace workspace, ILock workspaceLock) { 124 this.workspace = workspace; 125 this.autoBuildJob = new AutoBuildJob(workspace); 126 this.lock = workspaceLock; 127 InternalBuilder.buildManager = this; 128 } 129 130 private void basicBuild(int trigger, IncrementalProjectBuilder builder, Map args, MultiStatus status, IProgressMonitor monitor) { 131 try { 132 currentBuilder = builder; 133 currentBuilder.clearForgetLastBuiltState(); 135 boolean clean = trigger == IncrementalProjectBuilder.CLEAN_BUILD; 137 currentLastBuiltTree = currentBuilder.getLastBuiltTree(); 138 if (!clean && currentLastBuiltTree == null) 140 trigger = IncrementalProjectBuilder.FULL_BUILD; 141 if (!builder.getCommand().isBuilding(trigger)) 143 return; 144 currentTree = ((trigger == IncrementalProjectBuilder.FULL_BUILD) || clean) ? null : workspace.getElementTree(); 146 int depth = -1; 147 try { 148 if (!needsBuild(currentBuilder, trigger)) { 150 monitor.beginTask("", 1); monitor.done(); 153 return; 154 } 155 String name = currentBuilder.getLabel(); 156 String message; 157 if (name != null) 158 message = NLS.bind(Messages.events_invoking_2, name, builder.getProject().getFullPath()); 159 else 160 message = NLS.bind(Messages.events_invoking_1, builder.getProject().getFullPath()); 161 monitor.subTask(message); 162 hookStartBuild(builder, trigger); 163 depth = getWorkManager().beginUnprotected(); 165 SafeRunner.run(getSafeRunnable(trigger, args, status, monitor)); 167 } finally { 168 if (depth >= 0) 169 getWorkManager().endUnprotected(depth); 170 if (clean || currentBuilder.wasForgetStateRequested()) { 172 currentBuilder.setLastBuiltTree(null); 173 } else { 174 ElementTree lastTree = workspace.getElementTree(); 176 lastTree.immutable(); 177 currentBuilder.setLastBuiltTree(lastTree); 178 } 179 hookEndBuild(builder); 180 } 181 } finally { 182 currentBuilder = null; 183 currentTree = null; 184 currentLastBuiltTree = null; 185 currentDelta = null; 186 } 187 } 188 189 protected void basicBuild(IProject project, int trigger, ICommand[] commands, MultiStatus status, IProgressMonitor monitor) { 190 try { 191 for (int i = 0; i < commands.length; i++) { 192 checkCanceled(trigger, monitor); 193 BuildCommand command = (BuildCommand) commands[i]; 194 IProgressMonitor sub = Policy.subMonitorFor(monitor, 1); 195 IncrementalProjectBuilder builder = getBuilder(project, command, i, status); 196 if (builder != null) 197 basicBuild(trigger, builder, command.getArguments(false), status, sub); 198 } 199 } catch (CoreException e) { 200 status.add(e.getStatus()); 201 } 202 } 203 204 208 private IStatus basicBuild(IProject project, int trigger, IProgressMonitor monitor) { 209 if (!canRun(trigger)) 210 return Status.OK_STATUS; 211 try { 212 hookStartBuild(trigger); 213 MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, Messages.events_errors, null); 214 basicBuild(project, trigger, status, monitor); 215 return status; 216 } finally { 217 hookEndBuild(trigger); 218 } 219 } 220 221 private void basicBuild(final IProject project, final int trigger, final MultiStatus status, final IProgressMonitor monitor) { 222 try { 223 final ICommand[] commands; 224 if (project.isAccessible()) 225 commands = ((Project) project).internalGetDescription().getBuildSpec(false); 226 else 227 commands = null; 228 int work = commands == null ? 0 : commands.length; 229 monitor.beginTask(NLS.bind(Messages.events_building_1, project.getFullPath()), work); 230 if (work == 0) 231 return; 232 ISafeRunnable code = new ISafeRunnable() { 233 public void handleException(Throwable e) { 234 if (e instanceof OperationCanceledException) 235 throw (OperationCanceledException) e; 236 String errorText = e.getMessage(); 240 if (errorText == null) 241 errorText = NLS.bind(Messages.events_unknown, e.getClass().getName(), project.getName()); 242 status.add(new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, errorText, e)); 243 } 244 245 public void run() throws Exception { 246 basicBuild(project, trigger, commands, status, monitor); 247 } 248 }; 249 SafeRunner.run(code); 250 } finally { 251 monitor.done(); 252 } 253 } 254 255 259 private IStatus basicBuild(IProject project, int trigger, String builderName, Map args, IProgressMonitor monitor) { 260 monitor = Policy.monitorFor(monitor); 261 try { 262 String message = NLS.bind(Messages.events_building_1, project.getFullPath()); 263 monitor.beginTask(message, 1); 264 if (!canRun(trigger)) 265 return Status.OK_STATUS; 266 try { 267 hookStartBuild(trigger); 268 MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, Messages.events_errors, null); 269 ICommand command = getCommand(project, builderName, args); 270 try { 271 IncrementalProjectBuilder builder = getBuilder(project, command, -1, status); 272 if (builder != null) 273 basicBuild(trigger, builder, args, status, Policy.subMonitorFor(monitor, 1)); 274 } catch (CoreException e) { 275 status.add(e.getStatus()); 276 } 277 return status; 278 } finally { 279 hookEndBuild(trigger); 280 } 281 } finally { 282 monitor.done(); 283 } 284 } 285 286 289 private void basicBuildLoop(IProject[] ordered, IProject[] unordered, int trigger, MultiStatus status, IProgressMonitor monitor) { 290 int projectWork = ordered.length + unordered.length; 291 if (projectWork > 0) 292 projectWork = TOTAL_BUILD_WORK / projectWork; 293 int maxIterations = workspace.getDescription().getMaxBuildIterations(); 294 if (maxIterations <= 0) 295 maxIterations = 1; 296 rebuildRequested = true; 297 for (int iter = 0; rebuildRequested && iter < maxIterations; iter++) { 298 rebuildRequested = false; 299 builtProjects.clear(); 300 for (int i = 0; i < ordered.length; i++) { 301 if (ordered[i].isAccessible()) { 302 basicBuild(ordered[i], trigger, status, Policy.subMonitorFor(monitor, projectWork)); 303 builtProjects.add(ordered[i]); 304 } 305 } 306 for (int i = 0; i < unordered.length; i++) { 307 if (unordered[i].isAccessible()) { 308 basicBuild(unordered[i], trigger, status, Policy.subMonitorFor(monitor, projectWork)); 309 builtProjects.add(unordered[i]); 310 } 311 } 312 trigger = IncrementalProjectBuilder.INCREMENTAL_BUILD; 314 } 315 } 316 317 321 public IStatus build(int trigger, IProgressMonitor monitor) { 322 monitor = Policy.monitorFor(monitor); 323 try { 324 monitor.beginTask(Messages.events_building_0, TOTAL_BUILD_WORK); 325 if (!canRun(trigger)) 326 return Status.OK_STATUS; 327 try { 328 hookStartBuild(trigger); 329 IProject[] ordered = workspace.getBuildOrder(); 330 HashSet leftover = new HashSet(Arrays.asList(workspace.getRoot().getProjects())); 331 leftover.removeAll(Arrays.asList(ordered)); 332 IProject[] unordered = (IProject[]) leftover.toArray(new IProject[leftover.size()]); 333 MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.BUILD_FAILED, Messages.events_errors, null); 334 basicBuildLoop(ordered, unordered, trigger, status, monitor); 335 return status; 336 } finally { 337 hookEndBuild(trigger); 338 } 339 } finally { 340 monitor.done(); 341 if (trigger == IncrementalProjectBuilder.INCREMENTAL_BUILD || trigger == IncrementalProjectBuilder.FULL_BUILD) 342 autoBuildJob.avoidBuild(); 343 } 344 } 345 346 350 public IStatus build(IProject project, int trigger, String builderName, Map args, IProgressMonitor monitor) { 351 monitor = Policy.monitorFor(monitor); 352 if (builderName == null) 353 return basicBuild(project, trigger, monitor); 354 return basicBuild(project, trigger, builderName, args, monitor); 355 } 356 357 private boolean canRun(int trigger) { 358 return !building; 359 } 360 361 364 private void checkCanceled(int trigger, IProgressMonitor monitor) { 365 if (systemBundle.getState() == Bundle.STOPPING) 367 throw new OperationCanceledException(); 368 Policy.checkCanceled(monitor); 369 if (trigger != IncrementalProjectBuilder.AUTO_BUILD) 371 return; 372 if (autoBuildJob.isInterrupted()) 374 throw new OperationCanceledException(); 375 } 376 377 383 public ArrayList createBuildersPersistentInfo(IProject project) throws CoreException { 384 385 ArrayList oldInfos = getBuildersPersistentInfo(project); 386 387 ICommand[] commands = ((Project) project).internalGetDescription().getBuildSpec(false); 388 if (commands.length == 0) 389 return null; 390 391 392 ArrayList newInfos = new ArrayList(commands.length); 393 for (int i = 0; i < commands.length; i++) { 394 String builderName = commands[i].getBuilderName(); 395 BuilderPersistentInfo info = null; 396 IncrementalProjectBuilder builder = ((BuildCommand) commands[i]).getBuilder(); 397 if (builder == null) { 398 if (oldInfos != null) 400 info = getBuilderInfo(oldInfos, builderName, i); 401 } else if (!(builder instanceof MissingBuilder)) { 402 ElementTree oldTree = ((InternalBuilder) builder).getLastBuiltTree(); 403 if (oldTree != null) { 405 info = new BuilderPersistentInfo(project.getName(), builderName, i); 407 info.setLastBuildTree(oldTree); 408 info.setInterestingProjects(((InternalBuilder) builder).getInterestingProjects()); 409 } 410 } 411 if (info != null) 412 newInfos.add(info); 413 } 414 return newInfos; 415 } 416 417 private String debugBuilder() { 418 return currentBuilder == null ? "<no builder>" : currentBuilder.getClass().getName(); } 420 421 private String debugProject() { 422 if (currentBuilder == null) 423 return "<no project>"; return currentBuilder.getProject().getFullPath().toString(); 425 } 426 427 432 private String debugTrigger(int trigger) { 433 switch (trigger) { 434 case IncrementalProjectBuilder.FULL_BUILD : 435 return "FULL_BUILD"; case IncrementalProjectBuilder.CLEAN_BUILD : 437 return "CLEAN_BUILD"; case IncrementalProjectBuilder.AUTO_BUILD : 439 case IncrementalProjectBuilder.INCREMENTAL_BUILD : 440 default : 441 return "INCREMENTAL_BUILD"; } 443 } 444 445 448 public void endTopLevel(boolean needsBuild) { 449 autoBuildJob.build(needsBuild); 450 } 451 452 456 private boolean getBooleanAttribute(IConfigurationElement element, String name) { 457 String valueString = element.getAttribute(name); 458 return valueString != null && valueString.equalsIgnoreCase(Boolean.TRUE.toString()); 459 } 460 461 470 private IncrementalProjectBuilder getBuilder(IProject project, ICommand command, int buildSpecIndex, MultiStatus status) throws CoreException { 471 InternalBuilder result = ((BuildCommand) command).getBuilder(); 472 if (result == null) { 473 result = initializeBuilder(command.getBuilderName(), project, buildSpecIndex, status); 474 ((BuildCommand) command).setBuilder((IncrementalProjectBuilder) result); 475 result.setCommand(command); 476 result.setProject(project); 477 result.startupOnInitialize(); 478 } 479 if (!validateNature(result, command.getBuilderName())) { 480 result.setLastBuiltTree(null); 483 return null; 484 } 485 return (IncrementalProjectBuilder) result; 486 } 487 488 494 private BuilderPersistentInfo getBuilderInfo(ArrayList infos, String builderName, int buildSpecIndex) { 495 BuilderPersistentInfo nameMatch = null; 498 for (Iterator it = infos.iterator(); it.hasNext();) { 499 BuilderPersistentInfo info = (BuilderPersistentInfo) it.next(); 500 if (info.getBuilderName().equals(builderName)) { 502 if (nameMatch == null) 504 nameMatch = info; 505 if (buildSpecIndex == -1 || info.getBuildSpecIndex() == -1 || buildSpecIndex == info.getBuildSpecIndex()) 507 return info; 508 } 509 } 510 return nameMatch; 512 } 513 514 519 public ArrayList getBuildersPersistentInfo(IProject project) throws CoreException { 520 return (ArrayList) project.getSessionProperty(K_BUILD_LIST); 521 } 522 523 530 private ICommand getCommand(IProject project, String builderName, Map args) { 531 ICommand[] buildSpec = ((Project) project).internalGetDescription().getBuildSpec(false); 532 for (int i = 0; i < buildSpec.length; i++) 533 if (buildSpec[i].getBuilderName().equals(builderName)) 534 return buildSpec[i]; 535 BuildCommand result = new BuildCommand(); 537 result.setBuilderName(builderName); 538 result.setArguments(args); 539 return result; 540 } 541 542 IResourceDelta getDelta(IProject project) { 543 try { 544 lock.acquire(); 545 if (currentTree == null) { 546 if (Policy.DEBUG_BUILD_FAILURE) 547 Policy.debug("Build: no tree for delta " + debugBuilder() + " [" + debugProject() + "]"); return null; 549 } 550 if (!isInterestingProject(project)) { 552 if (Policy.DEBUG_BUILD_FAILURE) 553 Policy.debug("Build: project not interesting for this builder " + debugBuilder() + " [" + debugProject() + "] " + project.getFullPath()); return null; 555 } 556 if (currentDelta != null && currentDelta.findNodeAt(project.getFullPath()) == null) { 558 if (!project.exists()) 560 return null; 561 return ResourceDeltaFactory.newEmptyDelta(project); 563 } 564 IResourceDelta result = (IResourceDelta) deltaCache.getDelta(project.getFullPath(), currentLastBuiltTree, currentTree); 566 if (result != null) 567 return result; 568 569 long startTime = 0L; 570 if (Policy.DEBUG_BUILD_DELTA) { 571 startTime = System.currentTimeMillis(); 572 Policy.debug("Computing delta for project: " + project.getName()); } 574 result = ResourceDeltaFactory.computeDelta(workspace, currentLastBuiltTree, currentTree, project.getFullPath(), -1); 575 deltaCache.cache(project.getFullPath(), currentLastBuiltTree, currentTree, result); 576 if (Policy.DEBUG_BUILD_FAILURE && result == null) 577 Policy.debug("Build: no delta " + debugBuilder() + " [" + debugProject() + "] " + project.getFullPath()); if (Policy.DEBUG_BUILD_DELTA) 579 Policy.debug("Finished computing delta, time: " + (System.currentTimeMillis() - startTime) + "ms"); return result; 581 } finally { 582 lock.release(); 583 } 584 } 585 586 589 private ISafeRunnable getSafeRunnable(final int trigger, final Map args, final MultiStatus status, final IProgressMonitor monitor) { 590 return new ISafeRunnable() { 591 public void handleException(Throwable e) { 592 if (e instanceof OperationCanceledException) { 593 currentBuilder.forgetLastBuiltState(); 596 throw (OperationCanceledException) e; 597 } 598 601 String builderName = currentBuilder.getLabel(); 603 if (builderName == null || builderName.length() == 0) 604 builderName = currentBuilder.getClass().getName(); 605 String pluginId = currentBuilder.getPluginId(); 606 String message = NLS.bind(Messages.events_builderError, builderName, currentBuilder.getProject().getName()); 607 status.add(new Status(IStatus.WARNING, pluginId, IResourceStatus.BUILD_FAILED, message, null)); 608 609 if (e instanceof CoreException) 611 status.add(((CoreException) e).getStatus()); 612 else { 613 message = e.getMessage(); 614 if (message == null) 615 message = NLS.bind(Messages.events_unknown, e.getClass().getName(), builderName); 616 status.add(new Status(IStatus.WARNING, pluginId, IResourceStatus.BUILD_FAILED, message, e)); 617 } 618 } 619 620 public void run() throws Exception { 621 IProject[] prereqs = null; 622 if (trigger != IncrementalProjectBuilder.CLEAN_BUILD) 624 prereqs = currentBuilder.build(trigger, args, monitor); 625 else 626 currentBuilder.clean(monitor); 627 if (prereqs == null) 628 prereqs = new IProject[0]; 629 currentBuilder.setInterestingProjects((IProject[]) prereqs.clone()); 630 } 631 }; 632 } 633 634 638 private WorkManager getWorkManager() { 639 try { 640 return workspace.getWorkManager(); 641 } catch (CoreException e) { 642 } 644 return null; 646 } 647 648 public void handleEvent(LifecycleEvent event) { 649 IProject project = null; 650 switch (event.kind) { 651 case LifecycleEvent.PRE_PROJECT_DELETE : 652 case LifecycleEvent.PRE_PROJECT_MOVE : 653 project = (IProject) event.resource; 654 if (project.isAccessible()) 656 setBuildersPersistentInfo(project, null); 657 } 658 } 659 660 664 boolean hasBeenBuilt(IProject project) { 665 return builtProjects.contains(project); 666 } 667 668 672 private void hookEndBuild(IncrementalProjectBuilder builder) { 673 if (ResourceStats.TRACE_BUILDERS) 674 ResourceStats.endBuild(); 675 if (!Policy.DEBUG_BUILD_INVOKING || timeStamp == -1) 676 return; Policy.debug("Builder finished: " + toString(builder) + " time: " + (System.currentTimeMillis() - timeStamp) + "ms"); timeStamp = -1; 679 } 680 681 686 private void hookEndBuild(int trigger) { 687 building = false; 688 builtProjects.clear(); 689 deltaCache.flush(); 690 deltaTreeCache.flush(); 691 if (trigger == IncrementalProjectBuilder.CLEAN_BUILD) 693 autoBuildJob.forceBuild(); 694 } 695 696 700 private void hookStartBuild(IncrementalProjectBuilder builder, int trigger) { 701 if (ResourceStats.TRACE_BUILDERS) 702 ResourceStats.startBuild(builder); 703 if (Policy.DEBUG_BUILD_INVOKING) { 704 timeStamp = System.currentTimeMillis(); 705 Policy.debug("Invoking (" + debugTrigger(trigger) + ") on builder: " + toString(builder)); } 707 } 708 709 714 private void hookStartBuild(int trigger) { 715 building = true; 716 if (Policy.DEBUG_BUILD_STACK) { 717 IStatus info = new Status(IStatus.INFO, ResourcesPlugin.PI_RESOURCES, 1, "Starting build: " + debugTrigger(trigger), new RuntimeException ().fillInStackTrace()); Policy.log(info); 719 } 720 } 721 722 729 private IncrementalProjectBuilder initializeBuilder(String builderName, IProject project, int buildSpecIndex, MultiStatus status) throws CoreException { 730 IncrementalProjectBuilder builder = null; 731 try { 732 builder = instantiateBuilder(builderName); 733 } catch (CoreException e) { 734 status.add(new ResourceStatus(IResourceStatus.BUILD_FAILED, project.getFullPath(), NLS.bind(Messages.events_instantiate_1, builderName), e)); 735 status.add(e.getStatus()); 736 } 737 if (builder == null) { 738 builder = new MissingBuilder(builderName); 740 } 741 ArrayList infos = getBuildersPersistentInfo(project); 743 if (infos != null) { 744 BuilderPersistentInfo info = getBuilderInfo(infos, builderName, buildSpecIndex); 745 if (info != null) { 746 infos.remove(info); 747 ElementTree tree = info.getLastBuiltTree(); 748 if (tree != null) 749 ((InternalBuilder) builder).setLastBuiltTree(tree); 750 ((InternalBuilder) builder).setInterestingProjects(info.getInterestingProjects()); 751 } 752 if (infos.size() == 0) 754 setBuildersPersistentInfo(project, null); 755 } 756 return builder; 757 } 758 759 763 private IncrementalProjectBuilder instantiateBuilder(String builderName) throws CoreException { 764 IExtension extension = Platform.getExtensionRegistry().getExtension(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_BUILDERS, builderName); 765 if (extension == null) 766 return null; 767 IConfigurationElement[] configs = extension.getConfigurationElements(); 768 if (configs.length == 0) 769 return null; 770 String natureId = null; 771 if (getBooleanAttribute(configs[0], "hasNature")) { String builderId = extension.getUniqueIdentifier(); 774 natureId = workspace.getNatureManager().findNatureForBuilder(builderId); 775 if (natureId == null) 776 return null; 777 } 778 InternalBuilder builder = (InternalBuilder) configs[0].createExecutableExtension("run"); builder.setPluginId(extension.getContributor().getName()); 781 builder.setLabel(extension.getLabel()); 782 builder.setNatureId(natureId); 783 builder.setCallOnEmptyDelta(getBooleanAttribute(configs[0], "callOnEmptyDelta")); return (IncrementalProjectBuilder) builder; 785 } 786 787 791 public void interrupt() { 792 autoBuildJob.interrupt(); 793 } 794 795 799 private boolean isInterestingProject(IProject project) { 800 if (project.equals(currentBuilder.getProject())) 801 return true; 802 IProject[] interestingProjects = currentBuilder.getInterestingProjects(); 803 for (int i = 0; i < interestingProjects.length; i++) { 804 if (interestingProjects[i].equals(project)) { 805 return true; 806 } 807 } 808 return false; 809 } 810 811 822 private boolean needsBuild(InternalBuilder builder, int trigger) { 823 switch (trigger) { 825 case IncrementalProjectBuilder.CLEAN_BUILD : 826 return true; 827 case IncrementalProjectBuilder.FULL_BUILD : 828 return true; 829 case IncrementalProjectBuilder.INCREMENTAL_BUILD : 830 if (currentBuilder.callOnEmptyDelta()) 831 return true; 832 } 834 835 ElementTree oldTree = builder.getLastBuiltTree(); 837 ElementTree newTree = workspace.getElementTree(); 838 long start = System.currentTimeMillis(); 839 currentDelta = (DeltaDataTree) deltaTreeCache.getDelta(null, oldTree, newTree); 840 if (currentDelta == null) { 841 if (Policy.DEBUG_BUILD_NEEDED) { 842 String message = "Checking if need to build. Starting delta computation between: " + oldTree.toString() + " and " + newTree.toString(); Policy.debug(message); 844 } 845 currentDelta = newTree.getDataTree().forwardDeltaWith(oldTree.getDataTree(), ResourceComparator.getBuildComparator()); 846 if (Policy.DEBUG_BUILD_NEEDED) 847 Policy.debug("End delta computation. (" + (System.currentTimeMillis() - start) + "ms)."); deltaTreeCache.cache(null, oldTree, newTree, currentDelta); 849 } 850 851 if (currentDelta.findNodeAt(builder.getProject().getFullPath()) != null) { 853 if (Policy.DEBUG_BUILD_NEEDED) 854 Policy.debug(toString(builder) + " needs building because of changes in: " + builder.getProject().getName()); return true; 856 } 857 858 IProject[] projects = builder.getInterestingProjects(); 860 for (int i = 0; i < projects.length; i++) { 861 if (currentDelta.findNodeAt(projects[i].getFullPath()) != null) { 862 if (Policy.DEBUG_BUILD_NEEDED) 863 Policy.debug(toString(builder) + " needs building because of changes in: " + projects[i].getName()); return true; 865 } 866 } 867 return false; 868 } 869 870 874 private void removeBuilders(IProject project, String builderId) throws CoreException { 875 IProjectDescription desc = project.getDescription(); 876 ICommand[] oldSpec = desc.getBuildSpec(); 877 int oldLength = oldSpec.length; 878 if (oldLength == 0) 879 return; 880 int remaining = 0; 881 for (int i = 0; i < oldSpec.length; i++) { 883 if (oldSpec[i].getBuilderName().equals(builderId)) 884 oldSpec[i] = null; 885 else 886 remaining++; 887 } 888 if (remaining == oldSpec.length) 890 return; 891 ICommand[] newSpec = new ICommand[remaining]; 892 for (int i = 0, newIndex = 0; i < oldLength; i++) { 893 if (oldSpec[i] != null) 894 newSpec[newIndex++] = oldSpec[i]; 895 } 896 desc.setBuildSpec(newSpec); 897 project.setDescription(desc, IResource.NONE, null); 898 } 899 900 903 void requestRebuild() { 904 rebuildRequested = true; 905 } 906 907 914 public void setBuildersPersistentInfo(IProject project, ArrayList list) { 915 try { 916 project.setSessionProperty(K_BUILD_LIST, list); 917 } catch (CoreException e) { 918 Policy.log(new ResourceStatus(IStatus.ERROR, 1, project.getFullPath(), "Project missing in setBuildersPersistentInfo", null)); } 922 } 923 924 public void shutdown(IProgressMonitor monitor) { 925 autoBuildJob.cancel(); 926 } 927 928 public void startup(IProgressMonitor monitor) { 929 workspace.addLifecycleListener(this); 930 } 931 932 936 private String toString(InternalBuilder builder) { 937 String name = builder.getClass().getName(); 938 name = name.substring(name.lastIndexOf('.') + 1); 939 return name + "(" + builder.getProject().getName() + ")"; } 941 942 958 private boolean validateNature(InternalBuilder builder, String builderId) throws CoreException { 959 String nature = builder.getNatureId(); 960 if (nature == null) 961 return true; 962 IProject project = builder.getProject(); 963 if (!project.hasNature(nature)) { 964 removeBuilders(project, builderId); 966 return false; 967 } 968 return project.isNatureEnabled(nature); 969 } 970 } 971 | Popular Tags |