use of groovy.lang.DelegatingMetaClass in project groovy-core by groovy.
the class MixinInMetaClass method mixinClassesToMetaClass.
public static void mixinClassesToMetaClass(MetaClass self, List<Class> categoryClasses) {
final Class selfClass = self.getTheClass();
if (self instanceof HandleMetaClass) {
self = (MetaClass) ((HandleMetaClass) self).replaceDelegate();
}
if (!(self instanceof ExpandoMetaClass)) {
if (self instanceof DelegatingMetaClass && ((DelegatingMetaClass) self).getAdaptee() instanceof ExpandoMetaClass) {
self = ((DelegatingMetaClass) self).getAdaptee();
} else {
throw new GroovyRuntimeException("Can't mixin methods to meta class: " + self);
}
}
ExpandoMetaClass mc = (ExpandoMetaClass) self;
List<MetaMethod> arr = new ArrayList<MetaMethod>();
for (Class categoryClass : categoryClasses) {
final CachedClass cachedCategoryClass = ReflectionCache.getCachedClass(categoryClass);
final MixinInMetaClass mixin = new MixinInMetaClass(mc, cachedCategoryClass);
final MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(categoryClass);
final List<MetaProperty> propList = metaClass.getProperties();
for (MetaProperty prop : propList) if (self.getMetaProperty(prop.getName()) == null) {
mc.registerBeanProperty(prop.getName(), new MixinInstanceMetaProperty(prop, mixin));
}
for (MetaProperty prop : cachedCategoryClass.getFields()) if (self.getMetaProperty(prop.getName()) == null) {
mc.registerBeanProperty(prop.getName(), new MixinInstanceMetaProperty(prop, mixin));
}
for (MetaMethod method : metaClass.getMethods()) {
final int mod = method.getModifiers();
if (!Modifier.isPublic(mod))
continue;
if (method instanceof CachedMethod && ((CachedMethod) method).getCachedMethod().isSynthetic())
continue;
if (Modifier.isStatic(mod)) {
if (method instanceof CachedMethod)
staticMethod(self, arr, (CachedMethod) method);
} else if (method.getDeclaringClass().getTheClass() != Object.class || method.getName().equals("toString")) {
// if (self.pickMethod(method.getName(), method.getNativeParameterTypes()) == null) {
final MixinInstanceMetaMethod metaMethod = new MixinInstanceMetaMethod(method, mixin);
arr.add(metaMethod);
// }
}
}
}
for (Object res : arr) {
final MetaMethod metaMethod = (MetaMethod) res;
if (metaMethod.getDeclaringClass().isAssignableFrom(selfClass))
mc.registerInstanceMethod(metaMethod);
else {
mc.registerSubclassInstanceMethod(metaMethod);
}
}
}
use of groovy.lang.DelegatingMetaClass in project groovy-core by groovy.
the class GPathResult method setMetaClass.
/**
* Replaces the MetaClass of this GPathResult.
*
* @param metaClass the new MetaClass
*/
@Override
public void setMetaClass(final MetaClass metaClass) {
final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
@Override
public Object getAttribute(final Object object, final String attribute) {
return GPathResult.this.getProperty("@" + attribute);
}
@Override
public void setAttribute(final Object object, final String attribute, final Object newValue) {
GPathResult.this.setProperty("@" + attribute, newValue);
}
};
super.setMetaClass(newMetaClass);
}
use of groovy.lang.DelegatingMetaClass in project groovy-core by groovy.
the class GroovyScriptEngineImpl method eval.
// package-privates
Object eval(Class scriptClass, final ScriptContext ctx) throws ScriptException {
// Only initialize once.
if (null == ctx.getAttribute("context", ScriptContext.ENGINE_SCOPE)) {
// add context to bindings
ctx.setAttribute("context", ctx, ScriptContext.ENGINE_SCOPE);
// direct output to ctx.getWriter
// If we're wrapping with a PrintWriter here,
// enable autoFlush because otherwise it might not get done!
final Writer writer = ctx.getWriter();
ctx.setAttribute("out", (writer instanceof PrintWriter) ? writer : new PrintWriter(writer, true), ScriptContext.ENGINE_SCOPE);
// Not going to do this after all (at least for now).
// Scripts can use context.{reader, writer, errorWriter}.
// That is a modern version of System.{in, out, err} or Console.{reader, writer}().
//
// // New I/O names consistent with ScriptContext and java.io.Console.
//
// ctx.setAttribute("writer", writer, ScriptContext.ENGINE_SCOPE);
//
// // Direct errors to ctx.getErrorWriter
// final Writer errorWriter = ctx.getErrorWriter();
// ctx.setAttribute("errorWriter", (errorWriter instanceof PrintWriter) ?
// errorWriter :
// new PrintWriter(errorWriter),
// ScriptContext.ENGINE_SCOPE);
//
// // Get input from ctx.getReader
// // We don't wrap with BufferedReader here because we expect that if
// // the host wants that they do it. Either way Groovy scripts will
// // always have readLine because the GDK supplies it for Reader.
// ctx.setAttribute("reader", ctx.getReader(), ScriptContext.ENGINE_SCOPE);
}
// Fix for GROOVY-3669: Can't use several times the same JSR-223 ScriptContext for differents groovy script
if (ctx.getWriter() != null) {
ctx.setAttribute("out", new PrintWriter(ctx.getWriter(), true), ScriptContext.ENGINE_SCOPE);
}
/*
* We use the following Binding instance so that global variable lookup
* will be done in the current ScriptContext instance.
*/
Binding binding = new Binding(ctx.getBindings(ScriptContext.ENGINE_SCOPE)) {
@Override
public Object getVariable(String name) {
synchronized (ctx) {
int scope = ctx.getAttributesScope(name);
if (scope != -1) {
return ctx.getAttribute(name, scope);
}
}
throw new MissingPropertyException(name, getClass());
}
@Override
public void setVariable(String name, Object value) {
synchronized (ctx) {
int scope = ctx.getAttributesScope(name);
if (scope == -1) {
scope = ScriptContext.ENGINE_SCOPE;
}
ctx.setAttribute(name, value, scope);
}
}
};
try {
// then simply return that class
if (!Script.class.isAssignableFrom(scriptClass)) {
return scriptClass;
} else {
// it's a script
Script scriptObject = InvokerHelper.createScript(scriptClass, binding);
// save all current closures into global closures map
Method[] methods = scriptClass.getMethods();
for (Method m : methods) {
String name = m.getName();
globalClosures.put(name, new MethodClosure(scriptObject, name));
}
MetaClass oldMetaClass = scriptObject.getMetaClass();
/*
* We override the MetaClass of this script object so that we can
* forward calls to global closures (of previous or future "eval" calls)
* This gives the illusion of working on the same "global" scope.
*/
scriptObject.setMetaClass(new DelegatingMetaClass(oldMetaClass) {
@Override
public Object invokeMethod(Object object, String name, Object args) {
if (args == null) {
return invokeMethod(object, name, MetaClassHelper.EMPTY_ARRAY);
}
if (args instanceof Tuple) {
return invokeMethod(object, name, ((Tuple) args).toArray());
}
if (args instanceof Object[]) {
return invokeMethod(object, name, (Object[]) args);
} else {
return invokeMethod(object, name, new Object[] { args });
}
}
@Override
public Object invokeMethod(Object object, String name, Object[] args) {
try {
return super.invokeMethod(object, name, args);
} catch (MissingMethodException mme) {
return callGlobal(name, args, ctx);
}
}
@Override
public Object invokeStaticMethod(Object object, String name, Object[] args) {
try {
return super.invokeStaticMethod(object, name, args);
} catch (MissingMethodException mme) {
return callGlobal(name, args, ctx);
}
}
});
return scriptObject.run();
}
} catch (Exception e) {
throw new ScriptException(e);
} finally {
// Fix for GROOVY-3669: Can't use several times the same JSR-223 ScriptContext for different groovy script
// Groovy's scripting engine implementation adds those two variables in the binding
// but should clean up afterwards
ctx.removeAttribute("context", ScriptContext.ENGINE_SCOPE);
ctx.removeAttribute("out", ScriptContext.ENGINE_SCOPE);
}
}
use of groovy.lang.DelegatingMetaClass in project groovy-core by groovy.
the class Node method setMetaClass.
/**
* Extension point for subclasses to override the metaclass. The default
* one supports the property and @ attribute notations.
*
* @param metaClass the original metaclass
* @param nodeClass the class whose metaclass we wish to override (this class or a subclass)
*/
protected static void setMetaClass(final MetaClass metaClass, Class nodeClass) {
// TODO Is protected static a bit of a smell?
// TODO perhaps set nodeClass to be Class<? extends Node>
final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
@Override
public Object getAttribute(final Object object, final String attribute) {
Node n = (Node) object;
return n.get("@" + attribute);
}
@Override
public void setAttribute(final Object object, final String attribute, final Object newValue) {
Node n = (Node) object;
n.attributes().put(attribute, newValue);
}
@Override
public Object getProperty(Object object, String property) {
if (object instanceof Node) {
Node n = (Node) object;
return n.get(property);
}
return super.getProperty(object, property);
}
@Override
public void setProperty(Object object, String property, Object newValue) {
if (property.startsWith("@")) {
setAttribute(object, property.substring(1), newValue);
return;
}
delegate.setProperty(object, property, newValue);
}
};
GroovySystem.getMetaClassRegistry().setMetaClass(nodeClass, newMetaClass);
}
use of groovy.lang.DelegatingMetaClass in project groovy-core by groovy.
the class NodeList method setMetaClass.
protected static void setMetaClass(final Class nodelistClass, final MetaClass metaClass) {
final MetaClass newMetaClass = new DelegatingMetaClass(metaClass) {
@Override
public Object getAttribute(final Object object, final String attribute) {
NodeList nl = (NodeList) object;
Iterator it = nl.iterator();
List result = new ArrayList();
while (it.hasNext()) {
Node node = (Node) it.next();
result.add(node.attributes().get(attribute));
}
return result;
}
@Override
public void setAttribute(final Object object, final String attribute, final Object newValue) {
for (Object o : (NodeList) object) {
Node node = (Node) o;
node.attributes().put(attribute, newValue);
}
}
@Override
public Object getProperty(Object object, String property) {
if (object instanceof NodeList) {
NodeList nl = (NodeList) object;
return nl.getAt(property);
}
return super.getProperty(object, property);
}
};
GroovySystem.getMetaClassRegistry().setMetaClass(nodelistClass, newMetaClass);
}
Aggregations