KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mc4j > console > connection > ConnectionNode


1 /*
2  * Copyright 2002-2004 Greg Hinkle
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.mc4j.console.connection;
18
19 import org.mc4j.console.IConnectionNode;
20 import org.mc4j.console.bean.MBeanNode;
21 import org.mc4j.console.connection.create.CreateMBeanAction;
22 import org.mc4j.console.connection.persistence.ConnectionSetDatabase;
23 import org.mc4j.console.dashboard.global.GlobalDashboardSetNode;
24 import org.mc4j.console.domain.DomainNode;
25 import org.mc4j.console.install.ExplorerUtil;
26 import org.mc4j.console.mejb.MEJBNode;
27 import org.mc4j.console.query.NewQueryAction;
28 import org.mc4j.console.util.NodeUtil;
29 import org.mc4j.console.util.ConnectionInfoAction;
30 import org.mc4j.ems.connection.ConnectionFactory;
31 import org.mc4j.ems.connection.EmsConnection;
32 import org.mc4j.ems.connection.MBeanRegistrationEvent;
33 import org.mc4j.ems.connection.MBeanRegistrationListener;
34 import org.mc4j.ems.connection.EmsConnectException;
35 import org.mc4j.ems.connection.bean.EmsBean;
36 import org.mc4j.ems.connection.bean.attribute.EmsAttribute;
37 import org.mc4j.ems.connection.settings.ConnectionSettings;
38 import org.openide.ErrorManager;
39 import org.openide.actions.OpenLocalExplorerAction;
40 import org.openide.actions.PropertiesAction;
41 import org.openide.actions.ToolsAction;
42 import org.openide.awt.StatusDisplayer;
43 import org.openide.nodes.AbstractNode;
44 import org.openide.nodes.BeanNode;
45 import org.openide.nodes.Children;
46 import org.openide.nodes.Node;
47 import org.openide.nodes.Sheet;
48 import org.openide.util.HelpCtx;
49 import org.openide.util.actions.NodeAction;
50 import org.openide.util.actions.SystemAction;
51 import org.openide.windows.IOProvider;
52 import org.openide.windows.TopComponent;
53
54 import javax.swing.*;
55 import java.awt.*;
56 import java.beans.IntrospectionException JavaDoc;
57 import java.beans.PropertyChangeEvent JavaDoc;
58 import java.beans.PropertyChangeListener JavaDoc;
59 import java.io.IOException JavaDoc;
60 import java.util.ArrayList JavaDoc;
61 import java.util.Collections JavaDoc;
62 import java.util.HashMap JavaDoc;
63 import java.util.HashSet JavaDoc;
64 import java.util.Iterator JavaDoc;
65 import java.util.List JavaDoc;
66 import java.util.Map JavaDoc;
67 import java.util.Set JavaDoc;
68 import java.util.Timer JavaDoc;
69
70 /**
71  * This Node is the abstract node representing a connection to a JMX Server.
72  *
73  * @author Greg Hinkle (ghinkle@users.sourceforge.net), January 2002
74  * @version $Revision: 575 $($Author: ghinkl $ / $Date: 2006-05-21 22:38:53 -0400 (Sun, 21 May 2006) $)
75  */

