[New] REST and WS API extends the Activity JSON with ExecutionPolicy data
This commit is contained in:
parent
f28e3d7683
commit
a596793380
|
@ -159,6 +159,7 @@ public class Tags {
|
|||
public static final String WITH_VERSION = "withVersion";
|
||||
public static final String PARAMS = "params";
|
||||
public static final String OPERATION = "operation";
|
||||
public static final String EXECUTION_POLICY = "executionPolicy";
|
||||
|
||||
public static final String APP_VERSION = "appVersion";
|
||||
public static final String SYSTEM_STATE = "systemState";
|
||||
|
|
|
@ -2,6 +2,7 @@ package li.strolch.rest.endpoint;
|
|||
|
||||
import static li.strolch.execution.ExecutionHandler.PARAM_STATE;
|
||||
import static li.strolch.rest.StrolchRestfulConstants.STROLCH_CERTIFICATE;
|
||||
import static li.strolch.rest.model.ToJsonHelper.inExecutionActivityToJson;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.*;
|
||||
|
@ -18,13 +19,13 @@ import li.strolch.execution.service.*;
|
|||
import li.strolch.model.Locator;
|
||||
import li.strolch.model.State;
|
||||
import li.strolch.model.activity.Activity;
|
||||
import li.strolch.model.json.StrolchElementToJsonVisitor;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.privilege.model.Certificate;
|
||||
import li.strolch.rest.RestfulStrolchComponent;
|
||||
import li.strolch.rest.helper.ResponseUtil;
|
||||
import li.strolch.service.LocatorArgument;
|
||||
import li.strolch.service.StringMapArgument;
|
||||
import li.strolch.service.api.Service;
|
||||
import li.strolch.service.api.ServiceArgument;
|
||||
import li.strolch.service.api.ServiceHandler;
|
||||
import li.strolch.service.api.ServiceResult;
|
||||
|
@ -47,8 +48,6 @@ public class ControlResource {
|
|||
|
||||
Certificate cert = (Certificate) request.getAttribute(STROLCH_CERTIFICATE);
|
||||
|
||||
StrolchElementToJsonVisitor visitor = new StrolchElementToJsonVisitor().withVersion().withLocator();
|
||||
|
||||
try (StrolchTransaction tx = openTx(cert, realm)) {
|
||||
ExecutionHandler executionHandler = tx.getContainer().getComponent(ExecutionHandler.class);
|
||||
JsonArray activitiesJ = executionHandler.getActiveActivitiesLocator(realm) //
|
||||
|
@ -56,7 +55,7 @@ public class ControlResource {
|
|||
.map(locator -> tx.getActivityBy(locator.get(1), locator.get(2))) //
|
||||
.filter(Objects::nonNull) //
|
||||
.sorted(Comparator.comparing(Activity::getId)) //
|
||||
.map(activity -> activity.accept(visitor)) //
|
||||
.map(activity -> activity.accept(inExecutionActivityToJson(tx.getRealmName(), executionHandler))) //
|
||||
.collect(JsonArray::new, JsonArray::add, JsonArray::addAll);
|
||||
|
||||
ExecutionHandlerState state = executionHandler.getState(tx.getRealmName());
|
||||
|
@ -69,7 +68,6 @@ public class ControlResource {
|
|||
public Response clearAllActivities(@Context HttpServletRequest request, @QueryParam("realm") String realm) {
|
||||
|
||||
Certificate cert = (Certificate) request.getAttribute(STROLCH_CERTIFICATE);
|
||||
|
||||
RestfulStrolchComponent instance = RestfulStrolchComponent.getInstance();
|
||||
|
||||
ClearAllCurrentExecutionsService svc = new ClearAllCurrentExecutionsService();
|
||||
|
@ -77,7 +75,6 @@ public class ControlResource {
|
|||
arg.realm = realm;
|
||||
|
||||
ServiceResult svcResult = instance.getServiceHandler().doService(cert, svc, arg);
|
||||
|
||||
return ResponseUtil.toResponse(svcResult);
|
||||
}
|
||||
|
||||
|
@ -114,9 +111,7 @@ public class ControlResource {
|
|||
@QueryParam("type") String type, @QueryParam("id") String id, @QueryParam("state") String stateS) {
|
||||
|
||||
Certificate cert = (Certificate) request.getAttribute(STROLCH_CERTIFICATE);
|
||||
|
||||
Locator locator = Activity.locatorFor(type, id);
|
||||
|
||||
RestfulStrolchComponent instance = RestfulStrolchComponent.getInstance();
|
||||
|
||||
StartActivityExecutionService svc = new StartActivityExecutionService();
|
||||
|
@ -124,7 +119,6 @@ public class ControlResource {
|
|||
arg.locator = locator;
|
||||
|
||||
ServiceResult svcResult = instance.getServiceHandler().doService(cert, svc, arg);
|
||||
|
||||
return ResponseUtil.toResponse(svcResult);
|
||||
}
|
||||
|
||||
|
@ -142,76 +136,21 @@ public class ControlResource {
|
|||
|
||||
ServiceHandler serviceHandler = RestfulStrolchComponent.getInstance().getServiceHandler();
|
||||
ServiceResult svcResult;
|
||||
Service<LocatorArgument, ServiceResult> svc;
|
||||
|
||||
switch (state) {
|
||||
case CREATED: {
|
||||
|
||||
SetActionToCreatedService svc = new SetActionToCreatedService();
|
||||
svcResult = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PLANNED: {
|
||||
|
||||
SetActionToPlannedService svc = new SetActionToPlannedService();
|
||||
svcResult = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EXECUTION: {
|
||||
|
||||
ExecuteActionService svc = new ExecuteActionService();
|
||||
svcResult = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WARNING: {
|
||||
|
||||
SetActionToWarningService svc = new SetActionToWarningService();
|
||||
svcResult = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ERROR: {
|
||||
|
||||
SetActionToErrorService svc = new SetActionToErrorService();
|
||||
svcResult = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case STOPPED: {
|
||||
|
||||
SetActionToStoppedService svc = new SetActionToStoppedService();
|
||||
svcResult = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EXECUTED: {
|
||||
|
||||
SetActionToExecutedService svc = new SetActionToExecutedService();
|
||||
svcResult = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CLOSED: {
|
||||
|
||||
SetActionToClosedService svc = new SetActionToClosedService();
|
||||
svcResult = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unhandled state " + state);
|
||||
case CREATED -> svc = new SetActionToCreatedService();
|
||||
case PLANNED -> svc = new SetActionToPlannedService();
|
||||
case EXECUTION -> svc = new ExecuteActionService();
|
||||
case WARNING -> svc = new SetActionToWarningService();
|
||||
case ERROR -> svc = new SetActionToErrorService();
|
||||
case STOPPED -> svc = new SetActionToStoppedService();
|
||||
case EXECUTED -> svc = new SetActionToExecutedService();
|
||||
case CLOSED -> svc = new SetActionToClosedService();
|
||||
default -> throw new UnsupportedOperationException("Unhandled state " + state);
|
||||
}
|
||||
|
||||
svcResult = serviceHandler.doService(cert, svc, arg);
|
||||
return ResponseUtil.toResponse(svcResult);
|
||||
}
|
||||
|
||||
|
@ -221,9 +160,7 @@ public class ControlResource {
|
|||
@QueryParam("type") String type, @QueryParam("id") String id) {
|
||||
|
||||
Certificate cert = (Certificate) request.getAttribute(STROLCH_CERTIFICATE);
|
||||
|
||||
RestfulStrolchComponent instance = RestfulStrolchComponent.getInstance();
|
||||
|
||||
Locator locator = Activity.locatorFor(type, id);
|
||||
|
||||
RemoveActivityFromExecutionService svc = new RemoveActivityFromExecutionService();
|
||||
|
@ -232,7 +169,6 @@ public class ControlResource {
|
|||
arg.locator = locator;
|
||||
|
||||
ServiceResult svcResult = instance.getServiceHandler().doService(cert, svc, arg);
|
||||
|
||||
return ResponseUtil.toResponse(svcResult);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package li.strolch.rest.model;
|
||||
|
||||
import static li.strolch.model.Tags.Json.EXECUTION_POLICY;
|
||||
|
||||
import li.strolch.execution.Controller;
|
||||
import li.strolch.execution.ExecutionHandler;
|
||||
import li.strolch.execution.policy.ExecutionPolicy;
|
||||
import li.strolch.model.json.StrolchElementToJsonVisitor;
|
||||
|
||||
public class ToJsonHelper {
|
||||
|
||||
public static StrolchElementToJsonVisitor inExecutionActivityToJson(String realmName,
|
||||
ExecutionHandler executionHandler) {
|
||||
|
||||
StrolchElementToJsonVisitor visitor = new StrolchElementToJsonVisitor().withVersion().withLocator();
|
||||
return visitor.actionHook((action, actionJ) -> {
|
||||
if (action.inCreatedPhase()) {
|
||||
actionJ.addProperty(EXECUTION_POLICY, "-");
|
||||
return;
|
||||
}
|
||||
|
||||
Controller controller = executionHandler.getController(realmName, action.getRootElement().getLocator());
|
||||
if (controller == null) {
|
||||
actionJ.addProperty(EXECUTION_POLICY, "-");
|
||||
return;
|
||||
}
|
||||
|
||||
ExecutionPolicy executionPolicy = controller.getExecutionPolicy(action.getLocator());
|
||||
actionJ.addProperty(EXECUTION_POLICY, executionPolicy == null ? "-" : executionPolicy.getClass().getName());
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
package li.strolch.websocket;
|
||||
|
||||
import static li.strolch.model.StrolchModelConstants.ROLE_STROLCH_ADMIN;
|
||||
import static li.strolch.model.Tags.Json.*;
|
||||
import static li.strolch.rest.StrolchRestfulConstants.MSG;
|
||||
import static li.strolch.runtime.StrolchConstants.DEFAULT_REALM;
|
||||
import static li.strolch.model.StrolchModelConstants.ROLE_STROLCH_ADMIN;
|
||||
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessage;
|
||||
import static li.strolch.utils.helper.StringHelper.*;
|
||||
|
||||
|
@ -17,8 +17,8 @@ import java.util.Map;
|
|||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import li.strolch.agent.api.ComponentContainer;
|
||||
import li.strolch.agent.api.ObserverHandler;
|
||||
import li.strolch.agent.api.StrolchAgent;
|
||||
import li.strolch.exception.StrolchNotAuthenticatedException;
|
||||
import li.strolch.model.Tags;
|
||||
import li.strolch.privilege.model.Certificate;
|
||||
|
@ -31,18 +31,18 @@ public class WebSocketClient implements MessageHandler.Whole<String> {
|
|||
|
||||
public static final Logger logger = LoggerFactory.getLogger(WebSocketClient.class);
|
||||
|
||||
private final StrolchSessionHandler sessionHandler;
|
||||
private final ComponentContainer container;
|
||||
private final Session session;
|
||||
private final EndpointConfig config;
|
||||
private final String remoteIp;
|
||||
private final Map<String, WebSocketObserverHandler> observerHandlersByRealm;
|
||||
protected final StrolchSessionHandler sessionHandler;
|
||||
protected final StrolchAgent agent;
|
||||
protected final Session session;
|
||||
protected final EndpointConfig config;
|
||||
protected final String remoteIp;
|
||||
protected final Map<String, WebSocketObserverHandler> observerHandlersByRealm;
|
||||
|
||||
private Certificate certificate;
|
||||
protected Certificate certificate;
|
||||
|
||||
public WebSocketClient(ComponentContainer container, Session session, EndpointConfig config) {
|
||||
this.container = container;
|
||||
this.sessionHandler = container.getComponent(StrolchSessionHandler.class);
|
||||
public WebSocketClient(StrolchAgent agent, Session session, EndpointConfig config) {
|
||||
this.agent = agent;
|
||||
this.sessionHandler = agent.getComponent(StrolchSessionHandler.class);
|
||||
this.session = session;
|
||||
this.config = config;
|
||||
this.remoteIp = WebSocketRemoteIp.get();
|
||||
|
@ -62,27 +62,20 @@ public class WebSocketClient implements MessageHandler.Whole<String> {
|
|||
logger.info("Handling message " + msgType);
|
||||
|
||||
switch (msgType) {
|
||||
|
||||
case "Authenticate":
|
||||
handleAuthenticate(jsonObject);
|
||||
break;
|
||||
|
||||
case "ObserverRegister":
|
||||
case "Authenticate" -> handleAuthenticate(jsonObject);
|
||||
case "ObserverRegister" -> {
|
||||
assertAuthenticated(msgType);
|
||||
handleRegister(jsonObject);
|
||||
break;
|
||||
case "ObserverUnregister":
|
||||
}
|
||||
case "ObserverUnregister" -> {
|
||||
assertAuthenticated(msgType);
|
||||
handleUnregister(jsonObject);
|
||||
break;
|
||||
|
||||
default:
|
||||
logger.error("Unhandled Event msgType: " + msgType);
|
||||
}
|
||||
default -> logger.error("Unhandled Event msgType: " + msgType);
|
||||
}
|
||||
}
|
||||
|
||||
public void assertAuthenticated(String type) {
|
||||
|
||||
if (this.certificate == null) {
|
||||
logger.error("Received " + type + " request, but not yet authed!");
|
||||
close(CloseReason.CloseCodes.PROTOCOL_ERROR, "Not yet authed!");
|
||||
|
@ -92,8 +85,8 @@ public class WebSocketClient implements MessageHandler.Whole<String> {
|
|||
try {
|
||||
this.sessionHandler.validate(this.certificate, this.remoteIp);
|
||||
} catch (RuntimeException e) {
|
||||
logger.error("Received " + type + " request, but authentication is not valid anymore: " + ExceptionHelper
|
||||
.getExceptionMessage(e));
|
||||
logger.error("Received " + type + " request, but authentication is not valid anymore: "
|
||||
+ ExceptionHelper.getExceptionMessage(e));
|
||||
close(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "Not yet authed!");
|
||||
}
|
||||
}
|
||||
|
@ -122,15 +115,16 @@ public class WebSocketClient implements MessageHandler.Whole<String> {
|
|||
JsonObject params = jsonObject.get(PARAMS).getAsJsonObject();
|
||||
|
||||
this.observerHandlersByRealm.computeIfAbsent(objectType, s -> {
|
||||
ObserverHandler observerHandler = this.container.getRealm(realm).getObserverHandler();
|
||||
return getWebSocketObserverHandler(observerHandler);
|
||||
ObserverHandler observerHandler = this.agent.getRealm(realm).getObserverHandler();
|
||||
return getWebSocketObserverHandler(realm, observerHandler);
|
||||
}).register(objectType, type, params);
|
||||
logger.info(
|
||||
this.certificate.getUsername() + " registered for " + objectType + " " + type + " params: " + params);
|
||||
|
||||
String username = this.certificate.getUsername();
|
||||
logger.info(username + " registered for " + objectType + " " + type + " params: " + params);
|
||||
}
|
||||
|
||||
protected WebSocketObserverHandler getWebSocketObserverHandler(ObserverHandler observerHandler) {
|
||||
return new WebSocketObserverHandler(observerHandler, this);
|
||||
protected WebSocketObserverHandler getWebSocketObserverHandler(String realm, ObserverHandler observerHandler) {
|
||||
return new WebSocketObserverHandler(this.agent, realm, observerHandler, this);
|
||||
}
|
||||
|
||||
private void handleUnregister(JsonObject jsonObject) {
|
||||
|
@ -148,9 +142,8 @@ public class WebSocketClient implements MessageHandler.Whole<String> {
|
|||
}
|
||||
|
||||
private void handleAuthenticate(JsonObject jsonObject) {
|
||||
|
||||
if (!jsonObject.has("authToken") || !jsonObject.has("username")) {
|
||||
logger.error("Received invalid authentication request: " + jsonObject.toString());
|
||||
logger.error("Received invalid authentication request: " + jsonObject);
|
||||
close(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "Invalid authentication");
|
||||
return;
|
||||
}
|
||||
|
@ -159,7 +152,7 @@ public class WebSocketClient implements MessageHandler.Whole<String> {
|
|||
String username = jsonObject.get("username").getAsString();
|
||||
|
||||
if (authToken.isEmpty() || username.isEmpty()) {
|
||||
logger.error("Received invalid authentication request: " + jsonObject.toString());
|
||||
logger.error("Received invalid authentication request: " + jsonObject);
|
||||
close(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "Invalid authentication");
|
||||
return;
|
||||
}
|
||||
|
@ -204,9 +197,7 @@ public class WebSocketClient implements MessageHandler.Whole<String> {
|
|||
} catch (IOException e) {
|
||||
logger.error("Failed to close client after invalid authentication!", e);
|
||||
}
|
||||
this.observerHandlersByRealm.keySet().forEach(realm -> {
|
||||
this.observerHandlersByRealm.get(realm).unregisterAll();
|
||||
});
|
||||
this.observerHandlersByRealm.keySet().forEach(realm -> this.observerHandlersByRealm.get(realm).unregisterAll());
|
||||
}
|
||||
|
||||
public void onError(Throwable t) {
|
||||
|
|
|
@ -4,18 +4,18 @@ import javax.websocket.*;
|
|||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import li.strolch.agent.api.ComponentContainer;
|
||||
import li.strolch.agent.api.StrolchAgent;
|
||||
import li.strolch.rest.RestfulStrolchComponent;
|
||||
|
||||
@ServerEndpoint("/websocket/strolch/observer")
|
||||
public class WebSocketEndpoint {
|
||||
|
||||
private ConcurrentHashMap<Session, WebSocketClient> clientMap = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<Session, WebSocketClient> clientMap = new ConcurrentHashMap<>();
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session, EndpointConfig config) {
|
||||
ComponentContainer container = RestfulStrolchComponent.getInstance().getContainer();
|
||||
WebSocketClient webSocketClient = new WebSocketClient(container, session, config);
|
||||
StrolchAgent agent = RestfulStrolchComponent.getInstance().getAgent();
|
||||
WebSocketClient webSocketClient = new WebSocketClient(agent, session, config);
|
||||
this.clientMap.put(session, webSocketClient);
|
||||
session.addMessageHandler(webSocketClient);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package li.strolch.websocket;
|
|||
import static li.strolch.model.Tags.Json.*;
|
||||
import static li.strolch.rest.StrolchRestfulConstants.DATA;
|
||||
import static li.strolch.rest.StrolchRestfulConstants.MSG;
|
||||
import static li.strolch.rest.model.ToJsonHelper.inExecutionActivityToJson;
|
||||
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessage;
|
||||
import static li.strolch.utils.helper.StringHelper.DASH;
|
||||
|
||||
|
@ -16,6 +17,8 @@ import com.google.gson.JsonArray;
|
|||
import com.google.gson.JsonObject;
|
||||
import li.strolch.agent.api.Observer;
|
||||
import li.strolch.agent.api.ObserverHandler;
|
||||
import li.strolch.agent.api.StrolchAgent;
|
||||
import li.strolch.execution.ExecutionHandler;
|
||||
import li.strolch.model.StrolchRootElement;
|
||||
import li.strolch.model.Tags;
|
||||
import li.strolch.model.json.StrolchElementToJsonVisitor;
|
||||
|
@ -28,13 +31,18 @@ public class WebSocketObserverHandler implements Observer {
|
|||
|
||||
protected static final Logger logger = LoggerFactory.getLogger(WebSocketObserverHandler.class);
|
||||
|
||||
protected final StrolchAgent agent;
|
||||
protected final String realmName;
|
||||
protected ObserverHandler observerHandler;
|
||||
protected WebSocketClient client;
|
||||
|
||||
protected MapOfSets<String, String> observedTypes;
|
||||
protected Map<String, JsonObject> params;
|
||||
|
||||
public WebSocketObserverHandler(ObserverHandler observerHandler, WebSocketClient client) {
|
||||
public WebSocketObserverHandler(StrolchAgent agent, String realmName, ObserverHandler observerHandler,
|
||||
WebSocketClient client) {
|
||||
this.agent = agent;
|
||||
this.realmName = realmName;
|
||||
this.observerHandler = observerHandler;
|
||||
this.client = client;
|
||||
this.observedTypes = new MapOfSets<>();
|
||||
|
@ -113,7 +121,11 @@ public class WebSocketObserverHandler implements Observer {
|
|||
|
||||
protected JsonObject toJson(StrolchRootElement e) {
|
||||
|
||||
StrolchElementToJsonVisitor visitor = new StrolchElementToJsonVisitor();
|
||||
StrolchElementToJsonVisitor visitor;
|
||||
if (e.isActivity())
|
||||
visitor = inExecutionActivityToJson(this.realmName, this.agent.getComponent(ExecutionHandler.class));
|
||||
else
|
||||
visitor = new StrolchElementToJsonVisitor();
|
||||
|
||||
JsonObject params = this.params.get(e.getType());
|
||||
if (params == null)
|
||||
|
|
Loading…
Reference in New Issue