001 package com.khubla.pragmatach.plugin.mongodb.proxy; 002 003 import java.util.Hashtable; 004 005 import javassist.CannotCompileException; 006 import javassist.ClassPool; 007 import javassist.CtClass; 008 import javassist.CtField; 009 import javassist.Modifier; 010 import javassist.NotFoundException; 011 import javassist.util.proxy.ProxyFactory; 012 import javassist.util.proxy.ProxyObject; 013 014 import org.apache.commons.lang.reflect.FieldUtils; 015 016 /** 017 * @author tom 018 */ 019 public class MongoProxyFactory { 020 /** 021 * some special names 022 */ 023 public static final String LAZYID = "mongolazyid"; 024 public static final String LAZYFETCHED = "mongolazyfetched"; 025 /** 026 * static registry of lazy loading proxies 027 */ 028 private static final Hashtable<Class<?>, Class<?>> lazyProxies = new Hashtable<Class<?>, Class<?>>(); 029 030 /** 031 * create a class which extends the typeClazz with some new members 032 */ 033 private static Class<?> createProxyClass(Class<?> typeClazz) throws NotFoundException, CannotCompileException { 034 final ClassPool classPool = ClassPool.getDefault(); 035 final CtClass ctClass = classPool.makeClass(typeClazz.getName() + "_monogolazyload"); 036 ctClass.setSuperclass(classPool.getCtClass(typeClazz.getName())); 037 final CtClass ctStringClass = ClassPool.getDefault().get("java.lang.String"); 038 final CtField ctIdField = new CtField(ctStringClass, LAZYID, ctClass); 039 ctIdField.setModifiers(Modifier.PUBLIC); 040 ctClass.addField(ctIdField); 041 final CtField ctFetchedField = new CtField(CtClass.booleanType, LAZYFETCHED, ctClass); 042 ctFetchedField.setModifiers(Modifier.PUBLIC); 043 ctClass.addField(ctFetchedField); 044 return ctClass.toClass(); 045 } 046 047 /** 048 * get proxy 049 */ 050 private static Class<?> getProxyClass(Class<?> clazz) throws NotFoundException, CannotCompileException { 051 Class<?> ret = lazyProxies.get(clazz); 052 if (null == ret) { 053 ret = createProxyClass(clazz); 054 lazyProxies.put(clazz, ret); 055 } 056 return ret; 057 } 058 059 /** 060 * get a proxy to an instance of a type 061 */ 062 public static Object getProxyObject(Class<?> typeClazz) throws NotFoundException, IllegalAccessException, InstantiationException, CannotCompileException { 063 /* 064 * the handler 065 */ 066 final MongoMethodHandler mongoMethodHandler = new MongoMethodHandler(); 067 /* 068 * factory 069 */ 070 final ProxyFactory proxyFactory = new ProxyFactory(); 071 /* 072 * create the superclass 073 */ 074 final Class<?> superClass = getProxyClass(typeClazz); 075 /* 076 * set the super class 077 */ 078 proxyFactory.setSuperclass(superClass); 079 /* 080 * set the filter 081 */ 082 proxyFactory.setFilter(mongoMethodHandler); 083 /* 084 * create the proxy class 085 */ 086 final Class<?> clazz = proxyFactory.createClass(); 087 /* 088 * create the instance 089 */ 090 final Object instance = clazz.newInstance(); 091 /* 092 * weird magic required to set the handler 093 */ 094 ((ProxyObject) instance).setHandler(mongoMethodHandler); 095 /* 096 * done 097 */ 098 return instance; 099 } 100 101 public static void setID(Object o, String id) throws IllegalAccessException { 102 FieldUtils.writeField(o, MongoProxyFactory.LAZYID, id); 103 } 104 105 public static void setFetched(Object o, boolean fetched) throws IllegalAccessException { 106 FieldUtils.writeField(o, MongoProxyFactory.LAZYFETCHED, false); 107 } 108 109 public static String getId(Object o) throws IllegalAccessException { 110 return (String) FieldUtils.readField(o, MongoProxyFactory.LAZYID); 111 } 112 113 public static boolean getFetched(Object o) throws IllegalAccessException { 114 Boolean b = (Boolean) FieldUtils.readField(o, MongoProxyFactory.LAZYFETCHED); 115 return b.booleanValue(); 116 } 117 }