Skip to content

Commit

Permalink
[KOGITO-9775] Classpath loading as fallback (#3218)
Browse files Browse the repository at this point in the history
* [KOGITO-9775] Classpath loading as fallback

In case the file cannot be retrieved from file system or relative
classpath use absolute classpath to try to retrieve it.

* Marian comments

Co-authored-by: Marián Macik <[email protected]>

---------

Co-authored-by: Marián Macik <[email protected]>
  • Loading branch information
fjtirado and MarianMacik committed Sep 8, 2023
1 parent 0c2c036 commit 479f580
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Path;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class CachedContentLoader implements URIContentLoader {

private static final Logger logger = LoggerFactory.getLogger(CachedContentLoader.class);

private static class NoCopyByteArrayInputStream extends ByteArrayInputStream {
public NoCopyByteArrayInputStream(byte[] buf) {
super(buf);
Expand All @@ -39,14 +46,46 @@ public synchronized byte[] readAllBytes() {
}

private final URI uri;
private URIContentLoader[] fallbackContentLoaders;

protected CachedContentLoader(URI uri) {
protected CachedContentLoader(URI uri, URIContentLoader... fallbackContentLoaders) {
this.uri = uri;
this.fallbackContentLoaders = fallbackContentLoaders;
}

protected Optional<Path> internalGetPath() {
return Optional.empty();
}

@Override
public Optional<Path> getPath() {
return internalGetPath().or(() -> {
for (URIContentLoader contentLoader : fallbackContentLoaders) {
Optional<Path> alternativePath = contentLoader.getPath();
if (alternativePath.isPresent()) {
return alternativePath;
}
}
return Optional.empty();
});
}

@Override
public InputStream getInputStream() {
return new NoCopyByteArrayInputStream(ResourceCacheFactory.getCache().get(uri, this::loadURI));
try {
return new NoCopyByteArrayInputStream(ResourceCacheFactory.getCache().get(uri, this::loadURI));
} catch (RuntimeException ex) {
for (URIContentLoader contentLoader : fallbackContentLoaders) {
try {
InputStream stream = contentLoader.getInputStream();
logger.warn("URI {} was retrieved using a fallback mechanism {} rather than original {}", uri, contentLoader.type(), type());
return stream;
} catch (RuntimeException supressed) {
ex.addSuppressed(supressed);
}
}
throw ex;
}
}

protected abstract byte[] loadURI(URI uri);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,20 @@
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.util.Optional;

public class ClassPathContentLoader extends CachedContentLoader {

private final Optional<URL> resource;
private final String path;
private final String classpath;

ClassPathContentLoader(URI uri, Optional<ClassLoader> cl) {
super(uri);
this.path = getPath(uri);
this.resource = Optional.ofNullable(cl.orElse(Thread.currentThread().getContextClassLoader()).getResource(path));
ClassPathContentLoader(URI uri, Optional<ClassLoader> cl, URIContentLoader... fallbackContentLoaders) {
super(uri, fallbackContentLoaders);
this.classpath = getPath(uri);
this.resource = Optional.ofNullable(cl.orElse(Thread.currentThread().getContextClassLoader()).getResource(classpath));
}

static String getPath(URI uri) {
Expand All @@ -49,13 +51,26 @@ public Optional<URL> getResource() {
return resource;
}

public String getPath() {
return path;
@Override
protected Optional<Path> internalGetPath() {
return resource.map(ClassPathContentLoader::fromURL);
}

String classpath() {
return classpath;
}

private static Path fromURL(URL url) {
try {
return Path.of(url.toURI());
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid URI " + url, e);
}
}

@Override
protected byte[] loadURI(URI uri) {
return resource.map(this::loadBytes).orElseThrow(() -> new IllegalArgumentException("cannot find classpath resource " + path));
return resource.map(this::loadBytes).orElseThrow(() -> new IllegalArgumentException("cannot find classpath resource " + classpath));
}

private byte[] loadBytes(URL r) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,27 @@
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;

public class FileContentLoader extends CachedContentLoader {

private final Path path;

FileContentLoader(URI uri) {
super(uri);
FileContentLoader(URI uri, URIContentLoader... fallbackContentLoaders) {
super(uri, fallbackContentLoaders);
this.path = Path.of(getPath(uri));
}

public Path getPath() {
return path;
}

@Override
public URIContentLoaderType type() {
return URIContentLoaderType.FILE;
}

@Override
protected Optional<Path> internalGetPath() {
return Files.exists(path) ? Optional.of(path) : Optional.empty();
}

@Override
protected byte[] loadURI(URI uri) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import java.io.InputStream;
import java.net.URI;
import java.nio.file.Path;
import java.util.Optional;

public interface URIContentLoader {

Expand All @@ -25,4 +27,6 @@ public interface URIContentLoader {
InputStream getInputStream();

URIContentLoaderType type();

Optional<Path> getPath();
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,17 +123,16 @@ public Builder withBaseURI(URI baseURI) {
}

public URIContentLoader build() {
if (baseURI != null) {
uri = compoundURI(baseURI, uri);
}
switch (URIContentLoaderType.from(uri)) {
final URI finalURI = baseURI != null ? compoundURI(baseURI, uri) : uri;
switch (URIContentLoaderType.from(finalURI)) {
default:
case FILE:
return new FileContentLoader(uri);
return new FileContentLoader(finalURI, new ClassPathContentLoader(uri, Optional.ofNullable(cl)));
case HTTP:
return new HttpContentLoader(uri, Optional.ofNullable(workflow), authRef);
return new HttpContentLoader(finalURI, Optional.ofNullable(workflow), authRef);
case CLASSPATH:
return new ClassPathContentLoader(uri, Optional.ofNullable(cl));
Optional<ClassLoader> optionalCl = Optional.ofNullable(cl);
return finalURI == uri ? new ClassPathContentLoader(finalURI, optionalCl) : new ClassPathContentLoader(finalURI, optionalCl, new ClassPathContentLoader(uri, optionalCl));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void testPrefixSlashPath() {

void testPath(String prefix) {
ClassPathContentLoader contentLoader = new ClassPathContentLoader(URI.create(prefix + PATH), Optional.empty());
assertThat(contentLoader.getPath()).isEqualTo(PATH);
assertThat(contentLoader.classpath()).isEqualTo(PATH);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
package org.kie.kogito.quarkus.serverless.workflow.rpc;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
Expand All @@ -27,8 +25,6 @@

import org.kie.kogito.quarkus.serverless.workflow.WorkflowCodeGenUtils;
import org.kie.kogito.quarkus.serverless.workflow.WorkflowOperationResource;
import org.kie.kogito.serverless.workflow.io.ClassPathContentLoader;
import org.kie.kogito.serverless.workflow.io.FileContentLoader;
import org.kie.kogito.serverless.workflow.io.URIContentLoader;
import org.kie.kogito.serverless.workflow.io.URIContentLoaderFactory;
import org.slf4j.Logger;
Expand Down Expand Up @@ -79,32 +75,18 @@ public boolean trigger(CodeGenContext context) throws CodeGenException {
}

public Optional<Path> getPath(WorkflowOperationResource resource, Path outputPath) {
logger.debug("Checking if resource {} should be written to {}", resource, outputPath);
URIContentLoader contentLoader = resource.getContentLoader();
logger.debug("Checking if resource {} should be writen to {}", resource, outputPath);
switch (contentLoader.type()) {
case FILE:
return Optional.of(((FileContentLoader) contentLoader).getPath());
case CLASSPATH:
return ((ClassPathContentLoader) contentLoader).getResource().map(this::fromURL);
case HTTP:
try {
Path tempPath = outputPath.resolve(resource.getOperationId().getFileName());
Files.write(tempPath, URIContentLoaderFactory.readAllBytes(contentLoader));
return Optional.of(tempPath);
} catch (IOException io) {
throw new IllegalStateException(io);
}
default:
logger.warn("Unsupported content loader {}", contentLoader);
return Optional.empty();
Optional<Path> path = contentLoader.getPath();
if (path.isPresent()) {
return path;
}
}

private Path fromURL(URL url) {
try {
return Path.of(url.toURI());
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid URI " + url, e);
Path tempPath = outputPath.resolve(resource.getOperationId().getFileName());
Files.write(tempPath, URIContentLoaderFactory.readAllBytes(contentLoader));
return Optional.of(tempPath);
} catch (IOException io) {
throw new IllegalStateException(io);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{
"name": "publishEvent",
"type": "asyncapi",
"operation": "classpath:specs/asyncAPI.yaml#sendWait"
"operation": "specs/asyncAPI.yaml#sendWait"
}
],
"states": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"functions": [
{
"name": "echoFunction",
"operation": "classpath:specs/enum-parameter.yaml#echo"
"operation": "specs/enum-parameter.yaml#echo"
}
],
"states": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{
"name": "sayHello",
"type": "rpc",
"operation": "classpath:greeting.proto#Greeter#SayHello"
"operation": "greeting.proto#Greeter#SayHello"
}
],
"states": [
Expand Down

0 comments on commit 479f580

Please sign in to comment.