KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > excalibur > instrument > manager > DefaultInstrumentManager


1 /*
2
3  ============================================================================
4                    The Apache Software License, Version 1.1
5  ============================================================================
6  
7  Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  
9  Redistribution and use in source and binary forms, with or without modifica-
10  tion, are permitted provided that the following conditions are met:
11  
12  1. Redistributions of source code must retain the above copyright notice,
13     this list of conditions and the following disclaimer.
14  
15  2. Redistributions in binary form must reproduce the above copyright notice,
16     this list of conditions and the following disclaimer in the documentation
17     and/or other materials provided with the distribution.
18  
19  3. The end-user documentation included with the redistribution, if any, must
20     include the following acknowledgment: "This product includes software
21     developed by the Apache Software Foundation (http://www.apache.org/)."
22     Alternately, this acknowledgment may appear in the software itself, if
23     and wherever such third-party acknowledgments normally appear.
24  
25  4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
26     must not be used to endorse or promote products derived from this software
27     without prior written permission. For written permission, please contact
28     apache@apache.org.
29  
30  5. Products derived from this software may not be called "Apache", nor may
31     "Apache" appear in their name, without prior written permission of the
32     Apache Software Foundation.
33  
34  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  
45  This software consists of voluntary contributions made by many individuals
46  on behalf of the Apache Software Foundation. For more information on the
47  Apache Software Foundation, please see <http://www.apache.org/>.
48  
49 */

50 package org.apache.excalibur.instrument.manager;
51
52 import java.io.ByteArrayOutputStream JavaDoc;
53 import java.io.File JavaDoc;
54 import java.io.FileInputStream JavaDoc;
55 import java.io.FileOutputStream JavaDoc;
56 import java.io.InputStream JavaDoc;
57 import java.io.OutputStream JavaDoc;
58 import java.util.ArrayList JavaDoc;
59 import java.util.Arrays JavaDoc;
60 import java.util.Comparator JavaDoc;
61 import java.util.HashMap JavaDoc;
62 import java.util.Iterator JavaDoc;
63
64 import org.apache.avalon.framework.activity.Disposable;
65 import org.apache.avalon.framework.activity.Initializable;
66 import org.apache.avalon.framework.configuration.Configurable;
67 import org.apache.avalon.framework.configuration.Configuration;
68 import org.apache.avalon.framework.configuration.ConfigurationException;
69 import org.apache.avalon.framework.configuration.DefaultConfiguration;
70 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
71 import org.apache.avalon.framework.configuration.DefaultConfigurationSerializer;
72 import org.apache.avalon.framework.container.ContainerUtil;
73 import org.apache.avalon.framework.logger.AbstractLogEnabled;
74 import org.apache.avalon.framework.logger.Logger;
75 import org.apache.avalon.framework.service.ServiceException;
76 import org.apache.excalibur.instrument.AbstractInstrument;
77 import org.apache.excalibur.instrument.CounterInstrument;
78 import org.apache.excalibur.instrument.Instrument;
79 import org.apache.excalibur.instrument.InstrumentManager;
80 import org.apache.excalibur.instrument.Instrumentable;
81 import org.apache.excalibur.instrument.ValueInstrument;
82 import org.apache.excalibur.instrument.manager.interfaces.InstrumentManagerClient;
83 import org.apache.excalibur.instrument.manager.interfaces.NoSuchInstrumentException;
84 import org.apache.excalibur.instrument.manager.interfaces.NoSuchInstrumentSampleException;
85 import org.apache.excalibur.instrument.manager.interfaces.NoSuchInstrumentableException;
86
87 /**
88  *
89  * @author <a HREF="mailto:leif@tanukisoftware.com">Leif Mortenson</a>
90  * @version CVS $Revision: 1.5 $ $Date: 2003/02/25 16:28:16 $
91  * @since 4.1
92  */

