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 *******************************************************************************/
011 package 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
023 public 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, int /* long */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 }