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 DataShare server.
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: TreeView.java,v 1.5 2002/02/20 14:31:11 lizellaman Exp $
025: * $Log: TreeView.java,v $
026: * Revision 1.5 2002/02/20 14:31:11 lizellaman
027: * changes to improve history retrieval
028: *
029: * Revision 1.4 2002/02/04 13:51:40 lizellaman
030: * Remove all references to past product names (or)
031: * Add PublicAPI for creating Rendezvous Sessions
032: *
033: * Revision 1.3 2002/01/29 20:50:17 lizellaman
034: * Added LoggingInterface, modified the PropertiesInterface implementation
035: *
036: * Revision 1.2 2002/01/03 03:37:36 lizellaman
037: * periodic update of changes I have made
038: *
039: * Revision 1.1.1.1 2001/10/23 13:37:16 lizellaman
040: * initial sourceforge release
041: *
042: */
043:
044: package org.datashare;
045:
046: //import com.ball.ads.ejb.hc.DSSession;
047: //import com.ball.ads.ejb.hc.DSChannel;
048:
049: import javax.swing.JTree;
050: import javax.swing.tree.DefaultMutableTreeNode;
051: import javax.swing.event.TreeSelectionListener;
052: import javax.swing.event.TreeSelectionEvent;
053: import javax.swing.tree.TreeSelectionModel;
054: import javax.swing.tree.DefaultTreeCellRenderer;
055: import javax.swing.tree.TreePath;
056: import javax.swing.JTextArea;
057: import javax.swing.JScrollPane;
058: import javax.swing.tree.DefaultTreeModel;
059:
060: import org.datashare.objects.DataShareObject;
061: import org.datashare.objects.DefaultObjectInfo;
062: import org.datashare.objects.UpdateAvailableMsg;
063: import org.datashare.objects.DataShareConnectionDescriptor;
064: import org.datashare.objects.ChannelDescription;
065:
066: import java.net.InetAddress;
067:
068: //import java.lang.Exception;
069: import java.util.Enumeration;
070: import java.util.GregorianCalendar;
071: import java.util.Hashtable;
072: import java.util.Vector;
073: import java.util.StringTokenizer;
074: import java.awt.Frame;
075: import java.rmi.RemoteException;
076: import java.text.DateFormat;
077:
078: /**
079: * This class is run on the server and is responsible for maintaining our tree view of clients and
080: * sessions/channels/consumers, and for issuing UpdateAvailableMsg objects to clients indicating
081: * changes in our tree view. It makes calls back to the server when events warrent (such as a new
082: * client has joined so the server is told about it so an UpdateAvailable object can be sent to all
083: * registered listeners.
084: *
085: * @author Charles Wood
086: * @version 1.0
087: * @date March 01, 2001
088: */
089: public class TreeView {
090: /**
091: * a reference to the server instance that created this instance
092: */
093: TreeViewServerInterface server = null;
094:
095: /**
096: * used by tree to maintain the hierarchical structure of the Registry
097: */
098: private DefaultMutableTreeNode internalTreeNode;
099:
100: /**
101: * contains the Sessions of the Registry
102: */
103: private DefaultMutableTreeNode sessionNodes;
104:
105: /**
106: * contains the Special Clients of the Registry
107: */
108: private DefaultMutableTreeNode clientNodes;
109:
110: /**
111: * contains all the TreeViewListeners that wish to receive tree updates via the
112: * server's commandStatus connection when the TreeView changes (such as a
113: * Session is added, a Client leaves, etc.). Clients that see all tree events
114: * will not be included here.
115: * Note that this is now going to be a Hashtable of Hashtables. The toplevel
116: * Hashtables is keyed by clientClass and contains Hashtables. The second level
117: * of Hashtables are keyed by clientKey and contain SocketAdapters.
118: */
119: private Hashtable treeViewListeners = new Hashtable();
120:
121: /**
122: * contains all the TreeViewListeners that wish to receive All updates via the
123: * server's commandStatus connection when the TreeView changes (such as a
124: * Session is added, a Client leaves, etc.). These listeners are notified of
125: * ALL activity, even the private Session/channel creation. Keys are the
126: */
127: private Hashtable treeViewAllListeners = new Hashtable();
128:
129: /**
130: * the name that will appear as the sender of this class's objects (send over
131: * the listener's commandStatus connection)
132: */
133: private String myClientName = "TreeViewClient";
134:
135: private boolean foundArchivedSessions = false; // used so we create archived stuff only once
136: // table keyed by ADSKEY strings, and contains SessionInfo objects
137: // The objects are from sessions that were inactive when server started
138: Hashtable oldSessionsTable = new Hashtable();
139: private DefaultMutableTreeNode archiveNode = null;
140:
141: /**
142: * Constructor, performs no initialization
143: *
144: * @param server the server instance that created this instance
145: */
146: public TreeView(TreeViewServerInterface server) {
147: this .server = server;
148: initializeInternalNodes(); // create the basic node structure
149: createInternalTreeNode(); // takes all our Hashtables and puts them into internalTreeNode
150: if (server.getShowArchivedSessionsToAdmin())
151: getArchivedSessions();
152: }
153:
154: /**
155: * returns the DefaultMutableTreeNode that represents the present state of our connections
156: */
157: public DefaultMutableTreeNode getTreeNode() {
158: return this .internalTreeNode;
159: }
160:
161: /**
162: * returns the DefaultMutableTreeNode that contains DefaultObjectInfo objects, suitable for serializing
163: * @param clientInfo contains information about the client that will be the tree, used to
164: * customize the tree for that client
165: */
166: public DefaultMutableTreeNode getExternalTreeNode(
167: ClientInfo clientInfo) {
168: return this .createExternalTreeNode(clientInfo);
169: }
170:
171: /**
172: * calling this method will register the caller so that any subsequent tree updates
173: * will be sent to the specified TreeViewListenerInterface. Note that for now,
174: * a client may receive only their own class of sessions/clients updates, or all updates.
175: * @param clientInfo the client of the commandStatus connection to be used
176: * for the update objects, must be previously registered with server.
177: * @param ts the socket that is to be used when sending TreeView datashareobjects, should
178: * correspond to a commandStatus connection on a client.
179: * Some of what is going on in this class might be better handled by a database,
180: * but we really don't want to force a user to have access to a database...and the
181: * functioning of this method is important.
182: * Note that clients should only be in treeViewListeners or treeViewAllListeners, not both.
183: * If a client is added to one, this method will remove them from the other.
184: * The type of clientClass that the client will be notified of will be only their own
185: * clientClass, unless their ClientInfo has the seeAllTreeObjects flag set.
186: *
187: * @returns true if TreeViewListener was successfully registered, false otherwise
188: */
189: public boolean addTreeListener(ClientInfo clientInfo,
190: SocketAdapter ts) {
191: boolean retValue = false;
192: boolean removeFromListeners = false; // set to true if we add them to the AllListeners table
193: String clientKey = clientInfo.getKeyValue();
194: String clientClass = clientInfo.getClientClass();
195: if (server.isClientRegistered(clientKey)) {
196: // client is known to server...allow it to be a listener
197: if (clientInfo.getSeeAllTreeObjects()) {
198: SessionUtilities.getLoggingInterface().debugMsg(
199: SessionUtilities.getLoggingInterface().DEBUG,
200: SessionUtilities.getLoggingInterface().CLIENT,
201: "Adding AllTreeListener-> " + clientKey);
202: treeViewAllListeners.put(clientKey, ts);
203: retValue = true;
204: removeFromListeners = true; // if this client is in other table, remove it...
205: } else {
206: // remove from treeViewAllListeners (just in case)
207: treeViewAllListeners.remove(clientKey);
208: }
209:
210: // try to find the client in the treeViewListeners...
211: if (treeViewListeners.containsKey(clientClass)) {
212: // get hashtable for all clients of this class
213: Hashtable this ClientsTable = (Hashtable) treeViewListeners
214: .get(clientClass);
215: if (removeFromListeners)
216: this ClientsTable.remove(clientKey); // already in other table, remove from this one
217: else {
218: // we are adding...
219: this ClientsTable.put(clientKey, ts); // overwrite old value if present
220: }
221: } else // no entry for this class of clients
222: {
223: if (!removeFromListeners) // then we want to create an entry
224: {
225: Hashtable this ClientsTable = new Hashtable();
226: this ClientsTable.put(clientKey, ts); // create first entry
227: treeViewListeners
228: .put(clientClass, this ClientsTable);
229: retValue = true;
230: }
231: }
232: } else {
233: SessionUtilities.getLoggingInterface().debugMsg(
234: SessionUtilities.getLoggingInterface().WARNING,
235: SessionUtilities.getLoggingInterface().CLIENT,
236: "Non-Registered client tried to receive Tree updates-> "
237: + clientKey);
238: }
239: return retValue;
240: }
241:
242: /**
243: * removes the specified TreeViewListener from both Admin and normal Client listeners
244: */
245: public boolean removeTreeListener(SocketAdapter ts) {
246: boolean retValue = false; // set to true if listener was removed
247: if (treeViewAllListeners.containsKey(ts.getClientKey())) {
248: treeViewAllListeners.remove(ts.getClientKey());
249: retValue = true;
250: }
251: // could use else here, but why? play it safe and try to remove anyway
252: if (treeViewListeners.containsKey(ts.getClientClass())) {
253: Hashtable this ClientsTable = (Hashtable) treeViewListeners
254: .get(ts.getClientClass());
255: this ClientsTable.remove(ts.getClientKey());
256: if (this ClientsTable.isEmpty())
257: treeViewListeners.remove(ts.getClientKey());
258: retValue = true;
259: }
260: return retValue;
261: }
262:
263: /**
264: * Creates the top level TreeNodes for our internal tree
265: */
266: private void initializeInternalNodes() {
267: internalTreeNode = new DefaultMutableTreeNode(
268: new DefaultObjectInfo(DefaultObjectInfo.COLLABORATION,
269: DefaultObjectInfo.COLLABORATION, server
270: .getServerInfo()));
271: sessionNodes = new DefaultMutableTreeNode(
272: new DefaultObjectInfo(DefaultObjectInfo.ALLSESSIONS,
273: DefaultObjectInfo.ALLSESSIONS, SessionUtilities
274: .getAllSessionsHelpString()));
275: clientNodes = new DefaultMutableTreeNode(
276: new DefaultObjectInfo(DefaultObjectInfo.COLLABORANTS,
277: DefaultObjectInfo.COLLABORANTS,
278: "<br>Lists all the users connected to the DataShare Server</td></tr>"));
279: internalTreeNode.add(sessionNodes);
280: internalTreeNode.add(clientNodes);
281: }
282:
283: /**
284: * Takes our internal Hashtables and puts them into the DefaultMutableTreeNodes
285: * internalTreeNode. The top level is
286: * SpecialClients and Sessions, Sessions have Channels, Channels have Consumers.
287: * Note that we may want to pare down what we put into the TreeNodes to help on
288: * bandwidth to our TreeNode recipients (HC Functions).
289: */
290: private synchronized void createInternalTreeNode() {
291: Hashtable sessionTable = server.getSessionTable();
292: Hashtable clientTable = server.getSpecialClientTable();
293:
294: for (Enumeration e = sessionTable.elements(); e
295: .hasMoreElements();) {
296: sessionNodes
297: .add(new DefaultMutableTreeNode(e.nextElement()));
298: // now add all Channels to this Session
299: DefaultMutableTreeNode this SessionNode = sessionNodes
300: .getLastLeaf();
301: SessionInfo this SessionInfo = (SessionInfo) this SessionNode
302: .getUserObject();
303: if (this SessionInfo.getChannelTable() != null) {
304: for (Enumeration channelEnum = this SessionInfo
305: .getChannelTable().elements(); channelEnum
306: .hasMoreElements();) {
307: this SessionNode.add(new DefaultMutableTreeNode(
308: channelEnum.nextElement()));
309: // now add all Consumers to this Channel
310: DefaultMutableTreeNode this ChannelNode = this SessionNode
311: .getLastLeaf();
312: ChannelInfo this ChannelInfo = (ChannelInfo) this ChannelNode
313: .getUserObject();
314: if (this ChannelInfo.getConsumerTable() != null) {
315: for (Enumeration consumerEnum = this ChannelInfo
316: .getConsumerTable().elements(); consumerEnum
317: .hasMoreElements();) {
318: this ChannelNode
319: .add(new DefaultMutableTreeNode(
320: consumerEnum.nextElement()));
321: }
322: }
323: }
324: }
325: }
326: for (Enumeration e = clientTable.elements(); e
327: .hasMoreElements();) {
328: clientNodes
329: .add(new DefaultMutableTreeNode(e.nextElement()));
330: }
331:
332: }
333:
334: /**
335: * This creates a tree that contains only DefaultObjectInfo objects, suitable for serialization
336: * Note that the structure of the tree created depends on clientInfo.getSeeAllTreeObjects()
337: * @param clientInfo used to taylor the tree to the the clientInfo value of
338: */
339: private DefaultMutableTreeNode createExternalTreeNode(
340: ClientInfo clientInfo) {
341: DefaultMutableTreeNode externalTreeNode = new DefaultMutableTreeNode(
342: new DefaultObjectInfo(DefaultObjectInfo.COLLABORATION,
343: DefaultObjectInfo.COLLABORATION, server
344: .getServerInfo()));
345: DefaultMutableTreeNode sessionNodes = new DefaultMutableTreeNode(
346: new DefaultObjectInfo(DefaultObjectInfo.ALLSESSIONS,
347: DefaultObjectInfo.ALLSESSIONS, SessionUtilities
348: .getAllSessionsHelpString()));
349: DefaultMutableTreeNode clientNodes = new DefaultMutableTreeNode(
350: new DefaultObjectInfo(DefaultObjectInfo.COLLABORANTS,
351: DefaultObjectInfo.COLLABORANTS,
352: "<br>Lists all the users connected to the DataShare Server</td></tr>"));
353: externalTreeNode.add(sessionNodes);
354: externalTreeNode.add(clientNodes);
355:
356: boolean showAllClients = clientInfo.getSeeAllTreeObjects(); // if true, put all sessions/clients in tree
357: Hashtable sessionTable = server.getSessionTable();
358: Hashtable clientTable = server.getSpecialClientTable();
359: String clientClass = clientInfo.getClientClass(); // if showAllClients is false, used to find similar clients/Sessions
360:
361: DefaultMutableTreeNode classNode = null; // will be set to node we add sessions/clients to
362: Hashtable classTable = new Hashtable(); // keyed by clientClass, contains node to add session/client to
363:
364: for (Enumeration e = sessionTable.elements(); e
365: .hasMoreElements();) {
366: SessionInfo this SessionInfo = (SessionInfo) e.nextElement();
367: classNode = null;
368: if (showAllClients) {
369: if (clientInfo.getClientClass().equals(
370: this SessionInfo.getClientClass())) // session class same as client class?
371: classNode = sessionNodes; // then put at top level of Sessions
372: else if (classTable.containsKey(this SessionInfo
373: .getClientClass())) // we already have a subsession for this client class?
374: classNode = (DefaultMutableTreeNode) classTable
375: .get(this SessionInfo.getClientClass());
376: else // create a node to add the Session to...
377: {
378: String nodeName = this SessionInfo.getClientClass();
379: StringTokenizer st = new StringTokenizer(nodeName,
380: "//\\.");
381: while (st.hasMoreTokens())
382: nodeName = st.nextToken(); // make name be last part of clientClass
383: DefaultObjectInfo doi = new DefaultObjectInfo(
384: nodeName + " Sessions",
385: DefaultObjectInfo.SUBSESSIONTYPE,
386: this SessionInfo.getClientClass(),
387: "used by clients of class "
388: + this SessionInfo.getClientClass());
389: DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
390: doi);
391: sessionNodes.add(newNode);
392: classTable.put(this SessionInfo.getClientClass(),
393: newNode);
394: classNode = newNode;
395: }
396: } else if (this SessionInfo.getClientClass().equals(
397: clientClass)) {
398: classNode = sessionNodes;
399: }
400: // else this session is ignored and the clientClassSessionNode value is null
401:
402: if (classNode != null) // then we do process this session...
403: {
404: // add the session to the appropriate place in the tree
405: classNode.add(new DefaultMutableTreeNode(
406: new DefaultObjectInfo(this SessionInfo)));
407:
408: // now add all Channels to this Session
409: DefaultMutableTreeNode this SessionNode = sessionNodes
410: .getLastLeaf();
411:
412: if (this SessionInfo.getChannelTable() != null) {
413: for (Enumeration channelEnum = this SessionInfo
414: .getChannelTable().elements(); channelEnum
415: .hasMoreElements();) {
416: ChannelInfo this ChannelInfo = (ChannelInfo) channelEnum
417: .nextElement();
418: this SessionNode
419: .add(new DefaultMutableTreeNode(
420: new DefaultObjectInfo(
421: this ChannelInfo)));
422: // now add all Consumers to this Channel
423: DefaultMutableTreeNode this ChannelNode = this SessionNode
424: .getLastLeaf();
425: if (this ChannelInfo.getConsumerTable() != null) {
426: for (Enumeration consumerEnum = this ChannelInfo
427: .getConsumerTable().elements(); consumerEnum
428: .hasMoreElements();) {
429: ConsumerInfo consumerInfo = (ConsumerInfo) consumerEnum
430: .nextElement();
431: this ChannelNode
432: .add(new DefaultMutableTreeNode(
433: new DefaultObjectInfo(
434: consumerInfo)));
435: }
436: }
437: }
438: }
439: }
440: }
441:
442: ///now do the client part...
443: classTable.clear(); // keyed by clientClass, contains node to add client to
444:
445: for (Enumeration e = clientTable.elements(); e
446: .hasMoreElements();) {
447: ClientInfo ci = (ClientInfo) e.nextElement();
448: classNode = null; // will be set to node we add clients to
449: if (showAllClients) {
450: if (clientInfo.getClientClass().equals(
451: ci.getClientClass()))
452: classNode = clientNodes;
453: else if (classTable.containsKey(ci.getClientClass()))
454: classNode = (DefaultMutableTreeNode) classTable
455: .get(ci.getClientClass());
456: else // create a node to add the Session to...
457: {
458: String nodeName = ci.getClientClass();
459: StringTokenizer st = new StringTokenizer(nodeName,
460: "//\\.");
461: while (st.hasMoreTokens())
462: nodeName = st.nextToken(); // make name be last part of clientClass
463:
464: DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
465: new DefaultObjectInfo(
466: nodeName + " clients",
467: DefaultObjectInfo.SUBCLIENTTYPE, ci
468: .getClientClass(),
469: "used by clients of class "
470: + ci.getClientClass()));
471: clientNodes.add(newNode);
472: classTable.put(ci.getClientClass(), newNode);
473: classNode = newNode;
474: }
475: } else if (ci.getClientClass().equals(clientClass)) {
476: classNode = clientNodes;
477: }
478: // else this client is ignored and the classNode value is null
479:
480: if (classNode != null) // then we do process this session...
481: {
482: if (ci == null)
483: SessionUtilities
484: .getLoggingInterface()
485: .debugMsg(
486: SessionUtilities
487: .getLoggingInterface().DEBUG,
488: SessionUtilities
489: .getLoggingInterface().CLIENT,
490: "First client for this class ->"
491: + classNode.toString());
492: classNode.add(new DefaultMutableTreeNode(
493: new DefaultObjectInfo(ci)));
494: }
495: }
496:
497: SessionUtilities.getLoggingInterface().debugMsg(
498: SessionUtilities.getLoggingInterface().DEBUG,
499: SessionUtilities.getLoggingInterface().CLIENT,
500: "*** createExternalTreeNode() returning "
501: + externalTreeNode.toString());
502: return externalTreeNode;
503: }
504:
505: /**
506: * removes the specified Client from the ClientNodes and notifies listeners
507: */
508: public void removeSpecialClient(ClientInfo clientInfo) {
509: updateAvailable(new UpdateAvailableMsg(
510: "removing SpecialClient " + clientInfo.getKeyValue(),
511: new DefaultObjectInfo(clientInfo), false), false);
512: createInternalTreeNode(); // remake our local table
513: }
514:
515: /**
516: * adds the specified Client to the ClientNodes and notifies listeners
517: */
518: public void addSpecialClient(ClientInfo clientInfo) {
519: updateAvailable(new UpdateAvailableMsg("adding SpecialClient "
520: + clientInfo.getKeyValue(), new DefaultObjectInfo(
521: clientInfo), true), false);
522: createInternalTreeNode(); // remake our local table
523: }
524:
525: /**
526: * removes the specified Session from the sessionNodes and notifies listeners
527: */
528: public void removeSession(SessionInfo sessionInfo) {
529: updateAvailable(new UpdateAvailableMsg("removing Session "
530: + sessionInfo.getKeyValue(), new DefaultObjectInfo(
531: sessionInfo), false), false);
532: createInternalTreeNode(); // remake our local table
533: }
534:
535: /**
536: * adds the specified Session to the sessionNodes and notifies listeners
537: */
538: public void addSession(SessionInfo sessionInfo) {
539: updateAvailable(new UpdateAvailableMsg("adding Session "
540: + sessionInfo.getKeyValue(), new DefaultObjectInfo(
541: sessionInfo), true), false);
542: createInternalTreeNode(); // remake our local table
543: }
544:
545: /**
546: * removes the specified Channel from the parent Session and notifies listeners
547: */
548: public void removeChannel(ChannelInfo channelInfo) {
549: updateAvailable(new UpdateAvailableMsg("removing Channel "
550: + channelInfo.getKeyValue(), new DefaultObjectInfo(
551: channelInfo), false), false);
552: createInternalTreeNode(); // remake our local table
553: }
554:
555: /**
556: * adds the specified Channel to the parent Session and notifies listeners
557: */
558: public void addChannel(ChannelInfo channelInfo) {
559: updateAvailable(new UpdateAvailableMsg("adding Channel "
560: + channelInfo.getKeyValue(), new DefaultObjectInfo(
561: channelInfo), true), false);
562: createInternalTreeNode(); // remake our local table
563: }
564:
565: /**
566: * adds the specified Consumer to the specified Channel of the specified Session and notifies listeners
567: */
568: public void addConsumer(ConsumerInfo consumerInfo) {
569: DefaultObjectInfo consumerObject = new DefaultObjectInfo(
570: consumerInfo);
571: updateAvailable(new UpdateAvailableMsg("adding/updating "
572: + (consumerObject.getActive() ? "active" : "inactive")
573: + " Consumer " + consumerObject.getKeyValue(),
574: consumerObject, true), false);
575: createInternalTreeNode(); // remake our local table
576: }
577:
578: /**
579: * removes the specified Consumer from the specified Channel of the specified Session and notifies listeners
580: */
581: public void removeConsumer(ConsumerInfo consumerInfo) {
582: updateAvailable(new UpdateAvailableMsg("removing Consumer "
583: + consumerInfo.getKeyValue(), new DefaultObjectInfo(
584: consumerInfo), false), false);
585: createInternalTreeNode(); // remake our local table
586: }
587:
588: /**
589: * Uses the commandStatus connection on the server to issue objects
590: * to clients who have become TreeViewListeners, mainly used to send
591: * UpdateAvailableMsg objects, but can send any datashare.object object.
592: * @param object the serializable object to send to the registered TreeViewListeners
593: * @param adminOnly if true, this update is only sent to admin clients
594: */
595: public void
596: updateAvailable(UpdateAvailableMsg msg, boolean adminOnly)
597: {
598: boolean OKtoSend = true;
599:
600: // here we rely on the assumption that clients are only in one of the tables...
601: // first send to the clients that get all the updates
602: for(Enumeration enum = treeViewAllListeners.elements(); enum.hasMoreElements();)
603: {
604: OKtoSend = true;
605: SocketAdapter ts = (SocketAdapter)enum.nextElement();
606: if(!ts.getAdmin() && adminOnly)
607: OKtoSend = false; // don't send adminOnly message to non-admin client
608: else
609: {
610: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
611: SessionUtilities.getLoggingInterface().CLIENT,
612: "Sending UpdateAvailableMsg to (get all) client "+ ts.getClientKey());
613: try{
614: ts.sendData(new DataShareObject(SessionUtilities.convertObjectToByteArray(msg), ts.getType(), myClientName));
615: }
616: catch(Exception e)
617: {
618: e.printStackTrace();
619: }
620: }
621: }
622:
623: // now try to send to clientClass only listeners
624: for(Enumeration enum = treeViewListeners.elements(); enum.hasMoreElements();)
625: {
626: Hashtable table = (Hashtable)enum.nextElement();
627: for(Enumeration enum2 = table.elements(); enum2.hasMoreElements();)
628: {
629: SocketAdapter sa = (SocketAdapter)enum2.nextElement();
630: if(!sa.getAdmin() && adminOnly)
631: OKtoSend = false; // not really used, makes logic easier to understand
632: else
633: {
634: if(sa.getClientClass().equals(msg.getObject().getClientClass())) // get object's clientClass
635: {
636: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
637: SessionUtilities.getLoggingInterface().CLIENT,
638: "Sending UpdateAvailableMsg to client "+ sa.getClientKey());
639: try{
640: sa.sendData(new DataShareObject(SessionUtilities.convertObjectToByteArray(msg), sa.getType(), myClientName));
641: }
642: catch(Exception e)
643: {
644: e.printStackTrace();
645: }
646: }
647: }
648: }
649: }
650: }
651:
652: /////////////////////////
653: // this code has to do with displaying the archived sessions for admin users
654: /////////////////////////
655:
656: /**
657: * Creates a node that show all the archived Sessions on the server, suitable for Serialization (for external use)
658: */
659: DefaultMutableTreeNode getExternalArchivedNode() {
660: if (server.getPersistData()) {
661: archiveNode = new DefaultMutableTreeNode(
662: new DefaultObjectInfo(DefaultObjectInfo.ARCHIVES,
663: DefaultObjectInfo.ARCHIVES,
664: "Lists Sessions that have been closed"));
665: for (Enumeration e = getArchivedSessions().elements(); e
666: .hasMoreElements();) {
667: try {
668: SessionInfo oldSession = (SessionInfo) e
669: .nextElement();
670: archiveNode.add(new DefaultMutableTreeNode(
671: new DefaultObjectInfo(oldSession)));
672: // now add all Channels to this Session
673: DefaultMutableTreeNode this SessionNode = archiveNode
674: .getLastLeaf();
675: if (oldSession.getChannelTable() != null) {
676: for (Enumeration channelEnum = oldSession
677: .getChannelTable().elements(); channelEnum
678: .hasMoreElements();) {
679: ChannelInfo this ChannelInfo = (ChannelInfo) channelEnum
680: .nextElement();
681: this SessionNode
682: .add(new DefaultMutableTreeNode(
683: new DefaultObjectInfo(
684: this ChannelInfo)));
685: }
686: }
687: } catch (Exception ex) {
688: ex.printStackTrace();
689: }
690: }
691: }
692: return archiveNode;
693: }
694:
695: /**
696: * find all Sessions in database, remove the ones that exist in our sessionTable, what is left
697: * is returned as a Hashtable of archived Sessions, the key is the AdsKeyString, the entry is SessionInfo.
698: * Should only be called if server is running in a container and is creating EJBs.
699: */
700: private Hashtable
701: getArchivedSessions()
702: {
703: if(!foundArchivedSessions && server.getPersistData())
704: {
705: try{
706: PersistenceInterface persistenceInterface = server.getPersistenceInterface();
707: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
708: SessionUtilities.getLoggingInterface().DATABASE,
709: "Retrieving all archived sessions, may take a while...");
710: Enumeration enum = persistenceInterface.searchForUserObjects("DSSession3Home", "Order By getSessionName()" );
711: for( ; enum.hasMoreElements(); )
712: {
713: SessionInfo sessionInfo = (SessionInfo)enum.nextElement();
714: try{
715: // add it to oldSessionsTable only if it is not in server's sessionTable
716: if(!server.getSessionTable().containsKey(sessionInfo.getKeyValue()))
717: {
718: oldSessionsTable.put(sessionInfo.getDatabaseID(),sessionInfo);
719: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
720: SessionUtilities.getLoggingInterface().DATABASE,
721: "Found Session " + sessionInfo.getName() + ", created by "+ sessionInfo.getOwnerName() + " on " + DateFormat.getDateInstance().format(sessionInfo.getDate()) + "\n" +
722: "More SessionInfo:\n " + sessionInfo.getInfo());
723: Enumeration enum2 = persistenceInterface.searchForUserObjects("DSChannel3Home", "getSessionKey()='"+sessionInfo.getDatabaseID()+"'" );
724: for( ; enum2.hasMoreElements(); )
725: {
726: try{
727: ChannelInfo channelInfo = (ChannelInfo)enum2.nextElement();
728: channelInfo.setSessionInfo(sessionInfo);
729: //int count = persistenceInterface.findCount("DSData3Home", "getChannelKey()='"+channelInfo.getDatabaseID()+"'");
730: sessionInfo.addChannel(channelInfo);
731: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
732: SessionUtilities.getLoggingInterface().DATABASE,
733: " found Channel " + channelInfo.getName());
734: }
735: catch(Exception e)
736: {
737: e.printStackTrace();
738: }
739: }
740: }
741: }
742: catch(Exception e)
743: {
744: e.printStackTrace();
745: }
746: }
747: }
748: catch(Exception e)
749: {
750: e.printStackTrace();
751: }
752: foundArchivedSessions = true;
753: }
754: return oldSessionsTable;
755: }
756: }
|