93 public class DefaultInstrumentManager
94     extends AbstractLogEnabled
95     implements Configurable, Initializable, Disposable, InstrumentManager,
96         Instrumentable, Runnable JavaDoc
97 {
98     public static final String JavaDoc INSTRUMENT_TOTAL_MEMORY = "total-memory";
99     public static final String JavaDoc INSTRUMENT_FREE_MEMORY = "free-memory";
100     public static final String JavaDoc INSTRUMENT_MEMORY = "memory";
101     public static final String JavaDoc INSTRUMENT_ACTIVE_THREAD_COUNT = "active-thread-count";
102     
103     /** The name used to identify this InstrumentManager. */
104     private String JavaDoc m_name;
105
106     /** The description of this InstrumentManager. */
107     private String JavaDoc m_description;
108     
109     /** Configuration for the InstrumentManager */
110     private Configuration m_configuration;
111     
112     /** List of configured connectors. */
113     private ArrayList JavaDoc m_connectors = new ArrayList JavaDoc();
114
115     /** State file. */
116     private File JavaDoc m_stateFile;
117
118     /** Save state interval. */
119     private long m_stateInterval;
120
121     /** Last time that the state was saved. */
122     private long m_lastStateSave;
123
124     /** Semaphore for actions which must be synchronized */
125     private Object JavaDoc m_semaphore = new Object JavaDoc();
126
127     /** HashMap of all of the registered InstrumentableProxies by their keys. */
128     private HashMap JavaDoc m_instrumentableProxies = new HashMap JavaDoc();
129
130     /** Optimized array of the InstrumentableProxies. */
131     private InstrumentableProxy[] m_instrumentableProxyArray;
132
133     /** Optimized array of the InstrumentableDescriptorLocals. */
134     private InstrumentableDescriptorLocal[] m_instrumentableDescriptorArray;
135
136     /** List of leased InstrumentSamples. */
137     private ArrayList JavaDoc m_leasedInstrumentSamples = new ArrayList JavaDoc();
138     
139     /** Optimized array of the leased InstrumentSamples. */
140     private InstrumentSample[] m_leasedInstrumentSampleArray;
141     
142     /**
143      * Thread used to keep the instruments published by the InstrumentManager
144      * up to date.
145      */

146     private Thread JavaDoc m_runner;
147
148     /** Instrumentable Name assigned to this Instrumentable */
149     private String JavaDoc m_instrumentableName = "instrument-manager";
150
151     /** Instrument used to profile the total memory. */
152     private ValueInstrument m_totalMemoryInstrument;
153
154     /** Instrument used to profile the free memory. */
155     private ValueInstrument m_freeMemoryInstrument;
156
157     /** Instrument used to profile the in use memory. */
158     private ValueInstrument m_memoryInstrument;
159
160     /** Instrument used to profile the active thread count of the JVM. */
161     private ValueInstrument m_activeThreadCountInstrument;
162     
163     /** State Version. */
164     private int m_stateVersion;
165
166     /*---------------------------------------------------------------
167      * Constructors
168      *-------------------------------------------------------------*/

169     /**
170      * Creates a new DefaultInstrumentManager.
171      *
172      * @param name The name used to identify this InstrumentManager. Should not
173      * contain any spaces or periods.
174      *
175      * @deprecated Name should be set in the instrument configuration file.
176      */

177     public DefaultInstrumentManager( String JavaDoc name )
178     {
179         this();
180     }
181     
182     /**
183      * Creates a new DefaultInstrumentManager.
184      */

185     public DefaultInstrumentManager()
186     {
187         // Initialize the Instrumentable elements.
188
m_totalMemoryInstrument = new ValueInstrument( INSTRUMENT_TOTAL_MEMORY );
189         m_freeMemoryInstrument = new ValueInstrument( INSTRUMENT_FREE_MEMORY );
190         m_memoryInstrument = new ValueInstrument( INSTRUMENT_MEMORY );
191         m_activeThreadCountInstrument = new ValueInstrument( INSTRUMENT_ACTIVE_THREAD_COUNT );
192     }
193
194     /*---------------------------------------------------------------
195      * Configurable Methods
196      *-------------------------------------------------------------*/

197     /**
198      * Initializes the configured instrumentables.
199      *
200      * @param configuration InstrumentManager configuration.
201      *
202      * @throws ConfigurationException If there are any configuration problems.
203      */

204     public void configure( Configuration configuration )
205         throws ConfigurationException
206     {
207         synchronized( m_semaphore )
208         {
209             m_configuration = configuration;
210
211             // Look for a configured name and description
212
m_name = configuration.getChild( "name" ).getValue( "instrument-manager" );
213             m_description = configuration.getChild( "description" ).getValue( m_name );
214             
215             // Create a logger to use with the connectors
216
Logger connLogger = getLogger().getChildLogger( "connector" );
217             
218             // Configure the connectors
219
Configuration connectorsConf = configuration.getChild( "connectors" );
220             Configuration[] connectorConfs =
221                 connectorsConf.getChildren( "connector" );
222             for( int i = 0; i < connectorConfs.length; i++ )
223             {
224                 Configuration connectorConf = connectorConfs[ i ];
225                 String JavaDoc className = connectorConf.getAttribute( "class" );
226                 // Handle aliases
227
if ( className.equals( "altrmi" ) )
228                 {
229                     className = "org.apache.excalibur.instrument.manager.altrmi."
230                         + "InstrumentManagerAltrmiConnector";
231                 }
232                 
233                 // Look for the connector class and create an instance.
234
try
235                 {
236                     Class JavaDoc clazz = Class.forName( className );
237                     InstrumentManagerConnector connector =
238                         (InstrumentManagerConnector)clazz.newInstance();
239                     
240                     // Initialize the new connector
241
connector.setInstrumentManager( this );
242                     ContainerUtil.enableLogging( connector, connLogger );
243                     ContainerUtil.configure( connector, connectorConf );
244                     ContainerUtil.start( connector );
245                     
246                     m_connectors.add( connector );
247                 }
248                 catch ( Exception JavaDoc e )
249                 {
250                     throw new ConfigurationException( "Unable to create connector because: "
251                         + e );
252                 }
253             }
254             
255             // Configure the instrumentables.
256
Configuration instrumentablesConf = configuration.getChild( "instrumentables" );
257             Configuration[] instrumentableConfs =
258                 instrumentablesConf.getChildren( "instrumentable" );
259             for( int i = 0; i < instrumentableConfs.length; i++ )
260             {
261                 Configuration instrumentableConf = instrumentableConfs[ i ];
262                 String JavaDoc instrumentableName = instrumentableConf.getAttribute( "name" );
263
264                 InstrumentableProxy instrumentableProxy = new InstrumentableProxy(
265                     this, null, instrumentableName, instrumentableName );
266                 instrumentableProxy.enableLogging( getLogger() );
267                 instrumentableProxy.configure( instrumentableConf );
268                 m_instrumentableProxies.put( instrumentableName, instrumentableProxy );
269
270                 // Clear the optimized arrays
271
m_instrumentableProxyArray = null;
272                 m_instrumentableDescriptorArray = null;
273             }
274
275             // Configure the state file.
276
Configuration stateFileConf = configuration.getChild( "state-file" );
277             m_stateInterval = stateFileConf.getAttributeAsLong( "interval", 60000 );
278
279             String JavaDoc stateFile = stateFileConf.getValue( null );
280             if( stateFile != null )
281             {
282                 m_stateFile = new File JavaDoc( stateFile );
283                 if( m_stateFile.exists() )
284                 {
285                     try
286                     {
287                         loadStateFromFile( m_stateFile );
288                     }
289                     catch( Exception JavaDoc e )
290                     {
291                         getLogger().error(
292                             "Unable to load the instrument manager state. The configuration " +
293                             "may have been corruptped. A backup may have been made in the same " +
294                             "directory when it was saved.", e );
295                     }
296                 }
297             }
298         }
299     }
300
301     /*---------------------------------------------------------------
302      * Initializable Methods
303      *-------------------------------------------------------------*/

304     /**
305      * Initializes the InstrumentManager.
306      *
307      * @throws Exception If there were any problems initializing the object.
308      */

309     public void initialize()
310         throws Exception JavaDoc
311     {
312         // Register the InstrumentManager as an Instrumentable.
313
registerInstrumentable( this, getInstrumentableName() );
314
315         if( m_runner == null )
316         {
317             m_runner = new Thread JavaDoc( this, "InstrumentManagerRunner" );
318             m_runner.start();
319         }
320     }
321
322     /*---------------------------------------------------------------
323      * Disposable Methods
324      *-------------------------------------------------------------*/

325     /**
326      * Disposes the InstrumentManager.
327      */

328     public void dispose()
329     {
330         if( m_runner != null )
331         {
332             m_runner = null;
333         }
334         
335         // Shutdown the connectors
336
for ( Iterator JavaDoc iter = m_connectors.iterator(); iter.hasNext(); )
337         {
338             InstrumentManagerConnector connector = (InstrumentManagerConnector)iter.next();
339             try
340             {
341                 ContainerUtil.stop( connector );
342                 ContainerUtil.dispose( connector );
343             }
344             catch ( Exception JavaDoc e )
345             {
346                 getLogger().error( "Encountered an unexpected error shutting down a connector", e );
347             }
348         }
349
350         saveState();
351     }
352
353     /*---------------------------------------------------------------
354      * InstrumentManager Methods
355      *-------------------------------------------------------------*/

356     /**
357      * Instrumentable to be registered with the instrument manager. Should be
358      * called whenever an Instrumentable is created. The '.' character is
359      * used to denote a child Instrumentable and can be used to register the
360      * instrumentable at a specific point in an instrumentable hierarchy.
361      *
362      * @param instrumentable Instrumentable to register with the InstrumentManager.
363      * @param instrumentableName The name to use when registering the Instrumentable.
364      *
365      * @throws Exception If there were any problems registering the Instrumentable.
366      */

367     public void registerInstrumentable( Instrumentable instrumentable, String JavaDoc instrumentableName )
368         throws Exception JavaDoc
369     {
370         getLogger().debug( "Registering Instrumentable: " + instrumentableName );
371
372         synchronized( m_semaphore )
373         {
374             // If the specified instrumentable name contains '.' chars then we need to
375
// make sure we register the instrumentable at the correct location, creating
376
// any parent instrumentables as necessary.
377
int pos = instrumentableName.indexOf( '.' );
378             if ( pos >= 0 )
379             {
380                 String JavaDoc parentName = instrumentableName.substring( 0, pos );
381                 String JavaDoc childName =
382                     instrumentableName.substring( pos + 1 );
383                 InstrumentableProxy instrumentableProxy =
384                     (InstrumentableProxy)m_instrumentableProxies.get( parentName );
385                 if( instrumentableProxy == null )
386                 {
387                     // This is a Instrumentable that has not been seen before.
388
instrumentableProxy = new InstrumentableProxy(
389                         this, null, parentName, parentName );
390                     instrumentableProxy.enableLogging( getLogger() );
391                     // Do not call configure here because there is no configuration
392
// for discovered instrumentables.
393
m_instrumentableProxies.put( parentName, instrumentableProxy );
394     
395                     // Clear the optimized arrays
396
m_instrumentableProxyArray = null;
397                     m_instrumentableDescriptorArray = null;
398     
399                     // Recursively register all the Instruments in this and any child Instrumentables.
400
registerDummyInstrumentableInner(
401                         instrumentable, instrumentableProxy, parentName, childName );
402                 }
403                 else
404                 {
405                     // Additional Instrumentable instance. Possible that new Instruments could be found.
406
registerDummyInstrumentableInner(
407                         instrumentable, instrumentableProxy, parentName, childName );
408                 }
409             } else {
410                 // If the instrumentable does not implement ThreadSafe, then it is possible that
411
// another one of its instance was already registered. If so, then the
412
// Instruments will all be the same. The new instances still need to be
413
// registered however.
414
InstrumentableProxy instrumentableProxy =
415                     (InstrumentableProxy)m_instrumentableProxies.get( instrumentableName );
416                 if( instrumentableProxy == null )
417                 {
418                     // This is a Instrumentable that has not been seen before.
419
instrumentableProxy = new InstrumentableProxy(
420                         this, null, instrumentableName, instrumentableName );
421                     instrumentableProxy.enableLogging( getLogger() );
422                     // Do not call configure here because there is no configuration
423
// for discovered instrumentables.
424
m_instrumentableProxies.put( instrumentableName, instrumentableProxy );
425     
426                     // Clear the optimized arrays
427
m_instrumentableProxyArray = null;
428                     m_instrumentableDescriptorArray = null;
429     
430                     // Recursively register all the Instruments in this and any child Instrumentables.
431
registerInstrumentableInner(
432                         instrumentable, instrumentableProxy, instrumentableName );
433                 }
434                 else
435                 {
436                     // Additional Instrumentable instance. Possible that new Instruments could be found.
437
registerInstrumentableInner(
438                         instrumentable, instrumentableProxy, instrumentableName );
439                 }
440             }
441         }
442         
443         stateChanged();
444     }
445
446     
447     /*---------------------------------------------------------------
448      * Methods
449      *-------------------------------------------------------------*/

450     /**
451      * Returns the name used to identify this InstrumentManager.
452      *
453      * @return The name used to identify this InstrumentManager.
454      */

455     public String JavaDoc getName()
456     {
457         return m_name;
458     }
459     
460     /**
461      * Returns the description of this InstrumentManager.
462      *
463      * @return The description of this InstrumentManager.
464      */

465     public String JavaDoc getDescription()
466     {
467         return m_description;
468     }
469     
470     /**
471      * Returns an InstrumentableDescriptorLocal based on its name or the name
472      * of any of its children.
473      *
474      * @param instrumentableName Name of the Instrumentable being requested.
475      *
476      * @return A Descriptor of the requested Instrumentable.
477      *
478      * @throws NoSuchInstrumentableException If the specified Instrumentable
479      * does not exist.
480      */

481     public InstrumentableDescriptorLocal getInstrumentableDescriptor( String JavaDoc instrumentableName )
482         throws NoSuchInstrumentableException
483     {
484         InstrumentableProxy proxy = getInstrumentableProxy( instrumentableName );
485         if( proxy == null )
486         {
487             throw new NoSuchInstrumentableException(
488                 "No instrumentable can be found using name: " + instrumentableName );
489         }
490
491         return proxy.getDescriptor();
492     }
493
494     /**
495      * Returns an array of Descriptors for the Instrumentables managed by this
496      * InstrumentManager.
497      *
498      * @return An array of Descriptors for the Instrumentables managed by this
499      * InstrumentManager.
500      */

501     public InstrumentableDescriptorLocal[] getInstrumentableDescriptors()
502     {
503         InstrumentableDescriptorLocal[] descriptors = m_instrumentableDescriptorArray;
504         if( descriptors == null )
505         {
506             descriptors = updateInstrumentableDescriptorArray();
507         }
508         return descriptors;
509     }
510     
511     /**
512      * Searches the entire instrument tree an instrumentable with the given
513      * name.
514      *
515      * @param instrumentableName Name of the Instrumentable being requested.
516      *
517      * @return A Descriptor of the requested Instrumentable.
518      *
519      * @throws NoSuchInstrumentableException If the specified Instrumentable does
520      * not exist.
521      */

522     public InstrumentableDescriptorLocal locateInstrumentableDescriptor( String JavaDoc instrumentableName )
523         throws NoSuchInstrumentableException
524     {
525         InstrumentableProxy instrumentableProxy =
526             locateDeepestInstrumentableProxy( instrumentableName );
527         if ( instrumentableProxy != null )
528         {
529             if ( instrumentableProxy.getName().equals( instrumentableName ) )
530             {
531                 // Found what we were looking for
532
return instrumentableProxy.getDescriptor();
533             }
534         }
535         
536         // Unable to locate the requested Instrumentable
537
throw new NoSuchInstrumentableException(
538             "No instrumentable can be found with the name: " + instrumentableName );
539     }
540     
541     /**
542      * Searches the entire instrument tree an instrument with the given name.
543      *
544      * @param instrumentName Name of the Instrument being requested.
545      *
546      * @return A Descriptor of the requested Instrument.
547      *
548      * @throws NoSuchInstrumentException If the specified Instrument does
549      * not exist.
550      */

551     public InstrumentDescriptorLocal locateInstrumentDescriptor( String JavaDoc instrumentName )
552         throws NoSuchInstrumentException
553     {
554         InstrumentableProxy instrumentableProxy =
555             locateDeepestInstrumentableProxy( instrumentName );
556         if ( instrumentableProxy != null )
557         {
558             // Now look for the specified instrument
559
InstrumentProxy instrumentProxy =
560                 instrumentableProxy.getInstrumentProxy( instrumentName );
561             if ( instrumentProxy != null )
562             {
563                 if ( instrumentProxy.getName().equals( instrumentName ) )
564                 {
565                     // Found what we were looking for
566
return instrumentProxy.getDescriptor();
567                 }
568             }
569         }
570         
571         // Unable to locate the requested Instrument
572
throw new NoSuchInstrumentException(
573             "No instrument can be found with the name: " + instrumentName );
574     }
575
576     /**
577      * Searches the entire instrument tree an instrument sample with the given
578      * name.
579      *
580      * @param sampleName Name of the Instrument Sample being requested.
581      *
582      * @return A Descriptor of the requested Instrument Sample.
583      *
584      * @throws NoSuchInstrumentSampleException If the specified Instrument
585      * Sample does not exist.
586      */

587     public InstrumentSampleDescriptorLocal locateInstrumentSampleDescriptor( String JavaDoc sampleName )
588         throws NoSuchInstrumentSampleException
589     {
590         InstrumentableProxy instrumentableProxy =
591             locateDeepestInstrumentableProxy( sampleName );
592         if ( instrumentableProxy != null )
593         {
594             // Now look for the specified instrument
595
InstrumentProxy instrumentProxy =
596                 instrumentableProxy.getInstrumentProxy( sampleName );
597             if ( instrumentProxy != null )
598             {
599                 // Now look for the specified sample
600
InstrumentSample sample = instrumentProxy.getInstrumentSample( sampleName );
601                 if ( sample != null )
602                 {
603                     if ( sample.getName().equals( sampleName ) )
604                     {
605                         // Found what we were looking for
606
return sample.getDescriptor();
607                     }
608                 }
609             }
610         }
611         
612         // Unable to locate the requested Instrument Sample
613
throw new NoSuchInstrumentException(
614             "No instrument sample can be found with the name: " + sampleName );
615     }
616     
617     /**
618      * Returns the stateVersion of the instrument manager. The state version
619      * will be incremented each time any of the configuration of the
620      * instrument manager or any of its children is modified.
621      * Clients can use this value to tell whether or not anything has
622      * changed without having to do an exhaustive comparison.
623      *
624      * @return The state version of the instrument manager.
625      */

626     int getStateVersion()
627     {
628         return m_stateVersion;
629     }
630     
631     /**
632      * Invokes garbage collection.
633      */

634     public void invokeGarbageCollection()
635     {
636         System.gc();
637     }
638     
639     
640
641     /**
642      * Loads the Instrument Manager state from the specified file.
643      *
644      * @param stateFile File to read the instrument manager's state from.
645      *
646      * @throws Exception if there are any problems loading the state.
647      */

648     public void loadStateFromFile( File JavaDoc stateFile )
649         throws Exception JavaDoc
650     {
651         long now = System.currentTimeMillis();
652         getLogger().debug( "Loading Instrument Manager state from: " +
653             stateFile.getAbsolutePath() );
654
655         FileInputStream JavaDoc is = new FileInputStream JavaDoc( stateFile );
656         try
657         {
658             loadStateFromStream( is );
659         }
660         finally
661         {
662             is.close();
663         }
664
665         getLogger().debug( "Loading Instrument Manager state took " +
666                            ( System.currentTimeMillis() - now ) + "ms." );
667     }
668
669     /**
670      * Loads the Instrument Manager state from the specified stream.
671      *
672      * @param is Stream to read the instrument manager's state from.
673      *
674      * @throws Exception if there are any problems loading the state.
675      */

676     public void loadStateFromStream( InputStream JavaDoc is )
677         throws Exception JavaDoc
678     {
679         // Ride on top of the Configuration classes to load the state.
680
DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
681         Configuration stateConfig = builder.build( is );
682
683         loadStateFromConfiguration( stateConfig );
684     }
685
686     /**
687      * Loads the Instrument Manager state from the specified Configuration.
688      *
689      * @param state Configuration object to load the state from.
690      *
691      * @throws ConfigurationException If there were any problems loading the
692      * state.
693      */

694     public void loadStateFromConfiguration( Configuration state )
695         throws ConfigurationException
696     {
697         Configuration[] instrumentableConfs = state.getChildren( "instrumentable" );
698         for( int i = 0; i < instrumentableConfs.length; i++ )
699         {
700             Configuration instrumentableConf = instrumentableConfs[ i ];
701             String JavaDoc instrumentableName = instrumentableConf.getAttribute( "name" );
702             InstrumentableProxy instrumentableProxy = getInstrumentableProxy( instrumentableName );
703             if( instrumentableProxy == null )
704             {
705                 // The Instrumentable was in the state file, but has not yet
706
// been registered. It is possible that it will be registered
707
// at a later time. For now it needs to be created.
708
instrumentableProxy = new InstrumentableProxy(
709                     this, null, instrumentableName, instrumentableName );
710                 instrumentableProxy.enableLogging( getLogger() );
711                 m_instrumentableProxies.put( instrumentableName, instrumentableProxy );
712
713                 // Clear the optimized arrays
714
m_instrumentableProxyArray = null;
715                 m_instrumentableDescriptorArray = null;
716             }
717             
718             instrumentableProxy.loadState( instrumentableConf );
719         }
720         
721         stateChanged();
722     }
723
724     /**
725      * Saves the Instrument Manager's state to the specified file. Any
726      * existing file is backed up before the save takes place and replaced
727      * in the event of an error.
728      *
729      * @param stateFile File to write the Instrument Manager's state to.
730      *
731      * @throws Exception if there are any problems saving the state.
732      */

733     public void saveStateToFile( File JavaDoc stateFile )
734         throws Exception JavaDoc
735     {
736         long now = System.currentTimeMillis();
737         getLogger().debug( "Saving Instrument Manager state to: " + stateFile.getAbsolutePath() );
738
739         // First save the state to an in memory stream to shorten the
740
// period of time needed to write the data to disk. This makes it
741
// less likely that the files will be left in a corrupted state if
742
// the JVM dies at the wrong time.
743
ByteArrayOutputStream JavaDoc os = new ByteArrayOutputStream JavaDoc();
744         byte[] data;
745         try
746         {
747             saveStateToStream( os );
748             data = os.toByteArray();
749         }
750         finally
751         {
752             os.close();
753         }
754         
755         // If the specified file exists, then rename it before we start writing.
756
// This makes it possible to recover from some errors.
757
File JavaDoc renameFile = null;
758         boolean success = false;
759         if( stateFile.exists() )
760         {
761             renameFile = new File JavaDoc( stateFile.getAbsolutePath() + "." + now + ".backup" );
762             stateFile.renameTo( renameFile );
763         }
764         
765         // Write the data to the new file.
766
FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc( stateFile );
767         try
768         {
769             fos.write( data );
770             success = true;
771         }
772         finally
773         {
774             fos.close();
775             
776             if ( !success )
777             {
778                 // Make sure that part of the file does not exist.
779
stateFile.delete();
780             }
781             
782             // Handle the backup file.
783
if ( renameFile != null )
784             {
785                 if ( success )
786                 {
787                     // No longer need the backup.
788
renameFile.delete();
789                 }
790                 else
791                 {
792                     // Need to replace the backup.
793
renameFile.renameTo( stateFile );
794                 }
795             }
796         }
797         
798         getLogger().debug( "Saving Instrument Manager state took " +
799                            ( System.currentTimeMillis() - now ) + "ms." );
800     }
801
802     /**
803      * Saves the Instrument Manager's state to the specified output stream.
804      *
805      * @param os Stream to write the Instrument Manager's state to.
806      *
807      * @throws Exception if there are any problems saving the state.
808      */

809     public void saveStateToStream( OutputStream JavaDoc os )
810         throws Exception JavaDoc
811     {
812         Configuration stateConfig = saveStateToConfiguration();
813
814         // Ride on top of the Configuration classes to save the state.
815
DefaultConfigurationSerializer serializer = new DefaultConfigurationSerializer();
816         serializer.setIndent( true );
817         serializer.serialize( os, stateConfig );
818     }
819
820     /**
821      * Returns the Instrument Manager's state as a Configuration object.
822      *
823      * @return The Instrument Manager's state as a Configuration object.
824      */

825     public Configuration saveStateToConfiguration()
826     {
827         DefaultConfiguration state = new DefaultConfiguration( "instrument-manager-state", "-" );
828
829         InstrumentableProxy[] instrumentableProxies = m_instrumentableProxyArray;
830         if( instrumentableProxies == null )
831         {
832             instrumentableProxies = updateInstrumentableProxyArray();
833         }
834
835         for( int i = 0; i < instrumentableProxies.length; i++ )
836         {
837             Configuration childState = instrumentableProxies[ i ].saveState();
838             if ( childState != null )
839             {
840                 state.addChild( childState );
841             }
842         }
843
844         return state;
845     }
846
847     /*---------------------------------------------------------------
848      * Instrumentable Methods
849      *-------------------------------------------------------------*/

850     /**
851      * Sets the name for the Instrumentable. The Instrumentable Name is used
852      * to uniquely identify the Instrumentable during the configuration of
853      * the InstrumentManager and to gain access to an InstrumentableDescriptor
854      * through the InstrumentManager. The value should be a string which does
855      * not contain spaces or periods.
856      * <p>
857      * This value may be set by a parent Instrumentable, or by the
858      * InstrumentManager using the value of the 'instrumentable' attribute in
859      * the configuration of the component.
860      *
861      * @param name The name used to identify a Instrumentable.
862      */

863     public void setInstrumentableName( String JavaDoc name )
864     {
865         m_instrumentableName = name;
866     }
867
868     /**
869      * Gets the name of the Instrumentable.
870      *
871      * @return The name used to identify a Instrumentable.
872      */

873     public String JavaDoc getInstrumentableName()
874     {
875         return m_instrumentableName;
876     }
877
878     /**
879      * Obtain a reference to all the Instruments that the Instrumentable object
880      * wishes to expose. All sampling is done directly through the
881      * Instruments as opposed to the Instrumentable interface.
882      *
883      * @return An array of the Instruments available for profiling. Should
884      * never be null. If there are no Instruments, then
885      * EMPTY_INSTRUMENT_ARRAY can be returned. This should never be
886      * the case though unless there are child Instrumentables with
887      * Instruments.
888      */

889     public Instrument[] getInstruments()
890     {
891         return new Instrument[]
892         {
893             m_totalMemoryInstrument,
894             m_freeMemoryInstrument,
895             m_memoryInstrument,
896             m_activeThreadCountInstrument
897         };
898     }
899
900     /**
901      * Any Object which implements Instrumentable can also make use of other
902      * Instrumentable child objects. This method is used to tell the
903      * InstrumentManager about them.
904      *
905      * @return An array of child Instrumentables. This method should never
906      * return null. If there are no child Instrumentables, then
907      * EMPTY_INSTRUMENTABLE_ARRAY can be returned.
908      */

909     public Instrumentable[] getChildInstrumentables()
910     {
911         return Instrumentable.EMPTY_INSTRUMENTABLE_ARRAY;
912     }
913
914     /*---------------------------------------------------------------
915      * Runnable Methods
916      *-------------------------------------------------------------*/

917     public void run()
918     {
919         while( m_runner != null )
920         {
921             try
922             {
923                 Thread.sleep( 1000 );
924
925                 memoryInstruments();
926                 threadInstruments();
927                 testInstrumentSampleLeases();
928
929                 // Handle the state file if it is set
930
long now = System.currentTimeMillis();
931                 if( now - m_lastStateSave >= m_stateInterval )
932                 {
933                     saveState();
934                 }
935             }
936             catch( Throwable JavaDoc t )
937             {
938                 getLogger().error( "Encountered an unexpected error.", t );
939             }
940         }
941     }
942
943     /*---------------------------------------------------------------
944      * Methods
945      *-------------------------------------------------------------*/

946     /**
947      * Saves the state to the current state file if configured.
948      */

949     private void saveState()
950     {
951         long now = System.currentTimeMillis();
952
953         // Always set the time even if the save fails so that we don't thrash
954
m_lastStateSave = now;
955
956         if( m_stateFile == null )
957         {
958             return;
959         }
960         
961         try
962         {
963             saveStateToFile( m_stateFile );
964         }
965         catch ( Exception JavaDoc e )
966         {
967             getLogger().warn( "Unable to save the Instrument Manager state", e );
968         }
969     }
970
971     /**
972      * Returns a InstrumentableDescriptor based on its name or the name of any
973      * of its children.
974      *
975      * @param instrumentableName Name of the Instrumentable being requested.
976      *
977      * @return A Proxy of the requested Instrumentable or null if not found.
978      */

979     private InstrumentableProxy getInstrumentableProxy( String JavaDoc instrumentableName )
980     {
981         String JavaDoc name = instrumentableName;
982         while( true )
983         {
984             InstrumentableProxy proxy = (InstrumentableProxy)m_instrumentableProxies.get( name );
985             if( proxy != null )
986             {
987                 return proxy;
988             }
989
990             // Assume this is a child name and try looking with the parent name.
991
int pos = name.lastIndexOf( '.' );
992             if( pos > 0 )
993             {
994                 name = name.substring( 0, pos );
995             }
996             else
997             {
998                 return null;
999             }
1000        }
1001    }
1002    
1003    /**
1004     * Given the name of an instrumentable proxy, locate the deepest child
1005     * instrumentable given the name. The name can be the name of an
1006     * instrumentable or of any of its children.
1007     *
1008     * @param instrumentableName Fully qualified name of the instrumentable
1009     * being requested, or of any of its children.
1010     *
1011     * @return The requested instrumentable, or null if not found.
1012     */

1013    private InstrumentableProxy locateDeepestInstrumentableProxy( String JavaDoc instrumentableName )
1014    {
1015        InstrumentableProxy deepestProxy = null;
1016        // Start by obtaining a top level instrumentable
1017
InstrumentableProxy proxy = getInstrumentableProxy( instrumentableName );
1018        
1019        // Now attempt to locate a child instrumentable
1020
while ( proxy != null )
1021        {
1022            deepestProxy = proxy;
1023            
1024            proxy = deepestProxy.getChildInstrumentableProxy( instrumentableName );
1025        }
1026        
1027        return deepestProxy;
1028    }
1029
1030    /**
1031     * Updates the Memory based Profile Points published by the InstrumentManager.
1032     */

1033    private void memoryInstruments()
1034    {
1035        // Avoid doing unneeded work if profile points are not being used.
1036
Runtime JavaDoc runtime = null;
1037        long totalMemory = -1;
1038        long freeMemory = -1;
1039
1040        // Total Memory
1041
if( m_totalMemoryInstrument.isActive() )
1042        {
1043            runtime = Runtime.getRuntime();
1044            totalMemory = runtime.totalMemory();
1045            m_totalMemoryInstrument.setValue( (int)totalMemory );
1046        }
1047
1048        // Free Memory
1049
if( m_freeMemoryInstrument.isActive() )
1050        {
1051            if( runtime == null )
1052            {
1053                runtime = Runtime.getRuntime();
1054            }
1055            freeMemory = runtime.freeMemory();
1056            m_freeMemoryInstrument.setValue( (int)freeMemory );
1057        }
1058
1059        // In use Memory
1060
if( m_memoryInstrument.isActive() )
1061        {
1062            if( runtime == null )
1063            {
1064                runtime = Runtime.getRuntime();
1065            }
1066            if( totalMemory < 0 )
1067            {
1068                totalMemory = runtime.totalMemory();
1069            }
1070            if( freeMemory < 0 )
1071            {
1072                freeMemory = runtime.freeMemory();
1073            }
1074            m_memoryInstrument.setValue( (int)( totalMemory - freeMemory ) );
1075        }
1076    }
1077
1078    /**
1079     * Updates the Thread based Profile Points published by the InstrumentManager.
1080     */

1081    private void threadInstruments()
1082    {
1083        if( m_activeThreadCountInstrument.isActive() )
1084        {
1085            // Get the top level thread group.
1086
ThreadGroup JavaDoc threadGroup = Thread.currentThread().getThreadGroup();
1087            ThreadGroup JavaDoc parent;
1088            while( ( parent = threadGroup.getParent() ) != null )
1089            {
1090                threadGroup = parent;
1091            }
1092
1093            m_activeThreadCountInstrument.setValue( threadGroup.activeCount() );
1094        }
1095    }
1096    
1097    /**
1098     * Handles the maintenance of all Instrument Samples which have been leased
1099     * by a client. Any Samples whose leases which have expired are cleaned
1100     * up.
1101     */

1102    private void testInstrumentSampleLeases()
1103    {
1104        long now = System.currentTimeMillis();
1105        
1106        InstrumentSample[] samples;
1107        synchronized( m_leasedInstrumentSamples )
1108        {
1109            samples = m_leasedInstrumentSampleArray;
1110            if ( samples == null )
1111            {
1112                m_leasedInstrumentSampleArray =
1113                    new InstrumentSample[ m_leasedInstrumentSamples.size() ];
1114                m_leasedInstrumentSamples.toArray( m_leasedInstrumentSampleArray );
1115                samples = m_leasedInstrumentSampleArray;
1116            }
1117        }
1118        
1119        for ( int i = 0; i < samples.length; i++ )
1120        {
1121            InstrumentSample sample = samples[i];
1122            long expire = sample.getLeaseExpirationTime();
1123            if ( now >= expire )
1124            {
1125                // The sample lease has expired.
1126
InstrumentProxy instrument = sample.getInstrumentProxy();
1127                instrument.removeInstrumentSample( sample );
1128                sample.expire();
1129                
1130                m_leasedInstrumentSamples.remove( sample );
1131                m_leasedInstrumentSampleArray = null;
1132            }
1133        }
1134    }
1135    
1136    /**
1137     * Registers an InstrumentSample which has been leased so that the
1138     * Instrument Manager can efficiently purge it when it has expired.
1139     *
1140     * @param instrumentSample Leased InstrumentSample to register.
1141     */

1142    void registerLeasedInstrumentSample( InstrumentSample instrumentSample )
1143    {
1144        synchronized( m_leasedInstrumentSamples )
1145        {
1146            // Make sure that the sample is really leased.
1147
if ( instrumentSample.getLeaseExpirationTime() <= 0 )
1148            {
1149                throw new IllegalStateException JavaDoc( "Got an InstrumentSample that was not leased." );
1150            }
1151            
1152            // Make sure that it is not already in the list.
1153
if ( m_leasedInstrumentSamples.indexOf( instrumentSample ) < 0 )
1154            {
1155                m_leasedInstrumentSamples.add( instrumentSample );
1156                m_leasedInstrumentSampleArray = null;
1157            }
1158        }
1159    }
1160    
1161    /**
1162     * Updates the cached array of InstrumentableProxies taking
1163     * synchronization into account.
1164     *
1165     * @return An array of the InstrumentableProxies.
1166     */

1167    private InstrumentableProxy[] updateInstrumentableProxyArray()
1168    {
1169        synchronized( m_semaphore )
1170        {
1171            m_instrumentableProxyArray = new InstrumentableProxy[ m_instrumentableProxies.size() ];
1172            m_instrumentableProxies.values().toArray( m_instrumentableProxyArray );
1173
1174            // Sort the array. This is not a performance problem because this
1175
// method is rarely called and doing it here saves cycles in the
1176
// client.
1177
Arrays.sort( m_instrumentableProxyArray, new Comparator JavaDoc()
1178                {
1179                    public int compare( Object JavaDoc o1, Object JavaDoc o2 )
1180                    {
1181                        return ((InstrumentableProxy)o1).getDescription().
1182                            compareTo( ((InstrumentableProxy)o2).getDescription() );
1183                    }
1184                    
1185                    public boolean equals( Object JavaDoc obj )
1186                    {
1187                        return false;
1188                    }
1189                } );
1190            
1191            return m_instrumentableProxyArray;
1192        }
1193    }
1194
1195    /**
1196     * Updates the cached array of InstrumentableDescriptorLocals taking
1197     * synchronization into account.
1198     *
1199     * @return An array of the InstrumentableDescriptors.
1200     */

1201    private InstrumentableDescriptorLocal[] updateInstrumentableDescriptorArray()
1202    {
1203        synchronized( m_semaphore )
1204        {
1205            if( m_instrumentableProxyArray == null )
1206            {
1207                updateInstrumentableProxyArray();
1208            }
1209
1210            m_instrumentableDescriptorArray =
1211                new InstrumentableDescriptorLocal[ m_instrumentableProxyArray.length ];
1212            for( int i = 0; i < m_instrumentableProxyArray.length; i++ )
1213            {
1214                m_instrumentableDescriptorArray[ i ] = m_instrumentableProxyArray[ i ].getDescriptor();
1215            }
1216
1217            return m_instrumentableDescriptorArray;
1218        }
1219    }
1220
1221    /**
1222     * Called as a place holder to handle the registration of instrumentables
1223     * that do not really exist. This makes it possible to register
1224     * instrumentables at arbitrary locations in the instrumentable hierarchy.
1225     *
1226     * @param instrumentable The instrumentable that was registered below a dummy
1227     * parent.
1228     * @param instrumentableProxy The proxy assigned to the current placeholder
1229     * instrumentable.
1230     * @param instrumentableName The name of the current placeholder
1231     * instrumentable.
1232     * @param childName The name of the child instrumentable to register. May
1233     * contain further '.' characters.
1234     */

1235    private void registerDummyInstrumentableInner( Instrumentable instrumentable,
1236                                                   InstrumentableProxy instrumentableProxy,
1237                                                   String JavaDoc instrumentableName,
1238                                                   String JavaDoc childName )
1239        throws Exception JavaDoc
1240    {
1241        // If the specified instrumentable name contains '.' chars then we need to
1242
// make sure we register the instrumentable at the correct location, creating
1243
// any parent instrumentables as necessary.
1244
int pos = childName.indexOf( '.' );
1245        if ( pos >= 0 )
1246        {
1247            String JavaDoc newParentName = childName.substring( 0, pos );
1248            String JavaDoc newChildName =
1249                childName.substring( pos + 1 );
1250            
1251            String JavaDoc fullChildName = instrumentableName + "." + newParentName;
1252            
1253            getLogger().debug( "Registering Child Instrumentable: " + fullChildName );
1254            
1255            // See if a proxy exists for the child Instrumentable yet.
1256
InstrumentableProxy proxy =
1257                instrumentableProxy.getChildInstrumentableProxy( fullChildName );
1258            if( proxy == null )
1259            {
1260                proxy = new InstrumentableProxy(
1261                    this, instrumentableProxy, fullChildName, newParentName );
1262                proxy.enableLogging( getLogger() );
1263                
1264                instrumentableProxy.addChildInstrumentableProxy( proxy );
1265            }
1266            
1267            // Recurse to the child
1268
registerDummyInstrumentableInner( instrumentable, proxy, fullChildName, newChildName );
1269        }
1270        else
1271        {
1272            // The child does not contain and '.' characters, so we are at the correct location.
1273
String JavaDoc fullChildName = instrumentableName + "." + childName;
1274            
1275            getLogger().debug( "Registering Child Instrumentable: " + fullChildName );
1276            
1277            // See if a proxy exists for the child Instrumentable yet.
1278
InstrumentableProxy proxy =
1279                instrumentableProxy.getChildInstrumentableProxy( fullChildName );
1280            if( proxy == null )
1281            {
1282                proxy = new InstrumentableProxy(
1283                    this, instrumentableProxy, fullChildName, childName );
1284                proxy.enableLogging( getLogger() );
1285                
1286                instrumentableProxy.addChildInstrumentableProxy( proxy );
1287            }
1288            
1289            // Recurse to the child
1290
registerInstrumentableInner( instrumentable, proxy, fullChildName );
1291        }
1292    }
1293
1294    /**
1295     * Examines a instrumentable and Registers all of its child Instrumentables
1296     * and Instruments.
1297     * <p>
1298     * Only called when m_semaphore is locked.
1299     */

1300    private void registerInstrumentableInner( Instrumentable instrumentable,
1301                                              InstrumentableProxy instrumentableProxy,
1302                                              String JavaDoc instrumentableName )
1303        throws Exception JavaDoc
1304    {
1305        // Mark the instrumentable proxy as registered.
1306
instrumentableProxy.setRegistered();
1307
1308        // Loop over the Instruments published by this Instrumentable
1309
Instrument[] instruments = instrumentable.getInstruments();
1310        for( int i = 0; i < instruments.length; i++ )
1311        {
1312            Instrument instrument = instruments[ i ];
1313            String JavaDoc instrumentName = instrument.getInstrumentName();
1314            String JavaDoc fullInstrumentName = instrumentableName + "." + instrumentName;
1315
1316            getLogger().debug( "Registering Instrument: " + fullInstrumentName );
1317
1318            // See if a proxy exists for the Instrument yet.
1319
InstrumentProxy proxy = instrumentableProxy.getInstrumentProxy( fullInstrumentName );
1320            if( proxy == null )
1321            {
1322                proxy = new InstrumentProxy(
1323                    instrumentableProxy, fullInstrumentName, instrumentName );
1324                proxy.enableLogging( getLogger() );
1325
1326                // Set the type of the new InstrumentProxy depending on the
1327
// class of the actual Instrument.
1328
if( instrument instanceof CounterInstrument )
1329                {
1330                    proxy.setType( InstrumentManagerClient.INSTRUMENT_TYPE_COUNTER );
1331                }
1332                else if( instrument instanceof ValueInstrument )
1333                {
1334                    proxy.setType( InstrumentManagerClient.INSTRUMENT_TYPE_VALUE );
1335                }
1336                else
1337                {
1338                    throw new ServiceException( fullInstrumentName, "Encountered an unknown "
1339                        + "Instrument type for the Instrument with key, "
1340                        + fullInstrumentName + ": " + instrument.getClass().getName() );
1341                }
1342
1343                // Mark the instrument proxy as registered.
1344
proxy.setRegistered();
1345                
1346                // Store a reference to the proxy in the Instrument.
1347
( (AbstractInstrument)instrument ).setInstrumentProxy( proxy );
1348
1349                instrumentableProxy.addInstrumentProxy( proxy );
1350            }
1351            else
1352            {
1353                // Register the existing proxy with the Instrument. Make sure that the
1354
// type didn't change on us.
1355
if( instrument instanceof CounterInstrument )
1356                {
1357                    switch( proxy.getType() )
1358                    {
1359                        case InstrumentManagerClient.INSTRUMENT_TYPE_COUNTER:
1360                            // Type is the same.
1361
// Store a reference to the proxy in the Instrument.
1362
( (AbstractInstrument)instrument ).setInstrumentProxy( proxy );
1363                            break;
1364
1365                        case InstrumentManagerClient.INSTRUMENT_TYPE_NONE:
1366                            // Not yet set. Created in configuration.
1367
proxy.setType( InstrumentManagerClient.INSTRUMENT_TYPE_COUNTER );
1368
1369                            // Store a reference to the proxy in the Instrument.
1370
( (AbstractInstrument)instrument ).setInstrumentProxy( proxy );
1371                            break;
1372
1373                        default:
1374                            throw new ServiceException( instrumentName,
1375                                "Instruments of more than one type are assigned to name: "
1376                                + instrumentName );
1377                    }
1378                }
1379                else if( instrument instanceof ValueInstrument )
1380                {
1381                    switch( proxy.getType() )
1382                    {
1383                        case InstrumentManagerClient.INSTRUMENT_TYPE_VALUE:
1384                            // Type is the same.
1385
// Store a reference to the proxy in the Instrument.
1386
( (AbstractInstrument)instrument ).setInstrumentProxy( proxy );
1387                            break;
1388
1389                        case InstrumentManagerClient.INSTRUMENT_TYPE_NONE:
1390                            // Not yet set. Created in configuration.
1391
proxy.setType( InstrumentManagerClient.INSTRUMENT_TYPE_VALUE );
1392
1393                            // Store a reference to the proxy in the Instrument.
1394
( (AbstractInstrument)instrument ).setInstrumentProxy( proxy );
1395                            break;
1396
1397                        default:
1398                            throw new ServiceException( instrumentName,
1399                                "Instruments of more than one type are assigned to name: "
1400                                + instrumentName );
1401                    }
1402                }
1403                else
1404                {
1405                    throw new ServiceException( instrumentName, "Encountered an unknown Instrument "
1406                        + "type for the Instrument with name, " + instrumentName + ": "
1407                        + instrument.getClass().getName() );
1408                }
1409                
1410                // Mark the instrument proxy as registered.
1411
proxy.setRegistered();
1412            }
1413        }
1414
1415        // Loop over the child Instrumentables published by this Instrumentable
1416
Instrumentable[] children = instrumentable.getChildInstrumentables();
1417        for ( int i = 0; i < children.length; i++ )
1418        {
1419            Instrumentable child = children[i];
1420            
1421            // Make sure that the child instrumentable name is set.
1422
String JavaDoc childName = child.getInstrumentableName();
1423            if( childName == null )
1424            {
1425                String JavaDoc msg = "The getInstrumentableName() method of a child Instrumentable of " +
1426                    instrumentableName + " returned null. Child class: " +
1427                    child.getClass().getName();
1428                getLogger().debug( msg );
1429                throw new ServiceException( instrumentable.getClass().getName(), msg );
1430            }
1431            
1432            String JavaDoc fullChildName = instrumentableName + "." + childName;
1433            
1434            getLogger().debug( "Registering Child Instrumentable: " + fullChildName );
1435            
1436            // See if a proxy exists for the child Instrumentable yet.
1437
InstrumentableProxy proxy =
1438                instrumentableProxy.getChildInstrumentableProxy( fullChildName );
1439            if( proxy == null )
1440            {
1441                proxy = new InstrumentableProxy(
1442                    this, instrumentableProxy, fullChildName, childName );
1443                proxy.enableLogging( getLogger() );
1444                
1445                instrumentableProxy.addChildInstrumentableProxy( proxy );
1446            }
1447            
1448            // Recurse to the child
1449
registerInstrumentableInner( child, proxy, fullChildName );
1450        }
1451    }
1452    
1453    /**
1454     * Called whenever the state of the instrument manager is changed.
1455     */

1456    protected void stateChanged()
1457    {
1458        m_stateVersion++;
1459    }
1460}
1461
1462
Popular Tags