KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > eaio > nativecall > NativeCall


1 /*
2  * NativeCall.java
3  *
4  * Created on 07.09.2004.
5  *
6  * eaio: NativeCall - calling operating system methods from Java
7  * Copyright (c) 2004-2006 Johann Burkard (<mailto:jb@eaio.com>)
8  * <http://eaio.com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
23  * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
24  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
25  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
26  * USE OR OTHER DEALINGS IN THE SOFTWARE.
27  *
28  */

29 package com.eaio.nativecall;
30
31 import java.io.IOException JavaDoc;
32
33 import sun.misc.ServiceConfigurationError;
34
35 import com.eaio.util.lang.NativeLoader;
36
37 /**
38  * NativeCall loads the native library and prepares the matching
39  * {@link com.eaio.nativecall.Verifier}.
40  * <p>
41  * Before being able to use NativeCall, the {@link #init()} method must have
42  * been called:
43  * <pre>
44  * try {
45  * NativeCall.init();
46  * }
47  * catch (IOException ex) { ... }
48  * catch (SecurityException ex) { ... }
49  * catch (UnsatisfiedLinkError er) { ... }
50  * catch (sun.misc.ServiceConfigurationError) { ... }
51  * catch (UnsupportedOperationException) { ... }
52  * </pre>
53  * After usage, each NativeCall object must be destroyed to release
54  * resources. This is done by calling the {@link #destroy()} method. Failure
55  * to call this method might result in memory leaks.
56  *
57  * @see #destroy()
58  * @see #init()
59  * @author <a HREF="mailto:jb@eaio.com">Johann Burkard</a>
60  * @version $Id: NativeCall.java,v 1.3 2006/04/19 20:54:58 grnull Exp $
61  */

