KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > datashare > client > DataShareClient


1 /* ----- BEGIN LICENSE BLOCK -----
2  * Version: MPL 1.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code was the Rendezvous client.
15  * This Code is now part of DataShare.
16  *
17  * The Initial Developer of the Original Code is
18  * Ball Aerospace & Technologies Corp, Fairborn, Ohio
19  * Portions created by the Initial Developer are Copyright (C) 2001
20  * the Initial Developer. All Rights Reserved.
21  *
22  * Contributor(s): Charles Wood <cwood@ball.com>
23  *
24  * ----- END LICENSE BLOCK ----- */

25 /* RCS $Id: DataShareClient.java,v 1.2 2002/01/29 20:55:59 lizellaman Exp $
26  * $Log: DataShareClient.java,v $
27  * Revision 1.2 2002/01/29 20:55:59 lizellaman
28  * Added LoggingInterface, modified the PropertiesInterface implementation
29  *
30  * Revision 1.1 2002/01/03 03:21:36 lizellaman
31  * existing file, moved to client package
32  *
33  * Revision 1.1.1.1 2001/10/23 13:43:46 lizellaman
34  * initial sourceforge release
35  *
36  */

37
38 package org.datashare.client;
39
40 import org.datashare.objects.DataShareConnectionDescriptor;
41 import org.datashare.objects.ActivateConnectionObject;
42 import org.datashare.objects.DataShareObject;
43 import org.datashare.objects.ChannelDescription;
44 import org.datashare.objects.ChannelDescriptionArray;
45 import org.datashare.objects.RegistrationInfo;
46 import org.datashare.objects.RequestTree;
47 import org.datashare.objects.ServerInfo;
48 import org.datashare.objects.ClientSessionInfo;
49 import org.datashare.objects.CreateSessionRequest;
50 import org.datashare.objects.RegisterTreeListener;
51 import org.datashare.objects.TreeObject;
52 import org.datashare.objects.UpdateAvailableMsg;
53 import org.datashare.SessionUtilities;
54
55 import java.net.InetAddress JavaDoc;
56 import java.util.Arrays JavaDoc;
57
58 /**
59  * This class will provide the methods necessary to establish the commandStatusChannel
60  * to a DataShare server, activate it, and create a data channel for sharing data (no history).
61  * The parent class needs to provide the server, the commandStatusPort,
62  * a user name, password, an enterprise (for organizing clients/sessions if there are lots),
63  * a session name/description, and a channel name/description/type.
64  */

