blob: 72c7bba014124c40d6093d203e35c5e24e4bf2cc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.wst.sse.ui.internal.extension;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.text.IDocument;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;
import org.eclipse.wst.sse.ui.internal.IExtendedSimpleEditor;
import org.eclipse.wst.sse.ui.internal.Logger;
import org.eclipse.wst.sse.ui.internal.provisional.extensions.ISelfValidateEditAction;
/**
* Begins and ends UndoManager recording around run() and runWithEvent(...)
*/
public class ExtendedEditorActionProxy implements InvocationHandler {
public static Object newInstance(Object obj) {
Set set = new HashSet();
Class clazz = obj.getClass();
while (clazz != null) {
Class[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
set.add(interfaces[i]);
}
clazz = clazz.getSuperclass();
}
Class[] classes = new Class[set.size()];
Iterator itr = set.iterator();
int i = 0;
while (itr.hasNext()) {
classes[i] = (Class) itr.next();
i++;
}
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), classes, new ExtendedEditorActionProxy(obj));
}
private IExtendedSimpleEditor editor = null;
private IStructuredModel fRecorder;
private Object obj;
private ExtendedEditorActionProxy(Object obj) {
this.obj = obj;
}
private void beginRecording() {
IDocument document = null;
if (editor != null) {
document = editor.getDocument();
if (document != null)
fRecorder = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
// Prepare for Undo
if (fRecorder != null) {
IStructuredTextUndoManager um = fRecorder.getUndoManager();
if (um != null) {
um.beginRecording(this, ((IAction) this.obj).getText(), ((IAction) this.obj).getDescription());
}
}
}
}
private void endRecording() {
if (fRecorder != null) {
IStructuredTextUndoManager um = fRecorder.getUndoManager();
if (um != null) {
um.endRecording(this);
}
fRecorder.releaseFromEdit();
fRecorder = null;
}
}
/**
* @see java.lang.reflect.InvocationHandler#invoke(Object, Method,
* Object[])
*/
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object result = null;
String name = m.getName();
try {
if (name.equals("equals")) { //$NON-NLS-1$
// Workaround for JDK's bug 4652876
// "equals" always returns false even if both
// InvocationHandler
// class
// hold the same objects
// See
// http://developer.java.sun.com/developer/bugParade/bugs/4652876.html
// This problem is in the IBM SDK 1.3.1
// but I don't see the bug in Sun's JDK 1.4.1 (beta)
Object arg = args[0];
return (proxy.getClass() == arg.getClass() && equals(Proxy.getInvocationHandler(arg))) ? Boolean.TRUE : Boolean.FALSE;
} else if (name.equals("runWithEvent") || name.equals("run")) { //$NON-NLS-1$ //$NON-NLS-2$
beginRecording();
if ((editor != null) && !(this.obj instanceof ISelfValidateEditAction)) {
// TODO: cleanup validateEdit
// just leaving this check and following code here for transition.
// I assume we'll remove all need for 'validateEdit'
// or move to platform editor's validateState
// IStatus status = editor.validateEdit(getDisplay().getActiveShell());
// if (!status.isOK()) {
// return null;
// }
}
} else if (name.equals("setActiveExtendedEditor")) { //$NON-NLS-1$
if (args[0] instanceof IExtendedSimpleEditor) {
editor = (IExtendedSimpleEditor) args[0];
}
}
result = m.invoke(this.obj, args);
} catch (InvocationTargetException e) {
Logger.logException(e.getTargetException());
//throw e.getTargetException();
} catch (Exception e) {
Logger.logException(e);
if (name.equals("runWithEvent") || name.equals("run")) { //$NON-NLS-1$ //$NON-NLS-2$
// only expose user-driven exceptions from "running" to the
// user
throw new RuntimeException(e.getMessage());
}
} finally {
if (name.equals("runWithEvent") || name.equals("run")) { //$NON-NLS-1$ //$NON-NLS-2$
endRecording();
}
}
return result;
}
}