Config import: support .jar and .zip archives

This commit is contained in:
Roel Spilker committed 2020-01-20 14:11:21 +01:00
1 parent 290edf9527
commit 04523763df
13 files changed
+201 -21

No files matched your search

@@ -26,6 +26,11 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public abstract class ConfigurationFile {
private static final String LOMBOK_CONFIG_FILENAME = "lombok.config";
@@ -64,12 +69,12 @@ public abstract class ConfigurationFile {
return identifier;
}
@Override public boolean equals(Object obj) {
@Override public final boolean equals(Object obj) {
if (!(obj instanceof ConfigurationFile)) return false;
return identifier.equals(((ConfigurationFile)obj).identifier);
}
@Override public int hashCode() {
@Override public final int hashCode() {
return identifier.hashCode();
}
@@ -84,17 +89,13 @@ public abstract class ConfigurationFile {
private static String read(InputStream is) throws IOException {
byte[] b = buffers.get();
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
while (true) {
int r = is.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
return new String(out.toByteArray(), "UTF-8");
} finally {
is.close();
ByteArrayOutputStream out = new ByteArrayOutputStream();
while (true) {
int r = is.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
return new String(out.toByteArray(), "UTF-8");
}
private static class RegularConfigurationFile extends ConfigurationFile {
@@ -110,7 +111,22 @@ public abstract class ConfigurationFile {
}
public ConfigurationFile resolve(String path) {
File file = resolveFile(path);
if (path.endsWith("!")) return null;
String[] parts = path.split("!");
if (parts.length > 2) return null;
String realFileName = parts[0];
File file = resolveFile(realFileName);
if (realFileName.endsWith(".zip") || realFileName.endsWith(".jar")) {
try {
return ArchivedConfigurationFile.create(file, URI.create(parts.length == 1 ? LOMBOK_CONFIG_FILENAME : parts[1]));
} catch (Exception e) {
return null;
}
}
if (parts.length > 1) return null;
return file == null ? null : forFile(file);
}
@@ -138,7 +154,12 @@ public abstract class ConfigurationFile {
@Override
CharSequence contents() throws IOException {
return read(new FileInputStream(file));
FileInputStream is = new FileInputStream(file);
try {
return read(is);
} finally {
is.close();
}
}
@Override ConfigurationFile parent() {
@@ -147,6 +168,111 @@ public abstract class ConfigurationFile {
}
}
private static class ArchivedConfigurationFile extends ConfigurationFile {
private static final URI ROOT1 = URI.create("http://x.y/a/");
private static final URI ROOT2 = URI.create("ftp://y.x/b/");
private static final ConcurrentMap<String, Object> locks = new ConcurrentHashMap<String, Object>();
private final File archive;
private final URI file;
private final Object lock;
private long lastModified = -2;
private String contents;
public static ConfigurationFile create(File archive, URI file) {
if (!isRelative(file)) return null;
return new ArchivedConfigurationFile(archive, file, archive.getPath() + "!" + file.getPath());
}
static boolean isRelative(URI path) {
try {
return ROOT1.resolve(path).toString().startsWith(ROOT1.toString()) && ROOT2.resolve(path).toString().startsWith(ROOT2.toString());
} catch (Exception e) {
return false;
}
}
ArchivedConfigurationFile(File archive, URI file, String description) {
super(description);
this.archive = archive;
this.file = file;
locks.putIfAbsent(archive.getPath(), new Object());
this.lock = locks.get(archive.getPath());
}
@Override
long getLastModifiedOrMissing() {
return getLastModifiedOrMissing(archive);
}
@Override
boolean exists() {
if (!fileExists(archive)) return false;
synchronized (lock) {
try {
readIfNeccesary();
return contents != null;
} catch (Exception e) {
return false;
}
}
}
@Override
CharSequence contents() throws IOException {
synchronized (lock) {
readIfNeccesary();
return contents;
}
}
void readIfNeccesary() throws IOException {
long archiveModified = getLastModifiedOrMissing();
if (archiveModified == lastModified) return;
contents = null;
lastModified = archiveModified;
if (archiveModified == FileSystemSourceCache.MISSING) return;
contents = read();
}
private String read() throws IOException {
FileInputStream is = new FileInputStream(archive);
try {
ZipInputStream zip = new ZipInputStream(is);
try {
while (true) {
ZipEntry entry = zip.getNextEntry();
if (entry == null) return null;
if (entry.getName().equals(file.getPath())) {
return read(zip);
}
}
} finally {
zip.close();
}
} finally {
is.close();
}
}
@Override
public ConfigurationFile resolve(String path) {
try {
URI resolved = file.resolve(path);
if (!isRelative(resolved)) return null;
return create(archive, resolved);
} catch (Exception e) {
return null;
}
}
@Override
ConfigurationFile parent() {
return null;
}
}
private static class CharSequenceConfigurationFile extends ConfigurationFile {
private final CharSequence contents;
private final long lastModified;