1 22 package org.jboss.ha.framework.server; 23 24 import java.lang.ref.SoftReference ; 25 import java.lang.reflect.Method ; 26 import java.lang.reflect.Proxy ; 27 import java.net.InetAddress ; 28 import java.rmi.server.RMIClientSocketFactory ; 29 import java.rmi.server.RMIServerSocketFactory ; 30 import java.rmi.server.RemoteStub ; 31 import java.rmi.server.UnicastRemoteObject ; 32 import java.util.ArrayList ; 33 import java.util.HashMap ; 34 import java.util.List ; 35 import java.util.Map ; 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 55 public class HARMIServerImpl 56 implements HARMIServer 57 { 58 protected Object handler; 59 protected Map invokerMap = new HashMap (); 60 protected org.jboss.logging.Logger log; 61 protected RemoteStub rmistub; 62 protected Object stub; 63 protected String key; 64 protected Class intf; 65 protected RefreshProxiesHATarget target; 66 67 public HARMIServerImpl(HAPartition partition, 68 String replicantName, 69 Class intf, 70 Object handler, 71 int port, 72 RMIClientSocketFactory csf, 73 RMIServerSocketFactory ssf) 74 throws Exception 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 replicantName, 89 Class intf, 90 Object handler, 91 int port, 92 RMIClientSocketFactory clientSocketFactory, 93 RMIServerSocketFactory serverSocketFactory, 94 InetAddress bindAddress) 95 throws Exception 96 { 97 this.handler = handler; 98 this.log = Logger.getLogger(this.getClass()); 99 this.intf = intf; 100 this.key = partition.getPartitionName() + "/" + replicantName; 101 102 Class [] ifaces = handler.getClass().getInterfaces(); 104 for (int i = 0; i < ifaces.length; i++) 105 { 106 Map tmp = MarshalledInvocation.methodToHashesMap(ifaces[i]); 107 invokerMap.putAll(tmp); 108 } 109 110 if( bindAddress != null ) 111 { 112 if( serverSocketFactory == null ) 114 serverSocketFactory = new DefaultSocketFactory(bindAddress); 115 else 116 { 117 try 119 { 120 Class [] parameterTypes = {String .class}; 121 Class ssfClass = serverSocketFactory.getClass(); 122 Method m = ssfClass.getMethod("setBindAddress", parameterTypes); 123 Object [] args = {bindAddress.getHostAddress()}; 124 m.invoke(serverSocketFactory, args); 125 } 126 catch (NoSuchMethodException e) 127 { 128 log.warn("Socket factory does not support setBindAddress(String)"); 129 } 131 catch (Exception e) 132 { 133 log.warn("Failed to setBindAddress="+bindAddress+" on socket factory", e); 134 } 136 } 137 } 138 139 this.rmistub = (RemoteStub )UnicastRemoteObject.exportObject(this, port, clientSocketFactory, serverSocketFactory); this.target = new RefreshProxiesHATarget(partition, replicantName, rmistub, HATarget.ENABLE_INVOCATIONS); 141 142 HARMIServer.rmiServers.put(key, this); 143 } 144 145 154 public HARMIServerImpl(HAPartition partition, String replicantName, Class intf, Object handler) throws Exception 155 { 156 this(partition, replicantName, intf, handler, 0, null, null); 157 } 158 159 167 public Object 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 []{ 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 e) 187 { 188 log.error("failed to destroy", e); 189 } 190 } 191 192 194 public HARMIResponse invoke(long clientViewId, MarshalledInvocation mi) 195 throws Exception 196 { 197 mi.setMethodMap(invokerMap); 198 Method method = mi.getMethod(); 199 200 try 201 { 202 HARMIResponse rsp = new HARMIResponse(); 203 if (clientViewId != target.getCurrentViewId()) 204 { 205 rsp.newReplicants = new ArrayList (target.getReplicants()); 206 rsp.currentViewId = target.getCurrentViewId(); 207 } 208 209 rsp.response = method.invoke(handler, mi.getArguments()); 210 return rsp; 211 } 212 catch (IllegalAccessException iae) 213 { 214 throw iae; 215 } 216 catch (IllegalArgumentException iae) 217 { 218 throw iae; 219 } 220 catch (java.lang.reflect.InvocationTargetException ite) 221 { 222 throw (Exception )ite.getTargetException(); 223 } 224 } 225 226 public List getReplicants() throws Exception 227 { 228 return target.getReplicants(); 229 } 230 231 public Object getLocal() throws Exception 232 { 233 return handler; 234 } 235 236 public class RefreshProxiesHATarget extends HATarget 237 { 238 protected ArrayList generatedProxies; 239 240 public RefreshProxiesHATarget(HAPartition partition, 241 String replicantName, 242 java.io.Serializable target, 243 int allowInvocations) 244 throws Exception 245 { 246 super (partition, replicantName, target, allowInvocations); 247 } 248 249 public void init() throws Exception 250 { 251 super.init (); 252 generatedProxies = new ArrayList (); 253 } 254 255 256 public synchronized void addProxy (HARMIClient client) 257 { 258 SoftReference ref = new SoftReference (client); 259 generatedProxies.add (ref); 260 } 261 262 public synchronized void replicantsChanged(String key, List newReplicants, int newReplicantsViewId) 263 { 264 super.replicantsChanged (key, newReplicants, newReplicantsViewId); 265 266 int max = generatedProxies.size (); 269 ArrayList trash = new ArrayList (); 270 for (int i=0; i<max; i++) 271 { 272 SoftReference ref = (SoftReference )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 |