package com.googlecode.tawus.hibernate.internal.services; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import org.apache.tapestry5.ioc.services.Builtin; import org.apache.tapestry5.ioc.services.ClassFab; import org.apache.tapestry5.ioc.services.ClassFactory; import org.apache.tapestry5.ioc.services.MethodSignature; import org.apache.tapestry5.ioc.util.BodyBuilder; import org.hibernate.Session; import com.googlecode.tawus.hibernate.services.HibernateSessionManager; import com.googlecode.tawus.hibernate.services.SessionShadowBuilder; public class SessionShadowBuilderImpl implements SessionShadowBuilder { private final ClassFactory classFactory; public SessionShadowBuilderImpl(@Builtin ClassFactory classFactory) { this.classFactory = classFactory; } public Session build(HibernateSessionManager sm, String sessionFactoryId) { @SuppressWarnings("rawtypes") Class sourceClass = sm.getClass(); ClassFab cf = classFactory.newClass(Session.class); cf.addField("_source", Modifier.PRIVATE | Modifier.FINAL, sourceClass); cf.addConstructor(new Class[] { sourceClass }, null, "_source = $1;"); BodyBuilder body = new BodyBuilder(); body.begin(); body.addln("%s result = _source.getSession(\"%s\");", sourceClass.getName(), sessionFactoryId); body.addln("if (result == null)"); body.begin(); body.addln("throw new NullPointerException(%s.buildMessage(_source, \"getSession(%s)\"));", getClass().getName(), sessionFactoryId); body.end(); body.addln("return result;"); body.end(); MethodSignature sig = new MethodSignature(Session.class, "_delegate", null, null); cf.addMethod(Modifier.PRIVATE, sig, body.toString()); String toString = String.format("<Shadow: getSession(%s) of HibernateSessionManager>", sessionFactoryId); cf.proxyMethodsToDelegate(Session.class, "_delegate()", toString); @SuppressWarnings("rawtypes") Class shadowClass = cf.createClass(); try { @SuppressWarnings("rawtypes") Constructor cc = shadowClass.getConstructors()[0]; Object instance = cc.newInstance(sm); return (Session) instance; } catch (Exception ex) { // Should not be reachable throw new RuntimeException(ex); } } public static final String buildMessage(Object source, String propertyName) { return String.format( "Unable to delegate method invocation to property '%s' of %s, because the property is null.", propertyName, source); } }