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.ejb3.stateful;
023:
024: import java.io.Externalizable;
025: import java.io.IOException;
026: import java.io.ObjectInput;
027: import java.io.ObjectOutput;
028: import java.util.List;
029: import java.util.Map;
030: import java.util.concurrent.locks.ReentrantLock;
031: import javax.ejb.EJBContext;
032: import javax.persistence.EntityManager;
033: import org.jboss.aop.metadata.SimpleMetaData;
034: import org.jboss.ejb3.Container;
035: import org.jboss.ejb3.interceptor.InterceptorInfo;
036:
037: /**
038: * Proxy to a NestedStatefulBeanContext that can be independently passivated,
039: * activated and replicated without disturbing the object it is proxying.
040: *
041: * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
042: * @author Brian Stansberry
043: *
044: * @version $Revision: 60652 $
045: */
046: public class ProxiedStatefulBeanContext extends StatefulBeanContext
047: implements Externalizable {
048: /** The serialVersionUID */
049: private static final long serialVersionUID = -5156610459343035743L;
050:
051: private transient StatefulBeanContext delegate;
052:
053: private Object oid;
054:
055: private String containerId;
056:
057: private StatefulBeanContextReference parentRef;
058:
059: public ProxiedStatefulBeanContext(StatefulBeanContext delegate) {
060: this .delegate = delegate;
061: oid = delegate.getId();
062: containerId = delegate.getContainer().getObjectName()
063: .getCanonicalName();
064: parentRef = new StatefulBeanContextReference(delegate
065: .getContainedIn());
066: }
067:
068: public ProxiedStatefulBeanContext() {
069: }
070:
071: protected StatefulBeanContext getDelegate() {
072: if (delegate == null) {
073: for (StatefulBeanContext ctx : parentRef.getBeanContext()
074: .getContains()) {
075: Object matchingOid = ctx.getId();
076: if (oid.equals(matchingOid)
077: && ctx.getContainer().getObjectName()
078: .getCanonicalName().equals(containerId)) {
079: delegate = ctx;
080: break;
081: }
082: }
083: if (delegate == null)
084: throw new RuntimeException("Failed to read delegate");
085:
086: // If we just read our delegate, it's possible there's been a
087: // failover and a remote node still has a ref to a stale delegate.
088: // So, we should be replicated to invalidate the remote node.
089: this .markedForReplication = true;
090: }
091: return delegate;
092: }
093:
094: public void writeExternal(ObjectOutput out) throws IOException {
095: out.writeObject(oid);
096: out.writeUTF(containerId);
097: out.writeObject(parentRef);
098: }
099:
100: public void readExternal(ObjectInput in) throws IOException,
101: ClassNotFoundException {
102: oid = in.readObject();
103: containerId = in.readUTF();
104: parentRef = (StatefulBeanContextReference) in.readObject();
105: }
106:
107: @Override
108: public List<StatefulBeanContext> getContains() {
109: return getDelegate().getContains();
110: }
111:
112: @Override
113: public EntityManager getExtendedPersistenceContext(String id) {
114: return getDelegate().getExtendedPersistenceContext(id);
115: }
116:
117: @Override
118: public void addExtendedPersistenceContext(String id,
119: EntityManager pc) {
120: getDelegate().addExtendedPersistenceContext(id, pc);
121: }
122:
123: @Override
124: public Map<String, EntityManager> getExtendedPersistenceContexts() {
125: return getDelegate().getExtendedPersistenceContexts();
126: }
127:
128: @Override
129: public void removeExtendedPersistenceContext(String id) {
130: getDelegate().removeExtendedPersistenceContext(id);
131: }
132:
133: @Override
134: public boolean scanForExtendedPersistenceContext(String id,
135: StatefulBeanContext ignore) {
136: return getDelegate().scanForExtendedPersistenceContext(id,
137: ignore);
138: }
139:
140: @Override
141: public StatefulBeanContext getContainedIn() {
142: return getDelegate().getContainedIn();
143: }
144:
145: @Override
146: public void addContains(StatefulBeanContext ctx) {
147: getDelegate().addContains(ctx);
148: }
149:
150: @Override
151: public void removeContains(StatefulBeanContext ctx) {
152: getDelegate().removeContains(ctx);
153: }
154:
155: @Override
156: public StatefulBeanContext pushContainedIn() {
157: return getDelegate().pushContainedIn();
158: }
159:
160: @Override
161: public void popContainedIn() {
162: getDelegate().popContainedIn();
163: }
164:
165: @Override
166: public StatefulBeanContext getUltimateContainedIn() {
167: return getDelegate().getUltimateContainedIn();
168: }
169:
170: @Override
171: public boolean isInUse() {
172: // Don't call delegate
173: return super .isInUse();
174: }
175:
176: @Override
177: public void setInUse(boolean inUse) {
178: super .setInUse(inUse);
179: // delegate needs to know this for getCanPassivate()
180: getDelegate().setInUse(inUse);
181:
182: if (!inUse) {
183: // drop ref to delegate, as the delegate can be passivated/activated
184: // without our knowledge, and if that happens we have a ref to a
185: // stale delegate.
186: delegate = null;
187: }
188: }
189:
190: @Override
191: public boolean isDiscarded() {
192: return getDelegate().isDiscarded();
193: }
194:
195: @Override
196: public void setDiscarded(boolean discarded) {
197: getDelegate().setDiscarded(discarded);
198: }
199:
200: @Override
201: public boolean isRemoved() {
202: return getDelegate().isRemoved();
203: }
204:
205: @Override
206: public ReentrantLock getLock() {
207: return getDelegate().getLock();
208: }
209:
210: @Override
211: public boolean isInInvocation() {
212: return getDelegate().isInInvocation();
213: }
214:
215: @Override
216: public void setInInvocation(boolean inInvocation) {
217: getDelegate().setInInvocation(inInvocation);
218: }
219:
220: @Override
221: public Object getId() {
222: return getDelegate().getId();
223: }
224:
225: @Override
226: public void setId(Object id) {
227: this .oid = id;
228: getDelegate().setId(id);
229: }
230:
231: @Override
232: public boolean isTxSynchronized() {
233: return getDelegate().isTxSynchronized();
234: }
235:
236: @Override
237: public void setTxSynchronized(boolean txSynchronized) {
238: getDelegate().setTxSynchronized(txSynchronized);
239: }
240:
241: @Override
242: public void remove() {
243: getDelegate().remove();
244: }
245:
246: @Override
247: public void setContainer(Container container) {
248: getDelegate().setContainer(container);
249: }
250:
251: @Override
252: public Container getContainer() {
253: return getDelegate().getContainer();
254: }
255:
256: @Override
257: public Object getInstance() {
258: return getDelegate().getInstance();
259: }
260:
261: @Override
262: public SimpleMetaData getMetaData() {
263: return getDelegate().getMetaData();
264: }
265:
266: @Override
267: public Object[] getInterceptorInstances(
268: InterceptorInfo[] interceptorInfos) {
269: return getDelegate().getInterceptorInstances(interceptorInfos);
270: }
271:
272: @Override
273: public void extractBeanAndInterceptors() {
274: getDelegate().extractBeanAndInterceptors();
275: }
276:
277: @Override
278: public void setInstance(Object instance) {
279: getDelegate().setInstance(instance);
280: }
281:
282: @Override
283: public void initialiseInterceptorInstances() {
284: getDelegate().initialiseInterceptorInstances();
285: }
286:
287: @Override
288: public EJBContext getEJBContext() {
289: return getDelegate().getEJBContext();
290: }
291:
292: /**
293: * Ignores the call, as passivation of this proxy context
294: * does not affect the underlying bean (which is passivated
295: * along with its parent context).
296: */
297: @Override
298: public void prePassivate() {
299: }
300:
301: /**
302: * Ignores the call, as activation of this proxy context
303: * does not affect the underlying bean (which is activated
304: * along with its parent context).
305: */
306: @Override
307: public void postActivate() {
308: }
309:
310: /**
311: * Ignores the call, as passivation of this proxy context
312: * does not affect the underlying bean (which is passivated
313: * along with its parent context).
314: */
315: @Override
316: public void passivateAfterReplication() {
317: // ignore
318: }
319:
320: /**
321: * Ignores the call, as activation of this proxy context
322: * does not affect the underlying bean (which is activated
323: * along with its parent context).
324: */
325: @Override
326: public void activateAfterReplication() {
327: // ignore
328: }
329:
330: @Override
331: public boolean getCanPassivate() {
332: if (delegate == null) {
333: // If we haven't deserialized our delegate, we're not in use
334: // on this node
335: return true;
336: }
337: // Just check if *we* are in use; whether any children are
338: // in use doesn't matter, since passivating this proxy
339: // doesn't affect children
340: return (isInUse() == false);
341: }
342:
343: @Override
344: public boolean getCanRemoveFromCache() {
345: return getDelegate().getCanRemoveFromCache();
346: }
347:
348: @Override
349: public boolean getReplicationIsPassivation() {
350: return getDelegate().getReplicationIsPassivation();
351: }
352:
353: @Override
354: public void setReplicationIsPassivation(
355: boolean replicationIsPassivation) {
356: getDelegate().setReplicationIsPassivation(
357: replicationIsPassivation);
358: }
359:
360: /**
361: * Ignores the call, as replication of this proxy context
362: * does not affect the underlying bean (which is replicated
363: * along with its parent context).
364: */
365: @Override
366: public void preReplicate() {
367: // ignore
368: }
369:
370: /**
371: * Ignores the call, as replication of this proxy context
372: * does not affect the underlying bean (which is replicated
373: * along with its parent context).
374: */
375: @Override
376: public void postReplicate() {
377: // ignore
378: }
379:
380: }
|