diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlLauncher.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlLauncher.java deleted file mode 100644 index 5dccba3edb..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlLauncher.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.openbase.bco.api.graphql; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import org.openbase.bco.authentication.lib.BCO; -import org.openbase.bco.authentication.lib.jp.JPCredentialsDirectory; -import org.openbase.jps.core.JPService; -import org.openbase.jps.preset.JPDebugMode; -import org.openbase.jul.communication.jp.JPComHost; -import org.openbase.jul.communication.jp.JPComPort; -import org.openbase.jul.pattern.launch.AbstractLauncher; - -public class BcoApiGraphQlLauncher extends AbstractLauncher { - - public BcoApiGraphQlLauncher() throws org.openbase.jul.exception.InstantiationException { - super(BcoApiGraphQlLauncher.class, BcoApiGraphQlSpringLaunchable.class); - } - - @Override - protected void loadProperties() { - JPService.registerProperty(JPDebugMode.class); - JPService.registerProperty(JPCredentialsDirectory.class); - JPService.registerProperty(JPComHost.class); - JPService.registerProperty(JPComPort.class); - } - - /** - * @param args the command line arguments - */ - public static void main(final String[] args) { - BCO.printLogo(); - AbstractLauncher.main(BCO.class, BcoApiGraphQlLauncher.class, args, BcoApiGraphQlLauncher.class); - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlLauncher.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlLauncher.kt new file mode 100644 index 0000000000..8e241f4d24 --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlLauncher.kt @@ -0,0 +1,51 @@ +package org.openbase.bco.api.graphql + +import org.openbase.bco.authentication.lib.BCO +import org.openbase.bco.authentication.lib.jp.JPCredentialsDirectory +import org.openbase.jps.core.JPService +import org.openbase.jps.preset.JPDebugMode +import org.openbase.jul.communication.jp.JPComHost +import org.openbase.jul.communication.jp.JPComPort +import org.openbase.jul.pattern.launch.AbstractLauncher + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ class BcoApiGraphQlLauncher : AbstractLauncher( + BcoApiGraphQlLauncher::class.java, BcoApiGraphQlSpringLaunchable::class.java +) { + override fun loadProperties() { + JPService.registerProperty(JPDebugMode::class.java) + JPService.registerProperty(JPCredentialsDirectory::class.java) + JPService.registerProperty(JPComHost::class.java) + JPService.registerProperty(JPComPort::class.java) + } + + companion object { + /** + * @param args the command line arguments + */ + @JvmStatic + fun main(args: Array) { + BCO.printLogo() + main(BCO::class.java, BcoApiGraphQlLauncher::class.java, args, BcoApiGraphQlLauncher::class.java) + } + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlSpringLaunchable.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlSpringLaunchable.java deleted file mode 100644 index b24cd074f6..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlSpringLaunchable.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.openbase.bco.api.graphql; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import org.openbase.bco.api.graphql.discovery.ServiceAdvertiser; -import org.openbase.bco.registry.remote.Registries; -import org.openbase.bco.registry.remote.login.BCOLogin; -import org.openbase.jps.core.JPService; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.exception.InitializationException; -import org.openbase.jul.exception.InstantiationException; -import org.openbase.jul.iface.Launchable; -import org.openbase.jul.iface.VoidInitializable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.SpringApplication; -import org.springframework.context.ConfigurableApplicationContext; - -import javax.jmdns.ServiceInfo.Fields; -import java.util.HashMap; -import java.util.UUID; - -public class BcoApiGraphQlSpringLaunchable implements Launchable, VoidInitializable { - - private static Logger LOGGER = LoggerFactory.getLogger(BcoApiGraphQlSpringLaunchable.class); - private ServiceAdvertiser serviceAdvertiser; - - - private ConfigurableApplicationContext context; - - @Override - public void init() throws InitializationException { - try { - serviceAdvertiser = ServiceAdvertiser.getInstance(); - } catch (InstantiationException ex) { - throw new InitializationException(this, ex); - } - } - - @Override - public void activate() throws CouldNotPerformException, InterruptedException { - LOGGER.info("Connect to bco..."); - Registries.waitUntilReady(); - - LOGGER.info("Login to bco..."); - BCOLogin.getSession().loginBCOUser(); - - LOGGER.info("Start webserver..."); - context = SpringApplication.run(BcoGraphQlApiSpringBootApplication.class, JPService.getArgs()); - - LOGGER.info("Advertise graphql service..."); - final HashMap qualifiedNameMap = new HashMap<>(); - qualifiedNameMap.put(Fields.Application, "http"); - qualifiedNameMap.put(Fields.Instance, "graphql-bco-openbase"); - qualifiedNameMap.put(Fields.Subtype, "graphql"); - - final HashMap propertyMap = new HashMap<>(); - propertyMap.put("bco-uuid", UUID.randomUUID().toString()); - propertyMap.put("path", "graphql"); - - // lookup port - final int port = Integer.parseInt(context.getEnvironment().getProperty("server.port")); - - // register service advertising - serviceAdvertiser.register(qualifiedNameMap, port, 0, 0, false, propertyMap); - } - - @Override - public void deactivate() { - - LOGGER.info("Logout..."); - serviceAdvertiser.shutdown(); - BCOLogin.getSession().logout(); - - if (isActive()) { - LOGGER.info("Shutdown " + context.getApplicationName()); - SpringApplication.exit(context); - context = null; - } - } - - @Override - public boolean isActive() { - return context != null && context.isActive(); - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlSpringLaunchable.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlSpringLaunchable.kt new file mode 100644 index 0000000000..7873332a77 --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoApiGraphQlSpringLaunchable.kt @@ -0,0 +1,91 @@ +package org.openbase.bco.api.graphql + +import org.openbase.bco.api.graphql.discovery.ServiceAdvertiser +import org.openbase.bco.registry.remote.Registries +import org.openbase.bco.registry.remote.login.BCOLogin +import org.openbase.jps.core.JPService +import org.openbase.jul.exception.* +import org.openbase.jul.iface.Launchable +import org.openbase.jul.iface.VoidInitializable +import org.slf4j.LoggerFactory +import org.springframework.boot.SpringApplication +import org.springframework.context.ConfigurableApplicationContext +import java.util.* +import javax.jmdns.ServiceInfo + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ class BcoApiGraphQlSpringLaunchable : Launchable, VoidInitializable { + private var serviceAdvertiser: ServiceAdvertiser? = null + private var context: ConfigurableApplicationContext? = null + + @Throws(InitializationException::class) + override fun init() { + serviceAdvertiser = try { + ServiceAdvertiser.instance + } catch (ex: InstantiationException) { + throw InitializationException(this, ex) + } + } + + @Throws(CouldNotPerformException::class, InterruptedException::class) + override fun activate() { + LOGGER.info("Connect to bco...") + Registries.waitUntilReady() + LOGGER.info("Login to bco...") + BCOLogin.getSession().loginBCOUser() + LOGGER.info("Start webserver...") + context = SpringApplication.run(BcoGraphQlApiSpringBootApplication::class.java, *JPService.getArgs()) + LOGGER.info("Advertise graphql service...") + val qualifiedNameMap = HashMap() + qualifiedNameMap[ServiceInfo.Fields.Application] = "http" + qualifiedNameMap[ServiceInfo.Fields.Instance] = "graphql-bco-openbase" + qualifiedNameMap[ServiceInfo.Fields.Subtype] = "graphql" + val propertyMap = HashMap() + propertyMap["bco-uuid"] = UUID.randomUUID().toString() + propertyMap["path"] = "graphql" + + // lookup port + context?.getEnvironment()?.getProperty("server.port")?.toInt()?.let { port -> + // register service advertising + serviceAdvertiser!!.register(qualifiedNameMap, port, 0, 0, false, propertyMap) + } + } + + override fun deactivate() { + LOGGER.info("Logout...") + serviceAdvertiser!!.shutdown() + BCOLogin.getSession().logout() + if (isActive) { + LOGGER.info("Shutdown " + context!!.applicationName) + SpringApplication.exit(context) + context = null + } + } + + override fun isActive(): Boolean { + return context != null && context!!.isActive + } + + companion object { + private val LOGGER = LoggerFactory.getLogger(BcoApiGraphQlSpringLaunchable::class.java) + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoGraphQlApiSpringBootApplication.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoGraphQlApiSpringBootApplication.kt similarity index 60% rename from module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoGraphQlApiSpringBootApplication.java rename to module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoGraphQlApiSpringBootApplication.kt index 558fb6fd16..d5ceec9ddc 100644 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoGraphQlApiSpringBootApplication.java +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/BcoGraphQlApiSpringBootApplication.kt @@ -1,4 +1,40 @@ -package org.openbase.bco.api.graphql; +package org.openbase.bco.api.graphql + +import com.google.api.graphql.execution.GuavaListenableFutureSupport +import com.google.api.graphql.rejoiner.* +import com.google.inject.Guice +import com.google.inject.Injector +import com.google.inject.Key +import com.google.inject.Provides +import graphql.Scalars +import graphql.execution.instrumentation.Instrumentation +import graphql.kickstart.execution.context.DefaultGraphQLContext +import graphql.kickstart.execution.context.GraphQLKickstartContext +import graphql.kickstart.servlet.context.GraphQLServletContextBuilder +import graphql.schema.* +import org.dataloader.DataLoader +import org.dataloader.DataLoaderRegistry +import org.openbase.bco.api.graphql.batchloader.BCOUnitBatchLoader +import org.openbase.bco.api.graphql.context.AbstractBCOGraphQLContext +import org.openbase.bco.api.graphql.context.BCOGraphQLWebsocketContext +import org.openbase.bco.api.graphql.context.DefaultBCOGraphQLContext +import org.openbase.bco.api.graphql.schema.RegistrySchemaModule +import org.openbase.bco.api.graphql.schema.SchemaModificationsAdd +import org.openbase.bco.api.graphql.schema.SchemaModificationsRemove +import org.openbase.bco.api.graphql.schema.UnitSchemaModule +import org.openbase.bco.api.graphql.subscriptions.SubscriptionModule +import org.openbase.bco.registry.remote.Registries +import org.openbase.bco.registry.unit.lib.UnitRegistry +import org.openbase.jul.exception.NotAvailableException +import org.openbase.type.domotic.unit.UnitFilterType +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.context.annotation.Bean +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse +import javax.websocket.Session +import javax.websocket.server.HandshakeRequest /*- * #%L @@ -20,122 +56,76 @@ * License along with this program. If not, see * . * #L% - */ + */@SpringBootApplication +open class BcoGraphQlApiSpringBootApplication { + private var injector: Injector? = null -import com.google.api.graphql.execution.GuavaListenableFutureSupport; -import com.google.api.graphql.rejoiner.GqlInputConverter; -import com.google.api.graphql.rejoiner.Schema; -import com.google.api.graphql.rejoiner.SchemaProviderModule; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Provides; -import graphql.Scalars; -import graphql.execution.instrumentation.Instrumentation; -import graphql.kickstart.execution.context.DefaultGraphQLContext; -import graphql.kickstart.execution.context.GraphQLKickstartContext; -import graphql.kickstart.servlet.context.GraphQLServletContextBuilder; -import graphql.schema.*; -import org.dataloader.DataLoader; -import org.dataloader.DataLoaderRegistry; -import org.openbase.bco.api.graphql.batchloader.BCOUnitBatchLoader; -import org.openbase.bco.api.graphql.context.AbstractBCOGraphQLContext; -import org.openbase.bco.api.graphql.context.BCOGraphQLWebsocketContext; -import org.openbase.bco.api.graphql.context.DefaultBCOGraphQLContext; -import org.openbase.bco.api.graphql.schema.RegistrySchemaModule; -import org.openbase.bco.api.graphql.schema.SchemaModificationsAdd; -import org.openbase.bco.api.graphql.schema.SchemaModificationsRemove; -import org.openbase.bco.api.graphql.schema.UnitSchemaModule; -import org.openbase.bco.api.graphql.subscriptions.SubscriptionModule; -import org.openbase.bco.registry.remote.Registries; -import org.openbase.bco.registry.unit.lib.UnitRegistry; -import org.openbase.jul.exception.NotAvailableException; -import org.openbase.type.domotic.unit.UnitConfigType.UnitConfig; -import org.openbase.type.domotic.unit.UnitDataType.UnitData; -import org.openbase.type.domotic.unit.UnitFilterType.UnitFilter; -import org.reactivestreams.Publisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; + @Value("\${graphql.url:/graphql}") + private val graphqlurl: String? = null -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.websocket.Session; -import javax.websocket.server.HandshakeRequest; -import java.util.List; - -import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; - -@SpringBootApplication -public class BcoGraphQlApiSpringBootApplication { - - private static Logger LOGGER = LoggerFactory.getLogger(BcoGraphQlApiSpringBootApplication.class); - - private final Injector injector; - @Value("${graphql.url:/graphql}") - private String graphqlurl; - - { + init { injector = Guice.createInjector( - new SchemaProviderModule(), - - // WARNING: - // The order of those two is important, see either class descriptions for details - new SchemaModificationsRemove(), - new SchemaModificationsAdd(), - - new RegistrySchemaModule(), - new UnitSchemaModule() - ); + SchemaProviderModule(), // WARNING: + // The order of those two is important, see either class descriptions for details + SchemaModificationsRemove(), + SchemaModificationsAdd(), + RegistrySchemaModule(), + UnitSchemaModule() + ) } @Bean - GraphQLSchema schema() { - GraphQLSchema schema = injector.getInstance(Key.get(GraphQLSchema.class, Schema.class)); - - final GraphQLOutputType unitDataOutputType = (GraphQLOutputType) schema.getType("openbase_type_domotic_unit_UnitData"); - final GraphQLOutputType unitConfigOutputType = (GraphQLOutputType) schema.getType("openbase_type_domotic_unit_UnitConfig"); - final GraphQLInputType unitFilterInputType = (GraphQLInputType) schema.getType("Input_openbase_type_domotic_unit_UnitFilter"); - final GqlInputConverter unitFilterInputConverter = GqlInputConverter.newBuilder().add(UnitFilter.getDescriptor().getFile()).build(); - - GraphQLObjectType.Builder builder = GraphQLObjectType.newObject().name("Subscription"); - builder.field(newFieldDefinition().name("units").type(unitDataOutputType) + open fun schema(): GraphQLSchema { + var schema = injector!!.getInstance( + Key.get( + GraphQLSchema::class.java, Schema::class.java + ) + ) + val unitDataOutputType = schema.getType("openbase_type_domotic_unit_UnitData") as GraphQLOutputType? + val unitConfigOutputType = schema.getType("openbase_type_domotic_unit_UnitConfig") as GraphQLOutputType? + val unitFilterInputType = schema.getType("Input_openbase_type_domotic_unit_UnitFilter") as GraphQLInputType? + val unitFilterInputConverter = + GqlInputConverter.newBuilder().add(UnitFilterType.UnitFilter.getDescriptor().file).build() + val builder = GraphQLObjectType.newObject().name("Subscription") + builder.field( + GraphQLFieldDefinition.newFieldDefinition().name("units").type(unitDataOutputType) .argument(GraphQLArgument.newArgument().name("filter").type(unitFilterInputType).build()) - .build()); - builder.field(newFieldDefinition().name("unitConfigs").type(GraphQLList.list(unitConfigOutputType)) + .build() + ) + builder.field( + GraphQLFieldDefinition.newFieldDefinition().name("unitConfigs").type(GraphQLList.list(unitConfigOutputType)) .argument(GraphQLArgument.newArgument().name("filter").type(unitFilterInputType)) .argument(GraphQLArgument.newArgument().name("includeDisabledUnits").type(Scalars.GraphQLBoolean)) - .build()); - - GraphQLCodeRegistry codeRegistry = GraphQLCodeRegistry.newCodeRegistry(schema.getCodeRegistry()) - .dataFetcher(FieldCoordinates.coordinates("Subscription", "units"), new DataFetcher>() { - @Override - public Publisher get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception { - UnitFilter unitFilter = (UnitFilter) unitFilterInputConverter.createProtoBuf(UnitFilter.getDescriptor(), UnitFilter.newBuilder(), dataFetchingEnvironment.getArgument("filter")); - return SubscriptionModule.subscribeUnits(unitFilter); - } - }) - .dataFetcher(FieldCoordinates.coordinates("Subscription", "unitConfigs"), new DataFetcher>>() { - @Override - public Publisher> get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception { - UnitFilter unitFilter = (UnitFilter) unitFilterInputConverter.createProtoBuf(UnitFilter.getDescriptor(), UnitFilter.newBuilder(), dataFetchingEnvironment.getArgument("filter")); - - Boolean includeDisabledUnits = false; - if (dataFetchingEnvironment.getArgument("includeDisabledUnits") != null) { - includeDisabledUnits = dataFetchingEnvironment.getArgument("includeDisabledUnits"); - } - - return SubscriptionModule.subscribeUnitConfigs(unitFilter, includeDisabledUnits); + .build() + ) + val codeRegistry = GraphQLCodeRegistry.newCodeRegistry(schema.codeRegistry) + .dataFetcher(FieldCoordinates.coordinates("Subscription", "units"), DataFetcher { dataFetchingEnvironment -> + val unitFilter = unitFilterInputConverter.createProtoBuf( + UnitFilterType.UnitFilter.getDescriptor(), + UnitFilterType.UnitFilter.newBuilder(), + dataFetchingEnvironment.getArgument("filter") + ) as UnitFilterType.UnitFilter + SubscriptionModule.subscribeUnits(unitFilter) + }) + .dataFetcher( + FieldCoordinates.coordinates("Subscription", "unitConfigs"), + DataFetcher { dataFetchingEnvironment -> + val unitFilter = unitFilterInputConverter.createProtoBuf( + UnitFilterType.UnitFilter.getDescriptor(), + UnitFilterType.UnitFilter.newBuilder(), + dataFetchingEnvironment.getArgument("filter") + ) as UnitFilterType.UnitFilter + var includeDisabledUnits = false + if (dataFetchingEnvironment.getArgument("includeDisabledUnits") != null) { + includeDisabledUnits = dataFetchingEnvironment.getArgument("includeDisabledUnits") } + SubscriptionModule.subscribeUnitConfigs(unitFilter, includeDisabledUnits) }) - .build(); - + .build() schema = GraphQLSchema.newSchema(schema) - .subscription(builder.build()) - .codeRegistry(codeRegistry) - .build(); + .subscription(builder.build()) + .codeRegistry(codeRegistry) + .build() //final GraphQLObjectType.Builder queryTypeBuilder = GraphQLObjectType.newObject(schema.getQueryType()); // final GraphQLObjectType.Builder mutationTypeBuilder = GraphQLObjectType.newObject(schema.getMutationType()); @@ -201,9 +191,7 @@ public Boolean get(DataFetchingEnvironment dataFetchingEnvironment) throws Excep .query(queryTypeBuilder.build()) .mutation(mutationTypeBuilder.build()) .codeRegistry(codeRegistry) - .build();*/ - - return schema; + .build();*/return schema } /*@Bean @@ -211,80 +199,74 @@ public GraphQL graphQL() { System.out.println("Add exec strategy.."); return GraphQL.newGraphQL(schema()).subscriptionExecutionStrategy(new SubscriptionExecutionStrategy()).build(); }*/ -// -// @Bean -// public GraphQL graphQL() { -// return GraphQL.newGraphQL(schemaProvider().getSchema()).build(); -// } - + // + // @Bean + // public GraphQL graphQL() { + // return GraphQL.newGraphQL(schemaProvider().getSchema()).build(); + // } @Bean - public Instrumentation instrumentation() { - return GuavaListenableFutureSupport.listenableFutureInstrumentation(); + open fun instrumentation(): Instrumentation { + return GuavaListenableFutureSupport.listenableFutureInstrumentation() } @Bean - public UnitRegistry unitRegistry() { - try { - return Registries.getUnitRegistry(); - } catch (NotAvailableException e) { - e.printStackTrace(); - return null; + open fun unitRegistry(): UnitRegistry? { + return try { + Registries.getUnitRegistry() + } catch (e: NotAvailableException) { + e.printStackTrace() + null } } @Bean @Provides - public DataLoaderRegistry buildDataLoaderRegistry(BCOUnitBatchLoader bcoUnitBatchLoader) { - DataLoaderRegistry registry = new DataLoaderRegistry(); - registry.register(AbstractBCOGraphQLContext.DATA_LOADER_UNITS, new DataLoader<>(bcoUnitBatchLoader)); - return registry; + open fun buildDataLoaderRegistry(bcoUnitBatchLoader: BCOUnitBatchLoader): DataLoaderRegistry { + val registry = DataLoaderRegistry() + registry.register(AbstractBCOGraphQLContext.Companion.DATA_LOADER_UNITS, DataLoader(bcoUnitBatchLoader)) + return registry } @Bean - public GraphQLServletContextBuilder contextBuilder(DataLoaderRegistry dataLoaderRegistry) { - return new GraphQLServletContextBuilder() { - - @Override - public GraphQLKickstartContext build(HttpServletRequest request, HttpServletResponse response) { - return new DefaultBCOGraphQLContext(dataLoaderRegistry, request); + open fun contextBuilder(dataLoaderRegistry: DataLoaderRegistry): GraphQLServletContextBuilder { + return object : GraphQLServletContextBuilder { + override fun build(request: HttpServletRequest, response: HttpServletResponse): GraphQLKickstartContext { + return DefaultBCOGraphQLContext(dataLoaderRegistry, request) } - @Override - public GraphQLKickstartContext build() { - return new DefaultGraphQLContext(dataLoaderRegistry, null); + override fun build(): GraphQLKickstartContext { + return DefaultGraphQLContext(dataLoaderRegistry, null) } - @Override - public GraphQLKickstartContext build(Session session, HandshakeRequest request) { - return new BCOGraphQLWebsocketContext(dataLoaderRegistry, session, request); + override fun build(session: Session, request: HandshakeRequest): GraphQLKickstartContext { + return BCOGraphQLWebsocketContext( + session = session, + handshakeRequest = request, + dataLoaderRegistry = dataLoaderRegistry + ) } - }; - } - - -// @Autowired -// GraphQLDataFetchers graphQLDataFetchers; - -// public static void main(String[] args) throws InterruptedException, CouldNotPerformException { -// String schema = "type Query{hello: String}"; -// -// SchemaParser schemaParser = new SchemaParser(); -// TypeDefinitionRegistry typeDefinitionRegistry = schemaParser.parse(schema); -// -// RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring() -// .type("Query", builder -> builder.dataFetcher("hello", new StaticDataFetcher("world"))) -// .build(); -// -// SchemaGenerator schemaGenerator = new SchemaGenerator(); -// GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeDefinitionRegistry, runtimeWiring); -// -// GraphQL build = GraphQL.newGraphQL(new GraphQLProvider().buildSchema()).build(); -// ExecutionResult executionResult = build.execute("{bookById(id: \"book-1\"){name}}"); -// -// System.out.println(executionResult.getData().toString()); - -// } - + } + } // @Autowired + + // GraphQLDataFetchers graphQLDataFetchers; + // public static void main(String[] args) throws InterruptedException, CouldNotPerformException { + // String schema = "type Query{hello: String}"; + // + // SchemaParser schemaParser = new SchemaParser(); + // TypeDefinitionRegistry typeDefinitionRegistry = schemaParser.parse(schema); + // + // RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring() + // .type("Query", builder -> builder.dataFetcher("hello", new StaticDataFetcher("world"))) + // .build(); + // + // SchemaGenerator schemaGenerator = new SchemaGenerator(); + // GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeDefinitionRegistry, runtimeWiring); + // + // GraphQL build = GraphQL.newGraphQL(new GraphQLProvider().buildSchema()).build(); + // ExecutionResult executionResult = build.execute("{bookById(id: \"book-1\"){name}}"); + // + // System.out.println(executionResult.getData().toString()); + // } /*private static final ImmutableList STATIC_FIELD = ImmutableList.of(newFieldDefinition().type(Scalars.GraphQLString).name("_").staticValue("-").build()); @@ -371,13 +353,16 @@ static GraphQLEnumType convert( return builder.build(); } - /** Returns the GraphQL name of the supplied proto. */ + / ** Returns the GraphQL name of the supplied proto. */ /*static String getReferenceName(Descriptors.GenericDescriptor descriptor) { return CharMatcher.anyOf(".").replaceFrom(descriptor.getFullName(), "_"); } - /** Returns a reference to the GraphQL type corresponding to the supplied proto. */ + / ** Returns a reference to the GraphQL type corresponding to the supplied proto. */ /*static GraphQLTypeReference getReference(Descriptors.GenericDescriptor descriptor) { return new GraphQLTypeReference(getReferenceName(descriptor)); }*/ + companion object { + private val LOGGER = LoggerFactory.getLogger(BcoGraphQlApiSpringBootApplication::class.java) + } } diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/batchloader/BCOUnitBatchLoader.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/batchloader/BCOUnitBatchLoader.java deleted file mode 100644 index c063324e31..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/batchloader/BCOUnitBatchLoader.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.openbase.bco.api.graphql.batchloader; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import lombok.extern.slf4j.Slf4j; -import org.dataloader.BatchLoader; -import org.openbase.bco.registry.unit.lib.UnitRegistry; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.exception.printer.ExceptionPrinter; -import org.openbase.type.domotic.unit.UnitConfigType.UnitConfig; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; - -@Component -public class BCOUnitBatchLoader implements BatchLoader { - - private final org.slf4j.Logger log = LoggerFactory.getLogger(getClass()); - - private final UnitRegistry unitRegistry; - - public BCOUnitBatchLoader(UnitRegistry unitRegistry) { - this.unitRegistry = unitRegistry; - } - - @Override - public CompletionStage> load(List ids) { - - final List unitConfigList = new ArrayList<>(); - - for (String id : ids) { - try { - unitConfigList.add(unitRegistry.getUnitConfigById(id)); - } catch (CouldNotPerformException ex) { - ExceptionPrinter.printHistory("Could not resolve all unit config by id!", ex, log); - } - } - - return CompletableFuture.completedFuture(unitConfigList); - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/batchloader/BCOUnitBatchLoader.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/batchloader/BCOUnitBatchLoader.kt new file mode 100644 index 0000000000..1ddd83fe5a --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/batchloader/BCOUnitBatchLoader.kt @@ -0,0 +1,47 @@ +package org.openbase.bco.api.graphql.batchloader + +import org.dataloader.BatchLoader +import org.openbase.bco.registry.unit.lib.UnitRegistry +import org.openbase.jul.exception.CouldNotPerformException +import org.openbase.jul.exception.printer.ExceptionPrinter +import org.openbase.type.domotic.unit.UnitConfigType +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Component +import java.util.concurrent.CompletableFuture +import java.util.concurrent.CompletionStage + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */@Component +class BCOUnitBatchLoader(private val unitRegistry: UnitRegistry) : BatchLoader { + private val log = LoggerFactory.getLogger(javaClass) + override fun load(ids: List): CompletionStage> { + val unitConfigList: MutableList = ArrayList() + for (id in ids) { + try { + unitConfigList.add(unitRegistry.getUnitConfigById(id)) + } catch (ex: CouldNotPerformException) { + ExceptionPrinter.printHistory("Could not resolve all unit config by id!", ex, log) + } + } + return CompletableFuture.completedFuture(unitConfigList) + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/AbstractBCOGraphQLContext.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/AbstractBCOGraphQLContext.kt similarity index 55% rename from module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/AbstractBCOGraphQLContext.java rename to module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/AbstractBCOGraphQLContext.kt index 916874a12c..5dc614b01f 100644 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/AbstractBCOGraphQLContext.java +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/AbstractBCOGraphQLContext.kt @@ -1,4 +1,9 @@ -package org.openbase.bco.api.graphql.context; +package org.openbase.bco.api.graphql.context + +import graphql.kickstart.execution.context.DefaultGraphQLContext +import org.dataloader.DataLoaderRegistry +import org.openbase.jul.exception.NotAvailableException +import org.openbase.type.domotic.authentication.AuthTokenType /*- * #%L @@ -21,20 +26,17 @@ * . * #L% */ +abstract class AbstractBCOGraphQLContext( + dataLoaderRegistry: DataLoaderRegistry?, +) : DefaultGraphQLContext(dataLoaderRegistry) { + @get:Throws(NotAvailableException::class) + abstract val token: String? + abstract val languageCode: String? -import graphql.kickstart.execution.context.DefaultGraphQLContext; -import org.dataloader.DataLoaderRegistry; -import org.openbase.jul.exception.NotAvailableException; - -public abstract class AbstractBCOGraphQLContext extends DefaultGraphQLContext { - - public static final String DATA_LOADER_UNITS = "units"; + val auth: AuthTokenType.AuthToken? + get() = AuthTokenType.AuthToken.newBuilder().setAuthenticationToken(token).build() - public AbstractBCOGraphQLContext(DataLoaderRegistry dataLoaderRegistry) { - super(dataLoaderRegistry); + companion object { + const val DATA_LOADER_UNITS = "units" } - - public abstract String getToken() throws NotAvailableException; - - public abstract String getLanguageCode(); } diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/BCOGraphQLWebsocketContext.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/BCOGraphQLWebsocketContext.java deleted file mode 100644 index c7b7a3a6ba..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/BCOGraphQLWebsocketContext.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.openbase.bco.api.graphql.context; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import graphql.kickstart.servlet.context.GraphQLWebSocketContext; -import org.dataloader.DataLoaderRegistry; -import org.openbase.jul.exception.NotAvailableException; - -import javax.websocket.Session; -import javax.websocket.server.HandshakeRequest; -import java.util.Locale; - -public class BCOGraphQLWebsocketContext extends AbstractBCOGraphQLContext implements GraphQLWebSocketContext { - - private final Session session; - private final HandshakeRequest handshakeRequest; - - private final String token; - private final String languageCode; - - public BCOGraphQLWebsocketContext(DataLoaderRegistry dataLoaderRegistry, Session session, HandshakeRequest handshakeRequest) { - super(dataLoaderRegistry); - this.session = session; - this.handshakeRequest = handshakeRequest; - - if (handshakeRequest.getHeaders().get("Authorization") != null) { - this.token = handshakeRequest.getHeaders().get("Authorization").get(0); - } else { - this.token = null; - } - - if (handshakeRequest.getHeaders().get("Accept-Language") != null) { - final String language = handshakeRequest.getHeaders().get("Accept-Language").get(0); - this.languageCode = (language != null) ? language : Locale.getDefault().getLanguage(); - } else { - this.languageCode = Locale.getDefault().getLanguage(); - } - } - - @Override - public Session getSession() { - return session; - } - - @Override - public HandshakeRequest getHandshakeRequest() { - return handshakeRequest; - } - - public String getToken() throws NotAvailableException { - if (token == null) { - throw new NotAvailableException("AuthToken"); - } - - return token; - } - - public String getLanguageCode() { - return this.languageCode; - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/BCOGraphQLWebsocketContext.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/BCOGraphQLWebsocketContext.kt new file mode 100644 index 0000000000..28519f4c65 --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/BCOGraphQLWebsocketContext.kt @@ -0,0 +1,41 @@ +package org.openbase.bco.api.graphql.context + +import graphql.kickstart.execution.context.GraphQLKickstartContext +import org.dataloader.DataLoaderRegistry +import java.util.* +import javax.websocket.Session +import javax.websocket.server.HandshakeRequest + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ +data class BCOGraphQLWebsocketContext( + val session: Session, + val handshakeRequest: HandshakeRequest, + private val dataLoaderRegistry: DataLoaderRegistry, +) : AbstractBCOGraphQLContext(dataLoaderRegistry), GraphQLKickstartContext { + override val token: String? + get() + = handshakeRequest.headers[GQLHeader.AUTHORIZATION.key]?.get(0) + override val languageCode: String? + get() + = handshakeRequest.headers[GQLHeader.ACCEPT_LANGUAGE.key]?.get(0) ?: Locale.getDefault().language +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/DefaultBCOGraphQLContext.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/DefaultBCOGraphQLContext.java deleted file mode 100644 index 0652e37a01..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/DefaultBCOGraphQLContext.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.openbase.bco.api.graphql.context; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import org.dataloader.DataLoaderRegistry; -import org.openbase.jul.exception.NotAvailableException; - -import javax.servlet.http.HttpServletRequest; -import java.util.Locale; - -public class DefaultBCOGraphQLContext extends AbstractBCOGraphQLContext { - - private final String token; - private final String languageCode; - - public DefaultBCOGraphQLContext(DataLoaderRegistry dataLoaderRegistry, HttpServletRequest request) { - super(dataLoaderRegistry); - this.token = request.getHeader("Authorization"); - - final String language = request.getHeader("Accept-Language"); - this.languageCode = (language != null) ? language : Locale.getDefault().getLanguage(); - } - - public String getToken() throws NotAvailableException { - if (token == null) { - throw new NotAvailableException("AuthToken"); - } - - return token; - } - - public String getLanguageCode() { - return this.languageCode; - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/AuthorizationError.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/DefaultBCOGraphQLContext.kt similarity index 58% rename from module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/AuthorizationError.java rename to module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/DefaultBCOGraphQLContext.kt index 567d191b5f..8353c4cb83 100644 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/AuthorizationError.java +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/DefaultBCOGraphQLContext.kt @@ -1,4 +1,8 @@ -package org.openbase.bco.api.graphql.error; +package org.openbase.bco.api.graphql.context + +import org.dataloader.DataLoaderRegistry +import java.util.* +import javax.servlet.http.HttpServletRequest /*- * #%L @@ -10,28 +14,23 @@ * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public * License along with this program. If not, see * . * #L% */ - -import graphql.ErrorClassification; - -public class AuthorizationError extends BCOGraphQLError { - - public AuthorizationError(String message, Throwable cause) { - super(message, cause); - } - - @Override - public ErrorClassification getErrorType() { - return ErrorType.AUTHORIZATION_ERROR; - } +class DefaultBCOGraphQLContext( + dataLoaderRegistry: DataLoaderRegistry, + private val request: HttpServletRequest, +) : AbstractBCOGraphQLContext(dataLoaderRegistry) { + override val token: String? + get() = request.getHeader("Authorization") + override val languageCode: String? + get() = request.getHeader("Accept-Language") ?: Locale.getDefault().language } diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/GQLExtensions.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/GQLExtensions.kt new file mode 100644 index 0000000000..0f5fd9cd35 --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/GQLExtensions.kt @@ -0,0 +1,5 @@ +package org.openbase.bco.api.graphql.context + +import graphql.schema.DataFetchingEnvironment + +val DataFetchingEnvironment.context get() = (this.getContext() as AbstractBCOGraphQLContext) diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/GQLHeader.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/GQLHeader.kt new file mode 100644 index 0000000000..f17ba192da --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/context/GQLHeader.kt @@ -0,0 +1,6 @@ +package org.openbase.bco.api.graphql.context + +enum class GQLHeader(var key: String) { + AUTHORIZATION("Authorization"), + ACCEPT_LANGUAGE("Accept-Language") +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceAdvertiser.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceAdvertiser.java deleted file mode 100644 index 83abd735fa..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceAdvertiser.java +++ /dev/null @@ -1,172 +0,0 @@ -package org.openbase.bco.api.graphql.discovery; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import org.openbase.jps.core.JPService; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.exception.InstantiationException; -import org.openbase.jul.exception.printer.ExceptionPrinter; -import org.openbase.jul.iface.Shutdownable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jmdns.JmDNS; -import javax.jmdns.ServiceInfo; -import javax.jmdns.ServiceInfo.Fields; -import java.io.IOException; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.*; - -public class ServiceAdvertiser implements Shutdownable { - - private static Logger LOGGER = LoggerFactory.getLogger(ServiceAdvertiser.class); - - private static ServiceAdvertiser instance; - - private final List domainNameServices; - - private ServiceAdvertiser() throws InstantiationException { - this.domainNameServices = new ArrayList<>(); - - // skip advertising in debug mode - if (JPService.debugMode()) { - return; - } - - -// try { // disabled since its not used yet but causes some network service loops. service might be replaced by another implementation. -// domainNameServices.add(JmDNS.create()); -// } catch (IOException ex) { -// ExceptionPrinter.printHistory("Could not initiate domain name service for default interface!", ex, LOGGER); -// } - -// for (InetAddress localHostLANAddress : getLocalHostLANAddress()) { -// System.err.println("interface: "+localHostLANAddress.getHostAddress()); -// try { -// domainNameServices.add(JmDNS.create(localHostLANAddress)); -// } catch (IOException ex) { -// ExceptionPrinter.printHistory("Could not initiate domain name service for interface: " + localHostLANAddress.getAddress(), ex, LOGGER); -// } -// } - } - - /** - * Method tries to resolve the best local network interface address that can be used to advertise inet services. - */ - private static List getLocalHostLANAddress() { - - final List siteLocal = new ArrayList<>(); - final List local = new ArrayList<>(); - final List loopback = new ArrayList<>(); - - try { - // Iterate all NICs (network interface cards)... - for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) { - // Iterate all IP addresses assigned to each card... - for (Enumeration inetAddrs = ifaces.nextElement().getInetAddresses(); inetAddrs.hasMoreElements(); ) { - InetAddress inetAddr = (InetAddress) inetAddrs.nextElement(); - - // check if site local - if (inetAddr.isSiteLocalAddress()) { - siteLocal.add(inetAddr); - continue; - } - - // check if loopback - if (inetAddr.isLoopbackAddress()) { - loopback.add(inetAddr); - continue; - } - - // add other - local.add(inetAddr); - } - } - - // prefer site local addresses - if (!siteLocal.isEmpty()) { - System.out.println("found site local: " + siteLocal.size()); - return siteLocal; - } - - // prefer local if site local is not available - if (!local.isEmpty()) { - System.out.println("found local: " + local.size()); - return local; - } - - // fallback with loopback device - if (!loopback.isEmpty()) { - System.out.println("found loopback: " + loopback.size()); - return loopback; - } - } catch (final SocketException ex) { - // try default inet address as fallback - try { - local.add(InetAddress.getLocalHost()); - } catch (UnknownHostException e) { - // otherwise just return empty list. - } - } - return local; - } - - public static synchronized ServiceAdvertiser getInstance() throws InstantiationException { - if (instance == null) { - instance = new ServiceAdvertiser(); - } - return instance; - } - - public List register(final HashMap qualifiedNameMap, final int port, final int weight, final int priority, final boolean persistent, final Map props) throws CouldNotPerformException { - try { - final List serviceInfoList = new ArrayList<>(); - for (JmDNS domainNameService : domainNameServices) { - - // Register the service - final ServiceInfo serviceInfo = ServiceInfo.create(qualifiedNameMap, port, weight, priority, false, props); - domainNameService.registerService(serviceInfo); - serviceInfoList.add(serviceInfo); - } - return serviceInfoList; - } catch (IOException ex) { - throw new CouldNotPerformException("Could not register service!", ex); - } - } - - public void deregisterService(final ServiceInfo serviceInfo) { - for (JmDNS domainNameService : domainNameServices) { - domainNameService.unregisterService(serviceInfo); - } - } - - @Override - public void shutdown() { - for (JmDNS domainNameService : domainNameServices) { - domainNameService.unregisterAllServices(); - } - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceAdvertiser.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceAdvertiser.kt new file mode 100644 index 0000000000..cb4ec55219 --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceAdvertiser.kt @@ -0,0 +1,179 @@ +package org.openbase.bco.api.graphql.discovery + +import org.openbase.jps.core.JPService +import org.openbase.jul.exception.CouldNotPerformException +import org.openbase.jul.exception.InstantiationException +import org.openbase.jul.iface.Shutdownable +import org.slf4j.LoggerFactory +import java.io.IOException +import java.net.InetAddress +import java.net.NetworkInterface +import java.net.SocketException +import java.net.UnknownHostException +import java.util.* +import javax.jmdns.JmDNS +import javax.jmdns.ServiceInfo + + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ class ServiceAdvertiser private constructor() : Shutdownable { + private val domainNameServices: List + + init { + domainNameServices = ArrayList() + + // skip advertising in debug mode + if (!JPService.debugMode()) { + // disabled since its not used yet but causes some network service loops. service might be replaced by another implementation. +// try { domainNameServices.add( +// JmDNS.create()) +// } catch (ex: IOException) { +// ExceptionPrinter.printHistory( +// "Could not initiate domain name service for default interface!", +// ex, +// LOGGER +// ) +// } +// +// for (localHostLANAddress in getLocalHostLANAddress()) { +// System.err.println("interface: " + localHostLANAddress.hostAddress) +// try { +// domainNameServices.add(JmDNS.create(localHostLANAddress)) +// } catch (ex: IOException) { +// ExceptionPrinter.printHistory( +// "Could not initiate domain name service for interface: " + localHostLANAddress.address, +// ex, +// LOGGER +// ) +// } +// } + } + } + + @Throws(CouldNotPerformException::class) + fun register( + qualifiedNameMap: HashMap?, + port: Int, + weight: Int, + priority: Int, + persistent: Boolean, + props: Map?, + ): List { + return try { + val serviceInfoList: MutableList = ArrayList() + for (domainNameService in domainNameServices) { + + // Register the service + val serviceInfo = ServiceInfo.create(qualifiedNameMap, port, weight, priority, false, props) + domainNameService.registerService(serviceInfo) + serviceInfoList.add(serviceInfo) + } + serviceInfoList + } catch (ex: IOException) { + throw CouldNotPerformException("Could not register service!", ex) + } + } + + fun deregisterService(serviceInfo: ServiceInfo?) { + for (domainNameService in domainNameServices) { + domainNameService.unregisterService(serviceInfo) + } + } + + override fun shutdown() { + for (domainNameService in domainNameServices) { + domainNameService.unregisterAllServices() + } + } + + companion object { + private val LOGGER = LoggerFactory.getLogger(ServiceAdvertiser::class.java) + + + @get:Throws(InstantiationException::class) + @get:Synchronized + val instance: ServiceAdvertiser by lazy { ServiceAdvertiser() } + + private val localHostLANAddress: List + /** + * Method tries to resolve the best local network interface address that can be used to advertise inet services. + */ + private get() { + val siteLocal: MutableList = ArrayList() + val local: MutableList = ArrayList() + val loopback: MutableList = ArrayList() + try { + // Iterate all NICs (network interface cards)... + val ifaces = NetworkInterface.getNetworkInterfaces() + while (ifaces.hasMoreElements()) { + + // Iterate all IP addresses assigned to each card... + val inetAddrs: Enumeration<*> = ifaces.nextElement().inetAddresses + while (inetAddrs.hasMoreElements()) { + val inetAddr = inetAddrs.nextElement() as InetAddress + + // check if site local + if (inetAddr.isSiteLocalAddress) { + siteLocal.add(inetAddr) + continue + } + + // check if loopback + if (inetAddr.isLoopbackAddress) { + loopback.add(inetAddr) + continue + } + + // add other + local.add(inetAddr) + } + } + + // prefer site local addresses + if (!siteLocal.isEmpty()) { + println("found site local: " + siteLocal.size) + return siteLocal + } + + // prefer local if site local is not available + if (!local.isEmpty()) { + println("found local: " + local.size) + return local + } + + // fallback with loopback device + if (!loopback.isEmpty()) { + println("found loopback: " + loopback.size) + return loopback + } + } catch (ex: SocketException) { + // try default inet address as fallback + try { + local.add(InetAddress.getLocalHost()) + } catch (e: UnknownHostException) { + // otherwise just return empty list. + } + } + return local + } + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceDiscoveryDemo.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceDiscoveryDemo.java deleted file mode 100644 index be1342b6c4..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceDiscoveryDemo.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.openbase.bco.api.graphql.discovery; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import org.openbase.jul.processing.StringProcessor; - -import javax.jmdns.JmDNS; -import javax.jmdns.ServiceEvent; -import javax.jmdns.ServiceListener; -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; - -public class ServiceDiscoveryDemo { - - private static class SampleListener implements ServiceListener { - - private final String serviceNameFilter; - - public SampleListener(final String serviceNameFilter) { - this.serviceNameFilter = serviceNameFilter; - } - - public SampleListener() { - this.serviceNameFilter = null; - } - - @Override - public void serviceAdded(ServiceEvent event) { - } - - @Override - public void serviceRemoved(ServiceEvent event) { - if(serviceNameFilter == null || event.getName().equals(serviceNameFilter)) { - System.out.println("Offline: " + event.getName() + "@" + event.getInfo().getServer() + ":" + event.getInfo().getPort() + " - " + StringProcessor.transformCollectionToString(Arrays.asList(event.getInfo().getHostAddresses().clone()), ", ")); - } - } - - @Override - public void serviceResolved(ServiceEvent event) { - if(serviceNameFilter == null || event.getName().equals(serviceNameFilter)) { - System.out.println("Online: " + event.getName() + "@" + event.getInfo().getServer() + ":" + event.getInfo().getPort() + " - " + StringProcessor.transformCollectionToString(Arrays.asList(event.getInfo().getHostAddresses().clone()), ", ")); - } - } - } - - public static void disabledMain(String[] args) throws InterruptedException { - try { - // Create a JmDNS instance - JmDNS jmdns = JmDNS.create(InetAddress.getLocalHost()); - - // Add a service listener - jmdns.addServiceListener("_http._tcp.local.", new SampleListener("graphql-bco-openbase")); - - // Wait a bit - Thread.sleep(30000); - } catch (UnknownHostException e) { - System.out.println(e.getMessage()); - } catch (IOException e) { - System.out.println(e.getMessage()); - } - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceDiscoveryDemo.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceDiscoveryDemo.kt new file mode 100644 index 0000000000..0d10a4b94f --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/discovery/ServiceDiscoveryDemo.kt @@ -0,0 +1,83 @@ +package org.openbase.bco.api.graphql.discovery + +import org.openbase.jul.processing.StringProcessor +import java.io.IOException +import java.net.InetAddress +import java.net.UnknownHostException +import java.util.* +import javax.jmdns.JmDNS +import javax.jmdns.ServiceEvent +import javax.jmdns.ServiceListener + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ object ServiceDiscoveryDemo { + @Throws(InterruptedException::class) + fun disabledMain(args: Array?) { + try { + // Create a JmDNS instance + val jmdns = JmDNS.create(InetAddress.getLocalHost()) + + // Add a service listener + jmdns.addServiceListener("_http._tcp.local.", SampleListener("graphql-bco-openbase")) + + // Wait a bit + Thread.sleep(30000) + } catch (e: UnknownHostException) { + println(e.message) + } catch (e: IOException) { + println(e.message) + } + } + + private class SampleListener : ServiceListener { + private val serviceNameFilter: String? + + constructor(serviceNameFilter: String?) { + this.serviceNameFilter = serviceNameFilter + } + + constructor() { + serviceNameFilter = null + } + + override fun serviceAdded(event: ServiceEvent) {} + override fun serviceRemoved(event: ServiceEvent) { + if (serviceNameFilter == null || event.name == serviceNameFilter) { + println( + "Offline: " + event.name + "@" + event.info.server + ":" + event.info.port + " - " + StringProcessor.transformCollectionToString( + Arrays.asList(*event.info.hostAddresses.clone()), ", " + ) + ) + } + } + + override fun serviceResolved(event: ServiceEvent) { + if (serviceNameFilter == null || event.name == serviceNameFilter) { + println( + "Online: " + event.name + "@" + event.info.server + ":" + event.info.port + " - " + StringProcessor.transformCollectionToString( + Arrays.asList(*event.info.hostAddresses.clone()), ", " + ) + ) + } + } + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ErrorType.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ArgumentError.kt similarity index 76% rename from module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ErrorType.java rename to module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ArgumentError.kt index e8daff92f5..b7a85d3f43 100644 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ErrorType.java +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ArgumentError.kt @@ -1,4 +1,4 @@ -package org.openbase.bco.api.graphql.error; +package org.openbase.bco.api.graphql.error /*- * #%L @@ -21,15 +21,7 @@ * . * #L% */ +class ArgumentError(cause: Throwable) : BCOGraphQLError(cause) { -import graphql.ErrorClassification; - -public enum ErrorType implements ErrorClassification { - - ARGUMENT_ERROR, - AUTHORIZATION_ERROR, - SERVER_ERROR; - - private ErrorType() { - } + override fun getErrorType() = ErrorType.ARGUMENT_ERROR } diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ArgumentError.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/AuthorizationError.kt similarity index 68% rename from module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ArgumentError.java rename to module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/AuthorizationError.kt index 2f3eed9eb0..8a60743e62 100644 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ArgumentError.java +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/AuthorizationError.kt @@ -1,4 +1,6 @@ -package org.openbase.bco.api.graphql.error; +package org.openbase.bco.api.graphql.error + +import graphql.ErrorClassification /*- * #%L @@ -20,20 +22,8 @@ * License along with this program. If not, see * . * #L% - */ - -import graphql.ErrorClassification; - -public class ArgumentError extends BCOGraphQLError { - - public ArgumentError(final Throwable cause) { - super(cause.getMessage(), cause); + */ class AuthorizationError(cause: Throwable) : BCOGraphQLError(cause) { + override fun getErrorType(): ErrorClassification { + return ErrorType.AUTHORIZATION_ERROR } - - @Override - public ErrorClassification getErrorType() { - return ErrorType.ARGUMENT_ERROR; - } - - } diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/BCOGraphQLError.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/BCOGraphQLError.java index c5d3fdb548..da3a5fc990 100644 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/BCOGraphQLError.java +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/BCOGraphQLError.java @@ -10,12 +10,12 @@ * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public * License along with this program. If not, see * . @@ -32,8 +32,8 @@ public abstract class BCOGraphQLError extends Exception implements GraphQLError private List path = null; private List locations = null; - public BCOGraphQLError(final String message, final Throwable cause) { - super(message, cause); + public BCOGraphQLError(final Throwable cause) { + super(cause.getMessage(), cause); } @Override @@ -41,15 +41,15 @@ public List getLocations() { return locations; } + public void setLocations(final List locations) { + this.locations = locations; + } + @Override public List getPath() { return path; } - public void setLocations(final List locations) { - this.locations = locations; - } - public void setPath(final List path) { this.path = path; } diff --git a/module/api/graphql/src/test/java/org/openbase/bco/api/graphql/BcoGraphQlApiApplicationTests.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ErrorType.kt similarity index 75% rename from module/api/graphql/src/test/java/org/openbase/bco/api/graphql/BcoGraphQlApiApplicationTests.java rename to module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ErrorType.kt index 35c3563dd7..f285ce43c8 100644 --- a/module/api/graphql/src/test/java/org/openbase/bco/api/graphql/BcoGraphQlApiApplicationTests.java +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ErrorType.kt @@ -1,4 +1,6 @@ -package org.openbase.bco.api.graphql; +package org.openbase.bco.api.graphql.error + +import graphql.ErrorClassification /*- * #%L @@ -20,16 +22,6 @@ * License along with this program. If not, see * . * #L% - */ - -//import org.junit.jupiter.api.Test; -//import org.springframework.boot.test.context.SpringBootTest; -// -//@SpringBootTest -class BcoGraphQlApiApplicationTests { - -// @Test -// void contextLoads() { -// } - + */ enum class ErrorType : ErrorClassification { + ARGUMENT_ERROR, AUTHORIZATION_ERROR, SERVER_ERROR } diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/GenericError.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/GenericError.java deleted file mode 100644 index 79b637bc36..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/GenericError.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.openbase.bco.api.graphql.error; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import graphql.ErrorClassification; -import org.openbase.jul.exception.InstantiationException; -import org.openbase.jul.exception.*; - -import javax.crypto.BadPaddingException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.TimeoutException; - -public class GenericError extends BCOGraphQLError { - - private final Throwable initialCause; - - public GenericError(final Throwable cause) { - super(ExceptionProcessor.getInitialCauseMessage(cause), ExceptionProcessor.getInitialCause(cause)); - initialCause = ExceptionProcessor.getInitialCause(getCause()); - } - - @Override - public ErrorClassification getErrorType() { - - // skip if no cause has been set. - if (initialCause == null) { - return ErrorType.SERVER_ERROR; - } - - // compute error type based on initial cause - if (initialCause instanceof TimeoutException - | initialCause instanceof org.openbase.jul.exception.TimeoutException - | initialCause instanceof InterruptedException - | initialCause instanceof FatalImplementationErrorException - | initialCause instanceof NotInitializedException - | initialCause instanceof InstantiationException - | initialCause instanceof InvocationFailedException - | initialCause instanceof ShutdownException - | initialCause instanceof ExecutionException) { - return ErrorType.SERVER_ERROR; - } else if (initialCause instanceof NotAvailableException - | initialCause instanceof VerificationFailedException - | initialCause instanceof InvalidStateException - | initialCause instanceof IllegalArgumentException - | initialCause instanceof NotSupportedException - | initialCause instanceof TypeNotSupportedException - | initialCause instanceof RejectedExecutionException) { - return ErrorType.ARGUMENT_ERROR; - } else if (initialCause instanceof PermissionDeniedException - | initialCause instanceof BadPaddingException) { - return ErrorType.AUTHORIZATION_ERROR; - } else { - return ErrorType.SERVER_ERROR; - } - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/GenericError.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/GenericError.kt new file mode 100644 index 0000000000..cbde1c46e3 --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/GenericError.kt @@ -0,0 +1,62 @@ +package org.openbase.bco.api.graphql.error + +import graphql.ErrorClassification +import org.openbase.jul.exception.* +import org.openbase.jul.exception.ExceptionProcessor.getInitialCause +import java.util.concurrent.RejectedExecutionException +import java.util.concurrent.TimeoutException +import javax.crypto.BadPaddingException + + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ +class GenericError( + cause: Throwable, +) : BCOGraphQLError(getInitialCause(cause)) { + override fun getErrorType(): ErrorClassification = when (cause) { + is TimeoutException, + is org.openbase.jul.exception.TimeoutException, + is InterruptedException, + is FatalImplementationErrorException, + is NotInitializedException, + is InstantiationException, + is InvocationFailedException, + is ShutdownException, + is java.util.concurrent.ExecutionException, + -> ErrorType.SERVER_ERROR + + is NotAvailableException, + is VerificationFailedException, + is InvalidStateException, + is java.lang.IllegalArgumentException, + is NotSupportedException, + is TypeNotSupportedException, + is RejectedExecutionException, + -> ErrorType.ARGUMENT_ERROR + + is PermissionDeniedException, + is BadPaddingException, + -> ErrorType.AUTHORIZATION_ERROR + + else -> ErrorType.SERVER_ERROR + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ServerError.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ServerError.java deleted file mode 100644 index 71d6253e63..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ServerError.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.openbase.bco.api.graphql.error; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import graphql.ErrorClassification; - -import java.util.concurrent.TimeUnit; - -public class ServerError extends BCOGraphQLError { - - public static final long BCO_TIMEOUT_SHORT = 10; - public static final long BCO_TIMEOUT_LONG = 20; - public static final TimeUnit BCO_TIMEOUT_TIME_UNIT = TimeUnit.SECONDS; - - public ServerError(String message) { - this(message, null); - } - - public ServerError(String message, Throwable cause) { - super(message, cause); - } - - public ServerError(final Throwable cause) { - super(cause.getMessage(), cause); - } - - @Override - public ErrorClassification getErrorType() { - return ErrorType.SERVER_ERROR; - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ServerError.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ServerError.kt new file mode 100644 index 0000000000..8a8d537955 --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/error/ServerError.kt @@ -0,0 +1,40 @@ +package org.openbase.bco.api.graphql.error + +import graphql.ErrorClassification +import java.util.concurrent.TimeUnit + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ class ServerError : BCOGraphQLError { + @JvmOverloads + constructor(message: String?, cause: Throwable) : super(cause) + constructor(cause: Throwable) : super(cause) + + override fun getErrorType(): ErrorClassification { + return ErrorType.SERVER_ERROR + } + + companion object { + const val BCO_TIMEOUT_SHORT: Long = 10 + const val BCO_TIMEOUT_LONG: Long = 20 + val BCO_TIMEOUT_TIME_UNIT = TimeUnit.SECONDS + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/handler/CustomGraphQlErrorHandler.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/handler/CustomGraphQlErrorHandler.java deleted file mode 100644 index 379d1cea14..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/handler/CustomGraphQlErrorHandler.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.openbase.bco.api.graphql.handler; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import graphql.ExceptionWhileDataFetching; -import graphql.GraphQLError; -import graphql.kickstart.execution.error.GraphQLErrorHandler; -import org.openbase.bco.api.graphql.error.ArgumentError; -import org.openbase.bco.api.graphql.error.BCOGraphQLError; -import org.openbase.bco.api.graphql.error.ErrorType; -import org.openbase.bco.api.graphql.error.ServerError; -import org.openbase.jul.exception.printer.ExceptionPrinter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; - -@Component -class CustomGraphQlErrorHandler implements GraphQLErrorHandler { - - private final Logger logger = LoggerFactory.getLogger(GraphQLErrorHandler.class); - - @Override - public List processErrors(List list) { - final List errors = new ArrayList<>(); - for (final GraphQLError error : list) { - if (!(error instanceof ExceptionWhileDataFetching)) { - errors.add(error); - continue; - } - - final ExceptionWhileDataFetching dataFetchingError = (ExceptionWhileDataFetching) error; - final Throwable cause = dataFetchingError.getException().getCause(); - - // create as server error if the cause is not a bco graphql error - final BCOGraphQLError bcoError = (cause instanceof BCOGraphQLError) ? ((BCOGraphQLError) cause) : new ServerError(dataFetchingError.getMessage(), cause); - - // update argument error fields - if (bcoError.getErrorType() == ErrorType.ARGUMENT_ERROR) { - bcoError.setLocations(dataFetchingError.getLocations()); - bcoError.setPath(dataFetchingError.getPath()); - } - - // print server errors - if (bcoError.getErrorType() == ErrorType.SERVER_ERROR) { - ExceptionPrinter.printHistory(bcoError, logger); - } - - errors.add(bcoError); - } - return errors; - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/handler/CustomGraphQlErrorHandler.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/handler/CustomGraphQlErrorHandler.kt new file mode 100644 index 0000000000..ac13a23ecd --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/handler/CustomGraphQlErrorHandler.kt @@ -0,0 +1,57 @@ +package org.openbase.bco.api.graphql.handler + +import graphql.ExceptionWhileDataFetching +import graphql.GraphQLError +import graphql.kickstart.execution.error.GraphQLErrorHandler +import org.openbase.bco.api.graphql.error.BCOGraphQLError +import org.openbase.bco.api.graphql.error.ErrorType +import org.openbase.bco.api.graphql.error.ServerError +import org.openbase.jul.exception.printer.ExceptionPrinter +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Component + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */@Component +internal class CustomGraphQlErrorHandler : GraphQLErrorHandler { + private val logger = LoggerFactory.getLogger(GraphQLErrorHandler::class.java) + override fun processErrors(list: List): List = list.mapNotNull { error -> + if (error !is ExceptionWhileDataFetching) { + return@mapNotNull error + } + val cause = error.exception.cause ?: error.exception + + // create as server error if the cause is not a bco graphql error + val bcoError = if (cause is BCOGraphQLError) cause else ServerError(error.message, cause) + + // update argument error fields + if (bcoError.errorType === ErrorType.ARGUMENT_ERROR) { + bcoError.setLocations(error.locations) + bcoError.setPath(error.path) + } + + // print server errors + if (bcoError.errorType === ErrorType.SERVER_ERROR) { + ExceptionPrinter.printHistory(bcoError, logger) + } + bcoError + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/RegistrySchemaModule.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/RegistrySchemaModule.java deleted file mode 100644 index 156aa131e4..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/RegistrySchemaModule.java +++ /dev/null @@ -1,256 +0,0 @@ -package org.openbase.bco.api.graphql.schema; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import com.google.api.graphql.rejoiner.Arg; -import com.google.api.graphql.rejoiner.Mutation; -import com.google.api.graphql.rejoiner.Query; -import com.google.api.graphql.rejoiner.SchemaModule; -import com.google.common.collect.ImmutableList; -import graphql.schema.DataFetchingEnvironment; -import org.openbase.bco.api.graphql.context.AbstractBCOGraphQLContext; -import org.openbase.bco.api.graphql.error.ArgumentError; -import org.openbase.bco.api.graphql.error.BCOGraphQLError; -import org.openbase.bco.api.graphql.error.GenericError; -import org.openbase.bco.api.graphql.error.ServerError; -import org.openbase.bco.authentication.lib.SessionManager; -import org.openbase.bco.authentication.lib.iface.BCOSession; -import org.openbase.bco.registry.remote.Registries; -import org.openbase.bco.registry.remote.session.BCOSessionImpl; -import org.openbase.bco.registry.unit.lib.filter.UnitConfigFilterImpl; -import org.openbase.bco.registry.unit.remote.UnitRegistryRemote; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.extension.protobuf.ProtoBufBuilderProcessor; -import org.openbase.jul.extension.type.processing.LabelProcessor; -import org.openbase.jul.pattern.Filter; -import org.openbase.jul.pattern.ListFilter; -import org.openbase.type.configuration.EntryType; -import org.openbase.type.configuration.MetaConfigType; -import org.openbase.type.domotic.unit.UnitConfigType.UnitConfig; -import org.openbase.type.domotic.unit.UnitFilterType.UnitFilter; -import org.openbase.type.domotic.unit.gateway.GatewayClassType.GatewayClass; -import org.openbase.type.geometry.PoseType; -import org.openbase.type.language.LabelType; -import org.openbase.type.spatial.PlacementConfigType; -import org.openbase.type.spatial.ShapeType; - -import java.util.ArrayList; -import java.util.Base64; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; - -public class RegistrySchemaModule extends SchemaModule { - - // ===================================== Queries =================================================================== - - /** - * Check if an authentication token retrieved by the login method is still valid. - * - * @param token the token to be checked - * @return if the token is valid and can be used to authenticate further requests - */ - @Query("verifyToken") - Boolean verifyToken(@Arg("token") String token) { - //TODO: blocked by https://github.com/openbase/bco.registry/issues/108 - return true; - } - - /** - * Method can be used to request a token of the given bco user. - * - * @param username the name of the user as plain text string. - * @param passwordHash the password hash of the user that need to be generted first (see note below). - * @return the login token. - *

- * Note: The hash of the default admin password is: '''R+gZ+PFuauhav8rRVa3XlWXXSEyi5BcdrbeXLEY3tDQ=''' - * @throws BCOGraphQLError - */ - @Query("login") - String login(@Arg("username") String username, @Arg("password") String passwordHash) throws BCOGraphQLError { - try { - final BCOSession session = new BCOSessionImpl(); - - session.loginUserViaUsername(username, Base64.getDecoder().decode(passwordHash), false); - return session.generateAuthToken(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getAuthenticationToken(); - } catch (RuntimeException | CouldNotPerformException | InterruptedException | TimeoutException ex) { - throw new GenericError(ex); - } - } - - @Query("changePassword") - Boolean changePassword(@Arg("username") String username, @Arg("oldPassword") String oldPassword, @Arg("newPassword") String newPassword) throws BCOGraphQLError { - try { - final String userId = Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUserUnitIdByUserName(username); - - final SessionManager sessionManager = new SessionManager(); - try { - sessionManager.loginUser(userId, oldPassword, false); - } catch (CouldNotPerformException ex) { - throw new ArgumentError(ex); - } - sessionManager.changePassword(userId, oldPassword, newPassword).get(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - - return true; - } catch (RuntimeException | CouldNotPerformException | InterruptedException | ExecutionException | TimeoutException ex) { - throw new GenericError(ex); - } - } - - @Query("unitConfig") - UnitConfig getUnitConfigById(@Arg("id") String id, DataFetchingEnvironment env) throws BCOGraphQLError { - try { - return Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUnitConfigById(id); - } catch (RuntimeException | CouldNotPerformException | InterruptedException ex) { - throw new GenericError(ex); - } - } - - @Query("unitConfigs") - ImmutableList queryGetUnitConfigs(@Arg("filter") UnitFilter unitFilter, @Arg("includeDisabledUnits") Boolean includeDisabledUnits) throws BCOGraphQLError { - return getUnitConfigs(unitFilter, includeDisabledUnits); - } - - @Query("gatewayClasses") - ImmutableList gatewayClasses() throws CouldNotPerformException, InterruptedException { - return ImmutableList.copyOf(Registries.getClassRegistry(true).getGatewayClasses()); - } - - // ===================================== Mutations ================================================================= - - @Mutation("updateUnitConfig") - UnitConfig updateUnitConfig(@Arg("unitConfig") UnitConfig unitConfig) throws BCOGraphQLError { - try { - final UnitConfig.Builder unitConfigBuilder = Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT) - .getUnitConfigById(unitConfig.getId()) - .toBuilder(); - ProtoBufBuilderProcessor.mergeFromWithoutRepeatedFields(unitConfigBuilder, unitConfig); - return Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).updateUnitConfig(unitConfigBuilder.build()).get(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - } catch (RuntimeException | CouldNotPerformException | InterruptedException | ExecutionException | TimeoutException ex) { - throw new GenericError(ex); - } - } - - @Mutation("removeUnitConfig") - UnitConfig removeUnitConfig(@Arg("unitId") String unitId) throws BCOGraphQLError { - try { - final UnitConfig unitConfig = Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUnitConfigById(unitId); - return Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).removeUnitConfig(unitConfig).get(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - } catch (RuntimeException | CouldNotPerformException | InterruptedException | ExecutionException | TimeoutException ex) { - throw new GenericError(ex); - } - } - - @Mutation("registerUnitConfig") - UnitConfig registerUnitConfig(@Arg("unitConfig") UnitConfig unitConfig) throws BCOGraphQLError { - try { - return Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).registerUnitConfig(unitConfig).get(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - } catch (RuntimeException | CouldNotPerformException | InterruptedException | ExecutionException | TimeoutException ex) { - throw new GenericError(ex); - } - } - - @Mutation("updateLabel") - LabelType.Label updateLabel(@Arg("unitId") String unitId, @Arg("label") String label, DataFetchingEnvironment env) throws BCOGraphQLError { - try { - final UnitConfig.Builder builder = Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUnitConfigById(unitId).toBuilder(); - - final AbstractBCOGraphQLContext context = env.getContext(); - final String oldLabel = LabelProcessor.getBestMatch(context.getLanguageCode(), builder.getLabel()); - LabelProcessor.replace(builder.getLabelBuilder(), oldLabel, label); - - return Registries.getUnitRegistry().updateUnitConfig(builder.build()).get(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getLabel(); - } catch (RuntimeException | CouldNotPerformException | InterruptedException | ExecutionException | TimeoutException ex) { - throw new GenericError(ex); - } - } - - @Mutation("updateLocation") - PlacementConfigType.PlacementConfig updateLocation(@Arg("unitId") String unitId, @Arg("locationId") String locationId) throws BCOGraphQLError { - try { - final UnitConfig.Builder builder = Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUnitConfigById(unitId).toBuilder(); - builder.getPlacementConfigBuilder().setLocationId(locationId); - return Registries.getUnitRegistry().updateUnitConfig(builder.build()).get(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getPlacementConfig(); - } catch (RuntimeException | CouldNotPerformException | InterruptedException | ExecutionException | TimeoutException ex) { - throw new GenericError(ex); - } - } - - @Mutation("updateFloorPlan") - ShapeType.Shape updateFloorPlan(@Arg("locationId") String locationId, @Arg("shape") ShapeType.Shape shape) throws BCOGraphQLError { - try { - final UnitConfig.Builder unitConfigBuilder = Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUnitConfigById(locationId).toBuilder(); - unitConfigBuilder.getPlacementConfigBuilder().getShapeBuilder().clearFloor().addAllFloor(shape.getFloorList()); - return Registries.getUnitRegistry().updateUnitConfig(unitConfigBuilder.build()).get(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getPlacementConfig().getShape(); - } catch (RuntimeException | CouldNotPerformException | InterruptedException | ExecutionException | TimeoutException ex) { - throw new GenericError(ex); - } - } - - @Mutation("updatePose") - PoseType.Pose updatePose(@Arg("unitId") String unitId, @Arg("pose") PoseType.Pose pose) throws BCOGraphQLError { - try { - final UnitConfig.Builder builder = Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUnitConfigById(unitId).toBuilder(); - builder.getPlacementConfigBuilder().clearPose().setPose(pose); - return Registries.getUnitRegistry().updateUnitConfig(builder.build()).get(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getPlacementConfig().getPose(); - } catch (RuntimeException | CouldNotPerformException | InterruptedException | ExecutionException | TimeoutException ex) { - throw new GenericError(ex); - } - } - - @Mutation("updateMetaConfig") - MetaConfigType.MetaConfig updateMetaConfig(@Arg("unitId") String unitId, @Arg("entry") EntryType.Entry entry) throws BCOGraphQLError { - try { - final UnitRegistryRemote unitRegistry = Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - - final UnitConfig.Builder unitConfigBuilder = unitRegistry.getUnitConfigById(unitId).toBuilder(); - final MetaConfigType.MetaConfig.Builder metaConfigBuilder = unitConfigBuilder.getMetaConfigBuilder(); - for (int i = 0; i < metaConfigBuilder.getEntryCount(); i++) { - if (metaConfigBuilder.getEntry(i).getKey().equals(entry.getKey())) { - metaConfigBuilder.removeEntry(i); - break; - } - } - if (!entry.getValue().isEmpty()) { - metaConfigBuilder.addEntry(entry); - } - return unitRegistry.updateUnitConfig(unitConfigBuilder.build()).get(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getMetaConfig(); - } catch (RuntimeException | CouldNotPerformException | InterruptedException | ExecutionException | TimeoutException ex) { - throw new GenericError(ex); - } - } - - // ===================================== Service Methods =========================================================== - - public static ImmutableList getUnitConfigs(final UnitFilter unitFilter, Boolean includeDisabledUnits) throws BCOGraphQLError { - try { - if ((includeDisabledUnits == null)) { - includeDisabledUnits = false; - } - return ImmutableList.copyOf( - Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUnitConfigs(includeDisabledUnits, unitFilter)); - - } catch (RuntimeException | CouldNotPerformException | InterruptedException ex) { - throw new GenericError(ex); - } - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/RegistrySchemaModule.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/RegistrySchemaModule.kt new file mode 100644 index 0000000000..c3f96ee52a --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/RegistrySchemaModule.kt @@ -0,0 +1,418 @@ +package org.openbase.bco.api.graphql.schema + +import com.google.api.graphql.rejoiner.* +import com.google.common.collect.ImmutableList +import graphql.schema.DataFetchingEnvironment +import org.openbase.bco.api.graphql.context.context +import org.openbase.bco.api.graphql.error.ArgumentError +import org.openbase.bco.api.graphql.error.BCOGraphQLError +import org.openbase.bco.api.graphql.error.GenericError +import org.openbase.bco.api.graphql.error.ServerError +import org.openbase.bco.authentication.lib.SessionManager +import org.openbase.bco.authentication.lib.iface.BCOSession +import org.openbase.bco.registry.remote.Registries +import org.openbase.bco.registry.remote.session.BCOSessionImpl +import org.openbase.bco.registry.unit.remote.registerUnitConfigAuthenticated +import org.openbase.bco.registry.unit.remote.removeUnitConfigAuthenticated +import org.openbase.bco.registry.unit.remote.updateUnitConfigAuthenticated +import org.openbase.jul.exception.CouldNotPerformException +import org.openbase.jul.extension.protobuf.ProtoBufBuilderProcessor.mergeFromWithoutRepeatedFields +import org.openbase.jul.extension.type.processing.LabelProcessor.getBestMatch +import org.openbase.jul.extension.type.processing.LabelProcessor.replace +import org.openbase.type.configuration.EntryType +import org.openbase.type.configuration.MetaConfigType +import org.openbase.type.domotic.unit.UnitConfigType +import org.openbase.type.domotic.unit.UnitConfigType.UnitConfig +import org.openbase.type.domotic.unit.UnitFilterType +import org.openbase.type.domotic.unit.gateway.GatewayClassType +import org.openbase.type.geometry.PoseType +import org.openbase.type.language.LabelType +import org.openbase.type.spatial.PlacementConfigType +import org.openbase.type.spatial.ShapeType +import java.util.* +import java.util.concurrent.* + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ class RegistrySchemaModule : SchemaModule() { + /** + * Check if an authentication token retrieved by the login method is still valid. + * + * @param token the token to be checked + * + * @return if the token is valid and can be used to authenticate further requests + */ + @Query("verifyToken") + fun verifyToken(@Arg("token") token: String?): java.lang.Boolean { + TODO("blocked by https://github.com/openbase/bco.registry/issues/108") + } + + /** + * Method can be used to request a token of the given bco user. + * + * @param username the name of the user as plain text string. + * @param passwordHash the password hash of the user that need to be generted first (see note below). + * + * @return the login token. + * + * + * Note: The hash of the default admin password is: '''R+gZ+PFuauhav8rRVa3XlWXXSEyi5BcdrbeXLEY3tDQ=''' + * + * @throws BCOGraphQLError + */ + @Query("login") + @Throws(BCOGraphQLError::class) + fun login(@Arg("username") username: String?, @Arg("password") passwordHash: String?): String = try { + val session: BCOSession = BCOSessionImpl() + session.loginUserViaUsername(username, Base64.getDecoder().decode(passwordHash), false) + session.generateAuthToken( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).authenticationToken + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } catch (ex: TimeoutException) { + throw GenericError(ex) + } + + @Query("changePassword") + @Throws(BCOGraphQLError::class) + fun changePassword( + @Arg("username") username: String?, + @Arg("oldPassword") oldPassword: String?, + @Arg("newPassword") newPassword: String?, + ): String = try { + val userId = Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).getUserUnitIdByUserName(username) + val sessionManager = SessionManager() + try { + sessionManager.loginUser(userId, oldPassword, false) + } catch (ex: CouldNotPerformException) { + throw ArgumentError(ex) + } + sessionManager.changePassword( + userId, + oldPassword, + newPassword + )[ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT] + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } catch (ex: ExecutionException) { + throw GenericError(ex) + } catch (ex: TimeoutException) { + throw GenericError(ex) + }.let { "" } + + @Query("unitConfig") + @Throws(BCOGraphQLError::class) + fun getUnitConfigById(@Arg("id") id: String?): UnitConfigType.UnitConfig = try { + Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).getUnitConfigById(id) + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } + + @Query("unitConfigs") + @Throws(BCOGraphQLError::class) + fun queryGetUnitConfigs( + @Arg("filter") unitFilter: UnitFilterType.UnitFilter?, + @Arg("includeDisabledUnits") includeDisabledUnits: Boolean?, + ): ImmutableList = getUnitConfigs(unitFilter, includeDisabledUnits) + + @Query("gatewayClasses") + @Throws(CouldNotPerformException::class, InterruptedException::class) + fun gatewayClasses(): ImmutableList = + ImmutableList.copyOf(Registries.getClassRegistry(true).gatewayClasses) + + @Mutation("updateUnitConfig") + @Throws(BCOGraphQLError::class) + fun updateUnitConfig( + @Arg("unitConfig") unitConfig: UnitConfigType.UnitConfig, + env: DataFetchingEnvironment, + ): UnitConfigType.UnitConfig = try { + val unitConfigBuilder = Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ) + .getUnitConfigById(unitConfig.id) + .toBuilder() + unitConfigBuilder.mergeFromWithoutRepeatedFields(unitConfig) + Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).updateUnitConfigAuthenticated( + unitConfigBuilder.build(), + env.context.auth + )[ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT] + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } catch (ex: ExecutionException) { + throw GenericError(ex) + } catch (ex: TimeoutException) { + throw GenericError(ex) + } + + @Mutation("removeUnitConfig") + @Throws(BCOGraphQLError::class) + fun removeUnitConfig( + @Arg("unitId") unitId: String?, + env: DataFetchingEnvironment, + ): UnitConfigType.UnitConfig = try { + val unitConfig = Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).getUnitConfigById(unitId) + Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).removeUnitConfigAuthenticated( + unitConfig, + env.context.auth + )[ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT] + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } catch (ex: ExecutionException) { + throw GenericError(ex) + } catch (ex: TimeoutException) { + throw GenericError(ex) + } + + @Mutation("registerUnitConfig") + @Throws(BCOGraphQLError::class) + fun registerUnitConfig( + @Arg("unitConfig") unitConfig: UnitConfigType.UnitConfig?, + env: DataFetchingEnvironment, + ): UnitConfigType.UnitConfig = try { + Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).registerUnitConfigAuthenticated( + unitConfig, + env.context.auth + )[ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT] + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } catch (ex: ExecutionException) { + throw GenericError(ex) + } catch (ex: TimeoutException) { + throw GenericError(ex) + } + + @Mutation("updateLabel") + @Throws(BCOGraphQLError::class) + fun updateLabel( + @Arg("unitId") unitId: String?, + @Arg("label") label: String?, + env: DataFetchingEnvironment, + ): LabelType.Label = try { + val builder = Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).getUnitConfigById(unitId).toBuilder() + val oldLabel = getBestMatch(env.context.languageCode!!, builder.label) + replace(builder.labelBuilder, oldLabel, label) + Registries.getUnitRegistry().updateUnitConfigAuthenticated( + builder.build(), + env.context.auth + )[ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT].label + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } catch (ex: ExecutionException) { + throw GenericError(ex) + } catch (ex: TimeoutException) { + throw GenericError(ex) + } + + @Mutation("updateLocation") + @Throws(BCOGraphQLError::class) + fun updateLocation( + @Arg("unitId") unitId: String?, + @Arg("locationId") locationId: String?, + env: DataFetchingEnvironment, + ): PlacementConfigType.PlacementConfig = try { + val builder = Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).getUnitConfigById(unitId).toBuilder() + builder.placementConfigBuilder.locationId = locationId + Registries.getUnitRegistry().updateUnitConfigAuthenticated( + builder.build(), + env.context.auth + )[ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT].placementConfig + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } catch (ex: ExecutionException) { + throw GenericError(ex) + } catch (ex: TimeoutException) { + throw GenericError(ex) + } + + @Mutation("updateFloorPlan") + @Throws(BCOGraphQLError::class) + fun updateFloorPlan( + @Arg("locationId") locationId: String?, + @Arg("shape") shape: ShapeType.Shape, + env: DataFetchingEnvironment, + ): ShapeType.Shape = try { + val unitConfigBuilder = Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).getUnitConfigById(locationId).toBuilder() + unitConfigBuilder.placementConfigBuilder.shapeBuilder.clearFloor().addAllFloor(shape.floorList) + Registries.getUnitRegistry().updateUnitConfigAuthenticated( + unitConfigBuilder.build(), + env.context.auth + )[ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT].placementConfig.shape + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } catch (ex: ExecutionException) { + throw GenericError(ex) + } catch (ex: TimeoutException) { + throw GenericError(ex) + } + + @Mutation("updatePose") + @Throws(BCOGraphQLError::class) + fun updatePose( + @Arg("unitId") unitId: String?, + @Arg("pose") pose: PoseType.Pose?, + env: DataFetchingEnvironment, + ): PoseType.Pose = try { + val builder = Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).getUnitConfigById(unitId).toBuilder() + builder.placementConfigBuilder.clearPose().pose = pose + Registries.getUnitRegistry().updateUnitConfigAuthenticated( + builder.build(), + env.context.auth + )[ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT].placementConfig.pose + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } catch (ex: ExecutionException) { + throw GenericError(ex) + } catch (ex: TimeoutException) { + throw GenericError(ex) + } + + + @Mutation("updateMetaConfig") + @Throws(BCOGraphQLError::class) + fun updateMetaConfig( + @Arg("unitId") unitId: String?, + @Arg("entry") entry: EntryType.Entry, + env: DataFetchingEnvironment, + ): MetaConfigType.MetaConfig = try { + val unitRegistry = Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ) + val unitConfigBuilder = unitRegistry.getUnitConfigById(unitId).toBuilder() + val metaConfigBuilder = unitConfigBuilder.metaConfigBuilder + for (i in 0 until metaConfigBuilder.entryCount) { + if (metaConfigBuilder.getEntry(i).key == entry.key) { + metaConfigBuilder.removeEntry(i) + break + } + } + if (!entry.value.isEmpty()) { + metaConfigBuilder.addEntry(entry) + } + + unitRegistry.updateUnitConfigAuthenticated( + unitConfigBuilder.build(), + env.context.auth + )[ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT]!!.metaConfig + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } catch (ex: ExecutionException) { + throw GenericError(ex) + } + + companion object { + @Throws(BCOGraphQLError::class) + fun getUnitConfigs( + unitFilter: UnitFilterType.UnitFilter?, + includeDisabledUnits: Boolean?, + ): ImmutableList = try { + ImmutableList.copyOf( + Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).getUnitConfigs(includeDisabledUnits ?: true, unitFilter) + ) + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/UnitSchemaModule.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/UnitSchemaModule.java deleted file mode 100644 index 66b4cacefd..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/UnitSchemaModule.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.openbase.bco.api.graphql.schema; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import com.google.api.graphql.rejoiner.*; -import com.google.common.collect.ImmutableList; -import com.google.protobuf.Message; -import graphql.schema.DataFetchingEnvironment; -import org.openbase.bco.api.graphql.context.AbstractBCOGraphQLContext; -import org.openbase.bco.api.graphql.error.BCOGraphQLError; -import org.openbase.bco.api.graphql.error.GenericError; -import org.openbase.bco.api.graphql.error.ServerError; -import org.openbase.bco.dal.lib.action.ActionDescriptionProcessor; -import org.openbase.bco.dal.lib.layer.service.Services; -import org.openbase.bco.dal.lib.layer.unit.UnitRemote; -import org.openbase.bco.dal.remote.action.RemoteAction; -import org.openbase.bco.dal.remote.layer.unit.Units; -import org.openbase.bco.registry.remote.Registries; -import org.openbase.bco.registry.unit.lib.filter.UnitConfigFilterImpl; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.exception.NotAvailableException; -import org.openbase.jul.extension.protobuf.ProtoBufBuilderProcessor; -import org.openbase.jul.pattern.ListFilter; -import org.openbase.type.domotic.action.ActionParameterType.ActionParameter; -import org.openbase.type.domotic.authentication.AuthTokenType.AuthToken; -import org.openbase.type.domotic.service.ServiceTemplateType.ServiceTemplate.ServiceType; -import org.openbase.type.domotic.service.ServiceTempusTypeType.ServiceTempusType.ServiceTempus; -import org.openbase.type.domotic.unit.UnitConfigType.UnitConfig; -import org.openbase.type.domotic.unit.UnitDataType.UnitData; -import org.openbase.type.domotic.unit.UnitFilterType.UnitFilter; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -public class UnitSchemaModule extends SchemaModule { - - // ===================================== Schema Modifications ====================================================== - - @SchemaModification(addField = "config", onType = UnitData.class) - UnitConfig addConfigToData(UnitData data) throws CouldNotPerformException, InterruptedException { - return Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUnitConfigById(data.getId()); - } - - // ===================================== Queries =================================================================== - - @Query("unit") - UnitData unit(@Arg("unitId") String id) throws BCOGraphQLError { - try { - final UnitRemote unit = Units.getUnit(id, ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - return (UnitData) ProtoBufBuilderProcessor.merge(UnitData.newBuilder(), unit.getData()).build(); - } catch (RuntimeException | CouldNotPerformException | InterruptedException ex) { - throw new GenericError(ex); - } - } - - @Query("units") - ImmutableList units(@Arg("filter") UnitFilter unitFilter) throws BCOGraphQLError { - try { - final List dataList = new ArrayList<>(); - for (UnitConfig unitConfig : Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUnitConfigs(unitFilter)) { - UnitRemote unit = Units.getUnit(unitConfig, ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - dataList.add((UnitData) ProtoBufBuilderProcessor.merge(UnitData.newBuilder(), unit.getData()).build()); - } - return ImmutableList.copyOf(dataList); - } catch (RuntimeException | CouldNotPerformException | InterruptedException ex) { - throw new GenericError(ex); - } - } - - // ===================================== Queries =================================================================== - - @Mutation("unit") - UnitData unit(@Arg("unitId") String unitId, @Arg("data") UnitData data, DataFetchingEnvironment env) throws BCOGraphQLError { - try { - return setServiceStates(unitId, data, env, ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - } catch (RuntimeException | CouldNotPerformException | InterruptedException ex) { - throw new GenericError(ex); - } - } - - @Mutation("units") - ImmutableList units(@Arg("filter") UnitFilter unitFilter, @Arg("data") UnitData data, DataFetchingEnvironment env) throws BCOGraphQLError { - try { - final List dataList = new ArrayList<>(); - for (UnitConfig unitConfig : Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT).getUnitConfigs(unitFilter)) { - dataList.add(setServiceStates(unitConfig, data, env, ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT)); - } - return ImmutableList.copyOf(dataList); - } catch (RuntimeException | CouldNotPerformException | InterruptedException ex) { - throw new GenericError(ex); - } - } - - // ===================================== Service Methods =========================================================== - - private UnitData setServiceStates(final UnitConfig unitConfig, final UnitData data, DataFetchingEnvironment env, final long timeout, final TimeUnit timeUnit) throws CouldNotPerformException, InterruptedException { - return setServiceStates(unitConfig.getId(), data, env, timeout, timeUnit); - } - - private UnitData setServiceStates(final String unitId, final UnitData data, DataFetchingEnvironment env, final long timeout, final TimeUnit timeUnit) throws CouldNotPerformException, InterruptedException { - final UnitRemote unit = Units.getUnit(unitId, timeout, timeUnit); - - final List remoteActions = new ArrayList<>(); - for (final ServiceType serviceType : unit.getSupportedServiceTypes()) { - - if (!Services.hasServiceState(serviceType, ServiceTempus.CURRENT, data)) { - continue; - } - - final Message serviceState = Services.invokeProviderServiceMethod(serviceType, data); - - final ActionParameter.Builder builder = ActionDescriptionProcessor.generateDefaultActionParameter(serviceState, serviceType, unit); - try { - builder.setAuthToken(AuthToken.newBuilder().setAuthenticationToken(((AbstractBCOGraphQLContext) env.getContext()).getToken()).build()); - } catch (NotAvailableException ex) { - // in case the auth token is not available, we just continue without any authentication. - } - remoteActions.add(new RemoteAction(unit.applyAction(builder), builder.getAuthToken())); - } - - UnitData.Builder unitDataBuilder = UnitData.newBuilder(); - // TODO: blocked by https://github.com/openbase/bco.dal/issues/170 - if (!remoteActions.isEmpty()) { - for (final RemoteAction remoteAction : remoteActions) { - remoteAction.waitForRegistration(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - unitDataBuilder.addTriggeredAction(remoteAction.getActionDescription()); - } - } - - ProtoBufBuilderProcessor.merge(unitDataBuilder, unit.getData()); - return unitDataBuilder.build(); - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/UnitSchemaModule.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/UnitSchemaModule.kt new file mode 100644 index 0000000000..abe50510bb --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/schema/UnitSchemaModule.kt @@ -0,0 +1,183 @@ +package org.openbase.bco.api.graphql.schema + +import com.google.api.graphql.rejoiner.* +import com.google.common.collect.ImmutableList +import graphql.schema.DataFetchingEnvironment +import org.openbase.bco.api.graphql.context.AbstractBCOGraphQLContext +import org.openbase.bco.api.graphql.error.BCOGraphQLError +import org.openbase.bco.api.graphql.error.GenericError +import org.openbase.bco.api.graphql.error.ServerError +import org.openbase.bco.dal.lib.action.ActionDescriptionProcessor +import org.openbase.bco.dal.lib.layer.service.Services +import org.openbase.bco.dal.remote.action.RemoteAction +import org.openbase.bco.dal.remote.layer.unit.Units +import org.openbase.bco.registry.remote.Registries +import org.openbase.jul.exception.CouldNotPerformException +import org.openbase.jul.exception.NotAvailableException +import org.openbase.jul.extension.protobuf.ProtoBufBuilderProcessor.merge +import org.openbase.type.domotic.authentication.AuthTokenType +import org.openbase.type.domotic.service.ServiceTempusTypeType +import org.openbase.type.domotic.unit.UnitConfigType +import org.openbase.type.domotic.unit.UnitDataType +import org.openbase.type.domotic.unit.UnitFilterType +import java.util.concurrent.TimeUnit + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ +class UnitSchemaModule : SchemaModule() { + // ===================================== Schema Modifications ====================================================== + @SchemaModification(addField = "config", onType = UnitDataType.UnitData::class) + @Throws(CouldNotPerformException::class, InterruptedException::class) + fun addConfigToData(data: UnitDataType.UnitData): UnitConfigType.UnitConfig = Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).getUnitConfigById(data.id) + + // ===================================== Queries =================================================================== + @Query("unit") + @Throws(BCOGraphQLError::class) + fun unit(@Arg("unitId") id: String?): UnitDataType.UnitData = try { + Units + .getUnit(id, ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT) + .let { unit -> merge(UnitDataType.UnitData.newBuilder(), unit.data).build() as UnitDataType.UnitData } + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } + + @Query("units") + @Throws(BCOGraphQLError::class) + fun units(@Arg("filter") unitFilter: UnitFilterType.UnitFilter?): ImmutableList = try { + val dataList: MutableList = ArrayList() + for (unitConfig in Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ).getUnitConfigs(unitFilter)) { + val unit = Units.getUnit( + unitConfig, + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ) + dataList.add(merge(UnitDataType.UnitData.newBuilder(), unit.data).build() as UnitDataType.UnitData) + } + ImmutableList.copyOf(dataList) + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } + + // ===================================== Queries =================================================================== + @Mutation("unit") + @Throws(BCOGraphQLError::class) + fun unit( + @Arg("unitId") unitId: String, + @Arg("data") data: UnitDataType.UnitData, + env: DataFetchingEnvironment, + ): UnitDataType.UnitData = try { + setServiceStates(unitId, data, env) + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } + + @Mutation("units") + @Throws(BCOGraphQLError::class) + fun units( + @Arg("filter") unitFilter: UnitFilterType.UnitFilter?, + @Arg("data") data: UnitDataType.UnitData, + env: DataFetchingEnvironment, + ): ImmutableList = try { + Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT) + .getUnitConfigs(unitFilter) + .map { config -> setServiceStates(config, data, env) } + .let { ImmutableList.copyOf(it) } + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } + + // ===================================== Service Methods =========================================================== + @Throws(CouldNotPerformException::class, InterruptedException::class) + private fun setServiceStates( + unitConfig: UnitConfigType.UnitConfig, + data: UnitDataType.UnitData, + env: DataFetchingEnvironment, + timeout: Long = ServerError.BCO_TIMEOUT_SHORT, + timeUnit: TimeUnit = ServerError.BCO_TIMEOUT_TIME_UNIT, + ): UnitDataType.UnitData { + return setServiceStates(unitConfig.id, data, env, timeout, timeUnit) + } + + @Throws(CouldNotPerformException::class, InterruptedException::class) + private fun setServiceStates( + unitId: String, + data: UnitDataType.UnitData, + env: DataFetchingEnvironment, + timeout: Long = ServerError.BCO_TIMEOUT_SHORT, + timeUnit: TimeUnit = ServerError.BCO_TIMEOUT_TIME_UNIT, + ): UnitDataType.UnitData { + val unit = Units.getUnit(unitId, timeout, timeUnit) + val remoteActions: MutableList = ArrayList() + for (serviceType in unit.supportedServiceTypes) { + if (!Services.hasServiceState( + serviceType, + ServiceTempusTypeType.ServiceTempusType.ServiceTempus.CURRENT, + data + ) + ) { + continue + } + val serviceState = Services.invokeProviderServiceMethod(serviceType, data) + val builder = ActionDescriptionProcessor.generateDefaultActionParameter(serviceState, serviceType, unit) + try { + builder.authToken = AuthTokenType.AuthToken.newBuilder() + .setAuthenticationToken((env.getContext() as AbstractBCOGraphQLContext).token).build() + } catch (ex: NotAvailableException) { + // in case the auth token is not available, we just continue without any authentication. + } + remoteActions.add(RemoteAction(unit.applyAction(builder), builder.authToken)) + } + val unitDataBuilder = UnitDataType.UnitData.newBuilder() + // TODO: blocked by https://github.com/openbase/bco.dal/issues/170 + for (remoteAction in remoteActions) { + remoteAction.waitForRegistration( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ) + unitDataBuilder.addTriggeredAction(remoteAction.actionDescription) + } + merge(unitDataBuilder, unit.data) + return unitDataBuilder.build() + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/AbstractObserverMapper.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/AbstractObserverMapper.java deleted file mode 100644 index 01c5f1ae11..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/AbstractObserverMapper.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.openbase.bco.api.graphql.subscriptions; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import io.reactivex.Observable; -import io.reactivex.ObservableEmitter; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.pattern.Observer; - -import java.util.function.Consumer; - -public abstract class AbstractObserverMapper implements Observer { - - private ObservableEmitter emitter = null; - - @Override - public void update(final S source, T target) throws Exception { - if (emitter == null) { - return; - } - - emitter.onNext(mapData(source, target)); - } - - public void setEmitter(final ObservableEmitter emitter) { - this.emitter = emitter; - } - - public abstract E mapData(final S source, final T data) throws Exception; - - public void doAfterRemoveObserver() throws CouldNotPerformException { - } - - public void doAfterAddObserver() throws CouldNotPerformException, InterruptedException { - } - - public static Observable createObservable(Consumer> addObserver, Consumer> removeObserver, AbstractObserverMapper obs) { - Observable observable = Observable.create(emitter -> { - obs.setEmitter(emitter); - addObserver.accept(obs); - obs.doAfterAddObserver(); - }); - - observable = observable.doOnDispose(() -> { - removeObserver.accept(obs); - obs.doAfterRemoveObserver(); - }); - - return observable; - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/AbstractObserverMapper.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/AbstractObserverMapper.kt new file mode 100644 index 0000000000..a8230f6d6c --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/AbstractObserverMapper.kt @@ -0,0 +1,71 @@ +package org.openbase.bco.api.graphql.subscriptions + +import io.reactivex.Observable +import io.reactivex.ObservableEmitter +import org.openbase.jul.exception.CouldNotPerformException +import org.openbase.jul.pattern.Observer +import java.util.function.Consumer + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ abstract class AbstractObserverMapper : Observer { + private var emitter: ObservableEmitter? = null + @Throws(Exception::class) + override fun update(source: S, target: T) { + if (emitter == null) { + return + } + emitter!!.onNext(mapData(source, target)) + } + + fun setEmitter(emitter: ObservableEmitter?) { + this.emitter = emitter + } + + @Throws(Exception::class) + abstract fun mapData(source: S, data: T): E + @Throws(CouldNotPerformException::class) + open fun doAfterRemoveObserver() { + } + + @Throws(CouldNotPerformException::class, InterruptedException::class) + open fun doAfterAddObserver() { + } + + companion object { + fun createObservable( + addObserver: Consumer>, + removeObserver: Consumer>, + obs: AbstractObserverMapper + ): Observable { + var observable = Observable.create { emitter: ObservableEmitter? -> + obs.setEmitter(emitter) + addObserver.accept(obs) + obs.doAfterAddObserver() + } + observable = observable.doOnDispose { + removeObserver.accept(obs) + obs.doAfterRemoveObserver() + } + return observable + } + } +} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/SubscriptionModule.java b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/SubscriptionModule.java deleted file mode 100644 index d0fee30a07..0000000000 --- a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/SubscriptionModule.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.openbase.bco.api.graphql.subscriptions; - -/*- - * #%L - * BCO GraphQL API - * %% - * Copyright (C) 2020 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * . - * #L% - */ - -import com.google.common.collect.ImmutableList; -import com.google.protobuf.Message; -import io.reactivex.BackpressureStrategy; -import lombok.extern.slf4j.Slf4j; -import org.openbase.bco.api.graphql.error.BCOGraphQLError; -import org.openbase.bco.api.graphql.error.GenericError; -import org.openbase.bco.api.graphql.error.ServerError; -import org.openbase.bco.api.graphql.schema.RegistrySchemaModule; -import org.openbase.bco.dal.lib.layer.service.ServiceStateProvider; -import org.openbase.bco.dal.lib.layer.unit.Unit; -import org.openbase.bco.dal.lib.layer.unit.UnitRemote; -import org.openbase.bco.dal.remote.layer.unit.CustomUnitPool; -import org.openbase.bco.dal.remote.layer.unit.Units; -import org.openbase.bco.registry.remote.Registries; -import org.openbase.bco.registry.unit.remote.UnitRegistryRemote; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.extension.protobuf.ProtoBufBuilderProcessor; -import org.openbase.jul.pattern.provider.DataProvider; -import org.openbase.type.domotic.registry.UnitRegistryDataType.UnitRegistryData; -import org.openbase.type.domotic.unit.UnitConfigType.UnitConfig; -import org.openbase.type.domotic.unit.UnitDataType; -import org.openbase.type.domotic.unit.UnitFilterType.UnitFilter; -import org.reactivestreams.Publisher; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -public class SubscriptionModule { - - private static final org.slf4j.Logger log = LoggerFactory.getLogger(SubscriptionModule.class); - - //TODO: what is a good strategy here - private static BackpressureStrategy BACKPRESSURE_STRATEGY = BackpressureStrategy.BUFFER; - - public static Publisher subscribeUnits(final UnitFilter unitFilter) throws BCOGraphQLError { - try { - final CustomUnitPool subscriptionUnitPool = new CustomUnitPool(); - subscriptionUnitPool.init(unitFilter); - - return AbstractObserverMapper.createObservable( - subscriptionUnitPool::addDataObserver, - subscriptionUnitPool::removeDataObserver, - new AbstractObserverMapper, Message, UnitDataType.UnitData>() { - @Override - public UnitDataType.UnitData mapData(Unit source, Message data) { - return (UnitDataType.UnitData) ProtoBufBuilderProcessor.merge(UnitDataType.UnitData.newBuilder(), data).build(); - } - - @Override - public void doAfterAddObserver() throws CouldNotPerformException, InterruptedException { - subscriptionUnitPool.activate(); - for (UnitRemote unitRemote : subscriptionUnitPool.getInternalUnitList()) { - log.debug("Subscribe to: "+unitRemote); - } - } - - @Override - public void doAfterRemoveObserver() { - subscriptionUnitPool.shutdown(); - } - }).toFlowable(BACKPRESSURE_STRATEGY); - } catch (RuntimeException | CouldNotPerformException | InterruptedException ex) { - throw new GenericError(ex); - } - } - - public static Publisher> subscribeUnitConfigs(final UnitFilter unitFilter, boolean includeDisabledUnits) throws BCOGraphQLError { - try { - final RegistrySubscriptionObserver observer = new RegistrySubscriptionObserver(unitFilter, includeDisabledUnits); - final UnitRegistryRemote unitRegistry = Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - return AbstractObserverMapper.createObservable(unitRegistry::addDataObserver, unitRegistry::removeDataObserver, - observer).toFlowable(BACKPRESSURE_STRATEGY); - } catch (RuntimeException | CouldNotPerformException | InterruptedException ex) { - throw new GenericError(ex); - } - } - - public static class RegistrySubscriptionObserver extends AbstractObserverMapper, UnitRegistryData, List> { - - private final boolean includeDisabledUnits; - private final UnitFilter unitFilter; - private final List unitConfigs; - - public RegistrySubscriptionObserver(final UnitFilter unitFilter, boolean includeDisabledUnits) throws CouldNotPerformException, InterruptedException, BCOGraphQLError { - this.unitFilter = unitFilter; - this.includeDisabledUnits = includeDisabledUnits; - - Registries.getUnitRegistry(ServerError.BCO_TIMEOUT_SHORT, ServerError.BCO_TIMEOUT_TIME_UNIT); - this.unitConfigs = new ArrayList<>(RegistrySchemaModule.getUnitConfigs(unitFilter, includeDisabledUnits)); - } - - @Override - public void update(DataProvider source, UnitRegistryData target) throws Exception { - final ImmutableList newUnitConfigs = RegistrySchemaModule.getUnitConfigs(unitFilter, includeDisabledUnits); - - if (newUnitConfigs.equals(unitConfigs)) { - // nothing has changed - return; - } - - // store update - unitConfigs.clear(); - unitConfigs.addAll(newUnitConfigs); - - super.update(source, target); - } - - @Override - public List mapData(DataProvider source, UnitRegistryData data) throws Exception { - return this.unitConfigs; - } - } -} diff --git a/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/SubscriptionModule.kt b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/SubscriptionModule.kt new file mode 100644 index 0000000000..17e154c215 --- /dev/null +++ b/module/api/graphql/src/main/java/org/openbase/bco/api/graphql/subscriptions/SubscriptionModule.kt @@ -0,0 +1,168 @@ +package org.openbase.bco.api.graphql.subscriptions + +import com.google.common.collect.ImmutableList +import com.google.protobuf.Message +import io.reactivex.BackpressureStrategy +import org.openbase.bco.api.graphql.error.BCOGraphQLError +import org.openbase.bco.api.graphql.error.GenericError +import org.openbase.bco.api.graphql.error.ServerError +import org.openbase.bco.api.graphql.schema.RegistrySchemaModule +import org.openbase.bco.dal.lib.layer.unit.Unit +import org.openbase.bco.dal.remote.layer.unit.CustomUnitPool +import org.openbase.bco.registry.remote.Registries +import org.openbase.jul.exception.CouldNotPerformException +import org.openbase.jul.extension.protobuf.ProtoBufBuilderProcessor.merge +import org.openbase.jul.pattern.Observer +import org.openbase.jul.pattern.provider.DataProvider +import org.openbase.type.domotic.registry.UnitRegistryDataType.UnitRegistryData +import org.openbase.type.domotic.unit.UnitConfigType.UnitConfig +import org.openbase.type.domotic.unit.UnitDataType +import org.openbase.type.domotic.unit.UnitFilterType.UnitFilter +import org.reactivestreams.Publisher +import org.slf4j.LoggerFactory +import java.util.function.Consumer + +/*- + * #%L + * BCO GraphQL API + * %% + * Copyright (C) 2020 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ object SubscriptionModule { + private val log = LoggerFactory.getLogger(SubscriptionModule::class.java) + + //TODO: what is a good strategy here + private val BACKPRESSURE_STRATEGY = BackpressureStrategy.BUFFER + + @Throws(BCOGraphQLError::class) + fun subscribeUnits(unitFilter: UnitFilter?): Publisher { + return try { + val subscriptionUnitPool = CustomUnitPool() + subscriptionUnitPool.init(unitFilter) + AbstractObserverMapper.createObservable( + Consumer { observer: Observer, Message> -> + subscriptionUnitPool.addDataObserver( + observer + ) + }, + Consumer { observer: Observer, Message> -> + subscriptionUnitPool.removeDataObserver(observer) + }, + object : AbstractObserverMapper, Message, UnitDataType.UnitData>() { + override fun mapData(source: Unit, data: Message): UnitDataType.UnitData { + return merge(UnitDataType.UnitData.newBuilder(), data!!).build() as UnitDataType.UnitData + } + + @Throws(CouldNotPerformException::class, InterruptedException::class) + override fun doAfterAddObserver() { + subscriptionUnitPool.activate() + for (unitRemote in subscriptionUnitPool.internalUnitList) { + log.debug("Subscribe to: $unitRemote") + } + } + + override fun doAfterRemoveObserver() { + subscriptionUnitPool.shutdown() + } + }).toFlowable(BACKPRESSURE_STRATEGY) + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } + } + + @Throws(BCOGraphQLError::class) + fun subscribeUnitConfigs( + unitFilter: UnitFilter, + includeDisabledUnits: Boolean, + ): Publisher> { + return try { + val observer = RegistrySubscriptionObserver(unitFilter, includeDisabledUnits) + val unitRegistry = Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ) + AbstractObserverMapper.createObservable( + Consumer { observer: Observer, UnitRegistryData> -> + unitRegistry.addDataObserver( + observer + ) + }, + Consumer { observer: Observer, UnitRegistryData> -> + unitRegistry.removeDataObserver(observer) + }, + observer + ).toFlowable(BACKPRESSURE_STRATEGY) + } catch (ex: RuntimeException) { + throw GenericError(ex) + } catch (ex: CouldNotPerformException) { + throw GenericError(ex) + } catch (ex: InterruptedException) { + throw GenericError(ex) + } + } + + class RegistrySubscriptionObserver( + private val unitFilter: UnitFilter, + private val includeDisabledUnits: Boolean, + ) : AbstractObserverMapper, UnitRegistryData, List>() { + private val unitConfigs: MutableList + + init { + Registries.getUnitRegistry( + ServerError.BCO_TIMEOUT_SHORT, + ServerError.BCO_TIMEOUT_TIME_UNIT + ) + unitConfigs = ArrayList( + RegistrySchemaModule.getUnitConfigs( + unitFilter, includeDisabledUnits + ) + ) + } + + @Throws(Exception::class) + override fun update( + source: DataProvider, + target: UnitRegistryData, + ) { + val newUnitConfigs: ImmutableList = + RegistrySchemaModule.getUnitConfigs( + unitFilter, includeDisabledUnits + ) + if (newUnitConfigs == unitConfigs) { + // nothing has changed + return + } + + // store update + unitConfigs.clear() + unitConfigs.addAll(newUnitConfigs) + super.update(source, target) + } + + @Throws(Exception::class) + override fun mapData( + source: DataProvider, + data: UnitRegistryData, + ): List { + return unitConfigs + } + } +} diff --git a/module/registry/unit-registry/core/src/main/java/org/openbase/bco/registry/unit/core/consistency/unitgroupconfig/UnitGroupMemberRecursionConsistencyHandler.kt b/module/registry/unit-registry/core/src/main/java/org/openbase/bco/registry/unit/core/consistency/unitgroupconfig/UnitGroupMemberRecursionConsistencyHandler.kt index 02d530f2a6..46286f6e21 100644 --- a/module/registry/unit-registry/core/src/main/java/org/openbase/bco/registry/unit/core/consistency/unitgroupconfig/UnitGroupMemberRecursionConsistencyHandler.kt +++ b/module/registry/unit-registry/core/src/main/java/org/openbase/bco/registry/unit/core/consistency/unitgroupconfig/UnitGroupMemberRecursionConsistencyHandler.kt @@ -1,6 +1,5 @@ package org.openbase.bco.registry.unit.core.consistency.unitgroupconfig -import org.openbase.bco.registry.lib.util.UnitConfigProcessor import org.openbase.jul.exception.CouldNotPerformException import org.openbase.jul.exception.InvalidStateException import org.openbase.jul.extension.protobuf.IdentifiableMessage @@ -8,9 +7,7 @@ import org.openbase.jul.extension.protobuf.container.ProtoBufMessageMap import org.openbase.jul.extension.type.processing.LabelProcessor import org.openbase.jul.storage.registry.AbstractProtoBufRegistryConsistencyHandler import org.openbase.jul.storage.registry.EntryModification -import org.openbase.jul.storage.registry.ProtoBufFileSynchronizedRegistry import org.openbase.jul.storage.registry.ProtoBufRegistry -import org.openbase.type.domotic.registry.UnitRegistryDataType.UnitRegistryData import org.openbase.type.domotic.unit.UnitConfigType.UnitConfig /* @@ -35,14 +32,14 @@ import org.openbase.type.domotic.unit.UnitConfigType.UnitConfig * #L% */ /** @author [Tamino Huxohl](mailto:pleminoq@openbase.org) */ class UnitGroupMemberRecursionConsistencyHandler - : AbstractProtoBufRegistryConsistencyHandler() { + : AbstractProtoBufRegistryConsistencyHandler() { @Throws(CouldNotPerformException::class, EntryModification::class) override fun processData( id: String, - entry: IdentifiableMessage, - entryMap: ProtoBufMessageMap, - registry: ProtoBufRegistry + entry: IdentifiableMessage, + entryMap: ProtoBufMessageMap, + registry: ProtoBufRegistry, ) { val unitGroupUnitConfig = entry.message ?: return val memberIds = unitGroupUnitConfig.unitGroupConfig.memberIdList.toList() @@ -50,14 +47,16 @@ class UnitGroupMemberRecursionConsistencyHandler unitGroupUnitConfig .takeIf { memberIds.containsUnit(it, registry) } ?.let { - throw InvalidStateException("UnitGroup[${LabelProcessor.getBestMatch(unitGroupUnitConfig.label)}] " + - "refers itself as member!") + throw InvalidStateException( + "UnitGroup[${LabelProcessor.getBestMatch(unitGroupUnitConfig.label)}] " + + "refers itself as member!" + ) } } private fun List.containsUnit( unit: UnitConfig, - registry: ProtoBufRegistry + registry: ProtoBufRegistry, ): Boolean = this .filter { registry.contains(it) } .mapNotNull { registry.get(it).message } diff --git a/module/registry/unit-registry/remote/src/main/java/org/openbase/bco/registry/unit/remote/UnitRegistryRemote.java b/module/registry/unit-registry/remote/src/main/java/org/openbase/bco/registry/unit/remote/UnitRegistryRemote.java index 773ba83456..50f3395e9b 100644 --- a/module/registry/unit-registry/remote/src/main/java/org/openbase/bco/registry/unit/remote/UnitRegistryRemote.java +++ b/module/registry/unit-registry/remote/src/main/java/org/openbase/bco/registry/unit/remote/UnitRegistryRemote.java @@ -340,6 +340,7 @@ public RemoteRegistry getBaseUnitConfigR * {@inheritDoc} * * @param unitConfig {@inheritDoc} + * * @return {@inheritDoc} */ @Override @@ -356,7 +357,9 @@ public Future registerUnitConfigAuthenticated(AuthenticatedV * {@inheritDoc} * * @param unitConfigId {@inheritDoc} + * * @return {@inheritDoc} + * * @throws org.openbase.jul.exception.NotAvailableException {@inheritDoc} */ @Override @@ -373,7 +376,9 @@ public UnitConfig getUnitConfigById(final String unitConfigId) throws NotAvailab * {@inheritDoc} * * @param unitAlias {@inheritDoc} + * * @return {@inheritDoc} + * * @throws NotAvailableException {@inheritDoc} */ @Override @@ -395,7 +400,9 @@ public UnitConfig getUnitConfigByAlias(final String unitAlias) throws NotAvailab * * @param unitAlias {@inheritDoc} * @param unitType {@inheritDoc} + * * @return {@inheritDoc} + * * @throws NotAvailableException {@inheritDoc} */ @Override @@ -456,7 +463,9 @@ public Future removeUnitConfigAuthenticated(final Authentica * {@inheritDoc} * * @param filterDisabledUnits {@inheritDoc} + * * @return {@inheritDoc} + * * @throws CouldNotPerformException {@inheritDoc} * @throws NotAvailableException {@inheritDoc} */ @@ -478,6 +487,7 @@ public List getUnitConfigsFiltered(boolean filterDisabledUnits) thro * {@inheritDoc} * * @return {@inheritDoc} + * * @throws CouldNotPerformException {@inheritDoc} */ @Override @@ -498,6 +508,7 @@ public List getDalUnitConfigs() throws CouldNotPerformException { * {@inheritDoc} * * @return {@inheritDoc} + * * @throws CouldNotPerformException {@inheritDoc} */ @Override @@ -873,6 +884,7 @@ public Boolean isGatewayUnitRegistryConsistent() { * {@inheritDoc} * * @param authorizationToken {@inheritDoc} + * * @return {@inheritDoc} */ @Override @@ -889,6 +901,7 @@ public Future requestAuthorizationToken(final AuthorizationToken authori * {@inheritDoc} * * @param authenticatedValue {@inheritDoc} + * * @return {@inheritDoc} */ @Override diff --git a/module/registry/unit-registry/remote/src/main/java/org/openbase/bco/registry/unit/remote/UnitRegistryRemoteAuthExtensions.kt b/module/registry/unit-registry/remote/src/main/java/org/openbase/bco/registry/unit/remote/UnitRegistryRemoteAuthExtensions.kt new file mode 100644 index 0000000000..3c1f9c93da --- /dev/null +++ b/module/registry/unit-registry/remote/src/main/java/org/openbase/bco/registry/unit/remote/UnitRegistryRemoteAuthExtensions.kt @@ -0,0 +1,39 @@ +package org.openbase.bco.registry.unit.remote + +import org.openbase.bco.authentication.lib.SessionManager +import org.openbase.bco.authentication.lib.future.AuthenticatedValueFuture +import org.openbase.type.domotic.authentication.AuthTokenType +import org.openbase.type.domotic.authentication.AuthenticatedValueType +import org.openbase.type.domotic.unit.UnitConfigType +import java.io.Serializable +import java.util.concurrent.Future + +fun UnitRegistryRemote.updateUnitConfigAuthenticated( + unitConfig: UnitConfigType.UnitConfig?, + auth: AuthTokenType.AuthToken?, +): Future = authRequest(unitConfig, ::updateUnitConfigAuthenticated, auth) + +fun UnitRegistryRemote.removeUnitConfigAuthenticated( + unitConfig: UnitConfigType.UnitConfig?, + auth: AuthTokenType.AuthToken?, +): Future = authRequest(unitConfig, ::removeUnitConfigAuthenticated, auth) + +fun UnitRegistryRemote.registerUnitConfigAuthenticated( + unitConfig: UnitConfigType.UnitConfig?, + auth: AuthTokenType.AuthToken?, +): Future = authRequest(unitConfig, ::registerUnitConfigAuthenticated, auth) + +inline fun UnitRegistryRemote.authRequest( + value: T?, + origin: (AuthenticatedValueType.AuthenticatedValue) -> Future, + auth: AuthTokenType.AuthToken?, +): Future = with(SessionManager.getInstance()) { + initializeRequest(value, auth).let { value -> + AuthenticatedValueFuture( + origin(value), + T::class.java, + value.ticketAuthenticatorWrapper, + this + ) + } +} diff --git a/versions.properties b/versions.properties index ba9a8b711c..eb13ab729b 100644 --- a/versions.properties +++ b/versions.properties @@ -6,11 +6,32 @@ #### #### suppress inspection "SpellCheckingInspection" for whole file #### suppress inspection "UnusedProperty" for whole file + +version.com.adarshr..gradle-test-logger-plugin=3.2.0 + version.com.graphql-java-kickstart..graphql-spring-boot-starter=14.0.0 + version.io.quarkus..quarkus-junit4-mock=2.9.1.Final + ## unused version.junit.jupiter=5.9.2 + +version.kotest=5.5.5 +## # available=5.6.0.1123-SNAPSHOT +## # available=5.6.0.1125-SNAPSHOT +## # available=5.6.0.1126-SNAPSHOT +## # available=5.6.0.1127-SNAPSHOT +## # available=5.6.0.1128-SNAPSHOT +## # available=5.6.0.1129-SNAPSHOT +## # available=5.6.0.1131-SNAPSHOT + +version.kotlinx.coroutines=1.6.4 +## # available=1.7.0-Beta + +version.mockk=1.13.4 + version.org.jmdns..jmdns=3.5.7 + version.org.glassfish.jersey.security..oauth2-client=2.31 ## # available=2.32 ## # available=2.33 @@ -23,6 +44,7 @@ version.org.glassfish.jersey.security..oauth2-client=2.31 ## # available=3.0.1 ## # available=3.0.2 ## # available=3.0.3 + version.org.glassfish.jersey.media..jersey-media-sse=2.31 ## # available=2.32 ## # available=2.33 @@ -35,6 +57,7 @@ version.org.glassfish.jersey.media..jersey-media-sse=2.31 ## # available=3.0.1 ## # available=3.0.2 ## # available=3.0.3 + version.org.glassfish.jersey.inject..jersey-hk2=2.31 ## # available=2.32 ## # available=2.33 @@ -47,6 +70,7 @@ version.org.glassfish.jersey.inject..jersey-hk2=2.31 ## # available=3.0.1 ## # available=3.0.2 ## # available=3.0.3 + version.org.glassfish.jersey.core..jersey-client=2.31 ## # available=2.32 ## # available=2.33 @@ -59,25 +83,34 @@ version.org.glassfish.jersey.core..jersey-client=2.31 ## # available=3.0.1 ## # available=3.0.2 ## # available=3.0.3 + version.org.apache.commons..commons-math3=3.6.1 + version.net.javacrumbs.future-converter..future-converter-java8-guava=1.2.0 + version.io.socket..socket.io-client=1.0.0 ## # available=1.0.1 ## # available=2.0.0 ## # available=2.0.1 + version.io.reactivex.rxjava2..rxjava=2.2.21 + version.commons-collections..commons-collections=3.2.2 ## # available=20030418.083655 ## # available=20031027.000000 ## # available=20040102.233541 ## # available=20040616 + ## unused version.com.influxdb..influxdb-client-java=[5.0,5.1-alpha) + version.com.google.inject.extensions..guice-multibindings=4.2.3 + version.com.google.inject..guice=5.0.1 ## # available=5.0.2-SNAPSHOT ## # available=5.1.0 ## # available=5.1.1-SNAPSHOT + version.com.google.guava..guava=28.0-jre ## # available=28.1-android ## # available=28.1-jre @@ -95,74 +128,102 @@ version.com.google.guava..guava=28.0-jre ## # available=31.0-jre ## # available=31.0.1-android ## # available=31.0.1-jre + +version.org.openbase..jul.communication.mqtt.test=3.3-SNAPSHOT + version.org.openbase..jul.transformation=3.3-SNAPSHOT + version.org.testcontainers..junit-jupiter=1.17.2 + version.org.testcontainers..testcontainers=1.17.1 + version.org.springframework.boot..spring-boot-starter-webflux=2.6.3 + version.org.springframework.boot..spring-boot-starter-jetty=2.6.3 + version.org.springframework.boot..spring-boot-starter-websocket=2.6.3 + version.org.springframework..spring-webmvc=5.3.15 + version.org.openhab.core.bundles..org.openhab.core.io.rest.core=3.1.0 ## # available=3.1.1 ## # available=3.2.0 + plugin.org.springframework.boot=2.6.2 ## # available=2.6.3 + plugin.io.spring.dependency-management=1.0.11.RELEASE + version.kotlin=1.7.0 + version.org.openbase..jul.communication.controller=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.communication.mqtt=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.exception=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.extension.protobuf=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.extension.type.processing=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.extension.type.storage=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.extension.type.transform=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.extension.type.util=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.pattern.launch=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.pattern.trigger=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.processing=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.storage=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.visual.javafx=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.org.openbase..jul.visual.swing=3.3-SNAPSHOT ## # available=3.0.0 ## # available=3.0.1 ## # available=3.0.2 + version.rxjava2.rxjava=2.2.21