All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tinkerpop.frames.modules.javahandler.JavaHandlerModule Maven / Gradle / Ivy

Go to download

Windup Frames is an extension of the upstream Frames project, with tools to ease debugging and integration within windup.

There is a newer version: 4.0.1.Final
Show newest version
package com.tinkerpop.frames.modules.javahandler;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.concurrent.ExecutionException;

import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.frames.FramedGraph;
import com.tinkerpop.frames.FramedGraphConfiguration;
import com.tinkerpop.frames.modules.Module;

/**
 * 

* Adds support for calling Java methods to handle a frames call. A call to a * frames method annotated with {@link JavaHandler} will cause the supplied * factory to instantiate an instance of the handler class and call the * appropriate method on it. *

*

* The default implementation is an inner class of the frame interface named 'Impl'. For example: *

*
 * interface Person {
 * 
 *   @JavaHandler
 *   public String doSomething(); 
 *   
 *   abstract class Impl implements Person, JavaHandlerContext {
 *     public String doSomething() {
 *       return "Use Frames!";
 *     }
 *   }
 *   
 * }
 * 
 * 
*

The implementation class can be overridden by using the {@link JavaHandlerClass} annotation.

* * * @author Bryn Cooke */ public class JavaHandlerModule implements Module { // We don't want to use the global class cache. Instead we cache the classes // at the module level. // Maps from frameClass -> proxy class. private LoadingCache, Class> classCache = CacheBuilder .newBuilder().build(new CacheLoader, Class>() { @Override public Class load(final Class frameClass) throws Exception { final Class handlerClass = getHandlerClass(frameClass); ProxyFactory proxyFactory = new ProxyFactory() { protected ClassLoader getClassLoader() { return new URLClassLoader(new URL[0], handlerClass.getClassLoader()); } }; proxyFactory.setUseCache(false); proxyFactory.setSuperclass(handlerClass); return proxyFactory.createClass(); } }); private JavaHandlerFactory factory = new JavaHandlerFactory() { @Override public T create(Class handlerClass) throws InstantiationException, IllegalAccessException { return handlerClass.newInstance(); } }; /** * Provide an alternative factory for creating objects that handle frames * calls. * * @param factory * The factory to use. * @return The module. */ public JavaHandlerModule withFactory(JavaHandlerFactory factory) { this.factory = factory; return this; } @Override public Graph configure(Graph baseGraph, FramedGraphConfiguration config) { config.addMethodHandler(new JavaMethodHandler(this)); config.addFrameInitializer(new JavaFrameInitializer(this)); return baseGraph; } Class getHandlerClass(Class frameClass) throws ClassNotFoundException { JavaHandlerClass handlerClass = frameClass .getAnnotation(JavaHandlerClass.class); if (handlerClass != null) { return handlerClass.value(); } if (frameClass.getClassLoader() == null) { throw new ClassNotFoundException("FrameClass: " + frameClass.getCanonicalName() + " getClassLoader() returned null... no $Impl can be found in this case!"); } return frameClass.getClassLoader().loadClass( frameClass.getName() + "$Impl"); } T createHandler(final Object framedElement, final FramedGraph graph, final Element element, Class frameClass, final Method method) { try { Class implClass = (Class) classCache.get(frameClass); T handler = factory.create(implClass); ((Proxy) handler).setHandler(new MethodHandler() { private JavaHandlerContextImpl defaultJavahandlerImpl = new JavaHandlerContextImpl( graph, method, element); @Override public Object invoke(Object o, Method m, Method proceed, Object[] args) throws Throwable { if (!Modifier.isAbstract(m.getModifiers())) { return proceed.invoke(o, args); } else { if(m.getAnnotation(JavaHandler.class) != null) { throw new JavaHandlerException("Method " + m + " is marked with @JavaHandler but is not implemented"); } if (m.getDeclaringClass() == JavaHandlerContext.class) { return m.invoke(defaultJavahandlerImpl, args); } return m.invoke(framedElement, args); } } }); return handler; } catch (ExecutionException e) { Throwable cause = e.getCause(); if (cause instanceof ClassNotFoundException) { throw new JavaHandlerException("Problem locating handler class for " + frameClass, e); } else { throw new JavaHandlerException( "Cannot create class for handling framed method", cause); } } catch (InstantiationException e) { throw new JavaHandlerException( "Problem instantiating handler class", e); } catch (IllegalAccessException e) { throw new JavaHandlerException( "Problem instantiating handler class", e); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy