/******************************************************************************* * 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.JavaCore; import net.sourceforge.phpdt.core.JavaModelException; 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.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.getResourceAttributes().isReadOnly()) {
parentFolder.getResourceAttributes().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 operation
* newCUName
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 e = domCU.getChildren();
while (e.hasMoreElements()) {
IDOMNode node = (IDOMNode) e.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.ProjectPrefUtil.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:
*