package org.hotswap.agent.plugin.hibernate.proxy;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.service.ServiceRegistry;
import org.hotswap.agent.javassist.util.proxy.MethodHandler;
import org.hotswap.agent.javassist.util.proxy.Proxy;
import org.hotswap.agent.javassist.util.proxy.ProxyFactory;
import sun.reflect.ReflectionFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* For Hibernate without EJB (EntityManager).
* <p/>
* TODO - Not tested, some additional Configuration cleanup may be necessary
*
* @author Jiri Bubnik
*/
public class SessionFactoryProxy {
private static Map<Configuration, SessionFactoryProxy> proxiedFactories = new HashMap<Configuration, SessionFactoryProxy>();
private SessionFactoryProxy(Configuration configuration) {
this.configuration = configuration;
}
public static SessionFactoryProxy getWrapper(Configuration configuration) {
if (!proxiedFactories.containsKey(configuration)) {
proxiedFactories.put(configuration, new SessionFactoryProxy(configuration));
}
return proxiedFactories.get(configuration);
}
public static void refreshProxiedFactories() {
for (SessionFactoryProxy wrapper : proxiedFactories.values())
try {
wrapper.refreshProxiedFactory();
} catch (Exception e) {
e.printStackTrace();
}
}
public void refreshProxiedFactory() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method m = Configuration.class.getDeclaredMethod("_buildSessionFactory", ServiceRegistry.class);
currentInstance = (SessionFactory) m.invoke(configuration, serviceRegistry);
}
private Configuration configuration;
private SessionFactory currentInstance;
private ServiceRegistry serviceRegistry;
public SessionFactory proxy(SessionFactory sessionFactory, ServiceRegistry serviceRegistry) {
this.currentInstance = sessionFactory;
this.serviceRegistry = serviceRegistry;
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(SessionFactoryImpl.class);
factory.setInterfaces(new Class[]{SessionFactory.class});
MethodHandler handler = new MethodHandler() {
@Override
public Object invoke(Object self, Method overridden, Method forwarder,
Object[] args) throws Throwable {
return overridden.invoke(currentInstance, args);
}
};
Object instance;
try {
Constructor constructor = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(factory.createClass(), Object.class.getDeclaredConstructor(new Class[0]));
instance = constructor.newInstance();
((Proxy) instance).setHandler(handler);
} catch (Exception e) {
throw new Error("Unable instantiate SessionFactory proxy", e);
}
return (SessionFactory) instance;
}
}