/*
* 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.jpa;
import org.hotswap.agent.annotation.OnClassLoadEvent;
import org.hotswap.agent.javassist.CannotCompileException;
import org.hotswap.agent.javassist.CtClass;
import org.hotswap.agent.javassist.CtConstructor;
import org.hotswap.agent.javassist.CtMethod;
import org.hotswap.agent.javassist.CtNewMethod;
import org.hotswap.agent.logging.AgentLogger;
import org.hotswap.agent.util.PluginManagerInvoker;
/**
* Static transformers for Hibernate plugin.
*/
public class Hibernate3JPATransformers {
/** The logger. */
private static AgentLogger LOGGER = AgentLogger.getLogger(Hibernate3JPATransformers.class);
/**
* Override HibernatePersistence.createContainerEntityManagerFactory() to return EntityManagerFactory proxy object.
* {@link org.hotswap.agent.plugin.hibernate3.jpa.proxy.EntityManagerFactoryProxy} holds reference to all proxied factories
* and on refresh command replaces internal factory with fresh instance.
* <p/>
* Two variants covered - createContainerEntityManagerFactory and createEntityManagerFactory.
* <p/>
* After the entity manager factory and it's proxy are instantiated, plugin init method is invoked.
*
* @param clazz the clazz
* @throws Exception the exception
*/
@OnClassLoadEvent(classNameRegexp = "org.hibernate.ejb.HibernatePersistence")
public static void proxyHibernatePersistence(CtClass clazz) throws Exception {
LOGGER.debug("Override org.hibernate.ejb.HibernatePersistence#createContainerEntityManagerFactory and createEntityManagerFactory to create a EntityManagerFactoryProxy proxy.");
CtMethod oldMethod = clazz.getDeclaredMethod("createContainerEntityManagerFactory");
oldMethod.setName("_createContainerEntityManagerFactory" + clazz.getSimpleName());
CtMethod newMethod = CtNewMethod.make(
"public javax.persistence.EntityManagerFactory createContainerEntityManagerFactory(javax.persistence.spi.PersistenceUnitInfo info, java.util.Map properties) {" +
" return " + Hibernate3JPAHelper.class.getName() + ".createContainerEntityManagerFactoryProxy(" +
" info, properties, _createContainerEntityManagerFactory" + clazz.getSimpleName() + "(info, properties)); " +
"}", clazz);
clazz.addMethod(newMethod);
oldMethod = clazz.getDeclaredMethod("createEntityManagerFactory");
oldMethod.setName("_createEntityManagerFactory" + clazz.getSimpleName());
newMethod = CtNewMethod.make(
"public javax.persistence.EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, java.util.Map properties) {" +
" return " + Hibernate3JPAHelper.class.getName() + ".createEntityManagerFactoryProxy(" +
" persistenceUnitName, properties, _createEntityManagerFactory" + clazz.getSimpleName() + "(persistenceUnitName, properties)); " +
"}", clazz);
clazz.addMethod(newMethod);
}
/**
* Bean meta data manager register variable.
*
* @param ctClass the ct class
* @throws CannotCompileException the cannot compile exception
*/
@OnClassLoadEvent(classNameRegexp = "org.hibernate.validator.internal.metadata.BeanMetaDataManager")
public static void beanMetaDataManagerRegisterVariable(CtClass ctClass) throws CannotCompileException {
StringBuilder src = new StringBuilder("{");
src.append(PluginManagerInvoker.buildInitializePlugin(Hibernate3JPAPlugin.class));
src.append(PluginManagerInvoker.buildCallPluginMethod(Hibernate3JPAPlugin.class, "registerBeanMetaDataManager",
"this", "java.lang.Object"));
src.append("}");
for (CtConstructor constructor : ctClass.getDeclaredConstructors()) {
constructor.insertAfter(src.toString());
}
ctClass.addMethod(CtNewMethod.make("public void __resetCache() {" +
" this.beanMetaDataCache.clear(); " +
"}", ctClass));
LOGGER.debug("org.hibernate.validator.internal.metadata.BeanMetaDataManager - added method __resetCache().");
}
/**
* Annotation meta data provider register variable.
*
* @param ctClass the ct class
* @throws CannotCompileException the cannot compile exception
*/
@OnClassLoadEvent(classNameRegexp = "org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider")
public static void annotationMetaDataProviderRegisterVariable(CtClass ctClass) throws CannotCompileException {
StringBuilder src = new StringBuilder("{");
src.append(PluginManagerInvoker.buildInitializePlugin(Hibernate3JPAPlugin.class));
src.append(PluginManagerInvoker.buildCallPluginMethod(Hibernate3JPAPlugin.class, "registerAnnotationMetaDataProvider",
"this", "java.lang.Object"));
src.append("}");
for (CtConstructor constructor : ctClass.getDeclaredConstructors()) {
constructor.insertAfter(src.toString());
}
ctClass.addMethod(CtNewMethod.make("public void __resetCache() {" +
" this.configuredBeans.clear(); " +
"}", ctClass));
LOGGER.debug("org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider - added method __resetCache().");
}
}