use of org.openremote.model.Container in project openremote by openremote.
the class GatewayService method start.
@Override
public void start(Container container) throws Exception {
if (!active) {
return;
}
List<GatewayAsset> gateways = assetStorageService.findAll(new AssetQuery().types(GatewayAsset.class)).stream().map(asset -> (GatewayAsset) asset).collect(Collectors.toList());
List<String> gatewayIds = gateways.stream().map(Asset::getId).collect(Collectors.toList());
gateways = gateways.stream().filter(gateway -> Arrays.stream(gateway.getPath()).noneMatch(p -> !p.equals(gateway.getId()) && gatewayIds.contains(p))).collect(Collectors.toList());
if (!gateways.isEmpty()) {
LOG.info("Directly registered gateways found = " + gateways.size());
gateways.forEach(gateway -> {
// Check if client has been created
boolean hasClientId = gateway.getClientId().isPresent();
boolean hasClientSecret = gateway.getClientSecret().isPresent();
if (!hasClientId || !hasClientSecret) {
createUpdateGatewayServiceUser(gateway);
}
// Create connector
GatewayConnector connector = new GatewayConnector(assetStorageService, assetProcessingService, executorService, gateway);
gatewayConnectorMap.put(gateway.getId().toLowerCase(Locale.ROOT), connector);
// Get IDs of all assets under this gateway
List<Asset<?>> gatewayAssets = assetStorageService.findAll(new AssetQuery().parents(gateway.getId()).select(new AssetQuery.Select().excludeAttributes()).recursive(true));
gatewayAssets.forEach(asset -> assetIdGatewayIdMap.put(asset.getId(), gateway.getId()));
});
}
}
use of org.openremote.model.Container in project openremote by openremote.
the class ClientEventService method init.
@Override
public void init(Container container) throws Exception {
timerService = container.getService(TimerService.class);
messageBrokerService = container.getService(MessageBrokerService.class);
identityService = container.getService(ManagerIdentityService.class);
gatewayService = container.getService(GatewayService.class);
eventSubscriptions = new EventSubscriptions(container.getService(TimerService.class));
messageBrokerService.getContext().getTypeConverterRegistry().addTypeConverters(new EventTypeConverters());
// TODO: Remove prefix and just use event type then use a subscription wrapper to pass subscription ID around
messageBrokerService.getContext().addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("websocket://" + WEBSOCKET_EVENTS).routeId("FromClientWebsocketEvents").process(exchange -> exchange.getIn().setHeader(HEADER_CONNECTION_TYPE, HEADER_CONNECTION_TYPE_WEBSOCKET)).to(ClientEventService.CLIENT_EVENT_QUEUE).end();
from(ClientEventService.CLIENT_EVENT_QUEUE).routeId("ClientEvents").choice().when(header(ConnectionConstants.SESSION_OPEN)).process(exchange -> {
String sessionKey = getSessionKey(exchange);
sessionKeyInfoMap.put(sessionKey, createSessionInfo(sessionKey, exchange));
passToInterceptors(exchange);
}).stop().when(or(header(ConnectionConstants.SESSION_CLOSE), header(ConnectionConstants.SESSION_CLOSE_ERROR))).process(exchange -> {
String sessionKey = getSessionKey(exchange);
sessionKeyInfoMap.remove(sessionKey);
eventSubscriptions.cancelAll(sessionKey);
passToInterceptors(exchange);
}).stop().end().process(exchange -> {
// Do basic formatting of exchange
EventRequestResponseWrapper<?> requestResponse = null;
if (exchange.getIn().getBody() instanceof EventRequestResponseWrapper) {
requestResponse = exchange.getIn().getBody(EventRequestResponseWrapper.class);
} else if (exchange.getIn().getBody() instanceof String && exchange.getIn().getBody(String.class).startsWith(EventRequestResponseWrapper.MESSAGE_PREFIX)) {
requestResponse = exchange.getIn().getBody(EventRequestResponseWrapper.class);
}
if (requestResponse != null) {
SharedEvent event = requestResponse.getEvent();
exchange.getIn().setHeader(HEADER_REQUEST_RESPONSE_MESSAGE_ID, requestResponse.getMessageId());
exchange.getIn().setBody(event);
}
if (exchange.getIn().getBody() instanceof String) {
String bodyStr = exchange.getIn().getBody(String.class);
if (bodyStr.startsWith(EventSubscription.SUBSCRIBE_MESSAGE_PREFIX)) {
exchange.getIn().setBody(exchange.getIn().getBody(EventSubscription.class));
} else if (bodyStr.startsWith(CancelEventSubscription.MESSAGE_PREFIX)) {
exchange.getIn().setBody(exchange.getIn().getBody(CancelEventSubscription.class));
} else if (bodyStr.startsWith(SharedEvent.MESSAGE_PREFIX)) {
exchange.getIn().setBody(exchange.getIn().getBody(SharedEvent.class));
}
}
if (exchange.getIn().getBody() instanceof SharedEvent) {
SharedEvent event = exchange.getIn().getBody(SharedEvent.class);
// If there is no timestamp in event, set to system time
if (event.getTimestamp() <= 0) {
event.setTimestamp(timerService.getCurrentTimeMillis());
}
}
}).process(exchange -> passToInterceptors(exchange)).choice().when(body().isInstanceOf(EventSubscription.class)).process(exchange -> {
String sessionKey = getSessionKey(exchange);
EventSubscription<?> subscription = exchange.getIn().getBody(EventSubscription.class);
AuthContext authContext = exchange.getIn().getHeader(Constants.AUTH_CONTEXT, AuthContext.class);
boolean restrictedUser = identityService.getIdentityProvider().isRestrictedUser(authContext);
boolean anonymousUser = authContext == null;
String username = authContext == null ? "anonymous" : authContext.getUsername();
String realm = exchange.getIn().getHeader(Constants.REALM_PARAM_NAME, String.class);
if (authorizeEventSubscription(realm, authContext, subscription)) {
eventSubscriptions.createOrUpdate(sessionKey, restrictedUser, anonymousUser, subscription);
subscription.setSubscribed(true);
sendToSession(sessionKey, subscription);
} else {
LOG.warning("Unauthorized subscription from '" + username + "' in realm '" + realm + "': " + subscription);
sendToSession(sessionKey, new UnauthorizedEventSubscription<>(subscription));
}
}).stop().when(body().isInstanceOf(CancelEventSubscription.class)).process(exchange -> {
String sessionKey = getSessionKey(exchange);
eventSubscriptions.cancel(sessionKey, exchange.getIn().getBody(CancelEventSubscription.class));
}).stop().when(body().isInstanceOf(SharedEvent.class)).choice().when(// Inbound messages from clients
header(HEADER_CONNECTION_TYPE).isNotNull()).to(ClientEventService.CLIENT_EVENT_TOPIC).stop().when(// Outbound message to clients
header(HEADER_CONNECTION_TYPE).isNull()).split(method(eventSubscriptions, "splitForSubscribers")).process(exchange -> {
String sessionKey = getSessionKey(exchange);
sendToSession(sessionKey, exchange.getIn().getBody());
}).stop().endChoice().otherwise().process(exchange -> LOG.info("Unsupported message body: " + exchange.getIn().getBody())).end();
}
});
// Add pending internal subscriptions
if (!pendingInternalSubscriptions.isEmpty()) {
pendingInternalSubscriptions.forEach(subscription -> eventSubscriptions.createOrUpdate(INTERNAL_SESSION_KEY, false, false, subscription));
}
pendingInternalSubscriptions = null;
}
use of org.openremote.model.Container in project openremote by openremote.
the class MessageBrokerService method init.
@SuppressWarnings("deprecation")
@Override
public void init(Container container) throws Exception {
context = new MessageBrokerContext();
final ExecutorServiceManager executorServiceManager = context.getExecutorServiceManager();
executorServiceManager.setThreadNamePattern("#counter# #name#");
executorServiceManager.setThreadPoolFactory(new ThreadPoolFactory() {
@Override
public ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
// This is an unlimited pool used probably only be multicast aggregation
return new ContainerExecutor(getExecutorName("MessagingPool", threadFactory), 1, Integer.MAX_VALUE, 10, -1);
}
@Override
public ExecutorService newThreadPool(ThreadPoolProfile profile, ThreadFactory threadFactory) {
// This pool is used by SEDA consumers, so the endpoint parameters define the pool and queue sizes
return new ContainerExecutor(getExecutorName("Messaging", threadFactory), profile.getPoolSize(), profile.getMaxPoolSize(), profile.getKeepAliveTime(), profile.getMaxQueueSize());
}
@Override
public ScheduledExecutorService newScheduledThreadPool(ThreadPoolProfile profile, ThreadFactory threadFactory) {
return new ContainerScheduledExecutor(getExecutorName("MessagingTasks", threadFactory), profile.getPoolSize());
}
protected String getExecutorName(String name, ThreadFactory threadFactory) {
if (threadFactory instanceof CamelThreadFactory) {
CamelThreadFactory factory = (CamelThreadFactory) threadFactory;
String camelName = factory.getName();
camelName = camelName.contains("://") ? StringHelper.after(camelName, "://") : camelName;
camelName = camelName.contains("?") ? StringHelper.before(camelName, "?") : camelName;
name = name + "-" + camelName;
}
return name;
}
});
// TODO make configurable in environment
context.disableJMX();
// TODO might need this for errorhandler?
context.setAllowUseOriginalMessage(false);
// Don't use JMS, we do our own correlation
context.setUseBreadcrumb(false);
// Force a quick shutdown of routes with in-flight exchanges
context.getShutdownStrategy().setTimeout(1);
context.getShutdownStrategy().setSuppressLoggingOnTimeout(true);
context.setStreamCaching(true);
StreamCachingStrategy streamCachingStrategy = new DefaultStreamCachingStrategy();
// Half megabyte
streamCachingStrategy.setSpoolThreshold(524288);
context.setStreamCachingStrategy(streamCachingStrategy);
context.setErrorHandlerBuilder(new org.apache.camel.builder.LoggingErrorHandlerBuilder() {
@Override
public Processor createErrorHandler(RouteContext routeContext, Processor processor) {
// TODO: Custom error handler?
return super.createErrorHandler(routeContext, processor);
}
});
context.getRegistry().put(Container.class.getName(), container);
String allowedOrigin = getString(container.getConfig(), MESSAGE_SESSION_ALLOWED_ORIGIN, MESSAGE_SESSION_ALLOWED_ORIGIN_DEFAULT);
WebsocketComponent websocketComponent = new DefaultWebsocketComponent(container, allowedOrigin);
context.addComponent(WebsocketComponent.NAME, websocketComponent);
context.addComponent("snmp", new SnmpComponent());
}
use of org.openremote.model.Container in project openremote by openremote.
the class ManagerWebService method init.
@Override
public void init(Container container) throws Exception {
super.init(container);
String rootRedirectPath = getString(container.getConfig(), ROOT_REDIRECT_PATH, ROOT_REDIRECT_PATH_DEFAULT);
// Modify swagger object mapper to match ours
configureObjectMapper(Json.mapper());
Json.mapper().addMixIn(ServerVariable.class, ServerVariableMixin.class);
// Add swagger resource
OpenAPI oas = new OpenAPI().servers(Collections.singletonList(new Server().url("/api/{realm}/").variables(new ServerVariables().addServerVariable("realm", new ServerVariable()._default("master"))))).schemaRequirement("openid", new SecurityScheme().type(SecurityScheme.Type.OAUTH2).flows(new OAuthFlows().authorizationCode(new OAuthFlow().authorizationUrl("/auth/realms/master/protocol/openid-connect/auth").refreshUrl("/auth/realms/master/protocol/openid-connect/token").tokenUrl("/auth/realms/master/protocol/openid-connect/token")))).security(Collections.singletonList(new SecurityRequirement().addList("openid")));
Info info = new Info().title("OpenRemote Manager REST API").description("This is the documentation for the OpenRemote Manager HTTP REST API. Please see the [wiki](https://github.com/openremote/openremote/wiki) for more info.").contact(new Contact().email("info@openremote.io")).license(new License().name("AGPL 3.0").url("https://www.gnu.org/licenses/agpl-3.0.en.html"));
oas.info(info);
SwaggerConfiguration oasConfig = new SwaggerConfiguration().resourcePackages(Stream.of("org.openremote.model.*").collect(Collectors.toSet())).openAPI(oas);
OpenApiResource openApiResource = new OpenApiResource();
openApiResource.openApiConfiguration(oasConfig);
addApiSingleton(openApiResource);
initialised = true;
ResteasyDeployment resteasyDeployment = createResteasyDeployment(container, getApiClasses(), apiSingletons, true);
// Serve REST API
HttpHandler apiHandler = createApiHandler(container, resteasyDeployment);
if (apiHandler != null) {
// Authenticating requests requires a realm, either we receive this in a header or
// we extract it (e.g. from request path segment) and set it as a header before
// processing the request
HttpHandler baseApiHandler = apiHandler;
apiHandler = exchange -> {
String path = exchange.getRelativePath().substring(API_PATH.length());
Matcher realmSubMatcher = PATTERN_REALM_SUB.matcher(path);
if (!realmSubMatcher.matches()) {
exchange.setStatusCode(NOT_FOUND.getStatusCode());
throw new WebApplicationException(NOT_FOUND);
}
// Extract realm from path and push it into REQUEST_HEADER_REALM header
String realm = realmSubMatcher.group(1);
// Move the realm from path segment to header
exchange.getRequestHeaders().put(HttpString.tryFromString(REALM_PARAM_NAME), realm);
URI url = fromUri(exchange.getRequestURL()).replacePath(realmSubMatcher.group(2)).build();
exchange.setRequestURI(url.toString(), true);
exchange.setRequestPath(url.getPath());
exchange.setRelativePath(url.getPath());
baseApiHandler.handleRequest(exchange);
};
}
// Serve deployment files unsecured (explicitly map deployment folders to request paths)
builtInAppDocRoot = Paths.get(getString(container.getConfig(), APP_DOCROOT, APP_DOCROOT_DEFAULT));
customAppDocRoot = Paths.get(getString(container.getConfig(), CUSTOM_APP_DOCROOT, CUSTOM_APP_DOCROOT_DEFAULT));
HttpHandler defaultHandler = null;
if (Files.isDirectory(customAppDocRoot)) {
HttpHandler customBaseFileHandler = createFileHandler(container, customAppDocRoot, null);
defaultHandler = exchange -> {
if (exchange.getRelativePath().isEmpty() || "/".equals(exchange.getRelativePath())) {
exchange.setRelativePath("/index.html");
}
customBaseFileHandler.handleRequest(exchange);
};
}
PathHandler deploymentHandler = defaultHandler != null ? new PathHandler(defaultHandler) : new PathHandler();
// Serve deployment files
if (Files.isDirectory(builtInAppDocRoot)) {
HttpHandler appBaseFileHandler = createFileHandler(container, builtInAppDocRoot, null);
HttpHandler appFileHandler = exchange -> {
if (exchange.getRelativePath().isEmpty() || "/".equals(exchange.getRelativePath())) {
exchange.setRelativePath("/index.html");
}
// Reinstate the full path
exchange.setRelativePath(exchange.getRequestPath());
appBaseFileHandler.handleRequest(exchange);
};
deploymentHandler.addPrefixPath(MANAGER_APP_PATH, appFileHandler);
deploymentHandler.addPrefixPath(SWAGGER_APP_PATH, appFileHandler);
deploymentHandler.addPrefixPath(CONSOLE_LOADER_APP_PATH, appFileHandler);
deploymentHandler.addPrefixPath(SHARED_PATH, appFileHandler);
}
// Redirect / to default app
if (rootRedirectPath != null) {
getRequestHandlers().add(new RequestHandler("Default app redirect", exchange -> exchange.getRequestPath().equals("/"), exchange -> {
LOG.finer("Handling root request, redirecting client to default app");
new RedirectHandler(redirect(exchange, rootRedirectPath)).handleRequest(exchange);
}));
}
if (apiHandler != null) {
getRequestHandlers().add(pathStartsWithHandler("REST API Handler", API_PATH, apiHandler));
}
// This will try and handle any request that makes it to this handler
getRequestHandlers().add(new RequestHandler("Deployment files", exchange -> true, deploymentHandler));
}
use of org.openremote.model.Container in project openremote by openremote.
the class ManagerWebService method createApiHandler.
protected HttpHandler createApiHandler(Container container, ResteasyDeployment resteasyDeployment) {
if (resteasyDeployment == null)
return null;
ServletInfo restServlet = Servlets.servlet("RESTEasy Servlet", HttpServlet30Dispatcher.class).setAsyncSupported(true).setLoadOnStartup(1).addMapping("/*");
DeploymentInfo deploymentInfo = new DeploymentInfo().setDeploymentName("RESTEasy Deployment").setContextPath(API_PATH).addServletContextAttribute(ResteasyDeployment.class.getName(), resteasyDeployment).addServlet(restServlet).setClassLoader(Container.class.getClassLoader());
IdentityService identityService = container.getService(IdentityService.class);
if (identityService != null) {
resteasyDeployment.setSecurityEnabled(true);
} else {
throw new RuntimeException("No identity service deployed, can't enable API security");
}
return addServletDeployment(container, deploymentInfo, resteasyDeployment.isSecurityEnabled());
}
Aggregations