2016-11-25 15:42:29 +01:00
|
|
|
package org.gcube.smartgears;
|
|
|
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
import javax.servlet.ServletContainerInitializer;
|
|
|
|
import javax.servlet.ServletContext;
|
|
|
|
import javax.servlet.ServletException;
|
|
|
|
|
|
|
|
import org.gcube.smartgears.context.application.ApplicationContext;
|
|
|
|
import org.gcube.smartgears.context.container.ContainerContext;
|
|
|
|
import org.gcube.smartgears.managers.ApplicationManager;
|
|
|
|
import org.gcube.smartgears.managers.ContainerManager;
|
|
|
|
import org.gcube.smartgears.provider.ProviderFactory;
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2022-05-23 17:15:46 +02:00
|
|
|
import io.micrometer.core.instrument.Metrics;
|
|
|
|
import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics;
|
2023-02-01 17:18:13 +01:00
|
|
|
import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics;
|
2022-05-23 17:15:46 +02:00
|
|
|
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
|
|
|
|
import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics;
|
|
|
|
import io.micrometer.core.instrument.binder.system.ProcessorMetrics;
|
2023-02-01 17:18:13 +01:00
|
|
|
import io.micrometer.core.instrument.binder.system.UptimeMetrics;
|
2022-05-23 17:15:46 +02:00
|
|
|
import io.micrometer.prometheus.PrometheusConfig;
|
|
|
|
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
|
|
|
|
2016-11-25 15:42:29 +01:00
|
|
|
/**
|
|
|
|
* Bootstraps management of all deployed applications which require it.
|
|
|
|
*
|
|
|
|
* @author Fabio Simeoni
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public class Bootstrap implements ServletContainerInitializer {
|
|
|
|
|
|
|
|
private static Logger log = LoggerFactory.getLogger(Bootstrap.class);
|
|
|
|
|
|
|
|
private static boolean smartgearsHasStarted = false;
|
|
|
|
|
|
|
|
private static boolean containerHasFailed = false;
|
|
|
|
|
|
|
|
private static ContainerManager manager;
|
|
|
|
|
|
|
|
private static ContainerContext context;
|
|
|
|
|
|
|
|
public Bootstrap() {
|
|
|
|
|
|
|
|
if (smartgearsHasStarted)
|
|
|
|
return;
|
|
|
|
|
|
|
|
smartgearsHasStarted = true;
|
|
|
|
|
|
|
|
initialiseContainer();
|
|
|
|
|
|
|
|
//this can fail the app: managed resources need a working container
|
|
|
|
startContainerIfItHasntAlreadyFailed();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onStartup(Set<Class<?>> c, ServletContext application) throws ServletException {
|
|
|
|
|
|
|
|
ApplicationManager appManager = new ApplicationManager();
|
|
|
|
|
|
|
|
//act only on resources
|
|
|
|
if (isResource(application)) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
log.info("starting management of application @ {}", application.getContextPath());
|
|
|
|
|
|
|
|
ApplicationContext app = appManager.start(context, application);
|
|
|
|
|
|
|
|
manager.manage(app);
|
|
|
|
|
|
|
|
context.configuration().app(app.configuration());
|
|
|
|
|
|
|
|
} catch (Throwable t) {
|
|
|
|
|
|
|
|
appManager.stop();
|
|
|
|
|
|
|
|
throw new ServletException("cannot manage application @ " + application.getContextPath()
|
|
|
|
+ " (see cause)", t);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// helpers
|
2023-02-06 17:34:18 +01:00
|
|
|
@SuppressWarnings("resource")
|
2016-11-25 15:42:29 +01:00
|
|
|
private void initialiseContainer() {
|
|
|
|
|
2024-02-02 10:54:19 +01:00
|
|
|
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
|
|
|
|
|
2016-11-25 15:42:29 +01:00
|
|
|
try {
|
2024-02-02 10:54:19 +01:00
|
|
|
// TODO Ask why is needed?
|
|
|
|
Thread.currentThread().setContextClassLoader(ContainerManager.class.getClassLoader());
|
2016-11-25 15:42:29 +01:00
|
|
|
|
|
|
|
log.trace("smartgears is starting");
|
|
|
|
|
|
|
|
/* Get the ContainerContext. Look at DefaultProvider */
|
|
|
|
context = ProviderFactory.provider().containerContext();
|
|
|
|
|
2022-05-23 17:15:46 +02:00
|
|
|
PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
|
2023-02-01 17:18:13 +01:00
|
|
|
|
2022-05-23 17:15:46 +02:00
|
|
|
new ClassLoaderMetrics().bindTo(registry);
|
|
|
|
new JvmMemoryMetrics().bindTo(registry);
|
2023-02-01 17:18:13 +01:00
|
|
|
new JvmGcMetrics().bindTo(registry);
|
2022-05-23 17:15:46 +02:00
|
|
|
new ProcessorMetrics().bindTo(registry);
|
|
|
|
new JvmThreadMetrics().bindTo(registry);
|
2023-02-01 17:18:13 +01:00
|
|
|
new UptimeMetrics().bindTo(registry);
|
|
|
|
new ProcessorMetrics().bindTo(registry);
|
2022-05-23 17:15:46 +02:00
|
|
|
|
|
|
|
Metrics.addRegistry(registry);
|
2024-02-02 10:54:19 +01:00
|
|
|
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2016-11-25 15:42:29 +01:00
|
|
|
/* Validate the configuration retrieved by ContainerContext
|
|
|
|
* using gcube facilities annotation based
|
|
|
|
* ( i.e org.gcube.common.validator.annotations)
|
|
|
|
*/
|
2022-03-21 11:17:07 +01:00
|
|
|
context.configuration().validate();
|
2016-11-25 15:42:29 +01:00
|
|
|
|
|
|
|
} catch (RuntimeException e) {
|
|
|
|
|
|
|
|
containerHasFailed = true;
|
|
|
|
|
|
|
|
log.error("cannot start smartgears", e);
|
|
|
|
|
|
|
|
//we let the container continue
|
|
|
|
|
2024-02-02 10:54:19 +01:00
|
|
|
} finally {//restore the classloader of the current application
|
|
|
|
Thread.currentThread().setContextClassLoader(contextCL);
|
2016-11-25 15:42:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void startContainerIfItHasntAlreadyFailed() {
|
|
|
|
|
|
|
|
if (containerHasFailed)
|
|
|
|
throw new IllegalStateException("container is not managed due to previous failure");
|
|
|
|
|
|
|
|
|
|
|
|
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
|
|
|
|
|
|
|
|
|
|
|
|
// we initialise the container in the same classloader as this
|
|
|
|
// lib, lest container bind its resources to the current webapp
|
|
|
|
try {
|
|
|
|
|
|
|
|
// TODO Ask why is needed?
|
2024-02-02 10:54:19 +01:00
|
|
|
Thread.currentThread().setContextClassLoader(ContainerManager.class.getClassLoader());
|
2016-11-25 15:42:29 +01:00
|
|
|
|
|
|
|
manager = ContainerManager.instance;
|
|
|
|
|
|
|
|
context = manager.start(context);
|
|
|
|
|
|
|
|
} catch (RuntimeException e) {
|
|
|
|
|
|
|
|
containerHasFailed = true;
|
|
|
|
|
|
|
|
throw new IllegalStateException("cannot manage container", e);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
finally {//restore the classloader of the current application
|
|
|
|
Thread.currentThread().setContextClassLoader(contextCL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isResource(ServletContext application) {
|
|
|
|
|
|
|
|
//with care: smartgears may have already failed at this stage but we want to recognise
|
|
|
|
//apps that would have been managed otherwise and give specific errors for those
|
|
|
|
return (!containerHasFailed && context.configuration().app(application.getContextPath())!=null)
|
|
|
|
||
|
|
|
|
application.getResourceAsStream(Constants.configuration_file_path) != null;
|
|
|
|
}
|
|
|
|
}
|