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 *******************************************************************************/ 011package org.fusesource.hawtjni.runtime; 012 013/** 014 * Instances of this class represent entry points into Java which can be invoked 015 * from operating system level callback routines. 016 * <p> 017 * IMPORTANT: A callback is only valid when invoked on the thread which created 018 * it. The results are undefined (and typically bad) when a callback is passed 019 * out to the operating system (or other code) in such a way that the callback 020 * is called from a different thread. 021 */ 022 023public class Callback { 024 025 Object object; 026 027 String method, signature; 028 029 int argCount; 030 031 long /* int */ address, errorResult; 032 033 boolean isStatic, isArrayBased; 034 035 static final String PTR_SIGNATURE = "J"; /* C.PTR_SIZEOF == 4 ? "I" : "J"; */ 036 037 static final String SIGNATURE_0 = getSignature(0); 038 static final String SIGNATURE_1 = getSignature(1); 039 static final String SIGNATURE_2 = getSignature(2); 040 static final String SIGNATURE_3 = getSignature(3); 041 static final String SIGNATURE_4 = getSignature(4); 042 043 static final String SIGNATURE_N = "([" + PTR_SIGNATURE + ")" + PTR_SIGNATURE; 044 045 /** 046 * Constructs a new instance of this class given an object to send the 047 * message to, a string naming the method to invoke and an argument count. 048 * Note that, if the object is an instance of <code>Class</code> it is 049 * assumed that the method is a static method on that class. 050 * 051 * @param object 052 * the object to send the message to 053 * @param method 054 * the name of the method to invoke 055 * @param argCount 056 * the number of arguments that the method takes 057 */ 058 public Callback(Object object, String method, int argCount) { 059 this(object, method, argCount, false); 060 } 061 062 /** 063 * Constructs a new instance of this class given an object to send the 064 * message to, a string naming the method to invoke, an argument count and a 065 * flag indicating whether or not the arguments will be passed in an array. 066 * Note that, if the object is an instance of <code>Class</code> it is 067 * assumed that the method is a static method on that class. 068 * 069 * @param object 070 * the object to send the message to 071 * @param method 072 * the name of the method to invoke 073 * @param argCount 074 * the number of arguments that the method takes 075 * @param isArrayBased 076 * <code>true</code> if the arguments should be passed in an 077 * array and false otherwise 078 */ 079 public Callback(Object object, String method, int argCount, boolean isArrayBased) { 080 this(object, method, argCount, isArrayBased, 0); 081 } 082 083 /** 084 * Constructs a new instance of this class given an object to send the 085 * message to, a string naming the method to invoke, an argument count, a 086 * flag indicating whether or not the arguments will be passed in an array 087 * and a value to return when an exception happens. Note that, if the object 088 * is an instance of <code>Class</code> it is assumed that the method is a 089 * static method on that class. 090 * 091 * @param object 092 * the object to send the message to 093 * @param method 094 * the name of the method to invoke 095 * @param argCount 096 * the number of arguments that the method takes 097 * @param isArrayBased 098 * <code>true</code> if the arguments should be passed in an 099 * array and false otherwise 100 * @param errorResult 101 * the return value if the java code throws an exception 102 */ 103 public Callback(Object object, String method, int argCount, boolean isArrayBased, long /* int */errorResult) { 104 105 /* Set the callback fields */ 106 this.object = object; 107 this.method = method; 108 this.argCount = argCount; 109 this.isStatic = object instanceof Class<?>; 110 this.isArrayBased = isArrayBased; 111 this.errorResult = errorResult; 112 113 /* Inline the common cases */ 114 if (isArrayBased) { 115 signature = SIGNATURE_N; 116 } else { 117 switch (argCount) { 118 case 0: 119 signature = SIGNATURE_0; 120 break; //$NON-NLS-1$ 121 case 1: 122 signature = SIGNATURE_1; 123 break; //$NON-NLS-1$ 124 case 2: 125 signature = SIGNATURE_2; 126 break; //$NON-NLS-1$ 127 case 3: 128 signature = SIGNATURE_3; 129 break; //$NON-NLS-1$ 130 case 4: 131 signature = SIGNATURE_4; 132 break; //$NON-NLS-1$ 133 default: 134 signature = getSignature(argCount); 135 } 136 } 137 138 /* Bind the address */ 139 address = bind(this, object, method, signature, argCount, isStatic, isArrayBased, errorResult); 140 } 141 142 /** 143 * Allocates the native level resources associated with the callback. This 144 * method is only invoked from within the constructor for the argument. 145 * 146 * @param callback 147 * the callback to bind 148 * @param object 149 * the callback's object 150 * @param method 151 * the callback's method 152 * @param signature 153 * the callback's method signature 154 * @param argCount 155 * the callback's method argument count 156 * @param isStatic 157 * whether the callback's method is static 158 * @param isArrayBased 159 * whether the callback's method is array based 160 * @param errorResult 161 * the callback's error result 162 */ 163 static native synchronized long /* int */ bind(Callback callback, Object object, String method, String signature, int argCount, boolean isStatic, boolean isArrayBased, 164 long /* int */errorResult); 165 166 /** 167 * Releases the native level resources associated with the callback, and 168 * removes all references between the callback and other objects. This helps 169 * to prevent (bad) application code from accidentally holding onto 170 * extraneous garbage. 171 */ 172 public void dispose() { 173 if (object == null) 174 return; 175 unbind(this); 176 object = method = signature = null; 177 address = 0; 178 } 179 180 /** 181 * Returns the address of a block of machine code which will invoke the 182 * callback represented by the receiver. 183 * 184 * @return the callback address 185 */ 186 public long /* int */getAddress() { 187 return address; 188 } 189 190 /** 191 * Returns the SWT platform name. 192 * 193 * @return the platform name of the currently running SWT 194 */ 195 public static native String getPlatform(); 196 197 /** 198 * Returns the number of times the system has been recursively entered 199 * through a callback. 200 * <p> 201 * Note: This should not be called by application code. 202 * </p> 203 * 204 * @return the entry count 205 * 206 * @since 2.1 207 */ 208 public static native int getEntryCount(); 209 210 static String getSignature(int argCount) { 211 String signature = "("; //$NON-NLS-1$ 212 for (int i = 0; i < argCount; i++) 213 signature += PTR_SIGNATURE; 214 signature += ")" + PTR_SIGNATURE; //$NON-NLS-1$ 215 return signature; 216 } 217 218 /** 219 * Indicates whether or not callbacks which are triggered at the native 220 * level should cause the messages described by the matching 221 * <code>Callback</code> objects to be invoked. This method is used to 222 * safely shut down SWT when it is run within environments which can 223 * generate spurious events. 224 * <p> 225 * Note: This should not be called by application code. 226 * </p> 227 * 228 * @param enable 229 * true if callbacks should be invoked 230 */ 231 public static final native synchronized void setEnabled(boolean enable); 232 233 /** 234 * Returns whether or not callbacks which are triggered at the native level 235 * should cause the messages described by the matching <code>Callback</code> 236 * objects to be invoked. This method is used to safely shut down SWT when 237 * it is run within environments which can generate spurious events. 238 * <p> 239 * Note: This should not be called by application code. 240 * </p> 241 * 242 * @return true if callbacks should not be invoked 243 */ 244 public static final native synchronized boolean getEnabled(); 245 246 /** 247 * Immediately wipes out all native level state associated with <em>all</em> 248 * callbacks. 249 * <p> 250 * <b>WARNING:</b> This operation is <em>extremely</em> dangerous, and 251 * should never be performed by application code. 252 * </p> 253 */ 254 public static final native synchronized void reset(); 255 256 /** 257 * Releases the native level resources associated with the callback. 258 * 259 * @see #dispose 260 */ 261 static final native synchronized void unbind(Callback callback); 262 263}