KickJava   Java API By Example, From Geeks To Geeks.

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


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.Color JavaDoc;
23 import java.awt.Dimension JavaDoc;
24
25 import javax.swing.ImageIcon JavaDoc;
26 import javax.swing.JLabel JavaDoc;
27 import javax.swing.SwingConstants JavaDoc;
28 import javax.swing.event.InternalFrameEvent JavaDoc;
29 import javax.swing.tree.DefaultMutableTreeNode JavaDoc;
30
31 import org.apache.avalon.framework.configuration.Configuration;
32 import org.apache.avalon.framework.configuration.ConfigurationException;
33 import org.apache.avalon.framework.configuration.DefaultConfiguration;
34
35 /**
36  *
37  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
38  * @version CVS $Revision: 1.4 $ $Date: 2004/02/28 11:47:23 $
39  * @since 4.1
40  */

41 public class InstrumentSampleFrame
42     extends AbstractInternalFrame
43 {
44     public static final String JavaDoc FRAME_TYPE = "sample-frame";
45
46     private static final int STATE_NONE = 0;
47     private static final int STATE_DISCONNECTED = 1;
48     private static final int STATE_MISSING = 2;
49     private static final int STATE_SNAPSHOT = 3;
50     private static final int STATE_EXPIRED = 4;
51     
52     private static final ImageIcon JavaDoc m_iconDisconnected;
53     private static final ImageIcon JavaDoc m_iconMissing;
54     private static final ImageIcon JavaDoc m_iconExpired;
55     
56     private int m_state = STATE_NONE;
57     private InstrumentManagerConnection m_connection;
58     private String JavaDoc m_instrumentSampleName;
59     private String JavaDoc m_fullName;
60     
61     /** The last time that a snapshot was received. This is the time in the
62      * snapshot and is always in Server time. Not the time on this system. */

63     private long m_lastSnapshotTime;
64     
65     /** A buffered set of sample values. May be null. */
66     private int[] m_samples;
67     
68     /** The LineChart currently visible in the Frame. May be null. */
69     private LineChart m_lineChart;
70
71     /*---------------------------------------------------------------
72      * Class Initializer
73      *-------------------------------------------------------------*/

74     static
75     {
76         // Load the icons.
77
ClassLoader JavaDoc cl = InstrumentManagerTreeCellRenderer.class.getClassLoader();
78         m_iconDisconnected =
79             new ImageIcon JavaDoc( cl.getResource( NodeData.MEDIA_PATH + "sample_disconnected.gif") );
80         m_iconMissing =
81             new ImageIcon JavaDoc( cl.getResource( NodeData.MEDIA_PATH + "sample_missing.gif") );
82         m_iconExpired =
83             new ImageIcon JavaDoc( cl.getResource( NodeData.MEDIA_PATH + "sample_expired.gif") );
84     }
85     
86     /*---------------------------------------------------------------
87      * Constructors
88      *-------------------------------------------------------------*/

89     InstrumentSampleFrame( Configuration stateConfig,
90                            InstrumentManagerConnection connection,
91                            InstrumentClientFrame frame )
92         throws ConfigurationException
93     {
94         super( stateConfig, true, true, true, true, frame );
95         
96         m_instrumentSampleName = stateConfig.getAttribute( "sample" );
97         m_fullName = m_instrumentSampleName;
98         
99         m_connection = connection;
100     }
101
102     InstrumentSampleFrame( InstrumentManagerConnection connection,
103                            String JavaDoc sampleName,
104                            InstrumentClientFrame frame )
105     {
106         super( "", true, true, true, true, frame );
107
108         m_connection = connection;
109         m_instrumentSampleName = sampleName;
110         m_fullName = m_instrumentSampleName;
111         
112         setSize( new Dimension JavaDoc( 600, 120 ) );
113     }
114
115     /*---------------------------------------------------------------
116      * AbstractInternalFrame Methods
117      *-------------------------------------------------------------*/

118     /**
119      * Allows subclasses to fill in configuration information. At the least, they must set
120      * a type attribute.
121      */

122     protected void getState( DefaultConfiguration stateConfig )
123     {
124         stateConfig.setAttribute( "type", FRAME_TYPE );
125         stateConfig.setAttribute( "url", m_connection.getKey().toString() );
126         stateConfig.setAttribute( "sample", m_instrumentSampleName );
127     }
128     
129     void hideFrame()
130     {
131         //System.out.println("InstrumentSampleFrame.hideFrame()");
132

133         super.hideFrame();
134     }
135
136     /*---------------------------------------------------------------
137      * InternalFrameListener Methods
138      *-------------------------------------------------------------*/

139     public void internalFrameClosed( InternalFrameEvent JavaDoc event )
140     {
141         //System.out.println("InstrumentSampleFrame.internalFrameClosed()");
142
// Tell the connection that this frame is closing.
143
m_connection.hideSampleFrame( this );
144         
145         super.internalFrameClosed( event );
146     }
147
148     /*---------------------------------------------------------------
149      * Methods
150      *-------------------------------------------------------------*/

151     /**
152      * Returns the name of the sample being displayed.
153      *
154      * @return The name of the sample being displayed.
155      */

156     public String JavaDoc getInstrumentSampleName()
157     {
158         return m_instrumentSampleName;
159     }
160     
161     /**
162      * The last time that a snapshot was received. This is the time in the
163      * snapshot and is always in Server time. Not the time on this system.
164      *
165      * @return The last snapshot time.
166      */

167     public long getLastSnapshotTime()
168     {
169         return m_lastSnapshotTime;
170     }
171     
172     /**
173      * Update the icon that is displayed for the frame.
174      */

175     private void updateIcon()
176     {
177         ImageIcon JavaDoc icon;
178         DefaultMutableTreeNode JavaDoc sampleNode =
179             m_connection.getInstrumentSampleTreeNode( m_instrumentSampleName );
180         if ( sampleNode != null )
181         {
182             // We have a sample node, so build up a nice name
183
InstrumentSampleNodeData sampleNodeData =
184                 (InstrumentSampleNodeData)sampleNode.getUserObject();
185                 
186             // Set the icon
187
icon = sampleNodeData.getIcon();
188         }
189         else if ( m_state == STATE_MISSING )
190         {
191             icon = m_iconMissing;
192         }
193         else if ( m_state == STATE_EXPIRED )
194         {
195             icon = m_iconExpired;
196         }
197         else
198         {
199             icon = m_iconDisconnected;
200         }
201         
202         // Only change the icon if it is really different
203
if ( getFrameIcon() != icon )
204         {
205             setFrameIcon( icon );
206         }
207     }
208     
209     /**
210      * Sets the title of the frame and obtains a reference to the
211      * InstrumentSampleDescriptor in the process. The title is made up of the
212      * descriptions of all the elements up to the sample in reverse order.
213      * <p>
214      * Only called when synchronized.
215      */

216     private void updateTitle()
217     {
218         DefaultMutableTreeNode JavaDoc sampleNode =
219             m_connection.getInstrumentSampleTreeNode( m_instrumentSampleName );
220         if ( sampleNode != null )
221         {
222             // We have a sample node, so build up a nice name
223
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
224             InstrumentSampleNodeData sampleNodeData =
225                 (InstrumentSampleNodeData)sampleNode.getUserObject();
226             
227             sb.append( sampleNodeData.getDescription() );
228             
229             // Loop up to the root, appending each description.
230
DefaultMutableTreeNode JavaDoc parentNode = (DefaultMutableTreeNode JavaDoc)sampleNode.getParent();
231             while( parentNode != null )
232             {
233                 Object JavaDoc userObject = parentNode.getUserObject();
234                 if ( ( userObject == null ) || !( userObject instanceof NodeData) )
235                 {
236                     parentNode = null;
237                 }
238                 else
239                 {
240                     sb.append( " / " );
241                     sb.append( ((NodeData)userObject).getDescription() );
242                     parentNode = (DefaultMutableTreeNode JavaDoc)parentNode.getParent();
243                 }
244             }
245             
246             // Store the full name so that we can reuse it later.
247
m_fullName = sb.toString();
248         }
249         
250         // Build the title
251
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
252         switch ( m_state )
253         {
254         case STATE_SNAPSHOT:
255             break;
256             
257         case STATE_MISSING:
258             sb.append( "[Missing] " );
259             break;
260             
261         case STATE_EXPIRED:
262             sb.append( "[Expired] " );
263             break;
264             
265         default:
266             sb.append( "[Disconnected] " );
267             break;
268         }
269         
270         // Add the full name
271
sb.append( m_fullName );
272         
273         // Add the connection info
274
sb.append( " / " );
275         sb.append( m_connection.getTitle() );
276         
277         String JavaDoc title = sb.toString();
278         
279         // Only set the title if it has changed to avoid repaints
280
if ( !getTitle().equals( title ) )
281         {
282             setTitle( title );
283         }
284     }
285
286     /**
287      * Initializes the chart
288      *
289      * @param snapshot InstrumentSampleSnapshotData to use to initialize the chart.
290      */

291     private void initChart( InstrumentSampleSnapshotData snapshot )
292     {
293         // Decide on a line interval based on the interval of the sample.
294
long interval = Math.max( 1, snapshot.getInterval() );
295         int hInterval;
296         String JavaDoc format;
297         String JavaDoc detailFormat;
298         if( interval < 1000 )
299         {
300             // Once per 10 seconds.
301
hInterval = (int)( 10000 / interval );
302             format = "{3}:{4}:{5}";
303             detailFormat = "{1}/{2} {3}:{4}:{5}.{6}";
304         }
305         else if( interval < 60000 )
306         {
307             // Once per minute.
308
hInterval = (int)( 60000 / interval );
309             format = "{3}:{4}:{5}";
310             detailFormat = "{1}/{2} {3}:{4}:{5}";
311         }
312         else if( interval < 600000 )
313         {
314             // Once per 10 minutes
315
hInterval = (int)( 600000 / interval );
316             format = "{1}/{2} {3}:{4}";
317             detailFormat = "{1}/{2} {3}:{4}";
318         }
319         else if( interval < 3600000 )
320         {
321             // Once per hour.
322
hInterval = (int)( 3600000 / interval );
323             format = "{1}/{2} {3}:{4}";
324             detailFormat = "{1}/{2} {3}:{4}";
325         }
326         else if( interval < 86400000 )
327         {
328             // Once per day.
329
hInterval = (int)( 86400000 / interval );
330             format = "{1}/{2}";
331             detailFormat = "{1}/{2} {3}:{4}";
332         }
333         else if( interval < 604800000 )
334         {
335             // Once per week.
336
hInterval = (int)( 604800000 / interval );
337             format = "{0}/{1}/{2}";
338             detailFormat = "{0}/{1}/{2}";
339         }
340         else
341         {
342             // Default to every 10 points.
343
hInterval = 10;
344             format = "{0}/{1}/{2}";
345             detailFormat = "{0}/{1}/{2}";
346         }
347
348         // Make sure that the content pane is empty.
349
getContentPane().removeAll();
350             
351         // Actually create the chart and add it to the content pane
352
m_lineChart = new LineChart(
353             hInterval, interval, format, detailFormat, 20, getFrame().isAntialias() );
354         getContentPane().add( m_lineChart );
355     }
356     
357     private void setStateSnapshot( InstrumentSampleSnapshotData snapshot )
358     {
359         if ( m_state != STATE_SNAPSHOT )
360         {
361             initChart( snapshot );
362             
363             m_state = STATE_SNAPSHOT;
364             
365             updateTitle();
366         }
367
368         int size = snapshot.getSize();
369         
370         // The new samples that came in the snapshot may or may not be a complete
371
// set. They usually will be partial.
372
int[] newSamples = snapshot.getSamples();
373         if ( newSamples.length == size )
374         {
375             // We got a full sample set. Just replace the internal sample buffer.
376
m_samples = newSamples;
377         }
378         else if ( newSamples.length > size )
379         {
380             // Should never happen. But protect against it to avoid errors.
381
// Only use the last {size} samples.
382
m_samples = new int[size];
383             System.arraycopy( newSamples, newSamples.length - size, m_samples, 0, size );
384         }
385         else
386         {
387             // We received a partial sample set, so we need to adjust the existing
388
// data then copy the new data over the array.
389

390             // Make sure that the local buffer is the correct size.
391
if ( m_samples == null )
392             {
393                 m_samples = new int[size];
394             }
395             else if ( m_samples.length != size )
396             {
397                 // The sample size changed on the server.
398
int[] tmpSamples = new int[size];
399                 if ( m_samples.length > size )
400                 {
401                     // Got smaller. The beginning of the existing array gets trimmed.
402
System.arraycopy( m_samples, m_samples.length - size, tmpSamples, 0, size );
403                 }
404                 else
405                 {
406                     // Got larger. The beginning of the new array will be all 0s.
407
System.arraycopy(
408                         m_samples, 0, tmpSamples, size - m_samples.length, m_samples.length );
409                 }
410                 m_samples = tmpSamples;
411             }
412             
413             // Calculate the age of the buffered samples.
414
long age = snapshot.getTime() - m_lastSnapshotTime;
415             int intervalAge = (int)( age / snapshot.getInterval() );
416             if ( intervalAge > m_samples.length )
417             {
418                 intervalAge = m_samples.length;
419             }
420             
421             // Move existing values down in the buffer as necessary.
422
if ( ( intervalAge > 0 ) && ( intervalAge < m_samples.length ) )
423             {
424                 // We are moving down in the array so we can do this withtout a temp array.
425
System.arraycopy( m_samples, intervalAge, m_samples, 0, size - intervalAge );
426             }
427             
428             // This will only happen if there is a timing problem, but fill in any
429
// space between the old and new values with 0s.
430
if ( intervalAge > newSamples.length )
431             {
432                 for ( int i = size - intervalAge; i < size - newSamples.length; i++ )
433                 {
434                     m_samples[i] = 0;
435                 }
436             }
437             
438             // Copy the new samples over the end of the sample buffer.
439
System.arraycopy(
440                 newSamples, 0, m_samples, size - newSamples.length, newSamples.length );
441         }
442         
443         // Update the contents of the chart.
444
m_lineChart.setValues( m_samples, snapshot.getTime() );
445             
446         // Store the time of this snapshot.
447
m_lastSnapshotTime = snapshot.getTime();
448         
449         // Icon can change.
450
updateIcon();
451     }
452
453     /**
454      * Sets the state of the frame to show that the connection is closed.
455      */

456     private void setStateDisconnected()
457     {
458         if ( m_state != STATE_DISCONNECTED )
459         {
460             getContentPane().removeAll();
461             
462             // Not connected.
463
JLabel JavaDoc label = new JLabel JavaDoc( "Not connected" );
464             label.setForeground( Color.red );
465             label.setHorizontalAlignment( SwingConstants.CENTER );
466             label.setVerticalAlignment( SwingConstants.CENTER );
467             
468             getContentPane().add( label );
469             
470             m_state = STATE_DISCONNECTED;
471             
472             updateTitle();
473             updateIcon();
474         }
475     }
476     
477     /**
478      * Sets the state of the frame to show that the sample could not be found.
479      */

480     private void setStateSampleMissing()
481     {
482         if ( m_state != STATE_MISSING )
483         {
484             getContentPane().removeAll();
485             
486             // Not connected.
487
JLabel JavaDoc label = new JLabel JavaDoc( "Sample not found" );
488             label.setForeground( Color.red );
489             label.setHorizontalAlignment( SwingConstants.CENTER );
490             label.setVerticalAlignment( SwingConstants.CENTER );
491             
492             getContentPane().add( label );
493             
494             m_state = STATE_MISSING;
495             
496             updateTitle();
497             updateIcon();
498         }
499     }
500     
501     /**
502      * Sets the state of the frame to show that the sample could not be found.
503      */

504     private void setStateSampleExpired()
505     {
506         if ( m_state != STATE_EXPIRED )
507         {
508             // Leave the chart as is. It will just stop updating.
509
// Change its background color slightly.
510
m_lineChart.setBackground( new Color JavaDoc( 220, 220, 220 ) );
511             m_lineChart.repaint();
512             
513             m_state = STATE_EXPIRED;
514             
515             updateTitle();
516             updateIcon();
517         }
518     }
519     
520     /**
521      * Called to update the frame when a snapshot is already available.
522      *
523      * @param snapshot Snapshot to update the frame with. Null if unavailable.
524      */

525     public void updateSnapshot( InstrumentSampleSnapshotData snapshot )
526     {
527         if ( m_connection.isDeleted() )
528         {
529             // The connection was closed and deleted.
530
hideFrame();
531         }
532         else
533         {
534             if ( m_lineChart != null )
535             {
536                 m_lineChart.setAntialias( getFrame().isAntialias() );
537             }
538             
539             if ( snapshot == null )
540             {
541                 // A sample was not available. Why.
542
if ( !m_connection.isConnected() )
543                 {
544                     // Connection was closed.
545
setStateDisconnected();
546                 }
547                 else if ( ( m_state == STATE_SNAPSHOT ) || ( m_state == STATE_EXPIRED ) )
548                 {
549                     // We were getting snapshots, then they stopped. The sample expired.
550
setStateSampleExpired();
551                 }
552                 else
553                 {
554                     // Sample not found.
555
setStateSampleMissing();
556                 }
557             }
558             else
559             {
560                 setStateSnapshot( snapshot );
561             }
562         }
563     }
564     
565     /**
566      * Called to update the frame and request a new snapshot from the server.
567      */

568     void update()
569     {
570         InstrumentSampleSnapshotData snapshot = null;
571         if ( !m_connection.isDeleted() )
572         {
573             snapshot = m_connection.getSampleSnapshot( m_instrumentSampleName );
574         }
575         
576         updateSnapshot( snapshot );
577     }
578 }
579
580
Popular Tags