View Javadoc

1   /* (c) Copyright 2003 Caleigo AB, All rights reserved. 
2    * 
3    * This library is free software; you can redistribute it and/or
4    * modify it under the terms of the GNU Lesser General Public
5    * License as published by the Free Software Foundation; either
6    * version 2.1 of the License, or (at your option) any later version.
7    * 
8    * This library is distributed in the hope that it will be useful,
9    * but WITHOUT ANY WARRANTY; without even the implied warranty of
10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   * Lesser General Public License for more details.
12   * 
13   * You should have received a copy of the GNU Lesser General Public
14   * License along with this library; if not, write to the Free Software
15   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16   *  
17   */
18  
19  package org.caleigo.toolkit.tunnel;
20  
21  
22  import java.lang.reflect.*;
23  import java.util.*;
24  
25  import org.caleigo.toolkit.log.*;
26  
27  /***
28   *
29   * @author  Mattias Hagstrand
30   * @version 1.00
31   * 
32   *//* 
33   *
34   * WHEN        WHO               WHY & WHAT
35   * -----------------------------------------------------------------------------
36   * 2002-07-11  Mattias Hagstrand    Creation
37   */
38  public class DynamicRemoteProxy implements InvocationHandler, java.io.Serializable
39  {
40      // Data members ------------------------------------------------------------
41      protected int mID;
42      protected transient ProxyHandler mProxyHandler;
43      protected transient boolean mIsLocalProxy;
44      protected List mArgumentProxies;
45      protected String[] mInterfaceClasses;
46      
47      // Constructors ------------------------------------------------------------
48      DynamicRemoteProxy(int id, ProxyHandler proxyHandler, Class[] interfaceClasses)
49      {
50          mID = id;
51          mIsLocalProxy = true;
52          mProxyHandler = proxyHandler;
53          mArgumentProxies = new ArrayList();
54          mInterfaceClasses = new String[interfaceClasses.length];
55          for (int i = 0; i < mInterfaceClasses.length; i++)
56              mInterfaceClasses[i] = interfaceClasses[i].getName();
57      }
58      
59      // InvocationHandler implementation ----------------------------------------
60      public Object invoke(Object proxy, Method method, Object[] args)
61          throws Throwable
62      {
63          Log.print(this, "invoke: " + method.getName());
64          
65          if (method.getName().compareTo("hashCode") == 0)
66          {
67              int hashCode = 0;
68              for (int i = 0; i < mInterfaceClasses.length; i++)
69                  hashCode += mInterfaceClasses[i].hashCode();
70              return new Integer(hashCode);
71          }
72          if (method.getName().compareTo("equals") == 0)
73          {
74              boolean equals = true;
75              for (int i = 0; i < mInterfaceClasses.length && equals; i++)
76                  equals = mInterfaceClasses[i].equals(args[0]);
77              return new Boolean(equals);
78          }
79          if (method.getName().compareTo("toString") == 0)
80          {
81              String interfaceClassNames = "";
82              for (int i = 0; i < mInterfaceClasses.length; i++)
83              {
84                  interfaceClassNames = mInterfaceClasses[i];
85                  if (i < mInterfaceClasses.length - 1)
86                      interfaceClassNames += ", ";
87              }
88              return "DynamicRemoteProxy: " + interfaceClassNames;
89          }
90          
91          // Convert all arguments that are IDistributables to proxies
92          for (int i = 0; args != null && i < args.length; i++)
93              if (args[i] instanceof IDistributable)
94              {
95                  Object argProxy = mProxyHandler.createProxy(args[i]);
96                  mArgumentProxies.add(argProxy);
97                  args[i] = argProxy;
98              }
99          
100         // Send invocation message to server
101         Log.print(this, "Sending message");
102         Object returnMessage = mProxyHandler.getTunnel().ask(new DefaultProxyInvocationMessage(mInterfaceClasses, method.getName(), args, mID));
103         Log.print(this, "Answer received");
104         
105         // Finish all argument proxies for this proxy
106         Iterator argumentProxies = mArgumentProxies.iterator();
107         while (argumentProxies.hasNext())
108         {
109             mProxyHandler.finishProxy(argumentProxies.next());
110             argumentProxies.remove();
111         }
112         
113         // Handle return message
114         if (returnMessage instanceof IProxyReturnMessage)
115         {
116             Object returnValue = ((IProxyReturnMessage) returnMessage).getReturnValue();
117             if (returnValue != null && Proxy.isProxyClass(returnValue.getClass()))
118                 ((DynamicRemoteProxy) Proxy.getInvocationHandler(returnValue)).setProxyHandler(mProxyHandler);
119             return returnValue;
120         }
121         else
122             throw (Throwable) ((IProxyExceptionMessage) returnMessage).getExceptionClass().getConstructor(new Class[] {String.class}).newInstance(new Object[] {((IProxyExceptionMessage) returnMessage).getMessage()});
123     }
124     
125     // Superclass overrides ----------------------------------------------------
126     protected void finalize() throws Throwable
127     {
128         super.finalize();
129         
130         if (!mIsLocalProxy)
131             mProxyHandler.getTunnel().send(new DefaultProxyCleanUpMessage(mID));
132     }
133     
134     // Access methods ----------------------------------------------------------
135     public void setProxyHandler(ProxyHandler proxyHandler)
136     {
137         mProxyHandler = proxyHandler;
138     }
139     
140     public int getID()
141     {
142         return mID;
143     }
144     
145     // Nested classes ----------------------------------------------------------
146     interface IProxyInvocationMessage extends java.io.Serializable
147     {
148         // Methods -------------------------------------------------------------
149         public String[] getInterfaceClassNames();
150         public String getMethodName();
151         public Object[] getArguments();
152         public int getProxyID();
153     }
154     
155     interface IProxyReturnMessage extends java.io.Serializable
156     {
157         public Object getReturnValue();
158     }
159     
160     interface IProxyExceptionMessage extends java.io.Serializable
161     {
162         public Class getExceptionClass();
163         public String getMessage();
164     }
165     
166     interface IProxyCleanUpMessage extends java.io.Serializable
167     {
168         public int getProxyID();
169     }
170     
171     protected static final class DefaultProxyInvocationMessage implements IProxyInvocationMessage
172     {
173         // Data members --------------------------------------------------------
174         protected String[] mInterfaceClassNames;
175         protected String mMethodName;
176         protected Object[] mArguments;
177         protected int mProxyID;
178         
179         // Constructors --------------------------------------------------------
180         public DefaultProxyInvocationMessage(String[] interfaceClassNames, String methodName, Object[] arguments, int proxyID)
181         {
182             mInterfaceClassNames = interfaceClassNames;
183             mMethodName = methodName;
184             mArguments = arguments;
185             mProxyID = proxyID;
186         }
187         
188         // IProxyInvocationMessage implementation ------------------------------
189         public String[] getInterfaceClassNames()
190         {
191             return mInterfaceClassNames;
192         }
193         
194         public String getMethodName()
195         {
196             return mMethodName;
197         }
198         
199         public Object[] getArguments()
200         {
201             return mArguments;
202         }
203         
204         public int getProxyID()
205         {
206             return mProxyID;
207         }
208     }
209     
210     protected static final class DefaultProxyReturnMessage implements IProxyReturnMessage
211     {
212         // Data members --------------------------------------------------------
213         protected Object mReturnValue;
214         
215         // Constructors --------------------------------------------------------
216         public DefaultProxyReturnMessage(Object returnValue)
217         {
218             mReturnValue = returnValue;
219         }
220         
221         // IProxyReturnMessage implementation ----------------------------------
222         public Object getReturnValue()
223         {
224             return mReturnValue;
225         }
226     }
227     
228     protected static final class DefaultProxyExceptionMessage implements IProxyExceptionMessage
229     {
230         // Data members --------------------------------------------------------
231         protected Class mExceptionClass;
232         protected String mMessage;
233         
234         // Constructors --------------------------------------------------------
235         public DefaultProxyExceptionMessage(Class exceptionClass, String message)
236         {
237             mExceptionClass = exceptionClass;
238             mMessage = message;
239         }
240         
241         // IProxyExceptionMessage implementation -------------------------------
242         public Class getExceptionClass()
243         {
244             return mExceptionClass;
245         }
246         
247         public String getMessage()
248         {
249             return mMessage;
250         }
251     }
252     
253     protected static final class DefaultProxyCleanUpMessage implements IProxyCleanUpMessage
254     {
255         // Data members --------------------------------------------------------
256         protected int mID;
257         
258         // Constructors --------------------------------------------------------
259         public DefaultProxyCleanUpMessage(int id)
260         {
261             mID = id;
262         }
263         
264         // IProxyCleanUpMessage implementation ---------------------------------
265         public int getProxyID()
266         {
267             return mID;
268         }
269     }
270 }