Skip to content

Commit

Permalink
Merge pull request #42 from MontiCore/MCPathPerformance
Browse files Browse the repository at this point in the history
MCPath performance
  • Loading branch information
ahellwig authored Nov 5, 2024
2 parents 640f88f + 1215ada commit 95a3779
Showing 1 changed file with 34 additions and 15 deletions.
49 changes: 34 additions & 15 deletions monticore-runtime/src/main/java/de/monticore/io/paths/MCPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
import org.apache.commons.io.filefilter.RegexFileFilter;

import javax.annotation.Nonnull;
import java.io.*;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
Expand Down Expand Up @@ -91,6 +93,14 @@ public Optional<URL> load(@Nonnull FindCacheKey key) {
}
});

final LoadingCache<String, List<URL>> resolvedUrlsCache = CacheBuilder.newBuilder()
.build(new CacheLoader<>() {
@Override
public List<URL> load(String key) {
return do_findResolvedUrls(key);
}
});

/**
* Method for calculating a list of files located in an entry of the passed model path,
* with the passed qualified model name, and the passed regular expression over the file extension.
Expand Down Expand Up @@ -156,7 +166,7 @@ Optional<URL> do_find(FindCacheKey k) {
// iterate MCPath entries and check whether folder path exists within these
for (Path p : getEntries()) {
if(p.toString().endsWith(".jar")){
String path = "/" + folderPath.replaceAll("\\\\", "/") + "/" + fileNameRegEx;
String path = "/" + folderPath.replace('\\', '/') + "/" + fileNameRegEx;
if (k.fileExtRegEx.equals(".*sym")) {
// For .jar entries with a *.sym file extension regex, we cache the jar entries
jarSymCache.getUnchecked(p).getCandidates(path).map(uri -> {
Expand All @@ -180,7 +190,7 @@ Optional<URL> do_find(FindCacheKey k) {
}
}
File folder = p.resolve(folderPath).toFile(); //e.g., "src/test/resources/foo/bar"
if (folder.exists() && folder.isDirectory()) {
if (folder.isDirectory()) {
// perform the actual file filter on the folder and collect result
Arrays.stream(folder.listFiles(filter))
.map(f -> toURL(folder.toPath().resolve(f.getName())))
Expand Down Expand Up @@ -210,14 +220,8 @@ else if (1 < resolvedURLs.size()) {
* matching models
*/
public Optional<URL> find(String path) {
String fixedPath = path.replaceAll("\\" + File.separator, "/");

List<URL> resolvedURLs = classloaderMap.keySet().stream()
.map(classloader -> FileReaderWriter.getResource(classloader, fixedPath))
.filter(Optional::isPresent)
.map(Optional::get)
.distinct()
.collect(Collectors.toList());
String fixedPath = path.replace(File.separatorChar, '/');
List<URL> resolvedURLs = findResolvedUrls(fixedPath);

if (1 == resolvedURLs.size()) {
File resolvedFile = new File(resolvedURLs.get(0).getFile());
Expand All @@ -237,6 +241,19 @@ else if (1 < resolvedURLs.size()) {
return Optional.empty();
}

protected List<URL> findResolvedUrls(String fixedPath){
return resolvedUrlsCache.getUnchecked(fixedPath);
}

protected List<URL> do_findResolvedUrls(String fixedPath) {
return classloaderMap.keySet().stream()
.map(classloader -> FileReaderWriter.getResource(classloader, fixedPath))
.filter(Optional::isPresent)
.map(Optional::get)
.distinct()
.collect(Collectors.toList());
}

@Override
public String toString() {
String result = "[";
Expand Down Expand Up @@ -295,6 +312,7 @@ public void close(){
void invalidateCaches() {
jarSymCache.invalidateAll();
findCache.invalidateAll();
resolvedUrlsCache.invalidateAll();
}

// A List of all file systems opened for jars.
Expand Down Expand Up @@ -370,18 +388,19 @@ static class CachedPath {
final Set<Path> absolutePaths = new HashSet<>();
// path of the filesystem, which will be removed in the filter
final String replacedFS;
final Pattern removeFsPattern;

public CachedPath(String replacedFS) {
this.replacedFS = replacedFS;
this.replacedFS = replacedFS.replace('\\', '/');
removeFsPattern = Pattern.compile(Pattern.quote(replacedFS));
}

/**
* @param path the path regex, see {@link GlobExpressionEvaluator}
* @return a stream of URIs matching against this path
*/
Stream<URI> getCandidates(String path) {
path = path.replaceAll(Pattern.quote(replacedFS.replaceAll("\\\\", "/")), "");

path = removeFsPattern.matcher(path).replaceAll("");
Pattern pattern = Pattern.compile(path);

return absolutePaths.stream().filter(p -> pattern.matcher(p.toString()).matches()).map(this::toURL);
Expand All @@ -391,7 +410,7 @@ URI toURL(Path path) {
URI uri = path.toUri();
// this takes care of white spaces in files, especially jars, if they are double encoded
if (uri.toString().contains("%2520")) {
uri = URI.create(uri.toString().replaceAll("%2520", "%20"));
uri = URI.create(uri.toString().replace("%2520", "%20"));
}
return uri;
}
Expand Down

0 comments on commit 95a3779

Please sign in to comment.