package com.maxifier.guice.mbean; import net.sf.cglib.core.NamingPolicy; import net.sf.cglib.core.Predicate; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.InterfaceMaker; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * Created by: Aleksey Didik * Date: 5/26/11 * Time: 7:41 PM * <p/> * Copyright (c) 1999-2011 Maxifier Ltd. All Rights Reserved. * Code proprietary and confidential. * Use is subject to license terms. * * @author Aleksey Didik */ public class CGLIBMBeanGenerator implements MBeanGenerator { @SuppressWarnings({"unchecked"}) private AnnotatedMethodCache methodCache = new AnnotatedMethodCache(MBeanMethod.class); @Override public Object makeMBean(final Object mbeanPretender) throws MBeanGenerationException { Class<?> pretenderClass = mbeanPretender.getClass(); String pretenderClassName = pretenderClass.getName(); String hash = Integer.toHexString(mbeanPretender.hashCode()); final String mbeanName = pretenderClassName + "$$" + hash; final String mbeanInterfaceName = mbeanName + "MBean"; Method[] methods = methodCache.get(pretenderClass); if (methods.length == 0) { throw new MBeanGenerationException(String.format("MBean pretender %s have no methods, annotated with @MBeanMethod", pretenderClass.getName())); } InterfaceMaker interfaceMaker = new InterfaceMaker(); interfaceMaker.setNamingPolicy(new DefinedNameNamingPolicy(mbeanInterfaceName)); for (Method method : methods) { interfaceMaker.add(method); } Class mbeanInterface = interfaceMaker.create(); Enhancer enhancer = new Enhancer(); enhancer.setNamingPolicy(new DefinedNameNamingPolicy(mbeanName)); //enhancer.setSuperclass(pretenderClass); enhancer.setInterfaces(new Class[]{mbeanInterface}); enhancer.setCallback(new MBeanMethodInterceptor(mbeanPretender)); //we know the result type //noinspection unchecked return enhancer.create(); } private static class DefinedNameNamingPolicy implements NamingPolicy { private final String name; public DefinedNameNamingPolicy(String name) { this.name = name; } @Override public String getClassName(String prefix, String source, Object key, Predicate names) { return name; } } private static class MBeanMethodInterceptor implements MethodInterceptor { private final Object mbeanPretender; private final Class<?> mbeanPretenderClass; public MBeanMethodInterceptor(Object mbeanPretender) { this.mbeanPretender = mbeanPretender; this.mbeanPretenderClass = mbeanPretender.getClass(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return mbeanPretenderClass.getMethod(method.getName(), method.getParameterTypes()).invoke(mbeanPretender, args); } } }