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