package com.alibaba.doris.dproxy; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import net.sf.cglib.proxy.Enhancer; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * Proxy Factory. A AOP factory. * It use a specified class to create a instance of which the method invocation would be intercepted by Interceptors. * @author He Kun * */ public class ProxyFactory { private static Logger logger = Logger.getLogger( ProxyFactory.class.getName() ); private static String defaultConfigLocation = "common-aop.xml"; private String configLocation = defaultConfigLocation; private Map<String,InterceptorGroup> handlerMap = new HashMap<String,InterceptorGroup>(5); static { logger.setLevel( Level.INFO ); } public ProxyFactory() { loadConfig( defaultConfigLocation ); } public ProxyFactory(String configLocation) { this.configLocation = configLocation; loadConfig( this.configLocation ); } /** * Load config file. * @param configName */ public void loadConfig(String configName) { SAXReader saxReader = new SAXReader(); URL url = Thread.currentThread().getContextClassLoader().getResource(configName); if(url == null) { url = ProxyFactory.class.getResource(configName); } if(url== null) { throw new RuntimeException("Config not found! " + configName); } InputStream in = null; Document document; try { in = url.openStream(); document = saxReader.read(in); Element root = document.getRootElement(); List<?> handlers = root.selectNodes("interceptorGroups/interceptorGroup"); Iterator<?> iter = handlers.iterator(); while (iter.hasNext()) { Element handlerEle = (Element) iter.next(); String handlerName = handlerEle.attributeValue("name"); // InterceptorGroup name String handlerDescription = handlerEle.attributeValue("description"); //InterceptorGroup description String includeMethodString = handlerEle.attributeValue("methods"); //InterceptorGroup description if(handlerName == null || "".equals(handlerName.trim())) { throw new RuntimeException( "InterceptorGroup 'name' attribute can't be empty! "); } InterceptorGroup group = new InterceptorGroup(); group.setName(handlerName); group.setDescription(handlerDescription); if(includeMethodString!=null && includeMethodString.length() > 0) { String[] methods = includeMethodString.split(","); group.setIncludeMethods(methods); } loadHandler(handlerEle,group); } } catch (DocumentException e) { throw new RuntimeException("Can't locad config " + configName + " " + e.getMessage()); } catch (IOException e) { throw new RuntimeException("Can't locad config " + configName + " " + e.getMessage()) ; } finally { if (in!=null) try { in.close(); }catch(IOException e) { } } } private void loadHandler(Element handlerEle, InterceptorGroup group ) { Iterator<?> interceptors = handlerEle.elementIterator("interceptor"); while (interceptors.hasNext()) { Element interceptorEle = (Element) interceptors.next(); String interceptorClass = interceptorEle.attributeValue("class").trim(); // try { Class<?> clazz = Class.forName(interceptorClass); if(!Interceptor.class.isAssignableFrom(clazz)) { throw new RuntimeException("Interceptor class " + interceptorClass +" must implement interface " + Interceptor.class.getName() +" OR extends class " + AbstractInterceptor.class.getName()); }else { group.registerInterceptor(clazz); } } catch (ClassNotFoundException e) { throw new RuntimeException("Interceptor class " + interceptorClass +" not found"); } } handlerMap.put(group.getName(), group); } /** * Create proxy instance. * @param proxyClass * @param includeMethods method to be intercepted. * @param handlerName * @return * @throws InstantiationException */ public Object createObject(Class<?> proxyClass,String handlerName) throws InstantiationException { InterceptorGroup handler = (InterceptorGroup) handlerMap.get(handlerName); if(handler == null) { throw new InstantiationException("InterceptorGroup not found name:" + handlerName); } return createObject(proxyClass, null, handler); } /** * Create proxy instance. * @param proxyClass * @param includeMethods method to be intercepted. * @param handlerName * @return * @throws InstantiationException */ public Object createObject(Class<?> proxyClass,String[] includeMethods,String handlerName) throws InstantiationException { InterceptorGroup handler = (InterceptorGroup) handlerMap.get(handlerName); if(handler == null) { throw new InstantiationException("InterceptorGroup not found name:" + handlerName); } return createObject(proxyClass, includeMethods, handler); } public Object createObject(Class<?> proxyClass,InterceptorGroup handler) throws InstantiationException { return createObject(proxyClass, null, handler); } public Object createObject(Class<?> proxyClass,String[] includeMethods,InterceptorGroup interceptorGroup) throws InstantiationException { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(proxyClass); //override configed include methods by API if(includeMethods != null && includeMethods.length > 0) interceptorGroup.setIncludeMethods(includeMethods); interceptorGroup.setName(interceptorGroup.getName()); interceptorGroup.setDescription(interceptorGroup.getDescription()); interceptorGroup.setClazz(interceptorGroup.getClazz()); enhancer.setCallback( interceptorGroup ); Object proxyObject = enhancer.create(); return proxyObject; } @SuppressWarnings("unchecked") public static void main(String[] args) { try { ProxyFactory proxyFactory = new ProxyFactory("common-aop.xml"); // Map<String,String> map = (Map<String,String>)proxyFactory.createObject(HashMap.class, new String[] {"get"}, "AddOperationInterceptorHandler"); Map<String,String> map = (Map<String,String>)proxyFactory.createObject(HashMap.class, "MapInterceptorGroup"); System.out.println("AOP Demo: intercept Map.get method."); map.put("key1", "value1"); String v = map.get("key1"); System.out.println("map.put(\"key1\", \"value1\") \r\n map.get('key1'):" + v); map.clear(); } catch (InstantiationException e) { e.printStackTrace(); } } }