KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sapia > ubik > rmi > naming > remote > proxy > ReliableLocalContext


1 package org.sapia.ubik.rmi.naming.remote.proxy;
2
3 import java.io.IOException JavaDoc;
4 import java.lang.reflect.UndeclaredThrowableException JavaDoc;
5 import java.rmi.RemoteException JavaDoc;
6 import java.util.ArrayList JavaDoc;
7 import java.util.Collections JavaDoc;
8 import java.util.List JavaDoc;
9
10 import javax.naming.Context JavaDoc;
11 import javax.naming.Name JavaDoc;
12 import javax.naming.NamingException JavaDoc;
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 /**
27  * An instance of this class is created by a <code>ReliableInitialContextFactory</code>. It allows
28  * clients to register <code>ServiceDiscoveryListener</code>s that are notified when new services
29  * are bound to the JNDI servers on the network.
30  *
31  * @see org.sapia.ubik.rmi.naming.remote.RemoteInitialContextFactory
32  * @see org.sapia.ubik.rmi.naming.remote.discovery.ServiceDiscoListener
33  * @see org.sapia.ubik.rmi.naming.remote.discovery.ServiceDiscoveryEvent
34  *
35  * @author Yanick Duchesne
36  * <dl>
37  * <dt><b>Copyright:</b><dd>Copyright &#169; 2002-2003 <a HREF="http://www.sapia-oss.org">Sapia Open Source Software</a>. All Rights Reserved.</dd></dt>
38  * <dt><b>License:</b><dd>Read the license.txt file of the jar or visit the
39  * <a HREF="http://www.sapia-oss.org/license.html">license page</a> at the Sapia OSS web site</dd></dt>
40  * </dl>
41  */

42 public class ReliableLocalContext extends LocalContext
43   implements AsyncEventListener {
44   private static ThreadLocal JavaDoc _currentContext = new ThreadLocal JavaDoc();
45   private static String JavaDoc PING = "ubik/rmi/naming/ping/test";
46   private BindingCache _bindings = new BindingCache();
47   private DiscoveryHelper _helper;
48   private List JavaDoc _servers = Collections.synchronizedList(new ArrayList JavaDoc());
49   private DomainName _domainName;
50   private String JavaDoc _mcastAddress;
51   private int _mcastPort;
52   private String JavaDoc _url;
53   private ContextResolver _resolver;
54
55   /**
56    * Constructor for ReliableLocalContext.
57    */

58   public ReliableLocalContext(EventChannel channel,
59                               String JavaDoc url,
60                               RemoteContext ctx,
61                               boolean publish,
62                               ContextResolver resolver) throws NamingException JavaDoc, IOException JavaDoc {
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   /**
79    * @see org.sapia.ubik.rmi.naming.remote.proxy.LocalContext#bind(Name, Object)
80    */

81   public void bind(Name JavaDoc n, Object JavaDoc o) throws NamingException JavaDoc {
82     rebind(n, o);
83   }
84
85   /**
86    * @see org.sapia.ubik.rmi.naming.remote.proxy.LocalContext#bind(String, Object)
87    */

88   public void bind(String JavaDoc n, Object JavaDoc o) throws NamingException JavaDoc {
89     rebind(n, o);
90   }
91
92   /**
93    * @see org.sapia.ubik.rmi.naming.remote.proxy.LocalContext#rebind(Name, Object)
94    */

95   public void rebind(Name JavaDoc n, Object JavaDoc o) throws NamingException JavaDoc {
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   /**
105    * @see org.sapia.ubik.rmi.naming.remote.proxy.LocalContext#rebind(String, Object)
106    */

107   public void rebind(String JavaDoc n, Object JavaDoc o) throws NamingException JavaDoc {
108     super.rebind(n, o);
109
110     if (!_helper.getChannel().isClosed()) {
111       _bindings.add(_helper.getChannel().getDomainName().toString(), n, o);
112     }
113   }
114
115   /**
116    * Adds a service discovery listener to this instance.
117    *
118    * @param a <code>ServiceDiscoListener</code>.
119    */

120   public void addServiceDiscoListener(ServiceDiscoListener listener) {
121     if (!_helper.getChannel().isClosed()) {
122       _helper.addServiceDiscoListener(listener);
123     }
124   }
125
126   /**
127    * Adds a JNDI discovery listener to this instance.
128    *
129    * @param a <code>JndiDiscoListener</code>.
130    */

131   public void addJndiDiscoListener(JndiDiscoListener listener) {
132     if (!_helper.getChannel().isClosed()) {
133       _helper.addJndiDiscoListener(new JndiListenerWrapper(listener, _servers));
134     }
135   }
136
137   /**
138    * @see org.sapia.ubik.mcast.AsyncEventListener#onAsyncEvent(RemoteEvent)
139    */

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 JavaDoc remoteCtx = (Context JavaDoc) _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 JavaDoc remoteCtx = (Context JavaDoc) _resolver.resolve(tcp);
154         _servers.add(remoteCtx);
155       }
156     } catch (RemoteException JavaDoc e) {
157       e.printStackTrace();
158     } catch (IOException JavaDoc e) {
159       e.printStackTrace();
160     }
161   }
162
163   /**
164    * @see org.sapia.ubik.rmi.naming.remote.proxy.LocalContext#doFailOver(UndeclaredThrowableException)
165    */

