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.proxy.ejb;
023:
024: import java.io.IOException;
025: import java.io.ObjectOutput;
026: import java.io.ObjectInput;
027: import java.lang.reflect.Method;
028: import java.util.List;
029: import java.util.HashMap;
030: import java.util.Map;
031:
032: import org.jboss.ejb.ListCacheKey;
033: import org.jboss.invocation.Invocation;
034:
035: /**
036: * An EJB CMP entity bean proxy class holds info about the List that the entity belongs to,
037: * is used for reading ahead.
038: *
039: * @author <a href="mailto:on@ibis.odessa.ua">Oleg Nitz</a>
040: * @version $Revision: 57209 $
041: *
042: * @todo: (marcf) methinks that this behavior should be moved to a REAL interceptor (i.e not as extends)
043: */
044: public class ListEntityInterceptor extends EntityInterceptor {
045: /** Serial Version Identifier. @since 1.1 */
046: private static final long serialVersionUID = -5165912623246270565L;
047:
048: protected static final Method GET_READ_AHEAD_VALUES;
049:
050: // Attributes ----------------------------------------------------
051:
052: /**
053: * A List that this entity belongs to (used for reading ahead).
054: */
055: private List list;
056:
057: /**
058: * A hash map of read ahead values, maps Methods to values.
059: */
060: private transient HashMap readAheadValues;
061:
062: // Static --------------------------------------------------------
063:
064: static {
065: try {
066: final Class[] empty = {};
067:
068: GET_READ_AHEAD_VALUES = ReadAheadBuffer.class.getMethod(
069: "getReadAheadValues", empty);
070: } catch (Exception e) {
071: e.printStackTrace();
072: throw new ExceptionInInitializerError(e);
073: }
074: }
075:
076: // Constructors --------------------------------------------------
077:
078: /**
079: * No-argument constructor for externalization.
080: */
081: public ListEntityInterceptor() {
082: }
083:
084: /**
085: * Construct a <tt>ListEntityProxy</tt>.
086: *
087: * @param name The JNDI name of the container that we proxy for.
088: * @param container The remote interface of the invoker for which
089: * this is a proxy for.
090: * @param id The primary key of the entity.
091: * @param optimize True if the proxy will attempt to optimize
092: * VM-local calls.
093: * @param list A List that this entity belongs to (used for reading ahead).
094: * @param listId The list id.
095: * @param index The index of this entity in the list.
096: *
097: * @throws NullPointerException Id may not be null.
098: */
099:
100: public ListEntityInterceptor(List list) {
101: this .list = list;
102: }
103:
104: // Public --------------------------------------------------------
105:
106: public Map getReadAheadValues() {
107: if (readAheadValues == null) {
108: readAheadValues = new HashMap();
109: }
110: return readAheadValues;
111: }
112:
113: /**
114: * InvocationHandler implementation.
115: *
116: * @param proxy The proxy object.
117: * @param m The method being invoked.
118: * @param args The arguments for the method.
119: *
120: * @throws Throwable Any exception or error thrown while processing.
121: */
122: public Object invoke(Invocation invocation) throws Throwable {
123: Object result;
124: ReadAheadResult raResult;
125: Object[] aheadResult;
126: int from;
127: int to;
128: ReadAheadBuffer buf;
129:
130: Method m = invocation.getMethod();
131:
132: if (m.equals(GET_READ_AHEAD_VALUES)) {
133: return getReadAheadValues();
134: }
135:
136: // have we read ahead the result?
137: if (readAheadValues != null) {
138: result = readAheadValues.get(m);
139: if (readAheadValues.containsKey(m)) {
140: return readAheadValues.remove(m);
141: }
142: }
143:
144: result = super .invoke(invocation);
145:
146: // marcf : I think all these will map nicely to the in/out of real interceptor, i.e. do not "extend"
147:
148: if (result instanceof ReadAheadResult) {
149: raResult = (ReadAheadResult) result;
150: aheadResult = raResult.getAheadResult();
151: ListCacheKey key = (ListCacheKey) invocation
152: .getInvocationContext().getCacheId();
153: from = key.getIndex() + 1;
154: to = Math.min(from + aheadResult.length, list.size());
155: for (int i = from; i < to; i++) {
156: buf = (ReadAheadBuffer) list.get(i);
157: buf.getReadAheadValues().put(m, aheadResult[i - from]);
158: }
159: return raResult.getMainResult();
160: } else {
161: return result;
162: }
163: }
164:
165: // Package protected ---------------------------------------------
166:
167: // Protected -----------------------------------------------------
168:
169: /**
170: * Externalization support.
171: *
172: * @param out
173: *
174: * @throws IOException
175: */
176: public void writeExternal(final ObjectOutput out)
177: throws IOException {
178: super .writeExternal(out);
179: out.writeObject(list);
180: }
181:
182: /**
183: * Externalization support.
184: *
185: * @param in
186: *
187: * @throws IOException
188: * @throws ClassNotFoundException
189: */
190: public void readExternal(final ObjectInput in) throws IOException,
191: ClassNotFoundException {
192: super .readExternal(in);
193: list = (List) in.readObject();
194: }
195:
196: // Private -------------------------------------------------------
197:
198: // Inner classes -------------------------------------------------
199: }
|