package io.shockah.skylark.groovy;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.kohsuke.groovy.sandbox.GroovyInterceptor;
public abstract class AbstractGroovySandbox extends GroovyInterceptor {
public abstract boolean isInstanceMethodCallAllowed(Object obj, String method, Object... args);
public abstract boolean isClassMethodCallAllowed(Class<?> clazz, String method, Object... args);
public abstract boolean isConstructorAllowed(Class<?> clazz, Object... args);
public abstract boolean isInstanceFieldGetAllowed(Object obj, String field);
public abstract boolean isInstanceFieldSetAllowed(Object obj, String field, Object value);
public abstract boolean isClassFieldGetAllowed(Class<?> clazz, String field);
public abstract boolean isClassFieldSetAllowed(Class<?> clazz, String field, Object value);
@Override
public Object onMethodCall(Invoker invoker, Object receiver, String method, Object... args) throws Throwable {
if (isInstanceMethodCallAllowed(receiver, method, args))
return super.onMethodCall(invoker, receiver, method, args);
else
throw new SecurityException(String.format("%s.%s instance method call not allowed.", receiver.getClass().getName(), method));
}
@Override
public Object onStaticCall(Invoker invoker, Class receiver, String method, Object... args) throws Throwable {
if (isClassMethodCallAllowed(receiver, method, args))
return super.onStaticCall(invoker, receiver, method, args);
else
throw new SecurityException(String.format("%s.%s static method call not allowed.", receiver.getName(), method));
}
@Override
public Object onNewInstance(Invoker invoker, Class receiver, Object... args) throws Throwable {
if (isConstructorAllowed(receiver, args))
return super.onNewInstance(invoker, receiver, args);
else
throw new SecurityException(String.format("%s.%s constructor call not allowed.", receiver.getName()));
}
@Override
public Object onGetProperty(Invoker invoker, Object receiver, String property) throws Throwable {
if (receiver instanceof Class<?>) {
Class<?> clazz = (Class<?>)receiver;
try {
clazz.getField(property);
if (isClassFieldGetAllowed(clazz, property))
return super.onGetProperty(invoker, receiver, property);
else
throw new SecurityException(String.format("%s.%s static field access not allowed.", clazz.getName(), property));
} catch (NoSuchFieldException e) {
}
String method = String.format("get%s%s", property.substring(0, 1).toUpperCase(), property.substring(1));
try {
Method classMethod = clazz.getClass().getMethod(method);
if (!Modifier.isStatic(classMethod.getModifiers())) {
clazz = clazz.getClass();
if (isInstanceMethodCallAllowed(clazz, method))
return super.onGetProperty(invoker, receiver, property);
else
throw new SecurityException(String.format("%s.%s instance method call not allowed.", clazz.getName(), method));
}
} catch (NoSuchMethodException e) {
}
if (isClassMethodCallAllowed(clazz, method))
return super.onGetProperty(invoker, receiver, property);
else
throw new SecurityException(String.format("%s.%s static method call not allowed.", clazz.getName(), method));
} else {
Class<?> clazz = receiver.getClass();
try {
clazz.getField(property);
if (isInstanceFieldGetAllowed(receiver, property))
return super.onGetProperty(invoker, receiver, property);
else
throw new SecurityException(String.format("%s.%s instance field access not allowed.", clazz.getName(), property));
} catch (NoSuchFieldException e) {
}
String method = String.format("get%s%s", property.substring(0, 1).toUpperCase(), property.substring(1));
if (isInstanceMethodCallAllowed(receiver, method))
return super.onGetProperty(invoker, receiver, property);
else
throw new SecurityException(String.format("%s.%s instance method call not allowed.", clazz.getName(), method));
}
}
@Override
public Object onSetProperty(Invoker invoker, Object receiver, String property, Object value) throws Throwable {
if (receiver instanceof Class<?>) {
Class<?> clazz = (Class<?>)receiver;
try {
clazz.getField(property);
if (isClassFieldSetAllowed(clazz, property, value))
return super.onSetProperty(invoker, receiver, property, value);
else
throw new SecurityException(String.format("%s.%s static field access not allowed.", clazz.getName(), property));
} catch (NoSuchFieldException e) {
}
String method = String.format("set%s%s", property.substring(0, 1).toUpperCase(), property.substring(1));
try {
Method classMethod = clazz.getClass().getMethod(method);
if (!Modifier.isStatic(classMethod.getModifiers())) {
clazz = clazz.getClass();
if (isInstanceMethodCallAllowed(clazz, method, value))
return super.onSetProperty(invoker, receiver, property, value);
else
throw new SecurityException(String.format("%s.%s instance method call not allowed.", clazz.getName(), method));
}
} catch (NoSuchMethodException e) {
}
if (isClassMethodCallAllowed(clazz, method, value))
return super.onSetProperty(invoker, receiver, property, value);
else
throw new SecurityException(String.format("%s.%s static method call not allowed.", clazz.getName(), method));
} else {
Class<?> clazz = receiver.getClass();
try {
clazz.getField(property);
if (isInstanceFieldSetAllowed(receiver, property, value))
return super.onSetProperty(invoker, receiver, property, value);
else
throw new SecurityException(String.format("%s.%s instance field access not allowed.", clazz.getName(), property));
} catch (NoSuchFieldException e) {
}
String method = String.format("set%s%s", property.substring(0, 1).toUpperCase(), property.substring(1));
if (isInstanceMethodCallAllowed(receiver, method, value))
return super.onSetProperty(invoker, receiver, property, value);
else
throw new SecurityException(String.format("%s.%s instance method call not allowed.", clazz.getName(), method));
}
}
}