001: /* ----- BEGIN LICENSE BLOCK -----
002: * Version: MPL 1.1
003: *
004: * The contents of this file are subject to the Mozilla Public License Version
005: * 1.1 (the "License"); you may not use this file except in compliance with
006: * the License. You may obtain a copy of the License at
007: * http://www.mozilla.org/MPL/
008: *
009: * Software distributed under the License is distributed on an "AS IS" basis,
010: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011: * for the specific language governing rights and limitations under the
012: * License.
013: *
014: * The Original Code is the DataShareServer.
015: *
016: * The Initial Developer of the Original Code is
017: * Ball Aerospace & Technologies Corp, Fairborn, Ohio
018: * Portions created by the Initial Developer are Copyright (C) 2001
019: * the Initial Developer. All Rights Reserved.
020: *
021: * Contributor(s): Charles Wood <cwood@ball.com>
022: *
023: * ----- END LICENSE BLOCK ----- */
024: /* RCS $Id: BroadCastClient.java,v 1.2 2002/01/20 23:30:24 lizellaman Exp $
025: * $Log: BroadCastClient.java,v $
026: * Revision 1.2 2002/01/20 23:30:24 lizellaman
027: * javadoc updates
028: *
029: * Revision 1.1 2002/01/03 03:21:36 lizellaman
030: * existing file, moved to client package
031: *
032: *
033: */
034: package org.datashare.client;
035:
036: import org.datashare.objects.DataShareObject;
037: import org.datashare.objects.UpdateAvailableMsg;
038: import org.datashare.objects.ChannelDescription;
039: import org.datashare.client.DataShareClient;
040: import org.datashare.client.DataShareClientInterface;
041: import org.datashare.client.DataShareConnection;
042: import javax.swing.tree.DefaultMutableTreeNode;
043: import java.net.InetAddress;
044:
045: /**
046: * This class will provide the methods necessary to establish command/status and
047: * data connections over a network to a DataShareServer, and provide the input and
048: * output methods needed to share data with other BroadCast clients.
049: * BroadCastClients do not care to know about other clients that they are sending data to
050: * (they have no way to find out about other clients, if you need to know about other clients,
051: * use the more general DataShareClient class). BroadCastClients always have their data channels
052: * in the session named 'BroadCastClient'. BroadCastClient always uses a TCP connection for it's data.
053: *
054: * @version 1.1
055: */
056: public class BroadCastClient implements DataShareClientInterface {
057: /**
058: * if true, will cause the newDataReceived method of the
059: * BroadCastClientInterface to be executed asynchronously on the AWT event
060: * dispatching thread. This will happen after all pending AWT events have
061: * been processed. Should be set to true when received data (via the
062: * newDataReceived method of the BroadCastClientInterface) will be used to
063: * update the GUI. This is implemented via a SwingUtilities.invokeLater()
064: * call. Additional documentation and examples for this method can be found
065: * at <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html#invokeLater">How to Use Threads</a>, in The Java Tutorial.
066: */
067: private boolean useThreads = false;
068:
069: /**
070: * for reference only, will be set by the corresponding value in the call to initialize.
071: */
072: private String clientName;
073:
074: /**
075: * for reference only, will be set by the corresponding value in the call to initialize, after it has been made unique by the DataShareServer: will be how this client is known on the DataShareServer. No two clients can have the same name, but all can ask for the same name via the clientName parameter in the initialize call.
076: */
077: private String clientUniqueName;
078:
079: // these have to do with the connection to the server's command status channel
080:
081: /**
082: * for reference only, will be set by the corresponding value in the call to initialize.
083: */
084: private InetAddress serverInetAddress;
085:
086: /**
087: * for reference only, will be set by the corresponding value in the call to initialize.
088: */
089: private int serverCommandStatusPort;
090:
091: /**
092: * for reference only, will be set by the corresponding value in the call to initialize.
093: */
094: private String channelName;
095:
096: /**
097: * will be set by the corresponding value in the call to initialize, should be the set to the class that is
098: * using/supplying our data (note that the class must implement BroadCastClientInterface).
099: */
100: private BroadCastInterface bci;
101:
102: /**
103: * provides most of the functionality of connecting to the DataShareServer
104: */
105: private DataShareClient myClient = new DataShareClient();
106:
107: /**
108: * Constructor, note that initialize must be called for this class to do anything useful.
109: */
110: public BroadCastClient() {
111: }
112:
113: /**
114: * causes connections to DataShareServer to be established, must be called
115: * before any data
116: * can be shared.
117: *
118: * @param serverInetAddress must be set to the IP address, or name, of the
119: * DataShareServer machine
120: * @param serverCommandStatusPort must be set to the port that the
121: * DataShareServer is using for command/status connections
122: * @param clientName the name that this client would like to be know
123: * by, will be made unique by the DataShareServer and set into the
124: * clientUniqueName field
125: * @param bci must be set to the class that implements the
126: * BroadCastInterface, used to route any received data and to notify
127: * in case of network problems
128: * @param channelName the name of the channel that this client should
129: * use for data. Only clients in the same channel will be able to
130: * share data.
131: */
132: public void initialize(InetAddress serverInetAddress,
133: int serverCommandStatusPort, String clientName,
134: BroadCastInterface bci, String channelName) {
135: myClient.initialize(this , serverInetAddress,
136: serverCommandStatusPort, "BroadCastClient",
137: "used by all BroadCastClients", clientName, "", "", "",
138: channelName, "shared by all clients for this workflow",
139: ChannelDescription.TCP);
140: this .serverInetAddress = serverInetAddress;
141: this .serverCommandStatusPort = serverCommandStatusPort;
142: // this.clientName = myClient.clientUniqueName; must wait until data channel ready so we know name is unique
143: this .channelName = channelName;
144: this .bci = bci;
145: }
146:
147: /**
148: * call this when you want the command/status and data connections to be closed
149: * gracefully, like when preparing to exit.
150: */
151: public void shutDown() {
152: myClient.shutDown();
153: }
154:
155: /**
156: * Use this method to send an object to everybody in a Channel (including our instance)
157: *
158: * @param object the data to share, probably should be serializable
159: */
160: public void sendDataToAll(Object object) {
161: myClient.sendDataToAll(object);
162: }
163:
164: /**
165: * Use this method to send an object to everybody in a Channel (excluding our instance)
166: *
167: * @param object the data to share, probably should be serializable
168: */
169: public void sendDataToOthers(Object object) {
170: myClient.sendDataToOthers(object);
171: }
172:
173: /**
174: * This method should not be overidden and is called automatically when data
175: * is received. This method can ensure that any objects we receive
176: * are sent
177: * to the BroadCastClientInterface.newDataReceived method in a thread safe manner.
178: * dataShareObjects that may cause a GUI update should be made thread safe by
179: * setting the 'useThreads' field to true.
180: *
181: * @param dataShareObject the object received from the data channel
182: */
183: public void dataReceived(DataShareObject dataShareObject) {
184: if (useThreads) {
185: final DataShareObject this Object = dataShareObject;
186: final Runnable sendTheObject = new Runnable() {
187: public void run() {
188: bci.newDataReceived(this Object);
189: }
190: };
191: javax.swing.SwingUtilities.invokeLater(sendTheObject);
192: } else {
193: bci.newDataReceived(dataShareObject);
194: }
195: }
196:
197: /**
198: * do not call this method. It is called automatically when the data connection is setup and available
199: * for use. The
200: * data channel must not be used before this gets called. The
201: * BroadCastInterface will be
202: * notified via by calling its dataChannelIsReady method call.
203: *
204: * @param success true if the data channel is ready for use, false if we
205: * failed to get it established.
206: */
207: public void dataChannelIsReady(boolean success) {
208: clientUniqueName = myClient.clientUniqueName; // now we know our unique name has been determined
209: bci.dataChannelIsReady(success);
210: }
211:
212: /**
213: * do not call this method. It is called automatically when the command/status connection has an error.
214: * The BroadCastInterface will be notified via its commandStatusConnectionLost() method call.
215: *
216: * @param fatalError set to true for non-recoverable errors (none are
217: * recoverable at this time)
218: * @param errorMsg describes the nature of the error
219: */
220: public void commandStatusConnectionError(boolean fatalError,
221: String errorMsg) {
222: System.out
223: .println("BroadCastClient lost commandStatusConnection: "
224: + errorMsg);
225: if (fatalError)
226: bci.commandStatusConnectionLost();
227: }
228:
229: /**
230: * do not call this method. It is called automatically when the data connection has been lost.
231: * The BroadCastInterface will be notified via its dataConnectionLost() method call.
232: *
233: * @param dsc describes the connection that we lost
234: */
235: public void connectionLost(DataShareConnection dsc) {
236: System.out
237: .println("BroadCastClient lost data connection for channel: "
238: + dsc.dscd.channelDescription.channelName);
239: bci.dataConnectionLost();
240: }
241:
242: /**
243: * called when a change has occured with the session/client tree, not used. (required by the interface we implement)
244: *
245: * @param msg describes the update (if we has ever asked for them, which we
246: * don't)
247: */
248: public void updateReceived(UpdateAvailableMsg msg) {
249: }
250:
251: /**
252: * called when a new tree has been received, not used. (required by the interface we implement)
253: *
254: * @param newTreeNode describes the tree (if we has ever asked for them,
255: * which we don't)
256: */
257: public void treeReceived(DefaultMutableTreeNode newTreeNode) {
258: }
259:
260: }
|