001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.corext.refactoring.changes;
011:
012: import java.io.IOException;
013: import java.io.InputStream;
014: import java.io.InputStreamReader;
015: import java.io.UnsupportedEncodingException;
016: import java.util.HashMap;
017: import java.util.Iterator;
018: import java.util.Map.Entry;
019:
020: import org.eclipse.text.edits.ReplaceEdit;
021:
022: import org.eclipse.core.runtime.Assert;
023: import org.eclipse.core.runtime.CoreException;
024: import org.eclipse.core.runtime.IPath;
025: import org.eclipse.core.runtime.IProgressMonitor;
026: import org.eclipse.core.runtime.IStatus;
027: import org.eclipse.core.runtime.NullProgressMonitor;
028: import org.eclipse.core.runtime.Status;
029: import org.eclipse.core.runtime.SubProgressMonitor;
030:
031: import org.eclipse.core.filebuffers.FileBuffers;
032: import org.eclipse.core.filebuffers.ITextFileBufferManager;
033: import org.eclipse.core.filebuffers.LocationKind;
034:
035: import org.eclipse.core.resources.IFile;
036: import org.eclipse.core.resources.IResource;
037:
038: import org.eclipse.ui.ide.undo.ResourceDescription;
039:
040: import org.eclipse.ltk.core.refactoring.Change;
041: import org.eclipse.ltk.core.refactoring.CompositeChange;
042: import org.eclipse.ltk.core.refactoring.NullChange;
043: import org.eclipse.ltk.core.refactoring.RefactoringStatus;
044: import org.eclipse.ltk.core.refactoring.TextFileChange;
045:
046: import org.eclipse.jdt.core.IJavaProject;
047: import org.eclipse.jdt.core.IPackageFragmentRoot;
048: import org.eclipse.jdt.core.JavaCore;
049: import org.eclipse.jdt.core.JavaModelException;
050:
051: import org.eclipse.jdt.internal.corext.Corext;
052: import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
053: import org.eclipse.jdt.internal.corext.refactoring.reorg.IPackageFragmentRootManipulationQuery;
054: import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
055: import org.eclipse.jdt.internal.corext.util.Messages;
056:
057: import org.eclipse.jdt.internal.ui.JavaPlugin;
058:
059: public class DeletePackageFragmentRootChange extends
060: AbstractDeleteChange {
061:
062: private final String fHandle;
063: private final boolean fIsExecuteChange;
064: private final IPackageFragmentRootManipulationQuery fUpdateClasspathQuery;
065:
066: public DeletePackageFragmentRootChange(IPackageFragmentRoot root,
067: boolean isExecuteChange,
068: IPackageFragmentRootManipulationQuery updateClasspathQuery) {
069: Assert.isNotNull(root);
070: Assert.isTrue(!root.isExternal());
071: fHandle = root.getHandleIdentifier();
072: fIsExecuteChange = isExecuteChange;
073: fUpdateClasspathQuery = updateClasspathQuery;
074: }
075:
076: public String getName() {
077: String[] keys = { getRoot().getElementName() };
078: return Messages
079: .format(
080: RefactoringCoreMessages.DeletePackageFragmentRootChange_delete,
081: keys);
082: }
083:
084: public Object getModifiedElement() {
085: return getRoot();
086: }
087:
088: private IPackageFragmentRoot getRoot() {
089: return (IPackageFragmentRoot) JavaCore.create(fHandle);
090: }
091:
092: public RefactoringStatus isValid(IProgressMonitor pm)
093: throws CoreException {
094: if (fIsExecuteChange) {
095: // don't check for read-only resources since we already
096: // prompt the user via a dialog to confirm deletion of
097: // read only resource. The change is currently not used
098: // as
099: return super .isValid(pm, DIRTY);
100: } else {
101: return super .isValid(pm, READ_ONLY | DIRTY);
102: }
103: }
104:
105: protected Change doDelete(IProgressMonitor pm) throws CoreException {
106: if (!confirmDeleteIfReferenced())
107: return new NullChange();
108: int resourceUpdateFlags = IResource.KEEP_HISTORY;
109: int jCoreUpdateFlags = IPackageFragmentRoot.ORIGINATING_PROJECT_CLASSPATH
110: | IPackageFragmentRoot.OTHER_REFERRING_PROJECTS_CLASSPATH;
111:
112: pm.beginTask("", 2); //$NON-NLS-1$
113: IPackageFragmentRoot root = getRoot();
114: IResource rootResource = root.getResource();
115: CompositeChange result = new CompositeChange(getName());
116:
117: ResourceDescription rootDescription = ResourceDescription
118: .fromResource(rootResource);
119: IJavaProject[] referencingProjects = JavaElementUtil
120: .getReferencingProjects(root);
121: HashMap/*<IFile, String>*/classpathFilesContents = new HashMap();
122: for (int i = 0; i < referencingProjects.length; i++) {
123: IJavaProject javaProject = referencingProjects[i];
124: IFile classpathFile = javaProject.getProject().getFile(
125: ".classpath"); //$NON-NLS-1$
126: if (classpathFile.exists()) {
127: classpathFilesContents.put(classpathFile,
128: getFileContents(classpathFile));
129: }
130: }
131:
132: root.delete(resourceUpdateFlags, jCoreUpdateFlags,
133: new SubProgressMonitor(pm, 1));
134:
135: rootDescription.recordStateFromHistory(rootResource,
136: new SubProgressMonitor(pm, 1));
137: for (Iterator iterator = classpathFilesContents.entrySet()
138: .iterator(); iterator.hasNext();) {
139: Entry entry = (Entry) iterator.next();
140: IFile file = (IFile) entry.getKey();
141: String contents = (String) entry.getValue();
142: //Restore time stamps? This should probably be some sort of UndoTextFileChange.
143: TextFileChange classpathUndo = new TextFileChange(
144: Messages
145: .format(
146: RefactoringCoreMessages.DeletePackageFragmentRootChange_restore_file,
147: file.getFullPath().toOSString()),
148: file);
149: classpathUndo.setEdit(new ReplaceEdit(0,
150: getFileLength(file), contents));
151: result.add(classpathUndo);
152: }
153: result.add(new UndoDeleteResourceChange(rootDescription));
154:
155: pm.done();
156: return result;
157: }
158:
159: private static String getFileContents(IFile file)
160: throws CoreException {
161: ITextFileBufferManager manager = FileBuffers
162: .getTextFileBufferManager();
163: IPath path = file.getFullPath();
164: manager.connect(path, LocationKind.IFILE,
165: new NullProgressMonitor());
166: try {
167: return manager.getTextFileBuffer(path, LocationKind.IFILE)
168: .getDocument().get();
169: } finally {
170: manager.disconnect(path, LocationKind.IFILE,
171: new NullProgressMonitor());
172: }
173: }
174:
175: private static int getFileLength(IFile file) throws CoreException {
176: // Cannot use file buffers here, since they are not yet in sync at this point.
177: InputStream contents = file.getContents();
178: InputStreamReader reader;
179: try {
180: reader = new InputStreamReader(contents, file.getCharset());
181: } catch (UnsupportedEncodingException e) {
182: JavaPlugin.log(e);
183: reader = new InputStreamReader(contents);
184: }
185: try {
186: return (int) reader.skip(Integer.MAX_VALUE);
187: } catch (IOException e) {
188: throw new CoreException(new Status(IStatus.ERROR, Corext
189: .getPluginId(), e.getMessage(), e));
190: }
191: }
192:
193: private boolean confirmDeleteIfReferenced()
194: throws JavaModelException {
195: if (!getRoot().isArchive()) //for source folders, you don't ask, just do it
196: return true;
197: if (fUpdateClasspathQuery == null)
198: return true;
199: IJavaProject[] referencingProjects = JavaElementUtil
200: .getReferencingProjects(getRoot());
201: if (referencingProjects.length <= 1)
202: return true;
203: return fUpdateClasspathQuery.confirmManipulation(getRoot(),
204: referencingProjects);
205: }
206: }
|