/* * Copyright 2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hotswap.agent.plugin.hibernate3.session; import org.hotswap.agent.annotation.OnClassLoadEvent; import org.hotswap.agent.javassist.ClassPool; import org.hotswap.agent.javassist.CtClass; import org.hotswap.agent.javassist.CtConstructor; import org.hotswap.agent.javassist.CtField; import org.hotswap.agent.javassist.CtMethod; import org.hotswap.agent.javassist.CtNewMethod; import org.hotswap.agent.logging.AgentLogger; import org.hotswap.agent.plugin.hibernate3.session.proxy.SessionFactoryProxy; import org.hotswap.agent.plugin.hibernate3.session.util.ProxyUtil; import org.hotswap.agent.util.PluginManagerInvoker; /** * Static transformers for Hibernate Session factory plugin. * * @author alpapad@gmail.com */ public class Hibernate3Transformers { /** The logger. */ private static AgentLogger LOGGER = AgentLogger.getLogger(Hibernate3Transformers.class); /** * Ensure org.hibernate.impl.SessionFactoryImpl is Proxyable * * @param clazz * the clazz * @param classPool * the class pool * @param classLoader * the class loader * @throws Exception * the exception */ @OnClassLoadEvent(classNameRegexp = "org.hibernate.impl.SessionFactoryImpl") public static void removeSessionFactoryImplFinalFlag(CtClass clazz, ClassPool classPool, ClassLoader classLoader) throws Exception { ProxyUtil.ensureProxyable(clazz); LOGGER.info("Override org.hibernate.impl.SessionFactoryImpl {}", classLoader); } /** * Patch org.hibernate.cfg.Configuration with ReInitializable features. When * java8+ is supprted, then make methods default in ReInitializable * * @param classLoader * the class loader * @param classPool * the class pool * @param clazz * the clazz * @throws Exception * the exception */ @OnClassLoadEvent(classNameRegexp = "org.hibernate.cfg.Configuration") public static void proxySessionFactory(ClassLoader classLoader, ClassPool classPool, CtClass clazz) throws Exception { LOGGER.debug("Adding interface o.h.a.p.h.s.p.ReInitializable to org.hibernate.cfg.Configuration."); clazz.addInterface(classPool.get("org.hotswap.agent.plugin.hibernate3.session.proxy.ReInitializable")); CtField field = CtField.make("private org.hotswap.agent.plugin.hibernate3.session.proxy.OverrideConfig $$override = new org.hotswap.agent.plugin.hibernate3.session.proxy.OverrideConfig();", clazz); clazz.addField(field); LOGGER.debug("Patching org.hibernate.cfg.Configuration#buildSessionFactory to create a SessionFactoryProxy proxy."); CtMethod oldMethod = clazz.getDeclaredMethod("buildSessionFactory"); oldMethod.setName("_buildSessionFactory"); CtMethod newMethod = CtNewMethod.make(// "public org.hibernate.SessionFactory buildSessionFactory() throws org.hibernate.HibernateException {" + // " return " + SessionFactoryProxy.class.getName() + // " .getWrapper(this)" + // " .proxy(_buildSessionFactory()); " + // "}", clazz); clazz.addMethod(newMethod); LOGGER.debug("Adding org.hibernate.cfg.Configuration.reInitialize() method"); CtMethod reInitMethod = CtNewMethod.make(// "public void reInitialize(){" + // " this.settingsFactory = new org.hibernate.cfg.SettingsFactory();" + // " this.reset();" + // "}", clazz); clazz.addMethod(reInitMethod); LOGGER.debug("Adding org.hibernate.cfg.Configuration.getOverrideConfig() method"); CtMethod internalPropsMethod = CtNewMethod.make(// "public org.hotswap.agent.plugin.hibernate3.session.proxy.OverrideConfig getOverrideConfig(){" + // " return $$override;" + // "}", clazz); clazz.addMethod(internalPropsMethod); CtConstructor con = clazz.getDeclaredConstructor(new CtClass[] {}); LOGGER.debug("Patching org.hibernate.cfg.Configuration.<init>"); con.insertAfter(// "java.lang.ClassLoader $$cl = Thread.currentThread().getContextClassLoader();"// + PluginManagerInvoker.buildInitializePlugin(Hibernate3Plugin.class, "$$cl")// + "java.lang.String $$version = org.hibernate.Version.getVersionString();" // + PluginManagerInvoker.buildCallPluginMethod("$$cl", Hibernate3Plugin.class, "setVersion", "$$version", "java.lang.String")// ); ProxyUtil.addMethod(classLoader, classPool, clazz, "void", "hotSwap", null); ProxyUtil.addMethod(classLoader, classPool, clazz, "org.hibernate.cfg.Configuration", "setProperty", new String[] { "java.lang.String", "java.lang.String" }); ProxyUtil.addMethod(classLoader, classPool, clazz, "org.hibernate.cfg.Configuration", "configure", new String[] { "java.lang.String" }); ProxyUtil.addMethod(classLoader, classPool, clazz, "org.hibernate.cfg.Configuration", "configure", new String[] { "java.net.URL" }); ProxyUtil.addMethod(classLoader, classPool, clazz, "org.hibernate.cfg.Configuration", "configure", new String[] { "java.io.File" }); ProxyUtil.addMethod(classLoader, classPool, clazz, "org.hibernate.cfg.Configuration", "configure", new String[] { "org.w3c.dom.Document" }); ProxyUtil.addMethod(classLoader, classPool, clazz, "org.hibernate.cfg.Configuration", "configure", null); LOGGER.info("Hibernate3Plugin, patched org.hibernate.cfg.Configuration"); } /** * If org.hibernate.ejb.HibernatePersistence is loaded then we live in a JPA * environment. Disable the Hibernate3Plugin reload command * * @param clazz * the clazz * @throws Exception * the exception */ @OnClassLoadEvent(classNameRegexp = "org.hibernate.ejb.HibernatePersistence") public static void proxyHibernatePersistence(CtClass clazz) throws Exception { CtConstructor con = clazz.getDeclaredConstructor(new CtClass[] {}); LOGGER.debug("org.hibernate.ejb.HibernatePersistence.<init>"); con.insertAfter(// "java.lang.ClassLoader $$cl = Thread.currentThread().getContextClassLoader();"// + PluginManagerInvoker.buildInitializePlugin(Hibernate3Plugin.class, "$$cl")// + PluginManagerInvoker.buildCallPluginMethod("$$cl", Hibernate3Plugin.class, "disable")// ); } }