Health extension implemented
This commit is contained in:
parent
98c41e7463
commit
b873f97187
6
pom.xml
6
pom.xml
|
@ -38,9 +38,9 @@
|
||||||
</scm>
|
</scm>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.reflections</groupId>
|
<groupId>io.github.classgraph</groupId>
|
||||||
<artifactId>reflections</artifactId>
|
<artifactId>classgraph</artifactId>
|
||||||
<version>0.9.10</version>
|
<version>4.8.28</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.common</groupId>
|
<groupId>org.gcube.common</groupId>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.gcube.common.events.Hub;
|
||||||
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
|
import org.gcube.smartgears.configuration.application.ApplicationConfiguration;
|
||||||
import org.gcube.smartgears.context.Properties;
|
import org.gcube.smartgears.context.Properties;
|
||||||
import org.gcube.smartgears.context.container.ContainerContext;
|
import org.gcube.smartgears.context.container.ContainerContext;
|
||||||
|
import org.gcube.smartgears.health.HealthManager;
|
||||||
import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle;
|
import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle;
|
||||||
import org.gcube.smartgears.persistence.PersistenceWriter;
|
import org.gcube.smartgears.persistence.PersistenceWriter;
|
||||||
import org.gcube.smartgears.security.AuthorizationProvider;
|
import org.gcube.smartgears.security.AuthorizationProvider;
|
||||||
|
|
|
@ -51,4 +51,5 @@ public interface ContainerContext {
|
||||||
|
|
||||||
|
|
||||||
AuthorizationProvider authorizationProvider();
|
AuthorizationProvider authorizationProvider();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ public interface ApplicationExtension extends Servlet {
|
||||||
*/
|
*/
|
||||||
void init(ApplicationContext context) throws Exception;
|
void init(ApplicationContext context) throws Exception;
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of this extension.
|
* Returns the name of this extension.
|
||||||
* @return the name
|
* @return the name
|
||||||
|
|
|
@ -76,6 +76,9 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx
|
||||||
this.context=context;
|
this.context=context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Exclude> excludes() {
|
public Set<Exclude> excludes() {
|
||||||
return new HashSet<Exclude>(); //all managed by default
|
return new HashSet<Exclude>(); //all managed by default
|
||||||
|
|
|
@ -4,41 +4,108 @@ import static org.gcube.smartgears.Constants.application_json;
|
||||||
import static org.gcube.smartgears.extensions.HttpExtension.Method.GET;
|
import static org.gcube.smartgears.extensions.HttpExtension.Method.GET;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.gcube.common.health.api.response.HealthResponse;
|
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.gcube.common.health.api.HealthCheck;
|
||||||
|
import org.gcube.common.health.api.ReadinessChecker;
|
||||||
|
import org.gcube.smartgears.context.application.ApplicationContext;
|
||||||
import org.gcube.smartgears.extensions.ApiResource;
|
import org.gcube.smartgears.extensions.ApiResource;
|
||||||
import org.gcube.smartgears.extensions.ApiSignature;
|
import org.gcube.smartgears.extensions.ApiSignature;
|
||||||
|
import org.gcube.smartgears.handlers.application.request.RequestError;
|
||||||
|
import org.gcube.smartgears.health.HealthManager;
|
||||||
|
import org.gcube.smartgears.health.HealthResponse;
|
||||||
|
import org.gcube.smartgears.health.HealthTask;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import io.github.classgraph.ClassGraph;
|
||||||
|
import io.github.classgraph.ClassInfo;
|
||||||
|
import io.github.classgraph.ClassInfoList;
|
||||||
|
import io.github.classgraph.ScanResult;
|
||||||
|
|
||||||
public class HealthResource extends ApiResource {
|
public class HealthResource extends ApiResource {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static Logger log = LoggerFactory.getLogger(HealthResource.class);
|
||||||
|
|
||||||
public static final String mapping = "/health";
|
public static final String mapping = "/health";
|
||||||
|
|
||||||
private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json));
|
private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json));
|
||||||
|
|
||||||
|
private HealthManager manager;
|
||||||
|
|
||||||
|
private HealthTask task;
|
||||||
|
|
||||||
|
private Timer timer;
|
||||||
|
|
||||||
HealthResource() {
|
HealthResource() {
|
||||||
super(signature);
|
super(signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ApplicationContext context) throws Exception {
|
||||||
|
Set<Class<?>> annotatedReadiness;
|
||||||
|
|
||||||
|
try (ScanResult result = new ClassGraph().enableClassInfo().enableAnnotationInfo().scan()) {
|
||||||
|
|
||||||
|
ClassInfoList classInfos = result.getClassesWithAnnotation(ReadinessChecker.class.getName());
|
||||||
|
|
||||||
|
annotatedReadiness = classInfos.stream().map(ClassInfo::loadClass)
|
||||||
|
.filter(c -> HealthCheck.class.isAssignableFrom(c)).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
manager = new HealthManager();
|
||||||
|
for (Class<?> readnessClass : annotatedReadiness)
|
||||||
|
try {
|
||||||
|
manager.register((HealthCheck) readnessClass.getDeclaredConstructor().newInstance());
|
||||||
|
log.info("added class {} to health manager", readnessClass.getCanonicalName());
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.error("healthChecher class {} cannot be instantiated", readnessClass.getCanonicalName(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
task = new HealthTask(manager);
|
||||||
|
|
||||||
|
timer = new Timer(true);
|
||||||
|
|
||||||
|
timer.scheduleAtFixedRate(task, 0, 10000);
|
||||||
|
|
||||||
|
super.init(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
PrintWriter out = resp.getWriter();
|
||||||
|
resp.setContentType("application/json");
|
||||||
|
resp.setCharacterEncoding("UTF-8");
|
||||||
|
Object response = null;
|
||||||
|
|
||||||
}
|
String contextpath = req.getContextPath();
|
||||||
|
log.info("context path is {}", req.getContextPath());
|
||||||
|
if (contextpath.endsWith("/readiness"))
|
||||||
|
response = readiness();
|
||||||
|
else
|
||||||
|
RequestError.resource_notfound_error.fire();
|
||||||
|
|
||||||
|
new ObjectMapper().writeValue(out, response);
|
||||||
|
|
||||||
public HealthResponse liveness() {
|
out.flush();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public HealthResponse readiness() {
|
public HealthResponse readiness() {
|
||||||
return null;
|
return task.getResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.gcube.smartgears.health;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.gcube.common.health.api.HealthCheck;
|
||||||
|
|
||||||
|
public class HealthManager {
|
||||||
|
|
||||||
|
private List<HealthCheck> checks;
|
||||||
|
|
||||||
|
public void register(HealthCheck check){
|
||||||
|
checks.add(check);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HealthCheck> getChecks() {
|
||||||
|
return checks;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.gcube.smartgears.health;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.gcube.com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
import org.gcube.common.health.api.Status;
|
||||||
|
import org.gcube.common.health.api.response.HealthCheckResponse;
|
||||||
|
import org.gcube.common.validator.annotations.NotNull;
|
||||||
|
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
public class HealthResponse {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
private List<HealthCheckResponse> checks;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public HealthResponse(Status status, List<HealthCheckResponse> checks) {
|
||||||
|
super();
|
||||||
|
this.status = status;
|
||||||
|
this.checks = checks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HealthCheckResponse> getChecks() {
|
||||||
|
return checks;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package org.gcube.smartgears.health;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.gcube.common.health.api.HealthCheck;
|
||||||
|
import org.gcube.common.health.api.Status;
|
||||||
|
import org.gcube.common.health.api.response.HealthCheckResponse;
|
||||||
|
|
||||||
|
public class HealthTask extends TimerTask{
|
||||||
|
|
||||||
|
private HealthResponse response;
|
||||||
|
|
||||||
|
private HealthManager healthManager;
|
||||||
|
|
||||||
|
public HealthTask(HealthManager healthManager) {
|
||||||
|
this.healthManager = healthManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
List<HealthCheck> checks = healthManager.getChecks();
|
||||||
|
|
||||||
|
List<HealthCheckResponse> responses = checks.stream().map(c -> this.wrap(c)).collect(Collectors.toList());
|
||||||
|
Status totalStatus = responses.stream().anyMatch(r -> r.getStatus().equals(Status.DOWN)) ? Status.DOWN : Status.UP;
|
||||||
|
|
||||||
|
this.response = new HealthResponse(totalStatus, responses);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HealthResponse getResponse() {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HealthCheckResponse wrap(HealthCheck check){
|
||||||
|
try {
|
||||||
|
return check.check();
|
||||||
|
}catch (Throwable t) {
|
||||||
|
return HealthCheckResponse.builder(check.getName()).down().withMessage("unexpected error executing check").build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,10 @@ public class KeyCloakHealthCheck implements HealthCheck{
|
||||||
|
|
||||||
private static final String CHECK_NAME = "authorization-check" ;
|
private static final String CHECK_NAME = "authorization-check" ;
|
||||||
|
|
||||||
|
public String getName(){
|
||||||
|
return CHECK_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HealthCheckResponse check() {
|
public HealthCheckResponse check() {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
@ -52,6 +53,8 @@ public class ApplicationManager {
|
||||||
|
|
||||||
private ApplicationContext context;
|
private ApplicationContext context;
|
||||||
|
|
||||||
|
private ApplicationExtensions extensions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts application management.
|
* Starts application management.
|
||||||
*
|
*
|
||||||
|
@ -80,7 +83,7 @@ public class ApplicationManager {
|
||||||
|
|
||||||
ApplicationHandlers handlers = provider().handlersFor(context);
|
ApplicationHandlers handlers = provider().handlersFor(context);
|
||||||
|
|
||||||
ApplicationExtensions extensions = provider().extensionsFor(context);
|
extensions = provider().extensionsFor(context);
|
||||||
extensions.validate();
|
extensions.validate();
|
||||||
|
|
||||||
List<ApplicationLifecycleHandler> lifecycleHandlers = handlers.lifecycleHandlers();
|
List<ApplicationLifecycleHandler> lifecycleHandlers = handlers.lifecycleHandlers();
|
||||||
|
@ -151,6 +154,9 @@ public class ApplicationManager {
|
||||||
|
|
||||||
context.events().fire(context, ApplicationLifecycle.stop);
|
context.events().fire(context, ApplicationLifecycle.stop);
|
||||||
|
|
||||||
|
if (extensions != null)
|
||||||
|
unregister(extensions);
|
||||||
|
|
||||||
stopLifecycleHandlers();
|
stopLifecycleHandlers();
|
||||||
|
|
||||||
log.info("stopping application events for {}", context.name());
|
log.info("stopping application events for {}", context.name());
|
||||||
|
@ -228,6 +234,15 @@ public class ApplicationManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void unregister(ApplicationExtensions extensions) {
|
||||||
|
|
||||||
|
for (ApplicationExtension extension : extensions.extensions())
|
||||||
|
|
||||||
|
extension.stop();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void start(List<ApplicationLifecycleHandler> handlers) {
|
private void start(List<ApplicationLifecycleHandler> handlers) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -14,12 +14,11 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
@ -48,14 +47,14 @@ import org.gcube.smartgears.publishing.SmartgearsProfilePublisher;
|
||||||
import org.gcube.smartgears.security.AuthorizationProvider;
|
import org.gcube.smartgears.security.AuthorizationProvider;
|
||||||
import org.gcube.smartgears.security.AuthorizationProviderFactory;
|
import org.gcube.smartgears.security.AuthorizationProviderFactory;
|
||||||
import org.gcube.smartgears.utils.Utils;
|
import org.gcube.smartgears.utils.Utils;
|
||||||
import org.reflections.Reflections;
|
|
||||||
import org.reflections.scanners.SubTypesScanner;
|
|
||||||
import org.reflections.scanners.TypeAnnotationsScanner;
|
|
||||||
import org.reflections.util.ClasspathHelper;
|
|
||||||
import org.reflections.util.ConfigurationBuilder;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
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.
|
* Default implementation of the {@link Provider} interface.
|
||||||
*
|
*
|
||||||
|
@ -67,8 +66,7 @@ public class DefaultProvider implements Provider {
|
||||||
private static Logger log = LoggerFactory.getLogger(Provider.class);
|
private static Logger log = LoggerFactory.getLogger(Provider.class);
|
||||||
|
|
||||||
private ContainerContext containerContext;
|
private ContainerContext containerContext;
|
||||||
//TODO: do the same with applicationContext (with a map)
|
// TODO: do the same with applicationContext (with a map)
|
||||||
|
|
||||||
|
|
||||||
private File configFile = null;
|
private File configFile = null;
|
||||||
|
|
||||||
|
@ -78,13 +76,13 @@ public class DefaultProvider implements Provider {
|
||||||
|
|
||||||
List<Publisher> publishers;
|
List<Publisher> publishers;
|
||||||
|
|
||||||
|
protected DefaultProvider() {
|
||||||
protected DefaultProvider(){};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ContainerContext containerContext() {
|
public ContainerContext containerContext() {
|
||||||
|
|
||||||
if(containerContext==null){
|
if (containerContext == null) {
|
||||||
ContainerConfiguration configuration = containerConfiguration();
|
ContainerConfiguration configuration = containerConfiguration();
|
||||||
|
|
||||||
Hub hub = new DefaultHub();
|
Hub hub = new DefaultHub();
|
||||||
|
@ -94,27 +92,29 @@ public class DefaultProvider implements Provider {
|
||||||
File file = configuration.persistence().file(container_profile_file_path);
|
File file = configuration.persistence().file(container_profile_file_path);
|
||||||
|
|
||||||
String id = null;
|
String id = null;
|
||||||
if (file.exists()){
|
if (file.exists()) {
|
||||||
log.info("loading persisted state for container");
|
log.info("loading persisted state for container");
|
||||||
try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))){
|
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
|
||||||
id = (String)ois.readObject();
|
id = (String) ois.readObject();
|
||||||
}catch(Exception e){
|
} catch (Exception e) {
|
||||||
log.error("error loading persisted state, creating new uuid",e);
|
log.error("error loading persisted state, creating new uuid", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (id==null){
|
if (id == null) {
|
||||||
id = UUID.randomUUID().toString();
|
id = UUID.randomUUID().toString();
|
||||||
log.info("container id created is {}",id);
|
log.info("container id created is {}", id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthorizationProviderFactory<?> authfactory = configuration.getauthorizationConfiguration().getAuthProviderFactory();
|
AuthorizationProviderFactory<?> authfactory = configuration.getauthorizationConfiguration()
|
||||||
|
.getAuthProviderFactory();
|
||||||
Credentials credentials = configuration.getauthorizationConfiguration().getCredentials();
|
Credentials credentials = configuration.getauthorizationConfiguration().getCredentials();
|
||||||
|
|
||||||
AuthorizationProvider authProvider = authfactory.connect(credentials);
|
AuthorizationProvider authProvider = authfactory.connect(credentials);
|
||||||
|
|
||||||
containerContext = new DefaultContainerContext(id, configuration, hub, lifecycle, authProvider, new Properties());
|
containerContext = new DefaultContainerContext(id, configuration, hub, lifecycle, authProvider,
|
||||||
|
new Properties());
|
||||||
}
|
}
|
||||||
return containerContext;
|
return containerContext;
|
||||||
}
|
}
|
||||||
|
@ -127,12 +127,13 @@ public class DefaultProvider implements Provider {
|
||||||
ContainerConfigurationBinder binder = new ContainerConfigurationBinder();
|
ContainerConfigurationBinder binder = new ContainerConfigurationBinder();
|
||||||
|
|
||||||
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
|
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
if (currentClassLoader.getParent()!=null && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())){
|
if (currentClassLoader.getParent() != null
|
||||||
|
&& !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())) {
|
||||||
log.trace("probably i'm in a webapp classloader");
|
log.trace("probably i'm in a webapp classloader");
|
||||||
currentClassLoader = currentClassLoader.getParent();
|
currentClassLoader = currentClassLoader.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ContainerHandler> defaultHandlers = binder.bindHandlers(currentClassLoader);
|
List<ContainerHandler> defaultHandlers = binder.bindHandlers(currentClassLoader);
|
||||||
|
|
||||||
return defaultHandlers;
|
return defaultHandlers;
|
||||||
|
|
||||||
|
@ -150,31 +151,34 @@ public class DefaultProvider implements Provider {
|
||||||
ApplicationConfiguration embedded = configurationFor(application);
|
ApplicationConfiguration embedded = configurationFor(application);
|
||||||
ApplicationConfiguration external = context.configuration().app(application.getContextPath());
|
ApplicationConfiguration external = context.configuration().app(application.getContextPath());
|
||||||
|
|
||||||
//shouldn't happen: management shouldn't have started at all
|
// shouldn't happen: management shouldn't have started at all
|
||||||
if (embedded==null && external==null)
|
if (embedded == null && external == null)
|
||||||
throw new AssertionError("application @ "+application.getContextPath()+" is not distributed with "
|
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);
|
+ configuration_file_path + " and there is no external configuration for it in "
|
||||||
|
+ container_configuraton_file_path);
|
||||||
|
|
||||||
//no embedded configuration
|
// no embedded configuration
|
||||||
if (embedded == null) {
|
if (embedded == null) {
|
||||||
|
|
||||||
configuration = external ;
|
configuration = external;
|
||||||
|
|
||||||
log.info("loaded configuration for application "+configuration.name()+" from "+container_configuraton_file_path);
|
log.info("loaded configuration for application " + configuration.name() + " from "
|
||||||
}
|
+ container_configuraton_file_path);
|
||||||
else {
|
} else {
|
||||||
|
|
||||||
configuration = embedded;
|
configuration = embedded;
|
||||||
|
|
||||||
if (external == null)
|
if (external == null)
|
||||||
|
|
||||||
log.info("loaded configuration for application "+configuration.name()+" from "+configuration_file_path);
|
log.info("loaded configuration for application " + configuration.name() + " from "
|
||||||
|
+ configuration_file_path);
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
||||||
configuration.merge(external);
|
configuration.merge(external);
|
||||||
|
|
||||||
log.info("loaded configuration for application "+configuration.name()+" from "+configuration_file_path+" and "+container_configuraton_file_path);
|
log.info("loaded configuration for application " + configuration.name() + " from "
|
||||||
|
+ configuration_file_path + " and " + container_configuraton_file_path);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,16 +191,16 @@ public class DefaultProvider implements Provider {
|
||||||
ApplicationLifecycle lifecycle = new ApplicationLifecycle(hub, configuration.name());
|
ApplicationLifecycle lifecycle = new ApplicationLifecycle(hub, configuration.name());
|
||||||
|
|
||||||
File file = bridgedConfiguration.persistence().file(profile_file_path);
|
File file = bridgedConfiguration.persistence().file(profile_file_path);
|
||||||
String id= null;
|
String id = null;
|
||||||
if (file.exists()){
|
if (file.exists()) {
|
||||||
log.info("loading persisted state for application {}", application.getContextPath());
|
log.info("loading persisted state for application {}", application.getContextPath());
|
||||||
try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))){
|
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
|
||||||
id = (String)ois.readObject();
|
id = (String) ois.readObject();
|
||||||
}catch(Exception e){
|
} catch (Exception e) {
|
||||||
log.error("error loading persisted state, creating new uuid",e);
|
log.error("error loading persisted state, creating new uuid", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (id==null)
|
if (id == null)
|
||||||
id = UUID.randomUUID().toString();
|
id = UUID.randomUUID().toString();
|
||||||
|
|
||||||
return new DefaultApplicationContext(id, context, application, bridgedConfiguration, hub, lifecycle,
|
return new DefaultApplicationContext(id, context, application, bridgedConfiguration, hub, lifecycle,
|
||||||
|
@ -208,14 +212,13 @@ public class DefaultProvider implements Provider {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
||||||
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder();
|
ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder();
|
||||||
|
|
||||||
|
// searching for smartegars related application handlers in the common
|
||||||
|
// classloader
|
||||||
//searching for smartegars related application handlers in the common classloader
|
|
||||||
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
|
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
if (currentClassLoader.getParent()!=null && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())){
|
if (currentClassLoader.getParent() != null
|
||||||
|
&& !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())) {
|
||||||
log.trace("probably i'm in a webapp classloader");
|
log.trace("probably i'm in a webapp classloader");
|
||||||
currentClassLoader = currentClassLoader.getParent();
|
currentClassLoader = currentClassLoader.getParent();
|
||||||
}
|
}
|
||||||
|
@ -224,15 +227,14 @@ public class DefaultProvider implements Provider {
|
||||||
|
|
||||||
return defaultHandlers;
|
return defaultHandlers;
|
||||||
|
|
||||||
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
|
||||||
throw new RuntimeException("cannot install handlers for application @ " + context.name()+" (see cause) ", e);
|
throw new RuntimeException("cannot install handlers for application @ " + context.name() + " (see cause) ",
|
||||||
|
e);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApplicationExtensions extensionsFor(ApplicationContext context) {
|
public ApplicationExtensions extensionsFor(ApplicationContext context) {
|
||||||
|
|
||||||
|
@ -248,7 +250,8 @@ public class DefaultProvider implements Provider {
|
||||||
config = getClass().getResourceAsStream(default_extensions_file_path);
|
config = getClass().getResourceAsStream(default_extensions_file_path);
|
||||||
|
|
||||||
if (config == null)
|
if (config == null)
|
||||||
throw new IllegalStateException("invalid distribution: cannot find " + default_extensions_file_path);
|
throw new IllegalStateException(
|
||||||
|
"invalid distribution: cannot find " + default_extensions_file_path);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
log.info("{} uses custom extensions @ {}", context.name(), extensions_file_path);
|
log.info("{} uses custom extensions @ {}", context.name(), extensions_file_path);
|
||||||
|
@ -259,12 +262,12 @@ public class DefaultProvider implements Provider {
|
||||||
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
|
||||||
throw new RuntimeException("cannot install extensions for application @ " + context.name()+" (see cause) ", e);
|
throw new RuntimeException(
|
||||||
|
"cannot install extensions for application @ " + context.name() + " (see cause) ", e);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SmartGearsConfiguration smartgearsConfiguration() {
|
public SmartGearsConfiguration smartgearsConfiguration() {
|
||||||
|
|
||||||
|
@ -313,7 +316,7 @@ public class DefaultProvider implements Provider {
|
||||||
|
|
||||||
private ContainerConfiguration containerConfiguration() {
|
private ContainerConfiguration containerConfiguration() {
|
||||||
|
|
||||||
if (configFile==null) {
|
if (configFile == null) {
|
||||||
|
|
||||||
String home = Utils.home();
|
String home = Utils.home();
|
||||||
|
|
||||||
|
@ -324,22 +327,24 @@ public class DefaultProvider implements Provider {
|
||||||
File homeDir = new File(home);
|
File homeDir = new File(home);
|
||||||
|
|
||||||
if (!(homeDir.exists() && homeDir.isDirectory() && homeDir.canRead() && homeDir.canWrite()))
|
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");
|
throw new IllegalStateException("invalid node configuration: home " + home
|
||||||
|
+ " does not exist or is not a directory or cannot be accessed in read/write mode");
|
||||||
configFile = new File(homeDir,container_configuraton_file_path);
|
|
||||||
|
|
||||||
|
configFile = new File(homeDir, container_configuraton_file_path);
|
||||||
|
|
||||||
log.trace("reading container configuration @ {} ", configFile.getAbsolutePath());
|
log.trace("reading container configuration @ {} ", configFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(configFile.exists() && configFile.canRead()))
|
if (!(configFile.exists() && configFile.canRead()))
|
||||||
throw new IllegalStateException("invalid node configuration: file "+configFile.getAbsolutePath()+" does not exist or cannot be accessed");
|
throw new IllegalStateException("invalid node configuration: file " + configFile.getAbsolutePath()
|
||||||
|
+ " does not exist or cannot be accessed");
|
||||||
|
|
||||||
ContainerConfiguration configuration;
|
ContainerConfiguration configuration;
|
||||||
try (InputStream stream = new FileInputStream(configFile)){
|
try (InputStream stream = new FileInputStream(configFile)) {
|
||||||
configuration= new ContainerConfigurationBinder().load(stream);
|
configuration = new ContainerConfigurationBinder().load(stream);
|
||||||
}catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalStateException("invalid node configuration: file "+configFile.getAbsolutePath()+" is invalid", e);
|
throw new IllegalStateException(
|
||||||
|
"invalid node configuration: file " + configFile.getAbsolutePath() + " is invalid", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return configuration;
|
return configuration;
|
||||||
|
@ -348,27 +353,42 @@ public class DefaultProvider implements Provider {
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<Publisher> publishers() {
|
public synchronized List<Publisher> publishers() {
|
||||||
if (this.publishers == null) {
|
if (this.publishers == null) {
|
||||||
//retrieve from root class loader
|
|
||||||
Collection<URL> urls = ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader());
|
|
||||||
urls.removeIf(url -> url.toString().endsWith(".so") || url.toString().endsWith(".zip") );
|
|
||||||
|
|
||||||
|
Set<Class<?>> annotatedPublishers;
|
||||||
|
|
||||||
ConfigurationBuilder reflectionConf = new ConfigurationBuilder().addUrls(urls).setScanners(new TypeAnnotationsScanner(), new SubTypesScanner());
|
try (ScanResult result = new ClassGraph().enableClassInfo().enableAnnotationInfo()
|
||||||
|
.addClassLoader(Thread.currentThread().getContextClassLoader()).scan()) {
|
||||||
|
|
||||||
Reflections reflection = new Reflections(reflectionConf);
|
ClassInfoList classInfos = result.getClassesWithAnnotation(SmartgearsProfilePublisher.class.getName());
|
||||||
|
|
||||||
|
annotatedPublishers = classInfos.stream().map(ClassInfo::loadClass)
|
||||||
|
.filter(c -> Publisher.class.isAssignableFrom(c)).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
*/
|
||||||
|
|
||||||
Set<Class<?>> annotatedPublishers = reflection.getTypesAnnotatedWith(SmartgearsProfilePublisher.class);
|
|
||||||
List<Publisher> foundPublishers = new ArrayList<Publisher>();
|
List<Publisher> foundPublishers = new ArrayList<Publisher>();
|
||||||
for (Class<?> annotatedPublisher: annotatedPublishers) {
|
for (Class<?> annotatedPublisher : annotatedPublishers) {
|
||||||
if (Publisher.class.isAssignableFrom(annotatedPublisher))
|
try {
|
||||||
try {
|
foundPublishers.add((Publisher) annotatedPublisher.getDeclaredConstructor().newInstance());
|
||||||
foundPublishers.add((Publisher)annotatedPublisher.newInstance());
|
log.info("added class {} to publishers", annotatedPublisher);
|
||||||
log.info("added class {} to publishers",annotatedPublisher);
|
} catch (Throwable e) {
|
||||||
} catch (Exception e) {
|
log.error("publisher class {} cannot be instantiated", annotatedPublisher.getCanonicalName(), e);
|
||||||
log.error("publisher class {} cannot be instantiated", annotatedPublisher.getCanonicalName(),e);
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
log.warn("publisher class {} discarded, it doesn't implements Publisher class", annotatedPublisher.getCanonicalName());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
this.publishers = foundPublishers;
|
this.publishers = foundPublishers;
|
||||||
|
@ -380,11 +400,9 @@ public class DefaultProvider implements Provider {
|
||||||
return this.publishers;
|
return this.publishers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@Override
|
* @Override public AuthorizationProvider authorizationProvider() { return
|
||||||
public AuthorizationProvider authorizationProvider() {
|
* containerContext.authorizationProvider(); }
|
||||||
return containerContext.authorizationProvider();
|
*/
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue