summaryrefslogtreecommitdiffstats
path: root/qtjava/javalib/org/kde/qt/Invocation.java
diff options
context:
space:
mode:
Diffstat (limited to 'qtjava/javalib/org/kde/qt/Invocation.java')
-rw-r--r--qtjava/javalib/org/kde/qt/Invocation.java527
1 files changed, 527 insertions, 0 deletions
diff --git a/qtjava/javalib/org/kde/qt/Invocation.java b/qtjava/javalib/org/kde/qt/Invocation.java
new file mode 100644
index 00000000..04a41949
--- /dev/null
+++ b/qtjava/javalib/org/kde/qt/Invocation.java
@@ -0,0 +1,527 @@
+/***************************************************************************
+ Invocation.java - description
+ -------------------
+ begin : Tue Oct 31 06:12:14 2000
+ copyright : (C) 2000-2002 Lost Highway Ltd. All rights reserved.
+ 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.kde.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 <[email protected]>
+ */
+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.qWarning("QObject.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("QObject.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 QObject.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.qWarning("Slot invocation failed");
+ e.printStackTrace();
+ return null;
+ } catch (IllegalAccessException e) {
+ Qt.qWarning("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.qWarning("Invocation failed : " + onThis.getClass().getName() + "." + methodName + "()");
+ e.printStackTrace();
+ return false;
+ } catch (IllegalAccessException e) {
+ Qt.qWarning("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 KMainWindow::queryClose() */
+ public static boolean booleanInvoke(long target, String methodName) throws NoSuchMethodException, ClassNotFoundException {
+ Method method;
+ Object onThis = qtjava.objectForQtKey(target, "QObject", 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.qWarning("Invocation failed : " + onThis.getClass().getName() + "." + methodName + "()");
+ e.printStackTrace();
+ return true;
+ } catch (IllegalAccessException e) {
+ Qt.qWarning("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.kde.qt.QObject", 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.qWarning("Event handler failed : " + onThis.getClass().getName() + "." + methodName + "(" + qtjava.toFullyQualifiedClassName(argClass) + " event)");
+ e.printStackTrace();
+ return false;
+ } catch (IllegalAccessException e) {
+ Qt.qWarning("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[] { QObject.class, QEvent.class };
+ Object onThis = qtjava.objectForQtKey(target, "QObject", 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.qWarning("Event filter failed : " + onThis.getClass().getName() + "." + methodName + "()");
+ e.printStackTrace();
+ return false;
+ } catch (IllegalAccessException e) {
+ Qt.qWarning("Event filter failed : " + onThis.getClass().getName() + "." + methodName + "()");
+ e.printStackTrace();
+ return false;
+ } finally {
+ return result.booleanValue();
+ }
+ }
+}