001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.cache.invalidation.triggers;
023:
024: import org.jboss.metadata.XmlLoadable;
025: import org.jboss.metadata.MetaData;
026: import org.w3c.dom.Element;
027:
028: /**
029: * The role of this interceptor is to detect that an entity has been modified
030: * after an invocation has been performed an use the InvalidationsTxGrouper
031: * static class so that invalidation messages can be groupped and
032: * sent at transaction-commit time in a single batch.
033: *
034: * @author <a href="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>
035: * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
036: * @version $Revision: 57209 $
037: */
038: public class EntityBeanCacheBatchInvalidatorInterceptor extends
039: org.jboss.ejb.plugins.AbstractInterceptor implements
040: XmlLoadable {
041: protected boolean doCacheInvalidations = true;
042: protected org.jboss.cache.invalidation.InvalidationManagerMBean invalMgr = null;
043: protected org.jboss.cache.invalidation.InvalidationGroup ig = null;
044: protected org.jboss.ejb.EntityContainer container = null;
045: public boolean invalidateRelated;
046:
047: public void start() throws Exception {
048: org.jboss.metadata.EntityMetaData emd = ((org.jboss.metadata.EntityMetaData) this
049: .getContainer().getBeanMetaData());
050: doCacheInvalidations = emd.doDistributedCacheInvalidations();
051:
052: if (doCacheInvalidations) {
053: // we are interested in receiving cache invalidation callbacks
054: //
055: String groupName = emd
056: .getDistributedCacheInvalidationConfig()
057: .getInvalidationGroupName();
058: String imName = emd.getDistributedCacheInvalidationConfig()
059: .getInvalidationManagerName();
060:
061: this .invalMgr = (org.jboss.cache.invalidation.InvalidationManagerMBean) org.jboss.system.Registry
062: .lookup(imName);
063: this .ig = this .invalMgr.getInvalidationGroup(groupName);
064: }
065: }
066:
067: public void stop() {
068: this .invalMgr = null;
069: // ig can be null if cache-invalidation is false
070: if (ig != null) {
071: this .ig.removeReference(); // decrease the usage counter
072: this .ig = null;
073: }
074: }
075:
076: // Interceptor implementation --------------------------------------
077:
078: protected boolean changed(org.jboss.invocation.Invocation mi,
079: org.jboss.ejb.EntityEnterpriseContext ctx) throws Exception {
080: if (ctx.getId() == null)
081: return true;
082:
083: if (!container.isReadOnly()) {
084: java.lang.reflect.Method method = mi.getMethod();
085: if (method == null
086: || !container.getBeanMetaData().isMethodReadOnly(
087: method.getName())) {
088: return invalidateRelated ? container
089: .getPersistenceManager().isModified(ctx)
090: : container.getPersistenceManager()
091: .isStoreRequired(ctx);
092: }
093: }
094: return false;
095: }
096:
097: public Object invoke(org.jboss.invocation.Invocation mi)
098: throws Exception {
099: if (doCacheInvalidations) {
100: // We are going to work with the context a lot
101: org.jboss.ejb.EntityEnterpriseContext ctx = (org.jboss.ejb.EntityEnterpriseContext) mi
102: .getEnterpriseContext();
103: Object id = ctx.getId();
104:
105: // The Tx coming as part of the Method Invocation
106: javax.transaction.Transaction tx = mi.getTransaction();
107:
108: // Invocation with a running Transaction
109: if (tx != null
110: && tx.getStatus() != javax.transaction.Status.STATUS_NO_TRANSACTION) {
111: //Invoke down the chain
112: Object retVal = getNext().invoke(mi);
113:
114: if (changed(mi, ctx)) {
115: org.jboss.cache.invalidation.InvalidationsTxGrouper
116: .registerInvalidationSynchronization(tx,
117: this .ig, (java.io.Serializable) id);
118: }
119:
120: // return the return value
121: return retVal;
122: }
123: //
124: else { // No tx
125: Object result = getNext().invoke(mi);
126:
127: if (changed(mi, ctx)) {
128: org.jboss.cache.invalidation.InvalidationsTxGrouper
129: .registerInvalidationSynchronization(tx,
130: this .ig, (java.io.Serializable) id);
131: }
132: return result;
133: }
134: } else {
135: return getNext().invoke(mi);
136: }
137: }
138:
139: public void setContainer(org.jboss.ejb.Container container) {
140: this .container = (org.jboss.ejb.EntityContainer) container;
141: }
142:
143: public org.jboss.ejb.Container getContainer() {
144: return container;
145: }
146:
147: // XmlLoadable implementation --------------------------------------------------------
148:
149: public void importXml(Element element) throws Exception {
150: String str = MetaData.getElementAttribute(element,
151: "invalidate-related");
152: invalidateRelated = (str == null ? true : Boolean.valueOf(str)
153: .booleanValue());
154: if (log.isTraceEnabled()) {
155: log.trace("invalidate-related: " + invalidateRelated);
156: }
157: }
158: }
|