166   protected void doFailOver(UndeclaredThrowableException JavaDoc e)
167     throws NamingException JavaDoc {
168     if (!(e.getUndeclaredThrowable() instanceof RemoteException JavaDoc)) {
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 JavaDoc udte) {
184           if (udte.getUndeclaredThrowable() instanceof RemoteException JavaDoc) {
185             _servers.remove(i);
186           }
187         } catch (NamingException JavaDoc ne) {
188           _ctx = server;
189
190           return;
191         }
192       }
193     }
194
195     super.doFailOver(e);
196   }
197
198   /**
199    * @see org.sapia.ubik.rmi.naming.remote.proxy.LocalContext#close()
200    */

201   public void close() throws NamingException JavaDoc {
202     super.close();
203     _helper.close();
204   }
205
206   /**
207    * Returns the instance of this class that is currently registered with the calling thread.
208    *
209    * @throws IllegalStateException if no instance of this class is currently registered.
210    */

211   public static ReliableLocalContext currentContext()
212     throws IllegalStateException JavaDoc {
213     ReliableLocalContext ctx = (ReliableLocalContext) _currentContext.get();
214
215     if (ctx == null) {
216       throw new IllegalStateException JavaDoc("No " + ReliableLocalContext.class.getName() + " registered with current thread");
217     }
218
219     return ctx;
220   }
221   
222   /**
223    * @return the <code>EventChannel</code> used by this instance to perform
224    * discovery.
225    */

226   public EventChannel getEventChannel(){
227     return _helper.getChannel();
228   }
229
230   /*////////////////////////////////////////////////////////////////////
231                               INNER CLASSES
232   ////////////////////////////////////////////////////////////////////*/

233   static class JndiListenerWrapper implements JndiDiscoListener {
234     private JndiDiscoListener _wrapped;
235     private List JavaDoc _servers;
236
237     JndiListenerWrapper(JndiDiscoListener toWrap, List JavaDoc servers) {
238       _wrapped = toWrap;
239       _servers = servers;
240     }
241
242     /**
243      * @see org.sapia.ubik.rmi.naming.remote.discovery.JndiDiscoListener#onJndiDiscovered(Context)
244      */

245     public void onJndiDiscovered(Context JavaDoc ctx) {
246       synchronized (_servers) {
247         _servers.add(ctx);
248       }
249
250       _wrapped.onJndiDiscovered(ctx);
251     }
252   }
253 }
254
Popular Tags