123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- /*
- * Password Management Servlets (PWM)
- * http://www.pwm-project.org
- *
- * Copyright (c) 2006-2009 Novell, Inc.
- * Copyright (c) 2009-2021 The PWM Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package password.pwm.svc;
- import password.pwm.PwmApplication;
- import password.pwm.PwmEnvironment;
- import password.pwm.bean.DomainID;
- import password.pwm.bean.SessionLabel;
- import password.pwm.error.ErrorInformation;
- import password.pwm.error.PwmError;
- import password.pwm.error.PwmException;
- import password.pwm.error.PwmUnrecoverableException;
- import password.pwm.util.java.StatisticCounterBundle;
- import password.pwm.util.java.TimeDuration;
- import password.pwm.util.logging.PwmLogger;
- import java.time.Instant;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import java.util.Map;
- import java.util.Objects;
- import java.util.concurrent.ConcurrentHashMap;
- public class PwmServiceManager
- {
- private static final PwmLogger LOGGER = PwmLogger.forClass( PwmServiceManager.class );
- private final DomainID domainID;
- private final PwmApplication pwmApplication;
- private final Map<PwmServiceEnum, PwmService> runningServices = new ConcurrentHashMap<>();
- private final List<PwmServiceEnum> availableServices;
- private final SessionLabel sessionLabel;
- private boolean initialized;
- public PwmServiceManager(
- final SessionLabel sessionLabel,
- final PwmApplication pwmApplication,
- final DomainID domainID,
- final List<PwmServiceEnum> services
- )
- {
- this.sessionLabel = sessionLabel;
- this.domainID = Objects.requireNonNull( domainID );
- this.availableServices = List.copyOf( services );
- this.pwmApplication = Objects.requireNonNull( pwmApplication );
- }
- private enum InitializationStats
- {
- starts,
- stops,
- restarts,
- }
- public PwmService getService( final PwmServiceEnum serviceClass )
- {
- return runningServices.get( serviceClass );
- }
- public void initAllServices()
- throws PwmUnrecoverableException
- {
- final Instant startTime = Instant.now();
- final boolean internalRuntimeInstance = pwmApplication.getPwmEnvironment().isInternalRuntimeInstance()
- || pwmApplication.getPwmEnvironment().getFlags().contains( PwmEnvironment.ApplicationFlag.CommandLineInstance );
- final String logVerb = initialized ? "restart" : "start";
- final StatisticCounterBundle<InitializationStats> statCounter = new StatisticCounterBundle<>( InitializationStats.class );
- LOGGER.trace( sessionLabel, () -> "beginning service " + logVerb + " process" );
- for ( final PwmServiceEnum serviceClassEnum : availableServices )
- {
- boolean serviceShouldBeRunning = true;
- if ( internalRuntimeInstance && !serviceClassEnum.isInternalRuntime() )
- {
- serviceShouldBeRunning = false;
- }
- if ( serviceShouldBeRunning )
- {
- if ( runningServices.containsKey( serviceClassEnum ) )
- {
- shutDownService( runningServices.get( serviceClassEnum ) );
- statCounter.increment( InitializationStats.restarts );
- }
- else
- {
- statCounter.increment( InitializationStats.starts );
- }
- final PwmService newServiceInstance = initService( serviceClassEnum );
- runningServices.put( serviceClassEnum, newServiceInstance );
- }
- else
- {
- if ( runningServices.containsKey( serviceClassEnum ) )
- {
- shutDownService( runningServices.get( serviceClassEnum ) );
- statCounter.increment( InitializationStats.stops );
- }
- }
- }
- initialized = true;
- LOGGER.trace( sessionLabel, () -> logVerb + "ed services, " + statCounter.debugStats(), TimeDuration.fromCurrent( startTime ) );
- }
- private String debugSvcType()
- {
- return ( domainID.isSystem() ? "system" : "domain" ) + " service";
- }
- private PwmService initService( final PwmServiceEnum pwmServiceEnum )
- throws PwmUnrecoverableException
- {
- final Instant startTime = Instant.now();
- final PwmService newServiceInstance;
- try
- {
- final Class<? extends PwmService> serviceClass = pwmServiceEnum.getPwmServiceClass();
- newServiceInstance = serviceClass.getDeclaredConstructor().newInstance();
- }
- catch ( final Exception e )
- {
- final String errorMsg = "unexpected error instantiating " + debugSvcType() + " class '" + pwmServiceEnum.name() + "', error: " + e;
- LOGGER.fatal( () -> errorMsg, e );
- throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_STARTUP_ERROR, errorMsg ) );
- }
- try
- {
- LOGGER.trace( sessionLabel, () -> "initializing service " + newServiceInstance.name() );
- newServiceInstance.init( pwmApplication, domainID );
- final TimeDuration startupDuration = TimeDuration.fromCurrent( startTime );
- LOGGER.debug( sessionLabel, () -> "completed initialization of " + debugSvcType()
- + " " + newServiceInstance.name()
- + ", status=" + newServiceInstance.status(), startupDuration );
- }
- catch ( final PwmException e )
- {
- LOGGER.warn( sessionLabel, () -> "error instantiating " + debugSvcType() + " class '" + newServiceInstance.name()
- + "', service will remain unavailable, error: " + e.getMessage() );
- }
- catch ( final Exception e )
- {
- String errorMsg = "unexpected error instantiating " + debugSvcType() + " class '" + newServiceInstance.name() + "', cannot load, error: " + e.getMessage();
- if ( e.getCause() != null )
- {
- errorMsg += ", cause: " + e.getCause();
- }
- final String errorMsgFinal = errorMsg;
- LOGGER.fatal( sessionLabel, () -> errorMsgFinal );
- throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_STARTUP_ERROR, errorMsg ) );
- }
- return newServiceInstance;
- }
- public void shutdownAllServices( )
- {
- if ( !initialized )
- {
- return;
- }
- final int serviceCount = availableServices.size();
- LOGGER.trace( sessionLabel, () -> "beginning to close " + serviceCount + " " + debugSvcType() + "s" );
- final Instant startTime = Instant.now();
- final List<PwmServiceEnum> reverseServiceList = new ArrayList<>( availableServices );
- Collections.reverse( reverseServiceList );
- for ( final PwmServiceEnum pwmServiceEnum : reverseServiceList )
- {
- if ( runningServices.containsKey( pwmServiceEnum ) )
- {
- shutDownService( runningServices.get( pwmServiceEnum ) );
- }
- }
- initialized = false;
- LOGGER.trace( sessionLabel, () -> "closed " + serviceCount + " " + debugSvcType() + "s", TimeDuration.fromCurrent( startTime ) );
- }
- private void shutDownService( final PwmService serviceInstance )
- {
- LOGGER.trace( sessionLabel, () -> "closing " + debugSvcType() + " " + serviceInstance.name() );
- try
- {
- final Instant startTime = Instant.now();
- serviceInstance.shutdown();
- final TimeDuration timeDuration = TimeDuration.fromCurrent( startTime );
- LOGGER.trace( sessionLabel, () -> "successfully closed " + debugSvcType() + " " + serviceInstance.name()
- + " (" + timeDuration.asCompactString() + ")" );
- }
- catch ( final Exception e )
- {
- LOGGER.error( sessionLabel, () -> "error closing " + debugSvcType() + " " + serviceInstance.name() + ": " + e.getMessage(), e );
- }
- }
- public List<PwmService> getRunningServices( )
- {
- return List.copyOf( this.runningServices.values() );
- }
- }
|