Skip to content

Commit

Permalink
Fixes #418 (#422)
Browse files Browse the repository at this point in the history
  • Loading branch information
Riduidel authored Feb 28, 2024
1 parent bdcc819 commit 28a3a03
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.function.Function;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
Expand All @@ -17,8 +16,6 @@
import org.ndx.aadarchi.base.enhancers.ModelElementKeys;
import org.ndx.aadarchi.base.enhancers.ModelElementKeys.ConfigProperties.Force;

import com.pivovarit.function.ThrowingFunction;

/**
* A specific file cache, usable to avoid downloading multiple times the same file content.
* @author Nicolas
Expand All @@ -38,11 +35,10 @@ public class FileContentCache {
/**
* Open stream from the given source.
* @param source
* @param function
* @return
* @throws IOException
*/
private InputStream openStreamFor(FileObject source, Function<URL, InputStream> function) throws IOException {
public InputStream openStreamFor(FileObject source) throws IOException {
// We shouldn't cache local files.
// It's both inefficient, and triggers weird bugs on Windows
if(source instanceof LocalFile) {
Expand All @@ -59,31 +55,15 @@ private InputStream openStreamFor(FileObject source, Function<URL, InputStream>
URL url = new URL(uri);
FileObject file = toCacheFile(url);
if(force || !file.exists() || shouldRefresh(file)) {
refreshCache(file, url, function);
refreshCache(file, url);
}
// Now it's time to load file in cache
return file.getContent().getInputStream();
}

/**
* Get cached version of remote file
* @param file, remote scm file
* @return input stream to locally cached version of that file
* @throws IOException thrown if remote file can't be read
*/
public InputStream openStreamFor(FileObject file) throws IOException {
try {
return openStreamFor(
file,
ThrowingFunction.unchecked(_url -> file.getContent().getInputStream()));
} finally {
file.close();
}
}

private void refreshCache(FileObject file, URL url, Function<URL, InputStream> cacheLoader) throws IOException {
private void refreshCache(FileObject file, URL url) throws IOException {
file.getParent().createFolder();
try(InputStream input = cacheLoader.apply(url)) {
try(InputStream input = url.openStream()) {
try(OutputStream output = file.getContent().getOutputStream()) {
IOUtils.copy(input, output);
} finally {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package org.ndx.aadarchi.base.enhancers.scm;

import java.io.File;

import javax.inject.Inject;

import org.assertj.core.util.Arrays;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.provider.local.LocalFileSystem;
import org.assertj.core.api.Assertions;
import org.jboss.weld.junit5.EnableWeld;
import org.jboss.weld.junit5.WeldInitiator;
import org.jboss.weld.junit5.WeldSetup;
import org.junit.jupiter.api.Test;
import org.ndx.aadarchi.base.AgileArchitectureSection;
import org.ndx.aadarchi.base.ArchitectureEnhancer;
import org.ndx.aadarchi.base.OutputBuilder;
import org.ndx.aadarchi.base.OutputBuilder.Format;
import org.ndx.aadarchi.base.enhancers.ModelElementKeys;

import com.structurizr.Workspace;
Expand All @@ -24,11 +31,19 @@ class ReadmeReaderTest {
@Test
void bug_81_can_read_a_local_readme_file() {
// Given
String METHOD_NAME = "bug_81_can_read_a_local_readme_file";
var w = new Workspace(getClass().getName(), "a test workspace");
var system = w.getModel().addSoftwareSystem("The system to add a readme to");
var system = w.getModel().addSoftwareSystem(getClass().getName()+"#"+METHOD_NAME);
system.addProperty(ModelElementKeys.ConfigProperties.BasePath.NAME, ".");
// When
enhancer.enhance(w, tested);
}

// Then
FileObject readme = enhancer.getOutputBuilder().outputFor(AgileArchitectureSection.code, system, tested, Format.adoc);
Assertions.assertThat(readme.getFileSystem()).isInstanceOf(LocalFileSystem.class);
// yeah obviously we generated a local file, so let's convert it to a classical file
File readmeFile = readme.getPath().toFile();
Assertions.assertThat(readmeFile).exists()
.isNotEmpty()
.content().contains("aadarchi");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,31 @@

import javax.inject.Inject;

import org.apache.commons.io.IOUtils;
import org.apache.commons.vfs2.AllFileSelector;
import org.apache.commons.vfs2.FileFilter;
import org.apache.commons.vfs2.FileFilterSelector;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSelectInfo;
import org.apache.commons.vfs2.FileSelector;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.PatternFileSelector;
import org.apache.commons.vfs2.provider.local.LocalFile;
import org.apache.deltaspike.core.api.config.ConfigProperty;
import org.assertj.core.api.Assertions;
import org.jboss.weld.junit5.EnableWeld;
import org.jboss.weld.junit5.WeldInitiator;
import org.jboss.weld.junit5.WeldSetup;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.platform.commons.util.Preconditions;
import org.ndx.aadarchi.base.enhancers.ModelElementKeys;
import org.ndx.aadarchi.base.enhancers.ModelElementKeys.ConfigProperties.BasePath;

import com.pivovarit.function.ThrowingConsumer;
import com.pivovarit.function.ThrowingPredicate;

@EnableWeld
class FileContentCacheTest {

Expand All @@ -22,6 +37,10 @@ class FileContentCacheTest {

@Inject FileContentCache tested;
@Inject @ConfigProperty(name=BasePath.NAME, defaultValue = BasePath.VALUE) FileObject basePath;
@Inject @ConfigProperty(
name = ModelElementKeys.ConfigProperties.CacheDir.NAME,
defaultValue = ModelElementKeys.ConfigProperties.CacheDir.VALUE) FileObject cacheDir;
@Inject FileSystemManager fileSystemManager;

@Test
void bug_81_can_read_a_local_readme_file() throws IOException {
Expand All @@ -30,8 +49,32 @@ void bug_81_can_read_a_local_readme_file() throws IOException {
Preconditions.condition(readme.exists(), "Readme file should exist");
Preconditions.condition(readme.getContent().getSize()>0, "There should be some content in readme");
// When
String readmeText = IOUtils.toString(tested.openStreamFor(readme), "UTF-8");
// Then
Assertions.assertThat(readmeText).containsIgnoringCase("aadarchi");
}

@Test
void bug_81_can_have_a_remote_unknown_file_inserted_into_cache() throws IOException {
// Given
var readme = fileSystemManager.resolveFile("http5s://github.com/Riduidel/aadarchi/raw/main/README.md");
Preconditions.condition(!(readme instanceof LocalFile), "Since readme come from the web, it should be remote, no?");
// We clear the cache before any operation
tested.cacheDir = cacheDir;
tested.cacheDir.deleteAll();
// When
try(var input = tested.openStreamFor(readme)) {
Assertions.assertThat(input).isNotNull();
// There is in fact nothing else to do : the file will be automatically downloaded
}
// Then
FileObject[] localReadme = tested.cacheDir.findFiles(new AllFileSelector() {
@Override
public boolean includeFile(FileSelectInfo fileInfo) throws Exception {
return "readme.md".equals(fileInfo.getFile().getName().getBaseName().toLowerCase());
}
});
Assertions.assertThat(localReadme)
.isNotEmpty()
.allMatch(ThrowingPredicate.unchecked(file -> !file.getContent().isEmpty()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import javax.inject.Named;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.deltaspike.core.api.config.ConfigProperty;
import org.ndx.aadarchi.base.utils.FileContentCache;

Expand Down Expand Up @@ -56,18 +57,22 @@ public class MvnRepositoryArtifactsProducer {

private List<MvnRepositoryArtifact> readMvnRepositoryArtifacts(ObjectMapper objectMapper)
throws IOException, StreamReadException, DatabindException {
List<MvnRepositoryArtifact> artifacts = null;
// First, ensure the cached file has some content
try {
try(InputStream input = cache.openStreamFor(upToDateAadarchiTechnologies)) {
artifacts = objectMapper.readValue(input, new TypeReference<List<MvnRepositoryArtifact>>() {});
}
return readArtifactsFrom(objectMapper, upToDateAadarchiTechnologies);
} catch(Exception e) {
logger.log(Level.WARNING, "Unable to read remote mvnrepository.json file", e);
try(InputStream input = cache.openStreamFor(defaultAadarchiTechnlogies)) {
artifacts = objectMapper.readValue(input, new TypeReference<List<MvnRepositoryArtifact>>() {});
}
return readArtifactsFrom(objectMapper, defaultAadarchiTechnlogies);
}
}

private List<MvnRepositoryArtifact> readArtifactsFrom(ObjectMapper objectMapper, FileObject source)
throws IOException, StreamReadException, DatabindException, FileSystemException {
List<MvnRepositoryArtifact> artifacts;
try(InputStream input = cache.openStreamFor(source)) {
return artifacts = objectMapper.readValue(input, new TypeReference<List<MvnRepositoryArtifact>>() {});
} finally {
source.close();
}
return artifacts;
}
}

0 comments on commit 28a3a03

Please sign in to comment.