From 8e873378f144d4b09aa168656f17b3b381054275 Mon Sep 17 00:00:00 2001 From: Lyor Goldstein Date: Mon, 11 Jan 2016 09:35:45 +0200 Subject: [PATCH] Apply generic definitions wherever applicable --- CHANGES.md | 1 + src/com/sun/jna/CallbackParameterContext.java | 8 +- src/com/sun/jna/CallbackProxy.java | 8 +- src/com/sun/jna/CallbackReference.java | 178 +++---- src/com/sun/jna/DefaultTypeMapper.java | 111 ++--- src/com/sun/jna/FromNativeContext.java | 12 +- src/com/sun/jna/FromNativeConverter.java | 6 +- src/com/sun/jna/Function.java | 345 ++++++------- src/com/sun/jna/FunctionResultContext.java | 16 +- src/com/sun/jna/IntegerType.java | 3 +- src/com/sun/jna/LastErrorException.java | 17 +- src/com/sun/jna/Library.java | 143 +++--- src/com/sun/jna/Memory.java | 203 +++++--- src/com/sun/jna/MethodResultContext.java | 14 +- src/com/sun/jna/Native.java | 251 +++++----- src/com/sun/jna/NativeLibrary.java | 317 ++++++------ src/com/sun/jna/NativeLong.java | 5 +- src/com/sun/jna/NativeMapped.java | 14 +- src/com/sun/jna/NativeMappedConverter.java | 31 +- src/com/sun/jna/NativeString.java | 33 +- src/com/sun/jna/Pointer.java | 466 +++++++++--------- src/com/sun/jna/PointerType.java | 33 +- src/com/sun/jna/StringArray.java | 20 +- src/com/sun/jna/ToNativeConverter.java | 2 +- src/com/sun/jna/TypeMapper.java | 14 +- src/com/sun/jna/WString.java | 17 +- src/com/sun/jna/WeakIdentityHashMap.java | 122 +++-- .../sun/jna/win32/StdCallFunctionMapper.java | 45 +- src/com/sun/jna/win32/W32APIOptions.java | 12 +- src/com/sun/jna/win32/W32APITypeMapper.java | 22 +- test/com/sun/jna/AnnotatedLibraryTest.java | 30 +- test/com/sun/jna/CallbacksTest.java | 144 +++--- .../jna/DirectBufferArgumentsMarshalTest.java | 26 +- test/com/sun/jna/DirectCallbacksTest.java | 37 +- test/com/sun/jna/DirectReturnTypesTest.java | 47 +- .../sun/jna/DirectStructureByValueTest.java | 6 - test/com/sun/jna/DirectTest.java | 62 +-- test/com/sun/jna/DirectTypeMapperTest.java | 90 ++-- test/com/sun/jna/FunctionTest.java | 17 +- test/com/sun/jna/GCWaits.java | 13 + test/com/sun/jna/IntegerTypeTest.java | 15 +- test/com/sun/jna/JNALoadTest.java | 19 +- test/com/sun/jna/LastErrorTest.java | 55 ++- test/com/sun/jna/MemoryTest.java | 24 +- test/com/sun/jna/NativeLibraryTest.java | 47 +- test/com/sun/jna/NativeTest.java | 69 +-- test/com/sun/jna/PerformanceTest.java | 47 +- test/com/sun/jna/PointerBufferTest.java | 6 - test/com/sun/jna/PointerTest.java | 29 +- test/com/sun/jna/ReturnTypesTest.java | 9 +- .../sun/jna/StructureFieldOrderInspector.java | 12 +- .../jna/StructureFieldOrderInspectorTest.java | 17 +- test/com/sun/jna/StructureTest.java | 12 +- test/com/sun/jna/TypeMapperTest.java | 116 +++-- test/com/sun/jna/VarArgsTest.java | 4 +- test/com/sun/jna/WebStartTest.java | 182 +++---- test/com/sun/jna/win32/W32APIMapperTest.java | 10 +- test/com/sun/jna/win32/W32StdCallTest.java | 40 +- test/com/sun/jna/wince/CoreDLLTest.java | 34 +- 59 files changed, 1924 insertions(+), 1764 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 12f98c4cb0..9d67bdeda6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -31,6 +31,7 @@ Features * [#567](https://github.com/java-native-access/jna/pull/567): Added `PrintWindow`, `IsWindowEnabled`, `IsWindow`, `FindWindowEx`, `GetAncestor`, `GetCursorPos`, `SetCursorPos`, `SetWinEventHook`, `UnhookWinEvent`, `CopyIcon`, and `GetClassLong` to `com.sun.jna.platform.win32.User32` and supporting constants to `com.sun.jna.platform.win32.WinUser` - [@mlfreeman2](https://github.com/mlfreeman2). * [#573](https://github.com/java-native-access/jna/pull/573): Added `EnumProcessModules`, `GetModuleInformation`, and `GetProcessImageFileName` to `com.sun.jna.platform.win32.Psapi` and added `ExtractIconEx` to `com.sun.jna.platform.win32.Shell32` - [@mlfreeman2](https://github.com/mlfreeman2). * [#574](https://github.com/java-native-access/jna/pull/574): Using static final un-modifiable List of field names for structure(s) [@lgoldstein](https://github.com/lgoldstein) +* [#577](https://github.com/java-native-access/jna/pull/577): : Apply generic definitions wherever applicable [@lgoldstein](https://github.com/lgoldstein) Bug Fixes --------- diff --git a/src/com/sun/jna/CallbackParameterContext.java b/src/com/sun/jna/CallbackParameterContext.java index 44aea5fb2d..20d682888a 100644 --- a/src/com/sun/jna/CallbackParameterContext.java +++ b/src/com/sun/jna/CallbackParameterContext.java @@ -1,14 +1,14 @@ /* Copyright (c) 2007 Timothy Wall, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -19,7 +19,7 @@ public class CallbackParameterContext extends FromNativeContext { private Method method; private Object[] args; private int index; - CallbackParameterContext(Class javaType, Method m, Object[] args, int index) { + CallbackParameterContext(Class javaType, Method m, Object[] args, int index) { super(javaType); this.method = m; this.args = args; diff --git a/src/com/sun/jna/CallbackProxy.java b/src/com/sun/jna/CallbackProxy.java index b012be638b..0a77a6e121 100644 --- a/src/com/sun/jna/CallbackProxy.java +++ b/src/com/sun/jna/CallbackProxy.java @@ -8,7 +8,7 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -19,12 +19,12 @@ */ public interface CallbackProxy extends Callback { - /** This is the callback method invoked from native code. + /** This is the callback method invoked from native code. * It must not throw any exceptions whatsoever. */ Object callback(Object[] args); /** Returns the types of the parameters to the callback method. */ - Class[] getParameterTypes(); + Class[] getParameterTypes(); /** Returns the type of the callback method's return value. */ - Class getReturnType(); + Class getReturnType(); } \ No newline at end of file diff --git a/src/com/sun/jna/CallbackReference.java b/src/com/sun/jna/CallbackReference.java index 1031364c59..e96e3c3ba1 100644 --- a/src/com/sun/jna/CallbackReference.java +++ b/src/com/sun/jna/CallbackReference.java @@ -19,10 +19,12 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -34,35 +36,39 @@ * and a Java {@link Callback} closure. */ -class CallbackReference extends WeakReference { +class CallbackReference extends WeakReference { - static final Map callbackMap = new WeakHashMap(); - static final Map directCallbackMap = new WeakHashMap(); - static final Map pointerCallbackMap = new WeakHashMap(); + static final Map callbackMap = new WeakHashMap(); + static final Map directCallbackMap = new WeakHashMap(); + static final Map> pointerCallbackMap = new WeakHashMap>(); // Track memory allocations associated with this closure (usually String args) - static final Map allocations = new WeakHashMap(); + static final Map allocations = new WeakHashMap(); // Global map of allocated closures to facilitate centralized cleanup - private static final Map allocatedMemory = Collections.synchronizedMap(new WeakHashMap()); - + private static final Map> allocatedMemory = + Collections.synchronizedMap(new WeakHashMap>()); private static final Method PROXY_CALLBACK_METHOD; static { try { PROXY_CALLBACK_METHOD = CallbackProxy.class.getMethod("callback", new Class[] { Object[].class }); - } - catch(Exception e) { + } catch(Exception e) { throw new Error("Error looking up CallbackProxy.callback() method"); } } - private static final Map initializers = new WeakHashMap(); - static void setCallbackThreadInitializer(Callback cb, CallbackThreadInitializer initializer) { - synchronized(callbackMap) { + private static final Map initializers = new WeakHashMap(); + /** + * @param cb The {@link Callback} instance + * @param initializer The {@link CallbackThreadInitializer} - if {@code null} then the + * associated initializer instance is removed + * @return The previous initializer instance (may be {@code null}) + */ + static CallbackThreadInitializer setCallbackThreadInitializer(Callback cb, CallbackThreadInitializer initializer) { + synchronized(initializers) { if (initializer != null) { - initializers.put(cb, initializer); - } - else { - initializers.remove(cb); + return initializers.put(cb, initializer); + } else { + return initializers.remove(cb); } } } @@ -73,21 +79,24 @@ static class AttachOptions extends Structure { public boolean detach; public String name; // Thread name must be UTF8-encoded - { setStringEncoding("utf8"); } + { + setStringEncoding("utf8"); + } + @Override protected List getFieldOrder() { return FIELDS; } } - /** Called from native code to initialize a callback thread. */ + /* Called from native code to initialize a callback thread. */ private static ThreadGroup initializeThread(Callback cb, AttachOptions args) { CallbackThreadInitializer init = null; if (cb instanceof DefaultCallbackProxy) { cb = ((DefaultCallbackProxy)cb).getCallback(); } - synchronized(callbackMap) { - init = (CallbackThreadInitializer)initializers.get(cb); + synchronized(initializers) { + init = initializers.get(cb); } ThreadGroup group = null; if (init != null) { @@ -107,23 +116,23 @@ private static ThreadGroup initializeThread(Callback cb, AttachOptions args) { * @throws IllegalStateException if the given pointer has already been * mapped to a callback of a different type. */ - public static Callback getCallback(Class type, Pointer p) { + public static Callback getCallback(Class type, Pointer p) { return getCallback(type, p, false); } - private static Callback getCallback(Class type, Pointer p, boolean direct) { + private static Callback getCallback(Class type, Pointer p, boolean direct) { if (p == null) { return null; } if (!type.isInterface()) throw new IllegalArgumentException("Callback type must be an interface"); - Map map = direct ? directCallbackMap : callbackMap; - synchronized(callbackMap) { + Map map = direct ? directCallbackMap : callbackMap; + synchronized(pointerCallbackMap) { Callback cb = null; - Reference ref = (Reference)pointerCallbackMap.get(p); + Reference ref = pointerCallbackMap.get(p); if (ref != null) { - cb = (Callback)ref.get(); + cb = ref.get(); if (cb != null && !type.isAssignableFrom(cb.getClass())) { throw new IllegalStateException("Pointer " + p + " already mapped to " + cb + ".\nNative code may be re-using a default function pointer" @@ -134,13 +143,13 @@ private static Callback getCallback(Class type, Pointer p, boolean direct) { } int ctype = AltCallingConvention.class.isAssignableFrom(type) ? Function.ALT_CONVENTION : Function.C_CONVENTION; - Map foptions = new HashMap(Native.getLibraryOptions(type)); + Map foptions = new HashMap(Native.getLibraryOptions(type)); foptions.put(Function.OPTION_INVOKING_METHOD, getCallbackMethod(type)); NativeFunctionHandler h = new NativeFunctionHandler(p, ctype, foptions); cb = (Callback)Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, h); // No CallbackReference for this callback - map.put(cb, null); - pointerCallbackMap.put(p, new WeakReference(cb)); + map.remove(cb); + pointerCallbackMap.put(p, new WeakReference(cb)); return cb; } } @@ -155,15 +164,15 @@ private CallbackReference(Callback callback, int callingConvention, boolean dire super(callback); TypeMapper mapper = Native.getTypeMapper(callback.getClass()); this.callingConvention = callingConvention; - Class[] nativeParamTypes; - Class returnType; + Class[] nativeParamTypes; + Class returnType; // Check whether direct mapping may be used, or whether // we need to fall back to conventional mapping boolean ppc = Platform.isPPC(); if (direct) { Method m = getCallbackMethod(callback); - Class[] ptypes = m.getParameterTypes(); + Class[] ptypes = m.getParameterTypes(); for (int i=0;i < ptypes.length;i++) { // varargs w/FP args via ffi_call fails on ppc (darwin) if (ppc && (ptypes[i] == float.class @@ -199,8 +208,7 @@ private CallbackReference(Callback callback, int callingConvention, boolean dire nativeParamTypes, returnType, callingConvention, flags, encoding); - } - else { + } else { if (callback instanceof CallbackProxy) { proxy = (CallbackProxy)callback; } @@ -247,20 +255,18 @@ private CallbackReference(Callback callback, int callingConvention, boolean dire encoding); } cbstruct = peer != 0 ? new Pointer(peer) : null; - allocatedMemory.put(this, new WeakReference(this)); + allocatedMemory.put(this, new WeakReference(this)); } - private Class getNativeType(Class cls) { + private Class getNativeType(Class cls) { if (Structure.class.isAssignableFrom(cls)) { // Make sure we can instantiate an argument of this type Structure.validate(cls); if (!Structure.ByValue.class.isAssignableFrom(cls)) return Pointer.class; - } - else if (NativeMapped.class.isAssignableFrom(cls)) { + } else if (NativeMapped.class.isAssignableFrom(cls)) { return NativeMappedConverter.getInstance(cls).nativeType(); - } - else if (cls == String.class + } else if (cls == String.class || cls == WString.class || cls == String[].class || cls == WString[].class @@ -279,18 +285,19 @@ private static Method checkMethod(Method m) { return m; } - /** Find the first instance of an interface which implements the Callback + /* + * Find the first instance of an interface which implements the Callback * interface or an interface derived from Callback, which defines an * appropriate callback method. */ - static Class findCallbackClass(Class type) { + static Class findCallbackClass(Class type) { if (!Callback.class.isAssignableFrom(type)) { throw new IllegalArgumentException(type.getName() + " is not derived from com.sun.jna.Callback"); } if (type.isInterface()) { return type; } - Class[] ifaces = type.getInterfaces(); + Class[] ifaces = type.getInterfaces(); for (int i=0;i < ifaces.length;i++) { if (Callback.class.isAssignableFrom(ifaces[i])) { try { @@ -365,22 +372,27 @@ protected void finalize() { /** Free native resources associated with this callback. */ protected synchronized void dispose() { if (cbstruct != null) { - Native.freeNativeCallback(cbstruct.peer); - cbstruct.peer = 0; - cbstruct = null; - allocatedMemory.remove(this); + try { + Native.freeNativeCallback(cbstruct.peer); + } finally { + cbstruct.peer = 0; + cbstruct = null; + allocatedMemory.remove(this); + } } } /** Dispose of all memory allocated for callbacks. */ static void disposeAll() { - for (Iterator i=allocatedMemory.keySet().iterator();i.hasNext();) { - ((Memory)i.next()).dispose(); + // use a copy since dispose() modifes the map + Collection refs = new LinkedList(allocatedMemory.keySet()); + for (CallbackReference r : refs) { + r.dispose(); } } private Callback getCallback() { - return (Callback)get(); + return get(); } /** If the callback is one we generated to wrap a native function pointer, @@ -412,20 +424,20 @@ private static Pointer getFunctionPointer(Callback cb, boolean direct) { if ((fp = getNativeFunctionPointer(cb)) != null) { return fp; } - Map options = Native.getLibraryOptions(cb.getClass()); + Map options = Native.getLibraryOptions(cb.getClass()); int callingConvention = cb instanceof AltCallingConvention ? Function.ALT_CONVENTION : (options != null && options.containsKey(Library.OPTION_CALLING_CONVENTION) ? ((Integer)options.get(Library.OPTION_CALLING_CONVENTION)).intValue() : Function.C_CONVENTION); - Map map = direct ? directCallbackMap : callbackMap; - synchronized(callbackMap) { - CallbackReference cbref = (CallbackReference)map.get(cb); + Map map = direct ? directCallbackMap : callbackMap; + synchronized(pointerCallbackMap) { + CallbackReference cbref = map.get(cb); if (cbref == null) { cbref = new CallbackReference(cb, callingConvention, direct); map.put(cb, cbref); - pointerCallbackMap.put(cbref.getTrampoline(), new WeakReference(cb)); + pointerCallbackMap.put(cbref.getTrampoline(), new WeakReference(cb)); if (initializers.containsKey(cb)) { cbref.setCallbackOptions(Native.CB_HAS_INITIALIZER); } @@ -442,8 +454,8 @@ private class DefaultCallbackProxy implements CallbackProxy { public DefaultCallbackProxy(Method callbackMethod, TypeMapper mapper, String encoding) { this.callbackMethod = callbackMethod; this.encoding = encoding; - Class[] argTypes = callbackMethod.getParameterTypes(); - Class returnType = callbackMethod.getReturnType(); + Class[] argTypes = callbackMethod.getParameterTypes(); + Class returnType = callbackMethod.getReturnType(); fromNative = new FromNativeConverter[argTypes.length]; if (NativeMapped.class.isAssignableFrom(returnType)) { toNative = NativeMappedConverter.getInstance(returnType); @@ -474,19 +486,18 @@ public Callback getCallback() { } private Object invokeCallback(Object[] args) { - Class[] paramTypes = callbackMethod.getParameterTypes(); + Class[] paramTypes = callbackMethod.getParameterTypes(); Object[] callbackArgs = new Object[args.length]; // convert basic supported types to appropriate Java parameter types for (int i=0;i < args.length;i++) { - Class type = paramTypes[i]; + Class type = paramTypes[i]; Object arg = args[i]; if (fromNative[i] != null) { FromNativeContext context = new CallbackParameterContext(type, callbackMethod, args, i); callbackArgs[i] = fromNative[i].fromNative(arg, context); - } - else { + } else { callbackArgs[i] = convertArgument(arg, type); } } @@ -537,7 +548,7 @@ public Object callback(Object[] args) { /** Convert argument from its basic native type to the given * Java parameter type. */ - private Object convertArgument(Object value, Class dstType) { + private Object convertArgument(Object value, Class dstType) { if (value instanceof Pointer) { if (dstType == String.class) { value = ((Pointer)value).getString(0, encoding); @@ -552,7 +563,7 @@ else if (dstType == WString[].class) { value = ((Pointer)value).getWideStringArray(0); } else if (Callback.class.isAssignableFrom(dstType)) { - value = CallbackReference.this.getCallback(dstType, (Pointer)value); + value = CallbackReference.getCallback(dstType, (Pointer)value); } else if (Structure.class.isAssignableFrom(dstType)) { // If passed by value, don't hold onto the pointer, which @@ -564,8 +575,7 @@ else if (Structure.class.isAssignableFrom(dstType)) { s.getPointer().write(0, buf, 0, buf.length); s.read(); value = s; - } - else { + } else { Structure s = Structure.newInstance(dstType, (Pointer)value); s.conditionalAutoRead(); value = s; @@ -583,41 +593,39 @@ private Object convertResult(Object value) { if (toNative != null) { value = toNative.toNative(value, new CallbackResultContext(callbackMethod)); } - if (value == null) + if (value == null) { return null; - Class cls = value.getClass(); + } + + Class cls = value.getClass(); if (Structure.class.isAssignableFrom(cls)) { if (Structure.ByValue.class.isAssignableFrom(cls)) { return value; } return ((Structure)value).getPointer(); - } - else if (cls == boolean.class || cls == Boolean.class) { + } else if (cls == boolean.class || cls == Boolean.class) { return Boolean.TRUE.equals(value) ? Function.INTEGER_TRUE : Function.INTEGER_FALSE; - } - else if (cls == String.class || cls == WString.class) { + } else if (cls == String.class || cls == WString.class) { return getNativeString(value, cls == WString.class); - } - else if (cls == String[].class || cls == WString.class) { + } else if (cls == String[].class || cls == WString.class) { StringArray sa = cls == String[].class ? new StringArray((String[])value, encoding) : new StringArray((WString[])value); // Delay GC until array itself is GC'd. allocations.put(value, sa); return sa; - } - else if (Callback.class.isAssignableFrom(cls)) { + } else if (Callback.class.isAssignableFrom(cls)) { return getFunctionPointer((Callback)value); } return value; } @Override - public Class[] getParameterTypes() { + public Class[] getParameterTypes() { return callbackMethod.getParameterTypes(); } @Override - public Class getReturnType() { + public Class getReturnType() { return callbackMethod.getReturnType(); } } @@ -628,9 +636,9 @@ public Class getReturnType() { */ private static class NativeFunctionHandler implements InvocationHandler { private final Function function; - private final Map options; + private final Map options; - public NativeFunctionHandler(Pointer address, int callingConvention, Map options) { + public NativeFunctionHandler(Pointer address, int callingConvention, Map options) { String encoding = (String)options.get(Library.OPTION_STRING_ENCODING); this.function = new Function(address, callingConvention, encoding); this.options = options; @@ -642,15 +650,13 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl if (Library.Handler.OBJECT_TOSTRING.equals(method)) { String str = "Proxy interface to " + function; Method m = (Method)options.get(Function.OPTION_INVOKING_METHOD); - Class cls = findCallbackClass(m.getDeclaringClass()); + Class cls = findCallbackClass(m.getDeclaringClass()); str += " (" + cls.getName() + ")"; return str; - } - else if (Library.Handler.OBJECT_HASHCODE.equals(method)) { - return new Integer(hashCode()); - } - else if (Library.Handler.OBJECT_EQUALS.equals(method)) { + } else if (Library.Handler.OBJECT_HASHCODE.equals(method)) { + return Integer.valueOf(hashCode()); + } else if (Library.Handler.OBJECT_EQUALS.equals(method)) { Object o = args[0]; if (o != null && Proxy.isProxyClass(o.getClass())) { return Function.valueOf(Proxy.getInvocationHandler(o) == this); @@ -671,7 +677,7 @@ public Pointer getPointer() { * Other types (String, WString, Structure, arrays, NativeMapped, * etc) are supported in the Java library. */ - private static boolean isAllowableNativeType(Class cls) { + private static boolean isAllowableNativeType(Class cls) { return cls == void.class || cls == Void.class || cls == boolean.class || cls == Boolean.class || cls == byte.class || cls == Byte.class diff --git a/src/com/sun/jna/DefaultTypeMapper.java b/src/com/sun/jna/DefaultTypeMapper.java index af288a5801..7df92177fc 100644 --- a/src/com/sun/jna/DefaultTypeMapper.java +++ b/src/com/sun/jna/DefaultTypeMapper.java @@ -8,87 +8,74 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; import java.util.ArrayList; -import java.util.Iterator; +import java.util.Collection; import java.util.List; /** Provide custom mappings to and from native types. The default lookup * checks classes corresponding to converters in the order added; if the * class to be converted is an instance of the converter's registered class, - * the converter will be used.

- * Derived classes should install additional converters using + * the converter will be used.

+ * Derived classes should install additional converters using * {@link #addToNativeConverter} * and/or {@link #addFromNativeConverter} in the default constructor. Classes * for primitive types will automatically register for the corresponding - * Object type and vice versa (i.e. you don't have to register both + * Object type and vice versa (i.e. you don't have to register both * int.class and Integer.class). * If you want different mapping behavior than the default, simply override * {@link #getToNativeConverter} and {@link #getFromNativeConverter}. - * @see Library#OPTION_TYPE_MAPPER + * @see Library#OPTION_TYPE_MAPPER */ public class DefaultTypeMapper implements TypeMapper { private static class Entry { - public Class type; + public Class type; public Object converter; - public Entry(Class type, Object converter) { + public Entry(Class type, Object converter) { this.type = type; this.converter = converter; } } - private List toNativeConverters = new ArrayList(); - private List fromNativeConverters = new ArrayList(); - private Class getAltClass(Class cls) { + + private List toNativeConverters = new ArrayList(); + private List fromNativeConverters = new ArrayList(); + + private Class getAltClass(Class cls) { if (cls == Boolean.class) { return boolean.class; - } - else if (cls == boolean.class) { + } else if (cls == boolean.class) { return Boolean.class; - } - else if (cls == Byte.class) { + } else if (cls == Byte.class) { return byte.class; - } - else if (cls == byte.class) { + } else if (cls == byte.class) { return Byte.class; - } - else if (cls == Character.class) { + } else if (cls == Character.class) { return char.class; - } - else if (cls == char.class) { + } else if (cls == char.class) { return Character.class; - } - else if (cls == Short.class) { + } else if (cls == Short.class) { return short.class; - } - else if (cls == short.class) { + } else if (cls == short.class) { return Short.class; - } - else if (cls == Integer.class) { + } else if (cls == Integer.class) { return int.class; - } - else if (cls == int.class) { + } else if (cls == int.class) { return Integer.class; - } - else if (cls == Long.class) { + } else if (cls == Long.class) { return long.class; - } - else if (cls == long.class) { + } else if (cls == long.class) { return Long.class; - } - else if (cls == Float.class) { + } else if (cls == Float.class) { return float.class; - } - else if (cls == float.class) { + } else if (cls == float.class) { return Float.class; - } - else if (cls == Double.class) { + } else if (cls == Double.class) { return double.class; - } - else if (cls == double.class) { + } else if (cls == double.class) { return Double.class; } return null; @@ -100,56 +87,58 @@ else if (cls == double.class) { * @param converter {@link ToNativeConverter} to transform an object of * the given Java class into its native-compatible form. */ - public void addToNativeConverter(Class cls, ToNativeConverter converter) { + public void addToNativeConverter(Class cls, ToNativeConverter converter) { toNativeConverters.add(new Entry(cls, converter)); - Class alt = getAltClass(cls); + Class alt = getAltClass(cls); if (alt != null) { toNativeConverters.add(new Entry(alt, converter)); } } - /** Add a {@link FromNativeConverter} to convert a native result type into the + /** + * Add a {@link FromNativeConverter} to convert a native result type into the * given Java type. Converters are checked for in the order added. + * * @param cls Java class for the Java representation of a native type. * @param converter {@link FromNativeConverter} to transform a * native-compatible type into its Java equivalent. */ - public void addFromNativeConverter(Class cls, FromNativeConverter converter) { + public void addFromNativeConverter(Class cls, FromNativeConverter converter) { fromNativeConverters.add(new Entry(cls, converter)); - Class alt = getAltClass(cls); + Class alt = getAltClass(cls); if (alt != null) { fromNativeConverters.add(new Entry(alt, converter)); } } - /** Add a {@link TypeConverter} to provide bidirectional mapping between - * a native and Java type. + + /** + * Add a {@link TypeConverter} to provide bidirectional mapping between + * a native and Java type. + * * @param cls Java class representation for a native type * @param converter {@link TypeConverter} to translate between native and * Java types. */ - public void addTypeConverter(Class cls, TypeConverter converter) { + public void addTypeConverter(Class cls, TypeConverter converter) { addFromNativeConverter(cls, converter); addToNativeConverter(cls, converter); } - - private Object lookupConverter(Class javaClass, List converters) { - for (Iterator i=converters.iterator();i.hasNext();) { - Entry entry = (Entry)i.next(); + + private Object lookupConverter(Class javaClass, Collection converters) { + for (Entry entry : converters) { if (entry.type.isAssignableFrom(javaClass)) { return entry.converter; } } return null; } - /* (non-Javadoc) - * @see com.sun.jna.TypeMapper#getFromNativeConverter(java.lang.Class) - */ - public FromNativeConverter getFromNativeConverter(Class javaType) { + + @Override + public FromNativeConverter getFromNativeConverter(Class javaType) { return (FromNativeConverter)lookupConverter(javaType, fromNativeConverters); } - /* (non-Javadoc) - * @see com.sun.jna.TypeMapper#getToNativeConverter(java.lang.Class) - */ - public ToNativeConverter getToNativeConverter(Class javaType) { + + @Override + public ToNativeConverter getToNativeConverter(Class javaType) { return (ToNativeConverter)lookupConverter(javaType, toNativeConverters); } } diff --git a/src/com/sun/jna/FromNativeContext.java b/src/com/sun/jna/FromNativeContext.java index 70b905afd5..12d1727fb7 100644 --- a/src/com/sun/jna/FromNativeContext.java +++ b/src/com/sun/jna/FromNativeContext.java @@ -1,25 +1,25 @@ /* Copyright (c) 2007 Timothy Wall, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; /** Provides context for converting a native value into a Java type. */ public class FromNativeContext { - private Class type; - FromNativeContext(Class javaType) { + private Class type; + FromNativeContext(Class javaType) { this.type = javaType; } /** The desired Java type of the result. */ - public Class getTargetType() { + public Class getTargetType() { return type; } } diff --git a/src/com/sun/jna/FromNativeConverter.java b/src/com/sun/jna/FromNativeConverter.java index 2ee1485920..c73c7d7819 100644 --- a/src/com/sun/jna/FromNativeConverter.java +++ b/src/com/sun/jna/FromNativeConverter.java @@ -8,7 +8,7 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -16,9 +16,9 @@ /** Define conversion from a native type to the appropriate Java type. */ public interface FromNativeConverter { /** Convert the given native object into its Java representation using - * the given context. + * the given context. */ Object fromNative(Object nativeValue, FromNativeContext context); /** Indicate the native type used by this converter. */ - Class nativeType(); + Class nativeType(); } diff --git a/src/com/sun/jna/Function.java b/src/com/sun/jna/Function.java index c47d9db685..e88bf073c9 100644 --- a/src/com/sun/jna/Function.java +++ b/src/com/sun/jna/Function.java @@ -6,7 +6,7 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -15,13 +15,13 @@ import java.util.Map; /** - *

An abstraction for a native function pointer. An instance of - * Function represents a pointer to some native function. + *

An abstraction for a native function pointer. An instance of + * Function represents a pointer to some native function. * {@link #invoke(Class,Object[],Map)} is the primary means to call * the function.

* * Function call behavior may be modified by passing one of the following call - * flags: + * flags: *
    *
  • {@link Function#C_CONVENTION} Use C calling convention (default) *
  • {@link Function#ALT_CONVENTION} Use alternate calling convention (e.g. stdcall) @@ -47,7 +47,7 @@ public interface PostCallRead { */ void read(); } - + /** Maximum number of arguments supported by a JNA function call. */ public static final int MAX_NARGS = 256; @@ -63,11 +63,11 @@ public interface PostCallRead { static final Integer INTEGER_TRUE = new Integer(-1); static final Integer INTEGER_FALSE = new Integer(0); - /** - * Obtain a Function representing a native + /** + * Obtain a Function representing a native * function that follows the standard "C" calling convention. - * - *

    The allocated instance represents a pointer to the named native + * + *

    The allocated instance represents a pointer to the named native * function from the named library, called with the standard "C" calling * convention. * @@ -81,12 +81,12 @@ public interface PostCallRead { public static Function getFunction(String libraryName, String functionName) { return NativeLibrary.getInstance(libraryName).getFunction(functionName); } - + /** - * Obtain a Function representing a native + * Obtain a Function representing a native * function. - * - *

    The allocated instance represents a pointer to the named native + * + *

    The allocated instance represents a pointer to the named native * function from the named library. * * @param libraryName @@ -95,19 +95,19 @@ public static Function getFunction(String libraryName, String functionName) { * Name of the native function to be linked with * @param callFlags * Function call flags - * + * * @throws UnsatisfiedLinkError if the library is not found or * the given function name is not found within the library. */ public static Function getFunction(String libraryName, String functionName, int callFlags) { return NativeLibrary.getInstance(libraryName).getFunction(functionName, callFlags, null); } - + /** - * Obtain a Function representing a native + * Obtain a Function representing a native * function. - * - *

    The allocated instance represents a pointer to the named native + * + *

    The allocated instance represents a pointer to the named native * function from the named library. * * @param libraryName @@ -119,21 +119,21 @@ public static Function getFunction(String libraryName, String functionName, int * @param encoding * Encoding to use for conversion between Java and native * strings. - * + * * @throws UnsatisfiedLinkError if the library is not found or * the given function name is not found within the library. */ public static Function getFunction(String libraryName, String functionName, int callFlags, String encoding) { return NativeLibrary.getInstance(libraryName).getFunction(functionName, callFlags, encoding); } - + /** - * Obtain a Function representing a native + * Obtain a Function representing a native * function pointer. In general, this function should be used by dynamic * languages; Java code should allow JNA to bind to a specific Callback * interface instead by defining a return type or Structure field type. - * - *

    The allocated instance represents a pointer to the native + * + *

    The allocated instance represents a pointer to the native * function pointer. * * @param p Native function pointer @@ -143,12 +143,12 @@ public static Function getFunction(Pointer p) { } /** - * Obtain a Function representing a native + * Obtain a Function representing a native * function pointer. In general, this function should be used by dynamic * languages; Java code should allow JNA to bind to a specific Callback - * interface instead by defining a return type or Structure field type. - * - *

    The allocated instance represents a pointer to the native + * interface instead by defining a return type or Structure field type. + * + *

    The allocated instance represents a pointer to the native * function pointer. * * @param p @@ -166,7 +166,7 @@ public static Function getFunction(Pointer p, int callFlags) { private final String functionName; final String encoding; final int callFlags; - final Map options; + final Map options; /** For internal JNA use. */ static final String OPTION_INVOKING_METHOD = "invoking-method"; @@ -175,11 +175,11 @@ public static Function getFunction(Pointer p, int callFlags) { private static final VarArgsChecker IS_VARARGS = VarArgsChecker.create(); /** - * Create a new Function that is linked with a native + * Create a new Function that is linked with a native * function that follows the given calling convention. - * - *

    The allocated instance represents a pointer to the named native - * function from the supplied library, called with the given calling + * + *

    The allocated instance represents a pointer to the named native + * function from the supplied library, called with the given calling * convention. * * @param library @@ -195,8 +195,9 @@ public static Function getFunction(Pointer p, int callFlags) { */ Function(NativeLibrary library, String functionName, int callFlags, String encoding) { checkCallingConvention(callFlags & MASK_CC); - if (functionName == null) + if (functionName == null) { throw new NullPointerException("Function name must not be null"); + } this.library = library; this.functionName = functionName; this.callFlags = callFlags; @@ -205,24 +206,23 @@ public static Function getFunction(Pointer p, int callFlags) { ? encoding : Native.getDefaultStringEncoding(); try { this.peer = library.getSymbolAddress(functionName); - } - catch(UnsatisfiedLinkError e) { - throw new UnsatisfiedLinkError("Error looking up function '" - + functionName + "': " + } catch(UnsatisfiedLinkError e) { + throw new UnsatisfiedLinkError("Error looking up function '" + + functionName + "': " + e.getMessage()); } } - + /** - * Create a new Function that is linked with a native + * Create a new Function that is linked with a native * function that follows the given calling convention. - * - *

    The allocated instance represents a pointer to the given - * function address, called with the given calling + * + *

    The allocated instance represents a pointer to the given + * function address, called with the given calling * convention. * * @param functionAddress - * Address of the native function + * Address of the native function * @param callFlags * Function call flags * @param encoding @@ -241,12 +241,12 @@ public static Function getFunction(Pointer p, int callFlags) { this.encoding = encoding != null ? encoding : Native.getDefaultStringEncoding(); } - + private void checkCallingConvention(int convention) throws IllegalArgumentException { // TODO: perform per-platform calling convention checks if ((convention & MASK_CC) != convention) { - throw new IllegalArgumentException("Unrecognized calling convention: " + throw new IllegalArgumentException("Unrecognized calling convention: " + convention); } } @@ -262,16 +262,16 @@ public int getCallingConvention() { /** Invoke the native function with the given arguments, returning the * native result as an Object. */ - public Object invoke(Class returnType, Object[] inArgs) { + public Object invoke(Class returnType, Object[] inArgs) { return invoke(returnType, inArgs, this.options); - } - + } + /** Invoke the native function with the given arguments, returning the * native result as an Object. */ - public Object invoke(Class returnType, Object[] inArgs, Map options) { + public Object invoke(Class returnType, Object[] inArgs, Map options) { Method invokingMethod = (Method)options.get(OPTION_INVOKING_METHOD); - Class[] paramTypes = invokingMethod != null ? invokingMethod.getParameterTypes() : null; + Class[] paramTypes = invokingMethod != null ? invokingMethod.getParameterTypes() : null; return invoke(invokingMethod, paramTypes, returnType, inArgs, options); } @@ -280,7 +280,7 @@ public Object invoke(Class returnType, Object[] inArgs, Map options) { * types are already at hand. When calling {@link Function#invoke(Class, Object[], Map)}, * the method has to be in the options under key {@link Function#OPTION_INVOKING_METHOD}. */ - Object invoke(Method invokingMethod, Class[] paramTypes, Class returnType, Object[] inArgs, Map options) { + Object invoke(Method invokingMethod, Class[] paramTypes, Class returnType, Object[] inArgs, Map options) { // Clone the argument array to obtain a scratch space for modified // types/values Object[] args = { }; @@ -292,28 +292,25 @@ Object invoke(Method invokingMethod, Class[] paramTypes, Class returnType, Objec System.arraycopy(inArgs, 0, args, 0, args.length); } - TypeMapper mapper = - (TypeMapper)options.get(Library.OPTION_TYPE_MAPPER); + TypeMapper mapper = (TypeMapper)options.get(Library.OPTION_TYPE_MAPPER); boolean allowObjects = Boolean.TRUE.equals(options.get(Library.OPTION_ALLOW_OBJECTS)); boolean isVarArgs = args.length > 0 && invokingMethod != null ? isVarArgs(invokingMethod) : false; for (int i=0; i < args.length; i++) { - Class paramType = invokingMethod != null + Class paramType = invokingMethod != null ? (isVarArgs && i >= paramTypes.length-1 ? paramTypes[paramTypes.length-1].getComponentType() : paramTypes[i]) : null; - args[i] = convertArgument(args, i, invokingMethod, - mapper, allowObjects, paramType); + args[i] = convertArgument(args, i, invokingMethod, mapper, allowObjects, paramType); } - - Class nativeReturnType = returnType; + + Class nativeReturnType = returnType; FromNativeConverter resultConverter = null; if (NativeMapped.class.isAssignableFrom(returnType)) { NativeMappedConverter tc = NativeMappedConverter.getInstance(returnType); resultConverter = tc; nativeReturnType = tc.nativeType(); - } - else if (mapper != null) { + } else if (mapper != null) { resultConverter = mapper.getFromNativeConverter(returnType); if (resultConverter != null) { nativeReturnType = resultConverter.nativeType(); @@ -321,7 +318,6 @@ else if (mapper != null) { } Object result = invoke(args, nativeReturnType, allowObjects); - // Convert the result to a custom value/type if appropriate if (resultConverter != null) { FromNativeContext context; @@ -343,13 +339,12 @@ else if (mapper != null) { if (!(inArg instanceof Structure.ByValue)) { ((Structure)inArg).autoRead(); } - } - else if (args[i] instanceof PostCallRead) { + } else if (args[i] instanceof PostCallRead) { ((PostCallRead)args[i]).read(); if (args[i] instanceof PointerArray) { PointerArray array = (PointerArray)args[i]; if (Structure.ByReference[].class.isAssignableFrom(inArg.getClass())) { - Class type = inArg.getClass().getComponentType(); + Class type = inArg.getClass().getComponentType(); Structure[] ss = (Structure[])inArg; for (int si=0;si < ss.length;si++) { Pointer p = array.getPointer(Pointer.SIZE * si); @@ -357,68 +352,54 @@ else if (args[i] instanceof PostCallRead) { } } } - } - else if (Structure[].class.isAssignableFrom(inArg.getClass())) { + } else if (Structure[].class.isAssignableFrom(inArg.getClass())) { Structure.autoRead((Structure[])inArg); } } } - + return result; } - /** @see NativeLibrary#NativeLibrary(String,String,long,Map) implementation */ - Object invoke(Object[] args, Class returnType, boolean allowObjects) { + /* @see NativeLibrary#NativeLibrary(String,String,long,Map) implementation */ + Object invoke(Object[] args, Class returnType, boolean allowObjects) { Object result = null; if (returnType == null || returnType==void.class || returnType==Void.class) { Native.invokeVoid(peer, callFlags, args); result = null; - } - else if (returnType==boolean.class || returnType==Boolean.class) { + } else if (returnType==boolean.class || returnType==Boolean.class) { result = valueOf(Native.invokeInt(peer, callFlags, args) != 0); - } - else if (returnType==byte.class || returnType==Byte.class) { - result = new Byte((byte)Native.invokeInt(peer, callFlags, args)); - } - else if (returnType==short.class || returnType==Short.class) { - result = new Short((short)Native.invokeInt(peer, callFlags, args)); - } - else if (returnType==char.class || returnType==Character.class) { - result = new Character((char)Native.invokeInt(peer, callFlags, args)); - } - else if (returnType==int.class || returnType==Integer.class) { - result = new Integer(Native.invokeInt(peer, callFlags, args)); - } - else if (returnType==long.class || returnType==Long.class) { - result = new Long(Native.invokeLong(peer, callFlags, args)); - } - else if (returnType==float.class || returnType==Float.class) { - result = new Float(Native.invokeFloat(peer, callFlags, args)); - } - else if (returnType==double.class || returnType==Double.class) { - result = new Double(Native.invokeDouble(peer, callFlags, args)); - } - else if (returnType==String.class) { + } else if (returnType==byte.class || returnType==Byte.class) { + result = Byte.valueOf((byte)Native.invokeInt(peer, callFlags, args)); + } else if (returnType==short.class || returnType==Short.class) { + result = Short.valueOf((short)Native.invokeInt(peer, callFlags, args)); + } else if (returnType==char.class || returnType==Character.class) { + result = Character.valueOf((char)Native.invokeInt(peer, callFlags, args)); + } else if (returnType==int.class || returnType==Integer.class) { + result = Integer.valueOf(Native.invokeInt(peer, callFlags, args)); + } else if (returnType==long.class || returnType==Long.class) { + result = Long.valueOf(Native.invokeLong(peer, callFlags, args)); + } else if (returnType==float.class || returnType==Float.class) { + result = Float.valueOf(Native.invokeFloat(peer, callFlags, args)); + } else if (returnType==double.class || returnType==Double.class) { + result = Double.valueOf(Native.invokeDouble(peer, callFlags, args)); + } else if (returnType==String.class) { result = invokeString(callFlags, args, false); - } - else if (returnType==WString.class) { + } else if (returnType==WString.class) { String s = invokeString(callFlags, args, true); if (s != null) { result = new WString(s); } - } - else if (Pointer.class.isAssignableFrom(returnType)) { + } else if (Pointer.class.isAssignableFrom(returnType)) { return invokePointer(callFlags, args); - } - else if (Structure.class.isAssignableFrom(returnType)) { + } else if (Structure.class.isAssignableFrom(returnType)) { if (Structure.ByValue.class.isAssignableFrom(returnType)) { - Structure s = + Structure s = Native.invokeStructure(peer, callFlags, args, Structure.newInstance(returnType)); s.autoRead(); result = s; - } - else { + } else { result = invokePointer(callFlags, args); if (result != null) { Structure s = Structure.newInstance(returnType, (Pointer)result); @@ -426,20 +407,17 @@ else if (Structure.class.isAssignableFrom(returnType)) { result = s; } } - } - else if (Callback.class.isAssignableFrom(returnType)) { + } else if (Callback.class.isAssignableFrom(returnType)) { result = invokePointer(callFlags, args); if (result != null) { result = CallbackReference.getCallback(returnType, (Pointer)result); } - } - else if (returnType==String[].class) { + } else if (returnType==String[].class) { Pointer p = invokePointer(callFlags, args); if (p != null) { result = p.getStringArray(0, encoding); } - } - else if (returnType==WString[].class) { + } else if (returnType==WString[].class) { Pointer p = invokePointer(callFlags, args); if (p != null) { String[] arr = p.getWideStringArray(0); @@ -449,14 +427,12 @@ else if (returnType==WString[].class) { } result = warr; } - } - else if (returnType==Pointer[].class) { + } else if (returnType==Pointer[].class) { Pointer p = invokePointer(callFlags, args); if (p != null) { result = p.getPointerArray(0); } - } - else if (allowObjects) { + } else if (allowObjects) { result = Native.invokeObject(peer, callFlags, args); if (result != null && !returnType.isAssignableFrom(result.getClass())) { @@ -464,15 +440,12 @@ else if (allowObjects) { + " does not match result " + result.getClass()); } - } - else { - throw new IllegalArgumentException("Unsupported return type " - + returnType - + " in function " + getName()); + } else { + throw new IllegalArgumentException("Unsupported return type " + returnType + " in function " + getName()); } return result; } - + private Pointer invokePointer(int callFlags, Object[] args) { long ptr = Native.invokePointer(peer, callFlags, args); return ptr == 0 ? null : new Pointer(ptr); @@ -480,15 +453,14 @@ private Pointer invokePointer(int callFlags, Object[] args) { private Object convertArgument(Object[] args, int index, Method invokingMethod, TypeMapper mapper, - boolean allowObjects, Class expectedType) { + boolean allowObjects, Class expectedType) { Object arg = args[index]; if (arg != null) { - Class type = arg.getClass(); + Class type = arg.getClass(); ToNativeConverter converter = null; if (NativeMapped.class.isAssignableFrom(type)) { converter = NativeMappedConverter.getInstance(type); - } - else if (mapper != null) { + } else if (mapper != null) { converter = mapper.getToNativeConverter(type); } if (converter != null) { @@ -502,31 +474,30 @@ else if (mapper != null) { arg = converter.toNative(arg, context); } } - if (arg == null || isPrimitiveArray(arg.getClass())) { + if (arg == null || isPrimitiveArray(arg.getClass())) { return arg; } - Class argClass = arg.getClass(); - // Convert Structures to native pointers + + Class argClass = arg.getClass(); + // Convert Structures to native pointers if (arg instanceof Structure) { Structure struct = (Structure)arg; struct.autoWrite(); if (struct instanceof Structure.ByValue) { // Double-check against the method signature, if available - Class ptype = struct.getClass(); + Class ptype = struct.getClass(); if (invokingMethod != null) { - Class[] ptypes = invokingMethod.getParameterTypes(); + Class[] ptypes = invokingMethod.getParameterTypes(); if (IS_VARARGS.isVarArgs(invokingMethod)) { if (index < ptypes.length-1) { ptype = ptypes[index]; - } - else { - Class etype = ptypes[ptypes.length-1].getComponentType(); + } else { + Class etype = ptypes[ptypes.length-1].getComponentType(); if (etype != Object.class) { ptype = etype; } } - } - else { + } else { ptype = ptypes[index]; } } @@ -535,44 +506,35 @@ else if (mapper != null) { } } return struct.getPointer(); - } - // Convert Callback to Pointer - else if (arg instanceof Callback) { + } else if (arg instanceof Callback) { + // Convert Callback to Pointer return CallbackReference.getFunctionPointer((Callback)arg); - } - // String arguments are converted to native pointers here rather - // than in native code so that the values will be valid until - // this method returns. - // Convert String to native pointer (const) - else if (arg instanceof String) { + } else if (arg instanceof String) { + // String arguments are converted to native pointers here rather + // than in native code so that the values will be valid until + // this method returns. + // Convert String to native pointer (const) return new NativeString((String)arg, false).getPointer(); - } - // Convert WString to native pointer (const) - else if (arg instanceof WString) { + } else if (arg instanceof WString) { + // Convert WString to native pointer (const) return new NativeString(arg.toString(), true).getPointer(); - } - // Default conversion of boolean to int; if you want something - // different, use a ToNativeConverter - else if (arg instanceof Boolean) { + } else if (arg instanceof Boolean) { + // Default conversion of boolean to int; if you want something + // different, use a ToNativeConverter return Boolean.TRUE.equals(arg) ? INTEGER_TRUE : INTEGER_FALSE; - } - else if (String[].class == argClass) { + } else if (String[].class == argClass) { return new StringArray((String[])arg, encoding); - } - else if (WString[].class == argClass) { + } else if (WString[].class == argClass) { return new StringArray((WString[])arg); - } - else if (Pointer[].class == argClass) { + } else if (Pointer[].class == argClass) { return new PointerArray((Pointer[])arg); - } - else if (NativeMapped[].class.isAssignableFrom(argClass)) { + } else if (NativeMapped[].class.isAssignableFrom(argClass)) { return new NativeMappedArray((NativeMapped[])arg); - } - else if (Structure[].class.isAssignableFrom(argClass)) { + } else if (Structure[].class.isAssignableFrom(argClass)) { // If the signature is Structure[], disallow // Structure.ByReference[] and Structure.ByReference elements Structure[] ss = (Structure[])arg; - Class type = argClass.getComponentType(); + Class type = argClass.getComponentType(); boolean byRef = Structure.ByReference.class.isAssignableFrom(type); if (expectedType != null) { if (!Structure.ByReference[].class.isAssignableFrom(expectedType)) { @@ -599,27 +561,21 @@ else if (Structure[].class.isAssignableFrom(argClass)) { pointers[i] = ss[i] != null ? ss[i].getPointer() : null; } return new PointerArray(pointers); - } - else if (ss.length == 0) { + } else if (ss.length == 0) { throw new IllegalArgumentException("Structure array must have non-zero length"); - } - else if (ss[0] == null) { + } else if (ss[0] == null) { Structure.newInstance(type).toArray(ss); return ss[0].getPointer(); - } - else { + } else { Structure.autoWrite(ss); return ss[0].getPointer(); } - } - else if (argClass.isArray()){ - throw new IllegalArgumentException("Unsupported array argument type: " + } else if (argClass.isArray()){ + throw new IllegalArgumentException("Unsupported array argument type: " + argClass.getComponentType()); - } - else if (allowObjects) { + } else if (allowObjects) { return arg; - } - else if (!Native.isSupportedNativeType(arg.getClass())) { + } else if (!Native.isSupportedNativeType(arg.getClass())) { throw new IllegalArgumentException("Unsupported argument type " + arg.getClass().getName() + " at parameter " + index @@ -628,11 +584,11 @@ else if (!Native.isSupportedNativeType(arg.getClass())) { return arg; } - private boolean isPrimitiveArray(Class argClass) { - return argClass.isArray() + private boolean isPrimitiveArray(Class argClass) { + return argClass.isArray() && argClass.getComponentType().isPrimitive(); } - + /** * Call the native function being represented by this object * @@ -669,6 +625,7 @@ private String invokeString(int callFlags, Object[] args, boolean wide) { } /** Provide a human-readable representation of this object. */ + @Override public String toString() { if (library != null) { return "native function " + functionName + "(" + library.getName() @@ -684,13 +641,13 @@ public Object invokeObject(Object[] args) { return invoke(Object.class, args); } - /** Convenience method for + /** Convenience method for * {@link #invoke(Class,Object[]) invoke(Pointer.class, args)}. */ public Pointer invokePointer(Object[] args) { return (Pointer)invoke(Pointer.class, args); } - + /** Convenience method for * {@link #invoke(Class,Object[]) invoke(String.class, args)} * or {@link #invoke(Class,Object[]) invoke(WString.class, args)} @@ -703,40 +660,41 @@ public String invokeString(Object[] args, boolean wide) { return o != null ? o.toString() : null; } - /** Convenience method for + /** Convenience method for * {@link #invoke(Class,Object[]) invoke(Integer.class, args)}. */ public int invokeInt(Object[] args) { return ((Integer)invoke(Integer.class, args)).intValue(); } - /** Convenience method for + /** Convenience method for * {@link #invoke(Class,Object[]) invoke(Long.class, args)}. */ public long invokeLong(Object[] args) { return ((Long)invoke(Long.class, args)).longValue(); } - /** Convenience method for + /** Convenience method for * {@link #invoke(Class,Object[]) invoke(Float.class, args)}. */ public float invokeFloat(Object[] args) { return ((Float)invoke(Float.class, args)).floatValue(); } - /** Convenience method for + /** Convenience method for * {@link #invoke(Class,Object[]) invoke(Double.class, args)}. */ public double invokeDouble(Object[] args) { return ((Double)invoke(Double.class, args)).doubleValue(); } - /** Convenience method for + /** Convenience method for * {@link #invoke(Class,Object[]) invoke(Void.class, args)}. */ public void invokeVoid(Object[] args) { invoke(Void.class, args); } - + /** Two function pointers are equal if they share the same peer address * and calling convention. */ + @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; @@ -752,20 +710,21 @@ public boolean equals(Object o) { /** Provide a unique hash code for {@link Function}s which are equivalent. */ + @Override public int hashCode() { return callFlags + options.hashCode() + super.hashCode(); } - /** Concatenate varargs with normal args to obtain a simple argument - * array. + /** Concatenate varargs with normal args to obtain a simple argument + * array. */ static Object[] concatenateVarArgs(Object[] inArgs) { // If the final argument is an array of something other than - // primitives, Structure, or String, treat it as varargs and + // primitives, Structure, or String, treat it as varargs and // concatenate the previous arguments with the varargs elements. if (inArgs != null && inArgs.length > 0) { Object lastArg = inArgs[inArgs.length-1]; - Class argType = lastArg != null ? lastArg.getClass() : null; + Class argType = lastArg != null ? lastArg.getClass() : null; if (argType != null && argType.isArray()) { Object[] varArgs = (Object[])lastArg; Object[] fullArgs = new Object[inArgs.length+varArgs.length]; @@ -773,7 +732,7 @@ static Object[] concatenateVarArgs(Object[] inArgs) { System.arraycopy(varArgs, 0, fullArgs, inArgs.length-1, varArgs.length); // For convenience, always append a NULL argument to the end // of varargs, whether the called API requires it or not. If - // it is not needed, it will be ignored, but if it *is* + // it is not needed, it will be ignored, but if it *is* // required, it avoids forcing the Java client to always // explicitly add it. fullArgs[fullArgs.length-1] = null; @@ -782,12 +741,12 @@ static Object[] concatenateVarArgs(Object[] inArgs) { } return inArgs; } - + /** Varargs are only supported on 1.5+. */ static boolean isVarArgs(Method m) { return IS_VARARGS.isVarArgs(m); } - + private static class NativeMappedArray extends Memory implements PostCallRead { private final NativeMapped[] original; public NativeMappedArray(NativeMapped[] arg) { @@ -795,6 +754,7 @@ public NativeMappedArray(NativeMapped[] arg) { this.original = arg; setValue(0, original, original.getClass()); } + @Override public void read() { getValue(0, original.getClass(), original); } @@ -810,11 +770,12 @@ public PointerArray(Pointer[] arg) { } setPointer(Pointer.SIZE*arg.length, null); } + @Override public void read() { read(0, original, 0, original.length); } } - + /** Implementation of Boolean.valueOf for older VMs. */ static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; diff --git a/src/com/sun/jna/FunctionResultContext.java b/src/com/sun/jna/FunctionResultContext.java index 0e5da7dfcc..c357183017 100644 --- a/src/com/sun/jna/FunctionResultContext.java +++ b/src/com/sun/jna/FunctionResultContext.java @@ -1,29 +1,31 @@ /* Copyright (c) 2007 Timothy Wall, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; /** Provide result conversion context for a function call. */ public class FunctionResultContext extends FromNativeContext { - private Function function; private Object[] args; - FunctionResultContext(Class resultClass, Function function, Object[] args) { + + FunctionResultContext(Class resultClass, Function function, Object[] args) { super(resultClass); this.function = function; this.args = args; } - /** Get the function that was invoked. */ + + /** @return The {@link Function} that was invoked. */ public Function getFunction() { return function; } - /** Get the arguments used in this function call. */ + + /** @return The arguments used in this function call. */ public Object[] getArguments() { return args; } } diff --git a/src/com/sun/jna/IntegerType.java b/src/com/sun/jna/IntegerType.java index 4c999ea433..0d3d75625f 100644 --- a/src/com/sun/jna/IntegerType.java +++ b/src/com/sun/jna/IntegerType.java @@ -26,6 +26,7 @@ * @author twalljava@java.net */ public abstract class IntegerType extends Number implements NativeMapped { + private static final long serialVersionUID = 1L; private int size; private Number number; @@ -120,7 +121,7 @@ public Object fromNative(Object nativeValue, FromNativeContext context) { } @Override - public Class nativeType() { + public Class nativeType() { return number.getClass(); } diff --git a/src/com/sun/jna/LastErrorException.java b/src/com/sun/jna/LastErrorException.java index 83dc24cfe6..cb9bd64e85 100644 --- a/src/com/sun/jna/LastErrorException.java +++ b/src/com/sun/jna/LastErrorException.java @@ -8,19 +8,20 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; -/** +/** * Exception representing a non-zero error code returned in either - * errno + * errno * or GetLastError(). */ public class LastErrorException extends RuntimeException { - + private static final long serialVersionUID = 1L; + private int errorCode; - + private static String formatMessage(int code) { return Platform.isWindows() ? "GetLastError() returned " + code @@ -35,7 +36,7 @@ private static String parseMessage(String m) { return m; } } - + public LastErrorException(String msg) { super(parseMessage(msg.trim())); try { @@ -48,7 +49,7 @@ public LastErrorException(String msg) { this.errorCode = -1; } } - + /** * Returns the error code of the error. * @return @@ -57,7 +58,7 @@ public LastErrorException(String msg) { public int getErrorCode() { return errorCode; } - + public LastErrorException(int code) { super(formatMessage(code)); this.errorCode = code; diff --git a/src/com/sun/jna/Library.java b/src/com/sun/jna/Library.java index 54088abc28..c4fa96c7ef 100644 --- a/src/com/sun/jna/Library.java +++ b/src/com/sun/jna/Library.java @@ -6,7 +6,7 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -26,39 +26,39 @@ * *

    * By convention, method names are identical to the native names, although you - * can map java names to different native names by providing a + * can map java names to different native names by providing a * {@link FunctionMapper} as a value for key {@link #OPTION_FUNCTION_MAPPER} * in the options map passed to the * {@link Native#loadLibrary(String, Class, Map)} call. *

    - * Although the names for structures and structure fields may be chosen - * arbitrarily, they should correspond as closely as possible to the native + * Although the names for structures and structure fields may be chosen + * arbitrarily, they should correspond as closely as possible to the native * definitions. The same is true for parameter names. *

    * This interface supports multiple, concurrent invocations of any library * methods on the Java side. Check your library documentation for its * multi-threading requirements on the native side. If a library is not safe - * for simultaneous multi-threaded access, consider using - * {@link Native#synchronizedLibrary} to prevent simultaneous multi-threaded - * access to the native code. + * for simultaneous multi-threaded access, consider using + * {@link Native#synchronizedLibrary} to prevent simultaneous multi-threaded + * access to the native code. *

    * Optional fields
    * Interface options will be automatically propagated to structures defined - * within the library provided a call to + * within the library provided a call to * {@link Native#loadLibrary(String,Class,Map)} is made prior to instantiating * any of those structures. One common way of ensuring this is to declare - * an INSTANCE field in the interface which holds the + * an INSTANCE field in the interface which holds the * loadLibrary result. *

    * OPTIONS (an instance of {@link Map}), * TYPE_MAPPER (an instance of {@link TypeMapper}), - * STRUCTURE_ALIGNMENT (one of the alignment types defined in + * STRUCTURE_ALIGNMENT (one of the alignment types defined in * {@link Structure}), and STRING_ENCODING (a {@link String}) may also * be defined. If no instance of the interface has been instantiated, these * fields will be used to determine customization settings for structures and - * methods defined within the interface. + * methods defined within the interface. *

    - * + * * @author Todd Fast, todd.fast@sun.com * @author Timothy Wall, twalljava@dev.java.net */ @@ -70,7 +70,7 @@ public interface Library { /** Option key for an {@link InvocationMapper} for the library. */ String OPTION_INVOCATION_MAPPER = "invocation-mapper"; /** Option key for structure alignment type ({@link Integer}), which should - * be one of the predefined alignment types in {@link Structure}. + * be one of the predefined alignment types in {@link Structure}. */ String OPTION_STRUCTURE_ALIGNMENT = "structure-alignment"; /**

    Option key for per-library String encoding. This affects conversions @@ -102,110 +102,107 @@ public interface Library { String OPTION_CLASSLOADER = "classloader"; static class Handler implements InvocationHandler { - + static final Method OBJECT_TOSTRING; static final Method OBJECT_HASHCODE; static final Method OBJECT_EQUALS; - + static { try { - OBJECT_TOSTRING = Object.class.getMethod("toString", new Class[0]); - OBJECT_HASHCODE= Object.class.getMethod("hashCode", new Class[0]); - OBJECT_EQUALS = Object.class.getMethod("equals", new Class[] { Object.class }); - } - catch (Exception e) { + OBJECT_TOSTRING = Object.class.getMethod("toString"); + OBJECT_HASHCODE= Object.class.getMethod("hashCode"); + OBJECT_EQUALS = Object.class.getMethod("equals", Object.class); + } catch (Exception e) { throw new Error("Error retrieving Object.toString() method"); } } + /** + * FunctionInfo has to be immutable to to make the object visible + * to other threads fully initialized. This is a prerequisite for + * using the class in the double checked locking scenario of {@link Handler#invoke(Object, Method, Object[])} + */ + private static final class FunctionInfo { + final InvocationHandler handler; + final Function function; + final boolean isVarArgs; + final Map options; + final Class[] parameterTypes; + + FunctionInfo(InvocationHandler handler, Function function, Class[] parameterTypes, boolean isVarArgs, Map options) { + this.handler = handler; + this.function = function; + this.isVarArgs = isVarArgs; + this.options = options; + this.parameterTypes = parameterTypes; + } + } + private final NativeLibrary nativeLibrary; - private final Class interfaceClass; + private final Class interfaceClass; // Library invocation options - private final Map options; + private final Map options; private final InvocationMapper invocationMapper; - private final Map functions = new WeakHashMap(); - public Handler(String libname, Class interfaceClass, Map options) { + private final Map functions = new WeakHashMap(); + public Handler(String libname, Class interfaceClass, Map options) { if (libname != null && "".equals(libname.trim())) { - throw new IllegalArgumentException("Invalid library name \"" - + libname + "\""); + throw new IllegalArgumentException("Invalid library name \"" + libname + "\""); + } + + if (!interfaceClass.isInterface()) { + throw new IllegalArgumentException(libname + " does not implement an interface: " + interfaceClass.getName()); } this.interfaceClass = interfaceClass; - options = new HashMap(options); - int callingConvention = - AltCallingConvention.class.isAssignableFrom(interfaceClass) - ? Function.ALT_CONVENTION : Function.C_CONVENTION; - if (options.get(OPTION_CALLING_CONVENTION) == null) { - options.put(OPTION_CALLING_CONVENTION, - new Integer(callingConvention)); + this.options = new HashMap(options); + int callingConvention = AltCallingConvention.class.isAssignableFrom(interfaceClass) + ? Function.ALT_CONVENTION + : Function.C_CONVENTION; + if (this.options.get(OPTION_CALLING_CONVENTION) == null) { + this.options.put(OPTION_CALLING_CONVENTION, Integer.valueOf(callingConvention)); } - if (options.get(OPTION_CLASSLOADER) == null) { - options.put(OPTION_CLASSLOADER, interfaceClass.getClassLoader()); + if (this.options.get(OPTION_CLASSLOADER) == null) { + this.options.put(OPTION_CLASSLOADER, interfaceClass.getClassLoader()); } - this.options = options; - this.nativeLibrary = NativeLibrary.getInstance(libname, options); - invocationMapper = (InvocationMapper)options.get(OPTION_INVOCATION_MAPPER); + this.nativeLibrary = NativeLibrary.getInstance(libname, this.options); + invocationMapper = (InvocationMapper)this.options.get(OPTION_INVOCATION_MAPPER); } public NativeLibrary getNativeLibrary() { return nativeLibrary; } - + public String getLibraryName() { return nativeLibrary.getName(); } - public Class getInterfaceClass() { + public Class getInterfaceClass() { return interfaceClass; } - - /** - * FunctionInfo has to be immutable to to make the object visible - * to other threads fully initialized. This is a prerequisite for - * using the class in the double checked locking scenario of {@link Handler#invoke(Object, Method, Object[])} - */ - private static final class FunctionInfo { - - FunctionInfo(InvocationHandler handler, Function function, Class[] parameterTypes, boolean isVarArgs, Map options) { - super(); - this.handler = handler; - this.function = function; - this.isVarArgs = isVarArgs; - this.options = options; - this.parameterTypes = parameterTypes; - } - - final InvocationHandler handler; - final Function function; - final boolean isVarArgs; - final Map options; - final Class[] parameterTypes; - } + @Override public Object invoke(Object proxy, Method method, Object[] inArgs) throws Throwable { // Intercept Object methods if (OBJECT_TOSTRING.equals(method)) { return "Proxy interface to " + nativeLibrary; - } - else if (OBJECT_HASHCODE.equals(method)) { + } else if (OBJECT_HASHCODE.equals(method)) { return new Integer(hashCode()); - } - else if (OBJECT_EQUALS.equals(method)) { + } else if (OBJECT_EQUALS.equals(method)) { Object o = inArgs[0]; if (o != null && Proxy.isProxyClass(o.getClass())) { return Function.valueOf(Proxy.getInvocationHandler(o) == this); } return Boolean.FALSE; } - + // Using the double-checked locking pattern to speed up function calls - FunctionInfo f = (FunctionInfo)functions.get(method); + FunctionInfo f = functions.get(method); if(f == null) { synchronized(functions) { - f = (FunctionInfo)functions.get(method); + f = functions.get(method); if (f == null) { boolean isVarArgs = Function.isVarArgs(method); InvocationHandler handler = null; @@ -213,13 +210,13 @@ else if (OBJECT_EQUALS.equals(method)) { handler = invocationMapper.getInvocationHandler(nativeLibrary, method); } Function function = null; - Class[] parameterTypes = null; - Map options = null; + Class[] parameterTypes = null; + Map options = null; if (handler == null) { // Find the function to invoke function = nativeLibrary.getFunction(method.getName(), method); parameterTypes = method.getParameterTypes(); - options = new HashMap(this.options); + options = new HashMap(this.options); options.put(Function.OPTION_INVOKING_METHOD, method); } f = new FunctionInfo(handler, function, parameterTypes, isVarArgs, options); diff --git a/src/com/sun/jna/Memory.java b/src/com/sun/jna/Memory.java index d0f68dbb26..28a768055b 100644 --- a/src/com/sun/jna/Memory.java +++ b/src/com/sun/jna/Memory.java @@ -6,26 +6,27 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; +import java.lang.ref.Reference; import java.lang.ref.WeakReference; +import java.nio.Buffer; import java.nio.ByteBuffer; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; +import java.util.LinkedList; import java.util.Map; -import java.util.Set; import java.util.WeakHashMap; /** - * A Pointer to memory obtained from the native heap via a + * A Pointer to memory obtained from the native heap via a * call to malloc. * *

    In some cases it might be necessary to use memory obtained from - * malloc. For example, Memory helps + * malloc. For example, Memory helps * accomplish the following idiom: *

      * 		void *buf = malloc(BUF_LEN * sizeof(char));
    @@ -42,17 +43,14 @@
      * @see Pointer
      */
     public class Memory extends Pointer {
    -
    -    private static final Map buffers;
         /** Keep track of all allocated memory so we can dispose of it before unloading. */
    -    private static final Map allocatedMemory;
    +    private static final Map> allocatedMemory =
    +            Collections.synchronizedMap(new WeakHashMap>());
     
    -    static {
    -        buffers = Collections.synchronizedMap(Platform.HAS_BUFFERS
    -                                              ? (Map)new WeakIdentityHashMap()
    -                                              : (Map)new HashMap());
    -        allocatedMemory = Collections.synchronizedMap(new WeakHashMap());
    -    }
    +    private static final Map buffers =
    +            Collections.synchronizedMap(Platform.HAS_BUFFERS
    +                                              ? new WeakIdentityHashMap()
    +                                              : new HashMap());
     
         /** Force cleanup of memory that has associated NIO Buffers which have
             been GC'd.
    @@ -63,8 +61,10 @@ public static void purge() {
     
         /** Dispose of all allocated memory. */
         public static void disposeAll() {
    -        for (Iterator i=allocatedMemory.keySet().iterator();i.hasNext();) {
    -            ((Memory)i.next()).dispose();
    +        // use a copy since dispose() modifies the map
    +        Collection refs = new LinkedList(allocatedMemory.keySet());
    +        for (Memory r : refs) {
    +            r.dispose();
             }
         }
     
    @@ -79,18 +79,21 @@ public SharedMemory(long offset, long size) {
                 this.peer = Memory.this.peer + offset;
             }
             /** No need to free memory. */
    +        @Override
             protected void dispose() {
                 this.peer = 0;
    -        } 
    +        }
             /** Pass bounds check to parent. */
    +        @Override
             protected void boundsCheck(long off, long sz) {
                 Memory.this.boundsCheck(this.peer - Memory.this.peer + off, sz);
             }
    +        @Override
             public String toString() {
                 return super.toString() + " (shared from " + Memory.this.toString() + ")";
             }
         }
    -    
    +
         /**
          * Allocate space in the native heap via a call to C's malloc.
          *
    @@ -100,12 +103,12 @@ public Memory(long size) {
             this.size = size;
             if (size <= 0) {
                 throw new IllegalArgumentException("Allocation size must be greater than zero");
    -        } 
    +        }
             peer = malloc(size);
    -        if (peer == 0) 
    +        if (peer == 0)
                 throw new OutOfMemoryError("Cannot allocate " + size + " bytes");
     
    -        allocatedMemory.put(this, new WeakReference(this));
    +        allocatedMemory.put(this, new WeakReference(this));
         }
     
         protected Memory() { }
    @@ -114,25 +117,27 @@ protected Memory() { }
          * returned {@link Pointer} will have a size equal to that of the original
          * minus the offset.
          * @throws IndexOutOfBoundsException if the requested memory is outside
    -     * the allocated bounds. 
    +     * the allocated bounds.
          */
    +    @Override
         public Pointer share(long offset) {
             return share(offset, size() - offset);
         }
    -    
    +
         /** Provide a view of this memory using the given offset as the base
    -     * address, bounds-limited with the given size.  Maintains a reference to 
    +     * address, bounds-limited with the given size.  Maintains a reference to
          * the original {@link Memory} object to avoid GC as long as the shared
          * memory is referenced.
          * @throws IndexOutOfBoundsException if the requested memory is outside
    -     * the allocated bounds. 
    +     * the allocated bounds.
          */
    +    @Override
         public Pointer share(long offset, long sz) {
             boundsCheck(offset, sz);
             return new SharedMemory(offset, sz);
         }
    -    
    -    /** Provide a view onto this structure with the given alignment. 
    +
    +    /** Provide a view onto this structure with the given alignment.
          * @param byteBoundary Align memory to this number of bytes; should be a
          * power of two.
          * @throws IndexOutOfBoundsException if the requested alignment can
    @@ -147,7 +152,7 @@ public Memory align(int byteBoundary) {
             for (int i=0;i < 32;i++) {
                 if (byteBoundary == (1<malloc space, a la
    -     * Pointer.read.  But this method performs a bounds 
    +     * Pointer.read.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
    -     * @see Pointer#read(long,byte[],int,int) 
    +     * @see Pointer#read(long,byte[],int,int)
          */
    +    @Override
         public void read(long bOff, byte[] buf, int index, int length) {
             boundsCheck(bOff, length * 1L);
             super.read(bOff, buf, index, length);
    @@ -224,12 +234,13 @@ public void read(long bOff, byte[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.read.  But this method performs a bounds 
    +     * Pointer.read.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#read(long,short[],int,int)
          */
    +    @Override
         public void read(long bOff, short[] buf, int index, int length) {
             boundsCheck(bOff, length * 2L);
             super.read(bOff, buf, index, length);
    @@ -238,12 +249,13 @@ public void read(long bOff, short[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.read.  But this method performs a bounds 
    +     * Pointer.read.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
    -     * @see Pointer#read(long,char[],int,int) 
    +     * @see Pointer#read(long,char[],int,int)
          */
    +    @Override
         public void read(long bOff, char[] buf, int index, int length) {
             boundsCheck(bOff, length * 2L);
             super.read(bOff, buf, index, length);
    @@ -252,12 +264,13 @@ public void read(long bOff, char[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.read.  But this method performs a bounds 
    +     * Pointer.read.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#read(long,int[],int,int)
          */
    +    @Override
         public void read(long bOff, int[] buf, int index, int length) {
             boundsCheck(bOff, length * 4L);
             super.read(bOff, buf, index, length);
    @@ -266,12 +279,13 @@ public void read(long bOff, int[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.read.  But this method performs a bounds 
    +     * Pointer.read.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
    -     * @see Pointer#read(long,long[],int,int) 
    +     * @see Pointer#read(long,long[],int,int)
          */
    +    @Override
         public void read(long bOff, long[] buf, int index, int length) {
             boundsCheck(bOff, length * 8L);
             super.read(bOff, buf, index, length);
    @@ -280,12 +294,13 @@ public void read(long bOff, long[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.read.  But this method performs a bounds 
    +     * Pointer.read.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
    -     * @see Pointer#read(long,float[],int,int) 
    +     * @see Pointer#read(long,float[],int,int)
          */
    +    @Override
         public void read(long bOff, float[] buf, int index, int length) {
             boundsCheck(bOff, length * 4L);
             super.read(bOff, buf, index, length);
    @@ -298,9 +313,10 @@ public void read(long bOff, float[] buf, int index, int length) {
          * ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
    -     * @see Pointer#read(long,double[],int,int) 
    +     * @see Pointer#read(long,double[],int,int)
          */
    -    public void read(long bOff, double[] buf, int index, int length) 
    +    @Override
    +    public void read(long bOff, double[] buf, int index, int length)
         {
             boundsCheck(bOff, length * 8L);
             super.read(bOff, buf, index, length);
    @@ -315,12 +331,13 @@ public void read(long bOff, double[] buf, int index, int length)
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.write.  But this method performs a bounds 
    +     * Pointer.write.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
    -     * @see Pointer#write(long,byte[],int,int) 
    +     * @see Pointer#write(long,byte[],int,int)
          */
    +    @Override
         public void write(long bOff, byte[] buf, int index, int length) {
             boundsCheck(bOff, length * 1L);
             super.write(bOff, buf, index, length);
    @@ -329,12 +346,13 @@ public void write(long bOff, byte[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.write.  But this method performs a bounds 
    +     * Pointer.write.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#write(long,short[],int,int)
          */
    +    @Override
         public void write(long bOff, short[] buf, int index, int length) {
             boundsCheck(bOff, length * 2L);
             super.write(bOff, buf, index, length);
    @@ -343,12 +361,13 @@ public void write(long bOff, short[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.write.  But this method performs a bounds 
    +     * Pointer.write.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#write(long,char[],int,int)
          */
    +    @Override
         public void write(long bOff, char[] buf, int index, int length) {
             boundsCheck(bOff, length * 2L);
             super.write(bOff, buf, index, length);
    @@ -357,12 +376,13 @@ public void write(long bOff, char[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.write.  But this method performs a bounds 
    +     * Pointer.write.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
    -     * @see Pointer#write(long,int[],int,int) 
    +     * @see Pointer#write(long,int[],int,int)
          */
    +    @Override
         public void write(long bOff, int[] buf, int index, int length) {
             boundsCheck(bOff, length * 4L);
             super.write(bOff, buf, index, length);
    @@ -371,12 +391,13 @@ public void write(long bOff, int[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.write.  But this method performs a bounds 
    +     * Pointer.write.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
    -     * @see Pointer#write(long,long[],int,int) 
    +     * @see Pointer#write(long,long[],int,int)
          */
    +    @Override
         public void write(long bOff, long[] buf, int index, int length) {
             boundsCheck(bOff, length * 8L);
             super.write(bOff, buf, index, length);
    @@ -385,12 +406,13 @@ public void write(long bOff, long[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.write.  But this method performs a bounds 
    +     * Pointer.write.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#write(long,float[],int,int)
          */
    +    @Override
         public void write(long bOff, float[] buf, int index, int length) {
             boundsCheck(bOff, length * 4L);
             super.write(bOff, buf, index, length);
    @@ -399,12 +421,13 @@ public void write(long bOff, float[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.write.  But this method performs a bounds 
    +     * Pointer.write.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
    -     * @see Pointer#write(long,double[],int,int) 
    +     * @see Pointer#write(long,double[],int,int)
          */
    +    @Override
         public void write(long bOff, double[] buf, int index, int length) {
             boundsCheck(bOff, length * 8L);
             super.write(bOff, buf, index, length);
    @@ -419,12 +442,13 @@ public void write(long bOff, double[] buf, int index, int length) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.getByte.  But this method performs a bounds 
    +     * Pointer.getByte.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#getByte(long)
          */
    +    @Override
         public byte getByte(long offset) {
             boundsCheck(offset, 1);
             return super.getByte(offset);
    @@ -433,12 +457,13 @@ public byte getByte(long offset) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.getByte.  But this method performs a bounds 
    +     * Pointer.getByte.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#getByte(long)
          */
    +    @Override
         public char getChar(long offset) {
             boundsCheck(offset, 1);
             return super.getChar(offset);
    @@ -453,6 +478,7 @@ public char getChar(long offset) {
          *
          * @see Pointer#getShort(long)
          */
    +    @Override
         public short getShort(long offset) {
             boundsCheck(offset, 2);
             return super.getShort(offset);
    @@ -461,12 +487,13 @@ public short getShort(long offset) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.getInt.  But this method performs a bounds 
    +     * Pointer.getInt.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#getInt(long)
          */
    +    @Override
         public int getInt(long offset) {
             boundsCheck(offset, 4);
             return super.getInt(offset);
    @@ -475,12 +502,13 @@ public int getInt(long offset) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.getLong.  But this method performs a bounds 
    +     * Pointer.getLong.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#getLong(long)
          */
    +    @Override
         public long getLong(long offset) {
             boundsCheck(offset, 8);
             return super.getLong(offset);
    @@ -489,12 +517,13 @@ public long getLong(long offset) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.getFloat.  But this method performs a bounds 
    +     * Pointer.getFloat.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#getFloat(long)
          */
    +    @Override
         public float getFloat(long offset) {
             boundsCheck(offset, 4);
             return super.getFloat(offset);
    @@ -503,12 +532,13 @@ public float getFloat(long offset) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.getDouble.  But this method performs a 
    -     * bounds check to ensure that the indirection does not cause memory 
    +     * Pointer.getDouble.  But this method performs a
    +     * bounds check to ensure that the indirection does not cause memory
          * outside the malloced space to be accessed.
          *
          * @see Pointer#getDouble(long)
          */
    +    @Override
         public double getDouble(long offset) {
             boundsCheck(offset, 8);
             return super.getDouble(offset);
    @@ -517,19 +547,20 @@ public double getDouble(long offset) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.getPointer.  But this method performs 
    -     * a bounds checks to ensure that the indirection does not cause memory 
    +     * Pointer.getPointer.  But this method performs
    +     * a bounds checks to ensure that the indirection does not cause memory
          * outside the malloced space to be accessed.
          *
          * @see Pointer#getPointer(long)
          */
    +    @Override
         public Pointer getPointer(long offset) {
             boundsCheck(offset, Pointer.SIZE);
             return super.getPointer(offset);
         }
     
         /**
    -     * Get a ByteBuffer mapped to a portion of this memory.  
    +     * Get a ByteBuffer mapped to a portion of this memory.
          * We keep a weak reference to all ByteBuffers provided so that this
          * memory object is not GC'd while there are still implicit outstanding
          * references to it (it'd be nice if we could attach our own reference to
    @@ -538,8 +569,9 @@ public Pointer getPointer(long offset) {
          *
          * @param offset byte offset from pointer to start the buffer
          * @param length Length of ByteBuffer
    -     * @return a direct ByteBuffer that accesses the memory being pointed to, 
    +     * @return a direct ByteBuffer that accesses the memory being pointed to,
          */
    +    @Override
         public ByteBuffer getByteBuffer(long offset, long length) {
             boundsCheck(offset, length);
             ByteBuffer b = super.getByteBuffer(offset, length);
    @@ -549,12 +581,14 @@ public ByteBuffer getByteBuffer(long offset, long length) {
             return b;
         }
     
    +    @Override
         public String getString(long offset, String encoding) {
             // NOTE: we only make sure the start of the string is within bounds
             boundsCheck(offset, 0);
             return super.getString(offset, encoding);
         }
     
    +    @Override
         public String getWideString(long offset) {
             // NOTE: we only make sure the start of the string is within bounds
             boundsCheck(offset, 0);
    @@ -567,12 +601,13 @@ public String getWideString(long offset) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.setByte.  But this method performs a bounds 
    +     * Pointer.setByte.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#setByte
          */
    +    @Override
         public void setByte(long offset, byte value) {
             boundsCheck(offset, 1);
             super.setByte(offset, value);
    @@ -581,12 +616,13 @@ public void setByte(long offset, byte value) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.setChar.  But this method performs a bounds 
    +     * Pointer.setChar.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#setChar
          */
    +    @Override
         public void setChar(long offset, char value) {
             boundsCheck(offset, Native.WCHAR_SIZE);
             super.setChar(offset, value);
    @@ -595,12 +631,13 @@ public void setChar(long offset, char value) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.setShort.  But this method performs a bounds 
    +     * Pointer.setShort.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#setShort
          */
    +    @Override
         public void setShort(long offset, short value) {
             boundsCheck(offset, 2);
             super.setShort(offset, value);
    @@ -609,12 +646,13 @@ public void setShort(long offset, short value) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.setInt.  But this method performs a bounds 
    +     * Pointer.setInt.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#setInt
          */
    +    @Override
         public void setInt(long offset, int value) {
             boundsCheck(offset, 4);
             super.setInt(offset, value);
    @@ -623,12 +661,13 @@ public void setInt(long offset, int value) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.setLong.  But this method performs a bounds 
    +     * Pointer.setLong.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#setLong
          */
    +    @Override
         public void setLong(long offset, long value) {
             boundsCheck(offset, 8);
             super.setLong(offset, value);
    @@ -637,12 +676,13 @@ public void setLong(long offset, long value) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.setFloat.  But this method performs a bounds 
    +     * Pointer.setFloat.  But this method performs a bounds
          * checks to ensure that the indirection does not cause memory outside the
          * malloced space to be accessed.
          *
          * @see Pointer#setFloat
          */
    +    @Override
         public void setFloat(long offset, float value) {
             boundsCheck(offset, 4);
             super.setFloat(offset, value);
    @@ -651,12 +691,13 @@ public void setFloat(long offset, float value) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.setDouble.  But this method performs a 
    -     * bounds checks to ensure that the indirection does not cause memory 
    +     * Pointer.setDouble.  But this method performs a
    +     * bounds checks to ensure that the indirection does not cause memory
          * outside the malloced space to be accessed.
          *
          * @see Pointer#setDouble
          */
    +    @Override
         public void setDouble(long offset, double value) {
             boundsCheck(offset, 8);
             super.setDouble(offset, value);
    @@ -665,34 +706,38 @@ public void setDouble(long offset, double value) {
     
         /**
          * Indirect the native pointer to malloc space, a la
    -     * Pointer.setPointer.  But this method performs 
    -     * a bounds checks to ensure that the indirection does not cause memory 
    +     * Pointer.setPointer.  But this method performs
    +     * a bounds checks to ensure that the indirection does not cause memory
          * outside the malloced space to be accessed.
          *
          * @see Pointer#setPointer
          */
    +    @Override
         public void setPointer(long offset, Pointer value) {
             boundsCheck(offset, Pointer.SIZE);
             super.setPointer(offset, value);
         }
     
    +    @Override
         public void setString(long offset, String value, String encoding) {
             boundsCheck(offset, Native.getBytes(value, encoding).length + 1L);
             super.setString(offset, value, encoding);
         }
     
    +    @Override
         public void setWideString(long offset, String value) {
             boundsCheck(offset, (value.length() + 1L) * Native.WCHAR_SIZE);
             super.setWideString(offset, value);
         }
     
    +    @Override
         public String toString() {
             return "allocated@0x" + Long.toHexString(peer) + " ("
                 + size + " bytes)";
         }
     
         protected static void free(long p) {
    -        // free(0) is a no-op, so avoid the overhead of the call 
    +        // free(0) is a no-op, so avoid the overhead of the call
             if (p != 0) {
                 Native.free(p);
             }
    diff --git a/src/com/sun/jna/MethodResultContext.java b/src/com/sun/jna/MethodResultContext.java
    index 1078bbe4d8..f9e375e10a 100644
    --- a/src/com/sun/jna/MethodResultContext.java
    +++ b/src/com/sun/jna/MethodResultContext.java
    @@ -1,14 +1,14 @@
     /* Copyright (c) 2007 Wayne Meissner, All Rights Reserved
    - * 
    + *
      * This library is free software; you can redistribute it and/or
      * modify it under the terms of the GNU Lesser General Public
      * License as published by the Free Software Foundation; either
      * version 2.1 of the License, or (at your option) any later version.
    - * 
    + *
      * This library is distributed in the hope that it will be useful,
      * but WITHOUT ANY WARRANTY; without even the implied warranty of
      * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    - * Lesser General Public License for more details.  
    + * Lesser General Public License for more details.
      */
     
     package com.sun.jna;
    @@ -20,11 +20,11 @@
      */
     public class MethodResultContext extends FunctionResultContext {
         private final Method method;
    -    MethodResultContext(Class resultClass, Function function, Object[] args, 
    -            Method method) {
    +    MethodResultContext(Class resultClass, Function function, Object[] args, Method method) {
             super(resultClass, function, args);
    -        this.method = method;        
    +        this.method = method;
         }
    -    /** Get the Method used to invoke this function call. */
    +
    +    /** @return The {@link Method} used to invoke this function call. */
         public Method getMethod() { return method; }
     }
    diff --git a/src/com/sun/jna/Native.java b/src/com/sun/jna/Native.java
    index d960223941..519caddf10 100644
    --- a/src/com/sun/jna/Native.java
    +++ b/src/com/sun/jna/Native.java
    @@ -22,6 +22,7 @@
     import java.io.IOException;
     import java.io.InputStream;
     import java.io.UnsupportedEncodingException;
    +import java.lang.ref.Reference;
     import java.lang.ref.WeakReference;
     import java.lang.reflect.Array;
     import java.lang.reflect.Field;
    @@ -41,7 +42,6 @@
     import java.util.Arrays;
     import java.util.Collections;
     import java.util.HashMap;
    -import java.util.Iterator;
     import java.util.List;
     import java.util.Map;
     import java.util.StringTokenizer;
    @@ -101,8 +101,8 @@ public final class Native implements Version {
     
         // Used by tests, do not remove
         static String jnidispatchPath = null;
    -    private static final Map options = new WeakHashMap();
    -    private static final Map libraries = new WeakHashMap();
    +    private static final Map, Map> typeOptions = new WeakHashMap, Map>();
    +    private static final Map, Reference> libraries = new WeakHashMap, Reference>();
         private static final String _OPTION_ENCLOSING_LIBRARY = "enclosing-library";
         private static final UncaughtExceptionHandler DEFAULT_HANDLER =
             new UncaughtExceptionHandler() {
    @@ -465,7 +465,7 @@ public static  T loadLibrary(Class interfaceClass) {
          * dependent libraries are missing.
          * @see #loadLibrary(String, Class, Map)
          */
    -    public static  T loadLibrary(Class interfaceClass, Map options) {
    +    public static  T loadLibrary(Class interfaceClass, Map options) {
             return loadLibrary(null, interfaceClass, options);
         }
     
    @@ -503,7 +503,7 @@ public static  T loadLibrary(String name, Class interfaceClass) {
          * @throws UnsatisfiedLinkError if the library cannot be found or
          * dependent libraries are missing.
          */
    -    public static  T loadLibrary(String name, Class interfaceClass, Map options) {
    +    public static  T loadLibrary(String name, Class interfaceClass, Map options) {
             if (!Library.class.isAssignableFrom(interfaceClass)) {
                 throw new IllegalArgumentException("Interface (" + interfaceClass.getSimpleName() + ")"
                         + " of library=" + name + " does not extend " + Library.class.getSimpleName());
    @@ -531,7 +531,7 @@ private static void loadLibraryInstance(Class cls) {
                             if (field.getType() == cls
                                 && Modifier.isStatic(field.getModifiers())) {
                                 // Ensure the field gets initialized by reading it
    -                            libraries.put(cls, new WeakReference(field.get(null)));
    +                            libraries.put(cls, new WeakReference(field.get(null)));
                                 break;
                             }
                         }
    @@ -558,8 +558,8 @@ static Class findEnclosingLibraryClass(Class cls) {
             // Check for direct-mapped libraries, which won't necessarily
             // implement com.sun.jna.Library.
             synchronized(libraries) {
    -            if (options.containsKey(cls)) {
    -                Map libOptions = (Map)options.get(cls);
    +            if (typeOptions.containsKey(cls)) {
    +                Map libOptions = typeOptions.get(cls);
                     Class enclosingClass = (Class)libOptions.get(_OPTION_ENCLOSING_LIBRARY);
                     if (enclosingClass != null) {
                         return enclosingClass;
    @@ -594,40 +594,44 @@ static Class findEnclosingLibraryClass(Class cls) {
          * @param type The type class
          * @return The options map
          */
    -    public static Map getLibraryOptions(Class type) {
    +    public static Map getLibraryOptions(Class type) {
    +        Map libraryOptions;
    +        // cached already ?
             synchronized(libraries) {
    -            if (options.containsKey(type)) {
    -                return (Map)options.get(type);
    +            libraryOptions = typeOptions.get(type);
    +            if (libraryOptions != null) {
    +                return libraryOptions;
                 }
             }
    +
             Class mappingClass = findEnclosingLibraryClass(type);
             if (mappingClass != null) {
                 loadLibraryInstance(mappingClass);
    -        }
    -        else {
    +        } else {
                 mappingClass = type;
             }
    +
             synchronized(libraries) {
    -            if (options.containsKey(mappingClass)) {
    -                Map libraryOptions = (Map)options.get(mappingClass);
    -                options.put(type, libraryOptions);
    +            libraryOptions = typeOptions.get(mappingClass);
    +            if (libraryOptions != null) {
    +                typeOptions.put(type, libraryOptions);  // cache for next time
                     return libraryOptions;
                 }
    -            Map libraryOptions = null;
    +
                 try {
                     Field field = mappingClass.getField("OPTIONS");
                     field.setAccessible(true);
    -                libraryOptions = (Map)field.get(null);
    -            }
    -            catch (NoSuchFieldException e) {
    -                libraryOptions = Collections.EMPTY_MAP;
    -            }
    -            catch (Exception e) {
    -                throw new IllegalArgumentException("OPTIONS must be a public field of type java.util.Map ("
    -                                                   + e + "): " + mappingClass);
    +                libraryOptions = (Map) field.get(null);
    +                if (libraryOptions == null) {
    +                    throw new IllegalStateException("Null options field");
    +                }
    +            } catch (NoSuchFieldException e) {
    +                libraryOptions = Collections.emptyMap();
    +            } catch (Exception e) {
    +                throw new IllegalArgumentException("OPTIONS must be a public field of type java.util.Map (" + e + "): " + mappingClass);
                 }
                 // Make a clone of the original options
    -            libraryOptions = new HashMap(libraryOptions);
    +            libraryOptions = new HashMap(libraryOptions);
                 if (!libraryOptions.containsKey(Library.OPTION_TYPE_MAPPER)) {
                     libraryOptions.put(Library.OPTION_TYPE_MAPPER, lookupField(mappingClass, "TYPE_MAPPER", TypeMapper.class));
                 }
    @@ -640,7 +644,7 @@ public static Map getLibraryOptions(Class type) {
                 libraryOptions = cacheOptions(mappingClass, libraryOptions, null);
                 // Store the original lookup class, if different from the mapping class
                 if (type != mappingClass) {
    -                options.put(type, libraryOptions);
    +                typeOptions.put(type, libraryOptions);
                 }
                 return libraryOptions;
             }
    @@ -666,7 +670,8 @@ private static Object lookupField(Class mappingClass, String fieldName, Class
          * See {@link com.sun.jna.Library#OPTION_TYPE_MAPPER}.
          */
         public static TypeMapper getTypeMapper(Class cls) {
    -        return (TypeMapper)getLibraryOptions(cls).get(Library.OPTION_TYPE_MAPPER);
    +        Map options = getLibraryOptions(cls);
    +        return (TypeMapper) options.get(Library.OPTION_TYPE_MAPPER);
         }
     
         /**
    @@ -1331,9 +1336,9 @@ static Class findDirectMappedClass(Class cls) {
             was made.
         */
         static Class getCallingClass() {
    -        Class[] context = new SecurityManager() {
    +        Class[] context = new SecurityManager() {
                 @Override
    -            public Class[] getClassContext() {
    +            public Class[] getClassContext() {
                     return super.getClassContext();
                 }
             }.getClassContext();
    @@ -1356,16 +1361,16 @@ public static void setCallbackThreadInitializer(Callback cb, CallbackThreadIniti
             CallbackReference.setCallbackThreadInitializer(cb, initializer);
         }
     
    -    private static Map registeredClasses = new WeakHashMap();
    -    private static Map registeredLibraries = new WeakHashMap();
    +    private static Map, long[]> registeredClasses = new WeakHashMap, long[]>();
    +    private static Map, NativeLibrary> registeredLibraries = new WeakHashMap, NativeLibrary>();
     
         private static void unregisterAll() {
             synchronized(registeredClasses) {
    -            for (Iterator i=registeredClasses.entrySet().iterator();i.hasNext();) {
    -                Map.Entry e = (Map.Entry)i.next();
    -                unregister((Class)e.getKey(), (long[])e.getValue());
    -                i.remove();
    +            for (Map.Entry, long[]> e : registeredClasses.entrySet()) {
    +                unregister(e.getKey(), e.getValue());
                 }
    +
    +            registeredClasses.clear();
             }
         }
     
    @@ -1383,22 +1388,26 @@ public static void unregister() {
          */
         public static void unregister(Class cls) {
             synchronized(registeredClasses) {
    -            if (registeredClasses.containsKey(cls)) {
    -                unregister(cls, (long[])registeredClasses.get(cls));
    +            long[] handles = registeredClasses.get(cls);
    +            if (handles != null) {
    +                unregister(cls, handles);
                     registeredClasses.remove(cls);
                     registeredLibraries.remove(cls);
                 }
             }
         }
     
    -    /** @return whether the given class's native components are registered. */
    +    /**
    +     * @param cls The type {@link Class}
    +     * @return whether the given class's native components are registered.
    +     */
         public static boolean registered(Class cls) {
             synchronized(registeredClasses) {
                 return registeredClasses.containsKey(cls);
             }
         }
     
    -    /** Unregister the native methods for the given class. */
    +    /* Unregister the native methods for the given class. */
         private static native void unregister(Class cls, long[] handles);
     
         static String getSignature(Class cls) {
    @@ -1571,9 +1580,9 @@ private static int getConversion(Class type, TypeMapper mapper) {
          * should be bound
          */
         public static void register(Class cls, String libName) {
    -        Map options = new HashMap();
    -        options.put(Library.OPTION_CLASSLOADER, cls.getClassLoader());
    -        register(cls, NativeLibrary.getInstance(libName, options));
    +        NativeLibrary library =
    +                NativeLibrary.getInstance(libName, Collections.singletonMap(Library.OPTION_CLASSLOADER, cls.getClassLoader()));
    +        register(cls, library);
         }
     
         /** When called from a class static initializer, maps all native methods
    @@ -1588,15 +1597,16 @@ public static void register(Class cls, String libName) {
         public static void register(Class cls, NativeLibrary lib) {
             Method[] methods = cls.getDeclaredMethods();
             List mlist = new ArrayList();
    -        TypeMapper mapper = (TypeMapper)
    -            lib.getOptions().get(Library.OPTION_TYPE_MAPPER);
    -        cacheOptions(cls, lib.getOptions(), null);
    +        Map options = lib.getOptions();
    +        TypeMapper mapper = (TypeMapper) options.get(Library.OPTION_TYPE_MAPPER);
    +        options = cacheOptions(cls, options, null);
     
             for (Method m : methods) {
                 if ((m.getModifiers() & Modifier.NATIVE) != 0) {
                     mlist.add(m);
                 }
             }
    +
             long[] handles = new long[mlist.size()];
             for (int i=0;i < handles.length;i++) {
                 Method method = mlist.get(i);
    @@ -1612,80 +1622,80 @@ public static void register(Class cls, NativeLibrary lib) {
                 int rcvt = getConversion(rclass, mapper);
                 boolean throwLastError = false;
                 switch (rcvt) {
    -            case CVT_UNSUPPORTED:
    -                throw new IllegalArgumentException(rclass + " is not a supported return type (in method " + method.getName() + " in " + cls + ")");
    -            case CVT_TYPE_MAPPER:
    -            case CVT_TYPE_MAPPER_STRING:
    -            case CVT_TYPE_MAPPER_WSTRING:
    -                fromNative = mapper.getFromNativeConverter(rclass);
    -                // FFIType.get() always looks up the native type for any given
    -                // class, so if we actually have conversion into a Java
    -                // object, make sure we use the proper type information
    -                closure_rtype = FFIType.get(rclass.isPrimitive() ? rclass : Pointer.class).peer;
    -                rtype = FFIType.get(fromNative.nativeType()).peer;
    -                break;
    -            case CVT_NATIVE_MAPPED:
    -            case CVT_NATIVE_MAPPED_STRING:
    -            case CVT_NATIVE_MAPPED_WSTRING:
    -            case CVT_INTEGER_TYPE:
    -            case CVT_POINTER_TYPE:
    -                closure_rtype = FFIType.get(Pointer.class).peer;
    -                rtype = FFIType.get(NativeMappedConverter.getInstance(rclass).nativeType()).peer;
    -                break;
    -            case CVT_STRUCTURE:
    -                closure_rtype = rtype = FFIType.get(Pointer.class).peer;
    -                break;
    -            case CVT_STRUCTURE_BYVAL:
    -                closure_rtype = FFIType.get(Pointer.class).peer;
    -                rtype = FFIType.get(rclass).peer;
    -                break;
    -            default:
    -                closure_rtype = rtype = FFIType.get(rclass).peer;
    -                break;
    +                case CVT_UNSUPPORTED:
    +                    throw new IllegalArgumentException(rclass + " is not a supported return type (in method " + method.getName() + " in " + cls + ")");
    +                case CVT_TYPE_MAPPER:
    +                case CVT_TYPE_MAPPER_STRING:
    +                case CVT_TYPE_MAPPER_WSTRING:
    +                    fromNative = mapper.getFromNativeConverter(rclass);
    +                    // FFIType.get() always looks up the native type for any given
    +                    // class, so if we actually have conversion into a Java
    +                    // object, make sure we use the proper type information
    +                    closure_rtype = FFIType.get(rclass.isPrimitive() ? rclass : Pointer.class).peer;
    +                    rtype = FFIType.get(fromNative.nativeType()).peer;
    +                    break;
    +                case CVT_NATIVE_MAPPED:
    +                case CVT_NATIVE_MAPPED_STRING:
    +                case CVT_NATIVE_MAPPED_WSTRING:
    +                case CVT_INTEGER_TYPE:
    +                case CVT_POINTER_TYPE:
    +                    closure_rtype = FFIType.get(Pointer.class).peer;
    +                    rtype = FFIType.get(NativeMappedConverter.getInstance(rclass).nativeType()).peer;
    +                    break;
    +                case CVT_STRUCTURE:
    +                    closure_rtype = rtype = FFIType.get(Pointer.class).peer;
    +                    break;
    +                case CVT_STRUCTURE_BYVAL:
    +                    closure_rtype = FFIType.get(Pointer.class).peer;
    +                    rtype = FFIType.get(rclass).peer;
    +                    break;
    +                default:
    +                    closure_rtype = rtype = FFIType.get(rclass).peer;
                 }
    +
                 for (int t=0;t < ptypes.length;t++) {
                     Class type = ptypes[t];
                     sig += getSignature(type);
    -                cvt[t] = getConversion(type, mapper);
    -                if (cvt[t] == CVT_UNSUPPORTED) {
    +                int conversionType = getConversion(type, mapper);
    +                cvt[t] = conversionType;
    +                if (conversionType == CVT_UNSUPPORTED) {
                         throw new IllegalArgumentException(type + " is not a supported argument type (in method " + method.getName() + " in " + cls + ")");
                     }
    -                if (cvt[t] == CVT_NATIVE_MAPPED
    -                    || cvt[t] == CVT_NATIVE_MAPPED_STRING
    -                    || cvt[t] == CVT_NATIVE_MAPPED_WSTRING
    -                    || cvt[t] == CVT_INTEGER_TYPE) {
    +                if ((conversionType == CVT_NATIVE_MAPPED)
    +                 || (conversionType == CVT_NATIVE_MAPPED_STRING)
    +                 || (conversionType == CVT_NATIVE_MAPPED_WSTRING)
    +                 || (conversionType == CVT_INTEGER_TYPE)) {
                         type = NativeMappedConverter.getInstance(type).nativeType();
    -                }
    -                else if (cvt[t] == CVT_TYPE_MAPPER
    -                         || cvt[t] == CVT_TYPE_MAPPER_STRING
    -                         || cvt[t] == CVT_TYPE_MAPPER_WSTRING) {
    +                } else if ((conversionType == CVT_TYPE_MAPPER)
    +                        || (conversionType == CVT_TYPE_MAPPER_STRING)
    +                        || (conversionType == CVT_TYPE_MAPPER_WSTRING)) {
                         toNative[t] = mapper.getToNativeConverter(type);
                     }
    +
                     // Determine the type that will be passed to the native
                     // function, as well as the type to be passed
                     // from Java initially
    -                switch(cvt[t]) {
    -                case CVT_STRUCTURE_BYVAL:
    -                case CVT_INTEGER_TYPE:
    -                case CVT_POINTER_TYPE:
    -                case CVT_NATIVE_MAPPED:
    -                case CVT_NATIVE_MAPPED_STRING:
    -                case CVT_NATIVE_MAPPED_WSTRING:
    -                    atypes[t] = FFIType.get(type).peer;
    -                    closure_atypes[t] = FFIType.get(Pointer.class).peer;
    -                    break;
    -                case CVT_TYPE_MAPPER:
    -                case CVT_TYPE_MAPPER_STRING:
    -                case CVT_TYPE_MAPPER_WSTRING:
    -                    closure_atypes[t] = FFIType.get(type.isPrimitive() ? type : Pointer.class).peer;
    -                    atypes[t] = FFIType.get(toNative[t].nativeType()).peer;
    -                    break;
    -                case CVT_DEFAULT:
    -                    closure_atypes[t] = atypes[t] = FFIType.get(type).peer;
    -                    break;
    -                default:
    -                    closure_atypes[t] = atypes[t] = FFIType.get(Pointer.class).peer;
    -                    break;
    +                switch(conversionType) {
    +                    case CVT_STRUCTURE_BYVAL:
    +                    case CVT_INTEGER_TYPE:
    +                    case CVT_POINTER_TYPE:
    +                    case CVT_NATIVE_MAPPED:
    +                    case CVT_NATIVE_MAPPED_STRING:
    +                    case CVT_NATIVE_MAPPED_WSTRING:
    +                        atypes[t] = FFIType.get(type).peer;
    +                        closure_atypes[t] = FFIType.get(Pointer.class).peer;
    +                        break;
    +                    case CVT_TYPE_MAPPER:
    +                    case CVT_TYPE_MAPPER_STRING:
    +                    case CVT_TYPE_MAPPER_WSTRING:
    +                        closure_atypes[t] = FFIType.get(type.isPrimitive() ? type : Pointer.class).peer;
    +                        atypes[t] = FFIType.get(toNative[t].nativeType()).peer;
    +                        break;
    +                    case CVT_DEFAULT:
    +                        closure_atypes[t] = atypes[t] = FFIType.get(type).peer;
    +                        break;
    +                    default:
    +                        closure_atypes[t] = atypes[t] = FFIType.get(Pointer.class).peer;
                     }
                 }
                 sig += ")";
    @@ -1710,8 +1720,7 @@ else if (cvt[t] == CVT_TYPE_MAPPER
                                                 throwLastError,
                                                 toNative, fromNative,
                                                 f.encoding);
    -            }
    -            catch(NoSuchMethodError e) {
    +            } catch(NoSuchMethodError e) {
                     throw new UnsatisfiedLinkError("No method " + method.getName() + " with signature " + sig + " in " + cls);
                 }
             }
    @@ -1721,16 +1730,16 @@ else if (cvt[t] == CVT_TYPE_MAPPER
             }
         }
     
    -    /** Take note of options used for a given library mapping, to facilitate
    -        looking them up later.
    -    */
    -    private static Map cacheOptions(Class cls, Map libOptions, Object proxy) {
    -        libOptions = new HashMap(libOptions);
    +    /* Take note of options used for a given library mapping, to facilitate
    +     * looking them up later.
    +     */
    +    private static Map cacheOptions(Class cls, Map options, Object proxy) {
    +        Map libOptions = new HashMap(options);
             libOptions.put(_OPTION_ENCLOSING_LIBRARY, cls);
             synchronized(libraries) {
    -            options.put(cls, libOptions);
    +            typeOptions.put(cls, libOptions);
                 if (proxy != null) {
    -                libraries.put(cls, new WeakReference(proxy));
    +                libraries.put(cls, new WeakReference(proxy));
                 }
     
                 // If it's a direct mapping, AND implements a Library interface,
    @@ -1739,9 +1748,9 @@ private static Map cacheOptions(Class cls, Map libOptions, Object proxy) {
                 if (!cls.isInterface()
                     && Library.class.isAssignableFrom(cls)) {
                     Class ifaces[] = cls.getInterfaces();
    -                for (int i=0;i < ifaces.length;i++) {
    -                    if (Library.class.isAssignableFrom(ifaces[i])) {
    -                        cacheOptions(ifaces[i], libOptions, proxy);
    +                for (Class ifc : ifaces) {
    +                    if (Library.class.isAssignableFrom(ifc)) {
    +                        cacheOptions(ifc, libOptions, proxy);
                             break;
                         }
                     }
    @@ -1839,7 +1848,7 @@ public static void main(String[] args) {
          */
         static synchronized native long createNativeCallback(Callback callback,
                                                              Method method,
    -                                                         Class[] parameterTypes,
    +                                                         Class[] parameterTypes,
                                                              Class returnType,
                                                              int callingConvention,
                                                              int flags,
    diff --git a/src/com/sun/jna/NativeLibrary.java b/src/com/sun/jna/NativeLibrary.java
    index d60fce9362..3515e9c8b3 100644
    --- a/src/com/sun/jna/NativeLibrary.java
    +++ b/src/com/sun/jna/NativeLibrary.java
    @@ -17,17 +17,18 @@
     import java.io.BufferedReader;
     import java.io.File;
     import java.io.FilenameFilter;
    -import java.io.InputStreamReader;
     import java.io.IOException;
    -import java.lang.ref.WeakReference;
    +import java.io.InputStreamReader;
     import java.lang.ref.Reference;
    +import java.lang.ref.WeakReference;
     import java.lang.reflect.Method;
     import java.util.ArrayList;
     import java.util.Arrays;
    +import java.util.Collection;
     import java.util.Collections;
     import java.util.HashMap;
     import java.util.HashSet;
    -import java.util.Iterator;
    +import java.util.LinkedHashSet;
     import java.util.LinkedList;
     import java.util.List;
     import java.util.Map;
    @@ -51,7 +52,7 @@
      * with a name corresponding to that requested.  Absolute paths to frameworks
      * are also accepted, either ending at the framework name (sans ".framework")
      * or the full path to the framework shared library
    - * (e.g. CoreServices.framework/CoreServices). 
    + * (e.g. CoreServices.framework/CoreServices).
      * 
  • Context class loader classpath. Deployed native libraries may be * installed on the classpath under * ${os-prefix}/LIBRARY_FILENAME, where ${os-prefix} @@ -70,14 +71,14 @@ public class NativeLibrary { private long handle; private final String libraryName; private final String libraryPath; - private final Map functions = new HashMap(); + private final Map functions = new HashMap(); final int callFlags; private String encoding; - final Map options; + final Map options; - private static final Map libraries = new HashMap(); - private static final Map searchPaths = Collections.synchronizedMap(new HashMap()); - private static final List librarySearchPath = new LinkedList(); + private static final Map> libraries = new HashMap>(); + private static final Map> searchPaths = Collections.synchronizedMap(new HashMap>()); + private static final List librarySearchPath = new ArrayList(); static { // Force initialization of native library @@ -89,13 +90,12 @@ private static String functionKey(String name, int flags, String encoding) { return name + "|" + flags + "|" + encoding; } - private NativeLibrary(String libraryName, String libraryPath, long handle, Map options) { + private NativeLibrary(String libraryName, String libraryPath, long handle, Map options) { this.libraryName = getLibraryName(libraryName); this.libraryPath = libraryPath; this.handle = handle; Object option = options.get(Library.OPTION_CALLING_CONVENTION); - int callingConvention = option instanceof Number - ? ((Number)option).intValue() : Function.C_CONVENTION; + int callingConvention = option instanceof Number ? ((Number)option).intValue() : Function.C_CONVENTION; this.callFlags = callingConvention; this.options = options; this.encoding = (String)options.get(Library.OPTION_STRING_ENCODING); @@ -108,7 +108,8 @@ private NativeLibrary(String libraryName, String libraryPath, long handle, Map o if (Platform.isWindows() && "kernel32".equals(this.libraryName.toLowerCase())) { synchronized(functions) { Function f = new Function(this, "GetLastError", Function.ALT_CONVENTION, encoding) { - Object invoke(Object[] args, Class returnType, boolean b) { + @Override + Object invoke(Object[] args, Class returnType, boolean b) { return new Integer(Native.getLastError()); } }; @@ -118,7 +119,7 @@ Object invoke(Object[] args, Class returnType, boolean b) { } private static final int DEFAULT_OPEN_OPTIONS = -1; - private static int openFlags(Map options) { + private static int openFlags(Map options) { Object opt = options.get(Library.OPTION_OPEN_FLAGS); if (opt instanceof Number) { return ((Number)opt).intValue(); @@ -126,38 +127,39 @@ private static int openFlags(Map options) { return DEFAULT_OPEN_OPTIONS; } - private static NativeLibrary loadLibrary(String libraryName, Map options) { - if (Native.DEBUG_LOAD) { - System.out.println("Looking for library '" + libraryName + "'"); - } + private static NativeLibrary loadLibrary(String libraryName, Map options) { + if (Native.DEBUG_LOAD) { + System.out.println("Looking for library '" + libraryName + "'"); + } boolean isAbsolutePath = new File(libraryName).isAbsolute(); - List searchPath = new LinkedList(); + List searchPath = new ArrayList(); int openFlags = openFlags(options); // Append web start path, if available. Note that this does not // attempt any library name variations String webstartPath = Native.getWebStartLibraryPath(libraryName); if (webstartPath != null) { - if (Native.DEBUG_LOAD) { - System.out.println("Adding web start path " + webstartPath); - } + if (Native.DEBUG_LOAD) { + System.out.println("Adding web start path " + webstartPath); + } searchPath.add(webstartPath); } // // Prepend any custom search paths specifically for this library // - List customPaths = (List) searchPaths.get(libraryName); + List customPaths = searchPaths.get(libraryName); if (customPaths != null) { synchronized (customPaths) { searchPath.addAll(0, customPaths); } } - if (Native.DEBUG_LOAD) { - System.out.println("Adding paths from jna.library.path: " + System.getProperty("jna.library.path")); - } + if (Native.DEBUG_LOAD) { + System.out.println("Adding paths from jna.library.path: " + System.getProperty("jna.library.path")); + } + searchPath.addAll(initPaths("jna.library.path")); String libraryPath = findLibraryPath(libraryName, searchPath); long handle = 0; @@ -167,92 +169,99 @@ private static NativeLibrary loadLibrary(String libraryName, Map options) { // name if it cannot find the library. // try { - if (Native.DEBUG_LOAD) { - System.out.println("Trying " + libraryPath); - } + if (Native.DEBUG_LOAD) { + System.out.println("Trying " + libraryPath); + } handle = Native.open(libraryPath, openFlags); - } - catch(UnsatisfiedLinkError e) { + } catch(UnsatisfiedLinkError e) { // Add the system paths back for all fallback searching - if (Native.DEBUG_LOAD) { - System.out.println("Adding system paths: " + librarySearchPath); - } + if (Native.DEBUG_LOAD) { + System.out.println("Adding system paths: " + librarySearchPath); + } searchPath.addAll(librarySearchPath); } + try { if (handle == 0) { libraryPath = findLibraryPath(libraryName, searchPath); - if (Native.DEBUG_LOAD) { - System.out.println("Trying " + libraryPath); - } + if (Native.DEBUG_LOAD) { + System.out.println("Trying " + libraryPath); + } handle = Native.open(libraryPath, openFlags); if (handle == 0) { throw new UnsatisfiedLinkError("Failed to load library '" + libraryName + "'"); } } - } - catch(UnsatisfiedLinkError e) { - // For android, try to "preload" the library using + } catch(UnsatisfiedLinkError e) { + // For android, try to "preload" the library using // System.loadLibrary(), which looks into the private /data/data // path, not found in any properties if (Platform.isAndroid()) { try { - if (Native.DEBUG_LOAD) { - System.out.println("Preload (via System.loadLibrary) " + libraryName); - } + if (Native.DEBUG_LOAD) { + System.out.println("Preload (via System.loadLibrary) " + libraryName); + } System.loadLibrary(libraryName); handle = Native.open(libraryPath, openFlags); } - catch(UnsatisfiedLinkError e2) { e = e2; } + catch(UnsatisfiedLinkError e2) { + e = e2; + } } else if (Platform.isLinux() || Platform.isFreeBSD()) { // // Failed to load the library normally - try to match libfoo.so.* // - if (Native.DEBUG_LOAD) { - System.out.println("Looking for version variants"); - } + if (Native.DEBUG_LOAD) { + System.out.println("Looking for version variants"); + } libraryPath = matchLibrary(libraryName, searchPath); if (libraryPath != null) { - if (Native.DEBUG_LOAD) { - System.out.println("Trying " + libraryPath); - } - try { + if (Native.DEBUG_LOAD) { + System.out.println("Trying " + libraryPath); + } + try { handle = Native.open(libraryPath, openFlags); } - catch(UnsatisfiedLinkError e2) { e = e2; } + catch(UnsatisfiedLinkError e2) { + e = e2; + } } } // Search framework libraries on OS X - else if (Platform.isMac() - && !libraryName.endsWith(".dylib")) { - if (Native.DEBUG_LOAD) { - System.out.println("Looking for matching frameworks"); - } + else if (Platform.isMac() && !libraryName.endsWith(".dylib")) { + if (Native.DEBUG_LOAD) { + System.out.println("Looking for matching frameworks"); + } libraryPath = matchFramework(libraryName); if (libraryPath != null) { try { - if (Native.DEBUG_LOAD) { - System.out.println("Trying " + libraryPath); - } + if (Native.DEBUG_LOAD) { + System.out.println("Trying " + libraryPath); + } handle = Native.open(libraryPath, openFlags); } - catch(UnsatisfiedLinkError e2) { e = e2; } + catch(UnsatisfiedLinkError e2) { + e = e2; + } } } // Try the same library with a "lib" prefix else if (Platform.isWindows() && !isAbsolutePath) { - if (Native.DEBUG_LOAD) { - System.out.println("Looking for lib- prefix"); - } + if (Native.DEBUG_LOAD) { + System.out.println("Looking for lib- prefix"); + } libraryPath = findLibraryPath("lib" + libraryName, searchPath); - if (libraryPath != null) { - if (Native.DEBUG_LOAD) { - System.out.println("Trying " + libraryPath); - } - try { handle = Native.open(libraryPath, openFlags); } - catch(UnsatisfiedLinkError e2) { e = e2; } - } + if (libraryPath != null) { + if (Native.DEBUG_LOAD) { + System.out.println("Trying " + libraryPath); + } + try { + handle = Native.open(libraryPath, openFlags); + } catch(UnsatisfiedLinkError e2) { + e = e2; + } + } } // As a last resort, try to extract the library from the class // path, using the current context class loader. @@ -269,17 +278,19 @@ else if (Platform.isWindows() && !isAbsolutePath) { } } } - catch(IOException e2) { e = new UnsatisfiedLinkError(e2.getMessage()); } + catch(IOException e2) { + e = new UnsatisfiedLinkError(e2.getMessage()); + } } if (handle == 0) { - throw new UnsatisfiedLinkError("Unable to load library '" + libraryName + "': " - + e.getMessage()); + throw new UnsatisfiedLinkError("Unable to load library '" + libraryName + "': " + e.getMessage()); } } - if (Native.DEBUG_LOAD) { - System.out.println("Found library '" + libraryName + "' at " + libraryPath); - } + + if (Native.DEBUG_LOAD) { + System.out.println("Found library '" + libraryName + "' at " + libraryPath); + } return new NativeLibrary(libraryName, libraryPath, handle, options); } @@ -359,9 +370,7 @@ public static final NativeLibrary getInstance(String libraryName) { * or as a plain file within the classpath. */ public static final NativeLibrary getInstance(String libraryName, ClassLoader classLoader) { - Map map = new HashMap(); - map.put(Library.OPTION_CLASSLOADER, classLoader); - return getInstance(libraryName, map); + return getInstance(libraryName, Collections.singletonMap(Library.OPTION_CLASSLOADER, classLoader)); } /** @@ -374,15 +383,14 @@ public static final NativeLibrary getInstance(String libraryName, ClassLoader cl * @param libraryName The library name to load. * This can be short form (e.g. "c"), * an explicit version (e.g. "libc.so.6" or - * "QuickTime.framework/Versions/Current/QuickTime"), or - * the full (absolute) path to the library (e.g. "/lib/libc.so.6"). - * @param options native library options for the given library (see {@link - * Library}). + * "QuickTime.framework/Versions/Current/QuickTime"), or + * the full (absolute) path to the library (e.g. "/lib/libc.so.6"). + * @param libraryOptions Native library options for the given library (see {@link Library}). */ - public static final NativeLibrary getInstance(String libraryName, Map options) { - options = new HashMap(options); + public static final NativeLibrary getInstance(String libraryName, Map libraryOptions) { + Map options = new HashMap(libraryOptions); if (options.get(Library.OPTION_CALLING_CONVENTION) == null) { - options.put(Library.OPTION_CALLING_CONVENTION, new Integer(Function.C_CONVENTION)); + options.put(Library.OPTION_CALLING_CONVENTION, Integer.valueOf(Function.C_CONVENTION)); } // Use current process to load libraries we know are already @@ -392,8 +400,8 @@ public static final NativeLibrary getInstance(String libraryName, Map options) { libraryName = null; } synchronized (libraries) { - WeakReference ref = (WeakReference)libraries.get(libraryName + options); - NativeLibrary library = ref != null ? (NativeLibrary)ref.get() : null; + Reference ref = libraries.get(libraryName + options); + NativeLibrary library = (ref != null) ? ref.get() : null; if (library == null) { if (libraryName == null) { @@ -402,7 +410,7 @@ public static final NativeLibrary getInstance(String libraryName, Map options) { else { library = loadLibrary(libraryName, options); } - ref = new WeakReference(library); + ref = new WeakReference(library); libraries.put(library.getName() + options, ref); File file = library.getFile(); if (file != null) { @@ -430,7 +438,7 @@ public static synchronized final NativeLibrary getProcess() { * mapped by some other mechanism, without having to reference or even * know the exact name of the native library. */ - public static synchronized final NativeLibrary getProcess(Map options) { + public static synchronized final NativeLibrary getProcess(Map options) { return getInstance(null, options); } @@ -444,15 +452,16 @@ public static synchronized final NativeLibrary getProcess(Map options) { */ public static final void addSearchPath(String libraryName, String path) { synchronized (searchPaths) { - List customPaths = (List) searchPaths.get(libraryName); + List customPaths = searchPaths.get(libraryName); if (customPaths == null) { - customPaths = Collections.synchronizedList(new LinkedList()); + customPaths = Collections.synchronizedList(new ArrayList()); searchPaths.put(libraryName, customPaths); } customPaths.add(path); } } + /** * Create a new {@link Function} that is linked with a native * function that follows the NativeLibrary's calling convention. @@ -460,8 +469,8 @@ public static final void addSearchPath(String libraryName, String path) { *

    The allocated instance represents a pointer to the named native * function from the library. * - * @param functionName - * Name of the native function to be linked with + * @param functionName + * Name of the native function to be linked with * @throws UnsatisfiedLinkError if the function is not found */ public Function getFunction(String functionName) { @@ -475,12 +484,12 @@ public Function getFunction(String functionName) { *

    The allocated instance represents a pointer to the named native * function from the library. * - * @param name - * Name of the native function to be linked with. Uses a - * function mapper option if one was provided to - * transform the name. - * @param method - * Method to which the native function is to be mapped + * @param name + * Name of the native function to be linked with. Uses a + * function mapper option if one was provided to + * transform the name. + * @param method + * Method to which the native function is to be mapped * @throws UnsatisfiedLinkError if the function is not found */ Function getFunction(String name, Method method) { @@ -495,7 +504,7 @@ Function getFunction(String name, Method method) { name = name.substring(prefix.length()); } int flags = this.callFlags; - Class[] etypes = method.getExceptionTypes(); + Class[] etypes = method.getExceptionTypes(); for (int i=0;i < etypes.length;i++) { if (LastErrorException.class.isAssignableFrom(etypes[i])) { flags |= Function.THROW_LAST_ERROR; @@ -508,10 +517,10 @@ Function getFunction(String name, Method method) { * Create a new {@link Function} that is linked with a native * function that follows a given calling flags. * - * @param functionName - * Name of the native function to be linked with - * @param callFlags - * Flags affecting the function invocation + * @param functionName + * Name of the native function to be linked with + * @param callFlags + * Flags affecting the function invocation * @throws UnsatisfiedLinkError if the function is not found */ public Function getFunction(String functionName, int callFlags) { @@ -522,21 +531,22 @@ public Function getFunction(String functionName, int callFlags) { * Create a new {@link Function} that is linked with a native * function that follows a given calling flags. * - * @param functionName - * Name of the native function to be linked with - * @param callFlags - * Flags affecting the function invocation + * @param functionName + * Name of the native function to be linked with + * @param callFlags + * Flags affecting the function invocation * @param encoding * Encoding to use to convert between Java and native - * strings. + * strings. * @throws UnsatisfiedLinkError if the function is not found */ public Function getFunction(String functionName, int callFlags, String encoding) { - if (functionName == null) + if (functionName == null) { throw new NullPointerException("Function name may not be null"); + } synchronized (functions) { String key = functionKey(functionName, callFlags, encoding); - Function function = (Function) functions.get(key); + Function function = functions.get(key); if (function == null) { function = new Function(this, functionName, callFlags, encoding); functions.put(key, function); @@ -545,8 +555,8 @@ public Function getFunction(String functionName, int callFlags, String encoding) } } - /** Returns this native library instance's options. */ - public Map getOptions() { + /** @return this native library instance's options. */ + public Map getOptions() { return options; } @@ -558,11 +568,8 @@ public Map getOptions() { public Pointer getGlobalVariableAddress(String symbolName) { try { return new Pointer(getSymbolAddress(symbolName)); - } - catch(UnsatisfiedLinkError e) { - throw new UnsatisfiedLinkError("Error looking up '" - + symbolName + "': " - + e.getMessage()); + } catch(UnsatisfiedLinkError e) { + throw new UnsatisfiedLinkError("Error looking up '" + symbolName + "': " + e.getMessage()); } } @@ -576,6 +583,8 @@ long getSymbolAddress(String name) { } return Native.findSymbol(handle, name); } + + @Override public String toString() { return "Native Library <" + libraryPath + "@" + handle + ">"; } @@ -593,19 +602,19 @@ public File getFile() { return new File(libraryPath); } /** Close the library when it is no longer referenced. */ + @Override protected void finalize() { dispose(); } /** Close all open native libraries. */ static void disposeAll() { - Set values; + Set> values; synchronized(libraries) { - values = new HashSet(libraries.values()); + values = new LinkedHashSet>(libraries.values()); } - for (Iterator i=values.iterator();i.hasNext();) { - Reference ref = (WeakReference)i.next(); - NativeLibrary lib = (NativeLibrary)ref.get(); + for (Reference ref : values) { + NativeLibrary lib = ref.get(); if (lib != null) { lib.dispose(); } @@ -614,14 +623,20 @@ static void disposeAll() { /** Close the native library we're mapped to. */ public void dispose() { + Set keys = new HashSet(); synchronized(libraries) { - for (Iterator i=libraries.values().iterator();i.hasNext();) { - Reference ref = (WeakReference)i.next(); + for (Map.Entry> e : libraries.entrySet()) { + Reference ref = e.getValue(); if (ref.get() == this) { - i.remove(); + keys.add(e.getKey()); } } + + for (String k : keys) { + libraries.remove(k); + } } + synchronized(this) { if (handle != 0) { Native.close(handle); @@ -630,13 +645,13 @@ public void dispose() { } } - private static List initPaths(String key) { + private static List initPaths(String key) { String value = System.getProperty(key, ""); if ("".equals(value)) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } StringTokenizer st = new StringTokenizer(value, File.pathSeparator); - List list = new ArrayList(); + List list = new ArrayList(); while (st.hasMoreTokens()) { String path = st.nextToken(); if (!"".equals(path)) { @@ -647,7 +662,7 @@ private static List initPaths(String key) { } /** Use standard library search paths to find the library. */ - private static String findLibraryPath(String libName, List searchPath) { + private static String findLibraryPath(String libName, List searchPath) { // // If a full path to the library was specified, don't search for it @@ -662,8 +677,7 @@ private static String findLibraryPath(String libName, List searchPath) { String name = mapSharedLibraryName(libName); // Search in the JNA paths for it - for (Iterator it = searchPath.iterator(); it.hasNext(); ) { - String path = (String)it.next(); + for (String path : searchPath) { File file = new File(path, name); if (file.exists()) { return file.getAbsolutePath(); @@ -713,7 +727,7 @@ else if (Platform.isLinux() || Platform.isFreeBSD()) { return libName; } } - else if (Platform.isAIX()) { // can be libx.a, libx.a(shr.o), libx.so + else if (Platform.isAIX()) { // can be libx.a, libx.a(shr.o), libx.so if (libName.startsWith("lib")) { return libName; } @@ -748,12 +762,13 @@ private static boolean isVersionedName(String name) { * where /usr/lib/libc.so does not exist, or it is not a valid symlink to * a versioned file (e.g. /lib/libc.so.6). */ - static String matchLibrary(final String libName, List searchPath) { - File lib = new File(libName); + static String matchLibrary(final String libName, List searchPath) { + File lib = new File(libName); if (lib.isAbsolute()) { - searchPath = Arrays.asList(new String[] { lib.getParent() }); + searchPath = Arrays.asList(lib.getParent()); } FilenameFilter filter = new FilenameFilter() { + @Override public boolean accept(File dir, String filename) { return (filename.startsWith("lib" + libName + ".so") || (filename.startsWith(libName + ".so") @@ -762,9 +777,9 @@ public boolean accept(File dir, String filename) { } }; - List matches = new LinkedList(); - for (Iterator it = searchPath.iterator(); it.hasNext(); ) { - File[] files = new File((String) it.next()).listFiles(filter); + Collection matches = new LinkedList(); + for (String path : searchPath) { + File[] files = new File(path).listFiles(filter); if (files != null && files.length > 0) { matches.addAll(Arrays.asList(files)); } @@ -775,8 +790,8 @@ public boolean accept(File dir, String filename) { // i.e. libc.so.6 is preferred over libc.so.5 double bestVersion = -1; String bestMatch = null; - for (Iterator it = matches.iterator(); it.hasNext(); ) { - String path = ((File) it.next()).getAbsolutePath(); + for (File f : matches) { + String path = f.getAbsolutePath(); String ver = path.substring(path.lastIndexOf(".so.") + 4); double version = parseVersion(ver); if (version > bestVersion) { @@ -788,10 +803,10 @@ public boolean accept(File dir, String filename) { } static double parseVersion(String ver) { - double v = 0; - double divisor = 1; - int dot = ver.indexOf("."); - while (ver != null) { + double v = 0; + double divisor = 1; + int dot = ver.indexOf("."); + while (ver != null) { String num; if (dot != -1) { num = ver.substring(0, dot); @@ -809,9 +824,9 @@ static double parseVersion(String ver) { return 0; } divisor *= 100; - } + } - return v; + return v; } static { @@ -906,7 +921,7 @@ private static String getMultiArchPath() { ? "-kfreebsd" : (Platform.isGNU() ? "" : "-linux"); String libc = "-gnu"; - + if (Platform.isIntel()) { cpu = (Platform.is64Bit() ? "x86_64" : "i386"); } @@ -917,7 +932,7 @@ else if (Platform.isARM()) { cpu = "arm"; libc = "-gnueabi"; } - + return cpu + kernel + libc; } diff --git a/src/com/sun/jna/NativeLong.java b/src/com/sun/jna/NativeLong.java index 2d9dd17b8e..a760bf2a05 100644 --- a/src/com/sun/jna/NativeLong.java +++ b/src/com/sun/jna/NativeLong.java @@ -8,7 +8,7 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -19,6 +19,7 @@ * @author wmeissner@gmail.com */ public class NativeLong extends IntegerType { + private static final long serialVersionUID = 1L; /** Size of a native long, in bytes. */ public static final int SIZE = Native.LONG_SIZE; @@ -26,7 +27,7 @@ public class NativeLong extends IntegerType { public NativeLong() { this(0); } - + /** Create a NativeLong with the given value. */ public NativeLong(long value) { this(value, false); diff --git a/src/com/sun/jna/NativeMapped.java b/src/com/sun/jna/NativeMapped.java index a8a347e8d2..92065dd903 100644 --- a/src/com/sun/jna/NativeMapped.java +++ b/src/com/sun/jna/NativeMapped.java @@ -1,27 +1,27 @@ /* Copyright (c) 2007 Wayne Meissner, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; -/** Provide conversion for a Java type to and from a native type. +/** Provide conversion for a Java type to and from a native type. * {@link Function} and {@link Structure} will use this interface to determine * how to map a given Java object into a native type.

    * Implementations of this interface must provide a no-args constructor.

    *

    See {@link ToNativeConverter} for a list of allowable native types.

    - * @author wmeissner + * @author wmeissner */ public interface NativeMapped { /** Convert the given native object into its Java representation using - * the given context. + * the given context. * @param nativeValue Java representation of the native type to be converted. * @param context Context in which the conversion is taking place. * @return Converted object. @@ -34,5 +34,5 @@ public interface NativeMapped { /** Indicate the native type used by this converter. * @return Java class representation of the native type. */ - Class nativeType(); + Class nativeType(); } diff --git a/src/com/sun/jna/NativeMappedConverter.java b/src/com/sun/jna/NativeMappedConverter.java index 421dd8ff8c..963af3b3bb 100644 --- a/src/com/sun/jna/NativeMappedConverter.java +++ b/src/com/sun/jna/NativeMappedConverter.java @@ -19,27 +19,27 @@ /** Provides type conversion for instances of {@link NativeMapped}. */ public class NativeMappedConverter implements TypeConverter { - private static final Map/*>*/ converters = new WeakHashMap(); - private final Class type; - private final Class nativeType; + private static final Map, Reference> converters = + new WeakHashMap, Reference>(); + private final Class type; + private final Class nativeType; private final NativeMapped instance; - public static NativeMappedConverter getInstance(Class cls) { + public static NativeMappedConverter getInstance(Class cls) { synchronized(converters) { - Reference r = (Reference)converters.get(cls); - NativeMappedConverter nmc = r != null ? (NativeMappedConverter)r.get() : null; + Reference r = converters.get(cls); + NativeMappedConverter nmc = r != null ? r.get() : null; if (nmc == null) { nmc = new NativeMappedConverter(cls); - converters.put(cls, new SoftReference(nmc)); + converters.put(cls, new SoftReference(nmc)); } return nmc; } } - public NativeMappedConverter(Class type) { + public NativeMappedConverter(Class type) { if (!NativeMapped.class.isAssignableFrom(type)) - throw new IllegalArgumentException("Type must derive from " - + NativeMapped.class); + throw new IllegalArgumentException("Type must derive from " + NativeMapped.class); this.type = type; this.instance = defaultValue(); this.nativeType = instance.nativeType(); @@ -48,26 +48,27 @@ public NativeMappedConverter(Class type) { public NativeMapped defaultValue() { try { return (NativeMapped)type.newInstance(); - } - catch (InstantiationException e) { + } catch (InstantiationException e) { String msg = "Can't create an instance of " + type + ", requires a no-arg constructor: " + e; throw new IllegalArgumentException(msg); - } - catch (IllegalAccessException e) { + } catch (IllegalAccessException e) { String msg = "Not allowed to create an instance of " + type + ", requires a public, no-arg constructor: " + e; throw new IllegalArgumentException(msg); } } + @Override public Object fromNative(Object nativeValue, FromNativeContext context) { return instance.fromNative(nativeValue, context); } - public Class nativeType() { + @Override + public Class nativeType() { return nativeType; } + @Override public Object toNative(Object value, ToNativeContext context) { if (value == null) { if (Pointer.class.isAssignableFrom(nativeType)) { diff --git a/src/com/sun/jna/NativeString.java b/src/com/sun/jna/NativeString.java index 81f1b726fa..4250c68f98 100644 --- a/src/com/sun/jna/NativeString.java +++ b/src/com/sun/jna/NativeString.java @@ -6,16 +6,16 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; import java.nio.CharBuffer; -/** Provides a temporary allocation of an immutable C string - * (const char* or const wchar_t*) for use when - * converting a Java String into a native memory function argument. +/** Provides a temporary allocation of an immutable C string + * (const char* or const wchar_t*) for use when + * converting a Java String into a native memory function argument. * * @author Todd Fast, todd.fast@sun.com * @author twall@users.sf.net @@ -29,6 +29,7 @@ class NativeString implements CharSequence, Comparable { private class StringMemory extends Memory { public StringMemory(long size) { super(size); } + @Override public String toString() { return NativeString.this.toString(); } @@ -44,8 +45,8 @@ public NativeString(String string) { /** Create a native string as a NUL-terminated array of wchar_t * (if wide is true) or char.

    * If not wide, the encoding is obtained from {@link - * Native#getDefaultStringEncoding()}. - * + * Native#getDefaultStringEncoding()}. + * * @param string value to write to native memory * @param wide whether to store the String as wchar_t */ @@ -54,7 +55,7 @@ public NativeString(String string, boolean wide) { } /** Create a native string as a NUL-terminated array of - * wchar_t. + * wchar_t. */ public NativeString(WString string) { this(string.toString(), WIDE_STRING); @@ -68,15 +69,14 @@ public NativeString(String string, String encoding) { throw new NullPointerException("String must not be null"); } // Allocate the memory to hold the string. Note, we have to - // make this 1 element longer in order to accommodate the terminating + // make this 1 element longer in order to accommodate the terminating // NUL (which is generated in Pointer.setString()). this.encoding = encoding; - if (this.encoding == WIDE_STRING) { + if (WIDE_STRING.equals(this.encoding)) { int len = (string.length() + 1 ) * Native.WCHAR_SIZE; pointer = new StringMemory(len); pointer.setWideString(0, string); - } - else { + } else { byte[] data = Native.getBytes(string, encoding); pointer = new StringMemory(data.length + 1); pointer.write(0, data, 0, data.length); @@ -84,20 +84,22 @@ public NativeString(String string, String encoding) { } } + @Override public int hashCode() { return toString().hashCode(); } + @Override public boolean equals(Object other) { - if (other instanceof CharSequence) { return compareTo(other) == 0; } return false; } + @Override public String toString() { - boolean wide = encoding == WIDE_STRING; + boolean wide = WIDE_STRING.equals(encoding); String s = wide ? "const wchar_t*" : "const char*"; s += "(" + (wide ? pointer.getWideString(0) : pointer.getString(0, encoding)) + ")"; return s; @@ -107,20 +109,23 @@ public Pointer getPointer() { return pointer; } + @Override public char charAt(int index) { return toString().charAt(index); } + @Override public int length() { return toString().length(); } + @Override public CharSequence subSequence(int start, int end) { return CharBuffer.wrap(toString()).subSequence(start, end); } + @Override public int compareTo(Object other) { - if (other == null) return 1; diff --git a/src/com/sun/jna/Pointer.java b/src/com/sun/jna/Pointer.java index 111a683644..a11da87911 100644 --- a/src/com/sun/jna/Pointer.java +++ b/src/com/sun/jna/Pointer.java @@ -6,7 +6,7 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -18,13 +18,13 @@ import java.util.List; /** - * An abstraction for a native pointer data type. A Pointer instance - * represents, on the Java side, a native pointer. The native pointer could - * be any type of native pointer. Methods such as write, - * read, getXXX, and setXXX, provide + * An abstraction for a native pointer data type. A Pointer instance + * represents, on the Java side, a native pointer. The native pointer could + * be any type of native pointer. Methods such as write, + * read, getXXX, and setXXX, provide * means to access memory underlying the native pointer.

    * While a constructor exists to create a Pointer from an integer value, it's - * not generally a good idea to be creating pointers that way. + * not generally a good idea to be creating pointers that way. * * @author Sheng Liang, originator * @author Todd Fast, suitability modifications @@ -35,22 +35,22 @@ public class Pointer { /** Size of a native pointer, in bytes. */ public static final int SIZE; - + static { // Force load of native library if ((SIZE = Native.POINTER_SIZE) == 0) { throw new Error("Native library not initialized"); } } - + /** Convenience constant, same as null. */ public static final Pointer NULL = null; - + /** Convenience constant, equivalent to (void*)CONSTANT. */ public static final Pointer createConstant(long peer) { return new Opaque(peer); } - + /** Convenience constant, equivalent to (void*)CONSTANT. This version will avoid setting any of the high bits on 64-bit systems. @@ -58,14 +58,14 @@ public static final Pointer createConstant(long peer) { public static final Pointer createConstant(int peer) { return new Opaque((long)peer & 0xFFFFFFFF); } - - /** Pointer value of the real native pointer. Use long to be 64-bit safe. + + /** Pointer value of the real native pointer. Use long to be 64-bit safe. */ protected long peer; /** Derived class must assign peer pointer value. */ Pointer() { } - + /** Create from native pointer. Don't use this unless you know what * you're doing. */ @@ -77,7 +77,7 @@ public Pointer(long peer) { public Pointer share(long offset) { return share(offset, 0); } - + /** Provide a view of this memory using the given offset to calculate a * new base address, bounds-limiting the memory with the given size. */ @@ -94,12 +94,13 @@ public void clear(long size) { /** * Compares this Pointer to the specified object. * - * @param o + * @param o * A Pointer instance - * @return True if the other object is a Pointer, + * @return True if the other object is a Pointer, * and the C pointers being pointed to by these objects are also * equal. Returns false otherwise. */ + @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; @@ -112,6 +113,7 @@ public boolean equals(Object o) { * * @return A hash code value for the represented native pointer */ + @Override public int hashCode() { return (int)((peer >>> 32) + (peer & 0xFFFFFFFF)); } @@ -127,7 +129,7 @@ public int hashCode() { public long indexOf(long offset, byte value) { return Native.indexOf(peer + offset, value); } - + /** * Indirect the native pointer, copying from memory pointed to by * native pointer, into the specified array. @@ -166,7 +168,7 @@ public void read(long offset, short[] buf, int index, int length) { public void read(long offset, char[] buf, int index, int length) { Native.read(peer + offset, buf, index, length); } - + /** * Indirect the native pointer, copying from memory pointed to by * native pointer, into the specified array. @@ -301,7 +303,7 @@ public void write(long offset, int[] buf, int index, int length) { } /** - * Indirect the native pointer, copying into memory pointed to by + * Indirect the native pointer, copying into memory pointed to by * native pointer, from the specified array. * * @param offset byte offset from pointer into which data is copied @@ -359,71 +361,58 @@ public void write(long bOff, Pointer[] buf, int index, int length) { // Java type read methods ////////////////////////////////////////////////////////////////////////// - Object getValue(long offset, Class type, Object currentValue) { + Object getValue(long offset, Class type, Object currentValue) { Object result = null; if (Structure.class.isAssignableFrom(type)) { Structure s = (Structure)currentValue; if (Structure.ByReference.class.isAssignableFrom(type)) { s = Structure.updateStructureByReference(type, s, getPointer(offset)); - } - else { + } else { s.useMemory(this, (int)offset, true); s.read(); } result = s; - } - else if (type == boolean.class || type == Boolean.class) { + } else if (type == boolean.class || type == Boolean.class) { result = Function.valueOf(getInt(offset) != 0); - } - else if (type == byte.class || type == Byte.class) { - result = new Byte(getByte(offset)); - } - else if (type == short.class || type == Short.class) { - result = new Short(getShort(offset)); - } - else if (type == char.class || type == Character.class) { - result = new Character(getChar(offset)); - } - else if (type == int.class || type == Integer.class) { - result = new Integer(getInt(offset)); - } - else if (type == long.class || type == Long.class) { - result = new Long(getLong(offset)); - } - else if (type == float.class || type == Float.class) { - result=new Float(getFloat(offset)); - } - else if (type == double.class || type == Double.class) { - result = new Double(getDouble(offset)); - } - else if (Pointer.class.isAssignableFrom(type)) { + } else if (type == byte.class || type == Byte.class) { + result = Byte.valueOf(getByte(offset)); + } else if (type == short.class || type == Short.class) { + result = Short.valueOf(getShort(offset)); + } else if (type == char.class || type == Character.class) { + result = Character.valueOf(getChar(offset)); + } else if (type == int.class || type == Integer.class) { + result = Integer.valueOf(getInt(offset)); + } else if (type == long.class || type == Long.class) { + result = Long.valueOf(getLong(offset)); + } else if (type == float.class || type == Float.class) { + result = Float.valueOf(getFloat(offset)); + } else if (type == double.class || type == Double.class) { + result = Double.valueOf(getDouble(offset)); + } else if (Pointer.class.isAssignableFrom(type)) { Pointer p = getPointer(offset); if (p != null) { Pointer oldp = currentValue instanceof Pointer ? (Pointer)currentValue : null; - if (oldp == null || p.peer != oldp.peer) + if (oldp == null || p.peer != oldp.peer) { result = p; - else + } else { result = oldp; + } } - } - else if (type == String.class) { + } else if (type == String.class) { Pointer p = getPointer(offset); result = p != null ? p.getString(0) : null; - } - else if (type == WString.class) { + } else if (type == WString.class) { Pointer p = getPointer(offset); result = p != null ? new WString(p.getWideString(0)) : null; - } - else if (Callback.class.isAssignableFrom(type)) { + } else if (Callback.class.isAssignableFrom(type)) { // Overwrite the Java memory if the native pointer is a different // function pointer. Pointer fp = getPointer(offset); if (fp == null) { result = null; - } - else { + } else { Callback cb = (Callback)currentValue; Pointer oldfp = CallbackReference.getFunctionPointer(cb); if (!fp.equals(oldfp)) { @@ -431,13 +420,11 @@ else if (Callback.class.isAssignableFrom(type)) { } result = cb; } - } - else if (Platform.HAS_BUFFERS && Buffer.class.isAssignableFrom(type)) { + } else if (Platform.HAS_BUFFERS && Buffer.class.isAssignableFrom(type)) { Pointer bp = getPointer(offset); if (bp == null) { result = null; - } - else { + } else { Pointer oldbp = currentValue == null ? null : Native.getDirectBufferPointer((Buffer)currentValue); if (oldbp == null || !oldbp.equals(bp)) { @@ -445,8 +432,7 @@ else if (Platform.HAS_BUFFERS && Buffer.class.isAssignableFrom(type)) { } result = currentValue; } - } - else if (NativeMapped.class.isAssignableFrom(type)) { + } else if (NativeMapped.class.isAssignableFrom(type)) { NativeMapped nm = (NativeMapped)currentValue; if (nm != null) { Object value = getValue(offset, nm.nativeType(), null); @@ -454,33 +440,29 @@ else if (NativeMapped.class.isAssignableFrom(type)) { if (nm.equals(result)) { result = nm; } - } - else { + } else { NativeMappedConverter tc = NativeMappedConverter.getInstance(type); Object value = getValue(offset, tc.nativeType(), null); result = tc.fromNative(value, new FromNativeContext(type)); } - } - else if (type.isArray()) { + } else if (type.isArray()) { result = currentValue; if (result == null) { throw new IllegalStateException("Need an initialized array"); } readArray(offset, result, type.getComponentType()); - } - else { - throw new IllegalArgumentException("Reading \"" - + type + "\" from memory is not supported"); + } else { + throw new IllegalArgumentException("Reading \"" + type + "\" from memory is not supported"); } return result; } /** Read memory starting at offset into the array with element type cls. */ - private void readArray(long offset, Object o, Class cls) { + private void readArray(long offset, Object o, Class cls) { int length = 0; length = Array.getLength(o); Object result = o; - + if (cls == byte.class) { read(offset, (byte[])result, 0, length); } @@ -677,20 +659,21 @@ public ByteBuffer getByteBuffer(long offset, long length) { /** * Copy native memory to a Java String. If wide is true, - * access the memory as an array of wchar_t, otherwise + * access the memory as an array of wchar_t, otherwise * as an array of char, using the default platform encoding. * * @param offset byte offset from pointer to obtain the native string v * @param wide whether to convert from a wide or standard C string - * @return the String value being pointed to - * + * @return the String value being pointed to + * * @deprecated use {@link #getString(long,String)} or {@link - * #getWideString(long)} instead. + * #getWideString(long)} instead. */ + @Deprecated public String getString(long offset, boolean wide) { return wide ? getWideString(offset) : getString(offset); } - + /** Read a wide (const wchar_t *) string from memory. */ public String getWideString(long offset) { return Native.getWideString(peer + offset); @@ -701,7 +684,7 @@ public String getWideString(long offset) { * form {@link Native#getDefaultStringEncoding()}. * * @param offset byte offset from pointer to start reading bytes - * @return the String value being pointed to + * @return the String value being pointed to */ public String getString(long offset) { return getString(offset, Native.getDefaultStringEncoding()); @@ -712,7 +695,7 @@ public String getString(long offset) { * * @param offset byte offset from pointer to obtain the native string * @param encoding the desired encoding - * @return the String value being pointed to + * @return the String value being pointed to */ public String getString(long offset, String encoding) { return Native.getString(peer + offset, encoding); @@ -726,7 +709,7 @@ public byte[] getByteArray(long offset, int arraySize) { read(offset, buf, 0, arraySize); return buf; } - + /** Read a native array of wchar_t of size arraySize from the given offset from this {@link Pointer}. */ @@ -785,7 +768,7 @@ public double[] getDoubleArray(long offset, int arraySize) { * determined by a NULL-valued terminating element. */ public Pointer[] getPointerArray(long offset) { - List array = new ArrayList(); + List array = new ArrayList(); int addOffset = 0; Pointer p = getPointer(offset); while (p != null) { @@ -793,7 +776,7 @@ public Pointer[] getPointerArray(long offset) { addOffset += Pointer.SIZE; p = getPointer(offset + addOffset); } - return (Pointer[])array.toArray(new Pointer[array.size()]); + return array.toArray(new Pointer[array.size()]); } /** Returns an array of {@link Pointer} of the requested size. */ @@ -805,7 +788,7 @@ public Pointer[] getPointerArray(long offset, int arraySize) { /**

    Returns an array of String based on a native array * of char *. The array length is determined by a - * NULL-valued terminating element. + * NULL-valued terminating element. *

    * The strings are decoded using the encoding returned by {@link * Native#getDefaultStringEncoding()}. @@ -816,14 +799,14 @@ public String[] getStringArray(long offset) { /** Returns an array of String based on a native array * of char *, using the requested encoding. The array length - * is determined by a NULL-valued terminating element. + * is determined by a NULL-valued terminating element. */ public String[] getStringArray(long offset, String encoding) { return getStringArray(offset, -1, encoding); } /**

    Returns an array of String based on a native array - * of char *, using the given array length. + * of char *, using the given array length. *

    * The strings are decoded using the encoding returned by {@link * Native#getDefaultStringEncoding()}. @@ -835,11 +818,12 @@ public String[] getStringArray(long offset, int length) { /** Returns an array of String based on a native array * of char* or wchar_t* based on the * wide parameter. The array length is determined by a - * NULL-valued terminating element. - * + * NULL-valued terminating element. + * * @deprecated use {@link #getStringArray(long,String)} or {@link * #getWideStringArray(long)} instead. */ + @Deprecated public String[] getStringArray(long offset, boolean wide) { return getStringArray(offset, -1, wide); } @@ -855,10 +839,11 @@ public String[] getWideStringArray(long offset, int length) { /** Returns an array of String based on a native array * of char* or wchar_t* based on the * wide parameter, using the given array length. - * + * * @deprecated use {@link #getStringArray(long,int,String)} or {@link * #getWideStringArray(long,int)} instead. */ + @Deprecated public String[] getStringArray(long offset, int length, boolean wide) { return getStringArray(offset, length, wide ? NativeString.WIDE_STRING : Native.getDefaultStringEncoding()); } @@ -871,7 +856,7 @@ public String[] getStringArray(long offset, int length, boolean wide) { * @param encoding */ public String[] getStringArray(long offset, int length, String encoding) { - List strings = new ArrayList(); + List strings = new ArrayList(); Pointer p; int addOffset = 0; if (length != -1) { @@ -880,7 +865,7 @@ public String[] getStringArray(long offset, int length, String encoding) { while (count++ < length) { String s = p == null ? null - : (encoding == NativeString.WIDE_STRING + : (NativeString.WIDE_STRING.equals(encoding) ? p.getWideString(0) : p.getString(0, encoding)); strings.add(s); if (count < length) { @@ -888,61 +873,49 @@ public String[] getStringArray(long offset, int length, String encoding) { p = getPointer(offset + addOffset); } } - } - else { + } else { while ((p = getPointer(offset + addOffset)) != null) { String s = p == null ? null - : (encoding == NativeString.WIDE_STRING + : (NativeString.WIDE_STRING.equals(encoding) ? p.getWideString(0) : p.getString(0, encoding)); strings.add(s); addOffset += SIZE; } } - return (String[])strings.toArray(new String[strings.size()]); + return strings.toArray(new String[strings.size()]); } ////////////////////////////////////////////////////////////////////////// // Java type write methods ////////////////////////////////////////////////////////////////////////// - void setValue(long offset, Object value, Class type) { + void setValue(long offset, Object value, Class type) { // Set the value at the offset according to its type if (type == boolean.class || type == Boolean.class) { setInt(offset, Boolean.TRUE.equals(value) ? -1 : 0); - } - else if (type == byte.class || type == Byte.class) { + } else if (type == byte.class || type == Byte.class) { setByte(offset, value == null ? 0 : ((Byte)value).byteValue()); - } - else if (type == short.class || type == Short.class) { + } else if (type == short.class || type == Short.class) { setShort(offset, value == null ? 0 : ((Short)value).shortValue()); - } - else if (type == char.class || type == Character.class) { + } else if (type == char.class || type == Character.class) { setChar(offset, value == null ? 0 : ((Character)value).charValue()); - } - else if (type == int.class || type == Integer.class) { + } else if (type == int.class || type == Integer.class) { setInt(offset, value == null ? 0 : ((Integer)value).intValue()); - } - else if (type == long.class || type == Long.class) { + } else if (type == long.class || type == Long.class) { setLong(offset, value == null ? 0 : ((Long)value).longValue()); - } - else if (type == float.class || type == Float.class) { + } else if (type == float.class || type == Float.class) { setFloat(offset, value == null ? 0f : ((Float)value).floatValue()); - } - else if (type == double.class || type == Double.class) { + } else if (type == double.class || type == Double.class) { setDouble(offset, value == null ? 0.0 : ((Double)value).doubleValue()); - } - else if (type == Pointer.class) { + } else if (type == Pointer.class) { setPointer(offset, (Pointer)value); - } - else if (type == String.class) { + } else if (type == String.class) { setPointer(offset, (Pointer)value); - } - else if (type == WString.class) { + } else if (type == WString.class) { setPointer(offset, (Pointer)value); - } - else if (Structure.class.isAssignableFrom(type)) { + } else if (Structure.class.isAssignableFrom(type)) { Structure s = (Structure)value; if (Structure.ByReference.class.isAssignableFrom(type)) { setPointer(offset, s == null ? null : s.getPointer()); @@ -954,84 +927,68 @@ else if (Structure.class.isAssignableFrom(type)) { s.useMemory(this, (int)offset, true); s.write(); } - } - else if (Callback.class.isAssignableFrom(type)) { + } else if (Callback.class.isAssignableFrom(type)) { setPointer(offset, CallbackReference.getFunctionPointer((Callback)value)); - } - else if (Platform.HAS_BUFFERS && Buffer.class.isAssignableFrom(type)) { + } else if (Platform.HAS_BUFFERS && Buffer.class.isAssignableFrom(type)) { Pointer p = value == null ? null : Native.getDirectBufferPointer((Buffer)value); setPointer(offset, p); - } - else if (NativeMapped.class.isAssignableFrom(type)) { + } else if (NativeMapped.class.isAssignableFrom(type)) { NativeMappedConverter tc = NativeMappedConverter.getInstance(type); - Class nativeType = tc.nativeType(); + Class nativeType = tc.nativeType(); setValue(offset, tc.toNative(value, new ToNativeContext()), nativeType); - } - else if (type.isArray()) { + } else if (type.isArray()) { writeArray(offset, value, type.getComponentType()); - } - else { + } else { throw new IllegalArgumentException("Writing " + type + " to memory is not supported"); } } /** Write memory starting at offset from the array with element type cls. */ - private void writeArray(long offset, Object value, Class cls) { + private void writeArray(long offset, Object value, Class cls) { if (cls == byte.class) { byte[] buf = (byte[])value; write(offset, buf, 0, buf.length); - } - else if (cls == short.class) { + } else if (cls == short.class) { short[] buf = (short[])value; write(offset, buf, 0, buf.length); - } - else if (cls == char.class) { + } else if (cls == char.class) { char[] buf = (char[])value; write(offset, buf, 0, buf.length); - } - else if (cls == int.class) { + } else if (cls == int.class) { int[] buf = (int[])value; write(offset, buf, 0, buf.length); - } - else if (cls == long.class) { + } else if (cls == long.class) { long[] buf = (long[])value; write(offset, buf, 0, buf.length); - } - else if (cls == float.class) { + } else if (cls == float.class) { float[] buf = (float[])value; write(offset, buf, 0, buf.length); - } - else if (cls == double.class) { + } else if (cls == double.class) { double[] buf = (double[])value; write(offset, buf, 0, buf.length); - } - else if (Pointer.class.isAssignableFrom(cls)) { + } else if (Pointer.class.isAssignableFrom(cls)) { Pointer[] buf = (Pointer[])value; write(offset, buf, 0, buf.length); - } - else if (Structure.class.isAssignableFrom(cls)) { + } else if (Structure.class.isAssignableFrom(cls)) { Structure[] sbuf = (Structure[])value; if (Structure.ByReference.class.isAssignableFrom(cls)) { Pointer[] buf = new Pointer[sbuf.length]; for (int i=0;i < sbuf.length;i++) { if (sbuf[i] == null) { buf[i] = null; - } - else { + } else { buf[i] = sbuf[i].getPointer(); sbuf[i].write(); } } write(offset, buf, 0, buf.length); - } - else { + } else { Structure first = sbuf[0]; if (first == null) { first = Structure.newInstance(cls, share(offset)); sbuf[0] = first; - } - else { + } else { first.useMemory(this, (int)offset, true); } first.write(); @@ -1039,31 +996,28 @@ else if (Structure.class.isAssignableFrom(cls)) { for (int i=1;i < sbuf.length;i++) { if (sbuf[i] == null) { sbuf[i] = tmp[i]; - } - else { + } else { sbuf[i].useMemory(this, (int)(offset + i * sbuf[i].size()), true); } sbuf[i].write(); } } - } - else if (NativeMapped.class.isAssignableFrom(cls)) { + } else if (NativeMapped.class.isAssignableFrom(cls)) { NativeMapped[] buf = (NativeMapped[])value; NativeMappedConverter tc = NativeMappedConverter.getInstance(cls); - Class nativeType = tc.nativeType(); + Class nativeType = tc.nativeType(); int size = Native.getNativeSize(value.getClass(), value) / buf.length; for (int i=0;i < buf.length;i++) { Object element = tc.toNative(buf[i], new ToNativeContext()); setValue(offset + i*size, element, nativeType); } - } - else { + } else { throw new IllegalArgumentException("Writing array of " + cls + " to memory not supported"); } } - /** Write value to the requested bank of memory. + /** Write value to the requested bank of memory. * @param offset byte offset from pointer to start * @param length number of bytes to write * @param value value to be written @@ -1071,7 +1025,7 @@ else if (NativeMapped.class.isAssignableFrom(cls)) { public void setMemory(long offset, long length, byte value) { Native.setMemory(peer + offset, length, value); } - + /** * Set value at location being pointed to. This is equivalent * to the expression @@ -1097,7 +1051,7 @@ public void setByte(long offset, byte value) { public void setShort(long offset, short value) { Native.setShort(peer + offset, value); } - + /** * Set value at location being pointed to. This is equivalent * to the expression @@ -1110,7 +1064,7 @@ public void setShort(long offset, short value) { public void setChar(long offset, char value) { Native.setChar(peer + offset, value); } - + /** * Set value at location being pointed to. This is equivalent * to the expression @@ -1136,7 +1090,7 @@ public void setInt(long offset, int value) { public void setLong(long offset, long value) { Native.setLong(peer + offset, value); } - + /** * Set value at location being pointed to. This is equivalent * to the expression @@ -1166,7 +1120,7 @@ public void setNativeLong(long offset, NativeLong value) { public void setFloat(long offset, float value) { Native.setFloat(peer + offset, value); } - + /** * Set value at location being pointed to. This is equivalent * to the expression @@ -1182,12 +1136,12 @@ public void setDouble(long offset, double value) { /** * Set value at location being pointed to. This is equivalent - * to the expression + * to the expression * *((void **)((char *)Pointer + offset)) = value. * - * @param offset byte offset from pointer at which value + * @param offset byte offset from pointer at which value * must be set - * @param value Pointer holding the actual pointer value to + * @param value Pointer holding the actual pointer value to * set, which may be null to indicate a NULL * pointer. */ @@ -1196,18 +1150,19 @@ public void setPointer(long offset, Pointer value) { } /** - * Copy string value to the location being pointed to. + * Copy string value to the location being pointed to. * * @param offset byte offset from pointer at which characters in * value must be set * @param value java.lang.String value to set - * @param wide whether to write the native string as an array of - * wchar_t. If false, writes as a NUL-terminated array of + * @param wide whether to write the native string as an array of + * wchar_t. If false, writes as a NUL-terminated array of * char using the encoding indicated by {@link - * Native#getDefaultStringEncoding()}. - * + * Native#getDefaultStringEncoding()}. + * * @deprecated use {@link #setWideString(long,String)} instead. */ + @Deprecated public void setString(long offset, String value, boolean wide) { if (wide) { setWideString(offset, value); @@ -1216,10 +1171,10 @@ public void setString(long offset, String value, boolean wide) { setString(offset, value); } } - + /** * Copy string value to the location being pointed to as a - * wide string (wchar_t*). + * wide string (wchar_t*). * * @param offset byte offset from pointer at which characters in * value must be set @@ -1231,7 +1186,7 @@ public void setWideString(long offset, String value) { /** * Copy string value to the location being pointed to as a - * wide string (wchar_t*). + * wide string (wchar_t*). * * @param offset byte offset from pointer at which characters in * value must be set @@ -1244,7 +1199,7 @@ public void setString(long offset, WString value) { /** * Copy bytes out of string value to the location being * pointed to, using the encoding indicated by {@link - * Native#getDefaultStringEncoding()}. + * Native#getDefaultStringEncoding()}. * * @param offset byte offset from pointer at which characters in * value must be set @@ -1256,7 +1211,7 @@ public void setString(long offset, String value) { /** * Copy string value to the location being pointed to, using - * the requested encoding. + * the requested encoding. * * @param offset byte offset from pointer at which characters in * value must be set @@ -1268,7 +1223,7 @@ public void setString(long offset, String value, String encoding) { write(offset, data, 0, data.length); setByte(offset + data.length, (byte)0); } - + /** Dump memory for debugging purposes. */ public String dump(long offset, int size) { String LS = System.getProperty("line.separator"); @@ -1289,10 +1244,11 @@ public String dump(long offset, int size) { return contents; } + @Override public String toString() { return "native@0x" + Long.toHexString(peer); } - + /** Read the native peer value. Use with caution. */ public static long nativeValue(Pointer p) { return p == null ? 0 : p.peer; @@ -1307,129 +1263,171 @@ public static void nativeValue(Pointer p, long value) { private static class Opaque extends Pointer { private Opaque(long peer) { super(peer); } private final String MSG = "This pointer is opaque: " + this; + @Override public Pointer share(long offset, long size) { throw new UnsupportedOperationException(MSG); } + @Override public void clear(long size) { throw new UnsupportedOperationException(MSG); } + @Override public long indexOf(long offset, byte value) { throw new UnsupportedOperationException(MSG); } - public void read(long bOff, byte[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void read(long bOff, byte[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void read(long bOff, char[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void read(long bOff, char[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void read(long bOff, short[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void read(long bOff, short[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void read(long bOff, int[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void read(long bOff, int[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void read(long bOff, long[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void read(long bOff, long[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void read(long bOff, float[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void read(long bOff, float[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void read(long bOff, double[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void read(long bOff, double[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void read(long bOff, Pointer[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void read(long bOff, Pointer[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void write(long bOff, byte[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void write(long bOff, byte[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void write(long bOff, char[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void write(long bOff, char[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void write(long bOff, short[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void write(long bOff, short[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void write(long bOff, int[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void write(long bOff, int[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void write(long bOff, long[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void write(long bOff, long[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void write(long bOff, float[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void write(long bOff, float[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void write(long bOff, double[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void write(long bOff, double[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } - public void write(long bOff, Pointer[] buf, int index, int length) { - throw new UnsupportedOperationException(MSG); + @Override + public void write(long bOff, Pointer[] buf, int index, int length) { + throw new UnsupportedOperationException(MSG); } + @Override public ByteBuffer getByteBuffer(long offset, long length) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public byte getByte(long bOff) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public char getChar(long bOff) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public short getShort(long bOff) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public int getInt(long bOff) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public long getLong(long bOff) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public float getFloat(long bOff) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public double getDouble(long bOff) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public Pointer getPointer(long bOff) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public String getString(long bOff, String encoding) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public String getWideString(long bOff) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setByte(long bOff, byte value) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setChar(long bOff, char value) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setShort(long bOff, short value) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setInt(long bOff, int value) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setLong(long bOff, long value) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setFloat(long bOff, float value) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setDouble(long bOff, double value) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setPointer(long offset, Pointer value) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setString(long offset, String value, String encoding) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setWideString(long offset, String value) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public void setMemory(long offset, long size, byte value) { - throw new UnsupportedOperationException(MSG); + throw new UnsupportedOperationException(MSG); } + @Override public String toString() { return "const@0x" + Long.toHexString(peer); } diff --git a/src/com/sun/jna/PointerType.java b/src/com/sun/jna/PointerType.java index 0448be7417..566f97a500 100644 --- a/src/com/sun/jna/PointerType.java +++ b/src/com/sun/jna/PointerType.java @@ -1,44 +1,45 @@ /* Copyright (c) 2007 Timothy Wall, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; /** Type representing a type-safe native pointer. * Derived classes may override the {@link NativeMapped#fromNative} method, * which should instantiate a new object (or look up an existing one) - * of the appropriate type. + * of the appropriate type. */ public abstract class PointerType implements NativeMapped { private Pointer pointer; - + /** The default constructor wraps a NULL pointer. */ protected PointerType() { this.pointer = Pointer.NULL; } - + /** This constructor is typically used by {@link #fromNative} if generating - * a new object instance. + * a new object instance. */ protected PointerType(Pointer p) { this.pointer = p; } - /** All PointerType classes represent a native {@link Pointer}. - */ - public Class nativeType() { + /* All PointerType classes represent a native {@link Pointer}. */ + @Override + public Class nativeType() { return Pointer.class; } /** Convert this object to its native type (a {@link Pointer}). */ + @Override public Object toNative() { return getPointer(); } @@ -49,24 +50,25 @@ public Object toNative() { public Pointer getPointer() { return pointer; } - + public void setPointer(Pointer p) { this.pointer = p; } - + /** The default implementation simply creates a new instance of the class * and assigns its pointer field. Override if you need different behavior, * such as ensuring a single {@link PointerType} instance for each unique * {@link Pointer} value, or instantiating a different {@link PointerType} * subclass. */ + @Override public Object fromNative(Object nativeValue, FromNativeContext context) { // Always pass along null pointer values if (nativeValue == null) { return null; } try { - PointerType pt = (PointerType)getClass().newInstance(); + PointerType pt = getClass().newInstance(); pt.pointer = (Pointer)nativeValue; return pt; } @@ -81,13 +83,15 @@ public Object fromNative(Object nativeValue, FromNativeContext context) { /** The hash code for a PointerType is the same as that for * its pointer. */ + @Override public int hashCode() { return pointer != null ? pointer.hashCode() : 0; } - + /** Instances of PointerType with identical pointers compare * equal by default. */ + @Override public boolean equals(Object o) { if (o == this) return true; if (o instanceof PointerType) { @@ -99,6 +103,7 @@ public boolean equals(Object o) { return false; } + @Override public String toString() { return pointer == null ? "NULL" : pointer.toString() + " (" + super.toString() + ")"; } diff --git a/src/com/sun/jna/StringArray.java b/src/com/sun/jna/StringArray.java index f51a327506..d66773dac4 100644 --- a/src/com/sun/jna/StringArray.java +++ b/src/com/sun/jna/StringArray.java @@ -1,5 +1,5 @@ /* Copyright (c) 2007-2008 Timothy Wall, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -8,7 +8,7 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -16,14 +16,14 @@ import java.util.Arrays; import java.util.List; -/** Handle native array of char* or wchar_t* type - * by managing allocation/disposal of native strings within an array of +/** Handle native array of char* or wchar_t* type + * by managing allocation/disposal of native strings within an array of * pointers. An extra NULL pointer is always added to the end of the native - * pointer array for convenience. + * pointer array for convenience. */ public class StringArray extends Memory implements Function.PostCallRead { private String encoding; - private List natives = new ArrayList(); + private List natives = new ArrayList(); private Object[] original; /** Create a native array of strings. */ public StringArray(String[] strings) { @@ -41,7 +41,7 @@ public StringArray(String[] strings, String encoding) { public StringArray(WString[] strings) { this(strings, NativeString.WIDE_STRING); } - private StringArray(Object[] strings, String encoding) { + private StringArray(Object[] strings, String encoding) { super((strings.length + 1) * Pointer.SIZE); this.original = strings; this.encoding = encoding; @@ -57,9 +57,10 @@ private StringArray(Object[] strings, String encoding) { setPointer(Pointer.SIZE * strings.length, null); } /** Read back from native memory. */ + @Override public void read() { boolean returnWide = original instanceof WString[]; - boolean wide = encoding == NativeString.WIDE_STRING; + boolean wide = NativeString.WIDE_STRING.equals(encoding); for (int si=0;si < original.length;si++) { Pointer p = getPointer(si * Pointer.SIZE); Object s = null; @@ -71,8 +72,9 @@ public void read() { } } + @Override public String toString() { - boolean wide = encoding == NativeString.WIDE_STRING; + boolean wide = NativeString.WIDE_STRING.equals(encoding); String s = wide ? "const wchar_t*[]" : "const char*[]"; s += Arrays.asList(original); return s; diff --git a/src/com/sun/jna/ToNativeConverter.java b/src/com/sun/jna/ToNativeConverter.java index 473883bb91..1aec645fa8 100644 --- a/src/com/sun/jna/ToNativeConverter.java +++ b/src/com/sun/jna/ToNativeConverter.java @@ -38,5 +38,5 @@ public interface ToNativeConverter { */ Object toNative(Object value, ToNativeContext context); /** Indicate the type expected from {@link #toNative}. */ - Class nativeType(); + Class nativeType(); } diff --git a/src/com/sun/jna/TypeMapper.java b/src/com/sun/jna/TypeMapper.java index b370a66e5a..0674c7f08b 100644 --- a/src/com/sun/jna/TypeMapper.java +++ b/src/com/sun/jna/TypeMapper.java @@ -1,28 +1,28 @@ /* Copyright (c) 2007 Timothy Wall, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; /** Provides converters for conversion to and from native types. */ public interface TypeMapper { - /** Return the {@link FromNativeConverter} appropriate for the given Java class. + /** Return the {@link FromNativeConverter} appropriate for the given Java class. * @param javaType Java class representation of the native type. * @return Converter from the native-compatible type. */ - FromNativeConverter getFromNativeConverter(Class javaType); + FromNativeConverter getFromNativeConverter(Class javaType); - /** Return the {@link ToNativeConverter} appropriate for the given Java class. + /** Return the {@link ToNativeConverter} appropriate for the given Java class. * @param javaType Java class representation of the native type. * @return Converter to the native-compatible type. */ - ToNativeConverter getToNativeConverter(Class javaType); + ToNativeConverter getToNativeConverter(Class javaType); } diff --git a/src/com/sun/jna/WString.java b/src/com/sun/jna/WString.java index 829bf15846..318ab19f8c 100644 --- a/src/com/sun/jna/WString.java +++ b/src/com/sun/jna/WString.java @@ -8,39 +8,48 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; import java.nio.CharBuffer; /** Simple wrapper class to identify a wide string argument or return type. - * @author twall@users.sf.net + * @author twall@users.sf.net */ public final class WString implements CharSequence, Comparable { private String string; public WString(String s){ - if (s == null) throw new NullPointerException("String initializer must be non-null"); + if (s == null) { + throw new NullPointerException("String initializer must be non-null"); + } this.string = s; } + @Override public String toString() { return string; } + @Override public boolean equals(Object o) { - return o instanceof WString && toString().equals(o.toString()); + return (o instanceof WString) && toString().equals(o.toString()); } + @Override public int hashCode() { return toString().hashCode(); } + @Override public int compareTo(Object o) { return toString().compareTo(o.toString()); } + @Override public int length() { return toString().length(); } + @Override public char charAt(int index) { return toString().charAt(index); } + @Override public CharSequence subSequence(int start, int end) { return CharBuffer.wrap(toString()).subSequence(start, end); } diff --git a/src/com/sun/jna/WeakIdentityHashMap.java b/src/com/sun/jna/WeakIdentityHashMap.java index d4f5905e46..c4d6533b1d 100644 --- a/src/com/sun/jna/WeakIdentityHashMap.java +++ b/src/com/sun/jna/WeakIdentityHashMap.java @@ -20,13 +20,13 @@ * Modified to remove Genercs for JNA. */ +import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -35,56 +35,63 @@ * Implements a combination of WeakHashMap and IdentityHashMap. * Useful for caches that need to key off of a == comparison * instead of a .equals. - * + * * * This class is not a general-purpose Map implementation! While * this class implements the Map interface, it intentionally violates * Map's general contract, which mandates the use of the equals method * when comparing objects. This class is designed for use only in the * rare cases wherein reference-equality semantics are required. - * + * * Note that this implementation is not synchronized. * */ -public class WeakIdentityHashMap implements Map { - private final ReferenceQueue queue = new ReferenceQueue(); - private Map backingStore = new HashMap(); - +public class WeakIdentityHashMap implements Map { + private final ReferenceQueue queue = new ReferenceQueue(); + private Map, V> backingStore = new HashMap, V>(); public WeakIdentityHashMap() { + super(); } + @Override public void clear() { backingStore.clear(); reap(); } + @Override public boolean containsKey(Object key) { reap(); - return backingStore.containsKey(new IdentityWeakReference(key)); + return backingStore.containsKey(new IdentityWeakReference(key, queue)); } + @Override public boolean containsValue(Object value) { reap(); return backingStore.containsValue(value); } - public Set entrySet() { + @Override + public Set> entrySet() { reap(); - Set ret = new HashSet(); - for (Iterator i=backingStore.entrySet().iterator();i.hasNext();) { - Map.Entry ref = (Map.Entry)i.next(); - final Object key = ((IdentityWeakReference)ref.getKey()).get(); - final Object value = ref.getValue(); - Map.Entry entry = new Map.Entry() { - public Object getKey() { + + Set> ret = new LinkedHashSet>(); + for (Map.Entry, ? extends V> ref : backingStore.entrySet()) { + final K key = ref.getKey().get(); + final V value = ref.getValue(); + Map.Entry entry = new Map.Entry() { + @Override + public K getKey() { return key; } - public Object getValue() { + @Override + public V getValue() { return value; } - public Object setValue(Object value) { + @Override + public V setValue(V value) { throw new UnsupportedOperationException(); } }; @@ -92,81 +99,103 @@ public Object setValue(Object value) { } return Collections.unmodifiableSet(ret); } - public Set keySet() { + + @Override + public Set keySet() { reap(); - Set ret = new HashSet(); - for (Iterator i=backingStore.keySet().iterator();i.hasNext();) { - IdentityWeakReference ref = (IdentityWeakReference)i.next(); + + Set ret = new LinkedHashSet(); + for (Reference ref : backingStore.keySet()) { ret.add(ref.get()); } return Collections.unmodifiableSet(ret); } + @Override public boolean equals(Object o) { + if (o == null) { + return false; + } + if (o == this) { + return true; + } + + if (!(o instanceof WeakIdentityHashMap)) { + return false; + } + return backingStore.equals(((WeakIdentityHashMap)o).backingStore); } - public Object get(Object key) { + @Override + public V get(Object key) { reap(); - return backingStore.get(new IdentityWeakReference(key)); + return backingStore.get(new IdentityWeakReference(key, queue)); } - public Object put(Object key, Object value) { + + @Override + public V put(K key, V value) { reap(); - return backingStore.put(new IdentityWeakReference(key), value); + return backingStore.put(new IdentityWeakReference(key, queue), value); } + @Override public int hashCode() { reap(); return backingStore.hashCode(); } + @Override public boolean isEmpty() { reap(); return backingStore.isEmpty(); } - public void putAll(Map t) { + @Override + public void putAll(Map m) { throw new UnsupportedOperationException(); } - public Object remove(Object key) { + @Override + public V remove(Object key) { reap(); - return backingStore.remove(new IdentityWeakReference(key)); + return backingStore.remove(new IdentityWeakReference(key, queue)); } + @Override public int size() { reap(); return backingStore.size(); } - public Collection values() { + @Override + public Collection values() { reap(); return backingStore.values(); } private synchronized void reap() { - Object zombie = queue.poll(); - - while (zombie != null) { - IdentityWeakReference victim = (IdentityWeakReference)zombie; - backingStore.remove(victim); - zombie = queue.poll(); + for (Reference zombie = queue.poll(); zombie != null; zombie = queue.poll()) { + backingStore.remove(zombie); } } - class IdentityWeakReference extends WeakReference { - int hash; - + static class IdentityWeakReference extends WeakReference { + private final int hash; + //@SuppressWarnings("unchecked") - IdentityWeakReference(Object obj) { - super(obj, queue); + IdentityWeakReference(T obj, ReferenceQueue q) { + super(obj, q); hash = System.identityHashCode(obj); } + @Override public int hashCode() { return hash; } + @Override public boolean equals(Object o) { if (this == o) { return true; } - IdentityWeakReference ref = (IdentityWeakReference)o; + + IdentityWeakReference ref = (IdentityWeakReference)o; if (this.get() == ref.get()) { return true; } @@ -175,7 +204,6 @@ public boolean equals(Object o) { } } - - - - \ No newline at end of file + + + diff --git a/src/com/sun/jna/win32/StdCallFunctionMapper.java b/src/com/sun/jna/win32/StdCallFunctionMapper.java index 1a78c578fd..33badb55ab 100644 --- a/src/com/sun/jna/win32/StdCallFunctionMapper.java +++ b/src/com/sun/jna/win32/StdCallFunctionMapper.java @@ -1,19 +1,20 @@ /* Copyright (c) 2007 Timothy Wall, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna.win32; import java.lang.reflect.Method; +import com.sun.jna.Function; import com.sun.jna.FunctionMapper; import com.sun.jna.Native; import com.sun.jna.NativeLibrary; @@ -24,7 +25,7 @@ /** Provides mapping from simple method names to w32 stdcall-decorated names * where the name suffix is "@" followed by the number of bytes popped by * the called function.

    - * NOTE: if you use custom type mapping for primitive types, you may need to + * NOTE: if you use custom type mapping for primitive types, you may need to * override {@link #getArgumentNativeStackSize(Class)}. */ public class StdCallFunctionMapper implements FunctionMapper { @@ -32,7 +33,7 @@ public class StdCallFunctionMapper implements FunctionMapper { * @param cls Java class of a parameter * @return number of native bytes used for this class on the stack */ - protected int getArgumentNativeStackSize(Class cls) { + protected int getArgumentNativeStackSize(Class cls) { if (NativeMapped.class.isAssignableFrom(cls)) { cls = NativeMappedConverter.getInstance(cls).nativeType(); } @@ -41,36 +42,42 @@ protected int getArgumentNativeStackSize(Class cls) { } try { return Native.getNativeSize(cls); - } - catch(IllegalArgumentException e) { + } catch(IllegalArgumentException e) { throw new IllegalArgumentException("Unknown native stack allocation size for " + cls); } } - /** Convert the given Java method into a decorated stdcall name, - * if possible. + + /** + * Convert the given Java method into a decorated {@code stdcall} name, if possible. + * + * @param library The {@link NativeLibrary} instance + * @param method The invoked {@link Method} + * @return The decorated name */ + @Override public String getFunctionName(NativeLibrary library, Method method) { String name = method.getName(); int pop = 0; - Class[] argTypes = method.getParameterTypes(); - for (int i=0;i < argTypes.length;i++) { - pop += getArgumentNativeStackSize(argTypes[i]); + Class[] argTypes = method.getParameterTypes(); + for (Class cls : argTypes) { + pop += getArgumentNativeStackSize(cls); } + String decorated = name + "@" + pop; int conv = StdCallLibrary.STDCALL_CONVENTION; try { - name = library.getFunction(decorated, conv).getName(); - - } - catch(UnsatisfiedLinkError e) { + Function func = library.getFunction(decorated, conv); + name = func.getName(); + } catch(UnsatisfiedLinkError e) { // try with an explicit underscore try { - name = library.getFunction("_" + decorated, conv).getName(); - } - catch(UnsatisfiedLinkError e2) { + Function func = library.getFunction("_" + decorated, conv); + name = func.getName(); + } catch(UnsatisfiedLinkError e2) { // not found; let caller try undecorated version } } + return name; } } \ No newline at end of file diff --git a/src/com/sun/jna/win32/W32APIOptions.java b/src/com/sun/jna/win32/W32APIOptions.java index ac1ffbbf3f..62d01a54e3 100644 --- a/src/com/sun/jna/win32/W32APIOptions.java +++ b/src/com/sun/jna/win32/W32APIOptions.java @@ -6,18 +6,24 @@ public interface W32APIOptions extends StdCallLibrary { /** Standard options to use the unicode version of a w32 API. */ - Map UNICODE_OPTIONS = Collections.unmodifiableMap(new HashMap() { + Map UNICODE_OPTIONS = Collections.unmodifiableMap(new HashMap() { + private static final long serialVersionUID = 1L; // we're not serializing it + { put(OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE); put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE); } }); + /** Standard options to use the ASCII/MBCS version of a w32 API. */ - Map ASCII_OPTIONS = Collections.unmodifiableMap(new HashMap() { + Map ASCII_OPTIONS = Collections.unmodifiableMap(new HashMap() { + private static final long serialVersionUID = 1L; // we're not serializing it { put(OPTION_TYPE_MAPPER, W32APITypeMapper.ASCII); put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.ASCII); } }); - Map DEFAULT_OPTIONS = Boolean.getBoolean("w32.ascii") ? ASCII_OPTIONS : UNICODE_OPTIONS; + + /** Default options to use - depends on the value of {@code w32.ascii} system property */ + Map DEFAULT_OPTIONS = Boolean.getBoolean("w32.ascii") ? ASCII_OPTIONS : UNICODE_OPTIONS; } diff --git a/src/com/sun/jna/win32/W32APITypeMapper.java b/src/com/sun/jna/win32/W32APITypeMapper.java index 65bf9c944c..c6e26a993f 100644 --- a/src/com/sun/jna/win32/W32APITypeMapper.java +++ b/src/com/sun/jna/win32/W32APITypeMapper.java @@ -1,14 +1,14 @@ /* Copyright (c) 2007 Timothy Wall, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna.win32; @@ -20,7 +20,7 @@ import com.sun.jna.TypeMapper; import com.sun.jna.WString; -/** Provide standard conversion for W32 API types. This comprises the +/** Provide standard conversion for W32 API types. This comprises the * following native types: *

      *
    • Unicode or ASCII/MBCS strings and arrays of string, as appropriate @@ -29,13 +29,14 @@ * @author twall */ public class W32APITypeMapper extends DefaultTypeMapper { - + public static final TypeMapper UNICODE = new W32APITypeMapper(true); public static final TypeMapper ASCII = new W32APITypeMapper(false); - + protected W32APITypeMapper(boolean unicode) { if (unicode) { TypeConverter stringConverter = new TypeConverter() { + @Override public Object toNative(Object value, ToNativeContext context) { if (value == null) return null; @@ -44,12 +45,14 @@ public Object toNative(Object value, ToNativeContext context) { } return new WString(value.toString()); } + @Override public Object fromNative(Object value, FromNativeContext context) { if (value == null) return null; return value.toString(); } - public Class nativeType() { + @Override + public Class nativeType() { return WString.class; } }; @@ -57,13 +60,16 @@ public Class nativeType() { addToNativeConverter(String[].class, stringConverter); } TypeConverter booleanConverter = new TypeConverter() { + @Override public Object toNative(Object value, ToNativeContext context) { return new Integer(Boolean.TRUE.equals(value) ? 1 : 0); } + @Override public Object fromNative(Object value, FromNativeContext context) { return ((Integer)value).intValue() != 0 ? Boolean.TRUE : Boolean.FALSE; } - public Class nativeType() { + @Override + public Class nativeType() { // BOOL is 32-bit int return Integer.class; } diff --git a/test/com/sun/jna/AnnotatedLibraryTest.java b/test/com/sun/jna/AnnotatedLibraryTest.java index f3f0ff3615..6cf7ecc9ad 100644 --- a/test/com/sun/jna/AnnotatedLibraryTest.java +++ b/test/com/sun/jna/AnnotatedLibraryTest.java @@ -1,6 +1,5 @@ package com.sun.jna; -import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -8,9 +7,7 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; -import java.util.HashMap; -import java.util.Map; - +import java.util.Collections; import junit.framework.TestCase; public class AnnotatedLibraryTest extends TestCase { @@ -22,8 +19,9 @@ public class AnnotatedLibraryTest extends TestCase { public interface AnnotatedLibrary extends Library { @TestAnnotation boolean isAnnotated(); } - + public class TestInvocationHandler implements InvocationHandler { + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return Boolean.valueOf(method.getAnnotations().length == 1); } @@ -38,7 +36,7 @@ public void testProxyMethodHasAnnotations() throws Exception { new TestInvocationHandler()); assertTrue("Proxy method not annotated", a.isAnnotated()); } - + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public static @interface FooBoolean {} @@ -48,31 +46,33 @@ public static interface AnnotationTestLibrary extends Library { } public void testAnnotationsOnMethods() throws Exception { final int MAGIC = 0xABEDCF23; - Map options = new HashMap(); final boolean[] hasAnnotation = {false, false}; - DefaultTypeMapper mapper = new DefaultTypeMapper(); + DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addTypeConverter(Boolean.class, new TypeConverter() { + @Override public Object toNative(Object value, ToNativeContext ctx) { MethodParameterContext mcontext = (MethodParameterContext)ctx; hasAnnotation[0] = mcontext.getMethod().getAnnotation(FooBoolean.class) != null; return new Integer(Boolean.TRUE.equals(value) ? MAGIC : 0); } + @Override public Object fromNative(Object value, FromNativeContext context) { - MethodResultContext mcontext = (MethodResultContext)context; + MethodResultContext mcontext = (MethodResultContext)context; hasAnnotation[1] = mcontext.getMethod().getAnnotation(FooBoolean.class) != null; return Boolean.valueOf(((Integer) value).intValue() == MAGIC); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - - options.put(Library.OPTION_TYPE_MAPPER, mapper); - AnnotationTestLibrary lib = Native.loadLibrary("testlib", AnnotationTestLibrary.class, options); + + AnnotationTestLibrary lib = + Native.loadLibrary("testlib", AnnotationTestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); assertEquals("Failed to convert integer return to boolean TRUE", true, lib.returnInt32Argument(true)); - assertTrue("Failed to get annotation from ParameterContext", hasAnnotation[0]); - assertTrue("Failed to get annotation from ResultContext", hasAnnotation[1]); + assertTrue("Failed to get annotation from ParameterContext", hasAnnotation[0]); + assertTrue("Failed to get annotation from ResultContext", hasAnnotation[1]); } public static void main(String[] args) { diff --git a/test/com/sun/jna/CallbacksTest.java b/test/com/sun/jna/CallbacksTest.java index b511e50f99..3f6baeae98 100644 --- a/test/com/sun/jna/CallbacksTest.java +++ b/test/com/sun/jna/CallbacksTest.java @@ -14,8 +14,10 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -23,14 +25,14 @@ import java.util.Set; import java.util.WeakHashMap; -import junit.framework.TestCase; - import com.sun.jna.Callback.UncaughtExceptionHandler; import com.sun.jna.CallbacksTest.TestLibrary.CbCallback; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; import com.sun.jna.win32.W32APIOptions; +import junit.framework.TestCase; + /** Exercise callback-related functionality. * * @author twall@users.sf.net @@ -64,6 +66,7 @@ protected void waitFor(Thread thread) { } public static class SmallTestStructure extends Structure { + public static final List FIELDS = createFieldsOrder("value"); public double value; public static int allocations = 0; @Override @@ -74,8 +77,8 @@ protected void allocateMemory(int size) { public SmallTestStructure() { } public SmallTestStructure(Pointer p) { super(p); read(); } @Override - protected List getFieldOrder() { - return Arrays.asList(new String[] { "value" }); + protected List getFieldOrder() { + return FIELDS; } } public static class TestStructure extends Structure { @@ -83,14 +86,16 @@ public static class ByValue extends TestStructure implements Structure.ByValue { public static interface TestCallback extends Callback { TestStructure.ByValue callback(TestStructure.ByValue s); } + + public static final List FIELDS = createFieldsOrder("c", "s", "i", "j", "inner"); public byte c; public short s; public int i; public long j; public SmallTestStructure inner; @Override - protected List getFieldOrder() { - return Arrays.asList(new String[] { "c", "s", "i", "j", "inner" }); + protected List getFieldOrder() { + return FIELDS; } } public static interface TestLibrary extends Library { @@ -233,7 +238,7 @@ public Object fromNative(Object nativeValue, FromNativeContext context) { return new Custom(((Integer)nativeValue).intValue()); } @Override - public Class nativeType() { + public Class nativeType() { return Integer.class; } @Override @@ -252,8 +257,8 @@ public void testLookupNullCallback() { try { CallbackReference.getCallback(TestLibrary.VoidCallback.class, new Pointer(0)); fail("Null pointer lookup should fail"); - } - catch(NullPointerException e) { + } catch(NullPointerException e) { + // expected } } @@ -305,7 +310,7 @@ public void testMultipleMethodsCallback() { public void testNativeFunctionPointerStringValue() { Callback cb = CallbackReference.getCallback(TestLibrary.VoidCallback.class, new Pointer(getName().hashCode())); - Class cls = CallbackReference.findCallbackClass(cb.getClass()); + Class cls = CallbackReference.findCallbackClass(cb.getClass()); assertTrue("toString should include Java Callback type: " + cb + " (" + cls + ")", cb.toString().indexOf(cls.getName()) != -1); } @@ -318,7 +323,7 @@ public void testLookupSameCallback() { } // Allow direct tests to override - protected Map callbackCache() { + protected Map callbackCache() { return CallbackReference.callbackMap; } @@ -334,19 +339,17 @@ public void callback() { lib.callVoidCallback(cb); assertTrue("Callback not called", called[0]); - Map refs = new WeakHashMap(callbackCache()); + Map refs = new WeakHashMap(callbackCache()); assertTrue("Callback not cached", refs.containsKey(cb)); - CallbackReference ref = (CallbackReference)refs.get(cb); + CallbackReference ref = refs.get(cb); refs = callbackCache(); Pointer cbstruct = ref.cbstruct; cb = null; System.gc(); for (int i = 0; i < 100 && (ref.get() != null || refs.containsValue(ref)); ++i) { - try { - Thread.sleep(10); // Give the GC a chance to run - System.gc(); - } finally {} + Thread.sleep(10); // Give the GC a chance to run + System.gc(); } assertNull("Callback not GC'd", ref.get()); assertFalse("Callback still in map", refs.containsValue(ref)); @@ -668,13 +671,13 @@ public String callback(String arg, String arg2) { }; // A little internal groping - Map m = CallbackReference.allocations; + Map m = CallbackReference.allocations; m.clear(); String arg = getName() + "1" + UNICODE; String arg2 = getName() + "2" + UNICODE; String value = lib.callStringCallback(cb, arg, arg2); - WeakReference ref = new WeakReference(value); + WeakReference ref = new WeakReference(value); arg = null; value = null; @@ -905,11 +908,11 @@ public Object callback(Object[] args) { throw ERROR; } @Override - public Class[] getParameterTypes() { + public Class[] getParameterTypes() { return new Class[] { CbCallback.class }; } @Override - public Class getReturnType() { + public Class getReturnType() { return CbCallback.class; } }; @@ -1018,7 +1021,7 @@ public Object fromNative(Object value, FromNativeContext context) { return new Double(((Integer)value).intValue()); } @Override - public Class nativeType() { + public Class nativeType() { return Integer.class; } @Override @@ -1035,7 +1038,7 @@ public Object fromNative(Object value, FromNativeContext context) { return new Float(((Long)value).intValue()); } @Override - public Class nativeType() { + public Class nativeType() { return Long.class; } @Override @@ -1058,7 +1061,7 @@ public Object fromNative(Object value, FromNativeContext context) { return value.toString(); } @Override - public Class nativeType() { + public Class nativeType() { return WString.class; } @Override @@ -1073,7 +1076,9 @@ public Object toNative(Object value, ToNativeContext ctx) { public static interface CallbackTestLibrary extends Library { final CallbackTypeMapper _MAPPER = new CallbackTypeMapper(); - final Map _OPTIONS = new HashMap() { + final Map _OPTIONS = new HashMap() { + private static final long serialVersionUID = 1L; // we're not serializing it + { put(Library.OPTION_TYPE_MAPPER, _MAPPER); } @@ -1103,7 +1108,7 @@ protected CallbackTestLibrary loadCallbackTestLibrary() { */ public void testCallbackUsesTypeMapper() throws Exception { CallbackTestLibrary lib = loadCallbackTestLibrary(); - lib._MAPPER.clear(); + CallbackTestLibrary._MAPPER.clear(); final double[] ARGS = new double[2]; @@ -1115,9 +1120,9 @@ public double callback(double arg, double arg2) { return arg + arg2; } }; - assertEquals("Wrong type mapper for callback class", lib._MAPPER, + assertEquals("Wrong type mapper for callback class", CallbackTestLibrary._MAPPER, Native.getTypeMapper(CallbackTestLibrary.DoubleCallback.class)); - assertEquals("Wrong type mapper for callback object", lib._MAPPER, + assertEquals("Wrong type mapper for callback object", CallbackTestLibrary._MAPPER, Native.getTypeMapper(cb.getClass())); double result = lib.callInt32Callback(cb, -1, -2); @@ -1126,14 +1131,14 @@ public double callback(double arg, double arg2) { assertEquals("Incorrect result of callback invocation", -3, result, 0); // Once per argument, then again for return value (convert native int->Java double) - assertEquals("Type mapper not called for arguments", 3, lib._MAPPER.fromNativeConversions); + assertEquals("Type mapper not called for arguments", 3, CallbackTestLibrary._MAPPER.fromNativeConversions); // Once per argument, then again for return value (convert Java double->native int) - assertEquals("Type mapper not called for result", 3, lib._MAPPER.toNativeConversions); + assertEquals("Type mapper not called for result", 3, CallbackTestLibrary._MAPPER.toNativeConversions); } public void testTypeMapperWithWideStrings() throws Exception { CallbackTestLibrary lib = loadCallbackTestLibrary(); - lib._MAPPER.clear(); + CallbackTestLibrary._MAPPER.clear(); final String[] ARGS = new String[2]; @@ -1145,9 +1150,9 @@ public String callback(String arg, String arg2) { return arg + arg2; } }; - assertEquals("Wrong type mapper for callback class", lib._MAPPER, + assertEquals("Wrong type mapper for callback class", CallbackTestLibrary._MAPPER, Native.getTypeMapper(CallbackTestLibrary.WStringCallback.class)); - assertEquals("Wrong type mapper for callback object", lib._MAPPER, + assertEquals("Wrong type mapper for callback object", CallbackTestLibrary._MAPPER, Native.getTypeMapper(cb.getClass())); final String[] EXPECTED = { "magic" + UNICODE, getName() + UNICODE }; @@ -1157,9 +1162,9 @@ public String callback(String arg, String arg2) { assertEquals("Incorrect result of callback invocation", EXPECTED[0] + EXPECTED[1], result); // Once per argument, then again for return value (convert const wchar_t*->Java String) - assertEquals("Type mapper not called for arguments", 3, lib._MAPPER.fromNativeConversions); + assertEquals("Type mapper not called for arguments", 3, CallbackTestLibrary._MAPPER.fromNativeConversions); // Once per argument, then again for return value (convert Java String->const wchar_t*) - assertEquals("Type mapper not called for result", 3, lib._MAPPER.toNativeConversions); + assertEquals("Type mapper not called for result", 3, CallbackTestLibrary._MAPPER.toNativeConversions); } public void testCallbackUsesTypeMapperWithDifferentReturnTypeSize() throws Exception { @@ -1175,9 +1180,9 @@ public float callback(float arg, float arg2) { return arg + arg2; } }; - assertEquals("Wrong type mapper for callback class", lib._MAPPER, + assertEquals("Wrong type mapper for callback class", CallbackTestLibrary._MAPPER, Native.getTypeMapper(CallbackTestLibrary.FloatCallback.class)); - assertEquals("Wrong type mapper for callback object", lib._MAPPER, + assertEquals("Wrong type mapper for callback object", CallbackTestLibrary._MAPPER, Native.getTypeMapper(cb.getClass())); float result = lib.callInt64Callback(cb, -1, -2); @@ -1293,7 +1298,7 @@ public void callback() { // as daemon to avoid VM having to wait for it. public void testCallbackThreadPersistence() throws Exception { final int[] called = {0}; - final Set threads = new HashSet(); + final Set threads = new HashSet(); final int COUNT = 5; CallbackThreadInitializer init = new CallbackThreadInitializer(true, false) { @@ -1317,49 +1322,48 @@ public void callback() { assertEquals("Multiple callbacks on a given native thread should use the same Thread mapping: " + threads, 1, threads.size()); - waitFor((Thread)threads.iterator().next()); + waitFor(threads.iterator().next()); } // Thread object is never GC'd on linux-amd64 and darwin-amd64 (w/openjdk7) public void testCleanupUndetachedThreadOnThreadExit() throws Exception { - final Set threads = new HashSet(); + final Set> threads = new HashSet>(); final int[] called = { 0 }; TestLibrary.VoidCallback cb = new TestLibrary.VoidCallback() { @Override public void callback() { - threads.add(new WeakReference(Thread.currentThread())); + threads.add(new WeakReference(Thread.currentThread())); if (++called[0] == 1) { Thread.currentThread().setName(getName() + " (Thread to be cleaned up)"); } - Native.detach(false); + Native.detach(false); } }; - // Always attach as daemon to ensure tests will exit + // Always attach as daemon to ensure tests will exit CallbackThreadInitializer asDaemon = new CallbackThreadInitializer(true) { - @Override - public String getName(Callback cb) { - return "Test thread (native) for " + CallbacksTest.this.getName(); - } - }; + @Override + public String getName(Callback cb) { + return "Test thread (native) for " + CallbacksTest.this.getName(); + } + }; callThreadedCallback(cb, asDaemon, 2, 100, called); - // Wait for it to start up + // Wait for it to start up long start = System.currentTimeMillis(); while (threads.size() == 0 && called[0] == 0) { - Thread.sleep(10); - if (System.currentTimeMillis() - start > THREAD_TIMEOUT) { - fail("Timed out waiting for thread to detach and terminate"); - } + Thread.sleep(10L); + if (System.currentTimeMillis() - start > THREAD_TIMEOUT) { + fail("Timed out waiting for thread to detach and terminate"); + } } start = System.currentTimeMillis(); - WeakReference ref = (WeakReference)threads.iterator().next(); - + Reference ref = threads.iterator().next(); while (ref.get() != null) { System.gc(); Thread.sleep(100); - Thread[] remaining = new Thread[Thread.activeCount()]; - Thread.enumerate(remaining); + Thread[] remaining = new Thread[Thread.activeCount()]; + Thread.enumerate(remaining); if (System.currentTimeMillis() - start > THREAD_TIMEOUT) { - Thread t = (Thread)ref.get(); + Thread t = ref.get(); Pointer terminationFlag = Native.getTerminationFlag(t); assertNotNull("Native thread termination flag is missing", terminationFlag); if (terminationFlag.getInt(0) == 0) { @@ -1377,7 +1381,7 @@ public String getName(Callback cb) { // but callback explicitly detaches it on final invocation. public void testCallbackIndicatedThreadDetach() throws Exception { final int[] called = {0}; - final Set threads = new HashSet(); + final Set threads = new HashSet(); final int COUNT = 5; TestLibrary.VoidCallback cb = new TestLibrary.VoidCallback() { @Override @@ -1400,7 +1404,7 @@ else if (count == COUNT) { assertEquals("Multiple callbacks in the same native thread should use the same Thread mapping: " + threads, 1, threads.size()); - waitFor((Thread)threads.iterator().next()); + waitFor(threads.iterator().next()); } public void testDLLCallback() throws Exception { @@ -1440,9 +1444,9 @@ public void callback() { assertEquals("Wrong module HANDLE for DLL function pointer", handle, pref.getValue()); // Check slot re-use - Map refs = new WeakHashMap(callbackCache()); + Map refs = new WeakHashMap(callbackCache()); assertTrue("Callback not cached", refs.containsKey(cb)); - CallbackReference ref = (CallbackReference)refs.get(cb); + CallbackReference ref = refs.get(cb); refs = callbackCache(); Pointer cbstruct = ref.cbstruct; Pointer first_fptr = cbstruct.getPointer(0); @@ -1471,7 +1475,7 @@ public void callback() { cb = new TestCallback(); lib.callVoidCallback(cb); - ref = (CallbackReference)refs.get(cb); + ref = refs.get(cb); cbstruct = ref.cbstruct; assertTrue("Callback not called", called[0]); @@ -1517,7 +1521,7 @@ public void invoke() { } }; try { Pointer p = CallbackReference.getFunctionPointer(cb); - CallbackReference ref = (CallbackReference)CallbackReference.callbackMap.get(cb); + CallbackReference ref = CallbackReference.callbackMap.get(cb); assertNotNull("CallbackReference not found", ref); assertEquals("Tag-based calling convention not applied", Function.ALT_CONVENTION, ref.callingConvention); } @@ -1533,20 +1537,20 @@ interface TestCallback extends Callback { } public void testCallingConventionFromOptions() { - Map options = new HashMap(); - options.put(Library.OPTION_CALLING_CONVENTION, Function.ALT_CONVENTION); - OptionCallingConventionTestLibrary lib = Native.loadLibrary("testlib", OptionCallingConventionTestLibrary.class, options); + OptionCallingConventionTestLibrary lib = + Native.loadLibrary("testlib", OptionCallingConventionTestLibrary.class, Collections.singletonMap(Library.OPTION_CALLING_CONVENTION, Function.ALT_CONVENTION)); + assertNotNull("Library not loaded", lib); OptionCallingConventionTestLibrary.TestCallback cb = new OptionCallingConventionTestLibrary.TestCallback() { @Override public void invoke() { } }; try { Pointer p = CallbackReference.getFunctionPointer(cb); - CallbackReference ref = (CallbackReference)CallbackReference.callbackMap.get(cb); + assertNotNull("No function pointer", p); + CallbackReference ref = CallbackReference.callbackMap.get(cb); assertNotNull("CallbackReference not found", ref); assertEquals("Option-based calling convention not applied", Function.ALT_CONVENTION, ref.callingConvention); - } - catch(IllegalArgumentException e) { + } catch(IllegalArgumentException e) { // Alt convention not supported } } diff --git a/test/com/sun/jna/DirectBufferArgumentsMarshalTest.java b/test/com/sun/jna/DirectBufferArgumentsMarshalTest.java index a335c7806f..29b5009106 100644 --- a/test/com/sun/jna/DirectBufferArgumentsMarshalTest.java +++ b/test/com/sun/jna/DirectBufferArgumentsMarshalTest.java @@ -8,19 +8,17 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; import java.nio.ByteBuffer; -import java.nio.FloatBuffer; import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.ShortBuffer; -import com.sun.jna.ArgumentsMarshalTest.TestLibrary.CheckFieldAlignment.ByReference; - /** Exercise a range of native methods. * * @author twall@users.sf.net @@ -30,18 +28,29 @@ public class DirectBufferArgumentsMarshalTest extends BufferArgumentsMarshalTest public static class DirectTestLibrary implements TestLibrary { // ByteBuffer alternative definitions + @Override public native int fillInt8Buffer(ByteBuffer buf, int len, byte value); + @Override public native int fillInt16Buffer(ByteBuffer buf, int len, short value); + @Override public native int fillInt32Buffer(ByteBuffer buf, int len, int value); + @Override public native int fillInt64Buffer(ByteBuffer buf, int len, long value); + @Override public native int fillFloatBuffer(ByteBuffer buf, int len, float value); + @Override public native int fillDoubleBuffer(ByteBuffer buf, int len, double value); - - // {Short|Int|Long|Float|Double}Buffer alternative definitions + + // {Short|Int|Long|Float|Double}Buffer alternative definitions + @Override public native int fillInt16Buffer(ShortBuffer buf, int len, short value); + @Override public native int fillInt32Buffer(IntBuffer buf, int len, int value); + @Override public native int fillInt64Buffer(LongBuffer buf, int len, long value); + @Override public native int fillFloatBuffer(FloatBuffer buf, int len, float value); + @Override public native int fillDoubleBuffer(DoubleBuffer buf, int len, double value); static { @@ -50,12 +59,13 @@ public static class DirectTestLibrary implements TestLibrary { } /* Override original. */ + @Override protected void setUp() { lib = new DirectTestLibrary(); } - + public static void main(java.lang.String[] argList) { junit.textui.TestRunner.run(DirectBufferArgumentsMarshalTest.class); } - + } diff --git a/test/com/sun/jna/DirectCallbacksTest.java b/test/com/sun/jna/DirectCallbacksTest.java index 4be9d4b5b7..22aaa07455 100644 --- a/test/com/sun/jna/DirectCallbacksTest.java +++ b/test/com/sun/jna/DirectCallbacksTest.java @@ -8,7 +8,7 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -23,29 +23,52 @@ public class DirectCallbacksTest extends CallbacksTest { public static class DirectTestLibrary implements TestLibrary { + @Override public native void callVoidCallback(VoidCallbackCustom c); + @Override public native boolean callBooleanCallback(BooleanCallback c, boolean arg, boolean arg2); + @Override public native byte callInt8Callback(ByteCallback c, byte arg, byte arg2); + @Override public native short callInt16Callback(ShortCallback c, short arg, short arg2); + @Override public native int callInt32Callback(Int32Callback c, int arg, int arg2); + @Override public native NativeLong callNativeLongCallback(NativeLongCallback c, NativeLong arg, NativeLong arg2); + @Override public native long callInt64Callback(Int64Callback c, long arg, long arg2); + @Override public native float callFloatCallback(FloatCallback c, float arg, float arg2); + @Override public native double callDoubleCallback(DoubleCallback c, double arg, double arg2); + @Override public native SmallTestStructure callStructureCallback(StructureCallback c, SmallTestStructure arg); + @Override public native String callStringCallback(StringCallback c, String arg, String arg2); + @Override public native WString callWideStringCallback(WideStringCallback c, WString arg, WString arg2); + @Override public Pointer callStringArrayCallback(StringArrayCallback c, String[] arg) { throw new UnsupportedOperationException(); } + @Override public native int callCallbackWithByReferenceArgument(CopyArgToByReference cb, int arg, IntByReference result); + @Override public native TestStructure.ByValue callCallbackWithStructByValue(TestStructure.TestCallback callback, TestStructure.ByValue cbstruct); + @Override public native CbCallback callCallbackWithCallback(CbCallback cb); + @Override public native Int32CallbackX returnCallback(); + @Override public native Int32CallbackX returnCallbackArgument(Int32CallbackX cb); + @Override public native void callVoidCallback(VoidCallback c); + @Override public native void callVoidCallbackThreaded(VoidCallback c, int count, int ms, String name); + @Override public native int callInt32Callback(CustomCallback cb, int arg1, int arg2); + @Override public native void callCallbackInStruct(CbStruct s); + @Override public native TestUnion testUnionByValueCallbackArgument(UnionCallback cb, TestUnion arg); static { @@ -53,29 +76,37 @@ public static class DirectTestLibrary implements TestLibrary { } } + @Override protected void setUp() { lib = new DirectTestLibrary(); } - - protected Map callbackCache() { + + @Override + protected Map callbackCache() { return CallbackReference.directCallbackMap; } public static class DirectCallbackTestLibrary implements CallbackTestLibrary { + @Override public native double callInt32Callback(DoubleCallback c, double arg, double arg2); + @Override public native float callInt64Callback(FloatCallback c, float arg, float arg2); + @Override public native String callWideStringCallback(WStringCallback c, String arg, String arg2); static { Native.register(NativeLibrary.getInstance("testlib", _OPTIONS)); } } + @Override protected CallbackTestLibrary loadCallbackTestLibrary() { return new DirectCallbackTestLibrary(); } // Currently unsupported tests + @Override public void testCallStringArrayCallback() { } + @Override public void testCallbackExceptionHandlerWithCallbackProxy() { } public static void main(java.lang.String[] argList) { diff --git a/test/com/sun/jna/DirectReturnTypesTest.java b/test/com/sun/jna/DirectReturnTypesTest.java index 525a67be21..99ead6d9ec 100644 --- a/test/com/sun/jna/DirectReturnTypesTest.java +++ b/test/com/sun/jna/DirectReturnTypesTest.java @@ -8,19 +8,12 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; -import java.util.HashMap; import java.util.Map; -import junit.framework.TestCase; - -import com.sun.jna.ReturnTypesTest.TestLibrary.SimpleStructure; -import com.sun.jna.ReturnTypesTest.TestLibrary.TestStructure; -import com.sun.jna.ReturnTypesTest.TestLibrary.TestSmallStructure; - /** Exercise a range of native methods. * * @author twall@users.sf.net @@ -28,34 +21,57 @@ public class DirectReturnTypesTest extends ReturnTypesTest { public static class DirectTestLibrary implements TestLibrary { - + + @Override public Object returnObjectArgument(Object s) { throw new IllegalArgumentException(s.getClass().getName()); } + @Override public TestObject returnObjectArgument(TestObject s) { throw new IllegalArgumentException(s.getClass().getName()); } + @Override public native boolean returnFalse(); + @Override public native boolean returnTrue(); + @Override public native int returnInt32Zero(); + @Override public native int returnInt32Magic(); + @Override public native long returnInt64Zero(); + @Override public native long returnInt64Magic(); + @Override public native NativeLong returnLongZero(); + @Override public native NativeLong returnLongMagic(); + @Override public native float returnFloatZero(); + @Override public native float returnFloatMagic(); + @Override public native double returnDoubleZero(); + @Override public native double returnDoubleMagic(); + @Override public native String returnStringMagic(); + @Override public native WString returnWStringMagic(); + @Override public native SimpleStructure returnStaticTestStructure(); + @Override public native SimpleStructure returnNullTestStructure(); + @Override public native TestSmallStructure.ByValue returnSmallStructureByValue(); + @Override public native TestStructure.ByValue returnStructureByValue(); + @Override public Pointer[] returnPointerArgument(Pointer[] arg) {throw new UnsupportedOperationException();} + @Override public String[] returnPointerArgument(String[] arg) {throw new UnsupportedOperationException();} + @Override public WString[] returnPointerArgument(WString[] arg) {throw new UnsupportedOperationException();} static { @@ -63,32 +79,41 @@ public TestObject returnObjectArgument(TestObject s) { } } + @Override protected void setUp() { lib = new DirectTestLibrary(); } - + public static class DirectObjectTestLibrary extends DirectTestLibrary { - public DirectObjectTestLibrary(Map options) { + public DirectObjectTestLibrary(Map options) { Native.register(getClass(), NativeLibrary.getInstance("testlib", options)); } } public static class DirectNativeMappedLibrary implements NativeMappedLibrary { + @Override public native Custom returnInt32Argument(int arg); + @Override public native size_t returnInt32Magic(); + @Override public native size_t returnInt64Magic(); static { Native.register("testlib"); } } + @Override protected NativeMappedLibrary loadNativeMappedLibrary() { return new DirectNativeMappedLibrary(); } // Override not-yet-supported tests + @Override public void testReturnObject() { } + @Override public void testReturnPointerArray() { } + @Override public void testReturnStringArray() { } + @Override public void testReturnWStringArray() { } public static void main(java.lang.String[] argList) { diff --git a/test/com/sun/jna/DirectStructureByValueTest.java b/test/com/sun/jna/DirectStructureByValueTest.java index e0ae4f3189..c484c6bd71 100644 --- a/test/com/sun/jna/DirectStructureByValueTest.java +++ b/test/com/sun/jna/DirectStructureByValueTest.java @@ -12,12 +12,6 @@ */ package com.sun.jna; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.util.Map; - -import junit.framework.TestCase; - /** General structure by value functionality tests. */ public class DirectStructureByValueTest extends StructureByValueTest { diff --git a/test/com/sun/jna/DirectTest.java b/test/com/sun/jna/DirectTest.java index 769b5aec79..e81155d24c 100644 --- a/test/com/sun/jna/DirectTest.java +++ b/test/com/sun/jna/DirectTest.java @@ -19,6 +19,7 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -99,6 +100,7 @@ private static class TestLoader extends URLClassLoader { public TestLoader() throws MalformedURLException { this(null); } + public TestLoader(ClassLoader parent) throws MalformedURLException { super(Platform.isWindowsCE() ? new URL[] { @@ -171,13 +173,13 @@ protected List getFieldOrder() { public static interface DirectCallback extends Callback { void invoke(); } - public DirectMapping(Map options) { + public DirectMapping(Map options) { Native.register(getClass(), NativeLibrary.getInstance("testlib", options)); } } public void testGetOptionsForDirectMappingWithMemberInitializer() { - Class[] classes = { + Class[] classes = { DirectMapping.class, DirectMapping.DirectStructure.class, DirectMapping.DirectCallback.class, @@ -185,20 +187,20 @@ public void testGetOptionsForDirectMappingWithMemberInitializer() { final TypeMapper mapper = new DefaultTypeMapper(); final int alignment = Structure.ALIGN_NONE; final String encoding = System.getProperty("file.encoding"); - Map options = new HashMap(); + Map options = new HashMap(); options.put(Library.OPTION_TYPE_MAPPER, mapper); options.put(Library.OPTION_STRUCTURE_ALIGNMENT, alignment); options.put(Library.OPTION_STRING_ENCODING, encoding); DirectMapping lib = new DirectMapping(options); - for (int i=0;i < classes.length;i++) { - assertEquals("Wrong type mapper for direct mapping " + classes[i], - mapper, Native.getTypeMapper(classes[i])); - assertEquals("Wrong alignment for direct mapping " + classes[i], - alignment, Native.getStructureAlignment(classes[i])); - assertEquals("Wrong encoding for direct mapping " + classes[i], - encoding, Native.getStringEncoding(classes[i])); - Object last = Native.getLibraryOptions(classes[i]);; - assertSame("Options not cached", last, Native.getLibraryOptions(classes[i])); + for (Class cls : classes) { + assertEquals("Wrong type mapper for direct mapping " + cls, + mapper, Native.getTypeMapper(cls)); + assertEquals("Wrong alignment for direct mapping " + cls, + alignment, Native.getStructureAlignment(cls)); + assertEquals("Wrong encoding for direct mapping " + cls, + encoding, Native.getStringEncoding(cls)); + Object last = Native.getLibraryOptions(cls); + assertSame("Options not cached", last, Native.getLibraryOptions(cls)); } } @@ -206,7 +208,9 @@ public static class DirectMappingStatic { final static TypeMapper TEST_MAPPER = new DefaultTypeMapper(); final static int TEST_ALIGNMENT = Structure.ALIGN_DEFAULT; final static String TEST_ENCODING = System.getProperty("file.encoding"); - final static Map TEST_OPTIONS = new HashMap() { + final static Map TEST_OPTIONS = new HashMap() { + private static final long serialVersionUID = 1L; // we're not serializing it + { put(Library.OPTION_TYPE_MAPPER, TEST_MAPPER); put(Library.OPTION_STRUCTURE_ALIGNMENT, TEST_ALIGNMENT); @@ -229,20 +233,20 @@ public static interface DirectCallback extends Callback { } public void testGetOptionsForDirectMappingWithStaticInitializer() { - Class[] classes = { + Class[] classes = { DirectMappingStatic.class, DirectMappingStatic.DirectStructure.class, DirectMappingStatic.DirectCallback.class, }; - for (int i=0;i < classes.length;i++) { - assertEquals("Wrong type mapper for direct mapping " + classes[i], - DirectMappingStatic.TEST_MAPPER, Native.getTypeMapper(classes[i])); - assertEquals("Wrong alignment for direct mapping " + classes[i], - DirectMappingStatic.TEST_ALIGNMENT, Native.getStructureAlignment(classes[i])); - assertEquals("Wrong encoding for direct mapping " + classes[i], - DirectMappingStatic.TEST_ENCODING, Native.getStringEncoding(classes[i])); - Object last = Native.getLibraryOptions(classes[i]);; - assertSame("Options not cached", last, Native.getLibraryOptions(classes[i])); + for (Class cls : classes) { + assertEquals("Wrong type mapper for direct mapping " + cls, + DirectMappingStatic.TEST_MAPPER, Native.getTypeMapper(cls)); + assertEquals("Wrong alignment for direct mapping " + cls, + DirectMappingStatic.TEST_ALIGNMENT, Native.getStructureAlignment(cls)); + assertEquals("Wrong encoding for direct mapping " + cls, + DirectMappingStatic.TEST_ENCODING, Native.getStringEncoding(cls)); + Object last = Native.getLibraryOptions(cls); + assertSame("Options not cached", last, Native.getLibraryOptions(cls)); } } @@ -262,21 +266,19 @@ public String getFunctionName(NativeLibrary lib, Method method) { return name; } }; - Map options = new HashMap(); - options.put(Library.OPTION_FUNCTION_MAPPER, MAPPER); + try { Native.register(RemappedCLibrary.class, - NativeLibrary.getInstance(Platform.C_LIBRARY_NAME, options)); + NativeLibrary.getInstance(Platform.C_LIBRARY_NAME, Collections.singletonMap(Library.OPTION_FUNCTION_MAPPER, MAPPER))); final String VALUE = getName(); int len; len = RemappedCLibrary.$$YJP$$strlen(VALUE); - assertEquals(VALUE.length(), len); + assertEquals("Mismatched YJP strlen value", VALUE.length(), len); len = RemappedCLibrary._prefixed_strlen(VALUE); - assertEquals(VALUE.length(), len); - } - catch(Exception e) { + assertEquals("Mismatched prefixed strlen value", VALUE.length(), len); + } catch(Exception e) { fail("Native method was not properly mapped: " + e); } } diff --git a/test/com/sun/jna/DirectTypeMapperTest.java b/test/com/sun/jna/DirectTypeMapperTest.java index a03f481646..3ba3aeefd4 100644 --- a/test/com/sun/jna/DirectTypeMapperTest.java +++ b/test/com/sun/jna/DirectTypeMapperTest.java @@ -8,13 +8,12 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; -import java.util.HashMap; -import java.util.Map; +import java.util.Collections; import junit.framework.TestCase; public class DirectTypeMapperTest extends TestCase { @@ -26,18 +25,19 @@ public static class DirectTestLibraryBoolean { final static int MAGIC = 0xABEDCF23; public native int returnInt32Argument(boolean b); static { - Map options = new HashMap(); DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addToNativeConverter(Boolean.class, new ToNativeConverter() { + @Override public Object toNative(Object arg, ToNativeContext ctx) { return new Integer(Boolean.TRUE.equals(arg) ? MAGIC : 0); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - Native.register(NativeLibrary.getInstance("testlib", options)); + + Native.register(NativeLibrary.getInstance("testlib", Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper))); } } /** Converts String to int when going to native. */ @@ -46,16 +46,16 @@ public static class DirectTestLibraryString { static { DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addToNativeConverter(String.class, new ToNativeConverter() { + @Override public Object toNative(Object arg, ToNativeContext ctx) { return Integer.valueOf((String) arg, 16); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - Native.register(NativeLibrary.getInstance("testlib", options)); + Native.register(NativeLibrary.getInstance("testlib", Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper))); } } /** Converts CharSequence to int when going to native. */ @@ -64,17 +64,16 @@ public static class DirectTestLibraryCharSequence { static { DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addToNativeConverter(CharSequence.class, new ToNativeConverter() { + @Override public Object toNative(Object arg, ToNativeContext ctx) { return Integer.valueOf(((CharSequence)arg).toString(), 16); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - - Native.register(NativeLibrary.getInstance("testlib", options)); + Native.register(NativeLibrary.getInstance("testlib", Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper))); } } /** Converts Number to int when going to native. */ @@ -83,17 +82,16 @@ public static class DirectTestLibraryNumber { static { DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addToNativeConverter(Number.class, new ToNativeConverter() { + @Override public Object toNative(Object arg, ToNativeContext ctx) { return new Integer(((Number)arg).intValue()); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - - Native.register(NativeLibrary.getInstance("testlib", options)); + Native.register(NativeLibrary.getInstance("testlib", Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper))); } } /** Converts String to WString and back. */ @@ -102,32 +100,32 @@ public static class DirectTestLibraryWString { static { DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addTypeConverter(String.class, new TypeConverter() { + @Override public Object toNative(Object value, ToNativeContext ctx) { if (value == null) { return null; } return new WString(value.toString()); } + @Override public Object fromNative(Object value, FromNativeContext context) { if (value == null) { return null; } return value.toString(); } - public Class nativeType() { + @Override + public Class nativeType() { return WString.class; } }); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - - Native.register(NativeLibrary.getInstance("testlib", options)); + Native.register(NativeLibrary.getInstance("testlib", Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper))); } } public void testBooleanToIntArgumentConversion() { DirectTestLibraryBoolean lib = new DirectTestLibraryBoolean(); assertEquals("Failed to convert Boolean argument to Int", - lib.MAGIC, + DirectTestLibraryBoolean.MAGIC, lib.returnInt32Argument(true)); } public void testStringToIntArgumentConversion() { @@ -143,7 +141,7 @@ public void testCharSequenceToIntArgumentConversion() { lib.returnInt32Argument(Integer.toHexString(MAGIC))); } public void testNumberToIntArgumentConversion() { - + final int MAGIC = 0x7BEDCF23; DirectTestLibraryNumber lib = new DirectTestLibraryNumber(); assertEquals("Failed to convert Double argument to Int", MAGIC, @@ -161,36 +159,38 @@ public static class DirectTestLibraryBidirectionalBoolean { public native boolean returnInt32Argument(boolean b); static { final int MAGIC = 0xABEDCF23; - Map options = new HashMap(); DefaultTypeMapper mapper = new DefaultTypeMapper(); // Use opposite sense of default int<-->boolean conversions mapper.addToNativeConverter(Boolean.class, new ToNativeConverter() { + @Override public Object toNative(Object value, ToNativeContext ctx) { return new Integer(Boolean.TRUE.equals(value) ? 0 : MAGIC); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); mapper.addFromNativeConverter(Boolean.class, new FromNativeConverter() { + @Override public Object fromNative(Object value, FromNativeContext context) { return Boolean.valueOf(((Integer) value).intValue() != MAGIC); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - Native.register(NativeLibrary.getInstance("testlib", options)); + Native.register(NativeLibrary.getInstance("testlib", Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper))); } } public void testIntegerToBooleanResultConversion() throws Exception { DirectTestLibraryBidirectionalBoolean lib = new DirectTestLibraryBidirectionalBoolean(); // argument "true" converts to zero; result zero converts to "true" - assertTrue("Failed to convert integer return to boolean TRUE", + assertTrue("Failed to convert integer return to boolean TRUE", lib.returnInt32Argument(true)); // argument "true" converts to MAGIC; result MAGIC converts to "false" - assertFalse("Failed to convert integer return to boolean FALSE", + assertFalse("Failed to convert integer return to boolean FALSE", lib.returnInt32Argument(false)); } public static class PointTestClass { @@ -200,9 +200,9 @@ public static class PointTestClass { public static class DirectTypeMappedResultTypeTestLibrary { public native PointTestClass returnPoint(int x, int y); static { - Map options = new HashMap(); DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addTypeConverter(PointTestClass.class, new TypeConverter() { + @Override public Object fromNative(Object value, FromNativeContext context) { Pointer p = (Pointer) value; PointTestClass pc = new PointTestClass(); @@ -211,16 +211,18 @@ public Object fromNative(Object value, FromNativeContext context) { Native.free(Pointer.nativeValue(p)); return pc; } + @Override public Object toNative(Object value, ToNativeContext context) { return Pointer.NULL; // dummy implementation (not called) } - public Class nativeType() { + @Override + public Class nativeType() { return Pointer.class; } }); - options.put(Library.OPTION_TYPE_MAPPER, mapper); + PointTestClass.TYPE_MAPPER = mapper; - Native.register(NativeLibrary.getInstance("testlib", options)); + Native.register(NativeLibrary.getInstance("testlib", Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper))); } } public void testTypeMapperResultTypeConversion() throws Exception { @@ -247,20 +249,20 @@ public static Enumeration fromCode(int code) { static { DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addTypeConverter(Enumeration.class, new TypeConverter() { + @Override public Object toNative(Object arg, ToNativeContext ctx) { return new Integer(((Enumeration)arg).getCode()); } + @Override public Object fromNative(Object value, FromNativeContext context) { return Enumeration.fromCode(((Integer)value).intValue()); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - - Native.register(NativeLibrary.getInstance("testlib", options)); + Native.register(NativeLibrary.getInstance("testlib", Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper))); } } public void testEnumerationConversion() { diff --git a/test/com/sun/jna/FunctionTest.java b/test/com/sun/jna/FunctionTest.java index 867660e45a..05ceaf975f 100644 --- a/test/com/sun/jna/FunctionTest.java +++ b/test/com/sun/jna/FunctionTest.java @@ -8,13 +8,10 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; -import java.util.Arrays; -import java.util.List; - import junit.framework.TestCase; /** Exercise the {@link Function} class. @@ -30,11 +27,11 @@ public void testTooManyArgs() { Object[] args = new Object[Function.MAX_NARGS+1]; // Make sure we don't break 'printf' args[0] = getName(); - try { + try { f.invokeInt(args); fail("Arguments should be limited to " + Function.MAX_NARGS); - } - catch(UnsupportedOperationException e) { + } catch(UnsupportedOperationException e) { + // expected } assertEquals("Wrong result from 'printf'", getName().length(), f.invokeInt(new Object[] { getName() })); } @@ -45,13 +42,13 @@ public void testUnsupportedReturnType() { try { f.invoke(getClass(), new Object[] { getName() }); fail("Invalid return types should throw an exception"); - } - catch(IllegalArgumentException e) { + } catch(IllegalArgumentException e) { + // expected } } public static void main(java.lang.String[] argList) { junit.textui.TestRunner.run(FunctionTest.class); } - + } diff --git a/test/com/sun/jna/GCWaits.java b/test/com/sun/jna/GCWaits.java index d98043a810..be73d27dc0 100644 --- a/test/com/sun/jna/GCWaits.java +++ b/test/com/sun/jna/GCWaits.java @@ -1,3 +1,16 @@ +/* Copyright (c) 2007 Timothy Wall, All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + package com.sun.jna; public interface GCWaits { diff --git a/test/com/sun/jna/IntegerTypeTest.java b/test/com/sun/jna/IntegerTypeTest.java index b0660c8926..e38381f30b 100644 --- a/test/com/sun/jna/IntegerTypeTest.java +++ b/test/com/sun/jna/IntegerTypeTest.java @@ -8,6 +8,7 @@ public class IntegerTypeTest extends TestCase { public static class Sized extends IntegerType { + private static final long serialVersionUID = 1L; public Sized() { this(4, 0); } public Sized(int size, long value) { super(size, value); } } @@ -16,8 +17,8 @@ public void testWriteNull() { class NTStruct extends Structure { public Sized field; @Override - protected List getFieldOrder() { - return Arrays.asList(new String[] { "field" }); + protected List getFieldOrder() { + return Arrays.asList("field"); } } NTStruct s = new NTStruct(); @@ -27,8 +28,8 @@ public void testReadNull() { class NTStruct extends Structure { public Sized field; @Override - protected List getFieldOrder() { - return Arrays.asList(new String[] { "field" }); + protected List getFieldOrder() { + return Arrays.asList("field"); } } NTStruct s = new NTStruct(); @@ -78,6 +79,8 @@ public void testInitialValue() { public void testValueBoundaries() { class TestType extends IntegerType { + private static final long serialVersionUID = 1L; + public TestType(int size, long value) { super(size, value); } @@ -104,6 +107,8 @@ public TestType(int size, long value) { public void testUnsignedValues() { class TestType extends IntegerType { + private static final long serialVersionUID = 1L; + public TestType(int size, long value) { super(size, value); } @@ -116,6 +121,8 @@ public TestType(int size, long value) { assertEquals("Wrong unsigned int value", VALUE, new TestType(4, VALUE).longValue()); class UnsignedTestType extends IntegerType { + private static final long serialVersionUID = 1L; + public UnsignedTestType(int size, long value) { super(size, value, true); } diff --git a/test/com/sun/jna/JNALoadTest.java b/test/com/sun/jna/JNALoadTest.java index 42ffc2122c..a9b09c788b 100644 --- a/test/com/sun/jna/JNALoadTest.java +++ b/test/com/sun/jna/JNALoadTest.java @@ -13,6 +13,7 @@ package com.sun.jna; import java.io.File; +import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.net.MalformedURLException; @@ -115,8 +116,8 @@ public void testLoadAndUnloadFromJar() throws Exception { assertTrue("Native library not unpacked from jar: " + path, path.startsWith(System.getProperty("java.io.tmpdir"))); - WeakReference ref = new WeakReference(cls); - WeakReference clref = new WeakReference(loader); + Reference> ref = new WeakReference>(cls); + Reference clref = new WeakReference(loader); loader = null; cls = null; field = null; @@ -136,8 +137,8 @@ public void testLoadAndUnloadFromJar() throws Exception { } if (f.exists()) { - assertTrue("Temporary jnidispatch not marked for later deletion: " - + f, new File(f.getAbsolutePath()+".x").exists()); + assertTrue("Temporary jnidispatch not marked for later deletion: " + f, + new File(f.getAbsolutePath()+".x").exists()); } assertFalse("System property jna.loaded not cleared", Boolean.getBoolean("jna.loaded")); @@ -146,11 +147,9 @@ public void testLoadAndUnloadFromJar() throws Exception { try { loader = new TestLoader(true); cls = Class.forName("com.sun.jna.Native", true, loader); - } - catch(Throwable t) { + } catch(Throwable t) { fail("Couldn't load class again after discarding first load: " + t.getMessage()); - } - finally { + } finally { loader = null; cls = null; System.gc(); @@ -169,8 +168,8 @@ public void testLoadAndUnloadFromResourcePath() throws Exception { String path = (String)field.get(null); assertNotNull("Native library not found", path); - WeakReference ref = new WeakReference(cls); - WeakReference clref = new WeakReference(loader); + Reference> ref = new WeakReference>(cls); + Reference clref = new WeakReference(loader); loader = null; cls = null; field = null; diff --git a/test/com/sun/jna/LastErrorTest.java b/test/com/sun/jna/LastErrorTest.java index d8ccde6a96..0e0edd5857 100644 --- a/test/com/sun/jna/LastErrorTest.java +++ b/test/com/sun/jna/LastErrorTest.java @@ -12,29 +12,29 @@ */ package com.sun.jna; -import java.util.Map; -import java.util.HashMap; -import java.util.Set; -import java.util.HashSet; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; import junit.framework.TestCase; //@SuppressWarnings("unused") public class LastErrorTest extends TestCase { - private static final Map OPTIONS = new HashMap() {{ - put(Library.OPTION_FUNCTION_MAPPER, new FunctionMapper() { - @Override - public String getFunctionName(NativeLibrary library, Method m) { - if (m.getName().equals("noThrowLastError") - || m.getName().equals("throwLastError")) { - return "setLastError"; + private static final Map OPTIONS = + Collections.singletonMap(Library.OPTION_FUNCTION_MAPPER, new FunctionMapper() { + @Override + public String getFunctionName(NativeLibrary library, Method m) { + if (m.getName().equals("noThrowLastError") + || m.getName().equals("throwLastError")) { + return "setLastError"; + } + return m.getName(); } - return m.getName(); - } - }); - }}; + }); public interface TestLibrary extends Library { void setLastError(int code); @@ -58,14 +58,17 @@ public void testLastErrorPerThreadStorage() throws Exception { final TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class); final int NTHREADS = 100; final int[] errors = new int[NTHREADS]; - Set threads = new HashSet(); + List threads = new ArrayList(NTHREADS); for (int i=0;i < NTHREADS;i++) { final int idx = i; - Thread t = new Thread() { @Override - public void run() { - lib.setLastError(-idx-1); - errors[idx] = Native.getLastError(); - }}; + Thread t = new Thread("tLastErrorSetter-" + i) { + @Override + public void run() { + lib.setLastError(-idx-1); + errors[idx] = Native.getLastError(); + } + }; + t.setDaemon(true); // so we can stop the main thread if necessary threads.add(t); } int EXPECTED = 42; @@ -75,8 +78,10 @@ public void run() { t.start(); } for (Thread t : threads) { - t.join(); + t.join(TimeUnit.SECONDS.toMillis(7L)); + assertFalse("Thread " + t.getName() + " still alive", t.isAlive()); } + assertEquals("Wrong error on main thread", EXPECTED, Native.getLastError()); for (int i=0;i < threads.size();i++) { assertEquals("Wrong error on thread " + i, -i-1, errors[i]); @@ -92,8 +97,7 @@ public void testThrowLastError() { try { lib.throwLastError(ERROR); fail("Method should throw LastErrorException"); - } - catch(LastErrorException e) { + } catch(LastErrorException e) { assertEquals("Exception should contain error code", ERROR, e.getErrorCode()); assertTrue("Exception should include error message: '" + e.getMessage() + "'", e.getMessage().length() > 0); } @@ -107,8 +111,7 @@ public void testThrowLastErrorDirect() { try { lib.throwLastError(ERROR); fail("Method should throw LastErrorException"); - } - catch(LastErrorException e) { + } catch(LastErrorException e) { assertEquals("Exception should contain error code", ERROR, e.getErrorCode()); assertTrue("Exception should include error message: " + e.getMessage(), e.getMessage().length() > 0); } diff --git a/test/com/sun/jna/MemoryTest.java b/test/com/sun/jna/MemoryTest.java index 59614e5fd9..c292711793 100644 --- a/test/com/sun/jna/MemoryTest.java +++ b/test/com/sun/jna/MemoryTest.java @@ -1,19 +1,19 @@ /* Copyright (c) 2007 Timothy Wall, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; +import java.lang.ref.Reference; import java.lang.ref.WeakReference; -import java.nio.Buffer; import java.nio.ByteBuffer; import junit.framework.TestCase; @@ -23,23 +23,24 @@ public class MemoryTest extends TestCase implements GCWaits { public void testAutoFreeMemory() throws Exception { final boolean[] flag = { false }; Memory core = new Memory(10) { + @Override protected void finalize() { super.finalize(); flag[0] = true; } }; Pointer shared = core.share(0, 5); - WeakReference ref = new WeakReference(core); - + Reference ref = new WeakReference(core); + core = null; System.gc(); - long start = System.currentTimeMillis(); assertFalse("Memory prematurely GC'd", flag[0]); assertNotNull("Base memory GC'd while shared memory extant", ref.get()); // Avoid having IBM J9 prematurely nullify "shared" shared.setInt(0, 0); shared = null; + long start = System.currentTimeMillis(); System.gc(); Memory.purge(); for (int i=0;i < GC_WAITS && ref.get() != null;i++) { @@ -47,7 +48,8 @@ protected void finalize() { System.gc(); Memory.purge(); } - assertNull("Memory not GC'd", ref.get()); + long end = System.currentTimeMillis(); + assertNull("Memory not GC'd after " + (end - start) + " millis", ref.get()); } public void testShareMemory() { @@ -122,8 +124,8 @@ public void testAvoidGCWithExtantBuffer() throws Exception { m.clear(); ByteBuffer b = m.getByteBuffer(0, m.size()); - WeakReference ref = new WeakReference(m); - WeakReference bref = new WeakReference(b); + Reference ref = new WeakReference(m); + Reference bref = new WeakReference(b); // Create a second byte buffer "equal" to the first m = new Memory(1024); @@ -138,7 +140,7 @@ public void testAvoidGCWithExtantBuffer() throws Exception { System.gc(); Memory.purge(); } - assertNotNull("Memory GC'd while NIO Buffer still extant", ref.get()); + assertNotNull("Memory GC'd while NIO Buffer still exists", ref.get()); // Avoid IBM J9 optimization resulting in premature GC of buffer b.put((byte)0); diff --git a/test/com/sun/jna/NativeLibraryTest.java b/test/com/sun/jna/NativeLibraryTest.java index 2c6688134d..439a6f984d 100644 --- a/test/com/sun/jna/NativeLibraryTest.java +++ b/test/com/sun/jna/NativeLibraryTest.java @@ -15,13 +15,12 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; +import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.net.MalformedURLException; import java.net.URL; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.Collections; + import com.sun.jna.win32.W32APIOptions; import junit.framework.TestCase; @@ -59,13 +58,13 @@ public void testMapSharedLibraryName() { public void testGCNativeLibrary() throws Exception { NativeLibrary lib = NativeLibrary.getInstance("testlib"); - WeakReference ref = new WeakReference(lib); + Reference ref = new WeakReference(lib); lib = null; System.gc(); long start = System.currentTimeMillis(); while (ref.get() != null) { Thread.sleep(10); - if (System.currentTimeMillis() - start > 5000) + if ((System.currentTimeMillis() - start) > 5000L) break; } assertNull("Library not GC'd", ref.get()); @@ -115,14 +114,15 @@ public void testAliasLibraryFullPath() { public void testAliasSimpleLibraryName() throws Exception { NativeLibrary nl = NativeLibrary.getInstance("testlib"); File file = nl.getFile(); - WeakReference ref = new WeakReference(nl); + Reference ref = new WeakReference(nl); nl = null; System.gc(); long start = System.currentTimeMillis(); while (ref.get() != null) { Thread.sleep(10); - if (System.currentTimeMillis() - start > 5000) + if ((System.currentTimeMillis() - start) > 5000L) { fail("Timed out waiting for library to be GC'd"); + } } TestLibrary lib = Native.loadLibrary(file.getAbsolutePath(), TestLibrary.class); int count = lib.callCount(); @@ -135,9 +135,9 @@ public void testRejectNullFunctionName() { NativeLibrary lib = NativeLibrary.getInstance("testlib"); try { Function f = lib.getFunction(null); - fail("Function must have a name"); - } - catch(NullPointerException e) { + fail("Function must have a name: " + f); + } catch(NullPointerException e) { + // expected } } @@ -154,19 +154,18 @@ public void testIncludeSymbolNameInLookupError() { public void testFunctionHoldsLibraryReference() throws Exception { NativeLibrary lib = NativeLibrary.getInstance("testlib"); - WeakReference ref = new WeakReference(lib); + Reference ref = new WeakReference(lib); Function f = lib.getFunction("callCount"); lib = null; System.gc(); - long start = System.currentTimeMillis(); - while (ref.get() != null && System.currentTimeMillis() - start < 2000) { + for (long start = System.currentTimeMillis(); (ref.get() != null) && ((System.currentTimeMillis() - start) < 2000L); ) { Thread.sleep(10); } assertNotNull("Library GC'd when it should not be", ref.get()); f.invokeInt(new Object[0]); f = null; System.gc(); - while (ref.get() != null && System.currentTimeMillis() - start < 5000) { + for (long start = System.currentTimeMillis(); (ref.get() != null) && ((System.currentTimeMillis() - start) < 5000L); ) { Thread.sleep(10); } assertNull("Library not GC'd", ref.get()); @@ -195,10 +194,9 @@ public void testMatchUnversionedToVersioned() throws Exception { File lib1_1 = new File(dir, "lib" + name + ".so.1.1"); lib1_1.createNewFile(); lib1_1.deleteOnExit(); - List path = Arrays.asList(new String[] { dir.getCanonicalPath() }); - assertEquals("Latest versioned library not found when unversioned requested", + assertEquals("Latest versioned library not found when unversioned requested for path=" + dir, lib1_1.getCanonicalPath(), - NativeLibrary.matchLibrary(name, path)); + NativeLibrary.matchLibrary(name, Collections.singletonList(dir.getCanonicalPath()))); } public void testAvoidFalseMatch() throws Exception { @@ -210,10 +208,9 @@ public void testAvoidFalseMatch() throws Exception { File lib1 = new File(dir, "lib" + name + "-client.so.2"); lib1.createNewFile(); lib1.deleteOnExit(); - List path = Arrays.asList(new String[] { dir.getCanonicalPath() }); - assertEquals("Library with similar prefix should be ignored", + assertEquals("Library with similar prefix should be ignored for path=" + dir, lib0.getCanonicalPath(), - NativeLibrary.matchLibrary(name, path)); + NativeLibrary.matchLibrary(name, Collections.singletonList(dir.getCanonicalPath()))); } public void testParseVersion() throws Exception { @@ -264,9 +261,7 @@ public void testMatchFramework() { } public void testLoadLibraryWithOptions() { - Map options = new HashMap(); - options.put(Library.OPTION_OPEN_FLAGS, new Integer(-1)); - Native.loadLibrary("testlib", TestLibrary.class, options); + Native.loadLibrary("testlib", TestLibrary.class, Collections.singletonMap(Library.OPTION_OPEN_FLAGS, Integer.valueOf(-1))); } public interface Kernel32 { @@ -289,11 +284,9 @@ public void testInterceptLastError() { } public void testCleanupOnLoadError() throws Exception { - Map options = new HashMap(); - options.put(Library.OPTION_CLASSLOADER, new DisfunctClassLoader()); int previousTempFileCount = Native.getTempDir().listFiles().length; try { - NativeLibrary.getInstance("disfunct", options); + NativeLibrary.getInstance("disfunct", Collections.singletonMap(Library.OPTION_CLASSLOADER, new DisfunctClassLoader())); fail("Expected NativeLibrary.getInstance() to fail with an UnsatisfiedLinkError here."); } catch(UnsatisfiedLinkError e) { int currentTempFileCount = Native.getTempDir().listFiles().length; diff --git a/test/com/sun/jna/NativeTest.java b/test/com/sun/jna/NativeTest.java index 3058239344..2445b2de59 100644 --- a/test/com/sun/jna/NativeTest.java +++ b/test/com/sun/jna/NativeTest.java @@ -202,17 +202,17 @@ static class InnerTestClass extends Structure { interface TestCallback extends Callback { } static class InnerSubclass extends InnerTestClass implements Structure.ByReference { } @Override - protected List getFieldOrder() { - return Collections.EMPTY_LIST; + protected List getFieldOrder() { + return Collections.emptyList(); } } } public void testFindInterfaceClass() throws Exception { - Class interfaceClass = TestInterface.class; - Class cls = TestInterface.InnerTestClass.class; - Class subClass = TestInterface.InnerTestClass.InnerSubclass.class; - Class callbackClass = TestInterface.InnerTestClass.TestCallback.class; + Class interfaceClass = TestInterface.class; + Class cls = TestInterface.InnerTestClass.class; + Class subClass = TestInterface.InnerTestClass.InnerSubclass.class; + Class callbackClass = TestInterface.InnerTestClass.TestCallback.class; assertEquals("Enclosing interface not found for class", interfaceClass, Native.findEnclosingLibraryClass(cls)); assertEquals("Enclosing interface not found for derived class", @@ -225,17 +225,21 @@ public interface TestInterfaceWithInstance extends Library { int TEST_ALIGNMENT = Structure.ALIGN_NONE; TypeMapper TEST_MAPPER = new DefaultTypeMapper(); String TEST_ENCODING = "test-encoding"; - Map TEST_OPTS = new HashMap() { { - put(OPTION_CLASSLOADER, TestInterfaceWithInstance.class.getClassLoader()); - put(OPTION_TYPE_MAPPER, TEST_MAPPER); - put(OPTION_STRUCTURE_ALIGNMENT, new Integer(TEST_ALIGNMENT)); - put(OPTION_STRING_ENCODING, TEST_ENCODING); - }}; + Map TEST_OPTS = new HashMap() { + private static final long serialVersionUID = 1L; // we're not serializing it + + { + put(OPTION_CLASSLOADER, TestInterfaceWithInstance.class.getClassLoader()); + put(OPTION_TYPE_MAPPER, TEST_MAPPER); + put(OPTION_STRUCTURE_ALIGNMENT, new Integer(TEST_ALIGNMENT)); + put(OPTION_STRING_ENCODING, TEST_ENCODING); + } + }; TestInterfaceWithInstance ARBITRARY = Native.loadLibrary("testlib", TestInterfaceWithInstance.class, TEST_OPTS); abstract class TestStructure extends Structure {} } public void testOptionsInferenceFromInstanceField() { - Class[] classes = { TestInterfaceWithInstance.class, TestInterfaceWithInstance.TestStructure.class }; + Class[] classes = { TestInterfaceWithInstance.class, TestInterfaceWithInstance.TestStructure.class }; String[] desc = { "interface", "structure from interface" }; for (int i=0;i < classes.length;i++) { assertEquals("Wrong type mapper found for " + desc[i], @@ -254,25 +258,23 @@ public interface TestInterfaceWithOptions extends Library { int TEST_ALIGNMENT = Structure.ALIGN_NONE; TypeMapper TEST_MAPPER = new DefaultTypeMapper(); String TEST_ENCODING = "test-encoding"; - Map OPTIONS = new HashMap() { { - put(OPTION_TYPE_MAPPER, TEST_MAPPER); - put(OPTION_STRUCTURE_ALIGNMENT, new Integer(TEST_ALIGNMENT)); - put(OPTION_STRING_ENCODING, TEST_ENCODING); - }}; + Map OPTIONS = new HashMap() { + private static final long serialVersionUID = 1L; // we're not serializing it + + { + put(OPTION_TYPE_MAPPER, TEST_MAPPER); + put(OPTION_STRUCTURE_ALIGNMENT, new Integer(TEST_ALIGNMENT)); + put(OPTION_STRING_ENCODING, TEST_ENCODING); + } + }; abstract class TestStructure extends Structure {} } public void testOptionsInferenceFromOptionsField() { - Class[] classes = { TestInterfaceWithOptions.class, TestInterfaceWithOptions.TestStructure.class }; - for (int i=0;i < classes.length;i++) { - assertEquals("Wrong type mapper found", - TestInterfaceWithOptions.TEST_MAPPER, - Native.getTypeMapper(classes[i])); - assertEquals("Wrong alignment found", - TestInterfaceWithOptions.TEST_ALIGNMENT, - Native.getStructureAlignment(classes[i])); - assertEquals("Wrong encoding found", - TestInterfaceWithOptions.TEST_ENCODING, - Native.getStringEncoding(classes[i])); + Class[] classes = { TestInterfaceWithOptions.class, TestInterfaceWithOptions.TestStructure.class }; + for (Class cls : classes) { + assertEquals("Wrong type mapper found", TestInterfaceWithOptions.TEST_MAPPER, Native.getTypeMapper(cls)); + assertEquals("Wrong alignment found", TestInterfaceWithOptions.TEST_ALIGNMENT, Native.getStructureAlignment(cls)); + assertEquals("Wrong encoding found", TestInterfaceWithOptions.TEST_ENCODING, Native.getStringEncoding(cls)); } } @@ -322,12 +324,14 @@ public interface OptionsBase extends Library { class TypeMappedStructure extends Structure { public String stringField; @Override - protected List getFieldOrder() { return Arrays.asList("stringField"); } + protected List getFieldOrder() { + return Arrays.asList("stringField"); + } } } public interface OptionsSubclass extends OptionsBase, Library { TypeMapper _MAPPER = new DefaultTypeMapper(); - Map _OPTIONS = new HashMap() { { put(Library.OPTION_TYPE_MAPPER, _MAPPER); } }; + Map _OPTIONS = Collections.singletonMap(Library.OPTION_TYPE_MAPPER, _MAPPER); OptionsSubclass INSTANCE = Native.loadLibrary("testlib", OptionsSubclass.class, _OPTIONS); } public void testStructureOptionsInference() { @@ -482,8 +486,7 @@ public static void main(String[] args) { System.out.println("Running tests on class " + args[i]); try { junit.textui.TestRunner.run((Class) Class.forName(args[i])); - } - catch(Throwable e) { + } catch(Throwable e) { e.printStackTrace(); } } diff --git a/test/com/sun/jna/PerformanceTest.java b/test/com/sun/jna/PerformanceTest.java index 926d6b3fbf..4841bad1dc 100644 --- a/test/com/sun/jna/PerformanceTest.java +++ b/test/com/sun/jna/PerformanceTest.java @@ -18,7 +18,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Map; -import java.util.HashMap; +import java.util.Collections; import java.lang.reflect.Method; import com.sun.jna.DirectTest.TestInterface; @@ -61,6 +61,8 @@ interface MathInterface extends Library { static class CLibrary { public static class size_t extends IntegerType { + private static final long serialVersionUID = 1L; + public size_t() { super(Native.POINTER_SIZE); } @@ -195,11 +197,10 @@ public static void checkPerformance() { delta = System.currentTimeMillis() - start; System.out.println("cos (pure java): " + delta + "ms"); - Pointer presult; String cname = Platform.C_LIBRARY_NAME; - Map options = new HashMap(); + Map options = Collections.emptyMap(); if (Platform.isWindows()) { - options.put(Library.OPTION_FUNCTION_MAPPER, new FunctionMapper() { + options = Collections.singletonMap(Library.OPTION_FUNCTION_MAPPER, new FunctionMapper() { @Override public String getFunctionName(NativeLibrary library, Method method) { String name = method.getName(); @@ -247,7 +248,7 @@ public String getFunctionName(NativeLibrary library, Method method) { // memset start = System.currentTimeMillis(); for (int i=0;i < COUNT;i++) { - presult = clib.memset(null, 0, 0); + Pointer presult = clib.memset(null, 0, 0); } delta = System.currentTimeMillis() - start; System.out.println("memset (JNA interface): " + delta + "ms"); @@ -256,41 +257,37 @@ public String getFunctionName(NativeLibrary library, Method method) { args = new Object[] { null, new Integer(0), new Integer(0)}; start = System.currentTimeMillis(); for (int i=0;i < COUNT;i++) { - presult = f.invokePointer(args); + Pointer presult = f.invokePointer(args); } delta = System.currentTimeMillis() - start; System.out.println("memset (JNA function): " + delta + "ms"); start = System.currentTimeMillis(); for (int i=0;i < COUNT;i++) { - presult = CLibrary.memset((Pointer)null, 0, new CLibrary.size_t(0)); + Pointer presult = CLibrary.memset((Pointer)null, 0, new CLibrary.size_t(0)); } delta = System.currentTimeMillis() - start; System.out.println("memset (JNA direct Pointer/size_t): " + delta + "ms"); start = System.currentTimeMillis(); if (Native.POINTER_SIZE == 4) { for (int i=0;i < COUNT;i++) { - presult = CLibrary.memset((Pointer)null, 0, 0); + Pointer presult = CLibrary.memset((Pointer)null, 0, 0); } - } - else { + } else { for (int i=0;i < COUNT;i++) { - presult = CLibrary.memset((Pointer)null, 0, 0L); + Pointer presult = CLibrary.memset((Pointer)null, 0, 0L); } } delta = System.currentTimeMillis() - start; System.out.println("memset (JNA direct Pointer/primitive): " + delta + "ms"); - int iresult; - long jresult; start = System.currentTimeMillis(); if (Native.POINTER_SIZE == 4) { for (int i=0;i < COUNT;i++) { - iresult = CLibrary.memset(0, 0, 0); + int iresult = CLibrary.memset(0, 0, 0); } - } - else { + } else { for (int i=0;i < COUNT;i++) { - jresult = CLibrary.memset(0L, 0, 0L); + long jresult = CLibrary.memset(0L, 0, 0L); } } delta = System.currentTimeMillis() - start; @@ -350,7 +347,7 @@ public String getFunctionName(NativeLibrary library, Method method) { String str = "performance test"; start = System.currentTimeMillis(); for (int i=0;i < COUNT;i++) { - iresult = clib.strlen(str); + int iresult = clib.strlen(str); } delta = System.currentTimeMillis() - start; System.out.println("strlen (JNA interface): " + delta + "ms"); @@ -359,28 +356,28 @@ public String getFunctionName(NativeLibrary library, Method method) { args = new Object[] { str }; start = System.currentTimeMillis(); for (int i=0;i < COUNT;i++) { - iresult = f.invokeInt(args); + int iresult = f.invokeInt(args); } delta = System.currentTimeMillis() - start; System.out.println("strlen (JNA function): " + delta + "ms"); start = System.currentTimeMillis(); for (int i=0;i < COUNT;i++) { - iresult = CLibrary.strlen(str); + int iresult = CLibrary.strlen(str); } delta = System.currentTimeMillis() - start; System.out.println("strlen (JNA direct - String): " + delta + "ms"); start = System.currentTimeMillis(); for (int i=0;i < COUNT;i++) { - iresult = CLibrary.strlen(new NativeString(str).getPointer()); + int iresult = CLibrary.strlen(new NativeString(str).getPointer()); } delta = System.currentTimeMillis() - start; System.out.println("strlen (JNA direct - Pointer): " + delta + "ms"); start = System.currentTimeMillis(); for (int i=0;i < COUNT;i++) { - iresult = CLibrary.strlen(Native.toByteArray(str)); + int iresult = CLibrary.strlen(Native.toByteArray(str)); } delta = System.currentTimeMillis() - start; System.out.println("strlen (JNA direct - byte[]): " + delta + "ms"); @@ -391,7 +388,7 @@ public String getFunctionName(NativeLibrary library, Method method) { b.position(0); b.put(bytes); b.put((byte)0); - iresult = CLibrary.strlen(b); + int iresult = CLibrary.strlen(b); } delta = System.currentTimeMillis() - start; System.out.println("strlen (JNA direct - Buffer): " + delta + "ms"); @@ -410,7 +407,7 @@ public String getFunctionName(NativeLibrary library, Method method) { b.put(str.getBytes()); b.put((byte)0); Native.ffi_call(cif, f.peer, resp, argv); - iresult = b.getInt(4); + int iresult = b.getInt(4); } delta = System.currentTimeMillis() - start; } @@ -428,7 +425,7 @@ public String getFunctionName(NativeLibrary library, Method method) { b.put(str.getBytes()); b.put((byte)0); Native.ffi_call(cif, f.peer, resp, argv); - jresult = b.getLong(8); + long jresult = b.getLong(8); } delta = System.currentTimeMillis() - start; } diff --git a/test/com/sun/jna/PointerBufferTest.java b/test/com/sun/jna/PointerBufferTest.java index d77c32bc63..d539cb2bae 100644 --- a/test/com/sun/jna/PointerBufferTest.java +++ b/test/com/sun/jna/PointerBufferTest.java @@ -19,12 +19,6 @@ import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.Map.Entry; - import junit.framework.TestCase; diff --git a/test/com/sun/jna/PointerTest.java b/test/com/sun/jna/PointerTest.java index 4893a33e23..3bfd217498 100644 --- a/test/com/sun/jna/PointerTest.java +++ b/test/com/sun/jna/PointerTest.java @@ -9,7 +9,7 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -18,16 +18,11 @@ import java.lang.reflect.Modifier; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.Map.Entry; - import junit.framework.TestCase; public class PointerTest extends TestCase { - + private static final String UNICODE = "[\u0444]"; public void testGetNativeLong() { @@ -182,26 +177,26 @@ public void testReadStringArrayNULLElement() { assertNull("Array element should be null", arr[0]); } - private Object defaultArg(Class type) { + private Object defaultArg(Class type) { if (type == boolean.class || type == Boolean.class) return Boolean.FALSE; - if (type == byte.class || type == Byte.class) return new Byte((byte)0); - if (type == char.class || type == Character.class) return new Character((char)0); - if (type == short.class || type == Short.class) return new Short((short)0); - if (type == int.class || type == Integer.class) return new Integer(0); - if (type == long.class || type == Long.class) return new Long(0); - if (type == float.class || type == Float.class) return new Float(0); - if (type == double.class || type == Double.class) return new Double(0); + if (type == byte.class || type == Byte.class) return Byte.valueOf((byte)0); + if (type == char.class || type == Character.class) return Character.valueOf((char)0); + if (type == short.class || type == Short.class) return Short.valueOf((short)0); + if (type == int.class || type == Integer.class) return Integer.valueOf(0); + if (type == long.class || type == Long.class) return Long.valueOf(0L); + if (type == float.class || type == Float.class) return Float.valueOf(0); + if (type == double.class || type == Double.class) return Double.valueOf(0); if (type == NativeLong.class) return new NativeLong(0); return null; } public void testOpaquePointer() throws Exception { Pointer p = Pointer.createConstant(0); - Class cls = p.getClass(); + Class cls = p.getClass(); Method[] methods = cls.getMethods(); for (int i=0;i < methods.length;i++) { Method m = methods[i]; - Class[] argTypes = m.getParameterTypes(); + Class[] argTypes = m.getParameterTypes(); try { Object[] args = new Object[argTypes.length]; for (int arg=0;arg < args.length;arg++) { diff --git a/test/com/sun/jna/ReturnTypesTest.java b/test/com/sun/jna/ReturnTypesTest.java index d07fa7d98e..5c9536a30f 100644 --- a/test/com/sun/jna/ReturnTypesTest.java +++ b/test/com/sun/jna/ReturnTypesTest.java @@ -12,10 +12,8 @@ */ package com.sun.jna; -import java.util.HashMap; +import java.util.Collections; import java.util.List; -import java.util.Map; - import junit.framework.TestCase; import com.sun.jna.ReturnTypesTest.TestLibrary.SimpleStructure; @@ -130,10 +128,7 @@ protected void tearDown() { } public void testReturnObject() throws Exception { - Map options = new HashMap() { { - put(Library.OPTION_ALLOW_OBJECTS, Boolean.TRUE); - }}; - lib = Native.loadLibrary("testlib", TestLibrary.class, options); + lib = Native.loadLibrary("testlib", TestLibrary.class, Collections.singletonMap(Library.OPTION_ALLOW_OBJECTS, Boolean.TRUE)); assertNull("null value not returned", lib.returnObjectArgument(null)); final Object VALUE = new Object() { @Override diff --git a/test/com/sun/jna/StructureFieldOrderInspector.java b/test/com/sun/jna/StructureFieldOrderInspector.java index dd095a0e99..0ad3e58917 100644 --- a/test/com/sun/jna/StructureFieldOrderInspector.java +++ b/test/com/sun/jna/StructureFieldOrderInspector.java @@ -32,7 +32,7 @@ private StructureFieldOrderInspector(){} * @param classDeclaredInSourceTreeToSearch a class who's source tree will be searched for Structure sub types. * @param ignoreConstructorError list of classname prefixes for which to ignore construction errors. */ - public static void batchCheckStructureGetFieldOrder(final Class classDeclaredInSourceTreeToSearch, + public static void batchCheckStructureGetFieldOrder(final Class classDeclaredInSourceTreeToSearch, final List ignoreConstructorError) { final Set> classes = StructureFieldOrderInspector.findSubTypesOfStructure(classDeclaredInSourceTreeToSearch); @@ -62,7 +62,7 @@ public static void batchCheckStructureGetFieldOrder(final Class classDeclaredInS * @param classDeclaredInSourceTreeToSearch a class who's source tree will be searched for Structure sub types. * @param ignoreConstructorError list of classname prefixes for which to ignore construction errors. */ - public static void checkStructureGetFieldOrder(final Class classDeclaredInSourceTreeToSearch, + public static void checkStructureGetFieldOrder(final Class classDeclaredInSourceTreeToSearch, final List ignoreConstructorError) { final Set> classes = StructureFieldOrderInspector.findSubTypesOfStructure(classDeclaredInSourceTreeToSearch); @@ -74,7 +74,7 @@ public static void checkStructureGetFieldOrder(final Class classDeclaredInSource /** * Find all classes that extend {@link Structure}. */ - public static Set> findSubTypesOfStructure(final Class classDeclaredInSourceTreeToSearch) { + public static Set> findSubTypesOfStructure(final Class classDeclaredInSourceTreeToSearch) { // use: http://code.google.com/p/reflections/ @@ -142,9 +142,9 @@ public static void checkMethodGetFieldOrder(final Class str if (!methodGetFieldOrder.isAccessible()) { methodGetFieldOrder.setAccessible(true); } - final List methodCallFieldList; + final List methodCallFieldList; try { - methodCallFieldList = (List) methodGetFieldOrder.invoke(structure); + methodCallFieldList = (List) methodGetFieldOrder.invoke(structure); } catch (IllegalAccessException e) { throw new RuntimeException("Could not invoke getFieldOrder() on Structure sub type: " + structureSubType.getName(), e); } catch (InvocationTargetException e) { @@ -152,7 +152,7 @@ public static void checkMethodGetFieldOrder(final Class str } final Field[] actualFields = structureSubType.getFields(); // include fields from super classes - final List actualFieldNames = new ArrayList(actualFields.length); + final List actualFieldNames = new ArrayList(actualFields.length); for (final Field field : actualFields) { // ignore static fields if (!Modifier.isStatic(field.getModifiers())) { diff --git a/test/com/sun/jna/StructureFieldOrderInspectorTest.java b/test/com/sun/jna/StructureFieldOrderInspectorTest.java index ac70869174..61abc3e041 100644 --- a/test/com/sun/jna/StructureFieldOrderInspectorTest.java +++ b/test/com/sun/jna/StructureFieldOrderInspectorTest.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Properties; import java.util.Set; @@ -19,11 +20,13 @@ public class StructureFieldOrderInspectorTest extends TestCase { private String origPropJNANoSys; + @Override protected void setUp() { origPropJNANoSys = System.getProperty("jna.nosys"); System.setProperty("jna.nosys", "true"); // would be set by ant script, set here for IDE usage } + @Override protected void tearDown() { if (origPropJNANoSys == null) { Properties props = (Properties)System.getProperties().clone(); @@ -56,13 +59,12 @@ public void testCheckMethodGetFieldOrderTagInterface() { private static final class MyStructMissingField extends Structure { - @SuppressWarnings("UnusedDeclaration") public String missingDeclaredField; @Override - protected List getFieldOrder() { + protected List getFieldOrder() { //noinspection unchecked - return Arrays.asList(); + return Collections.emptyList(); } } public void testCheckMethodGetFieldOrderMissingField() throws Exception { @@ -76,7 +78,7 @@ public void testCheckMethodGetFieldOrderMissingField() throws Exception { private static final class MyStructExtraField extends Structure { @Override - protected List getFieldOrder() { + protected List getFieldOrder() { return Arrays.asList("extraField"); } } @@ -91,13 +93,11 @@ public void testCheckMethodGetFieldOrderExtraField() throws Exception { private static final class MyStructStaticField extends Structure { - @SuppressWarnings("UnusedDeclaration") public long instanceField; - @SuppressWarnings("UnusedDeclaration") public static long myStaticField = -1; @Override - protected List getFieldOrder() { + protected List getFieldOrder() { return Arrays.asList("instanceField"); } } @@ -107,11 +107,10 @@ public void testCheckMethodGetFieldOrderStaticField() throws Exception { private static class MyStructSuper extends Structure { - @SuppressWarnings("UnusedDeclaration") public long instanceField; @Override - protected List getFieldOrder() { + protected List getFieldOrder() { return Arrays.asList("instanceField"); } } diff --git a/test/com/sun/jna/StructureTest.java b/test/com/sun/jna/StructureTest.java index 2534ef9a6d..930b245ada 100644 --- a/test/com/sun/jna/StructureTest.java +++ b/test/com/sun/jna/StructureTest.java @@ -875,9 +875,9 @@ public void callback() { s.write(); Pointer func = s.getPointer().getPointer(0); assertNotNull("Callback trampoline not set", func); - Map refs = CallbackReference.callbackMap; + Map refs = CallbackReference.callbackMap; assertTrue("Callback not cached", refs.containsKey(s.cb)); - CallbackReference ref = (CallbackReference)refs.get(s.cb); + CallbackReference ref = refs.get(s.cb); assertEquals("Wrong trampoline", ref.getTrampoline(), func); } @@ -893,8 +893,8 @@ protected List getFieldOrder() { Structure s = new UninitializedArrayFieldStructure(); assertTrue("Invalid size: " + s.size(), s.size() > 0); fail("Uninitialized array field should cause write failure"); - } - catch(IllegalStateException e) { + } catch(IllegalStateException e) { + // expected } } @@ -1965,7 +1965,7 @@ public void testStructureSetIterator() { public void testFFITypeCalculationWithTypeMappedFields() { final TypeMapper mapper = new TypeMapper() { @Override - public FromNativeConverter getFromNativeConverter(Class cls) { + public FromNativeConverter getFromNativeConverter(Class cls) { if (Boolean.class.equals(cls) || boolean.class.equals(cls)) { return new FromNativeConverter() { @@ -1983,7 +1983,7 @@ public Object fromNative(Object nativeValue, FromNativeContext context) { return null; } @Override - public ToNativeConverter getToNativeConverter(Class javaType) { + public ToNativeConverter getToNativeConverter(Class javaType) { if (Boolean.class.equals(javaType) || boolean.class.equals(javaType)) { return new ToNativeConverter() { diff --git a/test/com/sun/jna/TypeMapperTest.java b/test/com/sun/jna/TypeMapperTest.java index 815ad885d6..ce4867cc31 100644 --- a/test/com/sun/jna/TypeMapperTest.java +++ b/test/com/sun/jna/TypeMapperTest.java @@ -8,16 +8,14 @@ * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; import java.util.Arrays; -import java.util.HashMap; +import java.util.Collections; import java.util.List; -import java.util.Map; - import junit.framework.TestCase; //@SuppressWarnings("unused") @@ -35,88 +33,85 @@ public static interface TestLibrary extends Library { public void testBooleanToIntArgumentConversion() { final int MAGIC = 0xABEDCF23; - Map options = new HashMap(); DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addToNativeConverter(Boolean.class, new ToNativeConverter() { + @Override public Object toNative(Object arg, ToNativeContext ctx) { return new Integer(Boolean.TRUE.equals(arg) ? MAGIC : 0); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, options); - assertEquals("Failed to convert Boolean argument to Int", MAGIC, - lib.returnInt32Argument(true)); + TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); + assertEquals("Failed to convert Boolean argument to Int", MAGIC, lib.returnInt32Argument(true)); } public void testStringToIntArgumentConversion() { DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addToNativeConverter(String.class, new ToNativeConverter() { + @Override public Object toNative(Object arg, ToNativeContext ctx) { return Integer.valueOf((String) arg, 16); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); final int MAGIC = 0x7BEDCF23; - TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, options); + TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); assertEquals("Failed to convert String argument to Int", MAGIC, lib.returnInt32Argument(Integer.toHexString(MAGIC))); } public void testStringToWStringArgumentConversion() { DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addToNativeConverter(String.class, new ToNativeConverter() { + @Override public Object toNative(Object arg, ToNativeContext ctx) { return new WString(arg.toString()); } - public Class nativeType() { + @Override + public Class nativeType() { return WString.class; } }); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); final String MAGIC = "magic" + UNICODE; - TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, options); + TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); assertEquals("Failed to convert String argument to WString", new WString(MAGIC), lib.returnWStringArgument(MAGIC)); } public void testCharSequenceToIntArgumentConversion() { DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addToNativeConverter(CharSequence.class, new ToNativeConverter() { + @Override public Object toNative(Object arg, ToNativeContext ctx) { return Integer.valueOf(((CharSequence)arg).toString(), 16); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - final int MAGIC = 0x7BEDCF23; - TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, options); - assertEquals("Failed to convert String argument to Int", MAGIC, - lib.returnInt32Argument(Integer.toHexString(MAGIC))); + TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); + assertEquals("Failed to convert String argument to Int", MAGIC, lib.returnInt32Argument(Integer.toHexString(MAGIC))); } public void testNumberToIntArgumentConversion() { DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addToNativeConverter(Double.class, new ToNativeConverter() { + @Override public Object toNative(Object arg, ToNativeContext ctx) { return new Integer(((Double)arg).intValue()); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - + final int MAGIC = 0x7BEDCF23; - TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, options); + TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); assertEquals("Failed to convert Double argument to Int", MAGIC, lib.returnInt32Argument(new Double(MAGIC))); } @@ -124,21 +119,20 @@ public void testWStringToStringResultConversion() throws Exception { final String MAGIC = "magic" + UNICODE; DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addFromNativeConverter(String.class, new FromNativeConverter() { + @Override public Object fromNative(Object value, FromNativeContext ctx) { if (value == null) { return null; } return value.toString(); } - public Class nativeType() { + @Override + public Class nativeType() { return WString.class; } }); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, options); - assertEquals("Failed to convert WString result to String", MAGIC, - lib.returnWStringArgument(new WString(MAGIC))); + TestLibrary lib = Native.loadLibrary("testlib", TestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); + assertEquals("Failed to convert WString result to String", MAGIC, lib.returnWStringArgument(new WString(MAGIC))); } public static interface BooleanTestLibrary extends Library { @@ -146,71 +140,74 @@ public static interface BooleanTestLibrary extends Library { } public void testIntegerToBooleanResultConversion() throws Exception { final int MAGIC = 0xABEDCF23; - Map options = new HashMap(); DefaultTypeMapper mapper = new DefaultTypeMapper(); mapper.addToNativeConverter(Boolean.class, new ToNativeConverter() { + @Override public Object toNative(Object value, ToNativeContext ctx) { return new Integer(Boolean.TRUE.equals(value) ? MAGIC : 0); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); mapper.addFromNativeConverter(Boolean.class, new FromNativeConverter() { + @Override public Object fromNative(Object value, FromNativeContext context) { return Boolean.valueOf(((Integer) value).intValue() == MAGIC); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - BooleanTestLibrary lib = Native.loadLibrary("testlib", BooleanTestLibrary.class, options); - assertEquals("Failed to convert integer return to boolean TRUE", true, - lib.returnInt32Argument(true)); - assertEquals("Failed to convert integer return to boolean FALSE", false, - lib.returnInt32Argument(false)); + BooleanTestLibrary lib = Native.loadLibrary("testlib", BooleanTestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); + assertEquals("Failed to convert integer return to boolean TRUE", true, lib.returnInt32Argument(true)); + assertEquals("Failed to convert integer return to boolean FALSE", false, lib.returnInt32Argument(false)); } + public static interface StructureTestLibrary extends Library { public static class TestStructure extends Structure { public TestStructure(TypeMapper mapper) { super(mapper); } public boolean data; - protected List getFieldOrder() { - return Arrays.asList(new String[] { "data" }); + @Override + protected List getFieldOrder() { + return Arrays.asList("data"); } } } public void testStructureConversion() throws Exception { DefaultTypeMapper mapper = new DefaultTypeMapper(); TypeConverter converter = new TypeConverter() { + @Override public Object toNative(Object value, ToNativeContext ctx) { return new Integer(Boolean.TRUE.equals(value) ? 1 : 0); } + @Override public Object fromNative(Object value, FromNativeContext context) { return new Boolean(((Integer)value).intValue() == 1); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }; mapper.addTypeConverter(Boolean.class, converter); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - StructureTestLibrary lib = Native.loadLibrary("testlib", StructureTestLibrary.class, options); + Native.loadLibrary("testlib", StructureTestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); StructureTestLibrary.TestStructure s = new StructureTestLibrary.TestStructure(mapper); assertEquals("Wrong native size", 4, s.size()); - + s.data = true; s.write(); assertEquals("Wrong value written", 1, s.getPointer().getInt(0)); - + s.getPointer().setInt(0, 0); s.read(); assertFalse("Wrong value read", s.data); } - + public static enum Enumeration { STATUS_0(0), STATUS_1(1), STATUS_ERROR(-1); private final int code; @@ -230,23 +227,24 @@ public static interface EnumerationTestLibrary extends Library { public void testEnumConversion() throws Exception { DefaultTypeMapper mapper = new DefaultTypeMapper(); TypeConverter converter = new TypeConverter() { + @Override public Object toNative(Object value, ToNativeContext ctx) { return new Integer(((Enumeration)value).getCode()); } + @Override public Object fromNative(Object value, FromNativeContext context) { return Enumeration.fromCode(((Integer)value).intValue()); } - public Class nativeType() { + @Override + public Class nativeType() { return Integer.class; } }; mapper.addTypeConverter(Enumeration.class, converter); - Map options = new HashMap(); - options.put(Library.OPTION_TYPE_MAPPER, mapper); - EnumerationTestLibrary lib = Native.loadLibrary("testlib", EnumerationTestLibrary.class, options); + EnumerationTestLibrary lib = Native.loadLibrary("testlib", EnumerationTestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); assertEquals("Enumeration improperly converted", Enumeration.STATUS_1, lib.returnInt32Argument(Enumeration.STATUS_1)); } - + public static void main(String[] args) { junit.textui.TestRunner.run(TypeMapperTest.class); } diff --git a/test/com/sun/jna/VarArgsTest.java b/test/com/sun/jna/VarArgsTest.java index 043b6a0d53..e68adf7fc5 100644 --- a/test/com/sun/jna/VarArgsTest.java +++ b/test/com/sun/jna/VarArgsTest.java @@ -25,8 +25,8 @@ public static interface TestLibrary extends Library { public static class TestStructure extends Structure { public int magic = 0; @Override - protected List getFieldOrder() { - return Arrays.asList(new String[] { "magic" }); + protected List getFieldOrder() { + return Arrays.asList("magic"); } } public int addInt32VarArgs(String fmt, Number... args); diff --git a/test/com/sun/jna/WebStartTest.java b/test/com/sun/jna/WebStartTest.java index 62c9d013d2..9c45d4d297 100644 --- a/test/com/sun/jna/WebStartTest.java +++ b/test/com/sun/jna/WebStartTest.java @@ -1,14 +1,14 @@ /* Copyright (c) 2009-2012 Timothy Wall, All Rights Reserved - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. */ package com.sun.jna; @@ -43,7 +43,7 @@ * Works under OSX, windows, and linux. */ public class WebStartTest extends TestCase implements Paths { - + // Provide a policy file for unsigned jars // Unfortunately this does not allow native libraries private static final String POLICY = @@ -51,7 +51,7 @@ public class WebStartTest extends TestCase implements Paths { + " permission java.security.AllPermission;\n" + "};"; - private static final String JNLP = + private static final String JNLP = "\n" + "\n" + " \n" @@ -135,91 +135,95 @@ private void runTestUnderWebStart(String testClass, String testMethod) throws Ex String codebase = new File(dir, "jws").toURI().toURL().toString(); ServerSocket s = new ServerSocket(0); - s.setSoTimeout(SOCKET_TIMEOUT); - int port = s.getLocalPort(); + try { + s.setSoTimeout(SOCKET_TIMEOUT); + int port = s.getLocalPort(); - File jnlp = File.createTempFile(getName(), ".jnlp"); - String contents = JNLP.replace("{CLASS}", testClass); - contents = contents.replace("{METHOD}", testMethod); - contents = contents.replace("{CODEBASE}", codebase); - contents = contents.replace("{JNLP_FILE}", jnlp.toURI().toURL().toString()); - contents = contents.replace("{PORT}", String.valueOf(port)); - contents = contents.replace("{CLOVER}", - USING_CLOVER ? "" : ""); + File jnlp = File.createTempFile(getName(), ".jnlp"); + String contents = JNLP.replace("{CLASS}", testClass); + contents = contents.replace("{METHOD}", testMethod); + contents = contents.replace("{CODEBASE}", codebase); + contents = contents.replace("{JNLP_FILE}", jnlp.toURI().toURL().toString()); + contents = contents.replace("{PORT}", String.valueOf(port)); + contents = contents.replace("{CLOVER}", USING_CLOVER ? "" : ""); - try { - OutputStream os = new FileOutputStream(jnlp); - os.write(contents.getBytes()); - os.close(); - String path = findJWS(); - String[] cmd = { - path, - Platform.isWindows() ? "-J-Ddummy" : (Platform.is64Bit() ? "-J-d64" : "-J-d32"), - "-Xnosplash", - "-wait", - jnlp.toURI().toURL().toString(), - }; - final Process p = Runtime.getRuntime().exec(cmd); - final StringBuffer output = new StringBuffer(); - class SocketHandler extends Thread { - private InputStream is; - private StringBuffer sb; - public SocketHandler(Socket s, StringBuffer b) throws IOException { - this.is = s.getInputStream(); - this.sb = b; - } - public void run() { - byte[] buf = new byte[256]; - while (true) { - try { - int count = is.read(buf, 0, buf.length); - if (count == -1) break; - if (count == 0) { - try { sleep(1); } catch(InterruptedException e) { } + try { + OutputStream os = new FileOutputStream(jnlp); + os.write(contents.getBytes()); + os.close(); + String path = findJWS(); + String[] cmd = { + path, + Platform.isWindows() ? "-J-Ddummy" : (Platform.is64Bit() ? "-J-d64" : "-J-d32"), + "-Xnosplash", + "-wait", + jnlp.toURI().toURL().toString(), + }; + final Process p = Runtime.getRuntime().exec(cmd); + final StringBuffer output = new StringBuffer(); + class SocketHandler extends Thread { + private InputStream is; + private StringBuffer sb; + public SocketHandler(Socket s, StringBuffer b) throws IOException { + this.is = s.getInputStream(); + this.sb = b; + } + @Override + public void run() { + byte[] buf = new byte[256]; + while (true) { + try { + int count = is.read(buf, 0, buf.length); + if (count == -1) break; + if (count == 0) { + try { sleep(1); } catch(InterruptedException e) { } + } + else { + sb.append(new String(buf, 0, count)); + } } - else { - sb.append(new String(buf, 0, count)); + catch(IOException e) { + showMessage("read error: " + e.toString()); } } - catch(IOException e) { - showMessage("read error: " + e.toString()); - } + try { is.close(); } catch(IOException e) { } } - try { is.close(); } catch(IOException e) { } } - } - - Thread out = null; - try { - out = new SocketHandler(s.accept(), output); - out.start(); - } - catch(SocketTimeoutException e) { - try { - p.exitValue(); + + Thread out = null; + try { + out = new SocketHandler(s.accept(), output); + out.start(); } - catch(IllegalThreadStateException e2) { - p.destroy(); - throw new Error("JWS Timed out"); + catch(SocketTimeoutException e) { + try { + p.exitValue(); + } + catch(IllegalThreadStateException e2) { + p.destroy(); + throw new Error("JWS Timed out"); + } } - } - p.waitFor(); - if (out != null) { - out.join(); - } - - int code = p.exitValue(); - String error = output.toString(); - if (code != 0 || !"".equals(error)) { - if (code == 1 - || error.indexOf("AssertionFailedError") != -1) { - fail("JWS FAIL: " + error); + p.waitFor(); + if (out != null) { + out.join(); + } + + int code = p.exitValue(); + String error = output.toString(); + if (code != 0 || !"".equals(error)) { + if (code == 1 + || error.indexOf("AssertionFailedError") != -1) { + fail("JWS FAIL: " + error); + } + throw new Error("JWS ERROR: " + error); } - throw new Error("JWS ERROR: " + error); } - } - finally { - jnlp.delete(); + finally { + jnlp.delete(); + } + } finally { + s.close(); } } @@ -261,7 +265,7 @@ else if (getName().equals("testDetectError")) { runTestUnderWebStart(getClass().getName(), getName()); } } - + public interface FolderInfo extends com.sun.jna.win32.StdCallLibrary { int MAX_PATH = 260; int SHGFP_TYPE_CURRENT = 0; @@ -276,7 +280,7 @@ private String findJWS() throws IOException { String JAVA_HOME = System.getProperty("java.home"); String BIN = new File(JAVA_HOME, "/bin").getAbsolutePath(); File javaws = new File(BIN, "javaws" + (Platform.isWindows()?".exe":"")); - List tried = new ArrayList(); + List tried = new ArrayList(); tried.add(javaws); if (!javaws.exists()) { // NOTE: OSX puts javaws somewhere else entirely @@ -311,7 +315,7 @@ private String findJWS() throws IOException { } // TODO: find some way of querying the current VM for the deployment - // properties path + // properties path private File findDeploymentProperties() { String path = System.getProperty("user.home"); File deployment; @@ -356,10 +360,11 @@ else if (Platform.isMac()) { return new File(deployment, "deployment.properties"); } - private static final String POLICY_KEY = + private static final String POLICY_KEY = "deployment.user.security.policy"; private static final String CERTS_KEY = "deployment.user.security.trusted.certs"; + @Override public void runBare() throws Throwable { if (runningWebStart()) { super.runBare(); @@ -406,12 +411,11 @@ private static Throwable runTestCaseTest(String testClass, String method, int po TestResult result = new TestResult(); test.run(result); if (result.failureCount() != 0) { - Enumeration e = result.failures(); - return ((TestFailure)e.nextElement()).thrownException(); - } - else if (result.errorCount() != 0) { - Enumeration e = result.errors(); - return ((TestFailure)e.nextElement()).thrownException(); + Enumeration e = result.failures(); + return e.nextElement().thrownException(); + } else if (result.errorCount() != 0) { + Enumeration e = result.errors(); + return e.nextElement().thrownException(); } return null; } diff --git a/test/com/sun/jna/win32/W32APIMapperTest.java b/test/com/sun/jna/win32/W32APIMapperTest.java index cb56cc1208..705b7e96f1 100644 --- a/test/com/sun/jna/win32/W32APIMapperTest.java +++ b/test/com/sun/jna/win32/W32APIMapperTest.java @@ -33,13 +33,14 @@ public static void main(String[] args) { public interface UnicodeLibrary extends Library { public static class TestStructure extends Structure { + public static final List FIELDS = createFieldsOrder("string", "string2", "bool", "bool2"); public String string; public String string2; public boolean bool; public boolean bool2; @Override - protected List getFieldOrder() { - return Arrays.asList(new String[] { "string", "string2", "bool", "bool2" }); + protected List getFieldOrder() { + return FIELDS; } } String returnWStringArgument(String arg); @@ -48,13 +49,14 @@ protected List getFieldOrder() { } public interface ASCIILibrary extends Library { public static class TestStructure extends Structure { + public static final List FIELDS = Arrays.asList("string", "string2", "bool", "bool2"); public String string; public String string2; public boolean bool; public boolean bool2; @Override - protected List getFieldOrder() { - return Arrays.asList(new String[] { "string", "string2", "bool", "bool2" }); + protected List getFieldOrder() { + return FIELDS; } } String returnStringArgument(String arg); diff --git a/test/com/sun/jna/win32/W32StdCallTest.java b/test/com/sun/jna/win32/W32StdCallTest.java index bfd4198062..bb3b1d395d 100644 --- a/test/com/sun/jna/win32/W32StdCallTest.java +++ b/test/com/sun/jna/win32/W32StdCallTest.java @@ -13,8 +13,7 @@ package com.sun.jna.win32; import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; +import java.util.Collections; import java.util.List; import junit.framework.TestCase; @@ -33,22 +32,24 @@ public class W32StdCallTest extends TestCase { public static interface TestLibrary extends StdCallLibrary { public static class Inner extends Structure { + public static final List FIELDS = createFieldsOrder("value"); public double value; @Override - protected List getFieldOrder() { - return Arrays.asList(new String[] { "value" }); + protected List getFieldOrder() { + return FIELDS; } } public static class TestStructure extends Structure { public static class ByValue extends TestStructure implements Structure.ByValue { } + public static final List FIELDS = createFieldsOrder("c", "s", "i", "j", "inner"); public byte c; public short s; public int i; public long j; public Inner inner; @Override - protected List getFieldOrder() { - return Arrays.asList(new String[] { "c", "s", "i", "j", "inner" }); + protected List getFieldOrder() { + return FIELDS; } } int returnInt32ArgumentStdCall(int arg); @@ -79,11 +80,8 @@ public static void main(java.lang.String[] argList) { @Override protected void setUp() { - testlib = Native.loadLibrary("testlib", TestLibrary.class, new HashMap() { - { - put(Library.OPTION_FUNCTION_MAPPER, StdCallLibrary.FUNCTION_MAPPER); - } - }); + testlib = Native.loadLibrary("testlib", TestLibrary.class, + Collections.singletonMap(Library.OPTION_FUNCTION_MAPPER, StdCallLibrary.FUNCTION_MAPPER)); } @Override @@ -96,23 +94,15 @@ public void testFunctionMapper() throws Exception { NativeLibrary lib = NativeLibrary.getInstance("testlib"); Method[] methods = { - TestLibrary.class.getMethod("returnInt32ArgumentStdCall", - new Class[] { int.class }), - TestLibrary.class.getMethod("returnStructureByValueArgumentStdCall", - new Class[] { - TestLibrary.TestStructure.ByValue.class - }), - TestLibrary.class.getMethod("callInt32StdCallCallback", - new Class[] { - TestLibrary.Int32Callback.class, - int.class, int.class, - }), + TestLibrary.class.getMethod("returnInt32ArgumentStdCall", int.class), + TestLibrary.class.getMethod("returnStructureByValueArgumentStdCall", TestLibrary.TestStructure.ByValue.class), + TestLibrary.class.getMethod("callInt32StdCallCallback", TestLibrary.Int32Callback.class, int.class, int.class) }; - for (int i=0;i < methods.length;i++) { - String name = mapper.getFunctionName(lib, methods[i]); + for (Method m : methods) { + String name = mapper.getFunctionName(lib, m); assertTrue("Function name not decorated for method " - + methods[i].getName() + + m.getName() + ": " + name, name.indexOf("@") != -1); assertEquals("Wrong name in mapped function", name, lib.getFunction(name, StdCallLibrary.STDCALL_CONVENTION).getName()); diff --git a/test/com/sun/jna/wince/CoreDLLTest.java b/test/com/sun/jna/wince/CoreDLLTest.java index b1c0ba87c9..959816e061 100644 --- a/test/com/sun/jna/wince/CoreDLLTest.java +++ b/test/com/sun/jna/wince/CoreDLLTest.java @@ -16,7 +16,6 @@ import com.sun.jna.*; import com.sun.jna.ptr.*; import com.sun.jna.win32.*; -import java.util.Arrays; import java.util.List; public class CoreDLLTest extends TestCase { @@ -28,18 +27,24 @@ public interface CoreDLL extends StdCallLibrary { CoreDLL INSTANCE = Native.loadLibrary("coredll", CoreDLL.class, W32APIOptions.UNICODE_OPTIONS); public static class SECURITY_ATTRIBUTES extends Structure { + public static final List FIELDS = createFieldsOrder("dwLength", "lpSecurityDescriptor", "bInheritHandle"); public int dwLength; public Pointer lpSecurityDescriptor; public boolean bInheritHandle; public SECURITY_ATTRIBUTES() { dwLength = size(); } - protected List getFieldOrder() { - return Arrays.asList(new String[] { "dwLength", "lpSecurityDescriptor", "bInheritHandle" }); + @Override + protected List getFieldOrder() { + return FIELDS; } } public static class STARTUPINFO extends Structure { + public static final List FIELDS = createFieldsOrder( + "cb", "lpReserved", "lpDesktop", "lpTitle", "dwX", "dwY", "dwXSize", "dwYSize", + "dwXCountChars", "dwYCountChars", "dwFillAttribute", "dwFlags", "wShowWindow", + "cbReserved2", "lpReserved2", "hStdInput", "hStdOutput", "hStdError"); public int cb; public String lpReserved; public String lpDesktop; @@ -61,11 +66,13 @@ public static class STARTUPINFO extends Structure { public STARTUPINFO() { cb = size(); } - protected List getFieldOrder() { - return Arrays.asList(new String[] { "cb", "lpReserved", "lpDesktop", "lpTitle", "dwX", "dwY", "dwXSize", "dwYSize", "dwXCountChars", "dwYCountChars", "dwFillAttribute", "dwFlags", "wShowWindow", "cbReserved2", "lpReserved2", "hStdInput", "hStdOutput", "hStdError" }); + @Override + protected List getFieldOrder() { + return FIELDS; } } public static class PROCESS_INFORMATION extends Structure { + public static final List FIELDS = createFieldsOrder("hProcess", "hThread", "dwProcessId", "dwThreadId"); public Pointer hProcess; public Pointer hThread; public int dwProcessId; @@ -74,20 +81,22 @@ public static class PROCESS_INFORMATION extends Structure { public static class ByReference extends PROCESS_INFORMATION implements Structure.ByReference { public ByReference() { } - + public ByReference(Pointer memory) { super(memory); } } - + public PROCESS_INFORMATION() { + super(); } - + public PROCESS_INFORMATION(Pointer memory) { super(memory); } - protected List getFieldOrder() { - return Arrays.asList(new String[] { "hProcess", "hThread", "dwProcessId", "dwThreadId" }); + @Override + protected List getFieldOrder() { + return FIELDS; } } @@ -108,7 +117,4 @@ public void testCreateProcess() { null, null, processInformation); assertTrue("Process launch failed", status); } -} - - - +} \ No newline at end of file