Я не смог найти какую-либо поддержку для этого в двигателе Rhino (если кто-нибудь знают о таких вещах, пожалуйста, так сказать.)
Это, как правило, легко реализовать. Вам необходимо реализовать собственный WrapFactory и собственный NativeJavaObject. Вам также нужно вызвать создать собственный ContextFactory, чтобы гарантировать, что ваш WrapFactory используется во всех объектах Context, используемых во всем движке сценария. Это звучит как много работы ... но на самом деле это на самом деле просто много кода обертки. Вот фрагмент моей реализации. ЧТО ПРОИСХОДИТ: фактический вызов ContextFactory.initGlobal для установки глобальной ContextFactory для вашей реализации ContextFactory.
Очевидно, что этот код не поточно
class ProtectedContextFactory extends ContextFactory
{
private static final ProtectedWrapFactory wrapper = new ProtectedWrapFactory();
@Override
protected Context makeContext()
{
Context c = super.makeContext();
c.setWrapFactory(wrapper);
return c;
}
}
class ProtectedWrapFactory extends WrapFactory
{
@Override
public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject, Class<?> staticType)
{
return new ProtectedNativeJavaObject(scope, javaObject, staticType);
}
}
class ProtectedNativeJavaObject extends NativeJavaObject
{
private static final HashMap<Class<?>, ArrayList<String>> CLASS_PROTECTION_CACHE = new HashMap<Class<?>, ArrayList<String>>();
private ArrayList<String> m_protectedMembers;
public ProtectedNativeJavaObject(Scriptable scope, Object javaObject, Class<?> staticType)
{
super(scope, javaObject, staticType);
Class<?> clazz = javaObject != null ? javaObject.getClass() : staticType;
m_protectedMembers = CLASS_PROTECTION_CACHE.get(clazz);
if(m_protectedMembers == null)
m_protectedMembers = processClass(clazz);
}
private static ArrayList<String> processClass(Class<?> clazz)
{
ArrayList<String> protectedMethods = new ArrayList<String>();
CLASS_PROTECTION_CACHE.put(clazz, protectedMethods);
for(Method m : clazz.getMethods())
{
if(m.getAnnotation(ScriptHiddenMember.class) != null)
protectedMethods.add(m.getName());
}
for(Field f : clazz.getFields())
{
if(f.getAnnotation(ScriptHiddenMember.class) != null)
protectedMethods.add(f.getName());
}
return protectedMethods;
}
@Override
public boolean has(String name, Scriptable start)
{
if(m_protectedMembers.contains(name))
return false;
else
return super.has(name, start);
}
@Override
public Object get(String name, Scriptable start)
{
if(m_protectedMembers.contains(name))
return NOT_FOUND;
else
return super.get(name, start);
}
}
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ScriptHiddenMember {}
Я использую внутренний класс (для представления внешний) для обеспечения ограниченного доступа к этому внешнему объекту из сценария. Проблема в том, что скрипт может захотеть ссылаться на этот внешний объект при вызове другого метода Java. Таким образом, метод Java будет иметь только экземпляр для внутреннего класса для работы (поскольку вызывающий скрипт имеет доступ только к внутреннему классу.) Теперь мне нужно перейти от внутреннего класса (который представляет его внешний класс к скриптам) к внешнему классу, чтобы он мог использоваться без ограничений с помощью метода. Проблема в том, что для получения этого внешнего объекта мне нужно открыть метод ... – Jeremy
(который я хочу скрыть от сценария, чтобы он не мог получить доступ к внешнему объекту) во внутреннем классе, который вернет экземпляр в внешний объект, который может использоваться вызываемым java-методом. Я могу привести пример, если мое объяснение трудно выполнить. – Jeremy
Вы считали использование интерфейса вместо внутреннего класса? – user987339