You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
528 lines
18 KiB
528 lines
18 KiB
/***************************************************************************
|
|
Invocation.java - description
|
|
-------------------
|
|
begin : Tue Oct 31 06:12:14 2000
|
|
copyright : (C) 2000-2002 Lost Highway Ltd. All rights reserved.
|
|
email : Lost_Highway@tipitina.demon.co.uk
|
|
written by : Richard Dale.
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
package org.trinitydesktop.qt;
|
|
|
|
import java.util.*;
|
|
import java.lang.reflect.*;
|
|
|
|
/** A utility class for creating a closure to invoke later - when a Java
|
|
slot or event handler needs to be activated
|
|
|
|
@author Richard Dale <Richard_Dale@tipitina.demon.co.uk>
|
|
*/
|
|
public class Invocation {
|
|
/** The target object */
|
|
private Object onThis;
|
|
/** Arguments from an emitted signal to pass to the slot method */
|
|
private Object[] arguments;
|
|
/** The Java method that implements the slot, (or emit() for a signal target) */
|
|
private Method method;
|
|
/** An optional instance variable, used when the target is a signal,
|
|
rather than a slot. */
|
|
private String signalName;
|
|
|
|
/** Converts a type signature from a Qt signal or slot to an array of
|
|
Class objects corresponding to the Java types of the parameters */
|
|
private static Class[] fromQtTypeSignature(String qtTypeSignature) {
|
|
ArrayList parameterTypes = new ArrayList();
|
|
StringTokenizer tokenizer = new StringTokenizer(qtTypeSignature, ",");
|
|
|
|
while (tokenizer.hasMoreTokens()) {
|
|
String token = tokenizer.nextToken();
|
|
|
|
if (token.equals("")) {
|
|
parameterTypes.add(null);
|
|
} else if (token.equals("boolean")) {
|
|
parameterTypes.add(boolean.class);
|
|
} else if (token.equals("char")) {
|
|
parameterTypes.add(char.class);
|
|
} else if (token.equals("long")) {
|
|
parameterTypes.add(long.class);
|
|
} else if (token.equals("int")) {
|
|
parameterTypes.add(int.class);
|
|
} else if (token.equals("short")) {
|
|
parameterTypes.add(short.class);
|
|
} else if (token.equals("float")) {
|
|
parameterTypes.add(float.class);
|
|
} else if (token.equals("double")) {
|
|
parameterTypes.add(double.class);
|
|
} else if (token.equals("int[]")) {
|
|
parameterTypes.add(int[].class);
|
|
} else if (token.equals("byte[]")) {
|
|
parameterTypes.add(byte[].class);
|
|
} else {
|
|
try {
|
|
parameterTypes.add(Class.forName(token));
|
|
} catch (ClassNotFoundException e) {
|
|
Qt.tqWarning("TQObject.connect: No such argument type: " + token);
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (Class[]) parameterTypes.toArray(new Class[0]);
|
|
}
|
|
|
|
/** Contained in a C++ JavaSlot instance, allows the JavaSlot to act as a proxy for the Java method to be invoked.
|
|
The method name in the slot string is converted to a Java Method instance, and the arguments to a suitable
|
|
Class[] structure, as the corresponding argument type list. */
|
|
Invocation(Object target, String receiverString) {
|
|
Method targetMethod = null;
|
|
Class targetClass = null;
|
|
String methodName;
|
|
Class[] parameterTypes;
|
|
|
|
if (receiverString.startsWith("2")) {
|
|
// Target is a signal
|
|
methodName = "emit";
|
|
parameterTypes = new Class[] {java.lang.String.class, Object[].class};
|
|
signalName = receiverString;
|
|
} else {
|
|
// Target is a slot
|
|
methodName = receiverString.substring(1, receiverString.indexOf('('));
|
|
parameterTypes = fromQtTypeSignature(receiverString.substring( receiverString.indexOf('(') + 1,
|
|
receiverString.indexOf(')') ) );
|
|
if (parameterTypes == null) {
|
|
return;
|
|
}
|
|
signalName = null;
|
|
}
|
|
|
|
// A slot can either be public or protected. However, it isn't possible
|
|
// to obtain inherited protected members using getMethod() or
|
|
// getDeclaredMethod(). Hence, the apparently over complicated loop here.
|
|
targetClass = target.getClass();
|
|
|
|
do {
|
|
try {
|
|
targetMethod = targetClass.getDeclaredMethod(methodName, parameterTypes);
|
|
} catch (NoSuchMethodException e1) {
|
|
try {
|
|
targetMethod = targetClass.getMethod(methodName, parameterTypes);
|
|
} catch (NoSuchMethodException e2) {
|
|
;
|
|
}
|
|
}
|
|
|
|
if (targetMethod != null) {
|
|
onThis = target;
|
|
arguments = null;
|
|
method = targetMethod;
|
|
method.setAccessible(true);
|
|
return;
|
|
}
|
|
|
|
targetClass = targetClass.getSuperclass();
|
|
} while (targetClass != null);
|
|
|
|
System.out.print("TQObject.connect: No such slot " + methodName + "(");
|
|
for (int index = 0; index < parameterTypes.length; index++) {
|
|
System.out.print(parameterTypes[index].toString());
|
|
|
|
if (index + 1 < parameterTypes.length) {
|
|
System.out.print(",");
|
|
}
|
|
}
|
|
System.out.println(")");
|
|
return;
|
|
}
|
|
|
|
Invocation(Object target, Object[] args, Method aMethod) {
|
|
onThis = target;
|
|
arguments = args;
|
|
method = aMethod;
|
|
method.setAccessible(true);
|
|
}
|
|
|
|
public void setArguments(Object[] args) {
|
|
arguments = args;
|
|
}
|
|
|
|
/** Not used at present, here for completeness */
|
|
public Object invoke() throws IllegalAccessException, InvocationTargetException {
|
|
try {
|
|
Object result = method.invoke(onThis, arguments);
|
|
} catch (InvocationTargetException e) {
|
|
return null;
|
|
} catch (IllegalAccessException e) {
|
|
return null;
|
|
} finally {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** Used for Java slot/signal targets, handles callbacks */
|
|
public Object invoke(Object[] args) throws IllegalAccessException, InvocationTargetException {
|
|
if (signalName != null) {
|
|
// If the target is a signal, then there are two parameters needed for TQObject.emit().
|
|
// A signal name, followed by an array of arguments to be emitted.
|
|
Object[] emitArgs = new Object[2];
|
|
emitArgs[0] = signalName;
|
|
emitArgs[1] = args;
|
|
setArguments(emitArgs);
|
|
} else {
|
|
// If the target is a slot, then just pass on the arguments to the target slot
|
|
setArguments(args);
|
|
}
|
|
|
|
try {
|
|
Object result = method.invoke(onThis, arguments);
|
|
} catch (InvocationTargetException e) {
|
|
Qt.tqWarning("Slot invocation failed");
|
|
e.printStackTrace();
|
|
return null;
|
|
} catch (IllegalAccessException e) {
|
|
Qt.tqWarning("Slot invocation failed");
|
|
e.printStackTrace();
|
|
return null;
|
|
} finally {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** Used for boolean slot handling callbacks */
|
|
public Object invoke(boolean arg) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[1];
|
|
arguments[0] = new Boolean(arg);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
/** Used for C++ sender to byte (ie unsigned char in C++) Java slot handling callbacks */
|
|
public Object invoke(byte arg) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[1];
|
|
arguments[0] = new Byte(arg);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
/** Used for C++ sender to char Java slot handling callbacks */
|
|
public Object invoke(char arg) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[1];
|
|
arguments[0] = new Character(arg);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
/** Used for C++ sender to short Java slot handling callbacks */
|
|
public Object invoke(short arg) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[1];
|
|
arguments[0] = new Short(arg);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
/** Used for C++ sender to int Java slot handling callbacks */
|
|
public Object invoke(int arg) throws IllegalAccessException, InvocationTargetException{
|
|
arguments = new Object[1];
|
|
arguments[0] = new Integer(arg);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
/** Used for C++ sender to long Java slot handling callbacks */
|
|
public Object invoke(long arg) throws IllegalAccessException, InvocationTargetException{
|
|
arguments = new Object[1];
|
|
arguments[0] = new Long(arg);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
/** Used for C++ sender float Java slot handling callbacks */
|
|
public Object invoke(float arg) throws IllegalAccessException, InvocationTargetException{
|
|
arguments = new Object[1];
|
|
arguments[0] = new Float(arg);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
/** Used for C++ sender to double Java slot handling callbacks */
|
|
public Object invoke(double arg) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[1];
|
|
arguments[0] = new Double(arg);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(Object arg) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[1];
|
|
arguments[0] = arg;
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(Object arg1, byte[] arg2) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[2];
|
|
arguments[0] = arg1;
|
|
arguments[1] = arg2;
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(Object arg1, Object arg2) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[2];
|
|
arguments[0] = arg1;
|
|
arguments[1] = arg2;
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(Object arg1, Object arg2, Object arg3) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[3];
|
|
arguments[0] = arg1;
|
|
arguments[1] = arg2;
|
|
arguments[2] = arg3;
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[4];
|
|
arguments[0] = arg1;
|
|
arguments[1] = arg2;
|
|
arguments[2] = arg3;
|
|
arguments[3] = arg4;
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(Object arg1, boolean arg2) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[2];
|
|
arguments[0] = arg1;
|
|
arguments[1] = new Boolean(arg2);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(Object arg1, Object arg2, int arg3) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[3];
|
|
arguments[0] = arg1;
|
|
arguments[1] = arg2;
|
|
arguments[2] = new Integer(arg3);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(int arg1, Object arg2) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[2];
|
|
arguments[0] = new Integer(arg1);
|
|
arguments[1] = arg2;
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(int arg1, Object arg2, Object arg3) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[3];
|
|
arguments[0] = new Integer(arg1);
|
|
arguments[1] = arg2;
|
|
arguments[2] = arg3;
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(int arg1, Object arg2, Object arg3, int arg4) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[3];
|
|
arguments[0] = new Integer(arg1);
|
|
arguments[1] = arg2;
|
|
arguments[2] = arg3;
|
|
arguments[3] = new Integer(arg4);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(int arg1, boolean arg2) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[2];
|
|
arguments[0] = new Integer(arg1);
|
|
arguments[1] = new Boolean(arg2);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(int arg1, int arg2) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[2];
|
|
arguments[0] = new Integer(arg1);
|
|
arguments[1] = new Integer(arg2);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(int arg1, int arg2, int arg3) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[3];
|
|
arguments[0] = new Integer(arg1);
|
|
arguments[1] = new Integer(arg2);
|
|
arguments[2] = new Integer(arg3);
|
|
return invoke(arguments);
|
|
}
|
|
|
|
public Object invoke(int arg1, int arg2, int arg3, Object arg4) throws IllegalAccessException, InvocationTargetException {
|
|
arguments = new Object[4];
|
|
arguments[0] = new Integer(arg1);
|
|
arguments[1] = new Integer(arg2);
|
|
arguments[2] = new Integer(arg3);
|
|
arguments[2] = arg4;
|
|
return invoke(arguments);
|
|
}
|
|
|
|
/** Invoke the named void method on the target object with no arguments. Returns true
|
|
if the target method was successfully invoked. */
|
|
public static boolean invoke(long target, String className, String methodName) throws NoSuchMethodException, ClassNotFoundException {
|
|
Method method;
|
|
Object onThis = qtjava.objectForQtKey(target, className, false);
|
|
|
|
try {
|
|
method = onThis.getClass().getMethod(methodName, (Class[]) null);
|
|
} catch (NoSuchMethodException e1) {
|
|
try {
|
|
method = onThis.getClass().getDeclaredMethod(methodName, (Class[]) null);
|
|
} catch (NoSuchMethodException e2) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Ignore any native code event handling methods
|
|
if ((method.getModifiers() & Modifier.NATIVE) != 0) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
method.setAccessible(true);
|
|
Object result = method.invoke(onThis, (Class[]) null);
|
|
return true;
|
|
} catch (InvocationTargetException e) {
|
|
Qt.tqWarning("Invocation failed : " + onThis.getClass().getName() + "." + methodName + "()");
|
|
e.printStackTrace();
|
|
return false;
|
|
} catch (IllegalAccessException e) {
|
|
Qt.tqWarning("Invocation failed : " + onThis.getClass().getName() + "." + methodName + "()");
|
|
e.printStackTrace();
|
|
return false;
|
|
}
|
|
}
|
|
/** Invoke the named method on the target object with no arguments. Returns false
|
|
iff the target method was successfully invoked AND returned false. Unlike the other
|
|
variants of boolean invoke(), this method returns true if no target java method exists.
|
|
Used for boolean callbacks such as TDEMainWindow::queryClose() */
|
|
public static boolean booleanInvoke(long target, String methodName) throws NoSuchMethodException, ClassNotFoundException {
|
|
Method method;
|
|
Object onThis = qtjava.objectForQtKey(target, "TQObject", false);
|
|
|
|
try {
|
|
method = onThis.getClass().getMethod(methodName, (Class[]) null);
|
|
} catch (NoSuchMethodException e1) {
|
|
try {
|
|
method = onThis.getClass().getDeclaredMethod(methodName, (Class[]) null);
|
|
} catch (NoSuchMethodException e2) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Ignore any native code event handling methods
|
|
if ((method.getModifiers() & Modifier.NATIVE) != 0) {
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
method.setAccessible(true);
|
|
Object result = method.invoke(onThis, (Class[]) null);
|
|
return ((Boolean) result).booleanValue();
|
|
} catch (InvocationTargetException e) {
|
|
Qt.tqWarning("Invocation failed : " + onThis.getClass().getName() + "." + methodName + "()");
|
|
e.printStackTrace();
|
|
return true;
|
|
} catch (IllegalAccessException e) {
|
|
Qt.tqWarning("Invocation failed : " + onThis.getClass().getName() + "." + methodName + "()");
|
|
e.printStackTrace();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/** Invoke the named method on the target object with a single argument. Returns true
|
|
if the method was successfully invoked, otherwise false.
|
|
Used for event handling callbacks */
|
|
public static boolean invoke(long target, long arg, String argClass, String methodName) throws NoSuchMethodException, ClassNotFoundException {
|
|
Method method = null;
|
|
Class[] parameterType = new Class[1];
|
|
parameterType[0] = Class.forName(qtjava.toFullyQualifiedClassName(argClass));
|
|
Object onThis = qtjava.objectForQtKey(target, "org.trinitydesktop.qt.TQObject", false);
|
|
|
|
Class targetClass = onThis.getClass();
|
|
|
|
do {
|
|
try {
|
|
method = targetClass.getDeclaredMethod(methodName, parameterType);
|
|
method.setAccessible(true);
|
|
break;
|
|
} catch (NoSuchMethodException e1) {
|
|
}
|
|
|
|
targetClass = targetClass.getSuperclass();
|
|
} while (targetClass != null);
|
|
|
|
if (targetClass == null) {
|
|
return false;
|
|
}
|
|
|
|
// Ignore any native code event handling methods
|
|
if ((method.getModifiers() & Modifier.NATIVE) != 0) {
|
|
return false;
|
|
}
|
|
|
|
Object[] arguments = new Object[1];
|
|
arguments[0] = qtjava.objectForQtKey(arg, argClass, false);
|
|
|
|
try {
|
|
// Invoke the event handler
|
|
Object result = method.invoke(onThis, arguments);
|
|
|
|
// The event will no longer be referenced, so force remove its java mapping entry.
|
|
qtjava.removeObjectForQtKey(arg);
|
|
} catch (InvocationTargetException e) {
|
|
Qt.tqWarning("Event handler failed : " + onThis.getClass().getName() + "." + methodName + "(" + qtjava.toFullyQualifiedClassName(argClass) + " event)");
|
|
e.printStackTrace();
|
|
return false;
|
|
} catch (IllegalAccessException e) {
|
|
Qt.tqWarning("Event handler failed : " + onThis.getClass().getName() + "." + methodName + "(" + qtjava.toFullyQualifiedClassName(argClass) + " event)");
|
|
e.printStackTrace();
|
|
return false;
|
|
} finally {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/** Invoke the named method on the target object with two arguments. Returns true
|
|
if the method was successfully invoked, otherwise false.
|
|
Used for event filter callbacks */
|
|
public static boolean invoke(long target, long arg1, String arg1class, long arg2, String arg2class, String methodName) throws NoSuchMethodException, ClassNotFoundException {
|
|
Method method;
|
|
Boolean result = null;
|
|
Object[] arguments = new Object[2];
|
|
arguments[0] = qtjava.objectForQtKey(arg1, arg1class, false);
|
|
arguments[1] = qtjava.objectForQtKey(arg2, arg2class, false);
|
|
|
|
Class[] parameterTypes = new Class[] { TQObject.class, TQEvent.class };
|
|
Object onThis = qtjava.objectForQtKey(target, "TQObject", false);
|
|
|
|
try {
|
|
method = onThis.getClass().getMethod(methodName, parameterTypes);
|
|
method.setAccessible(true);
|
|
} catch (NoSuchMethodException e) {
|
|
return false;
|
|
}
|
|
|
|
// Ignore any native code event handling methods
|
|
if ((method.getModifiers() & Modifier.NATIVE) != 0) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
result = (Boolean) method.invoke(onThis, arguments);
|
|
} catch (InvocationTargetException e) {
|
|
Qt.tqWarning("Event filter failed : " + onThis.getClass().getName() + "." + methodName + "()");
|
|
e.printStackTrace();
|
|
return false;
|
|
} catch (IllegalAccessException e) {
|
|
Qt.tqWarning("Event filter failed : " + onThis.getClass().getName() + "." + methodName + "()");
|
|
e.printStackTrace();
|
|
return false;
|
|
} finally {
|
|
return result.booleanValue();
|
|
}
|
|
}
|
|
}
|