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.invocation;
023:
024: import java.io.Serializable;
025: import java.io.ObjectOutputStream;
026: import java.io.ByteArrayOutputStream;
027: import java.io.ObjectInputStream;
028: import java.io.ByteArrayInputStream;
029: import java.lang.reflect.InvocationTargetException;
030: import java.lang.reflect.Method;
031: import java.security.Principal;
032: import java.util.Map;
033: import java.util.HashMap;
034:
035: import javax.transaction.Transaction;
036:
037: /**
038: * The Invocation object is the generic object flowing through our interceptors.
039: *
040: * <p>The heart of it is the payload map that can contain anything we then
041: * put readers on them. The first <em>reader</em> is this
042: * <em>Invocation</em> object that can interpret the data in it.
043: *
044: * <p>Essentially we can carry ANYTHING from the client to the server, we keep
045: * a series of of predifined variables and method calls to get at the
046: * pointers. But really it is just a repository of objects.
047: *
048: * @author <a href="mailto:marc@jboss.org">Marc Fleury</a>
049: * @author <a href="mailto:christoph.jung@infor.de">Christoph G. Jung</a>
050: * @version $Revision: 57209 $
051: */
052: public class Invocation {
053: /** The signature of the invoke() method */
054: public static final String[] INVOKE_SIGNATURE = { "org.jboss.invocation.Invocation" };
055:
056: // The payload is a repository of everything associated with the invocation
057: // It is information that will need to travel
058:
059: /**
060: * Contextual information to the invocation that is not part of the payload.
061: */
062: public Map transient_payload;
063:
064: /**
065: * as_is classes that will not be marshalled by the invocation
066: * (java.* and javax.* or anything in system classpath is OK)
067: */
068: public Map as_is_payload;
069:
070: /** Payload will be marshalled for type hiding at the RMI layers. */
071: public Map payload;
072:
073: public InvocationContext invocationContext;
074: public Object[] args;
075: public Object objectName;
076: public Method method;
077: public InvocationType invocationType;
078:
079: // The variables used to indicate what type of data and where to put it.
080:
081: //
082: // We are using the generic payload to store some of our data, we define
083: // some integer entries. These are just some variables that we define for
084: // use in "typed" getters and setters. One can define anything either in
085: // here explicitely or through the use of external calls to getValue
086: //
087:
088: /**
089: * No-args constructor exposed for externalization only.
090: */
091: public Invocation() {
092: }
093:
094: public Invocation(Object id, Method m, Object[] args,
095: Transaction tx, Principal identity, Object credential) {
096: setId(id);
097: setMethod(m);
098: setArguments(args);
099: setTransaction(tx);
100: setPrincipal(identity);
101: setCredential(credential);
102: }
103:
104: /**
105: * The generic store of variables.
106: *
107: * <p>
108: * The generic getter and setter is really all that one needs to talk
109: * to this object. We introduce typed getters and setters for
110: * convenience and code readability in the codeba
111: */
112: public void setValue(Object key, Object value) {
113: setValue(key, value, PayloadKey.PAYLOAD);
114: }
115:
116: /**
117: * Advanced store
118: * Here you can pass a TYPE that indicates where to put the value.
119: * TRANSIENT: the value is put in a map that WON'T be passed
120: * AS_IS: no need to marshall the value when passed (use for all JDK
121: * java types)
122: * PAYLOAD: we need to marshall the value as its type is application specific
123: */
124: public void setValue(Object key, Object value, PayloadKey type) {
125: if (type == PayloadKey.TRANSIENT) {
126: getTransientPayload().put(key, value);
127: } else if (type == PayloadKey.AS_IS) {
128: getAsIsPayload().put(key, value);
129: } else if (type == PayloadKey.PAYLOAD) {
130: getPayload().put(key, value);
131: } else {
132: throw new IllegalArgumentException("Unknown PayloadKey: "
133: + type);
134: }
135: }
136:
137: /**
138: * Get a value from the stores.
139: */
140: public Object getValue(Object key) {
141: // find where it is
142: Object rtn = getPayloadValue(key);
143: if (rtn != null)
144: return rtn;
145:
146: rtn = getAsIsValue(key);
147: if (rtn != null)
148: return rtn;
149:
150: rtn = getTransientValue(key);
151: return rtn;
152: }
153:
154: public Object getPayloadValue(Object key) {
155: if (payload == null)
156: return null;
157: return payload.get(key);
158: }
159:
160: public Object getTransientValue(Object key) {
161: if (transient_payload == null)
162: return null;
163: return transient_payload.get(key);
164: }
165:
166: public Object getAsIsValue(Object key) {
167: if (as_is_payload == null)
168: return null;
169: return as_is_payload.get(key);
170: }
171:
172: //
173: // Convenience typed getters, use pre-declared keys in the store,
174: // but it all comes back to the payload, here you see the usage of the
175: // different payloads. Anything that has a well defined type can go in as_is
176: // Anything that is arbitrary and depends on the application needs to go in
177: // in the serialized payload. The "Transaction" is known, the type of the
178: // method arguments are not for example and are part of the EJB jar.
179: //
180:
181: /**
182: * set the transaction.
183: */
184: public void setTransaction(Transaction tx) {
185: if (tx instanceof Serializable)
186: getAsIsPayload().put(InvocationKey.TRANSACTION, tx);
187: else
188: getTransientPayload().put(InvocationKey.TRANSACTION, tx);
189: }
190:
191: /**
192: * get the transaction.
193: */
194: public Transaction getTransaction() {
195: Transaction tx = (Transaction) getAsIsPayload().get(
196: InvocationKey.TRANSACTION);
197: if (tx == null)
198: tx = (Transaction) getTransientPayload().get(
199: InvocationKey.TRANSACTION);
200: return tx;
201: }
202:
203: /**
204: * Change the security identity of this invocation.
205: */
206: public void setPrincipal(Principal principal) {
207: getAsIsPayload().put(InvocationKey.PRINCIPAL, principal);
208: }
209:
210: public Principal getPrincipal() {
211: return (Principal) getAsIsPayload()
212: .get(InvocationKey.PRINCIPAL);
213: }
214:
215: /**
216: * Change the security credentials of this invocation.
217: */
218: public void setCredential(Object credential) {
219: getPayload().put(InvocationKey.CREDENTIAL, credential);
220: }
221:
222: public Object getCredential() {
223: return getPayloadValue(InvocationKey.CREDENTIAL);
224: }
225:
226: /**
227: * container for server side association.
228: */
229: public void setObjectName(Object objectName) {
230: this .objectName = objectName;
231: }
232:
233: public Object getObjectName() {
234: return objectName;
235: }
236:
237: /**
238: * An arbitrary type.
239: */
240: public void setType(InvocationType type) {
241: invocationType = type;
242: }
243:
244: public InvocationType getType() {
245: if (invocationType == null)
246: return InvocationType.LOCAL;
247: return invocationType;
248: }
249:
250: /**
251: * Return the invocation target ID. Can be used to identify a cached object
252: */
253: public void setId(Object id) {
254: getPayload().put(InvocationKey.CACHE_ID, id);
255: }
256:
257: public Object getId() {
258: return getPayloadValue(InvocationKey.CACHE_ID);
259: }
260:
261: /**
262: * set on method Return the invocation method.
263: */
264: public void setMethod(Method method) {
265: this .method = method;
266: }
267:
268: /**
269: * get on method Return the invocation method.
270: */
271: public Method getMethod() {
272: return method;
273: }
274:
275: /**
276: * A list of arguments for the method.
277: */
278: public void setArguments(Object[] arguments) {
279: this .args = arguments;
280: }
281:
282: public Object[] getArguments() {
283: return this .args;
284: }
285:
286: /**
287: * marcf: SCOTT WARNING! I removed the "setPrincipal" that was called here
288: */
289: public InvocationContext getInvocationContext() {
290: return invocationContext;
291: }
292:
293: public void setInvocationContext(InvocationContext ctx) {
294: this .invocationContext = ctx;
295: }
296:
297: public void setEnterpriseContext(Object ctx) {
298: getTransientPayload()
299: .put(InvocationKey.ENTERPRISE_CONTEXT, ctx);
300: }
301:
302: public Object getEnterpriseContext() {
303: return getTransientPayload().get(
304: InvocationKey.ENTERPRISE_CONTEXT);
305: }
306:
307: public Map getTransientPayload() {
308: if (transient_payload == null)
309: transient_payload = new HashMap();
310: return transient_payload;
311: }
312:
313: public Map getAsIsPayload() {
314: if (as_is_payload == null)
315: as_is_payload = new HashMap();
316: return as_is_payload;
317: }
318:
319: public Map getPayload() {
320: if (payload == null)
321: payload = new HashMap();
322: return payload;
323: }
324:
325: /**
326: * This method will be called by the container(ContainerInterceptor) to issue the
327: * ultimate method call represented by this invocation. It is overwritten, e.g., by the
328: * WS4EE invocation in order to realize JAXRPC pre- and postprocessing.
329: */
330: public Object performCall(Object instance, Method m,
331: Object[] arguments) throws IllegalArgumentException,
332: IllegalAccessException, InvocationTargetException,
333: Exception {
334: return m.invoke(instance, arguments);
335: }
336:
337: /**
338: * Helper method to determine whether an invocation is local
339: *
340: * @return true when local, false otherwise
341: */
342: public boolean isLocal() {
343: InvocationType type = getType();
344: return (type == InvocationType.LOCAL || type == InvocationType.LOCALHOME);
345: }
346: }
|