/* * $Id$ * * Copyright 2009 Glencoe Software, Inc. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.tools.hibernate; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import ome.util.SqlAction; import ome.util.TableIdGenerator; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.hibernate.Session; import org.hibernate.id.IdentifierGenerator; import org.hibernate.impl.SessionFactoryImpl; import org.springframework.aop.framework.ProxyFactory; import org.springframework.orm.hibernate3.SessionFactoryUtils; /** * Simple source of Thread-aware {@link Session} instances. Wraps a * call to {@link SessionFactoryUtils}. Should be safe to call from * within any service implementation call or inside of Executor.execute. * * @author Josh Moore, josh at glencoesoftware.com * @since 4.0 */ public class SessionFactory implements MethodInterceptor { private final static Set<String> FORBIDDEN = Collections.unmodifiableSet( new HashSet<String>( Arrays.asList( "createSQLQuery", "getSession", "doWork", "connection", "disconnect", "reconnect"))); static { // Check for spelling mistakes int found = 0; Method[] methods = Session.class.getMethods(); for (Method m : methods) { if (FORBIDDEN.contains(m.getName())) { found++; } } if (found < FORBIDDEN.size()) { throw new RuntimeException("Method name not found! " + FORBIDDEN); } } private final org.hibernate.SessionFactory factory; public SessionFactory(org.hibernate.SessionFactory factory, SqlAction isolatedSqlAction) { this.factory = factory; for (Object k : this.factory.getAllClassMetadata().keySet()) { IdentifierGenerator ig = ((SessionFactoryImpl) factory).getIdentifierGenerator((String)k); if (ig instanceof TableIdGenerator) { ((TableIdGenerator) ig).setSqlAction(isolatedSqlAction); } } } /** * Returns a session active for the current thread. The returned * instance will be wrapped with AOP to prevent certain usage. * @see <a href="http://trac.openmicroscopy.org/ome/ticket/73">Trac ticket #73</a> * @return a wrapped active Hibernate session */ public Session getSession() { Session unwrapped = SessionFactoryUtils.getSession(factory, false); ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setInterfaces(new Class[]{ Session.class, org.hibernate.classic.Session.class, org.hibernate.event.EventSource.class}); proxyFactory.setTarget(unwrapped); proxyFactory.addAdvice(0, this); return (Session) proxyFactory.getProxy(); } /** * Wraps all invocations to Session to prevent certain usages. * Note: {@link QueryBuilder} may unwrap the session in certain * cases. */ public Object invoke(MethodInvocation mi) throws Throwable { final String name = mi.getMethod().getName(); if (FORBIDDEN.contains(name)) { throw new ome.conditions.InternalException(String.format( "Usage of session.%s is forbidden. See ticket #73", name)); } return mi.proceed(); } }