1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */
22 package org.jboss.invocation;
23
24 import java.io.Serializable;
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.Method;
27 import java.security.Principal;
28 import java.util.Map;
29 import java.util.HashMap;
30
31 import javax.transaction.Transaction;
32
33 import org.jboss.security.SecurityContext;
34
35 /**
36 * The Invocation object is the generic object flowing through our interceptors.
37 *
38 * <p>The heart of it is the payload map that can contain anything we then
39 * put readers on them. The first <em>reader</em> is this
40 * <em>Invocation</em> object that can interpret the data in it.
41 *
42 * <p>Essentially we can carry ANYTHING from the client to the server, we keep
43 * a series of of predefined variables and method calls to get at the
44 * pointers. But really it is just a repository of objects.
45 *
46 * @author <a href="mailto:marc@jboss.org">Marc Fleury</a>
47 * @author <a href="mailto:christoph.jung@infor.de">Christoph G. Jung</a>
48 * @author Anil.Saldhana@redhat.com
49 * @version $Revision: 66982 $
50 */
51 public class Invocation
52 {
53 /** The signature of the invoke() method */
54 public static final String[] INVOKE_SIGNATURE = { "org.jboss.invocation.Invocation" };
55
56 // The payload is a repository of everything associated with the invocation
57 // It is information that will need to travel
58
59 /**
60 * Contextual information to the invocation that is not part of the payload.
61 */
62 public Map transient_payload;
63
64 /**
65 * as_is classes that will not be marshalled by the invocation
66 * (java.* and javax.* or anything in system classpath is OK)
67 */
68 public Map as_is_payload;
69
70 /** Payload will be marshalled for type hiding at the RMI layers. */
71 public Map payload;
72
73 public InvocationContext invocationContext;
74 public Object[] args;
75 public Object objectName;
76 public Method method;
77 public InvocationType invocationType;
78
79 // The variables used to indicate what type of data and where to put it.
80
81 //
82 // We are using the generic payload to store some of our data, we define
83 // some integer entries. These are just some variables that we define for
84 // use in "typed" getters and setters. One can define anything either in
85 // here explicitely or through the use of external calls to getValue
86 //
87
88 /**
89 * No-args constructor exposed for externalization only.
90 */
91 public Invocation()
92 {
93 }
94
95 public Invocation( Object id, Method m, Object[] args, Transaction tx,
96 Principal identity, Object credential )
97 {
98 setId(id);
99 setMethod(m);
100 setArguments(args);
101 setTransaction(tx);
102 setPrincipal(identity);
103 setCredential(credential);
104 }
105
106 /**
107 * The generic store of variables.
108 *
109 * <p>
110 * The generic getter and setter is really all that one needs to talk
111 * to this object. We introduce typed getters and setters for
112 * convenience and code readability in the codeba
113 */
114 public void setValue(Object key, Object value)
115 {
116 setValue(key, value, PayloadKey.PAYLOAD);
117 }
118
119 /**
120 * Advanced store
121 * Here you can pass a TYPE that indicates where to put the value.
122 * TRANSIENT: the value is put in a map that WON'T be passed
123 * AS_IS: no need to marshall the value when passed (use for all JDK
124 * java types)
125 * PAYLOAD: we need to marshall the value as its type is application specific
126 */
127 public void setValue(Object key, Object value, PayloadKey type)
128 {
129 if(type == PayloadKey.TRANSIENT)
130 {
131 getTransientPayload().put(key,value);
132 }
133 else if(type == PayloadKey.AS_IS)
134 {
135 getAsIsPayload().put(key,value);
136 }
137 else if(type == PayloadKey.PAYLOAD)
138 {
139 getPayload().put(key,value);
140 }
141 else
142 {
143 throw new IllegalArgumentException("Unknown PayloadKey: " + type);
144 }
145 }
146
147 /**
148 * Get a value from the stores.
149 */
150 public Object getValue(Object key)
151 {
152 // find where it is
153 Object rtn = getPayloadValue(key);
154 if (rtn != null) return rtn;
155
156 rtn = getAsIsValue(key);
157 if (rtn != null) return rtn;
158
159 rtn = getTransientValue(key);
160 return rtn;
161 }
162
163 public Object getPayloadValue(Object key)
164 {
165 if (payload == null) return null;
166 return payload.get(key);
167 }
168
169 public Object getTransientValue(Object key)
170 {
171 if (transient_payload == null) return null;
172 return transient_payload.get(key);
173 }
174
175 public Object getAsIsValue(Object key)
176 {
177 if (as_is_payload == null) return null;
178 return as_is_payload.get(key);
179 }
180
181
182
183 //
184 // Convenience typed getters, use pre-declared keys in the store,
185 // but it all comes back to the payload, here you see the usage of the
186 // different payloads. Anything that has a well defined type can go in as_is
187 // Anything that is arbitrary and depends on the application needs to go in
188 // in the serialized payload. The "Transaction" is known, the type of the
189 // method arguments are not for example and are part of the EJB jar.
190 //
191
192 /**
193 * set the transaction.
194 */
195 public void setTransaction(Transaction tx)
196 {
197 if( tx instanceof Serializable )
198 getAsIsPayload().put(InvocationKey.TRANSACTION, tx);
199 else
200 getTransientPayload().put(InvocationKey.TRANSACTION, tx);
201 }
202
203 /**
204 * get the transaction.
205 */
206 public Transaction getTransaction()
207 {
208 Transaction tx = (Transaction) getAsIsPayload().get(InvocationKey.TRANSACTION);
209 if( tx == null )
210 tx = (Transaction) getTransientPayload().get(InvocationKey.TRANSACTION);
211 return tx;
212 }
213
214 /**
215 * Change the security identity of this invocation.
216 */
217 public void setPrincipal(Principal principal)
218 {
219 getAsIsPayload().put(InvocationKey.PRINCIPAL, principal);
220 }
221
222 public Principal getPrincipal()
223 {
224 return (Principal) getAsIsPayload().get(InvocationKey.PRINCIPAL);
225 }
226
227 /**
228 * Change the security credentials of this invocation.
229 */
230 public void setCredential(Object credential)
231 {
232 getPayload().put(InvocationKey.CREDENTIAL, credential);
233 }
234
235 public Object getCredential()
236 {
237 return getPayloadValue(InvocationKey.CREDENTIAL);
238 }
239
240 /**
241 * container for server side association.
242 */
243 public void setObjectName(Object objectName)
244 {
245 this.objectName = objectName;
246 }
247
248 public Object getObjectName()
249 {
250 return objectName;
251 }
252
253 /**
254 * An arbitrary type.
255 */
256 public void setType(InvocationType type)
257 {
258 invocationType = type;
259 }
260
261 public InvocationType getType()
262 {
263 if (invocationType == null) return InvocationType.LOCAL;
264 return invocationType;
265 }
266
267 /**
268 * Return the invocation target ID. Can be used to identify a cached object
269 */
270 public void setId(Object id)
271 {
272 getPayload().put(InvocationKey.CACHE_ID, id);
273 }
274
275 public Object getId()
276 {
277 return getPayloadValue(InvocationKey.CACHE_ID);
278 }
279
280 /**
281 * set on method Return the invocation method.
282 */
283 public void setMethod(Method method)
284 {
285 this.method = method;
286 }
287
288 /**
289 * get on method Return the invocation method.
290 */
291 public Method getMethod()
292 {
293 return method;
294 }
295
296 /**
297 * A list of arguments for the method.
298 */
299 public void setArguments(Object[] arguments)
300 {
301 this.args = arguments;
302 }
303
304 public Object[] getArguments()
305 {
306 return this.args;
307 }
308
309 public InvocationContext getInvocationContext()
310 {
311 return invocationContext;
312 }
313
314 public void setInvocationContext(InvocationContext ctx)
315 {
316 this.invocationContext = ctx;
317 }
318
319 public void setEnterpriseContext(Object ctx)
320 {
321 getTransientPayload().put(InvocationKey.ENTERPRISE_CONTEXT, ctx);
322 }
323
324 public Object getEnterpriseContext()
325 {
326 return getTransientPayload().get(InvocationKey.ENTERPRISE_CONTEXT);
327 }
328
329 public SecurityContext getSecurityContext()
330 {
331 return (SecurityContext) getAsIsPayload().get(InvocationKey.SECURITY_CONTEXT);
332 }
333
334 public void setSecurityContext(SecurityContext sc)
335 {
336 getAsIsPayload().put(InvocationKey.SECURITY_CONTEXT, sc);
337 }
338
339 public boolean isInterVM()
340 {
341 Boolean b = (Boolean) getAsIsPayload().get(InvocationKey.INTERVM);
342 return b != null && b == Boolean.TRUE;
343 }
344
345 public void setInterVM(Boolean boolValue)
346 {
347 getAsIsPayload().put(InvocationKey.INTERVM, boolValue);
348 }
349
350 /**
351 * Set whether the invocation is secure or not
352 * @param secure boolean value
353 */
354 public void setSecure(Boolean secure)
355 {
356 this.getAsIsPayload().put(InvocationKey.SECURE, secure);
357 }
358
359
360 public Map getTransientPayload()
361 {
362 if (transient_payload == null) transient_payload = new HashMap();
363 return transient_payload;
364 }
365
366 public Map getAsIsPayload()
367 {
368 if (as_is_payload == null) as_is_payload = new HashMap();
369 return as_is_payload;
370 }
371
372 public Map getPayload()
373 {
374 if (payload == null) payload = new HashMap();
375 return payload;
376 }
377
378 /**
379 * This method will be called by the container(ContainerInterceptor) to issue the
380 * ultimate method call represented by this invocation. It is overwritten, e.g., by the
381 * WS4EE invocation in order to realize JAXRPC pre- and postprocessing.
382 */
383 public Object performCall(Object instance, Method m, Object[] arguments)
384 throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, Exception
385 {
386 return m.invoke(instance,arguments);
387 }
388
389 /**
390 * Helper method to determine whether an invocation is local
391 *
392 * @return true when local, false otherwise
393 */
394 public boolean isLocal()
395 {
396 InvocationType type = getType();
397 return (type == InvocationType.LOCAL || type == InvocationType.LOCALHOME
398 || type == InvocationType.SERVICE_ENDPOINT);
399 }
400
401 /**
402 * Determine whether the invocation arrived on a secure channel
403 * @return true invocation is secure
404 */
405 public Boolean isSecure()
406 {
407 return (Boolean) this.getAsIsPayload().get(InvocationKey.SECURE);
408 }
409 }