KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ha > framework > server > HARMIServerImpl


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.ha.framework.server;
23
24 import java.lang.ref.SoftReference JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.lang.reflect.Proxy JavaDoc;
27 import java.net.InetAddress JavaDoc;
28 import java.rmi.server.RMIClientSocketFactory JavaDoc;
29 import java.rmi.server.RMIServerSocketFactory JavaDoc;
30 import java.rmi.server.RemoteStub JavaDoc;
31 import java.rmi.server.UnicastRemoteObject JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Map JavaDoc;
36
37 import org.jboss.ha.framework.interfaces.HAPartition;
38 import org.jboss.ha.framework.interfaces.HARMIClient;
39 import org.jboss.ha.framework.interfaces.HARMIProxy;
40 import org.jboss.ha.framework.interfaces.HARMIResponse;
41 import org.jboss.ha.framework.interfaces.HARMIServer;
42 import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
43 import org.jboss.invocation.MarshalledInvocation;
44 import org.jboss.logging.Logger;
45 import org.jboss.net.sockets.DefaultSocketFactory;
46
47 /**
48  * This class is a <em>server-side</em> proxy for replicated RMI objects.
49  *
50  * @author bill@jboss.org
51  * @author sacha.labourey@jboss.org
52  * @author Scott.Stark@jboss.org
53  * @version $Revision: 37459 $
54  */

