/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
*
* Copyright 2006 - 2013 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.platform.engine.core.system.boot;
import org.pentaho.platform.api.engine.IApplicationContext;
import org.pentaho.platform.api.engine.IPentahoDefinableObjectFactory;
import org.pentaho.platform.api.engine.IPentahoDefinableObjectFactory.Scope;
import org.pentaho.platform.api.engine.IPentahoObjectFactory;
import org.pentaho.platform.api.engine.IPentahoPublisher;
import org.pentaho.platform.api.engine.IPentahoSystemListener;
import org.pentaho.platform.api.engine.ISessionStartupAction;
import org.pentaho.platform.api.engine.ISystemSettings;
import org.pentaho.platform.engine.core.messages.Messages;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.engine.core.system.StandaloneApplicationContext;
import org.pentaho.platform.engine.core.system.objfac.StandaloneObjectFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* This class is designed to help embedded deployments start the Pentaho system. {@link PentahoSystemBoot} is a
* self-contained and very easy to configure platform initializer which does not impose the use of configuration
* files on your filesystem. A booter instance gives you the flexibility to configure and run the platform entirely
* in memory.
* <p>
* In general you will want to
* <ol>
* <li>Construct a {@link PentahoSystemBoot}
* <li>define the system objects that your system requires, by using one of the {@link #define(Class, Class)}
* variants
* <li>(optionally) initialize the Pentaho system for processing requests by calling {@link #start()}
* </ol>
* An extremely minimal platform might be configured like this:
*
* <pre>
* @Before
* public void init() {
* PentahoSystemBoot booter = new PentahoSystemBoot();
* // setup your required object definitions
* booter.define( IUnifiedRepository.class, DefaultUnifiedRepository.class );
*
* // initialize the minimal platform
* booter.init();
* }
* </pre>
*
* @author jamesdixon and aphillips
*
*/
public class PentahoSystemBoot {
private IPentahoObjectFactory factory;
private String filePath;
private String fullyQualifiedServerUrl;
// list of the system listeners to hook up
private List<IPentahoSystemListener> lifecycleListeners = new ArrayList<IPentahoSystemListener>();
// list of startup actions to execute
private List<ISessionStartupAction> startupActions = new ArrayList<ISessionStartupAction>();
// list of admin plugins (aka publishers)
private List<IPentahoPublisher> adminActions = new ArrayList<IPentahoPublisher>();
private ISystemSettings settingsProvider = null;
private boolean initialized = false;
/**
* Creates a minimal ready-to-run platform. Use this constructor if you want to accept all the defaults for your
* in-memory platform.
*/
public PentahoSystemBoot() {
configure( null, null, null );
}
/**
* Creates a minimal ready-to-run platform with a specified solution path. Use this constructor if your system
* needs to access system or other solution files from a particular directory.
*
* @param solutionPath
* full path to the pentaho_solutions folder
*/
public PentahoSystemBoot( String solutionPath ) {
configure( solutionPath, null, null );
}
public PentahoSystemBoot( String solutionPath, String fullyQualifiedServerUrl ) {
configure( solutionPath, fullyQualifiedServerUrl, null );
}
public PentahoSystemBoot( String solutionPath, IPentahoDefinableObjectFactory factory ) {
configure( solutionPath, null, factory );
}
public PentahoSystemBoot( String solutionPath, String fullyQualifiedServerUrl,
IPentahoDefinableObjectFactory factory ) {
configure( solutionPath, fullyQualifiedServerUrl, factory );
}
/**
* Configures this booter to run. Any parameters that are <code>null</code> will be set with default values. The
* default values are as follows:
* <ul>
* <li>solutionPath = "." (current working directory)
* <li>fullyQualifiedServerUrl = "http://localhost:8080/pentaho/"
* <li>factory = a new StandaloneObjectFactory instance
* </ul>
* Override this method to create a different set of defaults or use the 'setter' methods to override defaults in
* a more fine-grained manner
*/
protected void configure( String userFilePath, String userFullyQualifiedServerUrl,
IPentahoDefinableObjectFactory userFactory ) {
setFilePath( userFilePath != null ? userFilePath : new File( "." ).getAbsolutePath() ); //$NON-NLS-1$
setFullyQualifiedServerUrl( userFullyQualifiedServerUrl != null ? userFullyQualifiedServerUrl
: "http://localhost:8080/pentaho/" ); //$NON-NLS-1$
setFactory( userFactory != null ? userFactory : new StandaloneObjectFactory() );
PentahoSystem.setSystemListeners( lifecycleListeners );
PentahoSystem.setSessionStartupActions( startupActions );
PentahoSystem.setAdministrationPlugins( adminActions );
}
/**
* Sets the file path that will be used to get to file-based resources
*
* @return
*/
public String getFilePath() {
return filePath;
}
/**
* Sets the file path to be used to find configuration and content files If this is not set the current directory
* (.) is used.
*
* @param filePath
*/
public void setFilePath( final String filePath ) {
this.filePath = filePath;
}
/**
* Sets the URL that the platform uses to generate paths to its own resources
*
* @param baseUrl
*/
public void setFullyQualifiedServerUrl( final String fullyQualifiedServerUrl ) {
this.fullyQualifiedServerUrl = fullyQualifiedServerUrl;
}
/**
* Override this method if you want to change the type and state of the application context used to initialize
* the system.
*
* @return an application context for system initialization
*/
protected IApplicationContext createApplicationContext() {
StandaloneApplicationContext appCtxt = new StandaloneApplicationContext( getFilePath(), "" ); //$NON-NLS-1$
appCtxt.setFullyQualifiedServerURL( fullyQualifiedServerUrl );
return appCtxt;
}
/**
* @deprecated use {@link #start()}. This method is hanging around for backward compatibility with MicroPlatform
*/
public void init() {
try {
start();
} catch ( PlatformInitializationException e ) {
throw new RuntimeException( e );
}
}
/**
* Starts the Pentaho platform, making it ready to process requests.
*
* @throws PlatformInitializationException
* if there was a problem initializing the platform
*/
public boolean start() throws PlatformInitializationException {
initialized = false;
try {
initialized = PentahoSystem.init( createApplicationContext() );
// we want to wrap any exception that causes initialization to fail, so we will
// catch throwable
} catch ( Throwable t ) {
throw new PlatformInitializationException( Messages.getInstance().getErrorString(
"PentahoSystemBoot.ERROR_0001_PLATFORM_INIT_FAILED" ), t ); //$NON-NLS-1$
}
if ( !initialized ) {
throw new PlatformInitializationException( Messages.getInstance().getErrorString(
"PentahoSystemBoot.ERROR_0001_PLATFORM_INIT_FAILED" ) ); //$NON-NLS-1$
}
return initialized;
}
/**
* Stops the Pentaho platform
*
* @return
*/
public boolean stop() {
initialized = false;
PentahoSystem.shutdown();
return true;
}
/**
* Gets the object factory for the Pentaho platform
*
* @return
*/
public IPentahoObjectFactory getFactory() {
return factory;
}
/**
* Sets the object factory for the Pentaho platform, This defaults to the StandaloneObjectFactory
*
* @return
*/
public void setFactory( IPentahoObjectFactory factory ) {
this.factory = factory;
// object factory needs to also be early here so clients that do not need to
// run the platform can have an object factory available
PentahoSystem.clearObjectFactory();
PentahoSystem.registerPrimaryObjectFactory( factory );
}
/**
* Adds an administrative action to the system.
*
* @param adminAction
*/
public void addAdminAction( final IPentahoPublisher adminAction ) {
adminActions.add( adminAction );
}
public void setAdminActions( final List<IPentahoPublisher> adminActions ) {
this.adminActions = adminActions;
}
/**
* Adds a lifecycle listener. This object will be notified when the Pentaho platform starts and stops.
*
* @param lifecycleListener
*/
public void addLifecycleListener( final IPentahoSystemListener lifecycleListener ) {
lifecycleListeners.add( lifecycleListener );
}
/**
* Returns the list of lifecycle listeners that will be used. These objects will be notified when the Pentaho
* platform starts and stops.
*
* @return
*/
public List<IPentahoSystemListener> getLifecycleListeners() {
return lifecycleListeners;
}
/**
* Returns the list of lifecycle listeners that will be used. These objects will be notified when the Pentaho
* platform starts and stops.
*
* @return
*/
public void setLifecycleListeners( final List<IPentahoSystemListener> lifecycleListeners ) {
this.lifecycleListeners = lifecycleListeners;
}
/**
* Gets the system settings object that will be used by the Pentaho platform
*
* @return
*/
public ISystemSettings getSettingsProvider() {
return settingsProvider;
}
/**
* Sets the system settings object that will be used by the Pentaho platform
*
* @return
*/
public void setSettingsProvider( final ISystemSettings settingsProvider ) {
PentahoSystem.setSystemSettingsService( settingsProvider );
this.settingsProvider = settingsProvider;
}
/**
* Returns true if the Pentaho platform has initialized successfully.
*
* @return
*/
public boolean isInitialized() {
return initialized;
}
/**
* Returns the list of startup actions. These actions will be executed on system startup or on session creation.
*
* @return
*/
public List<ISessionStartupAction> getStartupActions() {
return startupActions;
}
/**
* Sets the list of startup actions These actions will be executed on system startup or on session creation.
*
* @param startupActions
*/
public void setStartupActions( final List<ISessionStartupAction> startupActions ) {
this.startupActions = startupActions;
}
/**
* Adds a strtup action to the system. These actions will be executed on system startup or on session creation.
*
* @param startupAction
*/
public void addStartupAction( final ISessionStartupAction startupAction ) {
startupActions.add( startupAction );
}
/**
* Define an arbitrarily scoped object
*
* @param key
* the key to retrieval of this object
* @param implClassName
* the actual type that is served back to you when requested.
* @param scope
* the scope of the object
* @return the current {@link PentahoSystemBoot} instance, for chaining
* @throws NoSuchMethodError
* if the object factory does not support runtime object definition
*/
public PentahoSystemBoot define( String key, String implClassName, Scope scope ) {
if ( factory instanceof IPentahoDefinableObjectFactory ) {
IPentahoDefinableObjectFactory definableFactory = (IPentahoDefinableObjectFactory) getFactory();
definableFactory.defineObject( key, implClassName, scope );
} else {
throw new NoSuchMethodError( "define is only supported by IPentahoDefinableObjectFactory" ); //$NON-NLS-1$
}
return this;
}
/**
* Define an arbitrarily scoped object
*
* @param interfaceClass
* the key to retrieval of this object
* @param implClass
* the actual type that is served back to you when requested.
* @param scope
* the scope of the object
* @return the current {@link PentahoSystemBoot} instance, for chaining
* @throws NoSuchMethodError
* if the object factory does not support runtime object definition
*/
public PentahoSystemBoot define( Class<?> interfaceClass, Class<?> implClass, Scope scope ) {
return define( interfaceClass.getSimpleName(), implClass.getName(), scope );
}
/**
* Define an arbitrarily scoped object
*
* @param key
* the key to retrieval of this object
* @param implClass
* the actual type that is served back to you when requested.
* @param scope
* the scope of the object
* @return the current {@link PentahoSystemBoot} instance, for chaining
* @throws NoSuchMethodError
* if the object factory does not support runtime object definition
*/
public PentahoSystemBoot define( String key, Class<?> implClass, Scope scope ) {
return define( key, implClass.getName(), scope );
}
/**
* Define a locally scoped object (aka prototype scope -- unique instance for each request for the class)
*
* @param interfaceClass
* the key to retrieval of this object
* @param implClass
* the actual type that is served back to you when requested.
* @return the current MicroPlatform instance, for chaining
*/
public PentahoSystemBoot define( Class<?> interfaceClass, Class<?> implClass ) {
return define( interfaceClass.getSimpleName(), implClass.getName(), Scope.LOCAL );
}
/**
* Define a locally scoped object (aka prototype scope -- unique instance for each request for the class)
*
* @param key
* the key to retrieval of this object
* @param implClass
* the actual type that is served back to you when requested.
* @return the current MicroPlatform instance, for chaining
*/
public PentahoSystemBoot define( String key, Class<?> implClass ) {
return define( key, implClass.getName(), Scope.LOCAL );
}
/**
* Hold an object instance by key name.
*
* @param key
* the key to retrieval of this object
* @param instance
* the actual instance that is served back to you when requested.
* @return the current MicroPlatform instance, for chaining
*/
public PentahoSystemBoot define( String key, Object instance ) {
if ( factory instanceof IPentahoDefinableObjectFactory ) {
IPentahoDefinableObjectFactory definableFactory = (IPentahoDefinableObjectFactory) getFactory();
definableFactory.defineInstance( key, instance );
} else {
throw new NoSuchMethodError( "defineInstance is only supported by IPentahoDefinableObjectFactory" ); //$NON-NLS-1$
}
return this;
}
}