2016-11-25 15:42:29 +01:00
package org.gcube.smartgears.provider ;
import static org.gcube.smartgears.Constants.configuration_file_path ;
import static org.gcube.smartgears.Constants.container_configuraton_file_path ;
import static org.gcube.smartgears.Constants.container_profile_file_path ;
import static org.gcube.smartgears.Constants.default_extensions_file_path ;
import static org.gcube.smartgears.Constants.extensions_file_path ;
import static org.gcube.smartgears.Constants.ghn_home_env ;
import static org.gcube.smartgears.Constants.ghn_home_property ;
import static org.gcube.smartgears.Constants.library_configuration_file_path ;
import static org.gcube.smartgears.Constants.profile_file_path ;
import java.io.File ;
import java.io.FileInputStream ;
import java.io.InputStream ;
import java.io.ObjectInputStream ;
2022-05-25 18:56:42 +02:00
import java.util.List ;
2016-11-25 15:42:29 +01:00
import java.util.UUID ;
import javax.servlet.ServletContext ;
2022-03-21 11:17:07 +01:00
2016-11-25 15:42:29 +01:00
import org.gcube.common.events.Hub ;
import org.gcube.common.events.impl.DefaultHub ;
import org.gcube.informationsystem.publisher.RegistryPublisherFactory ;
import org.gcube.informationsystem.publisher.ScopedPublisher ;
import org.gcube.smartgears.configuration.Mode ;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration ;
import org.gcube.smartgears.configuration.application.ApplicationConfigurationBinder ;
import org.gcube.smartgears.configuration.application.ApplicationExtensions ;
import org.gcube.smartgears.configuration.application.ApplicationHandlers ;
import org.gcube.smartgears.configuration.application.BridgedApplicationConfiguration ;
import org.gcube.smartgears.configuration.container.ContainerConfiguration ;
import org.gcube.smartgears.configuration.container.ContainerConfigurationBinder ;
import org.gcube.smartgears.configuration.library.SmartGearsConfiguration ;
import org.gcube.smartgears.configuration.library.SmartGearsConfigurationBinder ;
import org.gcube.smartgears.context.Properties ;
import org.gcube.smartgears.context.application.ApplicationContext ;
import org.gcube.smartgears.context.application.DefaultApplicationContext ;
import org.gcube.smartgears.context.container.ContainerContext ;
import org.gcube.smartgears.context.container.DefaultContainerContext ;
2022-05-25 18:56:42 +02:00
import org.gcube.smartgears.handlers.container.ContainerHandler ;
2016-11-25 15:42:29 +01:00
import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle ;
import org.gcube.smartgears.lifecycle.container.ContainerLifecycle ;
2022-03-21 11:17:07 +01:00
import org.gcube.smartgears.security.AuthorizationProvider ;
2016-11-25 15:42:29 +01:00
import org.gcube.smartgears.utils.Utils ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
/ * *
* Default implementation of the { @link Provider } interface .
*
* @author Fabio Simeoni
*
* /
public class DefaultProvider implements Provider {
private static Logger log = LoggerFactory . getLogger ( Provider . class ) ;
2017-05-12 17:18:07 +02:00
2016-11-25 15:42:29 +01:00
private ContainerContext containerContext ;
//TODO: do the same with applicationContext (with a map)
2022-03-21 11:17:07 +01:00
private File configFile = null ;
protected DefaultProvider ( File configFile ) {
this . configFile = configFile ;
}
2022-05-25 18:56:42 +02:00
2022-03-21 11:17:07 +01:00
2016-11-25 15:42:29 +01:00
protected DefaultProvider ( ) { } ;
@Override
public ContainerContext containerContext ( ) {
if ( containerContext = = null ) {
ContainerConfiguration configuration = containerConfiguration ( ) ;
Hub hub = new DefaultHub ( ) ;
ContainerLifecycle lifecycle = new ContainerLifecycle ( hub ) ;
File file = configuration . persistence ( ) . file ( container_profile_file_path ) ;
String id = null ;
if ( file . exists ( ) ) {
log . info ( " loading persisted state for container " ) ;
try ( ObjectInputStream ois = new ObjectInputStream ( new FileInputStream ( file ) ) ) {
id = ( String ) ois . readObject ( ) ;
} catch ( Exception e ) {
log . error ( " error loading persisted state, creating new uuid " , e ) ;
}
}
if ( id = = null ) {
id = UUID . randomUUID ( ) . toString ( ) ;
log . info ( " container id created is {} " , id ) ;
}
containerContext = new DefaultContainerContext ( id , configuration , hub , lifecycle , new Properties ( ) ) ;
}
return containerContext ;
}
@Override
2022-05-25 18:56:42 +02:00
public List < ContainerHandler > containerHandlers ( ) {
2016-11-25 15:42:29 +01:00
try {
ContainerConfigurationBinder binder = new ContainerConfigurationBinder ( ) ;
2022-03-21 11:17:07 +01:00
2017-05-12 17:18:07 +02:00
ClassLoader currentClassLoader = Thread . currentThread ( ) . getContextClassLoader ( ) ;
if ( currentClassLoader . getParent ( ) ! = null & & ! currentClassLoader . getParent ( ) . equals ( ClassLoader . getSystemClassLoader ( ) ) ) {
log . trace ( " probably i'm in a webapp classloader " ) ;
currentClassLoader = currentClassLoader . getParent ( ) ;
}
2022-03-21 11:17:07 +01:00
2022-05-25 18:56:42 +02:00
List < ContainerHandler > defaultHandlers = binder . bindHandlers ( currentClassLoader ) ;
2016-11-25 15:42:29 +01:00
2017-05-12 17:18:07 +02:00
return defaultHandlers ;
2016-11-25 15:42:29 +01:00
} catch ( RuntimeException e ) {
throw new RuntimeException ( " cannot install container handlers (see cause) " , e ) ;
}
}
@Override
public ApplicationContext contextFor ( ContainerContext context , ServletContext application ) {
ApplicationConfiguration configuration = null ;
ApplicationConfiguration embedded = configurationFor ( application ) ;
ApplicationConfiguration external = context . configuration ( ) . app ( application . getContextPath ( ) ) ;
//shouldn't happen: management shouldn't have started at all
if ( embedded = = null & & external = = null )
throw new AssertionError ( " application @ " + application . getContextPath ( ) + " is not distributed with "
+ configuration_file_path + " and there is no external configuration for it in " + container_configuraton_file_path ) ;
//no embedded configuration
if ( embedded = = null ) {
configuration = external ;
log . info ( " loaded configuration for application " + configuration . name ( ) + " from " + container_configuraton_file_path ) ;
}
else {
configuration = embedded ;
if ( external = = null )
log . info ( " loaded configuration for application " + configuration . name ( ) + " from " + configuration_file_path ) ;
else {
configuration . merge ( external ) ;
log . info ( " loaded configuration for application " + configuration . name ( ) + " from " + configuration_file_path + " and " + container_configuraton_file_path ) ;
}
}
ApplicationConfiguration bridgedConfiguration = new BridgedApplicationConfiguration ( context . configuration ( ) ,
configuration ) ;
Hub hub = new DefaultHub ( ) ;
ApplicationLifecycle lifecycle = new ApplicationLifecycle ( hub , configuration . name ( ) ) ;
File file = bridgedConfiguration . persistence ( ) . file ( profile_file_path ) ;
String id = null ;
if ( file . exists ( ) ) {
log . info ( " loading persisted state for application {} " , application . getContextPath ( ) ) ;
try ( ObjectInputStream ois = new ObjectInputStream ( new FileInputStream ( file ) ) ) {
id = ( String ) ois . readObject ( ) ;
} catch ( Exception e ) {
log . error ( " error loading persisted state, creating new uuid " , e ) ;
}
}
if ( id = = null )
id = UUID . randomUUID ( ) . toString ( ) ;
return new DefaultApplicationContext ( id , context , application , bridgedConfiguration , hub , lifecycle ,
new Properties ( ) ) ;
}
@Override
public ApplicationHandlers handlersFor ( ApplicationContext context ) {
try {
2017-05-12 17:18:07 +02:00
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder ( ) ;
2022-05-25 18:56:42 +02:00
2022-03-21 11:17:07 +01:00
2017-05-12 17:18:07 +02:00
//searching for smartegars related application handlers in the common classloader
ClassLoader currentClassLoader = Thread . currentThread ( ) . getContextClassLoader ( ) ;
if ( currentClassLoader . getParent ( ) ! = null & & ! currentClassLoader . getParent ( ) . equals ( ClassLoader . getSystemClassLoader ( ) ) ) {
log . trace ( " probably i'm in a webapp classloader " ) ;
currentClassLoader = currentClassLoader . getParent ( ) ;
}
2022-03-21 11:17:07 +01:00
2022-05-25 18:56:42 +02:00
ApplicationHandlers defaultHandlers = binder . bindHandlers ( currentClassLoader ) ;
2017-03-30 11:37:40 +02:00
return defaultHandlers ;
2017-05-12 17:18:07 +02:00
2016-11-25 15:42:29 +01:00
} catch ( RuntimeException e ) {
throw new RuntimeException ( " cannot install handlers for application @ " + context . name ( ) + " (see cause) " , e ) ;
}
}
2017-05-12 17:18:07 +02:00
2016-11-25 15:42:29 +01:00
@Override
public ApplicationExtensions extensionsFor ( ApplicationContext context ) {
try {
InputStream config = context . application ( ) . getResourceAsStream ( extensions_file_path ) ;
if ( config = = null ) {
log . trace ( " {} uses default extensions as it does not include {} " , context . name ( ) , extensions_file_path ) ;
// it's in a library, using
config = getClass ( ) . getResourceAsStream ( default_extensions_file_path ) ;
if ( config = = null )
throw new IllegalStateException ( " invalid distribution: cannot find " + default_extensions_file_path ) ;
} else
log . info ( " {} uses custom extensions @ {} " , context . name ( ) , extensions_file_path ) ;
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder ( ) ;
return binder . bindExtensions ( config ) ;
} catch ( RuntimeException e ) {
throw new RuntimeException ( " cannot install extensions for application @ " + context . name ( ) + " (see cause) " , e ) ;
}
}
@Override
public SmartGearsConfiguration smartgearsConfiguration ( ) {
try {
2022-03-31 11:58:49 +02:00
InputStream config = getClass ( ) . getResourceAsStream ( library_configuration_file_path ) ;
if ( config = = null )
throw new IllegalStateException ( " invalid distribution: cannot find " + library_configuration_file_path ) ;
SmartGearsConfigurationBinder binder = new SmartGearsConfigurationBinder ( ) ;
SmartGearsConfiguration configuration = binder . bind ( config ) ;
2016-11-25 15:42:29 +01:00
configuration . validate ( ) ;
return configuration ;
} catch ( RuntimeException e ) {
throw new RuntimeException ( " cannot read library configuration (see cause) " , e ) ;
}
}
// helpers
private ApplicationConfiguration configurationFor ( ServletContext application ) {
try {
InputStream config = application . getResourceAsStream ( configuration_file_path ) ;
if ( config = = null )
return null ;
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder ( ) ;
return binder . bind ( config ) ;
} catch ( RuntimeException e ) {
throw new RuntimeException ( " invalid configuration (see cause) " , e ) ;
}
}
private ContainerConfiguration containerConfiguration ( ) {
2022-03-21 11:17:07 +01:00
if ( configFile = = null ) {
2022-05-25 18:56:42 +02:00
2022-03-21 11:17:07 +01:00
String home = Utils . home ( ) ;
2022-05-25 18:56:42 +02:00
2022-03-21 11:17:07 +01:00
if ( home = = null )
throw new IllegalStateException ( " invalid node configuration: the environment variable " + ghn_home_env
+ " or the system property " + ghn_home_property + " must be defined " ) ;
2016-11-25 15:42:29 +01:00
2022-03-21 11:17:07 +01:00
File homeDir = new File ( home ) ;
2016-11-25 15:42:29 +01:00
2022-03-21 11:17:07 +01:00
if ( ! ( homeDir . exists ( ) & & homeDir . isDirectory ( ) & & homeDir . canRead ( ) & & homeDir . canWrite ( ) ) )
throw new IllegalStateException ( " invalid node configuration: home " + home + " does not exist or is not a directory or cannot be accessed in read/write mode " ) ;
2016-11-25 15:42:29 +01:00
2022-03-21 11:17:07 +01:00
configFile = new File ( homeDir , container_configuraton_file_path ) ;
2016-11-25 15:42:29 +01:00
2022-05-25 18:56:42 +02:00
2022-03-21 11:17:07 +01:00
log . trace ( " reading container configuration @ {} " , configFile . getAbsolutePath ( ) ) ;
2016-11-25 15:42:29 +01:00
}
2022-03-21 11:17:07 +01:00
if ( ! ( configFile . exists ( ) & & configFile . canRead ( ) ) )
throw new IllegalStateException ( " invalid node configuration: file " + configFile . getAbsolutePath ( ) + " does not exist or cannot be accessed " ) ;
2016-11-25 15:42:29 +01:00
2022-03-21 11:17:07 +01:00
ContainerConfiguration configuration ;
try ( InputStream stream = new FileInputStream ( configFile ) ) {
2022-05-25 18:56:42 +02:00
configuration = new ContainerConfigurationBinder ( ) . load ( stream ) ;
2022-03-21 11:17:07 +01:00
} catch ( Exception e ) {
2022-05-25 18:56:42 +02:00
throw new IllegalStateException ( " invalid node configuration: file " + configFile . getAbsolutePath ( ) + " is invalid " , e ) ;
2016-11-25 15:42:29 +01:00
}
2022-05-25 18:56:42 +02:00
2016-11-25 15:42:29 +01:00
return configuration ;
}
2017-05-12 17:18:07 +02:00
2016-11-25 15:42:29 +01:00
@Override
2022-03-21 11:17:07 +01:00
public ScopedPublisher publisher ( ) {
return containerContext . configuration ( ) . mode ( ) = = Mode . online ? RegistryPublisherFactory . scopedPublisher ( )
2016-11-25 15:42:29 +01:00
: new OfflinePublisher ( ) ;
}
@Override
2022-03-21 11:17:07 +01:00
public AuthorizationProvider authorizationProvider ( ) {
return containerContext . configuration ( ) . authorizationProvider ( ) ;
2016-11-25 15:42:29 +01:00
}
}