newDependencyRef(String dependencyRef) {
- return new ResourceRefs<>(ResourceType.DEPENDENCY_REF, URI.create(dependencyRef));
- }
-}
diff --git a/src/main/java/ai/wanaku/code/engine/camel/downloader/ResourceType.java b/src/main/java/ai/wanaku/code/engine/camel/downloader/ResourceType.java
deleted file mode 100644
index 9efdd1c..0000000
--- a/src/main/java/ai/wanaku/code/engine/camel/downloader/ResourceType.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package ai.wanaku.code.engine.camel.downloader;
-
-/**
- * Defines the types of resources that can be downloaded and managed by the code execution engine.
- */
-public enum ResourceType {
- /** Reference to Camel route definitions. */
- ROUTES_REF,
- /** Reference to MCP rules definitions. */
- RULES_REF,
- /** Reference to Maven dependency specifications. */
- DEPENDENCY_REF,
- /** Reference to a code generation package (tar.bz2 archive). */
- CODEGEN_PACKAGE,
-}
diff --git a/src/main/java/ai/wanaku/code/engine/camel/downloader/TarBz2Downloader.java b/src/main/java/ai/wanaku/code/engine/camel/downloader/TarBz2Downloader.java
index 8d60356..dad9d29 100644
--- a/src/main/java/ai/wanaku/code/engine/camel/downloader/TarBz2Downloader.java
+++ b/src/main/java/ai/wanaku/code/engine/camel/downloader/TarBz2Downloader.java
@@ -2,11 +2,9 @@
import java.io.ByteArrayInputStream;
import java.net.URI;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.List;
-import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ai.wanaku.capabilities.sdk.api.types.DataStore;
@@ -20,7 +18,7 @@
* This downloader fetches base64-encoded tar.bz2 archives from the data store,
* decodes them, and extracts their contents to a subdirectory within the data directory.
*/
-public class TarBz2Downloader implements Downloader {
+public class TarBz2Downloader {
private static final Logger LOG = LoggerFactory.getLogger(TarBz2Downloader.class);
private final ServicesHttpClient servicesHttpClient;
@@ -37,71 +35,47 @@ public TarBz2Downloader(ServicesHttpClient servicesHttpClient, Path dataDir) {
this.dataDir = dataDir;
}
- @Override
- public void downloadResource(ResourceRefs resourceName, Map downloadedResources)
- throws Exception {
- final String resourceFileName = resourceName.ref().getHost();
+ /**
+ * Downloads a tar.bz2 archive from the data store and extracts it.
+ *
+ * @param archiveUri the URI of the archive in the data store (e.g., datastore-archive://name.tar.bz2)
+ * @return the path to the extracted directory
+ * @throws Exception if download or extraction fails
+ */
+ public Path downloadAndExtract(URI archiveUri) throws Exception {
+ final String resourceFileName = archiveUri.getHost();
LOG.info("Downloading and extracting archive: {}", resourceFileName);
- // Retrieve the data stores from the API
WanakuResponse> response = servicesHttpClient.getDataStoresByName(resourceFileName);
if (response == null || response.data() == null || response.data().isEmpty()) {
- LOG.warn("No data found for resource: {}", resourceName);
- return;
+ LOG.warn("No data found for resource: {}", resourceFileName);
+ return null;
}
List dataStores = response.data();
+ Path extractDir = null;
for (DataStore dataStore : dataStores) {
if (dataStore.getData() == null || dataStore.getData().isEmpty()) {
- LOG.warn("DataStore entry for '{}' contains no data", resourceName);
+ LOG.warn("DataStore entry for '{}' contains no data", resourceFileName);
continue;
}
- // Decode from base64
byte[] decodedData = Base64.getDecoder().decode(dataStore.getData());
LOG.debug("Decoded {} bytes from base64", decodedData.length);
- // Create extraction directory based on resource name (without extension)
String extractDirName = getExtractDirectoryName(resourceFileName);
- Path extractDir = dataDir.resolve(extractDirName);
+ extractDir = dataDir.resolve(extractDirName);
- // Extract the archive
try (ByteArrayInputStream bais = new ByteArrayInputStream(decodedData)) {
ArchiveExtractor.extractTarBz2(bais, extractDir);
}
- // Store the path to the extracted directory
- downloadedResources.put(resourceName.resourceType(), extractDir);
-
LOG.info("Successfully downloaded and extracted '{}' to {}", resourceFileName, extractDir.toAbsolutePath());
}
- }
-
- /**
- * Downloads and extracts a tar.bz2 archive from a local file.
- *
- * @param archivePath path to the local archive file
- * @param downloadedResources map to store the result
- * @throws Exception if download or extraction fails
- */
- public void downloadFromFile(Path archivePath, Map downloadedResources) throws Exception {
- String fileName = archivePath.getFileName().toString();
- LOG.info("Extracting local archive: {}", archivePath);
-
- if (!Files.exists(archivePath)) {
- throw new IllegalArgumentException("Archive file not found: " + archivePath);
- }
-
- String extractDirName = getExtractDirectoryName(fileName);
- Path extractDir = dataDir.resolve(extractDirName);
-
- ArchiveExtractor.extractTarBz2(archivePath, extractDir);
-
- downloadedResources.put(ResourceType.CODEGEN_PACKAGE, extractDir);
- LOG.info("Successfully extracted '{}' to {}", fileName, extractDir.toAbsolutePath());
+ return extractDir;
}
/**
diff --git a/src/main/java/ai/wanaku/code/engine/camel/grpc/ProvisionBase.java b/src/main/java/ai/wanaku/code/engine/camel/grpc/ProvisionBase.java
deleted file mode 100644
index 6966f50..0000000
--- a/src/main/java/ai/wanaku/code/engine/camel/grpc/ProvisionBase.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package ai.wanaku.code.engine.camel.grpc;
-
-import java.util.Map;
-import io.grpc.stub.StreamObserver;
-import ai.wanaku.capabilities.sdk.config.provider.api.ConfigProvisioner;
-import ai.wanaku.capabilities.sdk.config.provider.api.ProvisionedConfig;
-import ai.wanaku.capabilities.sdk.runtime.provisioners.FileProvisionerLoader;
-import ai.wanaku.capabilities.sdk.util.ProvisioningHelper;
-import ai.wanaku.core.exchange.v1.PropertySchema;
-import ai.wanaku.core.exchange.v1.ProvisionReply;
-import ai.wanaku.core.exchange.v1.ProvisionRequest;
-import ai.wanaku.core.exchange.v1.ProvisionerGrpc;
-
-public class ProvisionBase extends ProvisionerGrpc.ProvisionerImplBase {
-
- private final String name;
-
- public ProvisionBase(String name) {
- this.name = name;
- }
-
- @Override
- public void provision(ProvisionRequest request, StreamObserver responseObserver) {
-
- ConfigProvisioner provisioner = FileProvisionerLoader.newConfigProvisioner(request, name);
- final ProvisionedConfig provision = ProvisioningHelper.provision(request, provisioner);
-
- responseObserver.onNext(ProvisionReply.newBuilder()
- .putAllProperties(properties())
- .setConfigurationUri(provision.configurationsUri().toString())
- .setSecretUri(provision.secretsUri().toString())
- .build());
- responseObserver.onCompleted();
- }
-
- public Map properties() {
- // Use this to push any server-side properties/arguments. Use the toPropertySchema to serialize their additional
- // details
- // Map.of("argument-name", toPropertySchema("The description for what argument-name is", "string", true));
- return Map.of();
- }
-
- /*
- * You can use this to serialize the server-side properties to push.
- */
- private static PropertySchema toPropertySchema(String description, String type, boolean required) {
- return PropertySchema.newBuilder()
- .setDescription(description)
- .setType(type)
- .setRequired(required)
- .build();
- }
-}
diff --git a/src/main/java/ai/wanaku/code/engine/camel/init/GitInitializer.java b/src/main/java/ai/wanaku/code/engine/camel/init/GitInitializer.java
deleted file mode 100644
index 6a34c25..0000000
--- a/src/main/java/ai/wanaku/code/engine/camel/init/GitInitializer.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package ai.wanaku.code.engine.camel.init;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.api.errors.GitAPIException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Initializer that clones a Git repository during application startup.
- * The repository is cloned to {dataDir}/cloned-repo and reused if it already exists.
- */
-public class GitInitializer implements Initializer {
- private static final Logger LOG = LoggerFactory.getLogger(GitInitializer.class);
- private static final String CLONED_REPO_DIR_NAME = "cloned-repo";
-
- private final String gitRepoUrl;
- private final Path dataDir;
- private Path clonedRepoPath;
-
- public GitInitializer(String gitRepoUrl, Path dataDir) {
- this.gitRepoUrl = gitRepoUrl;
- this.dataDir = dataDir;
- }
-
- @Override
- public void initialize() throws GitAPIException, IOException {
- clonedRepoPath = dataDir.resolve(CLONED_REPO_DIR_NAME);
- File clonedRepoDir = clonedRepoPath.toFile();
-
- if (clonedRepoDir.exists()) {
- try (Git ignored = Git.open(clonedRepoDir)) {
- LOG.info("Reusing existing cloned repository at {}", clonedRepoPath);
- return;
- } catch (IOException e) {
- throw new IOException(
- "Existing cloned repository at " + clonedRepoPath + " is not a valid Git repository", e);
- }
- }
-
- LOG.info("Cloning git repository from {} to {}", gitRepoUrl, clonedRepoPath);
-
- try (Git git = Git.cloneRepository()
- .setURI(gitRepoUrl)
- .setDirectory(clonedRepoDir)
- .call()) {
- LOG.info("Successfully cloned repository from {}", gitRepoUrl);
- }
- }
-
- public Path getClonedRepoPath() {
- return clonedRepoPath;
- }
-}
diff --git a/src/main/java/ai/wanaku/code/engine/camel/init/Initializer.java b/src/main/java/ai/wanaku/code/engine/camel/init/Initializer.java
deleted file mode 100644
index cc3755c..0000000
--- a/src/main/java/ai/wanaku/code/engine/camel/init/Initializer.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package ai.wanaku.code.engine.camel.init;
-
-public interface Initializer {
-
- void initialize() throws Exception;
-}
diff --git a/src/main/java/ai/wanaku/code/engine/camel/init/InitializerFactory.java b/src/main/java/ai/wanaku/code/engine/camel/init/InitializerFactory.java
deleted file mode 100644
index c055509..0000000
--- a/src/main/java/ai/wanaku/code/engine/camel/init/InitializerFactory.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package ai.wanaku.code.engine.camel.init;
-
-import java.nio.file.Path;
-
-/**
- * Factory for creating initializers based on the initFrom parameter.
- * Returns a GitInitializer if a repository URL is provided, otherwise returns NoOpInitializer.
- */
-public final class InitializerFactory {
-
- /**
- * Creates an appropriate initializer based on the initFrom parameter.
- *
- * @param initFrom Git repository URL (SSH or HTTPS), or null for no initialization
- * @param dataDir Directory where the repository will be cloned
- * @return GitInitializer if initFrom is provided, NoOpInitializer otherwise
- */
- public static Initializer createInitializer(String initFrom, Path dataDir) {
- final String normalizedInitFrom = initFrom == null ? null : initFrom.trim();
- if (normalizedInitFrom == null || normalizedInitFrom.isEmpty()) {
- return new NoOpInitializer();
- }
-
- // Assume it's a Git repository URL (supports both SSH and HTTPS)
- // Examples: git@github.com:user/repo.git or https://github.com/user/repo.git
- return new GitInitializer(normalizedInitFrom, dataDir);
- }
-}
diff --git a/src/main/java/ai/wanaku/code/engine/camel/init/NoOpInitializer.java b/src/main/java/ai/wanaku/code/engine/camel/init/NoOpInitializer.java
deleted file mode 100644
index 8ba0174..0000000
--- a/src/main/java/ai/wanaku/code/engine/camel/init/NoOpInitializer.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package ai.wanaku.code.engine.camel.init;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * No-operation initializer used when no initialization is required.
- */
-public class NoOpInitializer implements Initializer {
- private static final Logger LOG = LoggerFactory.getLogger(NoOpInitializer.class);
-
- @Override
- public void initialize() throws Exception {
- LOG.debug("No initialization required");
- }
-}
diff --git a/src/main/java/ai/wanaku/code/engine/camel/util/FileUtil.java b/src/main/java/ai/wanaku/code/engine/camel/util/FileUtil.java
deleted file mode 100644
index faa5e93..0000000
--- a/src/main/java/ai/wanaku/code/engine/camel/util/FileUtil.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package ai.wanaku.code.engine.camel.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.FileSystems;
-import java.nio.file.Path;
-import java.nio.file.StandardWatchEventKinds;
-import java.nio.file.WatchEvent;
-import java.nio.file.WatchKey;
-import java.nio.file.WatchService;
-import java.util.concurrent.TimeUnit;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public final class FileUtil {
- private static final Logger LOG = LoggerFactory.getLogger(FileUtil.class);
-
- private FileUtil() {}
-
- public static boolean untilAvailable(File input, boolean isDirectory) throws IOException, InterruptedException {
- WatchService watchService = FileSystems.getDefault().newWatchService();
- Path path = isDirectory ? input.toPath() : input.getParentFile().toPath();
-
- if (input.exists()) {
- LOG.info("File {} already available", input);
- return true;
- }
-
- // We watch for both the file creation and truncation
- path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY);
-
- do {
- LOG.info("Waiting indefinitely for {} to be available", input);
-
- WatchKey watchKey = watchService.poll(1, TimeUnit.SECONDS);
-
- if (watchKey == null) {
- continue;
- }
-
- for (WatchEvent> event : watchKey.pollEvents()) {
-
- /*
- It should return a Path object for ENTRY_CREATE and ENTRY_MODIFY events
- */
- Object context = event.context();
- if (!(context instanceof Path contextPath)) {
- LOG.warn("Received an unexpected event of kind {} for context {}", event.kind(), event.context());
- continue;
- }
-
- if (contextPath.toString().equals(input.getName())) {
- LOG.debug(
- "File at the path {} had a matching event of type: {}",
- input.getParentFile().getPath(),
- event.kind());
-
- if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE
- || event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) {
- LOG.info(
- "File at the path {} was created or modified",
- input.getParentFile().getPath());
-
- break;
- }
- } else {
- LOG.debug(
- "Ignoring a watch event at build path {} of type {} for file: {}",
- input.getParentFile().getPath(),
- event.kind(),
- contextPath.getFileName());
- }
- }
- watchKey.reset();
- } while (!input.exists());
-
- return input.exists();
- }
-}
diff --git a/src/main/java/ai/wanaku/code/engine/camel/util/GavUtil.java b/src/main/java/ai/wanaku/code/engine/camel/util/GavUtil.java
deleted file mode 100644
index 1310724..0000000
--- a/src/main/java/ai/wanaku/code/engine/camel/util/GavUtil.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ai.wanaku.code.engine.camel.util;
-
-public class GavUtil {
-
- public static String group(String gav) {
- return gav.split(":")[0];
- }
-
- public static String artifact(String gav) {
- return gav.split(":")[1];
- }
-
- public static String version(String gav) {
- return gav.split(":")[2];
- }
-}
diff --git a/src/main/java/ai/wanaku/code/engine/camel/util/WanakuRoutesLoader.java b/src/main/java/ai/wanaku/code/engine/camel/util/WanakuRoutesLoader.java
deleted file mode 100644
index ec0876b..0000000
--- a/src/main/java/ai/wanaku/code/engine/camel/util/WanakuRoutesLoader.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package ai.wanaku.code.engine.camel.util;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.ExtendedCamelContext;
-import org.apache.camel.main.download.DependencyDownloader;
-import org.apache.camel.main.download.DependencyDownloaderClassLoader;
-import org.apache.camel.main.download.DependencyDownloaderComponentResolver;
-import org.apache.camel.main.download.DependencyDownloaderDataFormatResolver;
-import org.apache.camel.main.download.DependencyDownloaderLanguageResolver;
-import org.apache.camel.main.download.DependencyDownloaderRoutesLoader;
-import org.apache.camel.main.download.DependencyDownloaderTransformerResolver;
-import org.apache.camel.main.download.DependencyDownloaderUriFactoryResolver;
-import org.apache.camel.main.download.MavenDependencyDownloader;
-import org.apache.camel.spi.ComponentResolver;
-import org.apache.camel.spi.DataFormatResolver;
-import org.apache.camel.spi.LanguageResolver;
-import org.apache.camel.spi.Resource;
-import org.apache.camel.spi.ResourceLoader;
-import org.apache.camel.spi.RoutesLoader;
-import org.apache.camel.spi.TransformerResolver;
-import org.apache.camel.spi.UriFactoryResolver;
-import org.apache.camel.support.PluginHelper;
-import org.slf4j.Logger;
-
-public class WanakuRoutesLoader {
- private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(WanakuRoutesLoader.class);
-
- private final String dependenciesList;
- private final String repositoriesList;
- private final DependencyDownloaderClassLoader cl;
- private final MavenDependencyDownloader downloader;
-
- public WanakuRoutesLoader(String dependenciesList, String repositoriesList) {
- this.dependenciesList = dependenciesList;
- this.repositoriesList = repositoriesList;
- this.cl = createClassLoader();
- this.downloader = createDownloader(cl);
- }
-
- public void loadRoute(CamelContext context, String path) throws Exception {
- final ExtendedCamelContext camelContextExtension = context.getCamelContextExtension();
-
- try {
- context.addService(downloader);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- camelContextExtension.addContextPlugin(
- ComponentResolver.class, new DependencyDownloaderComponentResolver(context, null, false, false));
- camelContextExtension.addContextPlugin(
- DataFormatResolver.class, new DependencyDownloaderDataFormatResolver(context, null, false));
- camelContextExtension.addContextPlugin(
- LanguageResolver.class, new DependencyDownloaderLanguageResolver(context, null, false));
- camelContextExtension.addContextPlugin(
- TransformerResolver.class, new DependencyDownloaderTransformerResolver(context, null, false));
- camelContextExtension.addContextPlugin(
- UriFactoryResolver.class, new DependencyDownloaderUriFactoryResolver(context));
-
- downloadDependencies(context);
-
- DependencyDownloaderRoutesLoader loader = new DependencyDownloaderRoutesLoader(context);
- camelContextExtension.addContextPlugin(RoutesLoader.class, loader);
-
- final ResourceLoader resourceLoader = PluginHelper.getResourceLoader(context);
- final Resource resource = resourceLoader.resolveResource(path);
-
- loader.loadRoutes(resource);
-
- context.build();
- }
-
- private void downloadDependencies(CamelContext camelContext) {
- ExtendedCamelContext camelContextExtension = camelContext.getCamelContextExtension();
-
- if (dependenciesList != null) {
- final String[] dependencies = dependenciesList.split(",");
- for (String dependency : dependencies) {
- // In case of empty file
- if (!dependency.isEmpty()) {
- dependency = dependency.trim();
- downloader.downloadDependency(
- GavUtil.group(dependency), GavUtil.artifact(dependency), GavUtil.version(dependency));
- }
- }
-
- cl.getDownloaded().forEach(d -> LOG.debug("Downloaded {}", d));
- }
-
- Thread.currentThread().setContextClassLoader(cl);
- camelContextExtension.addContextPlugin(DependencyDownloader.class, downloader);
- }
-
- private MavenDependencyDownloader createDownloader(DependencyDownloaderClassLoader cl) {
- MavenDependencyDownloader downloader = new MavenDependencyDownloader();
- downloader.setClassLoader(cl);
-
- if (repositoriesList != null) {
- downloader.setRepositories(repositoriesList);
- }
-
- downloader.start();
- return downloader;
- }
-
- private static DependencyDownloaderClassLoader createClassLoader() {
- final ClassLoader parentCL = WanakuRoutesLoader.class.getClassLoader();
-
- return new DependencyDownloaderClassLoader(parentCL);
- }
-}