Reputation: 4449
I have a very creative solution to allow my unsigned code all access through my signed library. Although bad practice, I fear I have no other solution (except rewriting a lot of code, that then needs to be rewrited back).
I have the following class:
public abstract class full {
public static <T,S,P> S access(final T object, final String function, final P parameter) {
AccessController.doPrivileged(new PrivilegedAction<S>() {
@Override
public S run() {
try {
if (parameter == null) {
Class[] argTypes = { };
Object passedArgv[] = { };
return (S)object.getClass().getMethod(function, argTypes).invoke(object, passedArgv);
} else {
Class[] argTypes = { parameter.getClass() };
Object passedArgv[] = { parameter };
return (S)object.getClass().getMethod(function, argTypes).invoke(object, passedArgv);
}
} catch (NoSuchMethodException ex) {
Logger.getLogger(full.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(full.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(full.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(full.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
});
return null;
}
}
It works great for functions that return Objects, but not for primitives. Boolean bool = full.access(..); will result in a nullpointer, because generic methods can't handle primitives.
Any ideas about how to take the right approach?
To test:
public static Boolean test() {
return true;
}
public Main() {
System.out.println(((Boolean)redirect.full.access(this, "test", null)));
}
Upvotes: 2
Views: 1393
Reputation: 42849
The reason you are getting a NullPointerException
is because you are always returning null
. You call doPrivileged(...)
, yet null
is still returned. Try returning the output of doPrivileged(...)
. By the looks of things, Auto(un)boxing is working here on both the inputs and the returned outputs.
This worked for me (I passed in a primitive int, and expected a primitive boolean):
public class ATest
{
public static void main(String[] args) throws UnsupportedEncodingException
{
int i = 5;
Object equals = new Object();
boolean b = full.access(i, "equals", equals);
System.out.println(b);
}
public static class full
{
public static <T, S, P> S access(final T object, final String function, final P parameter)
{
return AccessController.doPrivileged(new PrivilegedAction<S>()
{
@Override
public S run()
{
try
{
if (parameter == null)
{
Class[] argTypes = {};
Object passedArgv[] = {};
return (S) object.getClass().getMethod(function, argTypes)
.invoke(object, passedArgv);
}
else
{
Class[] argTypes = { parameter.getClass() };
Object passedArgv[] = { parameter };
return (S) object.getClass().getMethod(function, argTypes)
.invoke(object, passedArgv);
}
}
catch (NoSuchMethodException ex)
{
Logger.getLogger(full.class.getName()).log(Level.ALL, null, ex);
}
catch (SecurityException ex)
{
Logger.getLogger(full.class.getName()).log(Level.ALL, null, ex);
}
catch (IllegalAccessException ex)
{
Logger.getLogger(full.class.getName()).log(Level.ALL, null, ex);
}
catch (InvocationTargetException ex)
{
Logger.getLogger(full.class.getName()).log(Level.ALL, null, ex);
}
return null;
}
});
}
}
}
On another note, you could make this more robust. When I passed in an Integer
instead of an Object
, the equals method was not found, even though it would have been a valid method call. If you do not find the method with the given Class
, you should check again with the classes' parent classes.
Upvotes: 1
Reputation:
Isn't that what the primitive classes are for? ( Boolean, Integer... ) I'm not sure if they'll do it, I haven't checked.
Long answer : make a clone of all those methods to return primitives.
Or much shorter; you could just wrap the primitive type you want in an object, that is do something like:
public class MyInt {
public int intValue;
}
Upvotes: 1