KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > excalibur > instrument > client > InstrumentManagerConnection


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14  * implied.
15  *
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */

19
20 package org.apache.excalibur.instrument.client;
21
22 import java.awt.BorderLayout JavaDoc;
23 import java.awt.Color JavaDoc;
24 import java.awt.FlowLayout JavaDoc;
25 import java.awt.event.ActionEvent JavaDoc;
26 import java.beans.PropertyVetoException JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31
32 import javax.swing.AbstractAction JavaDoc;
33 import javax.swing.Action JavaDoc;
34 import javax.swing.Box JavaDoc;
35 import javax.swing.JButton JavaDoc;
36 import javax.swing.JComponent JavaDoc;
37 import javax.swing.JLabel JavaDoc;
38 import javax.swing.JPanel JavaDoc;
39 import javax.swing.SwingUtilities JavaDoc;
40 import javax.swing.tree.DefaultMutableTreeNode JavaDoc;
41
42 import org.apache.avalon.framework.configuration.Configuration;
43 import org.apache.avalon.framework.configuration.ConfigurationException;
44 import org.apache.avalon.framework.configuration.DefaultConfiguration;
45 import org.apache.avalon.framework.logger.LogEnabled;
46 import org.apache.avalon.framework.logger.Logger;
47
48 /**
49  * A Connection to the remote InstrumentManager.
50  *
51  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
52  * @version CVS $Revision: 1.4 $ $Date: 2004/02/28 11:47:23 $
53  * @since 4.1
54  */

