37package com.jogamp.gluegen.runtime;
39import com.jogamp.common.os.DynamicLookupHelper;
40import com.jogamp.common.util.SecurityUtil;
42import java.io.BufferedOutputStream;
44import java.io.FileOutputStream;
45import java.io.IOException;
46import java.io.PrintStream;
47import java.lang.reflect.AccessibleObject;
48import java.lang.reflect.Field;
49import java.security.PrivilegedAction;
50import java.util.Iterator;
51import java.util.LinkedHashSet;
54import java.util.SortedMap;
55import java.util.TreeMap;
81 private static final String PROCADDRESS_VAR_PREFIX =
"_addressof_";
82 private static final int PROCADDRESS_VAR_PREFIX_LEN = PROCADDRESS_VAR_PREFIX.length();
94 DEBUG = (System.getProperty(
"jogamp.debug.ProcAddressHelper") !=
null);
96 DEBUG_PREFIX = System.getProperty(
"jogamp.debug.ProcAddressHelper.prefix");
104 this(
new One2OneResolver());
108 this.resolver = resolver;
122 throw new RuntimeException(
"Passed null DynamicLookupHelper");
125 final Field[] fields = getClass().getDeclaredFields();
127 final PrintStream dout;
129 dout = getDebugOutStream();
130 dout.println(getClass().getName()+
".reset() (w/ "+fields.length+
" prospective fields)");
136 AccessibleObject.setAccessible(fields,
true);
137 lookup.claimAllLinkPermission();
139 for (
int i = 0; i < fields.length; ++i) {
140 final String fieldName = fields[i].getName();
141 if ( isAddressField(fieldName) ) {
142 final String funcName = fieldToFunctionName(fieldName);
143 setEntry(fields[i], funcName, lookup);
147 lookup.releaseAllLinkPermission();
169 final Field addressField = fieldForFunction(name);
170 addressField.setAccessible(
true);
171 setEntry(addressField, name, lookup);
174 private final void setEntry(
final Field addressField,
final String funcName,
final DynamicLookupHelper lookup)
throws SecurityException {
176 assert (addressField.getType() == Long.TYPE);
177 final long newProcAddress = resolver.
resolve(funcName, lookup);
178 addressField.setLong(
this, newProcAddress);
180 getDebugOutStream().println(
" " + addressField.getName() +
" -> 0x" + Long.toHexString(newProcAddress));
182 }
catch (
final Exception e) {
183 throw new RuntimeException(
"Can not get proc address for method \""
184 + funcName +
"\": Couldn't set value of field \"" + addressField, e);
188 private final String fieldToFunctionName(
final String addressFieldName) {
189 return addressFieldName.substring(PROCADDRESS_VAR_PREFIX_LEN);
192 private final Field fieldForFunction(
final String name)
throws IllegalArgumentException {
194 return getClass().getDeclaredField(PROCADDRESS_VAR_PREFIX + name);
195 }
catch (
final NoSuchFieldException ex) {
196 throw new IllegalArgumentException(getClass().getName() +
" has no entry for the function '"+name+
"'.", ex);
208 private final Field fieldForFunctionInSec(
final String name)
throws IllegalArgumentException {
209 return SecurityUtil.doPrivileged(
new PrivilegedAction<Field>() {
213 final Field addressField =
ProcAddressTable.this.getClass().getDeclaredField(PROCADDRESS_VAR_PREFIX + name);
214 addressField.setAccessible(
true);
216 }
catch (
final NoSuchFieldException ex) {
217 throw new IllegalArgumentException(getClass().getName() +
" has no entry for the function '"+name+
"'.", ex);
223 private final boolean isAddressField(
final String fieldName) {
224 return fieldName.startsWith(PROCADDRESS_VAR_PREFIX);
227 private final static PrintStream getDebugOutStream() {
228 PrintStream out =
null;
232 out =
new PrintStream(
new BufferedOutputStream(
new FileOutputStream(
DEBUG_PREFIX + File.separatorChar
233 +
"procaddresstable-" + (++
debugNum) +
".txt")));
234 }
catch (
final IOException e) {
248 private final Map<String, Long> toMap() {
249 final SortedMap<String, Long> map =
new TreeMap<String, Long>();
251 final Field[] fields = getClass().getFields();
253 for (
int i = 0; i < fields.length; ++i) {
254 final String addressFieldName = fields[i].getName();
255 if (isAddressField(addressFieldName)) {
256 map.put(fieldToFunctionName(addressFieldName), (Long)fields[i].
get(
this));
259 }
catch (
final IllegalArgumentException ex) {
260 throw new RuntimeException(ex);
261 }
catch (
final IllegalAccessException ex) {
262 throw new RuntimeException(ex);
274 }
catch (
final IllegalArgumentException ex) {
290 final Field addressField = fieldForFunctionInSec(functionName);
292 return 0 != addressField.getLong(
this);
293 }
catch (
final IllegalAccessException ex) {
294 throw new RuntimeException(ex);
313 public long getAddressFor(
final String functionName)
throws SecurityException, IllegalArgumentException {
315 final Field addressField = fieldForFunctionInSec(functionName);
317 return addressField.getLong(
this);
318 }
catch (
final IllegalAccessException ex) {
319 throw new RuntimeException(ex);
327 final Map<String, Long> table = toMap();
328 final Set<String> nullPointers =
new LinkedHashSet<String>();
329 for (
final Iterator<Map.Entry<String, Long>> it = table.entrySet().iterator(); it.hasNext();) {
330 final Map.Entry<String, Long> entry = it.next();
331 final long address = entry.getValue().longValue();
333 nullPointers.add(entry.getKey());
341 return getClass().getName()+
""+toMap();
346 public long resolve(
final String name,
final DynamicLookupHelper lookup)
throws SecurityException {
347 return lookup.dynamicLookupFunction(name);
static< T > T doPrivileged(final PrivilegedAction< T > o)
Call wrapper for java.security.AccessController#doPrivileged(PrivilegedAction).
static final void checkAllLinkPermission()
Throws an SecurityException if an installed SecurityManager does not permit to dynamically link to al...
Superclass for all generated ProcAddressTables.
void reset(final DynamicLookupHelper lookup)
Resets the complete table.
long getAddressFor(final String functionName)
This is a convenience method to query the native function handle by name.
boolean isFunctionAvailableImpl(final String functionName)
This is a convenience method to query the native function existence by name.
void initEntry(final String name, final DynamicLookupHelper lookup)
Initializes the mapping for a single function.
static String DEBUG_PREFIX
final boolean isFunctionAvailable(final String functionName)
Returns true only if non null function pointer to this function exists.
ProcAddressTable(final FunctionAddressResolver resolver)
final Set< String > getNullPointerFunctions()
Returns all functions pointing to null.
Interface callers may use ProcAddressHelper's reset helper method to install function pointers into a...
long resolve(String name, DynamicLookupHelper lookup)
Resolves the name of the function bound to the method and returns the address.