1 package org.sapia.ubik.rmi.naming.remote.proxy; 2 3 import java.io.IOException ; 4 import java.lang.reflect.UndeclaredThrowableException ; 5 import java.rmi.RemoteException ; 6 import java.util.ArrayList ; 7 import java.util.Collections ; 8 import java.util.List ; 9 10 import javax.naming.Context ; 11 import javax.naming.Name ; 12 import javax.naming.NamingException ; 13 14 import org.sapia.ubik.mcast.AsyncEventListener; 15 import org.sapia.ubik.mcast.DomainName; 16 import org.sapia.ubik.mcast.EventChannel; 17 import org.sapia.ubik.mcast.RemoteEvent; 18 import org.sapia.ubik.net.TCPAddress; 19 import org.sapia.ubik.rmi.naming.remote.Consts; 20 import org.sapia.ubik.rmi.naming.remote.RemoteContext; 21 import org.sapia.ubik.rmi.naming.remote.discovery.DiscoveryHelper; 22 import org.sapia.ubik.rmi.naming.remote.discovery.JndiDiscoListener; 23 import org.sapia.ubik.rmi.naming.remote.discovery.ServiceDiscoListener; 24 25 26 42 public class ReliableLocalContext extends LocalContext 43 implements AsyncEventListener { 44 private static ThreadLocal _currentContext = new ThreadLocal (); 45 private static String PING = "ubik/rmi/naming/ping/test"; 46 private BindingCache _bindings = new BindingCache(); 47 private DiscoveryHelper _helper; 48 private List _servers = Collections.synchronizedList(new ArrayList ()); 49 private DomainName _domainName; 50 private String _mcastAddress; 51 private int _mcastPort; 52 private String _url; 53 private ContextResolver _resolver; 54 55 58 public ReliableLocalContext(EventChannel channel, 59 String url, 60 RemoteContext ctx, 61 boolean publish, 62 ContextResolver resolver) throws NamingException , IOException { 63 super(url, ctx); 64 _helper = new DiscoveryHelper(channel); 65 _resolver = resolver; 66 channel.registerAsyncListener(Consts.JNDI_SERVER_DISCO, this); 67 channel.registerAsyncListener(Consts.JNDI_SERVER_PUBLISH, this); 68 69 if (publish) { 70 if (!channel.isClosed()) { 71 channel.dispatch(Consts.JNDI_CLIENT_PUBLISH, ""); 72 } 73 } 74 75 _currentContext.set(this); 76 } 77 78 81 public void bind(Name n, Object o) throws NamingException { 82 rebind(n, o); 83 } 84 85 88 public void bind(String n, Object o) throws NamingException { 89 rebind(n, o); 90 } 91 92 95 public void rebind(Name n, Object o) throws NamingException { 96 super.rebind(n, o); 97 98 if (!_helper.getChannel().isClosed()) { 99 _bindings.add(_helper.getChannel().getDomainName().toString(), 100 n.toString(), o); 101 } 102 } 103 104 107 public void rebind(String n, Object o) throws NamingException { 108 super.rebind(n, o); 109 110 if (!_helper.getChannel().isClosed()) { 111 _bindings.add(_helper.getChannel().getDomainName().toString(), n, o); 112 } 113 } 114 115 120 public void addServiceDiscoListener(ServiceDiscoListener listener) { 121 if (!_helper.getChannel().isClosed()) { 122 _helper.addServiceDiscoListener(listener); 123 } 124 } 125 126 131 public void addJndiDiscoListener(JndiDiscoListener listener) { 132 if (!_helper.getChannel().isClosed()) { 133 _helper.addJndiDiscoListener(new JndiListenerWrapper(listener, _servers)); 134 } 135 } 136 137 140 public void onAsyncEvent(RemoteEvent evt) { 141 TCPAddress tcp; 142 143 try { 144 if (evt.getType().equals(Consts.JNDI_SERVER_DISCO)) { 145 tcp = (TCPAddress) evt.getData(); 146 147 Context remoteCtx = (Context ) _resolver.resolve(tcp); 148 _servers.add(remoteCtx); 149 } else if (evt.getType().equals(Consts.JNDI_SERVER_PUBLISH) && 150 (getInternalContext() != null)) { 151 tcp = (TCPAddress) evt.getData(); 152 153 Context remoteCtx = (Context ) _resolver.resolve(tcp); 154 _servers.add(remoteCtx); 155 } 156 } catch (RemoteException e) { 157 e.printStackTrace(); 158 } catch (IOException e) { 159 e.printStackTrace(); 160 } 161 } 162 163 166 protected void doFailOver(UndeclaredThrowableException e) 167 throws NamingException { 168 if (!(e.getUndeclaredThrowable() instanceof RemoteException )) { 169 super.doFailOver(e); 170 } 171 172 RemoteContext server; 173 174 synchronized (_servers) { 175 for (int i = 0; i < _servers.size(); i++) { 176 server = (RemoteContext) _servers.get(i); 177 178 try { 179 server.lookup(PING); 180 _ctx = server; 181 182 return; 183 } catch (UndeclaredThrowableException udte) { 184 if (udte.getUndeclaredThrowable() instanceof RemoteException ) { 185 _servers.remove(i); 186 } 187 } catch (NamingException ne) { 188 _ctx = server; 189 190 return; 191 } 192 } 193 } 194 195 super.doFailOver(e); 196 } 197 198 201 public void close() throws NamingException { 202 super.close(); 203 _helper.close(); 204 } 205 206 211 public static ReliableLocalContext currentContext() 212 throws IllegalStateException { 213 ReliableLocalContext ctx = (ReliableLocalContext) _currentContext.get(); 214 215 if (ctx == null) { 216 throw new IllegalStateException ("No " + ReliableLocalContext.class.getName() + " registered with current thread"); 217 } 218 219 return ctx; 220 } 221 222 226 public EventChannel getEventChannel(){ 227 return _helper.getChannel(); 228 } 229 230 233 static class JndiListenerWrapper implements JndiDiscoListener { 234 private JndiDiscoListener _wrapped; 235 private List _servers; 236 237 JndiListenerWrapper(JndiDiscoListener toWrap, List servers) { 238 _wrapped = toWrap; 239 _servers = servers; 240 } 241 242 245 public void onJndiDiscovered(Context ctx) { 246 synchronized (_servers) { 247 _servers.add(ctx); 248 } 249 250 _wrapped.onJndiDiscovered(ctx); 251 } 252 } 253 } 254 | Popular Tags |