/* * JBoss, Home of Professional Open Source. * Copyright 2006, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.resource.connectionmanager; import java.lang.reflect.Method; import java.rmi.RemoteException; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.ejb.EJBException; import javax.ejb.RemoveException; import javax.management.MBeanServer; import javax.resource.ResourceException; import org.jboss.ejb.Container; import org.jboss.ejb.EnterpriseContext; import org.jboss.ejb.EntityContainer; import org.jboss.ejb.EntityEnterpriseContext; import org.jboss.ejb.EntityPersistenceManager; import org.jboss.ejb.GenericEntityObjectFactory; import org.jboss.ejb.plugins.AbstractInterceptor; import org.jboss.invocation.Invocation; import org.jboss.invocation.InvocationType; import org.jboss.logging.Logger; import org.jboss.mx.util.JMXExceptionDecoder; import org.jboss.mx.util.MBeanServerLocator; /** * CachedConnectionInterceptor * * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a> * @author <a href="mailto:E.Guib@ceyoniq.com">Erwin Guib</a> * @author <a href="mailto:adrian@jboss.com">Adrian Brock</a> * @version $Revision: 76129 $ */ public class CachedConnectionInterceptor extends AbstractInterceptor implements EntityPersistenceManager { private final CachedConnectionManager ccm; private final Logger log = Logger.getLogger(getClass()); private Container container; private EntityPersistenceManager pm; // contains the JNDI names of unshareable resources private Set unsharableResources = new HashSet(); public CachedConnectionInterceptor() throws Exception { try { MBeanServer server = MBeanServerLocator.locateJBoss(); ccm = (CachedConnectionManager) server.getAttribute(CachedConnectionManagerMBean.OBJECT_NAME, "Instance"); } catch (Exception e) { JMXExceptionDecoder.rethrow(e); throw e; } } @SuppressWarnings("deprecation") public void start() throws Exception { log.debug("start called in CachedConnectionInterceptor"); if (container == null) { log.warn("container is null, can't steal persistence manager"); return; } if (container instanceof EntityContainer) { EntityContainer ec = (EntityContainer) container; if (ec.getPersistenceManager() == null) { log.info("no persistence manager in container!"); return; } if (ec.getPersistenceManager() == this) { log.info(" persistence manager in container already set!"); return; } pm = ec.getPersistenceManager(); ec.setPersistenceManager(this); } // get the JNDI names for all resources that are referenced "Unshareable" org.jboss.metadata.BeanMetaData bmd = container.getBeanMetaData(); org.jboss.metadata.ApplicationMetaData appMetaData = bmd.getApplicationMetaData(); org.jboss.metadata.ResourceRefMetaData resRefMetaData; String jndiName; for (Iterator iter = bmd.getResourceReferences(); iter.hasNext();) { resRefMetaData = (org.jboss.metadata.ResourceRefMetaData) iter.next(); jndiName = resRefMetaData.getJndiName(); if (jndiName == null) { jndiName = appMetaData.getResourceByName(resRefMetaData.getResourceName()); } if (jndiName != null && resRefMetaData.isShareable() == false) { int i = jndiName.indexOf(':'); if (jndiName.charAt(i + 1) == '/') { i++; } unsharableResources.add(jndiName.substring(i + 1)); } } } public void stop() { if (container != null && pm != null && ((EntityContainer) container).getPersistenceManager() == this) { ((EntityContainer) container).setPersistenceManager(pm); pm = null; } unsharableResources.clear(); } public Object invoke(Invocation mi) throws Exception { Object key = ((EnterpriseContext) mi.getEnterpriseContext()).getInstance(); try { ccm.pushMetaAwareObject(key, unsharableResources); try { return getNext().invoke(mi); } finally { ccm.popMetaAwareObject(unsharableResources); } } catch (ResourceException e) { InvocationType type = mi.getType(); boolean isLocal = (type == InvocationType.LOCAL || type == InvocationType.LOCALHOME); if (isLocal) throw new EJBException("Resource problem during invoke", e); else throw new RemoteException("Resource problem during invoke", e); } } public Object invokeHome(Invocation mi) throws Exception { EnterpriseContext ctx = (EnterpriseContext) mi.getEnterpriseContext(); if (ctx == null) return getNext().invokeHome(mi); else { Object key = ctx.getInstance(); try { ccm.pushMetaAwareObject(key, unsharableResources); try { return getNext().invokeHome(mi); } finally { ccm.popMetaAwareObject(unsharableResources); } } catch (ResourceException e) { InvocationType type = mi.getType(); boolean isLocal = (type == InvocationType.LOCAL || type == InvocationType.LOCALHOME); if (isLocal) throw new EJBException("Resource problem during invokeHome", e); else throw new RemoteException("Resource problem during invokeHome", e); } } } public void setContainer(Container container) { this.container = container; } public Container getContainer() { return container; } public Object createBeanClassInstance() throws Exception { return pm.createBeanClassInstance(); } public void createEntity(Method m, Object[] args, EntityEnterpriseContext instance) throws Exception { pm.createEntity(m, args, instance); } public void postCreateEntity(Method m, Object[] args, EntityEnterpriseContext instance) throws Exception { pm.postCreateEntity(m, args, instance); } public Object findEntity(Method finderMethod, Object[] args, EntityEnterpriseContext instance, GenericEntityObjectFactory factory) throws Exception { return pm.findEntity(finderMethod, args, instance, factory); } public Collection findEntities(Method finderMethod, Object[] args, EntityEnterpriseContext instance, GenericEntityObjectFactory factory) throws Exception { return pm.findEntities(finderMethod, args, instance, factory); } public void activateEntity(EntityEnterpriseContext instance) throws RemoteException { pm.activateEntity(instance); } public void loadEntity(EntityEnterpriseContext instance) throws RemoteException { pm.loadEntity(instance); } public boolean isStoreRequired(EntityEnterpriseContext instance) throws Exception { return pm.isStoreRequired(instance); } public boolean isModified(EntityEnterpriseContext ctx) throws Exception { return pm.isModified(ctx); } public void storeEntity(EntityEnterpriseContext ctx) throws RemoteException { Object key = ctx.getInstance(); try { ccm.pushMetaAwareObject(key, unsharableResources); try { pm.storeEntity(ctx); } finally { ccm.popMetaAwareObject(unsharableResources); } } catch (ResourceException e) { throw new RemoteException("Could not store!: ", e); } } public void invokeEjbStore(EntityEnterpriseContext ctx) throws RemoteException { Object key = ctx.getInstance(); try { ccm.pushMetaAwareObject(key, unsharableResources); try { pm.invokeEjbStore(ctx); } finally { ccm.popMetaAwareObject(unsharableResources); } } catch (ResourceException e) { throw new RemoteException("Could not store!: ", e); } } public void passivateEntity(EntityEnterpriseContext instance) throws RemoteException { pm.passivateEntity(instance); } public void removeEntity(EntityEnterpriseContext instance) throws RemoteException, RemoveException { pm.removeEntity(instance); } /** Return the real EntityPersistenceManager to which this interceptor delegates. @return the real EntityPersistenceManager */ public EntityPersistenceManager getDelegatePersistenceManager() { return pm; } }