diff --git a/klab.cli/src/main/java/org/integratedmodelling/cli/KlabCLI.java b/klab.cli/src/main/java/org/integratedmodelling/cli/KlabCLI.java index 680296747..858a5ad11 100644 --- a/klab.cli/src/main/java/org/integratedmodelling/cli/KlabCLI.java +++ b/klab.cli/src/main/java/org/integratedmodelling/cli/KlabCLI.java @@ -10,7 +10,6 @@ import org.integratedmodelling.klab.api.engine.Engine; import org.integratedmodelling.klab.api.exceptions.KlabIOException; import org.integratedmodelling.klab.api.exceptions.KlabIllegalStateException; -import org.integratedmodelling.klab.api.knowledge.Resource; import org.integratedmodelling.klab.api.knowledge.Urn; import org.integratedmodelling.klab.api.scope.ContextScope; import org.integratedmodelling.klab.api.scope.Scope; @@ -42,9 +41,7 @@ import picocli.shell.jline3.PicocliCommands.PicocliCommandsFactory; import java.io.*; -import java.net.MalformedURLException; import java.net.URI; -import java.net.URISyntaxException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; @@ -130,7 +127,7 @@ public void importWithSchema(KlabService service, String suggestedUrn, List findSchemata(Map> schemata, String sch */ ResourceTransport() { - addImport("component", COMPONENT_MAVEN = Schema.create("maven", - Schema.Type.PROPERTIES, KlabAsset.KnowledgeClass.COMPONENT, "Register a component " + - "available on Maven " + "using " + "the component's Maven coordinates").with( - "groupId", Artifact.Type.TEXT, false).with("adapterId", Artifact.Type.TEXT, - false).with("version", Artifact.Type.TEXT, false)); - - addImport("component.jar", COMPONENT_JAR = Schema.create("jar", - Schema.Type.STREAM, KlabAsset.KnowledgeClass.COMPONENT, "Register a component by directly " + - "submitting a jar file").mediaType("application/java-archive").fileExtensions("jar")); - - addImport("project.git", PROJECT_GIT = Schema.create("git", Schema.Type.PROPERTIES, - KlabAsset.KnowledgeClass.PROJECT, "Register a k.LAB project by submitting the URL of a Git " - + "repository and optional credentials").with("url", Artifact.Type.TEXT, false).with("username", Artifact.Type.TEXT, true).with("password", Artifact.Type.TEXT, true).with("token", Artifact.Type.TEXT, true)); - - addImport("project.zip", PROJECT_ZIP = Schema.create("zip", - Schema.Type.STREAM, - KlabAsset.KnowledgeClass.PROJECT, "Register a k.LAB by directly submitting a zip archive").mediaType("application/zip", "application/x-zip-compressed").fileExtensions("zip")); + addImport("component", + COMPONENT_MAVEN = Schema.create("component.maven", + Schema.Type.PROPERTIES, KlabAsset.KnowledgeClass.COMPONENT, "Register a component " + + "available on Maven " + "using " + "the component's Maven coordinates").with( + "groupId", Artifact.Type.TEXT, false).with("adapterId", Artifact.Type.TEXT, + false).with("version", Artifact.Type.TEXT, false), + COMPONENT_JAR = Schema.create("component.jar", + Schema.Type.STREAM, KlabAsset.KnowledgeClass.COMPONENT, "Register a component by " + + "directly " + + "submitting a jar file").mediaType("application/java-archive").fileExtensions("jar")); + + addImport("project.git", + PROJECT_GIT = Schema.create("project.git", Schema.Type.PROPERTIES, + KlabAsset.KnowledgeClass.PROJECT, "Register a k.LAB project by submitting the URL " + + "of a Git " + + "repository and optional credentials").with("url", Artifact.Type.TEXT, + false).with("username", Artifact.Type.TEXT, true).with("password", + Artifact.Type.TEXT, true).with("token", Artifact.Type.TEXT, true), + PROJECT_ZIP = Schema.create("project.zip", + Schema.Type.STREAM, + KlabAsset.KnowledgeClass.PROJECT, "Register a k.LAB by directly submitting a zip " + + "archive").mediaType("application/zip", "application/x-zip-compressed").fileExtensions("zip")); } - // TODO pass scope for permissions - public Schema findSchema(String id, Map> schemata) { + // TODO use the scope for permissions (here or downstream in service controllers) + public Schema findSchema(String id, Map> schemata, Scope scope) { var list = schemata.get(Utils.Paths.getLeading(id, '.')); if (list != null) { for (var schema : list) { - if (schema.getSchemaId().equals(Utils.Paths.getLast(id, '.'))) { + if (schema.getSchemaId().equals(id)) { return schema; } } diff --git a/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/resources/adapters/Exporter.java b/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/resources/adapters/Exporter.java new file mode 100644 index 000000000..fcbc00cc8 --- /dev/null +++ b/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/resources/adapters/Exporter.java @@ -0,0 +1,55 @@ +package org.integratedmodelling.klab.api.services.resources.adapters; + +import org.integratedmodelling.klab.api.knowledge.KlabAsset; +import org.integratedmodelling.klab.api.services.runtime.extension.KlabFunction; + +import java.lang.annotation.*; + +/** + * Annotates methods that implement (and possibly define) an export schema specified through + * {@link org.integratedmodelling.klab.api.services.resources.ResourceTransport} beans. The methods can be in + * a class annotated with {@link org.integratedmodelling.klab.api.services.runtime.extension.Library} or + * {@link ResourceAdapter}. + *

+ * Recognized method parameters should include an {@link org.integratedmodelling.klab.api.knowledge.Urn} or + * directly a Resource for resources with parameters, a scope, and possibly a String for a media type that + * should be part of the annotation and established through content negotiation. The method must return an + * {@link org.integratedmodelling.klab.api.knowledge.Urn} or a {@link String} that encodes one. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface Exporter { + + /** + * The unique ID of the import schema this implements. This is the complete ID as a dot-separated path, + * whose leading path is the "class" of the import and the last element specifies the import source or + * method (e.g. component.jar). + * + * @return + */ + String schema(); + + + KlabAsset.KnowledgeClass knowledgeClass(); + + /** + * If specified, these define the schema's properties which will be passed as a + * {@link org.integratedmodelling.klab.api.collections.Parameters} object. If not, the schema will expect + * binary content as a File, URL or InputStream. + * + * @return + */ + KlabFunction.Argument[] properties() default {}; + + /** + * Mandatory media type that will be sent along with the exported byte stream. + * + * @return + */ + String mediaType(); + + String[] fileExtensions() default {}; + + String description(); +} diff --git a/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/resources/adapters/Importer.java b/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/resources/adapters/Importer.java new file mode 100644 index 000000000..18db35d47 --- /dev/null +++ b/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/resources/adapters/Importer.java @@ -0,0 +1,60 @@ +package org.integratedmodelling.klab.api.services.resources.adapters; + +import org.integratedmodelling.klab.api.knowledge.KlabAsset; +import org.integratedmodelling.klab.api.services.runtime.extension.KlabFunction; + +import java.lang.annotation.*; + +/** + * Annotates methods that implement (and possibly define) an import schema specified through + * {@link org.integratedmodelling.klab.api.services.resources.ResourceTransport} beans. The methods can be in + * a class annotated with {@link org.integratedmodelling.klab.api.services.runtime.extension.Library} or + * {@link ResourceAdapter} (if the latter, the import will be expected to produce a Resource adopting that + * same adapter). + *

+ * Recognized method parameters can be {@link java.io.File}, {@link java.net.URL} or + * {@link java.io.InputStream} for binary content, + * {@link org.integratedmodelling.klab.api.collections.Parameters} for property-specified content, Resource + * for resources with parameters, and scopes. An {@link org.integratedmodelling.klab.api.knowledge.Urn} may be + * added which will be paired to a suggested URN if the caller has supplied one (the method may modify it). + * The method must return an {@link org.integratedmodelling.klab.api.knowledge.Urn} or a {@link String} that + * encodes one, which will be the final, unique URN. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface Importer { + + /** + * The unique ID of the import schema this implements. This is the complete ID as a dot-separated path, + * whose leading path is the "class" of the import and the last element specifies the import source or + * method (e.g. component.jar). + * + * @return + */ + String schema(); + + KlabAsset.KnowledgeClass knowledgeClass(); + + /** + * If specified, these define the schema's properties which will be passed as a + * {@link org.integratedmodelling.klab.api.collections.Parameters} object. If not, the schema will expect + * binary content as a File, URL or InputStream. + * + * @return + */ + KlabFunction.Argument[] properties() default {}; + + /** + * Optional media type that will be matched to the input's in case multiple schemata are possible for + * different media types. + * + * @return + */ + String mediaType() default ""; + + String[] fileExtensions() default {}; + + String description(); + +} diff --git a/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/resources/adapters/ResourceAdapter.java b/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/resources/adapters/ResourceAdapter.java index a79cec7db..303c03d55 100644 --- a/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/resources/adapters/ResourceAdapter.java +++ b/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/resources/adapters/ResourceAdapter.java @@ -208,20 +208,6 @@ enum LifecyclePhase { } - @Documented - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.TYPE}) - public @interface Importer { - - } - - @Documented - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD, ElementType.TYPE}) - public @interface Exporter { - - } - /** * Annotates a method returning {@link Artifact.Type} and taking a {@link Resource} as argument. Only used * if the type is not specified in the {@link ResourceAdapter} arguments. diff --git a/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/runtime/MessagingChannel.java b/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/runtime/MessagingChannel.java index a7a9b7981..72030979c 100644 --- a/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/runtime/MessagingChannel.java +++ b/klab.core.api/src/main/java/org/integratedmodelling/klab/api/services/runtime/MessagingChannel.java @@ -65,4 +65,18 @@ void connectToService(KlabService.ServiceCapabilities capabilities, UserIdentity * @return */ boolean isConnected(); + + /** + * True if the scope is connected to one or more queues and is set up for sending messages. + * + * @return + */ + boolean isSender(); + + /** + * True if the scope is connected to one or more queues and is set up for receiving messages. + * + * @return + */ + boolean isReceiver(); } diff --git a/klab.core.common/src/main/java/org/integratedmodelling/common/authentication/scope/MessagingChannelImpl.java b/klab.core.common/src/main/java/org/integratedmodelling/common/authentication/scope/MessagingChannelImpl.java index 550d4953b..feb0d03fb 100644 --- a/klab.core.common/src/main/java/org/integratedmodelling/common/authentication/scope/MessagingChannelImpl.java +++ b/klab.core.common/src/main/java/org/integratedmodelling/common/authentication/scope/MessagingChannelImpl.java @@ -14,7 +14,6 @@ import org.integratedmodelling.klab.api.services.runtime.Message; import org.integratedmodelling.klab.api.services.runtime.MessagingChannel; -import java.io.Closeable; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.*; @@ -470,11 +469,12 @@ public void presetMessagingQueue(Message.Queue queue, String s) { queueNames.put(queue, s + "." + queue.name().toLowerCase()); } - + @Override public boolean isSender() { return sender; } + @Override public boolean isReceiver() { return receiver; } diff --git a/klab.core.services/src/main/java/org/integratedmodelling/klab/components/ComponentRegistry.java b/klab.core.services/src/main/java/org/integratedmodelling/klab/components/ComponentRegistry.java index 953d4246b..962cabc01 100644 --- a/klab.core.services/src/main/java/org/integratedmodelling/klab/components/ComponentRegistry.java +++ b/klab.core.services/src/main/java/org/integratedmodelling/klab/components/ComponentRegistry.java @@ -24,6 +24,8 @@ import org.integratedmodelling.klab.api.services.ResourcesService; import org.integratedmodelling.klab.api.services.resources.ResourceSet; import org.integratedmodelling.klab.api.services.resources.adapters.Adapter; +import org.integratedmodelling.klab.api.services.resources.adapters.Exporter; +import org.integratedmodelling.klab.api.services.resources.adapters.Importer; import org.integratedmodelling.klab.api.services.resources.adapters.ResourceAdapter; import org.integratedmodelling.klab.api.services.runtime.Notification; import org.integratedmodelling.klab.api.services.runtime.extension.KlabAnnotation; @@ -56,10 +58,9 @@ public class ComponentRegistry { // FIXME the permissions should come from the external permission system, not as the internal // Plugin-License private final ComponentDescriptor localComponentDescriptor = - new ComponentDescriptor(LOCAL_SERVICE_COMPONENT, - Version.CURRENT_VERSION, - "Natively available services", null, ResourcePrivileges.PUBLIC, new ArrayList<>(), - new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>()); + new ComponentDescriptor(LOCAL_SERVICE_COMPONENT, Version.CURRENT_VERSION, "Natively available " + + "services", null, ResourcePrivileges.PUBLIC, new ArrayList<>(), new ArrayList<>(), + new HashMap<>(), new HashMap<>(), new HashMap<>()); /** * Component descriptors, uniquely identified by id + version @@ -75,6 +76,9 @@ public class ComponentRegistry { private MultiValuedMap annotationFinder = new HashSetValuedHashMap<>(); private MultiValuedMap verbFinder = new HashSetValuedHashMap<>(); private Map, Object> globalInstances = new HashMap<>(); + private Map importHandlers = new HashMap<>(); + private Map exportHandlers = new HashMap<>(); + public List resolveServiceCall(String name, Version version) { List ret = new ArrayList<>(); @@ -98,8 +102,8 @@ public List resolveServiceCall(String name, Version version } /** - * The adapter identifier may include a version after @; if not, retrieve the latest version - * available. Even if present, it must be authorized to the passed scope. + * The adapter identifier may include a version after @; if not, retrieve the latest version available. + * Even if present, it must be authorized to the passed scope. * * @param adapterType * @param scope @@ -118,8 +122,7 @@ public record LibraryDescriptor(String name, String description, List> verbs) { } - public record ComponentDescriptor(String id, Version version, String description, - File sourceArchive, + public record ComponentDescriptor(String id, Version version, String description, File sourceArchive, ResourcePrivileges permissions, List libraries, List adapters, Map services, @@ -182,8 +185,7 @@ public Pair installComponent(File resourcePath var pluginId = componentManager.loadPlugin(resourcePath.toPath()); var plugin = componentManager.getPlugin(pluginId); ResourceSet.Resource result = new ResourceSet.Resource("SERVICE ID TODO", pluginId, null, - Version.create(plugin.getDescriptor().getVersion()), - KlabAsset.KnowledgeClass.COMPONENT); + Version.create(plugin.getDescriptor().getVersion()), KlabAsset.KnowledgeClass.COMPONENT); // TODO dependencies @@ -204,8 +206,7 @@ public Pair installComponent(File resourcePath } } else { - ret.getNotifications().add(Notification.error("Plugin " + Utils.Files.getFileName(resourcePath) + " is " + - "not a valid k.LAB component")); + ret.getNotifications().add(Notification.error("Plugin " + Utils.Files.getFileName(resourcePath) + " is " + "not a valid k.LAB component")); ret.setEmpty(true); } } catch (Throwable t) { @@ -258,14 +259,13 @@ public ComponentDescriptor registerComponent(KlabComponent component) { component.getWrapper().getPluginPath().toFile(); var permissions = license == null ? ResourcePrivileges.PUBLIC : ResourcePrivileges.create(license); - scanPackage(component, Map.of(Library.class, (annotation, cls) -> registerLibrary( - (Library) annotation, cls, libraries), ResourceAdapter.class, - (annotation, cls) -> registerAdapter((ResourceAdapter) annotation, cls, - adapters))); + scanPackage(component, Map.of(Library.class, + (annotation, cls) -> registerLibrary((Library) annotation, cls, libraries), + ResourceAdapter.class, (annotation, cls) -> registerAdapter((ResourceAdapter) annotation, + cls, adapters))); var componentDescriptor = new ComponentDescriptor(componentName, componentVersion, description, - sourceArchive, - permissions, libraries, adapters, new HashMap<>(), new HashMap<>(), + sourceArchive, permissions, libraries, adapters, new HashMap<>(), new HashMap<>(), new HashMap<>()); // update catalog @@ -289,8 +289,7 @@ public ComponentDescriptor registerComponent(KlabComponent component) { return componentDescriptor; } - private void registerLibrary(Library annotation, Class cls, - List libraries) { + private void registerLibrary(Library annotation, Class cls, List libraries) { String namespacePrefix = Library.CORE_LIBRARY.equals(annotation.name()) ? "" : (annotation.name() + "."); @@ -322,11 +321,17 @@ private void registerLibrary(Library annotation, Class cls, prototypes.add(Pair.of(serviceInfo, createFunctionDescriptor(serviceInfo, cls, method))); } else if (method.isAnnotationPresent(KlabAnnotation.class)) { var serviceInfo = createAnnotationPrototype(namespacePrefix, - cls.getAnnotation(KlabAnnotation.class)); + method.getAnnotation(KlabAnnotation.class)); annotations.add(Pair.of(serviceInfo, createFunctionDescriptor(serviceInfo, cls, method))); } else if (method.isAnnotationPresent(Verb.class)) { - var serviceInfo = createVerbPrototype(namespacePrefix, cls.getAnnotation(Verb.class)); + var serviceInfo = createVerbPrototype(namespacePrefix, method.getAnnotation(Verb.class)); verbs.add(Pair.of(serviceInfo, createFunctionDescriptor(serviceInfo, cls, method))); + } else if (method.isAnnotationPresent(Importer.class)) { + var serviceInfo = createAnnotationPrototype(namespacePrefix,method.getAnnotation(Importer.class)); + importHandlers.put(serviceInfo.getName(), createFunctionDescriptor(serviceInfo, cls, method)); + } else if (method.isAnnotationPresent(Exporter.class)) { + var serviceInfo = createAnnotationPrototype(namespacePrefix, method.getAnnotation(Exporter.class)); + exportHandlers.put(serviceInfo.getName(), createFunctionDescriptor(serviceInfo, cls, method)); } } @@ -503,14 +508,12 @@ private Object createGlobalClassInstance(FunctionDescriptor ret) { return null; } - private void registerAdapter(ResourceAdapter annotation, Class cls, - List adapters) { + private void registerAdapter(ResourceAdapter annotation, Class cls, List adapters) { try { var adapter = new AdapterImpl(cls, annotation); } catch (Throwable t) { - Logging.INSTANCE.error("Adapter " + annotation.name() + " caused errors when loading and was " + - "rejected", t); + Logging.INSTANCE.error("Adapter " + annotation.name() + " caused errors when loading and was " + "rejected", t); } System.out.println("ZIO PORCO UN ADAPTER " + annotation.name()); @@ -583,16 +586,17 @@ public boolean loadComponents(ResourceSet resourceSet, Scope scope) { } File plugin = new File(pluginPath + File.separator + result.getResourceUrn() + ".jar"); - throw new KlabUnimplementedException("DIOCÜ reimplement the component retrieval"); + throw new KlabUnimplementedException("DIOCÜ reimplement the component retrieval"); // try (var input = service.retrieveResource(result.getResourceUrn(), -// result.getResourceVersion(), result.getAccessKey(), -// "application/java-archive", scope); var output = new FileOutputStream(plugin)) { -// IOUtils.copy(input, output); -// } catch (IOException e) { -// scope.error(e); -// return false; -// } -// loadComponents(pluginPath); + // result.getResourceVersion(), result.getAccessKey(), + // "application/java-archive", scope); var output = new + // FileOutputStream(plugin)) { + // IOUtils.copy(input, output); + // } catch (IOException e) { + // scope.error(e); + // return false; + // } + // loadComponents(pluginPath); } } @@ -602,8 +606,8 @@ public boolean loadComponents(ResourceSet resourceSet, Scope scope) { return true; } - public void scanPackage(String[] internalPackages, Map, BiConsumer>> annotationHandlers) { + public void scanPackage(String[] internalPackages, Map, + BiConsumer>> annotationHandlers) { try (ScanResult scanResult = new ClassGraph().enableAnnotationInfo().acceptPackages(internalPackages).scan()) { @@ -706,6 +710,48 @@ private ServiceInfo createAnnotationPrototype(String namespacePrefix, KlabAnnota return ret; } + private ServiceInfo createAnnotationPrototype(String namespacePrefix, Exporter annotation) { + + var ret = new ServiceInfoImpl(); + + ret.setName(namespacePrefix + annotation.schema()); + ret.setDescription(annotation.description()); + ret.setFunctionType(ServiceInfo.FunctionType.IMPORTER); + ret.getTargets().add(annotation.knowledgeClass()); + + for (KlabFunction.Argument argument : annotation.properties()) { + var arg = createArgument(argument); + ret.getArguments().put(arg.getName(), arg); + } + + /* + TODO create the records in ResourceTransport! + */ + + return ret; + } + + private ServiceInfo createAnnotationPrototype(String namespacePrefix, Importer annotation) { + + var ret = new ServiceInfoImpl(); + + ret.setName(namespacePrefix + annotation.schema()); + ret.setDescription(annotation.description()); + ret.setFunctionType(ServiceInfo.FunctionType.IMPORTER); + ret.getTargets().add(annotation.knowledgeClass()); + + for (KlabFunction.Argument argument : annotation.properties()) { + var arg = createArgument(argument); + ret.getArguments().put(arg.getName(), arg); + } + + /* + TODO create the records in ResourceTransport! + */ + + return ret; + } + private ServiceInfoImpl.ArgumentImpl createArgument(KlabFunction.Argument argument) { var arg = new ServiceInfoImpl.ArgumentImpl(); arg.setName(argument.name()); @@ -716,6 +762,7 @@ private ServiceInfoImpl.ArgumentImpl createArgument(KlabFunction.Argument argume for (Artifact.Type a : argument.type()) { arg.getType().add(a); } + return arg; } @@ -724,10 +771,10 @@ public void loadExtensions(String... packageName) { var libraries = new ArrayList(); var adapters = new ArrayList(); - scanPackage(packageName, Map.of(Library.class, (annotation, cls) -> registerLibrary( - (Library) annotation, cls, libraries), ResourceAdapter.class, - (annotation, cls) -> registerAdapter((ResourceAdapter) annotation, cls, - adapters))); + scanPackage(packageName, Map.of(Library.class, + (annotation, cls) -> registerLibrary((Library) annotation, cls, libraries), + ResourceAdapter.class, (annotation, cls) -> registerAdapter((ResourceAdapter) annotation, + cls, adapters))); localComponentDescriptor.libraries.addAll(libraries); localComponentDescriptor.adapters.addAll(adapters); @@ -779,8 +826,7 @@ public void initializeComponents(ResourcesConfiguration configuration, File plug remove anything not configured or deprecated; check integrity and certification for all components before loading them. */ - if (Utils.Maven.needsUpdate("org.integratedmodelling", "klab.component.generators", - "1.0-SNAPSHOT")) { + if (Utils.Maven.needsUpdate("org.integratedmodelling", "klab.component.generators", "1.0-SNAPSHOT")) { // shitdown } diff --git a/klab.core.services/src/main/java/org/integratedmodelling/klab/runtime/libraries/ComponentIOLibrary.java b/klab.core.services/src/main/java/org/integratedmodelling/klab/runtime/libraries/ComponentIOLibrary.java new file mode 100644 index 000000000..9561372bf --- /dev/null +++ b/klab.core.services/src/main/java/org/integratedmodelling/klab/runtime/libraries/ComponentIOLibrary.java @@ -0,0 +1,37 @@ +package org.integratedmodelling.klab.runtime.libraries; + +import org.integratedmodelling.klab.api.collections.Parameters; +import org.integratedmodelling.klab.api.knowledge.Artifact; +import org.integratedmodelling.klab.api.knowledge.KlabAsset; +import org.integratedmodelling.klab.api.services.resources.adapters.Exporter; +import org.integratedmodelling.klab.api.services.resources.adapters.Importer; +import org.integratedmodelling.klab.api.services.runtime.extension.KlabFunction; +import org.integratedmodelling.klab.api.services.runtime.extension.Library; + +import java.io.InputStream; + +@Library(name = "component", description = "Importers for components shared by all services" + + "extents.") +public class ComponentIOLibrary { + + @Importer(schema = "jar", knowledgeClass = KlabAsset.KnowledgeClass.COMPONENT, description = "") + public static String importComponentDirect() { + return null; + } + + @Importer(schema = "maven", knowledgeClass = KlabAsset.KnowledgeClass.COMPONENT, description = "", + properties = { + @KlabFunction.Argument(name = "groupId", type = Artifact.Type.TEXT, description = ""), + @KlabFunction.Argument(name = "artifactId", type = Artifact.Type.TEXT, description = ""), + @KlabFunction.Argument(name = "version", type = Artifact.Type.TEXT, description = "") + }) + public static String importComponentMaven(Parameters properties) { + return null; + } + + @Exporter(schema = "jar", description = "", mediaType = "", knowledgeClass = + KlabAsset.KnowledgeClass.COMPONENT) + public static InputStream exportComponentDirect(String componentId) { + return null; + } +} diff --git a/klab.core.services/src/main/java/org/integratedmodelling/klab/services/application/controllers/KlabServiceController.java b/klab.core.services/src/main/java/org/integratedmodelling/klab/services/application/controllers/KlabServiceController.java index 0c6afc751..7c8132ad8 100644 --- a/klab.core.services/src/main/java/org/integratedmodelling/klab/services/application/controllers/KlabServiceController.java +++ b/klab.core.services/src/main/java/org/integratedmodelling/klab/services/application/controllers/KlabServiceController.java @@ -111,34 +111,22 @@ public String importAsset(@PathVariable(name = "schema") String schema, @PathVariable(name = "urn") String urn, @RequestBody Parameters data, Principal principal) { - String ret = urn; + if (principal instanceof EngineAuthorization authorization) { var scope = authorization.getScope(); // retrieve schema. TODO not handling authorization yet - ResourceTransport.Schema s = null; - - for (var ss : ResourceTransport.INSTANCE.findImportSchemata(schema, null, authorization)) { - if (ss.getType() == ResourceTransport.Schema.Type.PROPERTIES) { - if (s != null) { - throw new KlabInternalErrorException("Ambiguous request: more than one " + - "property-based import schema with " + - "id " + schema + " is available"); - } - s = ss; - } - } + var s = ResourceTransport.INSTANCE.findSchema(schema, + instance.klabService().capabilities(scope).getImportSchemata(), scope); if (s == null) { throw new KlabAuthorizationException("No authorized import schema for property-based " + "submissions is available"); } var result = instance.klabService().importAsset(s, s.asset(data), urn, scope); - - ret = result == null ? null : result.getUrn(); - + return result == null ? null : result.getUrn(); } - return ret; + return null; } @PostMapping(value = ServicesAPI.IMPORT, consumes = MediaType.MULTIPART_FORM_DATA_VALUE) diff --git a/klab.services.resources/src/main/java/org/integratedmodelling/klab/services/resources/ResourcesProvider.java b/klab.services.resources/src/main/java/org/integratedmodelling/klab/services/resources/ResourcesProvider.java index 3f4f31784..a0db060c3 100644 --- a/klab.services.resources/src/main/java/org/integratedmodelling/klab/services/resources/ResourcesProvider.java +++ b/klab.services.resources/src/main/java/org/integratedmodelling/klab/services/resources/ResourcesProvider.java @@ -124,6 +124,8 @@ public ResourcesProvider(AbstractServiceDelegatingScope scope, ServiceStartupOpt } }, Instance.class); + + this.kbox = ModelKbox.create(this); this.workspaceManager = new WorkspaceManager(scope, getStartupOptions(), this, this::resolveRemoteProject); @@ -139,6 +141,9 @@ public ResourcesProvider(AbstractServiceDelegatingScope scope, ServiceStartupOpt getComponentRegistry().initializeComponents(this.workspaceManager.getConfiguration(), getConfigurationSubdirectory(options, "components")); + // load predefined runtime libraries + getComponentRegistry().loadExtensions("org.integratedmodelling.klab.runtime.libraries"); + } public Project resolveRemoteProject(String projectId) {