55 public class HARMIServerImpl
56    implements HARMIServer
57 {
58    protected Object JavaDoc handler;
59    protected Map JavaDoc invokerMap = new HashMap JavaDoc();
60    protected org.jboss.logging.Logger log;
61    protected RemoteStub JavaDoc rmistub;
62    protected Object JavaDoc stub;
63    protected String JavaDoc key;
64    protected Class JavaDoc intf;
65    protected RefreshProxiesHATarget target;
66
67    public HARMIServerImpl(HAPartition partition,
68                           String JavaDoc replicantName,
69                           Class JavaDoc intf,
70                           Object JavaDoc handler,
71                           int port,
72                           RMIClientSocketFactory JavaDoc csf,
73                           RMIServerSocketFactory JavaDoc ssf)
74       throws Exception JavaDoc
75    {
76       this(partition,
77                       replicantName,
78                       intf,
79                       handler,
80                       port,
81                       csf,
82                       ssf,
83                       null);
84
85    }
86
87    public HARMIServerImpl(HAPartition partition,
88                           String JavaDoc replicantName,
89                           Class JavaDoc intf,
90                           Object JavaDoc handler,
91                           int port,
92                           RMIClientSocketFactory JavaDoc clientSocketFactory,
93                           RMIServerSocketFactory JavaDoc serverSocketFactory,
94                           InetAddress JavaDoc bindAddress)
95       throws Exception JavaDoc
96    {
97       this.handler = handler;
98       this.log = Logger.getLogger(this.getClass());
99       this.intf = intf;
100       this.key = partition.getPartitionName() + "/" + replicantName;
101
102       // Obtain the hashes for the supported handler interfaces
103
Class JavaDoc[] ifaces = handler.getClass().getInterfaces();
104       for (int i = 0; i < ifaces.length; i++)
105       {
106          Map JavaDoc tmp = MarshalledInvocation.methodToHashesMap(ifaces[i]);
107          invokerMap.putAll(tmp);
108       }
109
110       if( bindAddress != null )
111       {
112          // If there is no serverSocketFactory use a default
113
if( serverSocketFactory == null )
114             serverSocketFactory = new DefaultSocketFactory(bindAddress);
115          else
116          {
117             // See if the server socket supports setBindAddress(String)
118
try
119             {
120                Class JavaDoc[] parameterTypes = {String JavaDoc.class};
121                Class JavaDoc ssfClass = serverSocketFactory.getClass();
122                Method JavaDoc m = ssfClass.getMethod("setBindAddress", parameterTypes);
123                Object JavaDoc[] args = {bindAddress.getHostAddress()};
124                m.invoke(serverSocketFactory, args);
125             }
126             catch (NoSuchMethodException JavaDoc e)
127             {
128                log.warn("Socket factory does not support setBindAddress(String)");
129                // Go with default address
130
}
131             catch (Exception JavaDoc e)
132             {
133                log.warn("Failed to setBindAddress="+bindAddress+" on socket factory", e);
134                // Go with default address
135
}
136          }
137       }
138
139       this.rmistub = (RemoteStub JavaDoc)UnicastRemoteObject.exportObject(this, port, clientSocketFactory, serverSocketFactory);// casting is necessary because interface has changed in JDK>=1.2
140
this.target = new RefreshProxiesHATarget(partition, replicantName, rmistub, HATarget.ENABLE_INVOCATIONS);
141
142       HARMIServer.rmiServers.put(key, this);
143    }
144
145    /**
146     * Create a new HARMIServer implementation that will act as a RMI end-point for a specific server.
147     *
148     * @param partition {@link HAPartition} that will determine the cluster member
149     * @param replicantName Name of the service using this HARMIServer
150     * @param intf Class type under which should appear the RMI server dynamically built
151     * @param handler Target object to which calls will be forwarded
152     * @throws Exception Thrown if any exception occurs during call forwarding
153     */

154    public HARMIServerImpl(HAPartition partition, String JavaDoc replicantName, Class JavaDoc intf, Object JavaDoc handler) throws Exception JavaDoc
155    {
156       this(partition, replicantName, intf, handler, 0, null, null);
157    }
158
159    /**
160     * Once a HARMIServer implementation exists, it is possible to ask for a stub that can, for example,
161     * be bound in JNDI for client use. Each client stub may incorpore a specific load-balancing
162     * policy.
163     *
164     * @param policy {@link org.jboss.ha.framework.interfaces.LoadBalancePolicy} implementation to ues on the client.
165     * @return
166     */

167    public Object JavaDoc createHAStub(LoadBalancePolicy policy)
168    {
169       HARMIClient client = new HARMIClient(target.getReplicants(),
170          target.getCurrentViewId (), policy, key, handler);
171       this.target.addProxy (client);
172       return Proxy.newProxyInstance(
173       intf.getClassLoader(),
174       new Class JavaDoc[]{ intf, HARMIProxy.class },
175       client);
176    }
177
178    public void destroy()
179    {
180       try
181       {
182      target.destroy();
183          HARMIServer.rmiServers.remove(key);
184          UnicastRemoteObject.unexportObject(this, true);
185
186       } catch (Exception JavaDoc e)
187       {
188          log.error("failed to destroy", e);
189       }
190    }
191
192    // HARMIServer implementation ----------------------------------------------
193

194    public HARMIResponse invoke(long clientViewId, MarshalledInvocation mi)
195       throws Exception JavaDoc
196    {
197       mi.setMethodMap(invokerMap);
198       Method JavaDoc method = mi.getMethod();
199
200       try
201       {
202          HARMIResponse rsp = new HARMIResponse();
203          if (clientViewId != target.getCurrentViewId())
204          {
205             rsp.newReplicants = new ArrayList JavaDoc(target.getReplicants());
206             rsp.currentViewId = target.getCurrentViewId();
207          }
208
209          rsp.response = method.invoke(handler, mi.getArguments());
210          return rsp;
211       }
212       catch (IllegalAccessException JavaDoc iae)
213       {
214          throw iae;
215       }
216       catch (IllegalArgumentException JavaDoc iae)
217       {
218          throw iae;
219       }
220       catch (java.lang.reflect.InvocationTargetException JavaDoc ite)
221       {
222          throw (Exception JavaDoc)ite.getTargetException();
223       }
224    }
225
226    public List JavaDoc getReplicants() throws Exception JavaDoc
227    {
228       return target.getReplicants();
229    }
230
231    public Object JavaDoc getLocal() throws Exception JavaDoc
232    {
233       return handler;
234    }
235
236    public class RefreshProxiesHATarget extends HATarget
237    {
238       protected ArrayList JavaDoc generatedProxies;
239
240       public RefreshProxiesHATarget(HAPartition partition,
241             String JavaDoc replicantName,
242             java.io.Serializable JavaDoc target,
243             int allowInvocations)
244          throws Exception JavaDoc
245       {
246          super (partition, replicantName, target, allowInvocations);
247       }
248
249       public void init() throws Exception JavaDoc
250       {
251          super.init ();
252          generatedProxies = new ArrayList JavaDoc ();
253       }
254
255
256       public synchronized void addProxy (HARMIClient client)
257       {
258          SoftReference JavaDoc ref = new SoftReference JavaDoc(client);
259          generatedProxies.add (ref);
260       }
261
262       public synchronized void replicantsChanged(String JavaDoc key, List JavaDoc newReplicants, int newReplicantsViewId)
263       {
264          super.replicantsChanged (key, newReplicants, newReplicantsViewId);
265
266          // we now update all generated proxies
267
//
268
int max = generatedProxies.size ();
269          ArrayList JavaDoc trash = new ArrayList JavaDoc();
270          for (int i=0; i<max; i++)
271          {
272             SoftReference JavaDoc ref = (SoftReference JavaDoc)generatedProxies.get (i);
273             HARMIClient proxy = (HARMIClient)ref.get ();
274             if (proxy == null)
275             {
276                trash.add (ref);
277             }
278             else
279             {
280                proxy.updateClusterInfo (this.replicants, this.clusterViewId);
281             }
282          }
283
284          if (trash.size () > 0)
285             generatedProxies.removeAll (trash);
286
287       }
288    }
289 }
290
Popular Tags