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;
@@ -0,0 +1,4 @@
import ../d2/include.config
import nonexisting
lombok.addGeneratedAnnotation = true
@@ -0,0 +1 @@
lombok.addJavaxGeneratedAnnotation = true
@@ -0,0 +1,3 @@
import d1/include.config
import /illegal
lombok.anyConstructor.addConstructorProperties = true
@@ -0,0 +1 @@
clear lombok.copyableAnnotations
@@ -1,5 +1,6 @@
import missing
import import1.config
import ../d111/import1.config
import ../../../archives/a1.jar
lombok.accessors.prefix += z_
lombok.accessors.prefix += f
@@ -1,3 +1,5 @@
import import1.config
import ../../../archives/a2.zip!reset.config
clear lombok.accessors.chain
lombok.accessors.prefix += m_
lombok.accessors.prefix += m_
lombok.copyableAnnotations += copy2
@@ -2,4 +2,6 @@ config.stopBubbling=true
lombok.accessors.chain = false
lombok.accessors.flagUsage = ERROR
lombok.accessors.prefix += f
lombok.accessors.prefix += f
lombok.copyableAnnotations += copy1
@@ -1,2 +1,4 @@
Problems in the configuration files:
- Imported file does not exist: import missing (BASE/d1/d11/d111/import1.config:1)
- Imported file does not exist: import missing (BASE/d1/d11/d111/import1.config:1)
- Import is not valid: import /illegal (BASE/archives/a1.jar!lombok.config:2)
- Imported file does not exist: import nonexisting (BASE/archives/a1.jar!d1/include.config:2)
@@ -0,0 +1,2 @@
jar -c -M -f archives/a1.jar -C archives/a1 .
jar -c -M -f archives/a2.zip -C archives/a2 .
@@ -28,9 +28,21 @@ lombok.accessors.flagUsage = ERROR
# BASE/d1/d11/lombok.config (stopped bubbling):
# 4: lombok.accessors.flagUsage = ERROR
#
# BASE/archives/a1.jar!d2/include.config (imported from BASE/archives/a1.jar!d1/include.config:1):
# <'lombok.accessors.flagUsage' not mentioned>
#
# BASE/archives/a1.jar!d1/include.config (imported from BASE/archives/a1.jar!lombok.config:1):
# <'lombok.accessors.flagUsage' not mentioned>
#
# BASE/archives/a1.jar!lombok.config (imported from BASE/d1/d11/d111/import1.config:4):
# <'lombok.accessors.flagUsage' not mentioned>
#
# BASE/d1/d11/d111/import1.config (imported from BASE/d1/d11/d111/lombok.config:1):
# <'lombok.accessors.flagUsage' not mentioned>
#
# BASE/archives/a2.zip!reset.config (imported from BASE/d1/d11/d111/lombok.config:2):
# <'lombok.accessors.flagUsage' not mentioned>
#
# BASE/d1/d11/d111/lombok.config:
# <'lombok.accessors.flagUsage' not mentioned>
@@ -39,11 +51,23 @@ clear lombok.accessors.chain
# BASE/d1/d11/lombok.config (stopped bubbling):
# 3: lombok.accessors.chain = false
#
# BASE/archives/a1.jar!d2/include.config (imported from BASE/archives/a1.jar!d1/include.config:1):
# <'lombok.accessors.chain' not mentioned>
#
# BASE/archives/a1.jar!d1/include.config (imported from BASE/archives/a1.jar!lombok.config:1):
# <'lombok.accessors.chain' not mentioned>
#
# BASE/archives/a1.jar!lombok.config (imported from BASE/d1/d11/d111/import1.config:4):
# <'lombok.accessors.chain' not mentioned>
#
# BASE/d1/d11/d111/import1.config (imported from BASE/d1/d11/d111/lombok.config:1):
# <'lombok.accessors.chain' not mentioned>
#
# BASE/archives/a2.zip!reset.config (imported from BASE/d1/d11/d111/lombok.config:2):
# <'lombok.accessors.chain' not mentioned>
#
# BASE/d1/d11/d111/lombok.config:
# 2: clear lombok.accessors.chain
# 3: clear lombok.accessors.chain
# Strip this field prefix, like 'f' or 'm_', from the names of generated getters and setters.
lombok.accessors.prefix += z_
@@ -52,12 +76,24 @@ lombok.accessors.prefix += m_
# BASE/d1/d11/lombok.config (stopped bubbling):
# 5: lombok.accessors.prefix += f
#
# BASE/archives/a1.jar!d2/include.config (imported from BASE/archives/a1.jar!d1/include.config:1):
# <'lombok.accessors.prefix' not mentioned>
#
# BASE/archives/a1.jar!d1/include.config (imported from BASE/archives/a1.jar!lombok.config:1):
# <'lombok.accessors.prefix' not mentioned>
#
# BASE/archives/a1.jar!lombok.config (imported from BASE/d1/d11/d111/import1.config:4):
# <'lombok.accessors.prefix' not mentioned>
#
# BASE/d1/d11/d111/import1.config (imported from BASE/d1/d11/d111/lombok.config:1):
# 4: lombok.accessors.prefix += z_
# 5: lombok.accessors.prefix += f
# 5: lombok.accessors.prefix += z_
# 6: lombok.accessors.prefix += f
#
# BASE/archives/a2.zip!reset.config (imported from BASE/d1/d11/d111/lombok.config:2):
# <'lombok.accessors.prefix' not mentioned>
#
# BASE/d1/d11/d111/lombok.config:
# 3: lombok.accessors.prefix += m_
# 4: lombok.accessors.prefix += m_
# Use this name for the generated logger fields (default: 'log').
clear lombok.log.fieldName