1 11 package org.eclipse.jdt.internal.core; 12 13 import java.io.InputStream ; 14 import java.util.ArrayList ; 15 import java.util.HashMap ; 16 17 import org.eclipse.core.resources.*; 18 import org.eclipse.core.runtime.*; 19 import org.eclipse.core.runtime.jobs.ISchedulingRule; 20 import org.eclipse.jdt.core.*; 21 import org.eclipse.jdt.internal.core.util.Messages; 22 import org.eclipse.jface.text.IDocument; 23 24 27 public abstract class JavaModelOperation implements IWorkspaceRunnable, IProgressMonitor { 28 protected interface IPostAction { 29 33 String getID(); 34 37 void run() throws JavaModelException; 38 } 39 43 protected static final int APPEND = 1; protected static final int REMOVEALL_APPEND = 2; protected static final int KEEP_EXISTING = 3; 47 50 protected static boolean POST_ACTION_VERBOSE; 51 52 55 protected IPostAction[] actions; 56 protected int actionsStart = 0; 57 protected int actionsEnd = -1; 58 61 protected HashMap attributes; 62 63 public static final String HAS_MODIFIED_RESOURCE_ATTR = "hasModifiedResource"; public static final String TRUE = JavaModelManager.TRUE; 65 67 72 protected IJavaElement[] elementsToProcess; 73 78 protected IJavaElement[] parentElements; 79 84 protected static IJavaElement[] NO_ELEMENTS= new IJavaElement[] {}; 85 86 87 91 protected IJavaElement[] resultElements= NO_ELEMENTS; 92 93 96 public IProgressMonitor progressMonitor= null; 97 100 protected boolean isNested = false; 101 104 protected boolean force = false; 105 106 109 protected static ThreadLocal operationStacks = new ThreadLocal (); 110 protected JavaModelOperation() { 111 } 113 116 protected JavaModelOperation(IJavaElement[] elements) { 117 this.elementsToProcess = elements; 118 } 119 122 protected JavaModelOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements) { 123 this.elementsToProcess = elementsToProcess; 124 this.parentElements= parentElements; 125 } 126 129 protected JavaModelOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements, boolean force) { 130 this.elementsToProcess = elementsToProcess; 131 this.parentElements= parentElements; 132 this.force= force; 133 } 134 137 protected JavaModelOperation(IJavaElement[] elements, boolean force) { 138 this.elementsToProcess = elements; 139 this.force= force; 140 } 141 142 145 protected JavaModelOperation(IJavaElement element) { 146 this.elementsToProcess = new IJavaElement[]{element}; 147 } 148 151 protected JavaModelOperation(IJavaElement element, boolean force) { 152 this.elementsToProcess = new IJavaElement[]{element}; 153 this.force= force; 154 } 155 156 159 protected void addAction(IPostAction action) { 160 int length = this.actions.length; 161 if (length == ++this.actionsEnd) { 162 System.arraycopy(this.actions, 0, this.actions = new IPostAction[length*2], 0, length); 163 } 164 this.actions[this.actionsEnd] = action; 165 } 166 169 protected void addDelta(IJavaElementDelta delta) { 170 JavaModelManager.getJavaModelManager().getDeltaProcessor().registerJavaModelDelta(delta); 171 } 172 175 protected void addReconcileDelta(ICompilationUnit workingCopy, IJavaElementDelta delta) { 176 HashMap reconcileDeltas = JavaModelManager.getJavaModelManager().getDeltaProcessor().reconcileDeltas; 177 JavaElementDelta previousDelta = (JavaElementDelta)reconcileDeltas.get(workingCopy); 178 if (previousDelta != null) { 179 IJavaElementDelta[] children = delta.getAffectedChildren(); 180 for (int i = 0, length = children.length; i < length; i++) { 181 JavaElementDelta child = (JavaElementDelta)children[i]; 182 previousDelta.insertDeltaTree(child.getElement(), child); 183 } 184 if ((delta.getFlags() & IJavaElementDelta.F_AST_AFFECTED) != 0) { 187 previousDelta.changedAST(delta.getCompilationUnitAST()); 188 } 189 190 } else { 191 reconcileDeltas.put(workingCopy, delta); 192 } 193 } 194 197 protected void removeReconcileDelta(ICompilationUnit workingCopy) { 198 JavaModelManager.getJavaModelManager().getDeltaProcessor().reconcileDeltas.remove(workingCopy); 199 } 200 203 public void beginTask(String name, int totalWork) { 204 if (progressMonitor != null) { 205 progressMonitor.beginTask(name, totalWork); 206 } 207 } 208 211 protected boolean canModifyRoots() { 212 return false; 213 } 214 222 protected void checkCanceled() { 223 if (isCanceled()) { 224 throw new OperationCanceledException(Messages.operation_cancelled); 225 } 226 } 227 231 protected IJavaModelStatus commonVerify() { 232 if (elementsToProcess == null || elementsToProcess.length == 0) { 233 return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS); 234 } 235 for (int i = 0; i < elementsToProcess.length; i++) { 236 if (elementsToProcess[i] == null) { 237 return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS); 238 } 239 } 240 return JavaModelStatus.VERIFIED_OK; 241 } 242 245 protected void copyResources(IResource[] resources, IPath destinationPath) throws JavaModelException { 246 IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length); 247 IWorkspace workspace = resources[0].getWorkspace(); 248 try { 249 workspace.copy(resources, destinationPath, false, subProgressMonitor); 250 setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 251 } catch (CoreException e) { 252 throw new JavaModelException(e); 253 } 254 } 255 258 protected void createFile(IContainer folder, String name, InputStream contents, boolean forceFlag) throws JavaModelException { 259 IFile file= folder.getFile(new Path(name)); 260 try { 261 file.create( 262 contents, 263 forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 264 getSubProgressMonitor(1)); 265 setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 266 } catch (CoreException e) { 267 throw new JavaModelException(e); 268 } 269 } 270 273 protected void createFolder(IContainer parentFolder, String name, boolean forceFlag) throws JavaModelException { 274 IFolder folder= parentFolder.getFolder(new Path(name)); 275 try { 276 folder.create( 278 forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 279 true, getSubProgressMonitor(1)); 281 setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 282 } catch (CoreException e) { 283 throw new JavaModelException(e); 284 } 285 } 286 289 protected void deleteEmptyPackageFragment( 290 IPackageFragment fragment, 291 boolean forceFlag, 292 IResource rootResource) 293 throws JavaModelException { 294 295 IContainer resource = (IContainer) fragment.getResource(); 296 297 try { 298 resource.delete( 299 forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 300 getSubProgressMonitor(1)); 301 setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 302 while (resource instanceof IFolder) { 303 resource = resource.getParent(); 306 if (!resource.equals(rootResource) && resource.members().length == 0) { 307 resource.delete( 308 forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 309 getSubProgressMonitor(1)); 310 setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 311 } 312 } 313 } catch (CoreException e) { 314 throw new JavaModelException(e); 315 } 316 } 317 320 protected void deleteResource(IResource resource,int flags) throws JavaModelException { 321 try { 322 resource.delete(flags, getSubProgressMonitor(1)); 323 setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 324 } catch (CoreException e) { 325 throw new JavaModelException(e); 326 } 327 } 328 331 protected void deleteResources(IResource[] resources, boolean forceFlag) throws JavaModelException { 332 if (resources == null || resources.length == 0) return; 333 IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length); 334 IWorkspace workspace = resources[0].getWorkspace(); 335 try { 336 workspace.delete( 337 resources, 338 forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 339 subProgressMonitor); 340 setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 341 } catch (CoreException e) { 342 throw new JavaModelException(e); 343 } 344 } 345 348 public void done() { 349 if (progressMonitor != null) { 350 progressMonitor.done(); 351 } 352 } 353 356 protected boolean equalsOneOf(IPath path, IPath[] otherPaths) { 357 for (int i = 0, length = otherPaths.length; i < length; i++) { 358 if (path.equals(otherPaths[i])) { 359 return true; 360 } 361 } 362 return false; 363 } 364 367 public void executeNestedOperation(JavaModelOperation operation, int subWorkAmount) throws JavaModelException { 368 IJavaModelStatus status= operation.verify(); 369 if (!status.isOK()) { 370 throw new JavaModelException(status); 371 } 372 IProgressMonitor subProgressMonitor = getSubProgressMonitor(subWorkAmount); 373 try { 375 operation.setNested(true); 376 operation.run(subProgressMonitor); 377 } catch (CoreException ce) { 378 if (ce instanceof JavaModelException) { 379 throw (JavaModelException)ce; 380 } else { 381 if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) { 383 Throwable e = ce.getStatus().getException(); 384 if (e instanceof JavaModelException) { 385 throw (JavaModelException) e; 386 } 387 } 388 throw new JavaModelException(ce); 389 } 390 } 391 } 392 395 protected abstract void executeOperation() throws JavaModelException; 396 400 protected static Object getAttribute(Object key) { 401 ArrayList stack = getCurrentOperationStack(); 402 if (stack.size() == 0) return null; 403 JavaModelOperation topLevelOp = (JavaModelOperation)stack.get(0); 404 if (topLevelOp.attributes == null) { 405 return null; 406 } else { 407 return topLevelOp.attributes.get(key); 408 } 409 } 410 415 protected ICompilationUnit getCompilationUnitFor(IJavaElement element) { 416 417 return ((JavaElement)element).getCompilationUnit(); 418 } 419 423 protected static ArrayList getCurrentOperationStack() { 424 ArrayList stack = (ArrayList )operationStacks.get(); 425 if (stack == null) { 426 stack = new ArrayList (); 427 operationStacks.set(stack); 428 } 429 return stack; 430 } 431 434 protected IDocument getDocument(ICompilationUnit cu) throws JavaModelException { 435 IBuffer buffer = cu.getBuffer(); 436 if (buffer instanceof IDocument) 437 return (IDocument) buffer; 438 return new DocumentAdapter(buffer); 439 } 440 444 protected IJavaElement[] getElementsToProcess() { 445 return elementsToProcess; 446 } 447 451 protected IJavaElement getElementToProcess() { 452 if (elementsToProcess == null || elementsToProcess.length == 0) { 453 return null; 454 } 455 return elementsToProcess[0]; 456 } 457 460 public IJavaModel getJavaModel() { 461 return JavaModelManager.getJavaModelManager().getJavaModel(); 462 } 463 protected IPath[] getNestedFolders(IPackageFragmentRoot root) throws JavaModelException { 464 IPath rootPath = root.getPath(); 465 IClasspathEntry[] classpath = root.getJavaProject().getRawClasspath(); 466 int length = classpath.length; 467 IPath[] result = new IPath[length]; 468 int index = 0; 469 for (int i = 0; i < length; i++) { 470 IPath path = classpath[i].getPath(); 471 if (rootPath.isPrefixOf(path) && !rootPath.equals(path)) { 472 result[index++] = path; 473 } 474 } 475 if (index < length) { 476 System.arraycopy(result, 0, result = new IPath[index], 0, index); 477 } 478 return result; 479 } 480 484 protected IJavaElement getParentElement() { 485 if (parentElements == null || parentElements.length == 0) { 486 return null; 487 } 488 return parentElements[0]; 489 } 490 494 protected IJavaElement[] getParentElements() { 495 return parentElements; 496 } 497 500 public IJavaElement[] getResultElements() { 501 return resultElements; 502 } 503 508 protected ISchedulingRule getSchedulingRule() { 509 return ResourcesPlugin.getWorkspace().getRoot(); 510 } 511 514 protected IProgressMonitor getSubProgressMonitor(int workAmount) { 515 IProgressMonitor sub = null; 516 if (progressMonitor != null) { 517 sub = new SubProgressMonitor(progressMonitor, workAmount, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); 518 } 519 return sub; 520 } 521 522 526 public boolean hasModifiedResource() { 527 return !this.isReadOnly() && getAttribute(HAS_MODIFIED_RESOURCE_ATTR) == TRUE; 528 } 529 public void internalWorked(double work) { 530 if (progressMonitor != null) { 531 progressMonitor.internalWorked(work); 532 } 533 } 534 537 public boolean isCanceled() { 538 if (progressMonitor != null) { 539 return progressMonitor.isCanceled(); 540 } 541 return false; 542 } 543 547 public boolean isReadOnly() { 548 return false; 549 } 550 553 protected boolean isTopLevelOperation() { 554 ArrayList stack; 555 return 556 (stack = getCurrentOperationStack()).size() > 0 557 && stack.get(0) == this; 558 } 559 563 protected int firstActionWithID(String id, int start) { 564 for (int i = start; i <= this.actionsEnd; i++) { 565 if (this.actions[i].getID().equals(id)) { 566 return i; 567 } 568 } 569 return -1; 570 } 571 572 575 protected void moveResources(IResource[] resources, IPath destinationPath) throws JavaModelException { 576 IProgressMonitor subProgressMonitor = null; 577 if (progressMonitor != null) { 578 subProgressMonitor = new SubProgressMonitor(progressMonitor, resources.length, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); 579 } 580 IWorkspace workspace = resources[0].getWorkspace(); 581 try { 582 workspace.move(resources, destinationPath, false, subProgressMonitor); 583 setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 584 } catch (CoreException e) { 585 throw new JavaModelException(e); 586 } 587 } 588 592 public JavaElementDelta newJavaElementDelta() { 593 return new JavaElementDelta(getJavaModel()); 594 } 595 599 protected JavaModelOperation popOperation() { 600 ArrayList stack = getCurrentOperationStack(); 601 int size = stack.size(); 602 if (size > 0) { 603 if (size == 1) { operationStacks.set(null); } 606 return (JavaModelOperation)stack.remove(size-1); 607 } else { 608 return null; 609 } 610 } 611 618 protected void postAction(IPostAction action, int insertionMode) { 619 if (POST_ACTION_VERBOSE) { 620 System.out.print("(" + Thread.currentThread() + ") [JavaModelOperation.postAction(IPostAction, int)] Posting action " + action.getID()); switch(insertionMode) { 622 case REMOVEALL_APPEND: 623 System.out.println(" (REMOVEALL_APPEND)"); break; 625 case KEEP_EXISTING: 626 System.out.println(" (KEEP_EXISTING)"); break; 628 case APPEND: 629 System.out.println(" (APPEND)"); break; 631 } 632 } 633 634 JavaModelOperation topLevelOp = (JavaModelOperation)getCurrentOperationStack().get(0); 635 IPostAction[] postActions = topLevelOp.actions; 636 if (postActions == null) { 637 topLevelOp.actions = postActions = new IPostAction[1]; 638 postActions[0] = action; 639 topLevelOp.actionsEnd = 0; 640 } else { 641 String id = action.getID(); 642 switch (insertionMode) { 643 case REMOVEALL_APPEND : 644 int index = this.actionsStart-1; 645 while ((index = topLevelOp.firstActionWithID(id, index+1)) >= 0) { 646 System.arraycopy(postActions, index+1, postActions, index, topLevelOp.actionsEnd - index); 648 postActions[topLevelOp.actionsEnd--] = null; 649 } 650 topLevelOp.addAction(action); 651 break; 652 case KEEP_EXISTING: 653 if (topLevelOp.firstActionWithID(id, 0) < 0) { 654 topLevelOp.addAction(action); 655 } 656 break; 657 case APPEND: 658 topLevelOp.addAction(action); 659 break; 660 } 661 } 662 } 663 666 protected boolean prefixesOneOf(IPath path, IPath[] otherPaths) { 667 for (int i = 0, length = otherPaths.length; i < length; i++) { 668 if (path.isPrefixOf(otherPaths[i])) { 669 return true; 670 } 671 } 672 return false; 673 } 674 677 protected void pushOperation(JavaModelOperation operation) { 678 getCurrentOperationStack().add(operation); 679 } 680 684 protected void removeAllPostAction(String actionID) { 685 if (POST_ACTION_VERBOSE) { 686 System.out.println("(" + Thread.currentThread() + ") [JavaModelOperation.removeAllPostAction(String)] Removing actions " + actionID); } 688 689 JavaModelOperation topLevelOp = (JavaModelOperation)getCurrentOperationStack().get(0); 690 IPostAction[] postActions = topLevelOp.actions; 691 if (postActions == null) return; 692 int index = this.actionsStart-1; 693 while ((index = topLevelOp.firstActionWithID(actionID, index+1)) >= 0) { 694 System.arraycopy(postActions, index+1, postActions, index, topLevelOp.actionsEnd - index); 696 postActions[topLevelOp.actionsEnd--] = null; 697 } 698 } 699 700 706 public void run(IProgressMonitor monitor) throws CoreException { 707 JavaModelManager manager = JavaModelManager.getJavaModelManager(); 708 DeltaProcessor deltaProcessor = manager.getDeltaProcessor(); 709 int previousDeltaCount = deltaProcessor.javaModelDeltas.size(); 710 try { 711 progressMonitor = monitor; 712 pushOperation(this); 713 try { 714 if (canModifyRoots()) { 715 JavaModelManager.getJavaModelManager().deltaState.initializeRoots(); 718 } 719 720 executeOperation(); 721 } finally { 722 if (this.isTopLevelOperation()) { 723 this.runPostActions(); 724 } 725 } 726 } finally { 727 try { 728 deltaProcessor = manager.getDeltaProcessor(); 730 731 for (int i = previousDeltaCount, size = deltaProcessor.javaModelDeltas.size(); i < size; i++) { 733 deltaProcessor.updateJavaModel((IJavaElementDelta)deltaProcessor.javaModelDeltas.get(i)); 734 } 735 736 for (int i = 0, length = this.resultElements.length; i < length; i++) { 740 IJavaElement element = this.resultElements[i]; 741 Openable openable = (Openable) element.getOpenable(); 742 if (!(openable instanceof CompilationUnit) || !((CompilationUnit) openable).isWorkingCopy()) { ((JavaElement) openable.getParent()).close(); 744 } 745 switch (element.getElementType()) { 746 case IJavaElement.PACKAGE_FRAGMENT_ROOT: 747 case IJavaElement.PACKAGE_FRAGMENT: 748 deltaProcessor.projectCachesToReset.add(element.getJavaProject()); 749 break; 750 } 751 } 752 deltaProcessor.resetProjectCaches(); 753 754 if (this.isTopLevelOperation()) { 759 if ((deltaProcessor.javaModelDeltas.size() > previousDeltaCount || !deltaProcessor.reconcileDeltas.isEmpty()) 760 && !this.hasModifiedResource()) { 761 deltaProcessor.fire(null, DeltaProcessor.DEFAULT_CHANGE_EVENT); 762 } } 764 } finally { 765 popOperation(); 766 } 767 } 768 } 769 773 public void runOperation(IProgressMonitor monitor) throws JavaModelException { 774 IJavaModelStatus status= verify(); 775 if (!status.isOK()) { 776 throw new JavaModelException(status); 777 } 778 try { 779 if (isReadOnly()) { 780 run(monitor); 781 } else { 782 ResourcesPlugin.getWorkspace().run(this, getSchedulingRule(), IWorkspace.AVOID_UPDATE, monitor); 786 } 787 } catch (CoreException ce) { 788 if (ce instanceof JavaModelException) { 789 throw (JavaModelException)ce; 790 } else { 791 if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) { 792 Throwable e= ce.getStatus().getException(); 793 if (e instanceof JavaModelException) { 794 throw (JavaModelException) e; 795 } 796 } 797 throw new JavaModelException(ce); 798 } 799 } 800 } 801 protected void runPostActions() throws JavaModelException { 802 while (this.actionsStart <= this.actionsEnd) { 803 IPostAction postAction = this.actions[this.actionsStart++]; 804 if (POST_ACTION_VERBOSE) { 805 System.out.println("(" + Thread.currentThread() + ") [JavaModelOperation.runPostActions()] Running action " + postAction.getID()); } 807 postAction.run(); 808 } 809 } 810 813 protected static void setAttribute(Object key, Object attribute) { 814 ArrayList operationStack = getCurrentOperationStack(); 815 if (operationStack.size() == 0) 816 return; 817 JavaModelOperation topLevelOp = (JavaModelOperation) operationStack.get(0); 818 if (topLevelOp.attributes == null) { 819 topLevelOp.attributes = new HashMap (); 820 } 821 topLevelOp.attributes.put(key, attribute); 822 } 823 826 public void setCanceled(boolean b) { 827 if (progressMonitor != null) { 828 progressMonitor.setCanceled(b); 829 } 830 } 831 835 protected void setNested(boolean nested) { 836 isNested = nested; 837 } 838 841 public void setTaskName(String name) { 842 if (progressMonitor != null) { 843 progressMonitor.setTaskName(name); 844 } 845 } 846 849 public void subTask(String name) { 850 if (progressMonitor != null) { 851 progressMonitor.subTask(name); 852 } 853 } 854 864 protected IJavaModelStatus verify() { 865 return commonVerify(); 866 } 867 868 871 public void worked(int work) { 872 if (progressMonitor != null) { 873 progressMonitor.worked(work); 874 checkCanceled(); 875 } 876 } 877 } 878 | Popular Tags |