001/*
002 * ============================================================================
003 * Copyright © 2002-2026 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 *
007 * Licensed to the public under the agreements of the GNU Lesser General Public
008 * License, version 3.0 (the "License"). You may obtain a copy of the License at
009 *
010 *      http://www.gnu.org/licenses/lgpl.html
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015 * License for the specific language governing permissions and limitations
016 * under the License.
017 */
018
019package org.tquadrat.foundation.perflog;
020
021import static java.lang.Boolean.getBoolean;
022import static java.lang.management.ManagementFactory.getPlatformMBeanServer;
023import static javax.management.MBeanServerFactory.createMBeanServer;
024import static org.apiguardian.api.API.Status.STABLE;
025import static org.tquadrat.foundation.lang.Objects.isNull;
026import static org.tquadrat.foundation.lang.Objects.nonNull;
027import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
028import static org.tquadrat.foundation.perflog.PerformanceTracker.TrackerStatus.STATUS_READY;
029
030import javax.management.MBeanServer;
031import javax.management.MBeanServerFactory;
032import javax.management.ObjectName;
033import java.lang.Thread.UncaughtExceptionHandler;
034import java.util.Optional;
035
036import org.apiguardian.api.API;
037import org.tquadrat.foundation.annotation.ClassVersion;
038import org.tquadrat.foundation.annotation.UtilityClass;
039import org.tquadrat.foundation.exception.PrivateConstructorForStaticClassCalledError;
040import org.tquadrat.foundation.lang.StringConverter;
041import org.tquadrat.foundation.perflog.internal.PerfLogManagerImpl;
042import org.tquadrat.foundation.perflog.internal.PerformanceSectionNameImpl;
043import org.tquadrat.foundation.perflog.internal.PerformanceTrackerImpl;
044import org.tquadrat.foundation.perflog.remote.PerfLogRemote;
045
046/**
047 *  <p>{@summary Several tools for the Foundation Performance Logging and
048 *  Monitoring.}</p>
049 *
050 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
051 *  @version $Id: PerfLogUtils.java 1258 2026-06-04 18:33:06Z tquadrat $
052 *  @since 0.25.0
053 *
054 *  @UMLGraph.link
055 */
056@ClassVersion( sourceVersion = "$Id: PerfLogUtils.java 1258 2026-06-04 18:33:06Z tquadrat $" )
057@API( status = STABLE, since = "0.25.0" )
058@UtilityClass
059public final class PerfLogUtils
060{
061        /*---------------*\
062    ====** Inner Classes **====================================================
063        \*---------------*/
064    /**
065     *  <p>{@summary A holder for
066     *  {@link PerformanceTracker}
067     *  that allows to use it with try-with-resources.}</p>
068     *
069     *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
070     *  @version $Id: PerfLogUtils.java 1258 2026-06-04 18:33:06Z tquadrat $
071     *  @since 0.25.0
072     *
073     *  @UMLGraph.link
074     */
075    @ClassVersion( sourceVersion = "$Id: PerfLogUtils.java 1258 2026-06-04 18:33:06Z tquadrat $" )
076    @API( status = STABLE, since = "0.25.0" )
077    public static final class PerformanceTrackerHolder implements AutoCloseable, PerformanceTracker
078    {
079            /*------------*\
080        ====** Attributes **====================================================
081            \*------------*/
082        /**
083         *  The flag that indicates whether
084         *  {@link #close()}
085         *  was already called on this instance.
086         */
087        private boolean m_IsClosed = false;
088
089        /**
090         *  <p>{@summary The reference to a volatile instance of
091         *  {@link PerfLogManager}.}</p>
092         *  <p>It is kept here to prevent it from prematurely being garbage
093         *  collected.</p>
094         */
095        private PerfLogManager m_Manager;
096
097        /**
098         *  <p>{@summary The wrapped instance of
099         *  {@link PerformanceTracker}.}</p>
100         *  <p>It can be {@null}.</p>
101         */
102        private final PerformanceTracker m_Tracker;
103
104            /*--------------*\
105        ====** Constructors **=================================================
106            \*--------------*/
107        /**
108         *  <p>{@summary Creates a new instance of
109         *  {@code PerformanceTrackerHolder} that holds an instance of
110         *  {@link PerformanceTracker}.}</p>
111         *
112         *  @param  tracker The tracker instance to wrap.
113         *  @throws ClassCastException  If called with an instance of
114         *      {@code Holder}.
115         */
116        private PerformanceTrackerHolder( final PerformanceTrackerImpl tracker )
117        {
118            m_Tracker = requireNonNullArgument( tracker, "tracker" );
119            m_Manager = null;
120        }   //  PerformanceTrackerHolder()
121
122        /**
123         *  <p>{@summary Creates a new instance of
124         *  {@code PerformanceTrackerHolder} that holds an instance of
125         *  {@link PerformanceTracker}, created by calling
126         *  {@link PerfLogManager#createPerformanceTracker(PerformanceSectionName)}
127         *  on the given
128         *  {@link PerfLogManager}
129         *  instance with the given
130         *  {@link PerformanceSectionName}.}</p>
131         *
132         *  @param  manager The Performance Logging manager.
133         *  @param  name    The performance section name.
134         */
135        private PerformanceTrackerHolder( final PerfLogManager manager, final PerformanceSectionName name )
136        {
137            final var trackerOptional = requireNonNullArgument( manager, "manager" ).createPerformanceTracker( name );
138            if( trackerOptional.isEmpty() )
139            {
140                m_Tracker = null;
141                m_Manager = null;
142            }
143            else
144            {
145                m_Tracker = trackerOptional.get();
146                m_Manager = manager;
147            }
148        }   //  PerformanceTrackerHolder()
149
150        /**
151         *  Creates a new instance of {@code PerformanceTrackerHolder} that
152         *  does not hold an instance of
153         *  {@link PerformanceTracker}.
154         */
155        private PerformanceTrackerHolder()
156        {
157            m_Tracker = null;
158            m_Manager = null;
159        }   //  PerformanceTrackerHolder()
160
161            /*---------*\
162        ====** Methods **======================================================
163            \*---------*/
164        /**
165         *  {@inheritDoc}
166         */
167        @Override
168        public final  void abort()
169        {
170            if( nonNull( m_Tracker ) ) m_Tracker.abort();
171        }   //  abort()
172
173        /**
174         *  {@inheritDoc}
175         */
176        @Override
177        public void abort( final String message )
178        {
179            if( nonNull( m_Tracker ) ) m_Tracker.abort( message );
180        }   //  abort()
181
182        /**
183         *  {@inheritDoc}
184         */
185        @Override
186        public void abort( final String message, final Throwable cause )
187        {
188            if( nonNull( m_Tracker ) ) m_Tracker.abort( message, cause );
189        }   //  abort()
190
191        /**
192         *  {@inheritDoc}
193         */
194        @Override
195        public final PerformanceTracker addContext( final String name, final String value )
196        {
197            if( nonNull( m_Tracker ) ) m_Tracker.addContext( name, value );
198
199            //---* Done *------------------------------------------------------
200            return this;
201        }   //  addContext()
202
203        /**
204         *  {@inheritDoc}
205         */
206        @Override
207        public final <T> PerformanceTracker addContext( final String name, final T value, final StringConverter<T> stringConverter )
208        {
209            if( nonNull( m_Tracker ) ) m_Tracker.addContext( name, value, stringConverter );
210
211            //---* Done *------------------------------------------------------
212            return this;
213        }   //  addContext()
214
215        /**
216         *  {@inheritDoc}
217         */
218        @Override
219        public final void close()
220        {
221            if( isActive() )
222            {
223                stop();
224            }
225            else
226            {
227                abort();
228            }
229            m_IsClosed = true;
230            if( nonNull( m_Manager ) )
231            {
232                m_Manager.close();
233                m_Manager = null;
234            }
235        }   //  close()
236
237        /**
238         *  {@inheritDoc}
239         */
240        @Override
241        public final TrackerStatus getStatus()
242        {
243            final var retValue = isNull( m_Tracker ) ? STATUS_READY : m_Tracker.getStatus();
244
245            //---* Done *------------------------------------------------------
246            return retValue;
247        }   //  getStatus()
248
249        /**
250         *  {@inheritDoc}
251         *  <p>Throws also an
252         *  {@link IllegalStateException}
253         *  if this instance of {@code PerformanceTrackerHolder} was already
254         *  closed.</p>
255         */
256        @Override
257        public final PerformanceTracker reset( final boolean resetContext ) throws IllegalArgumentException
258        {
259            if( m_IsClosed ) throw new IllegalStateException( "Holder was already closed" );
260            if( nonNull( m_Tracker ) ) m_Tracker.reset( resetContext );
261
262            //---* Done *------------------------------------------------------
263            return this;
264        }   //  reset()
265
266        /**
267         *  {@inheritDoc}
268         */
269        @Override
270        public final void start() throws IllegalArgumentException
271        {
272            if( nonNull( m_Tracker ) ) m_Tracker.start();
273        }   //  start()
274
275        /**
276         *  {@inheritDoc}
277         */
278        @Override
279        public final void stop() throws IllegalArgumentException
280        {
281            if( nonNull( m_Tracker ) ) m_Tracker.stop();
282        }   //  stop()
283    }
284    //  class PerformanceTrackerHolder
285
286        /*-----------*\
287    ====** Constants **========================================================
288        \*-----------*/
289    /**
290     *  <p>{@summary The domain name part of the
291     *  {@link ObjectName}
292     *  identifying the
293     *  {@link PerfLogMBean}
294     *  in the MBean server: {@value PerfLogRemote#DOMAIN_NAME}}.</p>
295     *  <p>It is also used for the creation of the MBean server, if a dedicated
296     *  MBean server is needed; usually the Platform MBean server is used.</p>
297     *
298     *  @see javax.management.MBeanServerFactory#createMBeanServer(String)
299     *  @see java.lang.management.ManagementFactory#getPlatformMBeanServer
300     */
301    public static final String DOMAIN_NAME = PerfLogRemote.DOMAIN_NAME;
302
303    /**
304     *  The type for the
305     *  {@link ObjectName}
306     *  identifying the
307     *  {@link PerfLogMBean}
308     *  in the MBean server: {@value PerfLogRemote#MBEAN_TYPE}.
309     */
310    public static final String MBEAN_TYPE = PerfLogRemote.MBEAN_TYPE;
311
312    /**
313     *  <p>{@summary The name of the system property that controls whether to
314     *  use a dedicated
315     *  {@link MBeanServer}: {@value}.}</p>
316     *  <p>If not provided or set to {@false}, the platform MBean server
317     *  is used.</p>
318     *
319     *  @see java.lang.management.ManagementFactory#getPlatformMBeanServer
320     */
321    @SuppressWarnings( "FieldNamingConvention" )
322    public static final String SYSTEM_PROPERTY_UsedDedicatedMBeanServer = "org.tquadrat.foundation.perflog.UseDedicatedMBeanServer";
323
324        /*--------------*\
325    ====** Constructors **=====================================================
326        \*--------------*/
327    /**
328     *  Not instance allowed for this class!
329     */
330    private PerfLogUtils() { throw new PrivateConstructorForStaticClassCalledError( PerfLogUtils.class ); }
331
332        /*---------*\
333    ====** Methods **==========================================================
334        \*---------*/
335    /**
336     *  <p>{@summary Creates an instance of
337     *  {@link PerfLogManager}
338     *  that handles the connection with the underlying
339     *  {@link PerfLogMBean}.}</p>
340     *  <p>When called multiple times with references to different
341     *  {@linkplain MBeanServer MBean servers},
342     *  each of these calls will create a new instance of
343     *  {@link PerfLogMBean}.</p>
344     *
345     *  @param  mbeanServer The MBean server that holds the
346     *      {@code PerfLogMBean}.
347     *  @return The new performance logging manager.
348     *
349     *  @see #createPerfLogManager()
350     *  @see #createPerfLogManager(UncaughtExceptionHandler)
351     *  @see #obtainMBeanServer()
352     */
353    public static final PerfLogManager createPerfLogManager( final MBeanServer mbeanServer )
354    {
355        final var retValue = new PerfLogManagerImpl( requireNonNullArgument( mbeanServer, "mbeanServer" ), getPerfLogMBeanObjectName() );
356
357        //---* Done *----------------------------------------------------------
358        return retValue;
359    }   //  createPerfLogManager()
360
361    /**
362     *  <p>{@summary Creates an instance of
363     *  {@link PerfLogManager}
364     *  that handles the connection with the underlying
365     *  {@link PerfLogMBean}.}</p>
366     *  <p>When called multiple times with references to different
367     *  {@linkplain MBeanServer MBean servers},
368     *  each of these calls will create a new instance of
369     *  {@link PerfLogMBean}.</p>
370     *
371     *  @param  mbeanServer The MBean server that holds the
372     *      {@code PerfLogMBean}.
373     *  @param  uncaughtExceptionHandler    The implementation of
374     *      {@link Thread.UncaughtExceptionHandler}
375     *      that is used for the timeout monitoring thread.
376     *  @return The new performance logging manager.
377     *
378     *  @see #createPerfLogManager()
379     *  @see #createPerfLogManager(UncaughtExceptionHandler)
380     *  @see #obtainMBeanServer()
381     */
382    @SuppressWarnings( "MethodParameterNamingConvention" )
383    public static final PerfLogManager createPerfLogManager( final MBeanServer mbeanServer, final UncaughtExceptionHandler uncaughtExceptionHandler )
384    {
385        final var retValue = new PerfLogManagerImpl( requireNonNullArgument( mbeanServer, "mbeanServer" ), getPerfLogMBeanObjectName(), uncaughtExceptionHandler );
386
387        //---* Done *----------------------------------------------------------
388        return retValue;
389    }   //  createPerfLogManager()
390
391    /**
392     *  <p>{@summary Creates an instance of
393     *  {@link PerfLogManager}
394     *  that handles the connection with the underlying
395     *  {@link PerfLogMBean}.}</p>
396     *  <p>The method uses the
397     *  {@link MBeanServer}
398     *  that is returned from
399     *  {@link #obtainMBeanServer()}.</p>
400     *
401     *  @return The new performance logging manager.
402     */
403    public static final PerfLogManager createPerfLogManager()
404    {
405        final var mbeanServer = obtainMBeanServer();
406        final var retValue = createPerfLogManager( mbeanServer );
407
408        //---* Done *----------------------------------------------------------
409        return retValue;
410    }   //  createPerfLogManager()
411
412    /**
413     *  <p>{@summary Creates an instance of
414     *  {@link PerfLogManager}
415     *  that handles the connection with the underlying
416     *  {@link PerfLogMBean}.}</p>
417     *  <p>The method uses the
418     *  {@link MBeanServer}
419     *  that is returned from
420     *  {@link #obtainMBeanServer()}.</p>
421     *
422     *  @param  uncaughtExceptionHandler    The implementation of
423     *      {@link Thread.UncaughtExceptionHandler}
424     *      that is used for the timeout monitoring thread.
425     *
426     *  @return The new performance logging manager.
427     */
428    @SuppressWarnings( "MethodParameterNamingConvention" )
429    public static final PerfLogManager createPerfLogManager( final UncaughtExceptionHandler uncaughtExceptionHandler )
430    {
431        final var mbeanServer = obtainMBeanServer();
432        final var retValue = new PerfLogManagerImpl( mbeanServer, getPerfLogMBeanObjectName(), uncaughtExceptionHandler );
433
434        //---* Done *----------------------------------------------------------
435        return retValue;
436    }   //  createPerfLogManager()
437
438    /**
439     *  Creates a new instance for an implementation of
440     *  {@code PerformanceSectionName} based on the given value.
441     *
442     *  @param  value   The value for the new name.
443     *  @return The new name.
444     */
445    public static PerformanceSectionName createPerformanceSectionName( final String value )
446    {
447        final var retValue = new PerformanceSectionNameImpl( value );
448
449        //---* Done *----------------------------------------------------------
450        return retValue;
451    }   //  createPerformanceSectionName()
452
453    /**
454     *  Returns the
455     *  {@link ObjectName}
456     *  for the
457     *  {@link PerfLogMBean}.
458     *
459     *  @return The object name for the performance logging MBean.
460     */
461    public static final ObjectName getPerfLogMBeanObjectName() { return PerfLogRemote.getPerfLogMBeanObjectName(); }
462
463    /**
464     *  <p>{@summary Creates a holder for the given
465     *  {@link PerformanceTracker}.}</p>
466     *  <p>This is a convenience method that allows to use a performance
467     *  tracker with {@code try-with-resources}.</p>
468     *
469     *  @param  tracker An instance of
470     *      {@link Optional}
471     *      that holds the tracker.
472     *  @return A holder for the given tracker.
473     *  @throws ClassCastException  If called with an instance of
474     *      {@code Holder} instead of a raw
475     *      {@link PerformanceTracker}.
476     */
477    @SuppressWarnings( {"OptionalUsedAsFieldOrParameterType"} )
478    public static final PerformanceTrackerHolder hold( final Optional<? extends PerformanceTracker> tracker )
479    {
480        final var retValue = requireNonNullArgument( tracker, "tracker" ).map( v -> new PerformanceTrackerHolder( (PerformanceTrackerImpl) v ) ).orElseGet( PerformanceTrackerHolder::new );
481
482        //---* Done *----------------------------------------------------------
483        return retValue;
484    }   //  hold()
485
486    /**
487     *  <p>{@summary Creates a
488     *  {@link PerformanceTracker}
489     *  for the
490     *  {@link PerformanceSection}
491     *  with the given
492     *  {@linkplain PerformanceSectionName name}.}</p>
493     *  <p>It creates an instance of
494     *  {@link PerfLogManager}
495     *  on the fly, using the
496     *  {@link MBeanServer}
497     *  returned by
498     *  {@link #obtainMBeanServer()}.</p>
499     *  <p>This is a convenience method that allows to use a performance
500     *  tracker with {@code try-with-resources}.</p>
501     *
502     *  @param  name    The name of the performance section.
503     *  @return A holder for the given tracker.
504     */
505    public static final PerformanceTrackerHolder hold( final PerformanceSectionName name )
506    {
507        final var retValue = new PerformanceTrackerHolder( createPerfLogManager(), name );
508
509        //---* Done *----------------------------------------------------------
510        return retValue;
511    }   //  hold()
512
513    /**
514     *  <p>{@summary Creates a
515     *  {@link PerformanceTracker}
516     *  for the
517     *  {@link PerformanceSection}
518     *  with the given
519     *  {@linkplain PerformanceSectionName name}.}</p>
520     *  <p>This is a convenience method that allows to use a performance
521     *  tracker with {@code try-with-resources}.</p>
522     *
523     *  @param  manager The Performance Logging Manager that connects to the
524     *      {@link PerfLogMBean}.
525     *  @param  name    The name of the performance section.
526     *  @return A holder for the given tracker.
527     */
528    public static final PerformanceTrackerHolder hold(  final PerfLogManager manager, final PerformanceSectionName name )
529    {
530        final var retValue = hold( requireNonNullArgument( manager, "manager" ).createPerformanceTracker( name ) );
531
532        //---* Done *----------------------------------------------------------
533        return retValue;
534    }   //  hold()
535
536    /**
537     *  <p>{@summary Creates a
538     *  {@link PerformanceTracker}
539     *  for the
540     *  {@link PerformanceSection}
541     *  with the given name.}</p>
542     *  <p>It creates an instance of
543     *  {@link PerfLogManager}
544     *  on the fly, using the
545     *  {@link MBeanServer}
546     *  returned by
547     *  {@link #obtainMBeanServer()}.</p>
548     *  <p>This is a convenience method that allows to use a performance
549     *  tracker with {@code try-with-resources}.</p>
550     *
551     *  @param  value   The name of the performance section.
552     *  @return A holder for the given tracker.
553     */
554    public static final PerformanceTrackerHolder hold( final String value )
555    {
556        final var retValue = hold( createPerformanceSectionName( value ) );
557
558        //---* Done *----------------------------------------------------------
559        return retValue;
560    }   //  hold()
561
562    /**
563     *  <p>{@summary Creates a holder for the given
564     *  {@link PerformanceTracker}
565     *  and immediately starts it.}</p>
566     *  <p>This is a convenience method that allows to use a performance
567     *  tracker with {@code try-with-resources}.</p>
568     *
569     *  @param  tracker An instance of
570     *      {@link Optional}
571     *      that holds the tracker.
572     *  @return A holder for the given tracker.
573     */
574    @SuppressWarnings( "OptionalUsedAsFieldOrParameterType" )
575    public static final PerformanceTrackerHolder holdAndStart( final Optional<? extends PerformanceTracker> tracker )
576    {
577        final var retValue = hold( tracker );
578        retValue.start();
579
580        //---* Done *----------------------------------------------------------
581        return retValue;
582    }   //  holdAndStart()
583
584    /**
585     *  <p>{@summary Creates a
586     *  {@link PerformanceTracker}
587     *  for the
588     *  {@link PerformanceSection}
589     *  with the given
590     *  {@linkplain PerformanceSectionName name}
591     *  and immediately starts it.}</p>
592     *  <p>It creates an instance of
593     *  {@link PerfLogManager}
594     *  on the fly, using the
595     *  {@link MBeanServer}
596     *  returned by
597     *  {@link #obtainMBeanServer()}.</p>
598     *  <p>This is a convenience method that allows to use a performance
599     *  tracker with {@code try-with-resources}.</p>
600     *
601     *  @param  name    The name of the performance section.
602     *  @return A holder for the given tracker.
603     */
604    public static final PerformanceTrackerHolder holdAndStart( final PerformanceSectionName name )
605    {
606        final var retValue = hold( name );
607        retValue.start();
608
609        //---* Done *----------------------------------------------------------
610        return retValue;
611    }   //  holdAndStart()
612
613    /**
614     *  <p>{@summary Creates a
615     *  {@link PerformanceTracker}
616     *  for the
617     *  {@link PerformanceSection}
618     *  with the given
619     *  {@linkplain PerformanceSectionName name}
620     *  and immediately starts it.}</p>
621     *  <p>It creates an instance of
622     *  {@link PerfLogManager}
623     *  on the fly, using the
624     *  {@link MBeanServer}
625     *  returned by
626     *  {@link #obtainMBeanServer()}.</p>
627     *  <p>This is a convenience method that allows to use a performance
628     *  tracker with {@code try-with-resources}.</p>
629     *
630     *  @param  manager The Performance Logging Manager that connects to the
631     *      {@link PerfLogMBean}.
632     *  @param  name    The name of the performance section.
633     *  @return A holder for the given tracker.
634     */
635    public static final PerformanceTrackerHolder holdAndStart( final PerfLogManager manager, final PerformanceSectionName name )
636    {
637        final var retValue = hold( manager, name );
638        retValue.start();
639
640        //---* Done *----------------------------------------------------------
641        return retValue;
642    }   //  holdAndStart()
643
644    /**
645     *  <p>{@summary Creates a
646     *  {@link PerformanceTracker}
647     *  for the
648     *  {@link PerformanceSection}
649     *  with the given name and immediately starts it.}</p>
650     *  <p>It creates an instance of
651     *  {@link PerfLogManager}
652     *  on the fly, using the
653     *  {@link MBeanServer}
654     *  returned by
655     *  {@link #obtainMBeanServer()}.</p>
656     *  <p>This is a convenience method that allows to use a performance
657     *  tracker with {@code try-with-resources}.</p>
658     *
659     *  @param  value   The name of the performance section.
660     *  @return A holder for the given tracker.
661     */
662    public static final PerformanceTrackerHolder holdAndStart( final String value )
663    {
664        final var retValue = hold( value );
665        retValue.start();
666
667        //---* Done *----------------------------------------------------------
668        return retValue;
669    }   //  holdAndStart()
670
671    /**
672     *  <p>{@summary Retrieves the
673     *  {@link MBeanServer}
674     *  that is used for the registration of the
675     *  {@link PerfLogMBean}.}</p>
676     *  <p>If the system property
677     *  {@value #SYSTEM_PROPERTY_UsedDedicatedMBeanServer}
678     *  is set to {@true}, a dedicated MBean server for the domain
679     *  {@value PerfLogRemote#DOMAIN_NAME}
680     *  will be used, otherwise the MBean server that is returned by
681     *  {@link java.lang.management.ManagementFactory#getPlatformMBeanServer()}
682     *  is returned.</p>
683     *
684     *  @return The MBean server.
685     *
686     *  @see #SYSTEM_PROPERTY_UsedDedicatedMBeanServer
687     */
688    public static final MBeanServer obtainMBeanServer()
689    {
690        final MBeanServer retValue;
691        //noinspection AccessOfSystemProperties
692        if( getBoolean( SYSTEM_PROPERTY_UsedDedicatedMBeanServer ) )
693        {
694            retValue = MBeanServerFactory.findMBeanServer( null )
695                .stream()
696                .filter( mbs -> mbs.getDefaultDomain().equals( DOMAIN_NAME ) )
697                .findFirst()
698                .orElseGet( () -> createMBeanServer( DOMAIN_NAME ) );
699        }
700        else
701        {
702            retValue = getPlatformMBeanServer();
703        }
704
705        //---* Done *----------------------------------------------------------
706        return retValue;
707    }   //  obtainMBeanServer()
708}
709//  class PerfLogUtils
710
711/*
712 *  End of File
713 */