class Hibernate3JPAPlugin {

    /** The Constant ENTITY_ANNOTATION. */
    private static final String ENTITY_ANNOTATION = "javax.persistence.Entity";

    /** The logger. */
    private static AgentLogger LOGGER = AgentLogger.getLogger(Hibernate3JPAPlugin.class);

    /** The scheduler. */
    @Init
    Scheduler scheduler;

    /** The app class loader. */
    @Init
    ClassLoader appClassLoader;

    /** The reg annotated meta data providers. */
    Set<Object> regAnnotatedMetaDataProviders = Collections.newSetFromMap(new WeakHashMap<Object, Boolean>());

    /** The reg bean meta data managers. */
    Set<Object> regBeanMetaDataManagers = Collections.newSetFromMap(new WeakHashMap<Object, Boolean>());

    /** The reload entity manager factory command. */
    // refresh commands
    Command reloadEntityManagerFactoryCommand = new ReflectionCommand(this, Hibernate3JPARefreshCommands.class.getName(),
            "reloadEntityManagerFactory");


    /** The invalidate hibernate validator caches. */
    private Command invalidateHibernateValidatorCaches = new Command() {
        @Override
        public void executeCommand() {<FILL_FUNCTION_BODY>}
    };

    /** The hibernate ejb. */
    // is EJB3 or plain hibernate
    boolean hibernateEjb;

    /**
     * Plugin initialization properties (from Hibernate3JPAHelper or
     * SessionFactoryProxy).
     *
     * @param version the version
     * @param hibernateEjb the hibernate ejb
     */
    public void init(String version, Boolean hibernateEjb) {
        LOGGER.info("Hibernate3 JPA plugin initialized - Hibernate Core version '{}'", version);
        this.hibernateEjb = hibernateEjb;
    }

    /**
     * Reload after entity class change. It covers also @Entity annotation
     * removal.
     *
     * @param clazz the clazz
     * @param original the original
     */
    @OnClassLoadEvent(classNameRegexp = ".*", events = LoadEvent.REDEFINE)
    public void entityReload(CtClass clazz, Class<?> original) {
        // TODO list of entity/resource files is known to hibernate, better to
        // check this list
        if (AnnotationHelper.hasAnnotation(original, ENTITY_ANNOTATION)
                || AnnotationHelper.hasAnnotation(clazz, ENTITY_ANNOTATION)) {
            LOGGER.debug("Entity reload class {}, original classloader {}", clazz.getName(), original.getClassLoader());
            refresh(100);
        }
    }

    /**
     * New entity class - not covered by reloading mechanism.
     * <p/>
     * Increase the reload timeout to avoid duplicate reloading in case of
     * recompile with IDE and delete/create event sequence - than create is
     * cached by this event and hotswap for the same class by entityReload.
     *
     * @param clazz the clazz
     * @throws Exception the exception
     */
    @OnClassFileEvent(classNameRegexp = ".*", events = { FileEvent.CREATE })
    public void newEntity(CtClass clazz) throws Exception {
        if (AnnotationHelper.hasAnnotation(clazz, ENTITY_ANNOTATION)) {
            refresh(500);
        }
    }

    /**
     * Reload on hbm file modifications.
     */
    @OnResourceFileEvent(path = "/", filter = ".*.hbm.xml")
    public void refreshOnHbm(){
        refresh(500);
    }

    /**
     * Reload on hibernate.cfg.xml file modifications
     */
    @OnResourceFileEvent(path = "/", filter = ".*.cfg.xml")
    public void refreshOnCfg(){
        refresh(500);
    }


    /**
     * Reload on persistence.xml file modifications
     */
    @OnResourceFileEvent(path = "/", filter = "persistence.xml")
    public void refreshOnPersistenceXml(){
        refresh(500);
    }


    /**
     * Invalidate class cache.
     *
     * @throws Exception the exception
     */
    @OnClassLoadEvent(classNameRegexp = ".*", events = LoadEvent.REDEFINE)
    public void invalidateClassCache() throws Exception {
        if (!regBeanMetaDataManagers.isEmpty() || !regAnnotatedMetaDataProviders.isEmpty()) {
            scheduler.scheduleCommand(invalidateHibernateValidatorCaches);
        }
    }

    // reload the configuration - schedule a command to run in the application
    // classloader and merge
    /**
     * Refresh.
     *
     * @param timeout the timeout
     */
    // duplicate commands.
    private void refresh(int timeout) {
        scheduler.scheduleCommand(reloadEntityManagerFactoryCommand, timeout);
    }

    /**
     * Register annotation meta data provider.
     *
     * @param annotatedMetaDataProvider the annotated meta data provider
     */
    public void registerAnnotationMetaDataProvider(Object annotatedMetaDataProvider) {
        regAnnotatedMetaDataProviders.add(annotatedMetaDataProvider);
    }

    /**
     * Register bean meta data manager.
     *
     * @param beanMetaDataManager the bean meta data manager
     */
    public void registerBeanMetaDataManager(Object beanMetaDataManager) {
        regBeanMetaDataManagers.add(beanMetaDataManager);
    }

    /**
     * Resolve class.
     *
     * @param name the name
     * @return the class
     * @throws ClassNotFoundException the class not found exception
     */
    private Class<?> resolveClass(String name) throws ClassNotFoundException {
        return Class.forName(name, true, appClassLoader);
    }

}

            LOGGER.debug("Refreshing BeanMetaDataManagerCache/AnnotatedMetaDataProvider cache.");

            try {
                Method resetCacheMethod1 = resolveClass(
                        "org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider")
                                .getDeclaredMethod("__resetCache");
                for (Object regAnnotatedDataManager : regAnnotatedMetaDataProviders) {
                    LOGGER.debug(
                            "Invoking org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider.__resetCache on {}",
                            regAnnotatedDataManager);
                    resetCacheMethod1.invoke(regAnnotatedDataManager);
                }
                Method resetCacheMethod2 = resolveClass("org.hibernate.validator.internal.metadata.BeanMetaDataManager")
                        .getDeclaredMethod("__resetCache");
                for (Object regBeanMetaDataManager : regBeanMetaDataManagers) {
                    LOGGER.debug(
                            "Invoking org.hibernate.validator.internal.metadata.BeanMetaDataManager.__resetCache on {}",
                            regBeanMetaDataManager);
                    resetCacheMethod2.invoke(regBeanMetaDataManager);
                }
            } catch (Exception e) {
                LOGGER.error("Error refreshing BeanMetaDataManagerCache/AnnotatedMetaDataProvider cache.", e);
            }
        
<no_super_class>