Woodpecker-Include/src/main/java/io/gitlab/jfronny/woodpecker/include/PipelineUnpacker.java

98 lines
3.9 KiB
Java
Raw Normal View History

2022-10-20 21:57:43 +02:00
package io.gitlab.jfronny.woodpecker.include;
import io.gitlab.jfronny.commons.HttpUtils;
2022-11-02 23:01:01 +01:00
import io.gitlab.jfronny.commons.StreamIterable;
2022-10-20 21:57:43 +02:00
import io.gitlab.jfronny.woodpecker.include.model.Pipeline;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Paths;
2022-10-28 17:55:26 +02:00
import java.util.*;
2022-10-20 21:57:43 +02:00
import java.util.concurrent.atomic.AtomicBoolean;
2022-11-02 23:01:01 +01:00
import java.util.function.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
2022-10-20 21:57:43 +02:00
2022-10-28 17:55:26 +02:00
final class PipelineUnpacker implements BiConsumer<Pipeline, Consumer<Pipeline>> {
2022-11-02 23:01:01 +01:00
private static final String URL = "https?://(?:www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b[-a-zA-Z0-9()@:%_+.~#?&/=]*";
private static final Pattern INCLUDE = Pattern.compile("^#include (" + URL + ")$");
private static final Pattern LINK = Pattern.compile("^#link (" + URL + ")$");
2022-10-28 17:55:26 +02:00
private final AtomicBoolean changed;
2022-11-02 23:01:01 +01:00
private final Set<String> linked = new HashSet<>();
2022-10-28 17:55:26 +02:00
public PipelineUnpacker(AtomicBoolean changed) {
this.changed = changed;
}
2022-10-20 21:57:43 +02:00
@Override
public void accept(Pipeline pipeline, Consumer<Pipeline> pipelineConsumer) {
try {
2022-11-02 23:01:01 +01:00
processPipeline(pipeline, pipelineConsumer, 0);
2022-10-20 21:57:43 +02:00
} catch (URISyntaxException e) {
throw new UncheckedIOException(new IOException("Could not find URL", e));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
2022-11-02 23:01:01 +01:00
private void processPipeline(Pipeline pipeline, Consumer<Pipeline> pipelineConsumer, int depth) throws URISyntaxException, IOException {
if (depth > 5) throw new IOException("Too many nested includes, a maximum of 5 is supported");
List<String> toLink = pipeline.data().lines()
.map(LINK::matcher)
.filter(Matcher::matches)
.map(s -> s.group(1))
.filter(s -> !linked.contains(s))
.toList();
boolean hasIncludes = pipeline.data().lines().anyMatch(INCLUDE.asPredicate());
if (toLink.isEmpty() && !hasIncludes) {
2022-10-20 21:57:43 +02:00
// Has no includes
pipelineConsumer.accept(pipeline);
return;
}
changed.set(true);
2022-11-02 23:01:01 +01:00
// Fill in includes and reprocess
if (hasIncludes) {
StringBuilder newData = new StringBuilder();
for (String line : new StreamIterable<>(pipeline.data().lines())) {
Matcher matcher = INCLUDE.matcher(line);
if (!matcher.matches()) newData.append(line);
2022-11-03 14:50:53 +01:00
else newData.append(download(matcher.group(1)).data());
2022-11-02 23:01:01 +01:00
newData.append('\n');
2022-10-20 21:57:43 +02:00
}
2022-11-02 23:01:01 +01:00
processPipeline(new Pipeline(pipeline.name(), newData.toString()), pipelineConsumer, depth + 1);
return;
}
// Link additional pipelines
for (String url : toLink) {
if (linked.contains(url)) continue;
linked.add(url);
processPipeline(download(url), pipelineConsumer, depth + 1);
}
2022-11-03 14:50:53 +01:00
// Filter
StringBuilder newDate = new StringBuilder();
boolean foundContent = false;
for (String line : new StreamIterable<>(pipeline.data().lines())) {
if (LINK.matcher(line).matches()) continue;
if (!line.isBlank()) foundContent = true;
newDate.append(line).append('\n');
}
if (foundContent) {
2022-11-03 15:03:13 +01:00
pipelineConsumer.accept(new Pipeline(pipeline.name(), newDate.toString().trim()));
2022-10-28 17:55:26 +02:00
}
2022-10-20 21:57:43 +02:00
}
2022-11-02 23:01:01 +01:00
private Pipeline download(String url) throws URISyntaxException, IOException {
2022-10-20 21:57:43 +02:00
URI uri = new URI(url.replace(" ", "%20"));
if (!"http".equalsIgnoreCase(uri.getScheme()) && !"https".equalsIgnoreCase(uri.getScheme())) {
throw new URISyntaxException(url, "Could not find scheme");
}
2022-11-02 23:01:01 +01:00
String fileName = Paths.get(new URI(url.replace(" ", "%20")).getPath()).getFileName().toString();
return new Pipeline(fileName, HttpUtils.get(url).sendString());
2022-10-20 21:57:43 +02:00
}
}