package org.gcube.smartgears.context.application; import static org.gcube.smartgears.Constants.profile_file_path; import java.io.File; import java.io.FileInputStream; import java.io.ObjectInputStream; import java.nio.file.Path; import java.nio.file.Paths; import java.util.UUID; import org.gcube.common.events.Hub; import org.gcube.smartgears.configuration.PersistenceConfiguration; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.persistence.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jakarta.servlet.ServletContext; /** * Default {@link ApplicationContext} implementation. * * @author Fabio Simeoni * */ public class DefaultApplicationContext implements ApplicationContext { private static Logger log = LoggerFactory.getLogger(DefaultApplicationContext.class); private final ContainerContext container; private final ServletContext sctx; private final ApplicationConfiguration configuration; private final ApplicationLifecycle lifecycle; private final Properties properties; private final Hub hub; private final PersistenceWriter persistenceWriter; private final String id; private Path appSpecificConfigurationFolder; private final static String APPS_CONFIG__DIR = "config/apps"; /** * Crates an intance with mandatory parameters * @param container the container context * @param sctx the servlet context * @param configuration the configuration * @param hub the event hub * @param lifecycle the lifecycle * @param properties the properties */ public DefaultApplicationContext(ContainerContext container,ServletContext sctx,ApplicationConfiguration configuration, Hub hub, ApplicationLifecycle lifecycle, Properties properties) { PersistenceConfiguration persistenceWriterConf = configuration.persistenceConfiguration(); try { persistenceWriter = persistenceWriterConf.getImplementationClass().getDeclaredConstructor().newInstance(); persistenceWriter.configure(persistenceWriterConf.getWriterConfiguration()); }catch (Exception e) { throw new RuntimeException(e); } File file = persistenceWriter.file(profile_file_path); String id = null; if (file.exists()) { log.info("loading persisted state for application {}", sctx.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(); this.id = id; this.container=container; this.sctx = sctx; this.configuration=configuration; this.hub=hub; this.lifecycle = lifecycle; this.appSpecificConfigurationFolder = getApplicationSpecificConfig(); this.properties=properties; } /** * Creates an instance by copying the configuration of another. * @param context the other instance */ public DefaultApplicationContext(ApplicationContext context) { this(context.id(), context.persistence(), context.container(),context.application(),context.configuration(),context.events(), context.lifecycle(), new Properties(context.properties())); } private DefaultApplicationContext(String id, PersistenceWriter writer, ContainerContext container,ServletContext sctx,ApplicationConfiguration configuration, Hub hub, ApplicationLifecycle lifecycle, Properties properties) { this.id = id; this.container=container; this.sctx = sctx; this.configuration=configuration; this.hub=hub; this.lifecycle = lifecycle; this.properties=properties; this.persistenceWriter = writer; } @Override public ServletContext application() { return sctx; } @Override public ContainerContext container() { return container; } @Override public String name() { //little shortcut for ease of logging return configuration.name(); } @Override public ApplicationConfiguration configuration() { return configuration; } @Override public ApplicationLifecycle lifecycle() { return lifecycle; } @Override public Hub events() { return hub; } @Override public PersistenceWriter persistence() { return persistenceWriter; } @Override public Properties properties() { return properties; } @Override public String id() { return id; } /** * Returns the authorization provider. * @return the AuhtorizationProvider **/ public AuthorizationProvider authorizationProvider() { return container().authorizationProvider(); } @Override public Path appSpecificConfigurationFolder() { return this.appSpecificConfigurationFolder; } private Path getApplicationSpecificConfig(){ String home = Utils.home(); File homeDir = new File(home); if (!(homeDir.exists() && homeDir.isDirectory() && homeDir.canRead())) throw new IllegalStateException("invalid node configuration: home " + home + " does not exist or is not a directory or cannot be accessed in read mode"); String appName = this.configuration.name(); Path appSpecificConfigurationPath = Paths.get(home, APPS_CONFIG__DIR, appName); File appSpecificConfiguration = appSpecificConfigurationPath.toFile(); if (!(appSpecificConfiguration.exists() && appSpecificConfiguration.isDirectory() && appSpecificConfiguration.canRead())) { log.warn("specific configuration folder for {} not found", appName); return null; } log.info("reading specific app configuration folder @ {} ", appSpecificConfiguration.getAbsolutePath()); return appSpecificConfigurationPath; } }