Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* Copyright (c) 2007-2015 Timothy Wall, All Rights Reserved
*
* The contents of this file is dual-licensed under 2
* alternative Open Source/Free licenses: LGPL 2.1 or later and
* Apache License 2.0. (starting with JNA version 4.0.0).
*
* You can freely decide which license you want to apply to
* the project.
*
* You may obtain a copy of the LGPL License at:
*
* http://www.gnu.org/licenses/licenses.html
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "LGPL2.1".
*
* You may obtain a copy of the Apache License at:
*
* http://www.apache.org/licenses/
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "AL2.0".
*/
package com.sun.jna;
import java.awt.Component;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Window;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
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;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.WeakHashMap;
import com.sun.jna.Callback.UncaughtExceptionHandler;
import com.sun.jna.Structure.FFIType;
import java.util.logging.Level;
import java.util.logging.Logger;
/** Provides generation of invocation plumbing for a defined native
* library interface. Also provides various utilities for native operations.
*
* {@link #getTypeMapper} and {@link #getStructureAlignment} are provided
* to avoid having to explicitly pass these parameters to {@link Structure}s,
* which would require every {@link Structure} which requires custom mapping
* or alignment to define a constructor and pass parameters to the superclass.
* To avoid lots of boilerplate, the base {@link Structure} constructor
* figures out these properties based on its enclosing interface.
*
*
Library Loading
*
When JNA classes are loaded, the native shared library (jnidispatch) is
* loaded as well. An attempt is made to load it from the any paths defined
* in jna.boot.library.path (if defined), then the system library
* path using {@link System#loadLibrary}, unless jna.nosys=true.
* If not found, the appropriate library will be extracted from the class path
* (into a temporary directory if found within a jar file) and loaded from
* there, unless jna.noclasspath=true. If your system has
* additional security constraints regarding execution or load of files
* (SELinux, for example), you should probably install the native library in
* an accessible location and configure your system accordingly, rather than
* relying on JNA to extract the library from its own jar file.
*
To avoid the automatic unpacking (in situations where you want to force a
* failure if the JNA native library is not properly installed on the system),
* set the system property jna.nounpack=true.
*
*
While this class and its corresponding native library are loaded, the
* system property jna.loaded will be set. The property will be
* cleared when native support has been unloaded (i.e. the Native class and
* its underlying native support has been GC'd).
*
NOTE: all native functions are provided within this class to ensure that
* all other JNA-provided classes and objects are GC'd and/or
* finalized/disposed before this class is disposed and/or removed from
* memory (most notably Memory and any other class which by default frees its
* resources in a finalizer).
*
*
Native Library Loading
* Native libraries loaded via {@link #load(Class)} may be found in
* several locations.
* @see Library
* @author Todd Fast, [email protected]
* @author [email protected]
*/
public final class Native implements Version {
private static final Logger LOG = Logger.getLogger(Native.class.getName());
public static final Charset DEFAULT_CHARSET = Charset.defaultCharset();
public static final String DEFAULT_ENCODING = Native.DEFAULT_CHARSET.name();
public static final boolean DEBUG_LOAD = Boolean.getBoolean("jna.debug_load");
public static final boolean DEBUG_JNA_LOAD = Boolean.getBoolean("jna.debug_load.jna");
private final static Level DEBUG_JNA_LOAD_LEVEL = DEBUG_JNA_LOAD ? Level.INFO : Level.FINE;
// Used by tests, do not remove
static String jnidispatchPath = null;
private static final Map, Map> typeOptions = Collections.synchronizedMap(new WeakHashMap, Map>());
private static final Map, Reference>> libraries = Collections.synchronizedMap(new WeakHashMap, Reference>>());
private static final String _OPTION_ENCLOSING_LIBRARY = "enclosing-library";
private static final UncaughtExceptionHandler DEFAULT_HANDLER =
new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Callback c, Throwable e) {
LOG.log(Level.WARNING, "JNA: Callback " + c + " threw the following exception", e);
}
};
private static UncaughtExceptionHandler callbackExceptionHandler = DEFAULT_HANDLER;
/** The size of a native pointer (void*) on the current
* platform, in bytes.
*/
public static final int POINTER_SIZE;
/** Size of a native long type, in bytes. */
public static final int LONG_SIZE;
/** Size of a native wchar_t type, in bytes. */
public static final int WCHAR_SIZE;
/** Size of a native size_t type, in bytes. */
public static final int SIZE_T_SIZE;
/** Size of a native bool type (C99 and later), in bytes. */
public static final int BOOL_SIZE;
/** Size of a native long double type (C99 and later), in bytes. */
public static final int LONG_DOUBLE_SIZE;
private static final int TYPE_VOIDP = 0;
private static final int TYPE_LONG = 1;
private static final int TYPE_WCHAR_T = 2;
private static final int TYPE_SIZE_T = 3;
private static final int TYPE_BOOL = 4;
private static final int TYPE_LONG_DOUBLE = 5;
static final int MAX_ALIGNMENT;
static final int MAX_PADDING;
/**
* Version string must have the structure ..
* a bugfix change in the native code increments revision, the minor is
* incremented for backwards compatible changes and the major version
* is changed for backwards incompatbile changes.
*
* @param expectedVersion
* @param nativeVersion
* @return true if nativeVersion describes a version compatible to expectedVersion
*/
static boolean isCompatibleVersion(String expectedVersion, String nativeVersion) {
String[] expectedVersionParts = expectedVersion.split("\\.");
String[] nativeVersionParts = nativeVersion.split("\\.");
if(expectedVersionParts.length < 3 || nativeVersionParts.length < 3) {
return false;
}
int expectedMajor = Integer.parseInt(expectedVersionParts[0]);
int nativeMajor = Integer.parseInt(nativeVersionParts[0]);
int expectedMinor = Integer.parseInt(expectedVersionParts[1]);
int nativeMinor = Integer.parseInt(nativeVersionParts[1]);
if(expectedMajor != nativeMajor) {
return false;
}
if(expectedMinor > nativeMinor) {
return false;
}
return true;
}
static {
loadNativeDispatchLibrary();
if (! isCompatibleVersion(VERSION_NATIVE, getNativeVersion())) {
String LS = System.getProperty("line.separator");
throw new Error(LS + LS
+ "There is an incompatible JNA native library installed on this system" + LS
+ "Expected: " + VERSION_NATIVE + LS
+ "Found: " + getNativeVersion() + LS
+ (jnidispatchPath != null
? "(at " + jnidispatchPath + ")" : System.getProperty("java.library.path"))
+ "." + LS
+ "To resolve this issue you may do one of the following:" + LS
+ " - remove or uninstall the offending library" + LS
+ " - set the system property jna.nosys=true" + LS
+ " - set jna.boot.library.path to include the path to the version of the " + LS
+ " jnidispatch library included with the JNA jar file you are using" + LS);
}
POINTER_SIZE = sizeof(TYPE_VOIDP);
LONG_SIZE = sizeof(TYPE_LONG);
WCHAR_SIZE = sizeof(TYPE_WCHAR_T);
SIZE_T_SIZE = sizeof(TYPE_SIZE_T);
BOOL_SIZE = sizeof(TYPE_BOOL);
LONG_DOUBLE_SIZE = sizeof(TYPE_LONG_DOUBLE);
// Perform initialization of other JNA classes until *after*
// initializing the above final fields
initIDs();
if (Boolean.getBoolean("jna.protected")) {
setProtected(true);
}
MAX_ALIGNMENT = Platform.isSPARC() || Platform.isWindows()
|| (Platform.isLinux() && (Platform.isARM() || Platform.isPPC() || Platform.isMIPS()))
|| Platform.isAIX()
|| (Platform.isAndroid() && !Platform.isIntel())
? 8 : LONG_SIZE;
MAX_PADDING = (Platform.isMac() && Platform.isPPC()) ? 8 : MAX_ALIGNMENT;
System.setProperty("jna.loaded", "true");
}
/** Force a dispose when the Native class is GC'd. */
private static final Object finalizer = new Object() {
@Override
protected void finalize() throws Throwable {
dispose();
super.finalize();
}
};
/** Properly dispose of JNA functionality.
Called when this class is finalized and also from JNI when
JNA's native shared library is unloaded.
*/
private static void dispose() {
CallbackReference.disposeAll();
Memory.disposeAll();
NativeLibrary.disposeAll();
unregisterAll();
jnidispatchPath = null;
System.setProperty("jna.loaded", "false");
}
/** Remove any automatically unpacked native library.
This will fail on windows, which disallows removal of any file that is
still in use, so an alternative is required in that case. Mark
the file that could not be deleted, and attempt to delete any
temporaries on next startup.
Do NOT force the class loader to unload the native library, since
that introduces issues with cleaning up any extant JNA bits
(e.g. Memory) which may still need use of the library before shutdown.
*/
static boolean deleteLibrary(File lib) {
if (lib.delete()) {
return true;
}
// Couldn't delete it, mark for later deletion
markTemporaryFile(lib);
return false;
}
private Native() { }
private static native void initIDs();
/** Set whether native memory accesses are protected from invalid
* accesses. This should only be set true when testing or debugging,
* and should not be considered reliable or robust for applications
* where JNA native calls are occurring on multiple threads.
* Protected mode will be automatically set if the
* system property jna.protected has a value of "true"
* when the JNA library is first loaded.
* If not supported by the underlying platform, this setting will
* have no effect.
* NOTE: On platforms which support signals (non-Windows), JNA uses
* signals to trap errors. This may interfere with the JVM's own use of
* signals. When protected mode is enabled, you should make use of the
* jsig library, if available (see Signal Chaining).
* In short, set the environment variable LD_PRELOAD to the
* path to libjsig.so in your JRE lib directory
* (usually ${java.home}/lib/${os.arch}/libjsig.so) before launching your
* Java application.
*/
public static synchronized native void setProtected(boolean enable);
/** Returns whether protection is enabled. Check the result of this method
* after calling {@link #setProtected setProtected(true)} to determine
* if this platform supports protecting memory accesses.
*/
public static synchronized native boolean isProtected();
/** Utility method to get the native window ID for a Java {@link Window}
* as a long value.
* This method is primarily for X11-based systems, which use an opaque
* XID (usually long int) to identify windows.
* @throws HeadlessException if the current VM is running headless
*/
public static long getWindowID(Window w) throws HeadlessException {
return AWT.getWindowID(w);
}
/** Utility method to get the native window ID for a heavyweight Java
* {@link Component} as a long value.
* This method is primarily for X11-based systems, which use an opaque
* XID (usually long int) to identify windows.
* @throws HeadlessException if the current VM is running headless
*/
public static long getComponentID(Component c) throws HeadlessException {
return AWT.getComponentID(c);
}
/** Utility method to get the native window pointer for a Java
* {@link Window} as a {@link Pointer} value. This method is primarily for
* w32, which uses the HANDLE type (actually
* void *) to identify windows.
* @throws HeadlessException if the current VM is running headless
*/
public static Pointer getWindowPointer(Window w) throws HeadlessException {
return new Pointer(AWT.getWindowID(w));
}
/** Utility method to get the native window pointer for a heavyweight Java
* {@link Component} as a {@link Pointer} value. This method is primarily
* for w32, which uses the HWND type (actually
* void *) to identify windows.
* @throws HeadlessException if the current VM is running headless
*/
public static Pointer getComponentPointer(Component c) throws HeadlessException {
return new Pointer(AWT.getComponentID(c));
}
static native long getWindowHandle0(Component c);
/** Convert a direct {@link Buffer} into a {@link Pointer}.
* @throws IllegalArgumentException if the buffer is not direct.
*/
public static Pointer getDirectBufferPointer(Buffer b) {
long peer = _getDirectBufferPointer(b);
return peer == 0 ? null : new Pointer(peer);
}
private static native long _getDirectBufferPointer(Buffer b);
/**
* Gets the charset belonging to the given {@code encoding}.
* @param encoding The encoding - if {@code null} then the default platform
* encoding is used.
* @return The charset belonging to the given {@code encoding} or the platform default.
* Never {@code null}.
*/
private static Charset getCharset(String encoding) {
Charset charset = null;
if (encoding != null) {
try {
charset = Charset.forName(encoding);
}
catch(IllegalCharsetNameException e) {
LOG.log(Level.WARNING, "JNA Warning: Encoding ''{0}'' is unsupported ({1})",
new Object[]{encoding, e.getMessage()});
}
catch(UnsupportedCharsetException e) {
LOG.log(Level.WARNING, "JNA Warning: Encoding ''{0}'' is unsupported ({1})",
new Object[]{encoding, e.getMessage()});
}
}
if (charset == null) {
LOG.log(Level.WARNING, "JNA Warning: Using fallback encoding {0}", Native.DEFAULT_CHARSET);
charset = Native.DEFAULT_CHARSET;
}
return charset;
}
/**
* Obtain a Java String from the given native byte array. If there is
* no NUL terminator, the String will comprise the entire array. The
* encoding is obtained from {@link #getDefaultStringEncoding()}.
*
* @param buf The buffer containing the encoded bytes
* @see #toString(byte[], String)
*/
public static String toString(byte[] buf) {
return toString(buf, getDefaultStringEncoding());
}
/**
* Obtain a Java String from the given native byte array, using the given
* encoding. If there is no NUL terminator, the String will comprise the
* entire array.
*
*
Usage note: This function assumes, that {@code buf}
* holds a {@code char} array. This means only single-byte encodings are
* supported.
*
* @param buf The buffer containing the encoded bytes. Must not be {@code null}.
* @param encoding The encoding name - if {@code null} then the platform
* default encoding will be used
*/
public static String toString(byte[] buf, String encoding) {
return Native.toString(buf, Native.getCharset(encoding));
}
/**
* Obtain a Java String from the given native byte array, using the given
* encoding. If there is no NUL terminator, the String will comprise the
* entire array.
*
*
Usage note: This function assumes, that {@code buf}
* holds a {@code char} array. This means only single-byte encodings are
* supported.
*
* @param buf The buffer containing the encoded bytes. Must not be {@code null}.
* @param charset The charset to decode {@code buf}. Must not be {@code null}.
*/
public static String toString(byte[] buf, Charset charset) {
int len = buf.length;
// find out the effective length
for (int index = 0; index < len; index++) {
if (buf[index] == 0) {
len = index;
break;
}
}
if (len == 0) {
return "";
}
return new String(buf, 0, len, charset);
}
/**
* Obtain a Java String from the given native wchar_t array. If there is
* no NUL terminator, the String will comprise the entire array.
*
* @param buf The buffer containing the characters
*/
public static String toString(char[] buf) {
int len = buf.length;
for (int index = 0; index < len; index++) {
if (buf[index] == '\0') {
len = index;
break;
}
}
if (len == 0) {
return "";
} else {
return new String(buf, 0, len);
}
}
/**
* Converts a "list" of strings each null terminated
* into a {@link List} of {@link String} values. The end of the
* list is signaled by an extra NULL value at the end or by the
* end of the buffer.
* @param buf The buffer containing the strings
* @return A {@link List} of all the strings in the buffer
* @see #toStringList(char[], int, int)
*/
public static List toStringList(char[] buf) {
return toStringList(buf, 0, buf.length);
}
/**
* Converts a "list" of strings each null terminated
* into a {@link List} of {@link String} values. The end of the
* list is signaled by an extra NULL value at the end or by the
* end of the data.
* @param buf The buffer containing the strings
* @param offset Offset to start parsing
* @param len The total characters to parse
* @return A {@link List} of all the strings in the buffer
*/
public static List toStringList(char[] buf, int offset, int len) {
List list = new ArrayList();
int lastPos = offset;
int maxPos = offset + len;
for (int curPos = offset; curPos < maxPos; curPos++) {
if (buf[curPos] != '\0') {
continue;
}
// check if found the extra null terminator
if (lastPos == curPos) {
return list;
}
String value = new String(buf, lastPos, curPos - lastPos);
list.add(value);
lastPos = curPos + 1; // skip the '\0'
}
// This point is reached if there is no double null terminator
if (lastPos < maxPos) {
String value = new String(buf, lastPos, maxPos - lastPos);
list.add(value);
}
return list;
}
/** Map a library interface to the current process, providing
* the explicit interface class.
* Native libraries loaded via this method may be found in
* several locations.
* @param Type of expected wrapper
* @param interfaceClass The implementation wrapper interface
* @return an instance of the requested interface, mapped to the current
* process.
* @throws UnsatisfiedLinkError if the library cannot be found or
* dependent libraries are missing.
*/
public static T load(Class interfaceClass) {
return load(null, interfaceClass);
}
/** Map a library interface to the current process, providing
* the explicit interface class. Any options provided for the library are
* cached and associated with the library and any of its defined
* structures and/or functions.
* Native libraries loaded via this method may be found in
* several locations.
* @param Type of expected wrapper
* @param interfaceClass The implementation wrapper interface
* @param options Map of library options
* @return an instance of the requested interface, mapped to the current
* process.
* @throws UnsatisfiedLinkError if the library cannot be found or
* dependent libraries are missing.
* @see #load(String, Class, Map)
*/
public static T load(Class interfaceClass, Map options) {
return load(null, interfaceClass, options);
}
/** Map a library interface to the given shared library, providing
* the explicit interface class.
* If name is null, attempts to map onto the current process.
* Native libraries loaded via this method may be found in
* several locations.
* @param Type of expected wrapper
* @param name Library base name
* @param interfaceClass The implementation wrapper interface
* @return an instance of the requested interface, mapped to the indicated
* native library.
* @throws UnsatisfiedLinkError if the library cannot be found or
* dependent libraries are missing.
* @see #load(String, Class, Map)
*/
public static T load(String name, Class interfaceClass) {
return load(name, interfaceClass, Collections.emptyMap());
}
/** Load a library interface from the given shared library, providing
* the explicit interface class and a map of options for the library.
* If no library options are detected the map is interpreted as a map
* of Java method names to native function names.
* If name is null, attempts to map onto the current process.
* Native libraries loaded via this method may be found in
* several locations.
* @param Type of expected wrapper
* @param name Library base name
* @param interfaceClass The implementation wrapper interface
* @param options Map of library options
* @return an instance of the requested interface, mapped to the indicated
* native library.
* @throws UnsatisfiedLinkError if the library cannot be found or
* dependent libraries are missing.
*/
public static T load(String name, Class interfaceClass, Map options) {
if (!Library.class.isAssignableFrom(interfaceClass)) {
// Maybe still possible if the caller is not using generics?
throw new IllegalArgumentException("Interface (" + interfaceClass.getSimpleName() + ")"
+ " of library=" + name + " does not extend " + Library.class.getSimpleName());
}
Library.Handler handler = new Library.Handler(name, interfaceClass, options);
ClassLoader loader = interfaceClass.getClassLoader();
Object proxy = Proxy.newProxyInstance(loader, new Class[] {interfaceClass}, handler);
cacheOptions(interfaceClass, options, proxy);
return interfaceClass.cast(proxy);
}
/**
* Provided for improved compatibility between JNA 4.X and 5.X
*
* @see Native#load(java.lang.Class)
*/
@Deprecated
public static T loadLibrary(Class interfaceClass) {
return loadLibrary(null, interfaceClass);
}
/**
* Provided for improved compatibility between JNA 4.X and 5.X
*
* @see Native#load(java.lang.Class, java.util.Map)
*/
@Deprecated
public static T loadLibrary(Class interfaceClass, Map options) {
return loadLibrary(null, interfaceClass, options);
}
/**
* Provided for improved compatibility between JNA 4.X and 5.X
*
* @see Native#load(java.lang.String, java.lang.Class)
*/
@Deprecated
public static T loadLibrary(String name, Class interfaceClass) {
return loadLibrary(name, interfaceClass, Collections.emptyMap());
}
/**
* Provided for improved compatibility between JNA 4.X and 5.X
*
* @see Native#load(java.lang.String, java.lang.Class, java.util.Map)
*/
@Deprecated
public static T loadLibrary(String name, Class interfaceClass, Map options) {
if (!Library.class.isAssignableFrom(interfaceClass)) {
// Maybe still possible if the caller is not using generics?
throw new IllegalArgumentException("Interface (" + interfaceClass.getSimpleName() + ")"
+ " of library=" + name + " does not extend " + Library.class.getSimpleName());
}
Library.Handler handler = new Library.Handler(name, interfaceClass, options);
ClassLoader loader = interfaceClass.getClassLoader();
Object proxy = Proxy.newProxyInstance(loader, new Class[] {interfaceClass}, handler);
cacheOptions(interfaceClass, options, proxy);
return interfaceClass.cast(proxy);
}
/** Attempts to force initialization of an instance of the library interface
* by loading a public static field of the requisite type.
* Returns whether an instance variable was instantiated.
* Expects that lock on libraries is already held
*/
private static void loadLibraryInstance(Class> cls) {
if (cls != null && !libraries.containsKey(cls)) {
try {
Field[] fields = cls.getFields();
for (int i=0;i < fields.length;i++) {
Field field = fields[i];
if (field.getType() == cls
&& Modifier.isStatic(field.getModifiers())) {
// Ensure the field gets initialized by reading it
field.setAccessible(true); // interface might be private
libraries.put(cls, new WeakReference