62 public abstract class NativeCall {
63
64     /**
65      * The error code of the last call.
66      * <p>
67      * Accessed by native code. DO NOT RENAME THIS FIELD.
68      */

69     private int lastErrorCode;
70
71     /**
72      * The internal handle to the function and the module.
73      * <p>
74      * These are set in native code, so ignore any warnings.
75      * <p>
76      * Accessed by native code. DO NOT RENAME THIS FIELD.
77      */

78     private int functionHandle, moduleHandle;
79
80     /**
81      * The name of the function to call.
82      * <p>
83      * Accessed by native code. DO NOT RENAME THIS FIELD.
84      */

85     private String JavaDoc function;
86
87     /**
88      * The name of the module to call.
89      * <p>
90      * Accessed by native code. DO NOT RENAME THIS FIELD.
91      */

92     private String JavaDoc module;
93
94     /**
95      * Initialize JNI field and method IDs
96      */

97     private static native void initIDs();
98
99     /**
100      * Whether the class has been initialized properly.
101      */

102     private static boolean initialized = false;
103
104     /**
105      * Before NativeCall may be used, this method must be called.
106      * It loads the native library, prepares JNI field and method IDs and loads
107      * the matching {@link Verifier}.
108      * <p>
109      * Multiple calls are ignored.
110      *
111      * @throws IOException if an IOException occured during unpacking of
112      * the native library
113      * @throws SecurityException if accessing system properties was forbidden
114      * by the {@link SecurityManager}
115      * @throws UnsatisfiedLinkError if the <code>NativeCall.dll</code> could
116      * not be found
117      * @throws sun.misc.ServiceConfigurationError
118      * @throws UnsupportedOperationException if no matching
119      * {@link Verifier} could be found
120      */

121     public static synchronized void init()
122         throws
123             IOException JavaDoc,
124             SecurityException JavaDoc,
125             UnsatisfiedLinkError JavaDoc,
126             ServiceConfigurationError,
127             UnsupportedOperationException JavaDoc {
128         if (!initialized) {
129             Verifiers.init();
130             if (Verifiers.getInstance() == null) {
131                 throw new UnsupportedOperationException JavaDoc();
132             }
133             new NativeLoader("NativeCall").load();
134             initIDs();
135             initialized = true;
136         }
137     }
138
139     /**
140      * Constructor for NativeCall.
141      *
142      * @param function the name of the function to use, may not be
143      * <code>null</code>
144      * @throws IllegalArgumentException if the function could not be found
145      * @throws NullPointerException if function is <code>null</code>
146      * @see Verifier#getDefaultModule()
147      * @see NativeCall#NativeCall(String, String)
148      */

149     public NativeCall(String JavaDoc function)
150         throws IllegalArgumentException JavaDoc, NullPointerException JavaDoc {
151         this(Verifiers.getInstance().getDefaultModule(), function);
152     }
153
154     /**
155      * Constructor for NativeCall.
156      *
157      * @param module the name of the module the function is stored in, may be
158      * <code>null</code>
159      * @param function the name of the function to use, may not be
160      * <code>null</code>
161      * @throws IllegalArgumentException if the function could not be found
162      * @throws NullPointerException if function is <code>null</code>
163      */

164     public NativeCall(String JavaDoc module, String JavaDoc function)
165         throws IllegalArgumentException JavaDoc, NullPointerException JavaDoc {
166         Verifier v = Verifiers.getInstance();
167         this.function = v.verifyFunctionName(function);
168         this.module = v.verifyModuleName(module);
169         if (!initHandles()) {
170             if (lastErrorCode != 0) {
171                 throw new IllegalArgumentException JavaDoc(getLastError());
172             }
173             throw new IllegalArgumentException JavaDoc();
174         }
175     }
176
177     /**
178      * Attempts to acquire handles to the functions. Returns if these could be
179      * acquired.
180      *
181      * @return if the handles could be acquired
182      */

183     private native boolean initHandles();
184
185     /**
186      * Returns the error code that was returned during the last method call or
187      * 0 if the last method call did not produce an error.
188      *
189      * @see #getLastError()
190      * @return the last error code or 0
191      */

192     public final int getLastErrorCode() {
193         return lastErrorCode;
194     }
195
196     /**
197      * Returns a formatted String containing the last error code or
198      * <code>null</code> if the last call did not produce an error.
199      *
200      * @see #getLastErrorCode()
201      * @return a String or <code>null</code> if the last error code is 0
202      */

203     public final native String JavaDoc getLastError();
204
205     /**
206      * Releases acquired module handles. This method must be called if the
207      * instance is not used anymore. After this method is called, methods of this
208      * NativeCall Object cannot be called anymore.
209      * <p>
210      * <strong>Failure to call this method might result in memory leaks.</strong>
211      * <p>
212      * <em>Updates the error code field. See {@link #getLastError()}.</em>
213      */

214     public native synchronized void destroy();
215
216     /**
217      * Checks the supplied Object array for illegal/unsupported types.
218      * <p>
219      * <strong>During the verification, the contents of the array might be
220      * changed.</strong>
221      *
222      * @param params the Object array, may be <code>null</code>
223      * @throws ClassCastException if the type of one argument is not supported
224      */

225     protected void check(Object JavaDoc[] params) throws ClassCastException JavaDoc {
226         if (params == null) {
227             return;
228         }
229         for (int i = 0; i < params.length; ++i) {
230             checkParam(params[i]);
231             if (params[i] instanceof String JavaDoc) {
232                 params[i] =
233                     Verifiers.getInstance().handleString(
234                         (String JavaDoc) params[i],
235                         module,
236                         function);
237             }
238         }
239     }
240
241     /**
242      * Checks one Object for illegal/unsupported types.
243      *
244      * @param o the Object, may be <code>null</code>
245      * @throws ClassCastException if the type of one argument is not supported
246      */

247     protected void checkParam(Object JavaDoc o) throws ClassCastException JavaDoc {
248         if (o == null
249             || o instanceof Boolean JavaDoc
250             || o instanceof Integer JavaDoc
251             || o instanceof byte[]
252             || o instanceof char[]
253             || o instanceof String JavaDoc) {
254             return;
255         }
256         if (o instanceof Holder) {
257             checkParam(((Holder) o).get());
258             return;
259         }
260         throw new ClassCastException JavaDoc(o.getClass().getName());
261     }
262
263     /**
264      * Returns if this Object is equal to another Object. The other Object must
265      * be an instance of the same type as this Object. Also, both the module
266      * and the function field must be equal.
267      *
268      * @param obj the other Object
269      * @return if this and the other Object are equal
270      * @see java.lang.Object#equals(java.lang.Object)
271      */

272     public boolean equals(Object JavaDoc obj) {
273         if (this == obj) {
274             return true;
275         }
276         if (!(obj instanceof NativeCall)) {
277             return false;
278         }
279         if (!getClass().getName().equals(obj.getClass().getName())) {
280             return false;
281         }
282         NativeCall c = (NativeCall) obj;
283         return module.equals(c.module) && function.equals(c.function);
284     }
285
286     /**
287      * Returns the hashCode of this Object. The hashCode is computed by XOR'ing
288      * the hash codes of the function and the module names.
289      *
290      * @return the hashCode
291      * @see java.lang.Object#hashCode()
292      */

293     public int hashCode() {
294         int out = function.hashCode();
295         out ^= module.hashCode();
296         return out;
297     }
298
299     /**
300      * Calls {@link #destroy()}.
301      *
302      * @see java.lang.Object#finalize()
303      */

304     protected void finalize() throws Throwable JavaDoc {
305         try {
306             destroy();
307         }
308         finally {
309             super.finalize();
310             // in case NativeCall is a subclass of a class other than Object
311
}
312     }
313
314     /**
315      * Returns a String representation of this Object.
316      *
317      * @return a String, never <code>null</code>
318      * @see java.lang.Object#toString()
319      * @see #toStringBuffer(StringBuffer)
320      */

321     public final String JavaDoc toString() {
322         return toStringBuffer(null).toString();
323     }
324
325     /**
326      * Appends a String representation of this Object to the given
327      * {@link StringBuffer} or creates a new one if none is given.
328      *
329      * @param in the StringBuffer to append to, may be <code>null</code>
330      * @return a StringBuffer, never <code>null</code>
331      */

332     public StringBuffer JavaDoc toStringBuffer(StringBuffer JavaDoc in) {
333         if (in == null) {
334             in = new StringBuffer JavaDoc(64);
335         }
336         else {
337             in.ensureCapacity(in.length() + 64);
338         }
339         in.append("{ ");
340         int idx = getClass().getName().lastIndexOf(".");
341         if (idx > -1) {
342             in.append(getClass().getName().substring(++idx));
343         }
344         else {
345             in.append(getClass().getName());
346         }
347         in.append(": module = ");
348         in.append(module);
349         in.append(", function = ");
350         in.append(function);
351         in.append(" }");
352         return in;
353     }
354
355 }
356
Popular Tags