added extra classpath manifest attribute

This commit is contained in:
2023-06-24 14:15:07 +08:00
parent d2040fb02a
commit a1139bdc1c
6 changed files with 310 additions and 8 deletions

View File

@@ -10,16 +10,27 @@ import java.io.Reader;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.TreeMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static net.woggioni.envelope.Constants.EXTRA_CLASSPATH_ENTRY_SEPARATOR;
public class Launcher {
@@ -53,6 +64,65 @@ public class Launcher {
}
}
private static Map<String, Map<String, Object>> createContextMap() {
Map<String, Map<String, Object>> dictMap = new TreeMap<>();
dictMap.put("env", Collections.unmodifiableMap(System.getenv()
.entrySet()
.stream()
.map(entry -> new AbstractMap.SimpleEntry<>(entry.getKey(), (Object) entry.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))));
dictMap.put("sys", Collections.unmodifiableMap(System.getProperties().entrySet().stream()
.map((Map.Entry<? super String, Object> entry) -> (Map.Entry<String, Object>) entry)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))));
return Collections.unmodifiableMap(dictMap);
}
private static Stream<JarFile> getExtraClasspath(Attributes mainAttributes) {
return Common.opt2Stream(Optional.ofNullable(mainAttributes.getValue(Constants.ManifestAttributes.EXTRA_CLASSPATH))
.map(manifestAttribute -> {
Map<String, Map<String, Object>> dictMap = createContextMap();
return Common.renderTemplate(manifestAttribute, Collections.emptyMap(), dictMap);
}).map(extraClasspathString -> {
List<String> paths = new ArrayList<>();
int cursor = 0;
while(true) {
int sep = Common.indexOfWithEscape(
extraClasspathString,
EXTRA_CLASSPATH_ENTRY_SEPARATOR,
EXTRA_CLASSPATH_ENTRY_SEPARATOR,
cursor,
extraClasspathString.length()
);
if(sep < 0) break;
paths.add(extraClasspathString.substring(cursor, sep));
cursor = sep + 1;
}
return paths;
}))
.flatMap(List::stream)
.map(Paths::get)
.flatMap(new Function<Path, Stream<Path>>() {
@Override
@SneakyThrows
public Stream<Path> apply(Path path) {
if(Files.isDirectory(path)) {
return Files.list(path).filter(childPath -> !Files.isDirectory(childPath));
} else {
return Stream.of(path);
}
}
})
.filter(path -> path.getFileName().toString().toLowerCase().endsWith(".jar"))
.map(Path::toFile)
.map(new Function<File, JarFile>() {
@Override
@SneakyThrows
public JarFile apply(File file) {
return new JarFile(file);
}
});
}
@SneakyThrows
public static void main(String[] args) {
Enumeration<URL> it = Launcher.class.getClassLoader().getResources(Constants.SYSTEM_PROPERTIES_FILE);
@@ -94,6 +164,8 @@ public class Launcher {
else sb.append((char) c);
}
}
getExtraClasspath(mainAttributes).forEach(classpath::add);
Consumer<Class<?>> runner = new Consumer<Class<?>>() {
@Override
@SneakyThrows