76 public class ConnectionNode extends AbstractNode implements IConnectionNode, PropertyChangeListener JavaDoc, Comparable JavaDoc, MBeanRegistrationListener {
77
78
79     // Persistable settings
80
protected ConnectionSettings connectionSettings;
81
82     // Live information
83
protected boolean connected = false;
84
85     protected boolean connectionFailure = false;
86
87     /** Holds a map of cannonical object names to MBeanNodes */
88     protected volatile Map JavaDoc<String JavaDoc, MBeanNode> mbeans = new HashMap JavaDoc<String JavaDoc, MBeanNode>();
89
90     protected Node.PropertySet[] settingsPropertySets;
91
92     private Timer JavaDoc refreshTimer;
93
94     private Node mbeanNode;
95
96     //private PooledExecutor remoteExecutor;
97

98     private Set JavaDoc openDashboards = new HashSet JavaDoc();
99
100
101     private EmsConnection emsConnection;
102
103
104     public ConnectionNode(ConnectionSettings connectionSettings) {
105         super(new ConnectionNodeChildren());
106         this.connectionSettings = connectionSettings;
107
108         // Setup a working pool of up to 5 threads to process remote calls
109
//remoteExecutor = new PooledExecutor(5);
110
//remoteExecutor.waitWhenBlocked();
111

112         // Set self on domain nodes so they can alert us when someone expands us
113
((ConnectionNodeChildren)this.getChildren()).setConnectionNode(this);
114
115         updateIcon();
116         // Set FeatureDescriptor stuff:
117

118         setName(connectionSettings.getConnectionName());
119
120         addPropertyChangeListener(this);
121     }
122
123     public EmsConnection getEmsConnection() {
124         return emsConnection;
125     }
126
127     public Object JavaDoc getMEJB() {
128         return null;
129     }
130
131 // /**
132
// * Provides access to the remote executor used to make calls to the remote server...
133
// * @return The pooled executor for this connection
134
// */
135
// public PooledExecutor getExecutor() {
136
// return this.remoteExecutor;
137
// }
138

139     public void propertyChange(PropertyChangeEvent JavaDoc evt) {
140         ConnectionSetDatabase.addNode(connectionSettings);
141     }
142
143
144     public int compareTo(Object JavaDoc o) {
145         Node otherNode = (Node) o;
146         return this.getDisplayName().compareTo(otherNode.getDisplayName());
147     }
148
149     public void initialize(ConnectionSettings settings) {
150         this.connectionSettings = settings;
151         setName(settings.getConnectionName());
152         setDisplayName(settings.getConnectionName());
153         setShortDescription("Connection to " + settings.getServerUrl());
154     }
155
156
157     // Create the popup menu:
158
protected SystemAction[] createActions() {
159         return new SystemAction[] {
160             SystemAction.get(OpenLocalExplorerAction.class),
161             null,
162             NodeAction.get(CreateMBeanAction.class),
163             null,
164             SystemAction.get(ReconnectAction.class),
165             SystemAction.get(DisconnectAction.class),
166             SystemAction.get(RefreshAction.class),
167             SystemAction.get(NewQueryAction.class),
168             SystemAction.get(StatsIntrospectorAction.class),
169             SystemAction.get(NumericIntrospectorAction.class),
170             null,
171             SystemAction.get(DeleteConnectionAction.class),
172             null,
173             SystemAction.get(ToolsAction.class),
174             null,
175             SystemAction.get(PropertiesAction.class),
176         };
177     }
178
179     public HelpCtx getHelpCtx() {
180         return HelpCtx.DEFAULT_HELP;
181         // When you have help, change to:
182
// return new HelpCtx(ConnectionNodeNode.class);
183
}
184
185     protected void loadConnectionNodeChildren() throws Exception JavaDoc {
186         loadConnectionNodeChildren(false);
187     }
188
189     protected void loadConnectionNodeChildren(boolean showProgress) throws Exception JavaDoc {
190
191         String JavaDoc currentText = StatusDisplayer.getDefault().getStatusText();
192         ProgressDialog progressDialog = null;
193
194         StatusDisplayer.getDefault().setStatusText("Loading nodes [" + connectionSettings.getConnectionName() + "]");
195
196
197         Set JavaDoc<EmsBean> emsBeans = emsConnection.getBeans();
198         StatusDisplayer.getDefault().setStatusText("Loading nodes [" + connectionSettings.getConnectionName()
199             + "] 0 of " + emsBeans.size());
200
201         if (showProgress)
202             progressDialog = new ProgressDialog(emsBeans.size());
203     }
204
205     public void registrationChanged(MBeanRegistrationEvent event) {
206         Set JavaDoc<EmsBean> registered = event.getRegistered();
207         Set JavaDoc<EmsBean> deregistered = event.getDeregistered();
208
209         for (EmsBean bean : registered) {
210             addMBean(bean);
211         }
212
213         Node[] oldNodes = new Node[deregistered.size()];
214         int i = 0;
215         for (EmsBean bean : deregistered) {
216             MBeanNode currentNode = this.mbeans.remove(bean.getBeanName().getCanonicalName());
217             oldNodes[i++] = currentNode;
218         }
219         getChildren().remove(oldNodes);
220
221         if (deregistered.size() > 0) {
222           // TODO removeEmptyDomainNodes()
223
}
224     }
225
226
227     /**
228      * Recursively removes empty domain nodes.
229      *
230      * The algorithm works the following way - children nodes are recursively
231      * checked for being empty, if a child node is empty then the method would return true
232      * the parent node can then in turn check if it's empty and return true or false. If
233      * the parent is NOT empty it would return false and remove it's empty children.
234      *
235      * Although the method is using an ArrayList to store empty children for possible removal
236      * it's quite effiecient because it makes a single removal of a root empty node.
237      *
238      * @param domain
239      */

240     private boolean removeEmptyDomainNodes(Node domain){
241         Node [] children = domain.getChildren().getNodes();
242         boolean isEmpty = true;
243         ArrayList JavaDoc emptyChildren = new ArrayList JavaDoc(children.length);
244         for(int i = 0; i < children.length; i++){
245             if(children[i] instanceof DomainNode){
246                 if(removeEmptyDomainNodes(children[i]) == true){ //child is empty?
247
emptyChildren.add(children[i]);
248                 } else {
249                     isEmpty = false;
250                 }
251             } else {
252                 isEmpty = false;
253             }
254         }
255         if(!isEmpty && emptyChildren.size() > 0){
256             Node [] emptyNodes = new Node[emptyChildren.size()];
257             emptyChildren.toArray(emptyNodes);
258             domain.getChildren().remove(emptyNodes);
259         }
260     
261         return isEmpty;
262     }
263
264
265
266     protected void addMBean(EmsBean emsBean) {
267         synchronized(this) {
268             String JavaDoc domain = emsBean.getBeanName().getDomain();
269
270             DomainNode domainNode = (DomainNode) this.mbeanNode.getChildren().findChild(domain);
271             if (domainNode == null) {
272                 domainNode = new DomainNode(domain);
273                 this.mbeanNode.getChildren().add(new Node[] { domainNode });
274             }
275
276             MBeanNode mbeanNode = new MBeanNode(this, emsBean);
277             this.mbeans.put(emsBean.getBeanName().getCanonicalName(), mbeanNode);
278
279             if(domainNode.isGroupTypes()) {
280                 domainNode.insertIntoGroup(mbeanNode);
281             } else {
282                 domainNode.getChildren().add(new Node[] { mbeanNode });
283             }
284         }
285     }
286
287     protected Sheet createSheet() {
288
289         Sheet sheet = super.createSheet();
290
291         Sheet.Set set = Sheet.createPropertiesSet();
292
293         try {
294             Node node = new BeanNode(this.connectionSettings);
295             Node.PropertySet[] sets = node.getPropertySets();
296             for (int i = 0; i < sets.length; i++) {
297                 Node.PropertySet propertySet = sets[i];
298                 Node.Property[] props = propertySet.getProperties();
299                 for (int j = 0; j < props.length; j++) {
300                     Node.Property property = props[j];
301                     set.put(property);
302                     if (property.getPropertyEditor() != null)
303                         property.getPropertyEditor().addPropertyChangeListener(this);
304                 }
305             }
306         sheet.put(set);
307
308         //set.addPropertyChangeListener(this);
309
//sheet.addPropertyChangeListener(this);
310
} catch (IntrospectionException JavaDoc ie) {
311             ErrorManager.getDefault().notify(ie);
312         }
313
314         return sheet;
315     }
316 /*
317     public Node.PropertySet[] getPropertySets() {
318         if (settingsPropertySets == null) {
319             Node node = null;
320             try {
321                 node = new BeanNode(this.connectionSettings);
322                 node.addPropertyChangeListener(new PropertyChangeListener() {
323                     public void propertyChange(PropertyChangeEvent evt) {
324                         org.openide.windows.IOProvider.getDefault().getStdOut().println("Saving node");
325                         ConnectionSetDatabase.addNode(connectionSettings);
326                     }
327                 });
328                 node.addNodeListener(new NodeListener() {
329                     public void propertyChange(PropertyChangeEvent evt) {
330                         org.openide.windows.IOProvider.getDefault().getStdOut().println("Saving node");
331                         //ConnectionSetDatabase.addNode(connectionSettings);
332                     }
333                     public void childrenAdded(NodeMemberEvent ev) {}
334                     public void childrenRemoved(NodeMemberEvent ev) {}
335                     public void childrenReordered(NodeReorderEvent ev) {}
336                     public void nodeDestroyed(NodeEvent ev) {}
337                 });
338
339             } catch (IntrospectionException ie) {
340                 ErrorManager.getDefault().notify(ie);
341             }
342             this.settingsPropertySets = node.getPropertySets();
343         }
344         return this.settingsPropertySets;
345     }
346 */

347     public boolean isConnected() {
348         return this.connected;
349     }
350
351     public void setConnected(boolean connected) {
352         try {
353             if (this.connected) {
354                 disconnect();
355             } else {
356                 connect();
357             }
358         } catch (Exception JavaDoc e) {
359             ErrorManager.getDefault().notify(e);
360         }
361     }
362
363     protected Image icon;
364     public void updateIcon() {
365         if (connectionFailure) {
366             icon = NodeUtil.mergeIcons(
367                     "org/mc4j/console/connection/ConnectionNodeIcon.gif",
368                     "org/mc4j/console/connection/Error.gif");
369         } else if (connected) {
370             icon = NodeUtil.mergeIcons(
371                     "org/mc4j/console/connection/ConnectionNodeIcon.gif",
372                     "org/mc4j/console/connection/Connected.gif");
373         } else {
374             icon = NodeUtil.mergeIcons(
375                     "org/mc4j/console/connection/ConnectionNodeIcon.gif",
376                     "org/mc4j/console/connection/Unconnected.gif");
377         }
378         fireIconChange();
379     }
380
381     public Image getOpenedIcon(int i) {
382         return icon;
383     }
384     public Image getIcon(int i) {
385         return icon;
386     }
387
388     public void connect() throws Exception JavaDoc {
389
390         ConnectionFactory connectionFactory = new ConnectionFactory();
391
392         try {
393             emsConnection = connectionFactory.connect(connectionSettings);
394         } catch(EmsConnectException e) {
395             connectionFailure = true;
396             updateIcon();
397
398             e.printStackTrace(IOProvider.getDefault().getStdOut());
399             JOptionPane.showMessageDialog(null,"Unable to open connection to server: " + e.getCause().getMessage(),
400                     "Connection Error", JOptionPane.ERROR_MESSAGE);
401             return;
402         }
403         // Store the last 100 values for numeric attributes
404
connectionSettings.getControlProperties().setProperty(EmsAttribute.CONTROL_ATTRIBUTE_HISTORY_DEPTH,"100");
405
406         ConnectionInfoAction.addStats(emsConnection);
407
408         this.emsConnection.addRegistrationListener(this);
409
410
411
412         this.connected = true;
413         this.connectionFailure = false;
414         updateIcon();
415
416         // Add the special node for global dashboards
417
getChildren().add(new Node [] { new GlobalDashboardSetNode(this)});
418
419         // Load the JSR-77 tree
420
if (connectionSettings.getConnectionType().isMEJBCompliant()) {
421             getChildren().add(new Node [] { new MEJBNode(this) });
422         }
423
424         // Load the MBeans node
425
mbeanNode = new AbstractNode(new Children.SortedArray()) {
426             {
427                 setIconBase("org/mc4j/console/domain/DomainNodeIcon32");
428             }
429         };
430         mbeanNode.setDisplayName("MBeans");
431
432         getChildren().add(new Node[] { mbeanNode });
433
434         emsConnection.loadSynchronous(false);
435
436         // Turn on domain hierarchy grouping by default
437
Node[] nodes = this.mbeanNode.getChildren().getNodes();
438         for (int i = 0; i < nodes.length; i++) {
439             Node node = nodes[i];
440             if (node instanceof DomainNode) {
441                 ((DomainNode)node).setGroupTypes(true);
442             }
443         }
444
445         super.systemActions = null;
446
447         refreshTimer = new Timer JavaDoc();
448 // refreshTimer.schedule(
449
// new TimerTask() {
450
// public void run() {
451
// refresh();
452
// }
453
// },
454
// 20000,
455
// 10000);
456

457     }
458
459     public void refresh() {
460         String JavaDoc oldStatus = StatusDisplayer.getDefault().getStatusText();
461         try {
462             long start = System.currentTimeMillis();
463
464             StatusDisplayer.getDefault().setStatusText("Refreshing connection " +
465                     this.connectionSettings.getConnectionName());
466
467             // Offer to refresh nodes below
468
Node[] nodes = this.mbeanNode.getChildren().getNodes();
469             for (int i = 0; i < nodes.length; i++) {
470                 if (nodes[i] instanceof DomainNode) {
471                     ((DomainNode)nodes[i]).refresh();
472                 }
473             }
474
475             // Check for newly registered MBeans
476
// Add after the existing node update as there would be no need to
477
// refresh items right after they've been added.
478
loadConnectionNodeChildren();
479
480 // org.openide.windows.IOProvider.getDefault().getStdOut().println(
481
// "Refresh took: " + (System.currentTimeMillis() -start));
482

483             if (connectionFailure) {
484                 connectionFailure = true;
485                 updateIcon();
486             }
487         } catch (Throwable JavaDoc t) {
488             IOProvider.getDefault().getStdOut().println("Connection failure on [" +
489                 connectionSettings.getConnectionName() + "]" );
490
491             connectionFailure = true;
492             updateIcon();
493
494             //System.out.println(ExceptionUtility.printStackTracesToString(t));
495
} finally {
496             StatusDisplayer.getDefault().setStatusText(oldStatus);
497         }
498     }
499
500     public void disconnect() throws Exception JavaDoc {
501
502         if (!openDashboards.isEmpty()) {
503             for (Iterator JavaDoc iterator = openDashboards.iterator(); iterator.hasNext();) {
504                 final TopComponent topComponent = (TopComponent) iterator.next();
505                 SwingUtilities.invokeLater( new Runnable JavaDoc() {
506                     public void run() {
507                         if (topComponent.isOpened()) {
508                             topComponent.close();
509                         }
510                     }
511                 });
512             }
513         }
514
515         if (this.refreshTimer != null)
516             this.refreshTimer.cancel();
517
518
519
520         this.getChildren().remove(this.getChildren().getNodes());
521         this.mbeans.clear();
522
523         this.connected = false;
524         this.connectionFailure = false;
525
526         updateIcon();
527         super.systemActions = null;
528         super.getContextMenu();
529         this.openDashboards.clear();
530     }
531
532     public void deleteConnection() {
533         if (this.isConnected()) {
534             try {
535                 disconnect();
536             } catch (Exception JavaDoc e) {
537                 // ignore
538
}
539         }
540
541         if (this.getParentNode() == null)
542             return;
543
544         this.getParentNode().getChildren().remove(new Node[] { this });
545         ConnectionSetDatabase.removeNode(this.connectionSettings);
546     }
547
548     /**
549      * Provide an iterable list of the MBeanNodes that are available
550      * on this connection.
551      */

552     public List JavaDoc getMBeanList() {
553         // TODO - need to pick a sorted or ordered tree and use keys from that
554
return Collections.unmodifiableList(new ArrayList JavaDoc(this.mbeans.values()));
555     }
556
557     public void refreshMBeanList() {
558         try {
559             loadConnectionNodeChildren();
560         } catch (Exception JavaDoc e) {
561
562         }
563     }
564
565     // Handle renaming:
566
public boolean canRename() {
567         return true;
568     }
569     public void setName(String JavaDoc name) {
570         // Update visible name, fire property changes:
571
super.setName(name);
572         // perform additional actions, i.e. rename underlying object
573
if (this.connectionSettings != null) {
574             this.connectionSettings.setConnectionName(name);
575         }
576         //ConnectionSetDatabase.addNode(connectionSettings);
577
}
578
579     // Handle deleting:
580
public boolean canDestroy() {
581         return true;
582     }
583     public void destroy() throws IOException JavaDoc {
584         // Actually remove the node itself and fire property changes:
585
super.destroy();
586         // perform additional actions, i.e. delete underlying object
587
// (and don't forget about objects represented by your children!)
588
this.deleteConnection();
589     }
590
591
592     public void browseToMBean(final String JavaDoc objectName) {
593         final MBeanNode node = getMBeanNode(objectName);
594         if (node != null) {
595             ExplorerUtil.browseTo(node);
596         }
597     }
598
599     public MBeanNode getMBeanNode(String JavaDoc objectName) {
600         return this.mbeans.get(objectName);
601     }
602
603
604     // Permit user to customize whole node at once (instead of per-property):
605
/*
606     public boolean hasCustomizer() {
607         return true;
608     }
609     public Component getCustomizer() {
610         return new MyCustomizingPanel(this);
611     }
612      */

613
614
615     public String JavaDoc getDefaultServerUrl() {
616         return null;
617     }
618
619     public String JavaDoc getDefaultJndiName() {
620         return null;
621     }
622
623     public String JavaDoc getDefaultInitialContext() {
624         return null;
625     }
626
627
628
629     public void registerDashboard(TopComponent dashboard) {
630         this.openDashboards.add(dashboard);
631     }
632
633     public boolean isOpenedDashboards() {
634         return !this.openDashboards.isEmpty();
635     }
636 }
637
Popular Tags