common-smartgears/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java

294 lines
9.6 KiB
Java
Raw Normal View History

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.ghn_home_env;
import static org.gcube.smartgears.Constants.ghn_home_property;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
2023-02-01 14:40:31 +01:00
import java.util.stream.Collectors;
2024-03-11 10:22:25 +01:00
import jakarta.servlet.ServletContext;
import org.gcube.common.events.Hub;
import org.gcube.common.events.impl.DefaultHub;
import org.gcube.common.security.credentials.Credentials;
2023-03-31 14:16:23 +02:00
import org.gcube.smartgears.configuration.SmartgearsConfiguration;
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
import org.gcube.smartgears.configuration.application.ApplicationConfigurationBinder;
import org.gcube.smartgears.configuration.application.ApplicationHandlers;
import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.configuration.container.ContainerConfigurationBinder;
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;
2023-02-06 17:34:18 +01:00
import org.gcube.smartgears.extensions.ApplicationExtension;
import org.gcube.smartgears.extensions.resource.RemoteResource;
import org.gcube.smartgears.handlers.container.ContainerHandler;
import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle;
import org.gcube.smartgears.lifecycle.container.ContainerLifecycle;
import org.gcube.smartgears.publishing.Publisher;
import org.gcube.smartgears.publishing.SmartgearsProfilePublisher;
import org.gcube.smartgears.security.AuthorizationProvider;
import org.gcube.smartgears.security.AuthorizationProviderFactory;
import org.gcube.smartgears.utils.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
2023-02-01 14:40:31 +01:00
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ClassInfo;
import io.github.classgraph.ClassInfoList;
import io.github.classgraph.ScanResult;
/**
* Default implementation of the {@link Provider} interface.
*
* @author Fabio Simeoni
*
*/
public class DefaultProvider implements Provider {
private static Logger log = LoggerFactory.getLogger(Provider.class);
private ContainerContext containerContext;
2023-02-01 14:40:31 +01:00
// TODO: do the same with applicationContext (with a map)
private File configFile = null;
protected DefaultProvider(File configFile) {
this.configFile = configFile;
}
List<Publisher> publishers;
2023-02-01 14:40:31 +01:00
protected DefaultProvider() {
};
@Override
public ContainerContext containerContext() {
2023-02-01 14:40:31 +01:00
if (containerContext == null) {
ContainerConfiguration configuration = containerConfiguration();
Hub hub = new DefaultHub();
ContainerLifecycle lifecycle = new ContainerLifecycle(hub);
2023-02-06 17:34:18 +01:00
AuthorizationProviderFactory<?> authfactory = configuration.authorizationConfiguration()
2023-02-01 14:40:31 +01:00
.getAuthProviderFactory();
2023-02-06 17:34:18 +01:00
Credentials credentials = configuration.authorizationConfiguration().getCredentials();
2023-02-01 14:40:31 +01:00
AuthorizationProvider authProvider = authfactory.connect(credentials);
2023-02-01 14:40:31 +01:00
2023-02-06 17:34:18 +01:00
containerContext = new DefaultContainerContext(configuration, hub, lifecycle, authProvider,
2023-02-01 14:40:31 +01:00
new Properties());
}
return containerContext;
}
@Override
public List<ContainerHandler> containerHandlers() {
try {
ContainerConfigurationBinder binder = new ContainerConfigurationBinder();
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
2023-02-01 14:40:31 +01:00
if (currentClassLoader.getParent() != null
&& !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())) {
log.trace("probably i'm in a webapp classloader");
currentClassLoader = currentClassLoader.getParent();
}
2023-02-01 14:40:31 +01:00
List<ContainerHandler> defaultHandlers = binder.bindHandlers(currentClassLoader);
return defaultHandlers;
} catch (RuntimeException e) {
throw new RuntimeException("cannot install container handlers (see cause) ", e);
}
}
@Override
public ApplicationContext contextFor(ContainerContext context, ServletContext application) {
ApplicationConfiguration embedded = configurationFor(application);
2023-02-06 17:34:18 +01:00
2023-02-01 14:40:31 +01:00
// shouldn't happen: management shouldn't have started at all
2023-02-06 17:34:18 +01:00
if (embedded == null)
2023-02-01 14:40:31 +01:00
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);
2023-02-06 17:34:18 +01:00
Hub hub = new DefaultHub();
2023-02-06 17:34:18 +01:00
ApplicationLifecycle lifecycle = new ApplicationLifecycle(hub, embedded.name());
2023-02-06 17:34:18 +01:00
return new DefaultApplicationContext(context, application, embedded, hub, lifecycle,
new Properties());
}
@Override
public ApplicationHandlers handlersFor(ApplicationContext context) {
try {
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder();
2023-02-01 14:40:31 +01:00
// searching for smartegars related application handlers in the common
// classloader
2024-01-19 22:51:34 +01:00
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
if (currentClassLoader.getParent() != null
2023-02-01 14:40:31 +01:00
&& !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())) {
log.trace("probably i'm in a webapp classloader");
currentClassLoader = currentClassLoader.getParent();
2024-01-19 22:51:34 +01:00
}
2024-01-19 22:51:34 +01:00
ApplicationHandlers defaultHandlers = binder.bindHandlers(currentClassLoader);
2023-02-01 14:40:31 +01:00
return defaultHandlers;
} catch (RuntimeException e) {
2023-02-01 14:40:31 +01:00
throw new RuntimeException("cannot install handlers for application @ " + context.name() + " (see cause) ",
e);
}
}
2023-02-06 17:34:18 +01:00
public List<ApplicationExtension> extensionsFor(ApplicationContext context){
return List.of(new RemoteResource());
}
// helpers
private ApplicationConfiguration configurationFor(ServletContext application) {
try {
InputStream config = application.getResourceAsStream(configuration_file_path);
2023-02-01 14:40:31 +01:00
if (config == null)
return null;
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder();
2023-02-06 17:34:18 +01:00
return binder.load(config);
} catch (RuntimeException e) {
throw new RuntimeException("invalid configuration (see cause)", e);
}
}
private ContainerConfiguration containerConfiguration() {
2023-02-01 14:40:31 +01:00
if (configFile == null) {
String home = Utils.home();
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");
File homeDir = new File(home);
if (!(homeDir.exists() && homeDir.isDirectory() && homeDir.canRead() && homeDir.canWrite()))
2023-02-01 14:40:31 +01:00
throw new IllegalStateException("invalid node configuration: home " + home
+ " does not exist or is not a directory or cannot be accessed in read/write mode");
2023-02-01 14:40:31 +01:00
configFile = new File(homeDir, container_configuraton_file_path);
log.trace("reading container configuration @ {} ", configFile.getAbsolutePath());
}
if (!(configFile.exists() && configFile.canRead()))
2023-02-01 14:40:31 +01:00
throw new IllegalStateException("invalid node configuration: file " + configFile.getAbsolutePath()
+ " does not exist or cannot be accessed");
ContainerConfiguration configuration;
2023-02-01 14:40:31 +01:00
try (InputStream stream = new FileInputStream(configFile)) {
configuration = new ContainerConfigurationBinder().load(stream);
} catch (Exception e) {
throw new IllegalStateException(
"invalid node configuration: file " + configFile.getAbsolutePath() + " is invalid", e);
}
return configuration;
}
@Override
public synchronized List<Publisher> publishers() {
if (this.publishers == null) {
2023-02-01 14:40:31 +01:00
Set<Class<?>> annotatedPublishers;
try (ScanResult result = new ClassGraph().enableClassInfo().enableAnnotationInfo()
.addClassLoader(Thread.currentThread().getContextClassLoader()).scan()) {
ClassInfoList classInfos = result.getClassesWithAnnotation(SmartgearsProfilePublisher.class.getName());
2023-02-01 14:40:31 +01:00
annotatedPublishers = classInfos.stream().map(ClassInfo::loadClass)
.filter(c -> Publisher.class.isAssignableFrom(c)).collect(Collectors.toSet());
2023-02-01 14:40:31 +01:00
}
/*
* Collection<URL> urls =
* ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader()
* ); urls.removeIf(url -> url.toString().endsWith(".so") ||
* url.toString().endsWith(".zip") );
*
*
* ConfigurationBuilder reflectionConf = new
* ConfigurationBuilder().addUrls(urls).setScanners(new
* TypeAnnotationsScanner(), new SubTypesScanner());
*
* Reflections reflection = new Reflections(reflectionConf);
*
* = reflection.getTypesAnnotatedWith(SmartgearsProfilePublisher.class);
*/
List<Publisher> foundPublishers = new ArrayList<Publisher>();
2023-02-01 14:40:31 +01:00
for (Class<?> annotatedPublisher : annotatedPublishers) {
try {
foundPublishers.add((Publisher) annotatedPublisher.getDeclaredConstructor().newInstance());
log.info("added class {} to publishers", annotatedPublisher);
} catch (Throwable e) {
log.error("publisher class {} cannot be instantiated", annotatedPublisher.getCanonicalName(), e);
}
}
this.publishers = foundPublishers;
if (foundPublishers.isEmpty())
log.warn("no publishers found in classloader");
}
2023-02-01 14:40:31 +01:00
return this.publishers;
}
2023-03-31 14:16:23 +02:00
@Override
public SmartgearsConfiguration smartgearsConfiguration() {
ContainerConfigurationBinder binder = new ContainerConfigurationBinder();
return binder.loadSmartgearsProperty();
}
2023-02-01 14:40:31 +01:00
/*
* @Override public AuthorizationProvider authorizationProvider() { return
* containerContext.authorizationProvider(); }
*/
2023-03-31 14:16:23 +02:00
}