/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * 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 org.pentaho.di.core.lifecycle; import com.google.common.annotations.VisibleForTesting; import org.pentaho.di.core.exception.KettlePluginException; import org.pentaho.di.core.logging.LogChannel; import org.pentaho.di.core.plugins.LifecyclePluginType; import org.pentaho.di.core.plugins.PluginInterface; import org.pentaho.di.core.plugins.PluginRegistry; import org.pentaho.di.core.plugins.PluginTypeInterface; import org.pentaho.di.core.plugins.PluginTypeListener; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; public class LifecycleSupport { @VisibleForTesting protected static PluginRegistry registry = PluginRegistry.getInstance(); private Set<LifecycleListener> lifeListeners; private boolean started; private LifeEventHandler handler; public LifecycleSupport() { lifeListeners = Collections.synchronizedSet( loadPlugins( LifecyclePluginType.class, LifecycleListener.class ) ); final PluginRegistry registry = PluginRegistry.getInstance(); registry.addPluginListener( LifecyclePluginType.class, new PluginTypeListener() { public void pluginAdded( Object serviceObject ) { LifecycleListener listener = null; try { listener = (LifecycleListener) PluginRegistry.getInstance().loadClass( (PluginInterface) serviceObject ); } catch ( KettlePluginException e ) { e.printStackTrace(); return; } lifeListeners.add( listener ); if ( started ) { try { listener.onStart( handler ); } catch ( LifecycleException e ) { e.printStackTrace(); } } } public void pluginRemoved( Object serviceObject ) { lifeListeners.remove( serviceObject ); } public void pluginChanged( Object serviceObject ) { } } ); } /** * Instantiate the main plugin class types for the plugin type provided from the set of registered plugins via * {@link PluginRegistry}. * * @param pluginType * Type of plugin whose main class types should be instanticated * @return Set of plugin main class instances (a.k.a. plugins) */ static <T> Set<T> loadPlugins( Class<? extends PluginTypeInterface> pluginType, Class<T> mainPluginClass ) { Set<T> pluginInstances = new HashSet<T>(); List<PluginInterface> plugins = registry.getPlugins( pluginType ); for ( PluginInterface plugin : plugins ) { try { pluginInstances.add( registry.loadClass( plugin, mainPluginClass ) ); } catch ( Throwable e ) { LogChannel.GENERAL.logError( "Unexpected error loading class for plugin " + plugin.getName(), e ); } } return pluginInstances; } public void onStart( LifeEventHandler handler ) throws LifecycleException { // Caching the last handler and the fact that start has been called. This would cause problems if onStart // is called by more than one handler. this.handler = handler; started = true; for ( LifecycleListener listener : lifeListeners ) { listener.onStart( handler ); } } public void onExit( LifeEventHandler handler ) throws LifecycleException { for ( LifecycleListener listener : lifeListeners ) { listener.onExit( handler ); } } }