55 public abstract class InstrumentManagerConnection
56     extends JComponent JavaDoc
57     implements LogEnabled, Runnable JavaDoc
58 {
59     private Logger m_logger;
60     private InstrumentManagerTreeModel m_treeModel;
61     private InstrumentManagerTree m_tree;
62     
63     private InstrumentClientFrame m_frame;
64     
65     private boolean m_deleted;
66     private Thread JavaDoc m_runner;
67     
68     private JLabel JavaDoc m_descriptionLabel;
69
70     private final List JavaDoc m_listeners = new ArrayList JavaDoc();
71     private InstrumentManagerConnectionListener[] m_listenerArray = null;
72
73     private long m_lastLeaseRenewalTime;
74     private HashMap JavaDoc m_maintainedSampleLeaseMap = new HashMap JavaDoc();
75     private MaintainedSampleLease[] m_maintainedSampleLeaseArray = null;
76
77     /** Maintain a list of all sample frames which are viewing data in this connection. */
78     private Map JavaDoc m_sampleFrames = new HashMap JavaDoc();
79     private InstrumentSampleFrame[] m_sampleFrameArray = null;
80     
81     /*---------------------------------------------------------------
82      * Constructors
83      *-------------------------------------------------------------*/

84     /**
85      * Creates a new InstrumentManagerConnection.
86      */

87     public InstrumentManagerConnection()
88     {
89     }
90     
91
92     /*---------------------------------------------------------------
93      * LogEnabled Methods
94      *-------------------------------------------------------------*/

95     public void enableLogging( Logger logger )
96     {
97         m_logger = logger.getChildLogger( "conn_" + getKey() );
98     }
99
100     protected Logger getLogger()
101     {
102         return m_logger;
103     }
104
105     /*---------------------------------------------------------------
106      * Runnable Methods
107      *-------------------------------------------------------------*/

108     public void run()
109     {
110         getLogger().debug( "Started " + Thread.currentThread().getName() );
111         try
112         {
113             while( m_runner != null )
114             {
115                 try
116                 {
117                     try
118                     {
119                         Thread.sleep( 1000 );
120                     }
121                     catch( InterruptedException JavaDoc e )
122                     {
123                         if ( m_runner == null )
124                         {
125                             return;
126                         }
127                     }
128                     
129                     update();
130                     
131                     m_frame.updateConnectionTab( this );
132                     
133                     updateSampleFrames();
134                 }
135                 catch( Throwable JavaDoc t )
136                 {
137                     // Should not get here, but we want to make sure that this never happens.
138
getLogger().error(
139                         "Unexpected error caught in " + Thread.currentThread().getName(), t );
140                     
141                     // Avoid thrashing.
142
try
143                     {
144                         Thread.sleep( 5000 );
145                     }
146                     catch ( InterruptedException JavaDoc e )
147                     {
148                         if ( m_runner == null )
149                         {
150                             return;
151                         }
152                     }
153                 }
154             }
155         }
156         finally
157         {
158             getLogger().debug( "Stopped " + Thread.currentThread().getName() );
159         }
160     }
161     
162     /*---------------------------------------------------------------
163      * Methods
164      *-------------------------------------------------------------*/

165     /**
166      * Stores a reference to the client frame.
167      *
168      * @param frame The main client frame.
169      */

170     final void setFrame( InstrumentClientFrame frame )
171     {
172         m_frame = frame;
173     }
174     
175     /**
176      * Returns a reference to the client frame.
177      *
178      * @return A reference to the client frame.
179      */

180     final InstrumentClientFrame getFrame()
181     {
182         return m_frame;
183     }
184     
185     /**
186      * Called to initialize the connection object.
187      */

188     public void init()
189     {
190         m_treeModel = new InstrumentManagerTreeModel( this );
191         m_treeModel.enableLogging( m_logger.getChildLogger( "treeModel" ) );
192         addInstrumentManagerConnectionListener( m_treeModel );
193
194         setLayout( new BorderLayout JavaDoc() );
195
196         // Top Pane
197
Box JavaDoc topPane = Box.createVerticalBox();
198
199         // Top Labels
200
// Row 1
201
Box JavaDoc labels = Box.createHorizontalBox();
202         labels.add( Box.createHorizontalStrut( 4 ) );
203         m_descriptionLabel = new JLabel JavaDoc( getInstrumentManager().getDescription() );
204         labels.add( m_descriptionLabel );
205         labels.add( Box.createHorizontalGlue() );
206         topPane.add( labels );
207         
208         // Row 2
209
labels = Box.createHorizontalBox();
210         labels.add( Box.createHorizontalStrut( 4 ) );
211         labels.add( new JLabel JavaDoc( "URL: " + getKey().toString() ) );
212         labels.add( Box.createHorizontalGlue() );
213         topPane.add( labels );
214
215         topPane.add( Box.createVerticalStrut( 4 ) );
216         
217         // Top Buttons
218
Action JavaDoc gcAction = new AbstractAction JavaDoc( "Invoke GC" )
219         {
220             public void actionPerformed( ActionEvent JavaDoc event )
221             {
222                 SwingUtilities.invokeLater( new Runnable JavaDoc()
223                     {
224                         public void run()
225                         {
226                             InstrumentManagerConnection.this.invokeGC();
227                         }
228                     });
229             }
230         };
231         JButton JavaDoc gcButton = new JButton JavaDoc( gcAction );
232
233         Action JavaDoc refreshAction = new AbstractAction JavaDoc( "Refresh" )
234         {
235             public void actionPerformed( ActionEvent JavaDoc event )
236             {
237                 SwingUtilities.invokeLater( new Runnable JavaDoc()
238                     {
239                         public void run()
240                         {
241                             InstrumentManagerConnection.this.getTreeModel().refreshModel();
242                         }
243                     });
244             }
245         };
246         JButton JavaDoc refreshButton = new JButton JavaDoc( refreshAction );
247
248         Action JavaDoc deleteAction = new AbstractAction JavaDoc( "Delete" )
249         {
250             public void actionPerformed( ActionEvent JavaDoc event )
251             {
252                 SwingUtilities.invokeLater( new Runnable JavaDoc()
253                     {
254                         public void run()
255                         {
256                             InstrumentManagerConnection.this.delete();
257                         }
258                     });
259             }
260         };
261         JButton JavaDoc deleteButton = new JButton JavaDoc( deleteAction );
262
263         Box JavaDoc buttons = Box.createHorizontalBox();
264         buttons.add( Box.createHorizontalStrut( 4 ) );
265         buttons.add ( gcButton );
266         buttons.add( Box.createHorizontalStrut( 4 ) );
267         buttons.add ( refreshButton );
268         buttons.add( Box.createHorizontalStrut( 4 ) );
269         buttons.add ( deleteButton );
270         buttons.add( Box.createHorizontalGlue() );
271         topPane.add( buttons );
272         
273         topPane.add( Box.createVerticalStrut( 4 ) );
274
275         add( topPane, BorderLayout.NORTH );
276
277         // Tree Pane
278
m_tree = new InstrumentManagerTree( this );
279         add( m_tree, BorderLayout.CENTER );
280         
281         m_runner = new Thread JavaDoc( this, "InstrumentManagerConnection[" + getKey() + "]" );
282         m_runner.start();
283     }
284     
285     /**
286      * Returns true once the connection has been deleted.
287      *
288      * @return True if deleted.
289      */

290     public boolean isDeleted()
291     {
292         return m_deleted;
293     }
294     
295     /**
296      * Returns the title to display in the tab for the connection.
297      *
298      * @return The tab title.
299      */

300     public String JavaDoc getTabTitle()
301     {
302         return getInstrumentManager().getName();
303     }
304     
305     /**
306      * Returns the tooltip to display in the tab for the connection.
307      *
308      * @return The tab tooltip.
309      */

310     public String JavaDoc getTabTooltip()
311     {
312         String JavaDoc key = getKey().toString();
313         String JavaDoc tab = getInstrumentManager().getDescription();
314         
315         if ( key.equals( tab ) )
316         {
317             return tab;
318         }
319         else
320         {
321             return tab + " [" + key + "]";
322         }
323     }
324     
325     /**
326      * Returns the title for the connection.
327      *
328      * @return The title.
329      */

330     public String JavaDoc getTitle()
331     {
332         return getInstrumentManager().getDescription();
333     }
334     
335     /**
336      * Returns the key used to identify this object.
337      *
338      * @return The key used to identify this object.
339      */

340     public abstract Object JavaDoc getKey();
341     
342     /**
343      * Returns true if connected.
344      *
345      * @return True if connected.
346      */

347     public abstract boolean isConnected();
348     
349     /**
350      * Returns the Instrument Manager.
351      *
352      * @return The Instrument Manager.
353      */

354     public abstract InstrumentManagerData getInstrumentManager();
355     
356     /**
357      * Causes the InstrumentManagerConnection to update itself with the latest
358      * data from the server. Called by the updateConnection method.
359      */

360     public void update()
361     {
362         // If we are currently connected then we are only looking for changes so do the
363
// regular update. If not connected then we will want all of the data.
364
if ( isConnected() )
365         {
366             getInstrumentManager().update();
367         }
368         else
369         {
370             getInstrumentManager().updateAll();
371         }
372         
373         String JavaDoc description = getInstrumentManager().getDescription();
374         if ( !m_descriptionLabel.getText().equals( description ) )
375         {
376             m_descriptionLabel.setText( description );
377         }
378         
379         getTreeModel().refreshModel();
380         
381         // Handle the leased samples.
382
if ( isConnected() )
383         {
384             handleLeasedSamples();
385         }
386     }
387
388     /**
389      * Invokes GC on the JVM running the InstrumentManager.
390      */

391     protected abstract void invokeGC();
392
393     /**
394      * Saves the current state into a Configuration.
395      *
396      * @return The state as a Configuration.
397      */

398     public Configuration saveState()
399     {
400         synchronized( this )
401         {
402             DefaultConfiguration state = new DefaultConfiguration( "connection", "-" );
403             
404             // Save any maintained samples
405
MaintainedSampleLease[] samples = getMaintainedSampleLeaseArray();
406             for ( int i = 0; i < samples.length; i++ )
407             {
408                 state.addChild( samples[ i ].saveState() );
409             }
410             
411             return state;
412         }
413     }
414
415     /**
416      * Loads the state from a Configuration object.
417      *
418      * @param state Configuration object to load state from.
419      *
420      * @throws ConfigurationException If there were any problems loading the
421      * state.
422      */

423     public void loadState( Configuration state )
424         throws ConfigurationException
425     {
426         synchronized( this )
427         {
428             // Load any maintained samples
429
Configuration[] sampleConfs = state.getChildren( "maintained-sample" );
430             for( int i = 0; i < sampleConfs.length; i++ )
431             {
432                 Configuration sampleConf = sampleConfs[ i ];
433                 String JavaDoc instrumentName = sampleConf.getAttribute( "instrument-name" );
434                 int sampleType = InstrumentSampleUtils.resolveInstrumentSampleType(
435                     sampleConf.getAttribute( "type" ) );
436                 long sampleInterval = sampleConf.getAttributeAsLong( "interval" );
437                 int sampleSize = sampleConf.getAttributeAsInteger( "size" );
438                 long sampleLeaseDuration = sampleConf.getAttributeAsLong( "lease-duration" );
439                 String JavaDoc sampleDescription = sampleConf.getAttribute( "description" );
440
441                 startMaintainingSample( instrumentName, sampleType, sampleInterval, sampleSize,
442                     sampleLeaseDuration, sampleDescription );
443             }
444         }
445     }
446     
447     /**
448      * Updates all registered SampleFrames with the latest data from the
449      * server. The status of all Sample Frames is also handled by this
450      * method, so it must handle disconnected connections and missing or
451      * expired samples correctly.
452      */

453     public void updateSampleFrames()
454     {
455         InstrumentSampleFrame[] frames = getSampleFrameArray();
456         for ( int i = 0; i < frames.length; i++ )
457         {
458             InstrumentSampleFrame frame = frames[i];
459             frame.update();
460         }
461     }
462     
463     /**
464      * Returns the TreeModel which contains the entire Instrument tree for
465      * this connection.
466      *
467      * @return The TreeModel.
468      */

469     InstrumentManagerTreeModel getTreeModel()
470     {
471         return m_treeModel;
472     }
473
474     DefaultMutableTreeNode JavaDoc getInstrumentSampleTreeNode( String JavaDoc sampleName )
475     {
476         return m_treeModel.getInstrumentSampleTreeNode( sampleName );
477     }
478
479     /**
480      * Adds a InstrumentManagerConnectionListener to the list of listeners
481      * which receive state updates of the connection.
482      *
483      * @param listener InstrumentManagerConnectionListener to start receiving
484      * state updates.
485      */

486     void addInstrumentManagerConnectionListener(
487         InstrumentManagerConnectionListener listener )
488     {
489         synchronized (this)
490         {
491             m_listeners.add( listener );
492             m_listenerArray = null;
493         }
494     }
495
496     /**
497      * Removes a InstrumentManagerConnectionListener from the list of listeners
498      * which receive state updates of the connection.
499      *
500      * @param listener InstrumentManagerConnectionListener to stop receiving
501      * state updates.
502      */

503     void removeInstrumentManagerConnectionListener(
504         InstrumentManagerConnectionListener listener )
505     {
506         synchronized (this)
507         {
508             m_listeners.remove( listener );
509             m_listenerArray = null;
510         }
511     }
512
513     /**
514      * Get a threadsafe array of the current listeners avoiding synchronization
515      * when possible. The contents of the returned array will never change.
516      *
517      * @return An array of the currently registered listeners
518      */

519     protected InstrumentManagerConnectionListener[] getListenerArray()
520     {
521         InstrumentManagerConnectionListener[] listenerArray = m_listenerArray;
522         if ( listenerArray == null )
523         {
524             synchronized(this)
525             {
526                 m_listenerArray = new InstrumentManagerConnectionListener[ m_listeners.size() ];
527                 m_listeners.toArray( m_listenerArray );
528                 listenerArray = m_listenerArray;
529             }
530         }
531         return listenerArray;
532     }
533
534     /**
535      * Returns a snapshot of the specified sample. If a snapshot can not
536      * be returned for any reason, then return null.
537      *
538      * @param Returns a snapshot of the specified sample.
539      */

540     InstrumentSampleSnapshotData getSampleSnapshot( String JavaDoc sampleName )
541     {
542         DefaultMutableTreeNode JavaDoc sampleNode = getInstrumentSampleTreeNode( sampleName );
543         if ( sampleNode == null )
544         {
545             return null;
546         }
547
548         InstrumentSampleNodeData sampleNodeData =
549             (InstrumentSampleNodeData)sampleNode.getUserObject();
550         InstrumentSampleData sampleData = sampleNodeData.getData();
551         if ( sampleData == null )
552         {
553             return null;
554         }
555
556         // Request the actual snapshot.
557
return sampleData.getSnapshot();
558     }
559
560     /**
561      * Returns a sample frame given a sample name.
562      * Caller must synchronize on this connection before calling.
563      *
564      * @param sampleName Name of the sample requested.
565      *
566      * @return A sample frame given a sample name.
567      */

568     private InstrumentSampleFrame getSampleFrame( String JavaDoc sampleName )
569     {
570         getLogger().debug("InstrumentManagerConnection.getSampleFrame(" + sampleName + ")");
571         // Assumes "this" is synchronized.
572
return (InstrumentSampleFrame)m_sampleFrames.get( sampleName );
573     }
574
575     /**
576      * Adds a single sample frame.
577      * Caller must synchronize on this connection before calling.
578      */

579     private void addSampleFrame( String JavaDoc sampleName, InstrumentSampleFrame sampleFrame )
580     {
581         getLogger().debug("InstrumentManagerConnection.addSampleFrame(" + sampleName + ", frame)");
582         // Assumes "this" is synchronized.
583
m_sampleFrames.put( sampleName, sampleFrame );
584         m_sampleFrameArray = null;
585     }
586
587     /**
588      * Removes a single sample frame.
589      * Caller must synchronize on this connection before calling.
590      */

591     private void removeSampleFrame( String JavaDoc sampleName )
592     {
593         getLogger().debug("InstrumentManagerConnection.removeSampleFrame(" + sampleName + ")");
594         // Assumes "this" is synchronized.
595
m_sampleFrames.remove( sampleName );
596         m_sampleFrameArray = null;
597     }
598
599     /**
600      * Returns a thread save array representation of the InstrumentSampleFrames.
601      *
602      * @return A thread save array representation of the InstrumentSampleFrames.
603      */

604     protected InstrumentSampleFrame[] getSampleFrameArray()
605     {
606         InstrumentSampleFrame[] array = m_sampleFrameArray;
607         if ( array == null )
608         {
609             synchronized(this)
610             {
611                 m_sampleFrameArray = new InstrumentSampleFrame[m_sampleFrames.size()];
612                 m_sampleFrames.values().toArray( m_sampleFrameArray );
613                 array = m_sampleFrameArray;
614             }
615         }
616         return array;
617     }
618
619     /**
620      * Loads an InstrumentSampleFrame from a saved state.
621      *
622      * @param sampleFrameState Saved state of the frame to load.
623      *
624      * @throws ConfigurationException If there are any problems with the state.
625      */

626     void loadSampleFrame( Configuration sampleFrameState )
627         throws ConfigurationException
628     {
629         // Get the sample name
630
String JavaDoc sampleName = sampleFrameState.getAttribute( "sample" );
631         getLogger().debug( "Loading sample frame: " + sampleName );
632
633         // See if a frame already exists.
634
InstrumentSampleFrame sampleFrame;
635         synchronized(this)
636         {
637             sampleFrame = getSampleFrame( sampleName );
638             if ( sampleFrame != null )
639             {
640                 // A frame already existed. It needs to be closed as it will be
641
// replaced by the new one.
642
sampleFrame.hideFrame();
643                 sampleFrame = null;
644             }
645
646             // Now create the frame
647
sampleFrame = new InstrumentSampleFrame( sampleFrameState, this, m_frame );
648             sampleFrame.enableLogging( getLogger() );
649             addSampleFrame( sampleName, sampleFrame );
650             sampleFrame.addToDesktop( m_frame.getDesktopPane() );
651         }
652         sampleFrame.show(); // Outside of synchronization to avoid deadlocks.
653
}
654     
655     /**
656      * Displays a frame for the given sample.
657      *
658      * @param sampleName Name of the sample to display.
659      */

660     void viewSample( String JavaDoc sampleName )
661     {
662         InstrumentSampleFrame sampleFrame;
663         synchronized( this )
664         {
665             //String sampleName = sampleNodeData.getName();
666
sampleFrame = getSampleFrame( sampleName );
667             if ( sampleFrame == null )
668             {
669                 sampleFrame = new InstrumentSampleFrame( this, sampleName, m_frame );
670                 sampleFrame.enableLogging( getLogger() );
671                 addSampleFrame( sampleName, sampleFrame );
672                 sampleFrame.addToDesktop( m_frame.getDesktopPane() );
673             }
674         }
675
676         sampleFrame.show();
677         // Need to restore the frame if it is an icon.
678
if ( sampleFrame.isIcon() )
679         {
680             // Restore the sample frame.
681
try
682             {
683                 sampleFrame.setIcon( false );
684             }
685             catch ( PropertyVetoException JavaDoc e )
686             {
687                 // Shouldn't happen.
688
getLogger().warn( "Unexpected error", e );
689             }
690         }
691
692         // Set the focus of the frame so that it is selected and on top.
693
try
694         {
695             sampleFrame.setSelected( true );
696         }
697         catch ( PropertyVetoException JavaDoc e )
698         {
699             // Shouldn't happen.
700
getLogger().warn( "Unexpected error", e );
701         }
702         
703         // Always update the sample immediately to make the app look responsive.
704
sampleFrame.update();
705     }
706
707
708     /**
709      * Called when the connection should be closed and then deleted along with
710      * any frames and resources that are associated with it.
711      */

712     void delete()
713     {
714         getLogger().debug( "delete()" );
715
716         m_deleted = true;
717         
718         Thread JavaDoc runner = m_runner;
719         if ( runner != null )
720         {
721             m_runner = null;
722             runner.interrupt();
723         }
724         
725         // Hide any of our own sample frames.
726
InstrumentSampleFrame[] frames = getSampleFrameArray();
727         for ( int i = 0; i < frames.length; i++ )
728         {
729             frames[i].hideFrame();
730         }
731
732         // Notify the listeners.
733
InstrumentManagerConnectionListener[] listenerArray = getListenerArray();
734         for ( int i = 0; i < listenerArray.length; i++ )
735         {
736             listenerArray[i].deleted( this );
737         }
738     }
739     
740     /**
741      * Called when a Sample Frame is closed.
742      */

743     void hideSampleFrame( InstrumentSampleFrame sampleFrame )
744     {
745         String JavaDoc sampleName = sampleFrame.getInstrumentSampleName();
746         synchronized(this)
747         {
748             removeSampleFrame( sampleName );
749         }
750     }
751
752     /**
753      * Start maintaining the lease for an instrument sample which already
754      * exists.
755      *
756      * @param instrumentName The full name of the instrument whose sample is
757      * to be created or updated.
758      * @param type The type of sample to be created.
759      * @param interval Sample interval of the new sample.
760      * @param size Number of samples in the new sample.
761      * @param leaseDuration Length of the lease to maintain in milliseconds.
762      * @param description Description to assign to the new sample.
763      */

764     void startMaintainingSample( String JavaDoc instrumentName,
765                                  int type,
766                                  long interval,
767                                  int size,
768                                  long leaseDuration,
769                                  String JavaDoc description )
770     {
771         if ( getLogger().isDebugEnabled() )
772         {
773             getLogger().debug( "startMaintainingSample(" + instrumentName + ", " + type + ", " +
774                 interval + ", " + size + ", " + leaseDuration + ", " + description + ")" );
775         }
776
777         synchronized(this)
778         {
779             MaintainedSampleLease sampleLease = new MaintainedSampleLease(
780                 instrumentName, type, interval, size, leaseDuration, description );
781             String JavaDoc sampleName = sampleLease.getSampleName();
782             m_maintainedSampleLeaseMap.put( sampleName, sampleLease );
783             m_maintainedSampleLeaseArray = null;
784
785             // Reset the last lease renewal time so that the leases along with this
786
// new one will be renewed right away.
787
m_lastLeaseRenewalTime = 0;
788
789             // Update the appropriate node in the tree model.
790
DefaultMutableTreeNode JavaDoc sampleTreeNode =
791                 m_treeModel.getInstrumentSampleTreeNode( sampleName );
792
793             if ( sampleTreeNode != null )
794             {
795                 InstrumentSampleNodeData sampleNodeData =
796                     (InstrumentSampleNodeData)sampleTreeNode.getUserObject();
797
798                 sampleNodeData.setLeaseDuration( leaseDuration );
799                 sampleNodeData.setDescription( description );
800                 m_treeModel.updateInstrumentSample( sampleNodeData.getData(), sampleTreeNode );
801             }
802         }
803     }
804
805     /**
806      * Stop maintaining the lease for an instrument sample which already
807      * exists.
808      */

809     void stopMaintainingSample( String JavaDoc sampleName )
810     {
811         if ( getLogger().isDebugEnabled() )
812         {
813             getLogger().debug( "stopMaintainingSample(" + sampleName + ")" );
814         }
815
816         synchronized(this)
817         {
818             m_maintainedSampleLeaseMap.remove( sampleName );
819             m_maintainedSampleLeaseArray = null;
820
821             // Update the appropriate node in the tree model.
822
DefaultMutableTreeNode JavaDoc sampleTreeNode =
823                 m_treeModel.getInstrumentSampleTreeNode( sampleName );
824             if ( sampleTreeNode != null )
825             {
826                 InstrumentSampleNodeData sampleNodeData =
827                     (InstrumentSampleNodeData)sampleTreeNode.getUserObject();
828
829                 sampleNodeData.setLeaseDuration( 0 );
830                 m_treeModel.updateInstrumentSample( sampleNodeData.getData(), sampleTreeNode );
831             }
832         }
833     }
834
835     /**
836      * Returns a MaintainedSampleLease given a name if the sample is being
837      * maintained. Otherwise returns null.
838      *
839      * @param sampleName Name of the sample being requested.
840      *
841      * @return A MaintainedSampleLease given a name.
842      */

843     MaintainedSampleLease getMaintainedSampleLease( String JavaDoc sampleName )
844     {
845         synchronized(this)
846         {
847             return (MaintainedSampleLease)m_maintainedSampleLeaseMap.get( sampleName );
848         }
849     }
850
851     /**
852      * Returns a thread save array representation of the MaintainedSampleLeases.
853      *
854      * @return A thread save array representation of the MaintainedSampleLeases.
855      */

856     private MaintainedSampleLease[] getMaintainedSampleLeaseArray()
857     {
858         MaintainedSampleLease[] array = m_maintainedSampleLeaseArray;
859         if ( array == null )
860         {
861             synchronized(this)
862             {
863                 m_maintainedSampleLeaseArray =
864                     new MaintainedSampleLease[ m_maintainedSampleLeaseMap.size() ];
865                 m_maintainedSampleLeaseMap.values().toArray( m_maintainedSampleLeaseArray );
866                 array = m_maintainedSampleLeaseArray;
867             }
868         }
869         return array;
870     }
871
872     /**
873      * Called once each second by the main worker thread of the client. This
874      * method is responsible for maintaining and expiring leased samples.
875      */

876     void handleLeasedSamples()
877     {
878         // If we are not connected, then there is nothing to be done here.
879

880         // Only renew leases once every 30 seconds.
881
long now = System.currentTimeMillis();
882         if ( now - m_lastLeaseRenewalTime > 30000 )
883         {
884             getLogger().debug( "Renew Leases:" );
885             
886             MaintainedSampleLease[] leases = getMaintainedSampleLeaseArray();
887             String JavaDoc[] instrumentNames = new String JavaDoc[leases.length];
888             String JavaDoc[] descriptions = new String JavaDoc[leases.length];
889             long[] intervals = new long[leases.length];
890             int[] sampleCounts = new int[leases.length];
891             long[] leaseTimes = new long[leases.length];
892             int[] sampleTypes = new int[leases.length];
893             for ( int i = 0; i < leases.length; i++ )
894             {
895                 MaintainedSampleLease lease = leases[i];
896                 getLogger().debug( " lease: " + lease.getSampleName() );
897                 
898                 instrumentNames[i] = lease.getInstrumentName();
899                 descriptions[i] = lease.getDescription();
900                 intervals[i] = lease.getInterval();
901                 sampleCounts[i] = lease.getSize();
902                 leaseTimes[i] = lease.getLeaseDuration();
903                 sampleTypes[i] = lease.getType();
904             }
905             
906             // Regardless of whether the samples already exists or not, they
907
// are created or extended the same way. This way the client
908
// will recreate a sample if it has expored.
909
getInstrumentManager().createInstrumentSamples(
910                 instrumentNames, descriptions, intervals, sampleCounts, leaseTimes, sampleTypes );
911
912             // Also, take this oportunity to update all of the leased samples in
913
// the model.
914
m_treeModel.renewAllSampleLeases();
915
916             m_lastLeaseRenewalTime = now;
917         }
918
919         // Now have the TreeModel purge any expired samples from the tree.
920
m_treeModel.purgeExpiredSamples();
921     }
922     
923     
924     /**
925      * Create a new Sample assigned to the specified instrument data.
926      *
927      * @param instrumentData Instrument to add a sample to.
928      */

929     void showCreateSampleDialog( final InstrumentData instrumentData )
930     {
931         SwingUtilities.invokeLater( new Runnable JavaDoc()
932         {
933             public void run()
934             {
935                 CreateSampleDialog dialog = new CreateSampleDialog(
936                     m_frame, instrumentData.getName(), instrumentData.getDescription(),
937                     instrumentData.getType() );
938                 dialog.show();
939
940                 if ( dialog.getAction() == CreateSampleDialog.BUTTON_OK )
941                 {
942                     String JavaDoc description = dialog.getSampleDescription();
943                     long interval = dialog.getInterval();
944                     int sampleCount = dialog.getSampleCount();
945                     long leaseTime = dialog.getLeaseTime();
946                     int type = dialog.getSampleType();
947                     boolean maintain = dialog.getMaintainLease();
948                     
949                     if ( getLogger().isDebugEnabled() )
950                     {
951                         getLogger().debug( "New Sample: desc=" + description
952                             + ", interval=" + interval
953                             + ", size=" + sampleCount
954                             + ", lease=" + leaseTime
955                             + ", type=" + type
956                             + ", maintain=" + maintain );
957                     }
958
959                     // If the sample already exists on the server, then the existing one
960
// will be returned.
961
boolean success = instrumentData.createInstrumentSample(
962                         description,
963                         interval,
964                         sampleCount,
965                         leaseTime,
966                         type );
967                     
968                     // Figure out what the name of the new sample will be
969
String JavaDoc sampleName = InstrumentSampleUtils.generateFullInstrumentSampleName(
970                         instrumentData.getName(), type, interval, sampleCount );
971                     
972                     if ( success )
973                     {
974                         // If configured to do so, start maintaining the sample
975
if ( maintain )
976                         {
977                             startMaintainingSample( instrumentData.getName(), type, interval,
978                                 sampleCount, leaseTime, description );
979                         }
980                         
981                         // Display a sample frame.
982
viewSample( sampleName );
983                     }
984                     else
985                     {
986                         getLogger().warn( "Attempt to register the sample with the server failed: "
987                             + sampleName );
988                     }
989                 }
990             }
991         } );
992     }
993     
994     /**
995      * Returns a string representation of the connection.
996      */

997     public String JavaDoc toString()
998     {
999         return getClass().getName() + " : " + getKey();
1000    }
1001}
Popular Tags