/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.internal.core; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import net.sourceforge.phpdt.core.IBuffer; import net.sourceforge.phpdt.core.ICompilationUnit; import net.sourceforge.phpdt.core.IJavaElement; import net.sourceforge.phpdt.core.IJavaElementDelta; import net.sourceforge.phpdt.core.IJavaModelStatus; import net.sourceforge.phpdt.core.IJavaModelStatusConstants; import net.sourceforge.phpdt.core.IJavaProject; import net.sourceforge.phpdt.core.IPackageFragment; import net.sourceforge.phpdt.core.IPackageFragmentRoot; import net.sourceforge.phpdt.core.IType; import net.sourceforge.phpdt.core.JavaModelException; import net.sourceforge.phpdt.core.JavaCore; import net.sourceforge.phpdt.core.jdom.DOMException; import net.sourceforge.phpdt.core.jdom.DOMFactory; import net.sourceforge.phpdt.core.jdom.IDOMCompilationUnit; import net.sourceforge.phpdt.core.jdom.IDOMNode; import net.sourceforge.phpdt.core.jdom.IDOMPackage; import net.sourceforge.phpdt.internal.core.util.Util; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; /** * This operation copies/moves/renames a collection of resources from their current * container to a new container, optionally renaming the * elements. *
Notes:
DOMFactory
used to manipulate the source code of
* ICompilationUnit
.
*/
protected DOMFactory fFactory;
/**
* The list of new resources created during this operation.
*/
protected ArrayList fCreatedElements;
/**
* When executed, this operation will copy the given resources to the
* given containers. The resources and destination containers must be in
* the correct order. If there is > 1 destination, the number of destinations
* must be the same as the number of resources being copied/moved.
*/
public CopyResourceElementsOperation(IJavaElement[] resourcesToCopy, IJavaElement[] destContainers, boolean force) {
super(resourcesToCopy, destContainers, force);
fFactory = new DOMFactory();
}
/**
* When executed, this operation will copy the given resources to the
* given container.
*/
public CopyResourceElementsOperation(IJavaElement[] resourcesToCopy, IJavaElement destContainer, boolean force) {
this(resourcesToCopy, new IJavaElement[]{destContainer}, force);
}
/**
* Returns the children of source
which are affected by this operation.
* If source
is a K_SOURCE
, these are the .java
* files, if it is a K_BINARY
, they are the .class
files.
*/
private IResource[] collectResourcesOfInterest(IPackageFragment source) throws JavaModelException {
IJavaElement[] children = source.getChildren();
int childOfInterest = IJavaElement.COMPILATION_UNIT;
// if (source.getKind() == IPackageFragmentRoot.K_BINARY) {
// childOfInterest = IJavaElement.CLASS_FILE;
// }
ArrayList correctKindChildren = new ArrayList(children.length);
for (int i = 0; i < children.length; i++) {
IJavaElement child = children[i];
if (child.getElementType() == childOfInterest) {
correctKindChildren.add(child.getResource());
}
}
// Gather non-java resources
// Object[] nonJavaResources = source.getNonJavaResources();
// int actualNonJavaResourceCount = 0;
// for (int i = 0, max = nonJavaResources.length; i < max; i++){
// if (nonJavaResources[i] instanceof IResource) actualNonJavaResourceCount++;
// }
// IResource[] actualNonJavaResources = new IResource[actualNonJavaResourceCount];
// for (int i = 0, max = nonJavaResources.length, index = 0; i < max; i++){
// if (nonJavaResources[i] instanceof IResource) actualNonJavaResources[index++] = (IResource)nonJavaResources[i];
// }
// if (actualNonJavaResourceCount != 0) {
// int correctKindChildrenSize = correctKindChildren.size();
// IResource[] result = new IResource[correctKindChildrenSize + actualNonJavaResourceCount];
// correctKindChildren.toArray(result);
// System.arraycopy(actualNonJavaResources, 0, result, correctKindChildrenSize, actualNonJavaResourceCount);
// return result;
// } else {
IResource[] result = new IResource[correctKindChildren.size()];
correctKindChildren.toArray(result);
return result;
// }
}
/**
* Creates any destination package fragment(s) which do not exists yet.
*/
private void createNeededPackageFragments(IContainer sourceFolder, IPackageFragmentRoot root, String newFragName, boolean moveFolder) throws JavaModelException {
IContainer parentFolder = (IContainer) root.getResource();
JavaElementDelta projectDelta = null;
String[] names = net.sourceforge.phpdt.internal.core.util.Util.getTrimmedSimpleNames(newFragName);
StringBuffer sideEffectPackageName = new StringBuffer();
char[][] exclusionsPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars();
for (int i = 0; i < names.length; i++) {
String subFolderName = names[i];
sideEffectPackageName.append(subFolderName);
IResource subFolder = parentFolder.findMember(subFolderName);
if (subFolder == null) {
// create deepest folder only if not a move (folder will be moved in processPackageFragmentResource)
if (!(moveFolder && i == names.length-1)) {
createFolder(parentFolder, subFolderName, force);
}
parentFolder = parentFolder.getFolder(new Path(subFolderName));
sourceFolder = sourceFolder.getFolder(new Path(subFolderName));
if (sourceFolder.isReadOnly()) {
parentFolder.setReadOnly(true);
}
IPackageFragment sideEffectPackage = root.getPackageFragment(sideEffectPackageName.toString());
if (i < names.length - 1 // all but the last one are side effect packages
&& !net.sourceforge.phpdt.internal.core.util.Util.isExcluded(parentFolder, exclusionsPatterns)) {
if (projectDelta == null) {
projectDelta = getDeltaFor(root.getJavaProject());
}
projectDelta.added(sideEffectPackage);
}
fCreatedElements.add(sideEffectPackage);
} else {
parentFolder = (IContainer) subFolder;
}
sideEffectPackageName.append('.');
}
}
/**
* Returns the JavaElementDelta
for javaProject
,
* creating it and putting it in fDeltasPerProject
if
* it does not exist yet.
*/
private JavaElementDelta getDeltaFor(IJavaProject javaProject) {
JavaElementDelta delta = (JavaElementDelta) fDeltasPerProject.get(javaProject);
if (delta == null) {
delta = new JavaElementDelta(javaProject);
fDeltasPerProject.put(javaProject, delta);
}
return delta;
}
/**
* @see MultiOperation
*/
protected String getMainTaskName() {
return net.sourceforge.phpdt.internal.core.util.Util.bind("operation.copyResourceProgress"); //$NON-NLS-1$
}
/**
* Sets the deltas to register the changes resulting from this operation
* for this source element and its destination.
* If the operation is a cross project operationnewCUName
* to the destination package.processCompilationUnitResource
or
* processPackageFragmentResource
, depending on the type of
* element
.
*/
protected void processElement(IJavaElement element) throws JavaModelException {
IJavaElement dest = getDestinationParent(element);
switch (element.getElementType()) {
case IJavaElement.COMPILATION_UNIT :
processCompilationUnitResource((ICompilationUnit) element, (IPackageFragment) dest);
fCreatedElements.add(((IPackageFragment) dest).getCompilationUnit(element.getElementName()));
break;
case IJavaElement.PACKAGE_FRAGMENT :
processPackageFragmentResource((IPackageFragment) element, (IPackageFragmentRoot) dest, getNewNameFor(element));
break;
default :
throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element));
}
}
/**
* @see MultiOperation
* Overridden to allow special processing of JavaElementDelta
s
* and fResultElements
.
*/
protected void processElements() throws JavaModelException {
fCreatedElements = new ArrayList(fElementsToProcess.length);
try {
super.processElements();
} catch (JavaModelException jme) {
throw jme;
} finally {
resultElements = new IJavaElement[fCreatedElements.size()];
fCreatedElements.toArray(resultElements);
processDeltas();
}
}
/**
* Copies/moves a package fragment with the name newName
* to the destination package.cu
, modifying the type name and/or package
* declaration as necessary.
*
* @return the new source
*/
private String updatedContent(ICompilationUnit cu, IPackageFragment dest, String newName) throws JavaModelException {
String currPackageName = cu.getParent().getElementName();
String destPackageName = dest.getElementName();
if (currPackageName.equals(destPackageName) && newName == null) {
return null; //nothing to change
} else {
String typeName = cu.getElementName();
typeName = typeName.substring(0, typeName.length() - 5);
IDOMCompilationUnit cuDOM = null;
IBuffer buffer = cu.getBuffer();
if (buffer == null) return null;
char[] contents = buffer.getCharacters();
if (contents == null) return null;
cuDOM = fFactory.createCompilationUnit(contents, typeName);
updateTypeName(cu, cuDOM, cu.getElementName(), newName);
updatePackageStatement(cuDOM, destPackageName);
return cuDOM.getContents();
}
}
/**
* Makes sure that cu
declares to be in the pkgName
package.
*/
private void updatePackageStatement(IDOMCompilationUnit domCU, String pkgName) throws JavaModelException {
boolean defaultPackage = pkgName.equals(IPackageFragment.DEFAULT_PACKAGE_NAME);
boolean seenPackageNode = false;
Enumeration enum = domCU.getChildren();
while (enum.hasMoreElements()) {
IDOMNode node = (IDOMNode) enum.nextElement();
if (node.getNodeType() == IDOMNode.PACKAGE) {
if (! defaultPackage) {
node.setName(pkgName);
} else {
node.remove();
}
seenPackageNode = true;
break;
}
}
if (!seenPackageNode && !defaultPackage) {
//the cu was in a default package...no package declaration
//create the new package declaration as the first child of the cu
// IDOMPackage pkg = fFactory.createPackage("package " + pkgName + ";" + net.sourceforge.phpdt.internal.compiler.util.Util.LINE_SEPARATOR); //$NON-NLS-1$ //$NON-NLS-2$
// IDOMNode firstChild = domCU.getFirstChild();
// if (firstChild != null) {
// firstChild.insertSibling(pkg);
// } // else the cu was empty: leave it empty
}
}
/**
* Renames the main type in cu
.
*/
private void updateTypeName(ICompilationUnit cu, IDOMCompilationUnit domCU, String oldName, String newName) throws JavaModelException {
if (newName != null) {
if (fRenamedCompilationUnits == null) {
fRenamedCompilationUnits= new ArrayList(1);
}
fRenamedCompilationUnits.add(cu);
String oldTypeName= oldName.substring(0, oldName.length() - 5);
String newTypeName= newName.substring(0, newName.length() - 5);
// update main type name
IType[] types = cu.getTypes();
for (int i = 0, max = types.length; i < max; i++) {
IType currentType = types[i];
if (currentType.getElementName().equals(oldTypeName)) {
IDOMNode typeNode = ((JavaElement) currentType).findNode(domCU);
if (typeNode != null) {
typeNode.setName(newTypeName);
}
}
}
}
}
/**
* Possible failures:
*