aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorRoel Spilker <r.spilker@gmail.com>2020-01-17 02:40:10 +0100
committerRoel Spilker <r.spilker@gmail.com>2020-01-20 14:11:21 +0100
commit04523763dff98206487b2e358697226ac7b87fd7 (patch)
tree8ca871b92f6ed22b8fe843b66b3d8d7c66c1e633 /src/core
parent290edf95275f82e674952b21d27b9f485f5a2418 (diff)
downloadlombok-04523763dff98206487b2e358697226ac7b87fd7.tar.gz
lombok-04523763dff98206487b2e358697226ac7b87fd7.tar.bz2
lombok-04523763dff98206487b2e358697226ac7b87fd7.zip
Config import: support .jar and .zip archives
Diffstat (limited to 'src/core')
-rw-r--r--src/core/lombok/core/configuration/ConfigurationFile.java154
1 files changed, 140 insertions, 14 deletions
diff --git a/src/core/lombok/core/configuration/ConfigurationFile.java b/src/core/lombok/core/configuration/ConfigurationFile.java
index 218fa73b..bb15d177 100644
--- a/src/core/lombok/core/configuration/ConfigurationFile.java
+++ b/src/core/lombok/core/configuration/ConfigurationFile.java
@@ -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;