65 public class DataShareClient implements ClientDataReceiverInterface
66    {
67    private DataShareClientInterface rci; // who we will pass data on to and will notify about errors
68
private String JavaDoc userName; // the name that this client wishes to be known by (may be modified by the DataShareServer
69
private String JavaDoc password; // password for username's account
70
public String JavaDoc sessionName; // the session that we are to use (all our Sessions only have one Channel)
71
private String JavaDoc sessionDescription;
72    private String JavaDoc enterpriseName; // used to organize the client in the server's tree of Clients
73
public String JavaDoc clientUniqueName = null; // clientName that has been made unique by the DataShareServer
74
private String JavaDoc publicInfo; // information about this user that is to be shared with other users
75
private InetAddress JavaDoc serverInetAddress = null; // will be set to our server
76
private String JavaDoc clientClass;
77
78    // these have to do with the connection to the server's command status channel
79
private DataShareConnectionDescriptor commandStatusConnectionDescriptor = null;
80    private DataShareConnection commandStatusConnection = null;
81    private int serverCommandStatusPort = 42444; // this value must match the one used by the DataShareServer!!!
82

83    // these have to do with the data connection
84
private DataShareConnectionDescriptor dataConnectionDescriptor = null;
85    private DataShareConnection dataConnection = null;
86    private String JavaDoc channelName;
87    private String JavaDoc channelDescription;
88    private int channelType;
89
90    /**
91     * Constructor
92     */

93    public DataShareClient()
94       {}
95
96    /**
97     * causes connections to DataShareServer to be established
98     * @param channelType must be ChannelDescription.MULTICAST, ChannelDescription.TCP, or
99     * ChannelDescription.UDP
100     */

101    public void
102    initialize(DataShareClientInterface rci,
103               InetAddress JavaDoc serverInetAddress,
104               int serverCommandStatusPort,
105               String JavaDoc sessionName,
106               String JavaDoc sessionDescription,
107               String JavaDoc userName,
108               String JavaDoc password,
109               String JavaDoc publicInfo,
110               String JavaDoc enterpriseName,
111               String JavaDoc channelName,
112               String JavaDoc channelDescription,
113               int channelType
114               )
115       {
116       this.rci = rci;
117       clientClass = rci.getClass().toString();
118       if(clientClass.startsWith("class "))
119          clientClass = clientClass.substring(5); // skip past 'class '
120
this.serverInetAddress = serverInetAddress;
121       this.serverCommandStatusPort = serverCommandStatusPort;
122       this.sessionName = sessionName;
123       this.sessionDescription = sessionDescription;
124       this.userName = userName;
125       this.password = password;
126       this.publicInfo = publicInfo;
127       this.enterpriseName = enterpriseName;
128       this.channelName = channelName;
129       this.channelDescription = channelDescription;
130       this.channelType = channelType;
131       connectToServer();
132       }
133
134    /**
135     * calling this will connect this client to the DataShareServer commandStatusPort
136     */

137    private void connectToServer()
138       {
139       commandStatusConnectionDescriptor =
140               new DataShareConnectionDescriptor("", /* sessionName, not used for commandStatus */
141                                                 new ChannelDescription(), /* channelDescription */
142                                                 serverInetAddress, /* serverIP */
143                                                 serverCommandStatusPort); /* serverPort */
144       try{
145          //System.out.println("creating commandStatus connection...");
146
commandStatusConnection = new DataShareConnection(commandStatusConnectionDescriptor,this);
147          RegistrationInfo ri =
148               new RegistrationInfo(userName, /* clientUserName */
149                                    password, /* password */
150                                    enterpriseName, /* enterpriseName */
151                                    clientClass, /* class of main client */
152                                    RegistrationInfo.UNKNOWN, /* clientMode */
153                                    publicInfo); /* otherInfo */
154          //System.out.println("Sending a RegistrationInfo object to the server...");
155
commandStatusConnection.sendToAll(ri); // doesn't matter which way we send it, just get it to the server
156
// we should get a ServerInfo object back shortly
157
//System.out.println("Waiting for the server to send us a ServerInfo object...");
158
}
159       catch(Exception JavaDoc e)
160          {
161          System.out.println("Problems creating our commandStatus connection...");
162          e.printStackTrace();
163          rci.commandStatusConnectionError(true, e.getMessage());
164          rci.dataChannelIsReady(false);
165          shutDown();
166          }
167       }
168
169
170    /**
171     * Use this method to send an object to everybody in a Channel (including our instance)
172     */

173    public void
174    sendDataToAll(Object JavaDoc object)
175       {
176       if(dataConnection != null)
177          dataConnection.sendToAll(object);
178       else
179          System.out.println("Trying to send data before the data connection is ready");
180       }
181
182    /**
183     * Use this method to send an object to everybody in a Channel (excluding our instance)
184     */

185    public void
186    sendDataToOthers(Object JavaDoc object)
187       {
188       if(dataConnection != null)
189          dataConnection.sendToOthers(object);
190       else
191          System.out.println("Trying to send data before the data connection is ready");
192       }
193
194    /**
195     * Use this method to send an object to one client in a Channel
196     */

197    public void
198    sendDataToClient(Object JavaDoc object, String JavaDoc destinationClientKey)
199       {
200       if(dataConnection != null)
201          dataConnection.sendToClient(object, destinationClientKey);
202       else
203          System.out.println("Trying to send data before the data connection is ready");
204       }
205
206    /**
207     */

208    private void
209    createDataChannel()
210       {
211       ChannelDescription cd = new ChannelDescription(channelName,
212                                                      channelDescription,
213                                                      ChannelDescription.TCP);
214       ChannelDescription cda1[] = {cd};
215       ChannelDescriptionArray cda = new ChannelDescriptionArray(cda1);
216       // first, we need to create a description of our session on the server
217
CreateSessionRequest csr =
218             new CreateSessionRequest(sessionName,
219                                      sessionDescription,
220                                      false, // sessionIsPrivate
221
true, // autoDelete any empty Channels
222
cda,
223                                      true); // join any session that looks like this one
224
commandStatusConnection.sendToAll(csr); // doesn't matter which way we send it, just get it to the server
225
}
226
227
228
229    /**
230     * this method is called when this instance is supposed to clean up and shutdown
231     */

232    public void
233    shutDown()
234       {
235       try{
236          if(dataConnection != null)
237             {
238             rci.dataChannelIsReady(false);
239             dataConnection.closeAll();
240             dataConnection = null;
241             }
242          }
243       catch(Exception JavaDoc e) {}
244       try{
245          if(commandStatusConnection != null)
246             {
247             commandStatusConnection.closeAll();
248             commandStatusConnection = null;
249             }
250          }
251       catch(Exception JavaDoc e) {}
252
253       }
254
255    /**
256     * call this method if you want to be notified when clients/sessions come and go via
257     * the updateReceived() method.
258     */

259    public void
260    registerForUpdates(boolean allChanges)
261       {
262       commandStatusConnection.sendToAll(new RegisterTreeListener(allChanges)); // we want updates
263
}
264
265    /**
266     * call this if you want the server to send a full tree. The tree type will be based on the last
267     * call to registerForUpdates().
268     */

269    public void
270    requestNewTreeNodes()
271       {
272       commandStatusConnection.sendToAll(new RequestTree());
273       }
274
275    /**
276     * this method will be called when data is received on our commandStatus connection
277     */

278    public void
279    dataReceived(DataShareObject dso)
280       {
281       try{
282          Object JavaDoc object = SessionUtilities.retrieveObject(dso.objectBytes);
283          if(object instanceof ServerInfo)
284             {
285             //System.out.println("Received a ServerInfo object");
286
ServerInfo serverInfo = (ServerInfo)object;
287             clientUniqueName = serverInfo.clientKey; // from now on, we use this name to talk to the server
288
this.createDataChannel();
289             }
290          else if(object instanceof UpdateAvailableMsg)
291             {
292             UpdateAvailableMsg msg = (UpdateAvailableMsg)object;
293             rci.updateReceived(msg);
294             }
295          else if(object instanceof TreeObject)
296             {
297             TreeObject to = (TreeObject)object;
298             rci.treeReceived(to.allNodes);
299             }
300          else if(object instanceof ClientSessionInfo)
301             { // join any session that we receive info about this way
302
System.out.println("Received a ClientSessionInfo object...");
303             ClientSessionInfo ourNewSession = (ClientSessionInfo)object;
304             // Check for a server using Network Address Translation (NAT):
305
// test to see that server sent an IP address for data connection that
306
// agrees with the one we think the server is using...
307
// unless it is a Multicast channel.
308
byte[] originalAddress = serverInetAddress.getAddress();
309             for(int channelCount=0; channelCount<ourNewSession.dsConnDescriptor.length; channelCount++)
310                {
311                byte[] dataAddress = ourNewSession.dsConnDescriptor[channelCount].serverIP.getAddress();
312                int channelProtocol = ourNewSession.dsConnDescriptor[channelCount].type;
313                if(channelProtocol != ChannelDescription.MULTICAST && !Arrays.equals(originalAddress, dataAddress))
314                   {
315                   System.out.println("Server is using a different IP address now, suspect NAT is used...");
316                   // server is now sending us a different IP address than we used for CommandStatus connection,
317
// assume NAT is used and convert the server IP address in data channels back to original.
318
ourNewSession.dsConnDescriptor[channelCount].serverIP = serverInetAddress;
319                   }
320                }
321             joinSession(ourNewSession);
322             }
323          else
324             {
325             System.out.println("received unexpected object in command stream");
326             }
327          }
328       catch(Exception JavaDoc e)
329          {
330          e.printStackTrace();
331          }
332       }
333
334    /**
335     * called to create network connection to data channel after server has told us what we need
336     * to know in order to connect.
337     */

338    private void
339    joinSession(ClientSessionInfo newSession)
340       {
341       try{
342          dataConnectionDescriptor = newSession.dsConnDescriptor[0]; // assume only one channel returned
343

344          dataConnection = new DataShareConnection(dataConnectionDescriptor, rci);
345 // System.out.println("Sending the ActivateConnectionObject over our data channel...");
346
dataConnection.sendToAll(new ActivateConnectionObject(this.clientUniqueName),true);
347          rci.dataChannelIsReady(true);
348          //System.out.println("Successfully created our data connection");
349
}
350       catch(Exception JavaDoc e)
351          {
352          e.printStackTrace();
353          rci.dataChannelIsReady(false);
354          }
355       }
356
357
358    /**
359     * this method is called when the commandStatusConnection has been lost,
360     * this will be used to notify anybody that cares...
361     */

362    public void
363    connectionLost(DataShareConnection dsc)
364       {
365       rci.commandStatusConnectionError(true, "Lost commandStatus connection to server");
366       }
367
368    }
369
370
371
Popular Tags