Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/chaoswg/xtc4y/proxy/InvocationStack.java


1   //$Header: /cvsroot/xtc4y/xtc4y/src/com/chaoswg/xtc4y/proxy/InvocationStack.java,v 1.1 2003/09/07 19:38:21 toggm Exp $
2   /******************************************************************************
3    * CHAOSWG.COM
4    * -------------------------------------------------------------------------- *
5    * URL: http://www.chaoswg.com/                                               *
6    * Author: Mike Toggweiler (2.dog@gmx.ch)                                     *
7    *                                                                            *
8    * Last Updated: $Date: 2003/09/07 19:38:21 $, by $Author: toggm $            *
9    * Version: $Revision: 1.1 $                                                  *
10   * -------------------------------------------------------------------------- *
11   * COPYRIGHT:   (c) 2003 by Mike Toggweiler                                   *
12   *                                                                            *
13   * This program is free software; you can redistribute it and/or modify       *
14   * it under the terms of the GNU General Public License as published by       *
15   * the Free Software Foundation; either version 2 of the License, or          *
16   * (at your option) any later version.                                        *
17   *****************************************************************************/
18  
19  package com.chaoswg.xtc4y.proxy;
20  
21  //third company code imports
22  import java.util.*;
23  import java.lang.reflect.*;
24  
25  //WIN imports
26  
27  /**
28   * Invocation stack, used to trace calls on a class
29   * @author Mike Toggweiler
30   **/
31  public class InvocationStack implements InvocationHandler {
32      private Stack stack = new Stack();
33      private Object proxy;
34      private Object targetObject = null;
35      private Class targetClass;
36      private HashMap returnValues = new HashMap();
37  
38      /**
39       * Creates a new invocation stack and a proxy of a class
40       * if methods are invoked on this proxy, they are traced and 
41       * default values are returned.
42       **/
43      public InvocationStack(Class target) {       
44    try {
45        targetClass = target;
46        Class proxyClass = 
47      Proxy.getProxyClass(target.getClassLoader(), 
48          new Class[] {target});
49        proxy = proxyClass.
50      getConstructor(new Class[] {InvocationHandler.class}).
51      newInstance(new Object[] {this});  
52    }
53    catch (Exception e) {
54        throw new RuntimeException(e);
55    }
56      }
57  
58      /**
59       * Creates a new invocationstack and a proxy of the given object.
60       * if methods are invoked in the proxy, they are traced and the 
61       * invocations are redirected to the target object
62       **/
63      public InvocationStack(Object target) {
64    this(target.getClass());
65    targetObject = target;  
66      }
67  
68      /**
69       * @return the proxy object
70       **/
71      public Object getProxyObject() {
72    return proxy;
73      }
74  
75      /**
76       * @return the last MethodContainer element in the stack or null
77       * if empty, remove it atfter returning
78       **/
79      public MethodContainer popStack() {
80    try {
81        return (MethodContainer)stack.pop();
82    }
83    catch (EmptyStackException ese) {
84        return null;
85    }
86      }
87  
88      /**
89       * @return the last MethodContainer element in the stack or null 
90       * if empty, without removing it
91       **/
92      public MethodContainer peekStack() {
93    try {
94        return (MethodContainer)stack.peek();
95    }
96    catch (EmptyStackException ese) {
97        return null;
98    }
99      }
100 
101     /**
102      * Empty stack
103      **/
104     public void emptyStack() {
105   stack.removeAllElements();
106     }
107 
108     /**
109      * @return the first method matching without checking paramter types
110      * this should only be used if there is just one method with this name
111      **/
112     public Method getMethod(String name) {
113   Method[] methods = targetClass.getMethods();
114   for (int i=0; i<methods.length; ++i) {
115       if (methods[i].getName().equals(name)) {
116     return methods[i];
117       }
118   }
119   throw new RuntimeException(new NoSuchMethodException(name));
120     }
121 
122     /**
123      * @return the method matching the name and parameter types
124      **/
125     public Method getMethod(String name, Class[] params) {
126   try {
127       return targetClass.getMethod(name, params);
128   }
129   catch (NoSuchMethodException nsme) {
130       throw new RuntimeException(nsme);
131   }
132     }    
133 
134     /**
135      * set a return value for a specific method
136      * @param method method to define the return value
137      * @param Object return value
138      **/
139     public void setReturnValue(Method method, Object value) {
140   returnValues.put(method, value);
141     }
142 
143     /**
144      * Remove a previously defined return value for a method
145      * @param method the method for which the return value should be 
146      * removed
147      **/
148     public void removeReturnValue(Method method) {
149   returnValues.remove(method);
150     }
151     
152     /**
153      * Implementation of a InvocationHandler
154      **/
155     public Object invoke(Object obj, Method method, Object[] args) 
156   throws Throwable {
157 
158   //store on stack
159   stack.push(new MethodContainer(method, args));
160   
161   //check first if a special return value was defined before
162   if (returnValues.containsKey(method)) {
163       return returnValues.get(method);
164   }
165 
166   //if target object is specified, redirect invocation
167   if (targetObject != null) {
168       return method.invoke(targetObject, args);
169   }
170 
171   //try to invoke the invoke an implemented method on an abstract class
172   int mod = method.getModifiers();
173   if (!Modifier.isAbstract(mod)) {
174       return method.invoke(obj, args);
175   }
176 
177   Class retType = method.getReturnType();
178   if (!retType.isPrimitive()) {
179       return retType.newInstance();
180   }
181   else {
182       if (retType.isAssignableFrom(Integer.TYPE)) {
183     return new Integer(0);
184       }
185       else if (retType.isAssignableFrom(Long.TYPE)) {
186     return new Long(0);
187       }
188       else if (retType.isAssignableFrom(Short.TYPE)) {
189     return new Short((short)0);
190       }
191       else if (retType.isAssignableFrom(Double.TYPE)) {
192     return new Double(0);
193       }
194       else if (retType.isAssignableFrom(Float.TYPE)) {
195     return new Float(0);
196       }
197       else if (retType.isAssignableFrom(Boolean.TYPE)) {
198     return new Boolean(false);
199       }
200       else if (retType.isAssignableFrom(Character.TYPE)) {
201     return new Character(' ');
202       }
203       else if (retType.isAssignableFrom(Byte.TYPE)) {
204     return new Byte((byte)0);
205       }
206       else if (retType.isAssignableFrom(Void.TYPE)) {
207     return null;
208       }
209   }
210   return null;
211     }    
212 }