blob: b15bff5c38eb7bc82a110b3ce2c86d5dd7750403 [file] [log] [blame]
/*******************************************************************************
* 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 org.eclipse.jdt.internal.ui.refactoring;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.text.Assert;
import org.eclipse.jface.text.IRewriteTarget;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.ui.IEditorPart;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.corext.refactoring.base.ChangeAbortException;
import org.eclipse.jdt.internal.corext.refactoring.base.ChangeContext;
import org.eclipse.jdt.internal.corext.refactoring.base.IChange;
import org.eclipse.jdt.internal.corext.refactoring.base.IRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.base.IUndoManager;
import org.eclipse.jdt.internal.corext.refactoring.base.Refactoring;
import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatus;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.refactoring.changes.AbortChangeExceptionHandler;
import org.eclipse.jdt.internal.ui.refactoring.changes.ChangeExceptionHandler;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
/**
* A helper class to execute a refactoring. The class takes care of pushing the
* undo change onto the undo stack and folding editor edits into one editor
* undo object.
*/
public class RefactoringExecutionHelper {
private IRefactoring fRefactoring;
private Shell fParent;
private IRunnableContext fExecContext;
private int fStopSeverity;
private ChangeContext fContext;
private class Operation implements IRunnableWithProgress {
public IChange fChange;
public void run(IProgressMonitor pm) throws InvocationTargetException, InterruptedException {
try {
pm.beginTask("", 10); //$NON-NLS-1$
pm.subTask(""); //$NON-NLS-1$
RefactoringStatus status= fRefactoring.checkPreconditions(new SubProgressMonitor(pm, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
if (status.getSeverity() >= fStopSeverity) {
RefactoringStatusDialog dialog= new RefactoringStatusDialog(fParent, status, fRefactoring.getName(), false);
if(dialog.open() == IDialogConstants.CANCEL_ID) {
throw new InterruptedException();
}
}
fChange= fRefactoring.createChange(new SubProgressMonitor(pm, 2, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
try {
fChange.aboutToPerform(fContext, new NullProgressMonitor());
JavaCore.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
fChange.perform(fContext, monitor);
}
}, new SubProgressMonitor(pm, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
} finally {
fChange.performed();
}
} catch (ChangeAbortException e) {
throw new InvocationTargetException(e);
} catch (CoreException e) {
throw new InvocationTargetException(e);
} finally {
pm.done();
}
}
public boolean isExecuted() {
return fChange != null;
}
public boolean isUndoable() {
return fChange.isUndoable();
}
public IChange getUndoChange() {
return fChange.getUndoChange();
}
}
public RefactoringExecutionHelper(IRefactoring refactoring, int stopSevertity, Shell parent, IRunnableContext context) {
super();
Assert.isNotNull(refactoring);
Assert.isNotNull(parent);
Assert.isNotNull(context);
fRefactoring= refactoring;
fStopSeverity= stopSevertity;
fParent= parent;
fExecContext= context;
}
public void perform() throws InterruptedException, InvocationTargetException {
RefactoringSaveHelper saveHelper= new RefactoringSaveHelper();
if (!saveHelper.saveEditors())
throw new InterruptedException();
fContext= new ChangeContext(new ChangeExceptionHandler(fParent));
boolean success= false;
IUndoManager undoManager= Refactoring.getUndoManager();
Operation op= new Operation();
IRewriteTarget[] targets= null;
try{
targets= getRewriteTargets();
beginCompoundChange(targets);
undoManager.aboutToPerformRefactoring();
fExecContext.run(false, false, op);
if (op.isExecuted()) {
if (!op.isUndoable()) {
success= false;
} else {
undoManager.addUndo(fRefactoring.getName(), op.getUndoChange());
success= true;
}
}
} catch (InvocationTargetException e) {
Throwable t= e.getTargetException();
if (t instanceof ChangeAbortException) {
handleChangeAbortException((ChangeAbortException)t);
} else {
throw e;
}
} finally {
fContext.clearPerformedChanges();
undoManager.refactoringPerformed(success);
saveHelper.triggerBuild();
if (targets != null)
endCompoundChange(targets);
}
}
private void handleChangeAbortException(ChangeAbortException exception) {
if (!fContext.getTryToUndo())
return;
IRunnableWithProgress op= new IRunnableWithProgress() {
public void run(IProgressMonitor pm) throws InterruptedException, InvocationTargetException {
try {
JavaCore.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor pm) throws CoreException {
ChangeContext undoContext= new ChangeContext(new AbortChangeExceptionHandler());
IChange[] changes= fContext.getPerformedChanges();
pm.beginTask(RefactoringMessages.getString("RefactoringWizard.undoing"), changes.length); //$NON-NLS-1$
IProgressMonitor sub= new NullProgressMonitor();
for (int i= changes.length - 1; i >= 0; i--) {
IChange change= changes[i];
pm.subTask(change.getName());
change.getUndoChange().perform(undoContext, sub);
pm.worked(1);
}
}
}, pm);
} catch (ChangeAbortException e) {
throw new InvocationTargetException(e.getThrowable());
} catch (CoreException e) {
throw new InvocationTargetException(e);
} finally {
pm.done();
}
}
};
try {
fExecContext.run(false, false, op);
} catch (InvocationTargetException e) {
handleUnexpectedException(e);
} catch (InterruptedException e) {
// not possible. Operation not cancelable.
}
}
private void handleUnexpectedException(InvocationTargetException e) {
ExceptionHandler.handle(e, RefactoringMessages.getString("RefactoringWizard.refactoring"), RefactoringMessages.getString("RefactoringWizard.unexpected_exception_1")); //$NON-NLS-2$ //$NON-NLS-1$
}
private static void beginCompoundChange(IRewriteTarget[] targets) {
for (int i= 0; i < targets.length; i++) {
targets[i].beginCompoundChange();
}
}
private static void endCompoundChange(IRewriteTarget[] targets) {
for (int i= 0; i < targets.length; i++) {
targets[i].endCompoundChange();
}
}
private static IRewriteTarget[] getRewriteTargets() {
IEditorPart[] editors= JavaPlugin.getInstanciatedEditors();
List result= new ArrayList(editors.length);
for (int i= 0; i < editors.length; i++) {
IRewriteTarget target= (IRewriteTarget)editors[i].getAdapter(IRewriteTarget.class);
if (target != null) {
result.add(target);
}
}
return (IRewriteTarget[]) result.toArray(new IRewriteTarget[result.size()]);
}
}