1 11 package org.eclipse.jdt.internal.core; 12 13 import java.util.*; 14 15 import org.eclipse.core.resources.*; 16 import org.eclipse.core.runtime.CoreException; 17 import org.eclipse.core.runtime.IPath; 18 import org.eclipse.core.runtime.Path; 19 import org.eclipse.jdt.core.*; 20 import org.eclipse.jdt.core.dom.AST; 21 import org.eclipse.jdt.core.dom.ASTParser; 22 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 23 import org.eclipse.jdt.core.dom.CompilationUnit; 24 import org.eclipse.jdt.core.dom.MethodDeclaration; 25 import org.eclipse.jdt.core.dom.Name; 26 import org.eclipse.jdt.core.dom.PackageDeclaration; 27 import org.eclipse.jdt.core.dom.SimpleName; 28 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; 29 import org.eclipse.jdt.internal.compiler.util.SuffixConstants; 30 import org.eclipse.jdt.internal.core.util.Messages; 31 import org.eclipse.jdt.internal.core.util.Util; 32 import org.eclipse.jface.text.BadLocationException; 33 import org.eclipse.jface.text.IDocument; 34 import org.eclipse.text.edits.TextEdit; 35 36 60 public class CopyResourceElementsOperation extends MultiOperation implements SuffixConstants { 61 64 protected ArrayList createdElements; 65 70 protected Map deltasPerProject = new HashMap(1); 71 75 protected ASTParser parser; 76 80 public CopyResourceElementsOperation(IJavaElement[] resourcesToCopy, IJavaElement destContainer, boolean force) { 81 this(resourcesToCopy, new IJavaElement[]{destContainer}, force); 82 } 83 89 public CopyResourceElementsOperation(IJavaElement[] resourcesToCopy, IJavaElement[] destContainers, boolean force) { 90 super(resourcesToCopy, destContainers, force); 91 initializeASTParser(); 92 } 93 private void initializeASTParser() { 94 this.parser = ASTParser.newParser(AST.JLS3); 95 } 96 101 private IResource[] collectResourcesOfInterest(IPackageFragment source) throws JavaModelException { 102 IJavaElement[] children = source.getChildren(); 103 int childOfInterest = IJavaElement.COMPILATION_UNIT; 104 if (source.getKind() == IPackageFragmentRoot.K_BINARY) { 105 childOfInterest = IJavaElement.CLASS_FILE; 106 } 107 ArrayList correctKindChildren = new ArrayList(children.length); 108 for (int i = 0; i < children.length; i++) { 109 IJavaElement child = children[i]; 110 if (child.getElementType() == childOfInterest) { 111 correctKindChildren.add(child.getResource()); 112 } 113 } 114 Object [] nonJavaResources = source.getNonJavaResources(); 116 int actualNonJavaResourceCount = 0; 117 for (int i = 0, max = nonJavaResources.length; i < max; i++){ 118 if (nonJavaResources[i] instanceof IResource) actualNonJavaResourceCount++; 119 } 120 IResource[] actualNonJavaResources = new IResource[actualNonJavaResourceCount]; 121 for (int i = 0, max = nonJavaResources.length, index = 0; i < max; i++){ 122 if (nonJavaResources[i] instanceof IResource) actualNonJavaResources[index++] = (IResource)nonJavaResources[i]; 123 } 124 125 if (actualNonJavaResourceCount != 0) { 126 int correctKindChildrenSize = correctKindChildren.size(); 127 IResource[] result = new IResource[correctKindChildrenSize + actualNonJavaResourceCount]; 128 correctKindChildren.toArray(result); 129 System.arraycopy(actualNonJavaResources, 0, result, correctKindChildrenSize, actualNonJavaResourceCount); 130 return result; 131 } else { 132 IResource[] result = new IResource[correctKindChildren.size()]; 133 correctKindChildren.toArray(result); 134 return result; 135 } 136 } 137 141 private boolean createNeededPackageFragments(IContainer sourceFolder, PackageFragmentRoot root, String [] newFragName, boolean moveFolder) throws JavaModelException { 142 boolean containsReadOnlyPackageFragment = false; 143 IContainer parentFolder = (IContainer) root.getResource(); 144 JavaElementDelta projectDelta = null; 145 String [] sideEffectPackageName = null; 146 char[][] inclusionPatterns = root.fullInclusionPatternChars(); 147 char[][] exclusionPatterns = root.fullExclusionPatternChars(); 148 for (int i = 0; i < newFragName.length; i++) { 149 String subFolderName = newFragName[i]; 150 sideEffectPackageName = Util.arrayConcat(sideEffectPackageName, subFolderName); 151 IResource subFolder = parentFolder.findMember(subFolderName); 152 if (subFolder == null) { 153 if (!(moveFolder && i == newFragName.length-1)) { 155 createFolder(parentFolder, subFolderName, force); 156 } 157 parentFolder = parentFolder.getFolder(new Path(subFolderName)); 158 sourceFolder = sourceFolder.getFolder(new Path(subFolderName)); 159 if (Util.isReadOnly(sourceFolder)) { 160 containsReadOnlyPackageFragment = true; 161 } 162 IPackageFragment sideEffectPackage = root.getPackageFragment(sideEffectPackageName); 163 if (i < newFragName.length - 1 && !Util.isExcluded(parentFolder, inclusionPatterns, exclusionPatterns)) { 165 if (projectDelta == null) { 166 projectDelta = getDeltaFor(root.getJavaProject()); 167 } 168 projectDelta.added(sideEffectPackage); 169 } 170 createdElements.add(sideEffectPackage); 171 } else { 172 parentFolder = (IContainer) subFolder; 173 } 174 } 175 return containsReadOnlyPackageFragment; 176 } 177 178 183 private JavaElementDelta getDeltaFor(IJavaProject javaProject) { 184 JavaElementDelta delta = (JavaElementDelta) deltasPerProject.get(javaProject); 185 if (delta == null) { 186 delta = new JavaElementDelta(javaProject); 187 deltasPerProject.put(javaProject, delta); 188 } 189 return delta; 190 } 191 194 protected String getMainTaskName() { 195 return Messages.operation_copyResourceProgress; 196 } 197 208 protected void prepareDeltas(IJavaElement sourceElement, IJavaElement destinationElement, boolean isMove) { 209 if (Util.isExcluded(sourceElement) || Util.isExcluded(destinationElement)) return; 210 IJavaProject destProject = destinationElement.getJavaProject(); 211 if (isMove) { 212 IJavaProject sourceProject = sourceElement.getJavaProject(); 213 getDeltaFor(sourceProject).movedFrom(sourceElement, destinationElement); 214 getDeltaFor(destProject).movedTo(destinationElement, sourceElement); 215 } else { 216 getDeltaFor(destProject).added(destinationElement); 217 } 218 } 219 228 private void processCompilationUnitResource(ICompilationUnit source, PackageFragment dest) throws JavaModelException { 229 String newCUName = getNewNameFor(source); 230 String destName = (newCUName != null) ? newCUName : source.getElementName(); 231 ASTRewrite rewrite = updateContent(source, dest, newCUName); 233 IFile sourceResource = (IFile)source.getResource(); 236 String sourceEncoding = null; 237 try { 238 sourceEncoding = sourceResource.getCharset(false); 239 } 240 catch (CoreException ce) { 241 } 243 IContainer destFolder = (IContainer)dest.getResource(); IFile destFile = destFolder.getFile(new Path(destName)); 247 org.eclipse.jdt.internal.core.CompilationUnit destCU = new org.eclipse.jdt.internal.core.CompilationUnit(dest, destName, DefaultWorkingCopyOwner.PRIMARY); 248 if (!destFile.equals(sourceResource)) { 249 try { 250 if (!destCU.isWorkingCopy()) { 251 if (destFile.exists()) { 252 if (this.force) { 253 deleteResource(destFile, IResource.KEEP_HISTORY); 255 destCU.close(); } else { 257 throw new JavaModelException(new JavaModelStatus( 259 IJavaModelStatusConstants.NAME_COLLISION, 260 Messages.bind(Messages.status_nameCollision, destFile.getFullPath().toString()))); 261 } 262 } 263 int flags = this.force ? IResource.FORCE : IResource.NONE; 264 if (this.isMove()) { 265 flags |= IResource.KEEP_HISTORY; 266 sourceResource.move(destFile.getFullPath(), flags, getSubProgressMonitor(1)); 267 } else { 268 if (rewrite != null) flags |= IResource.KEEP_HISTORY; 269 sourceResource.copy(destFile.getFullPath(), flags, getSubProgressMonitor(1)); 270 } 271 setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 272 } else { 273 destCU.getBuffer().setContents(source.getBuffer().getContents()); 274 } 275 } catch (JavaModelException e) { 276 throw e; 277 } catch (CoreException e) { 278 throw new JavaModelException(e); 279 } 280 281 if (rewrite != null){ 283 boolean wasReadOnly = destFile.isReadOnly(); 284 try { 285 saveContent(dest, destName, rewrite, sourceEncoding, destFile); 286 } catch (CoreException e) { 287 if (e instanceof JavaModelException) throw (JavaModelException) e; 288 throw new JavaModelException(e); 289 } finally { 290 Util.setReadOnly(destFile, wasReadOnly); 291 } 292 } 293 294 prepareDeltas(source, destCU, isMove()); 296 if (newCUName != null) { 297 String oldName = Util.getNameWithoutJavaLikeExtension(source.getElementName()); 299 String newName = Util.getNameWithoutJavaLikeExtension(newCUName); 300 prepareDeltas(source.getType(oldName), destCU.getType(newName), isMove()); 301 } 302 } else { 303 if (!this.force) { 304 throw new JavaModelException(new JavaModelStatus( 305 IJavaModelStatusConstants.NAME_COLLISION, 306 Messages.bind(Messages.status_nameCollision, destFile.getFullPath().toString()))); 307 } 308 if (rewrite != null){ 312 saveContent(dest, destName, rewrite, sourceEncoding, destFile); 313 } 314 } 315 } 316 319 protected void processDeltas() { 320 for (Iterator deltas = this.deltasPerProject.values().iterator(); deltas.hasNext();){ 321 addDelta((IJavaElementDelta) deltas.next()); 322 } 323 } 324 330 protected void processElement(IJavaElement element) throws JavaModelException { 331 IJavaElement dest = getDestinationParent(element); 332 switch (element.getElementType()) { 333 case IJavaElement.COMPILATION_UNIT : 334 processCompilationUnitResource((ICompilationUnit) element, (PackageFragment) dest); 335 createdElements.add(((IPackageFragment) dest).getCompilationUnit(element.getElementName())); 336 break; 337 case IJavaElement.PACKAGE_FRAGMENT : 338 processPackageFragmentResource((PackageFragment) element, (PackageFragmentRoot) dest, getNewNameFor(element)); 339 break; 340 default : 341 throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element)); 342 } 343 } 344 349 protected void processElements() throws JavaModelException { 350 createdElements = new ArrayList(elementsToProcess.length); 351 try { 352 super.processElements(); 353 } catch (JavaModelException jme) { 354 throw jme; 355 } finally { 356 resultElements = new IJavaElement[createdElements.size()]; 357 createdElements.toArray(resultElements); 358 processDeltas(); 359 } 360 } 361 368 private void processPackageFragmentResource(PackageFragment source, PackageFragmentRoot root, String newName) throws JavaModelException { 369 try { 370 String [] newFragName = (newName == null) ? source.names : Util.getTrimmedSimpleNames(newName); 371 IPackageFragment newFrag = root.getPackageFragment(newFragName); 372 IResource[] resources = collectResourcesOfInterest(source); 373 374 boolean shouldMoveFolder = isMove() && !newFrag.getResource().exists(); IFolder srcFolder = (IFolder)source.getResource(); 377 IPath destPath = newFrag.getPath(); 378 if (shouldMoveFolder) { 379 if (srcFolder.getFullPath().isPrefixOf(destPath)) { 381 shouldMoveFolder = false; 382 } else { 383 IResource[] members = srcFolder.members(); 385 for (int i = 0; i < members.length; i++) { 386 if ( members[i] instanceof IFolder) { 387 shouldMoveFolder = false; 388 break; 389 } 390 } 391 } 392 } 393 boolean containsReadOnlySubPackageFragments = createNeededPackageFragments((IContainer) source.getParent().getResource(), root, newFragName, shouldMoveFolder); 394 boolean sourceIsReadOnly = Util.isReadOnly(srcFolder); 395 396 if (shouldMoveFolder) { 398 if (sourceIsReadOnly) { 401 Util.setReadOnly(srcFolder, false); 402 } 403 srcFolder.move(destPath, force, true , getSubProgressMonitor(1)); 404 if (sourceIsReadOnly) { 405 Util.setReadOnly(srcFolder, true); 406 } 407 setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 408 } else { 409 if (resources.length > 0) { 411 if (isRename()) { 412 if (! destPath.equals(source.getPath())) { 413 moveResources(resources, destPath); 414 } 415 } else if (isMove()) { 416 for (int i = 0, max = resources.length; i < max; i++) { 418 IResource destinationResource = ResourcesPlugin.getWorkspace().getRoot().findMember(destPath.append(resources[i].getName())); 419 if (destinationResource != null) { 420 if (force) { 421 deleteResource(destinationResource, IResource.KEEP_HISTORY); 422 } else { 423 throw new JavaModelException(new JavaModelStatus( 424 IJavaModelStatusConstants.NAME_COLLISION, 425 Messages.bind(Messages.status_nameCollision, destinationResource.getFullPath().toString()))); 426 } 427 } 428 } 429 moveResources(resources, destPath); 430 } else { 431 for (int i = 0, max = resources.length; i < max; i++) { 433 IResource destinationResource = ResourcesPlugin.getWorkspace().getRoot().findMember(destPath.append(resources[i].getName())); 434 if (destinationResource != null) { 435 if (force) { 436 deleteResource(destinationResource, IResource.KEEP_HISTORY); 438 } else { 439 throw new JavaModelException(new JavaModelStatus( 440 IJavaModelStatusConstants.NAME_COLLISION, 441 Messages.bind(Messages.status_nameCollision, destinationResource.getFullPath().toString()))); 442 } 443 } 444 } 445 copyResources(resources, destPath); 446 } 447 } 448 } 449 450 if (!Util.equalArraysOrNull(newFragName, source.names)) { char[][] inclusionPatterns = root.fullInclusionPatternChars(); 453 char[][] exclusionPatterns = root.fullExclusionPatternChars(); 454 for (int i = 0; i < resources.length; i++) { 455 String resourceName = resources[i].getName(); 456 if (Util.isJavaLikeFileName(resourceName)) { 457 ICompilationUnit cu = newFrag.getCompilationUnit(resourceName); 459 if (Util.isExcluded(cu.getPath(), inclusionPatterns, exclusionPatterns, false)) continue; 460 this.parser.setSource(cu); 461 CompilationUnit astCU = (CompilationUnit) this.parser.createAST(this.progressMonitor); 462 AST ast = astCU.getAST(); 463 ASTRewrite rewrite = ASTRewrite.create(ast); 464 updatePackageStatement(astCU, newFragName, rewrite); 465 IDocument document = getDocument(cu); 466 TextEdit edits = rewrite.rewriteAST(document, null); 467 try { 468 edits.apply(document); 469 } catch (BadLocationException e) { 470 throw new JavaModelException(e, IJavaModelStatusConstants.INVALID_CONTENTS); 471 } 472 cu.save(null, false); 473 } 474 } 475 } 476 477 boolean isEmpty = true; 479 if (isMove()) { 480 updateReadOnlyPackageFragmentsForMove((IContainer) source.getParent().getResource(), root, newFragName, sourceIsReadOnly); 483 if (srcFolder.exists()) { 484 IResource[] remaining = srcFolder.members(); 485 for (int i = 0, length = remaining.length; i < length; i++) { 486 IResource file = remaining[i]; 487 if (file instanceof IFile) { 488 if (Util.isReadOnly(file)) { 489 Util.setReadOnly(file, false); 490 } 491 this.deleteResource(file, IResource.FORCE | IResource.KEEP_HISTORY); 492 } else { 493 isEmpty = false; 494 } 495 } 496 } 497 if (isEmpty) { 498 IResource rootResource; 499 if (destPath.isPrefixOf(srcFolder.getFullPath())) { 501 rootResource = newFrag.getResource(); 502 } else { 503 rootResource = source.getParent().getResource(); 504 } 505 506 deleteEmptyPackageFragment(source, false, rootResource); 508 } 509 } else if (containsReadOnlySubPackageFragments) { 510 updateReadOnlyPackageFragmentsForCopy((IContainer) source.getParent().getResource(), root, newFragName); 512 } 513 if (isEmpty && isMove() && !(Util.isExcluded(source) || Util.isExcluded(newFrag))) { 515 IJavaProject sourceProject = source.getJavaProject(); 516 getDeltaFor(sourceProject).movedFrom(source, newFrag); 517 IJavaProject destProject = newFrag.getJavaProject(); 518 getDeltaFor(destProject).movedTo(newFrag, source); 519 } 520 } catch (JavaModelException e) { 521 throw e; 522 } catch (CoreException ce) { 523 throw new JavaModelException(ce); 524 } 525 } 526 private void saveContent(PackageFragment dest, String destName, ASTRewrite rewrite, String sourceEncoding, IFile destFile) throws JavaModelException { 527 try { 528 if (sourceEncoding != null) destFile.setCharset(sourceEncoding, this.progressMonitor); 531 } 533 catch (CoreException ce) { 534 } 536 Util.setReadOnly(destFile, false); 540 ICompilationUnit destCU = dest.getCompilationUnit(destName); 541 IDocument document = getDocument(destCU); 542 TextEdit edits = rewrite.rewriteAST(document, null); 543 try { 544 edits.apply(document); 545 } catch (BadLocationException e) { 546 throw new JavaModelException(e, IJavaModelStatusConstants.INVALID_CONTENTS); 547 } 548 destCU.save(getSubProgressMonitor(1), this.force); 549 } 550 556 private ASTRewrite updateContent(ICompilationUnit cu, PackageFragment dest, String newName) throws JavaModelException { 557 String [] currPackageName = ((PackageFragment) cu.getParent()).names; 558 String [] destPackageName = dest.names; 559 if (Util.equalArraysOrNull(currPackageName, destPackageName) && newName == null) { 560 return null; } else { 562 cu.makeConsistent(this.progressMonitor); 564 this.parser.setSource(cu); 565 CompilationUnit astCU = (CompilationUnit) this.parser.createAST(this.progressMonitor); 566 AST ast = astCU.getAST(); 567 ASTRewrite rewrite = ASTRewrite.create(ast); 568 updateTypeName(cu, astCU, cu.getElementName(), newName, rewrite); 569 updatePackageStatement(astCU, destPackageName, rewrite); 570 return rewrite; 571 } 572 } 573 private void updatePackageStatement(CompilationUnit astCU, String [] pkgName, ASTRewrite rewriter) throws JavaModelException { 574 boolean defaultPackage = pkgName.length == 0; 575 AST ast = astCU.getAST(); 576 if (defaultPackage) { 577 if (astCU.getPackage() != null) 579 rewriter.set(astCU, CompilationUnit.PACKAGE_PROPERTY, null, null); 580 } else { 581 org.eclipse.jdt.core.dom.PackageDeclaration pkg = astCU.getPackage(); 582 if (pkg != null) { 583 Name name = ast.newName(pkgName); 585 rewriter.set(pkg, PackageDeclaration.NAME_PROPERTY, name, null); 586 } else { 587 pkg = ast.newPackageDeclaration(); 589 pkg.setName(ast.newName(pkgName)); 590 rewriter.set(astCU, CompilationUnit.PACKAGE_PROPERTY, pkg, null); 591 } 592 } 593 } 594 595 private void updateReadOnlyPackageFragmentsForCopy(IContainer sourceFolder, IPackageFragmentRoot root, String [] newFragName) { 596 IContainer parentFolder = (IContainer) root.getResource(); 597 for (int i = 0, length = newFragName.length; i <length; i++) { 598 String subFolderName = newFragName[i]; 599 parentFolder = parentFolder.getFolder(new Path(subFolderName)); 600 sourceFolder = sourceFolder.getFolder(new Path(subFolderName)); 601 if (sourceFolder.exists() && Util.isReadOnly(sourceFolder)) { 602 Util.setReadOnly(parentFolder, true); 603 } 604 } 605 } 606 607 private void updateReadOnlyPackageFragmentsForMove(IContainer sourceFolder, IPackageFragmentRoot root, String [] newFragName, boolean sourceFolderIsReadOnly) { 608 IContainer parentFolder = (IContainer) root.getResource(); 609 for (int i = 0, length = newFragName.length; i < length; i++) { 610 String subFolderName = newFragName[i]; 611 parentFolder = parentFolder.getFolder(new Path(subFolderName)); 612 sourceFolder = sourceFolder.getFolder(new Path(subFolderName)); 613 if ((sourceFolder.exists() && Util.isReadOnly(sourceFolder)) || (i == length - 1 && sourceFolderIsReadOnly)) { 614 Util.setReadOnly(parentFolder, true); 615 Util.setReadOnly(sourceFolder, false); 617 } 618 } 619 } 620 623 private void updateTypeName(ICompilationUnit cu, CompilationUnit astCU, String oldName, String newName, ASTRewrite rewriter) throws JavaModelException { 624 if (newName != null) { 625 String oldTypeName= Util.getNameWithoutJavaLikeExtension(oldName); 626 String newTypeName= Util.getNameWithoutJavaLikeExtension(newName); 627 AST ast = astCU.getAST(); 628 IType[] types = cu.getTypes(); 630 for (int i = 0, max = types.length; i < max; i++) { 631 IType currentType = types[i]; 632 if (currentType.getElementName().equals(oldTypeName)) { 633 AbstractTypeDeclaration typeNode = (AbstractTypeDeclaration) ((JavaElement) currentType).findNode(astCU); 634 if (typeNode != null) { 635 rewriter.replace(typeNode.getName(), ast.newSimpleName(newTypeName), null); 637 Iterator bodyDeclarations = typeNode.bodyDeclarations().iterator(); 639 while (bodyDeclarations.hasNext()) { 640 Object bodyDeclaration = bodyDeclarations.next(); 641 if (bodyDeclaration instanceof MethodDeclaration) { 642 MethodDeclaration methodDeclaration = (MethodDeclaration) bodyDeclaration; 643 if (methodDeclaration.isConstructor()) { 644 SimpleName methodName = methodDeclaration.getName(); 645 if (methodName.getIdentifier().equals(oldTypeName)) { 646 rewriter.replace(methodName, ast.newSimpleName(newTypeName), null); 647 } 648 } 649 } 650 } 651 } 652 } 653 } 654 } 655 } 656 664 protected IJavaModelStatus verify() { 665 IJavaModelStatus status = super.verify(); 666 if (!status.isOK()) { 667 return status; 668 } 669 670 if (this.renamingsList != null && this.renamingsList.length != elementsToProcess.length) { 671 return new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS); 672 } 673 return JavaModelStatus.VERIFIED_OK; 674 } 675 678 protected void verify(IJavaElement element) throws JavaModelException { 679 if (element == null || !element.exists()) 680 error(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, element); 681 682 if (element.isReadOnly() && (isRename() || isMove())) 683 error(IJavaModelStatusConstants.READ_ONLY, element); 684 685 IResource resource = element.getResource(); 686 if (resource instanceof IFolder) { 687 if (resource.isLinked()) { 688 error(IJavaModelStatusConstants.INVALID_RESOURCE, element); 689 } 690 } 691 692 int elementType = element.getElementType(); 693 694 if (elementType == IJavaElement.COMPILATION_UNIT) { 695 org.eclipse.jdt.internal.core.CompilationUnit compilationUnit = (org.eclipse.jdt.internal.core.CompilationUnit) element; 696 if (isMove() && compilationUnit.isWorkingCopy() && !compilationUnit.isPrimary()) 697 error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element); 698 } else if (elementType != IJavaElement.PACKAGE_FRAGMENT) { 699 error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element); 700 } 701 702 JavaElement dest = (JavaElement) getDestinationParent(element); 703 verifyDestination(element, dest); 704 if (this.renamings != null) { 705 verifyRenaming(element); 706 } 707 } 708 } 709 | Popular Tags |