diff options
13 files changed, 201 insertions, 21 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; diff --git a/test/configuration/resource/configurationRoot/archives/a1.jar b/test/configuration/resource/configurationRoot/archives/a1.jar Binary files differnew file mode 100644 index 00000000..d7dca22d --- /dev/null +++ b/test/configuration/resource/configurationRoot/archives/a1.jar diff --git a/test/configuration/resource/configurationRoot/archives/a1/d1/include.config b/test/configuration/resource/configurationRoot/archives/a1/d1/include.config new file mode 100644 index 00000000..cb5316f2 --- /dev/null +++ b/test/configuration/resource/configurationRoot/archives/a1/d1/include.config @@ -0,0 +1,4 @@ +import ../d2/include.config +import nonexisting + +lombok.addGeneratedAnnotation = true
\ No newline at end of file diff --git a/test/configuration/resource/configurationRoot/archives/a1/d2/include.config b/test/configuration/resource/configurationRoot/archives/a1/d2/include.config new file mode 100644 index 00000000..d936fcfb --- /dev/null +++ b/test/configuration/resource/configurationRoot/archives/a1/d2/include.config @@ -0,0 +1 @@ +lombok.addJavaxGeneratedAnnotation = true
\ No newline at end of file diff --git a/test/configuration/resource/configurationRoot/archives/a1/lombok.config b/test/configuration/resource/configurationRoot/archives/a1/lombok.config new file mode 100644 index 00000000..14ad3803 --- /dev/null +++ b/test/configuration/resource/configurationRoot/archives/a1/lombok.config @@ -0,0 +1,3 @@ +import d1/include.config +import /illegal +lombok.anyConstructor.addConstructorProperties = true
\ No newline at end of file diff --git a/test/configuration/resource/configurationRoot/archives/a2.zip b/test/configuration/resource/configurationRoot/archives/a2.zip Binary files differnew file mode 100644 index 00000000..2b0d0036 --- /dev/null +++ b/test/configuration/resource/configurationRoot/archives/a2.zip diff --git a/test/configuration/resource/configurationRoot/archives/a2/reset.config b/test/configuration/resource/configurationRoot/archives/a2/reset.config new file mode 100644 index 00000000..94f6e4aa --- /dev/null +++ b/test/configuration/resource/configurationRoot/archives/a2/reset.config @@ -0,0 +1 @@ +clear lombok.copyableAnnotations
\ No newline at end of file diff --git a/test/configuration/resource/configurationRoot/d1/d11/d111/import1.config b/test/configuration/resource/configurationRoot/d1/d11/d111/import1.config index 2a38bda5..e94bd991 100644 --- a/test/configuration/resource/configurationRoot/d1/d11/d111/import1.config +++ b/test/configuration/resource/configurationRoot/d1/d11/d111/import1.config @@ -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
\ No newline at end of file diff --git a/test/configuration/resource/configurationRoot/d1/d11/d111/lombok.config b/test/configuration/resource/configurationRoot/d1/d11/d111/lombok.config index fefcea42..7e7719e1 100644 --- a/test/configuration/resource/configurationRoot/d1/d11/d111/lombok.config +++ b/test/configuration/resource/configurationRoot/d1/d11/d111/lombok.config @@ -1,3 +1,5 @@ import import1.config +import ../../../archives/a2.zip!reset.config clear lombok.accessors.chain -lombok.accessors.prefix += m_
\ No newline at end of file +lombok.accessors.prefix += m_ +lombok.copyableAnnotations += copy2
\ No newline at end of file diff --git a/test/configuration/resource/configurationRoot/d1/d11/lombok.config b/test/configuration/resource/configurationRoot/d1/d11/lombok.config index ec53df09..82238ba6 100644 --- a/test/configuration/resource/configurationRoot/d1/d11/lombok.config +++ b/test/configuration/resource/configurationRoot/d1/d11/lombok.config @@ -2,4 +2,6 @@ config.stopBubbling=true lombok.accessors.chain = false lombok.accessors.flagUsage = ERROR -lombok.accessors.prefix += f
\ No newline at end of file +lombok.accessors.prefix += f + +lombok.copyableAnnotations += copy1
\ No newline at end of file diff --git a/test/configuration/resource/configurationRoot/err.txt b/test/configuration/resource/configurationRoot/err.txt index a9b3f8af..c17a6dea 100644 --- a/test/configuration/resource/configurationRoot/err.txt +++ b/test/configuration/resource/configurationRoot/err.txt @@ -1,2 +1,4 @@ Problems in the configuration files: -- Imported file does not exist: import missing (BASE/d1/d11/d111/import1.config:1)
\ No newline at end of file +- 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)
\ No newline at end of file diff --git a/test/configuration/resource/configurationRoot/generate.bat b/test/configuration/resource/configurationRoot/generate.bat new file mode 100644 index 00000000..1a1f8fb0 --- /dev/null +++ b/test/configuration/resource/configurationRoot/generate.bat @@ -0,0 +1,2 @@ +jar -c -M -f archives/a1.jar -C archives/a1 . +jar -c -M -f archives/a2.zip -C archives/a2 .
\ No newline at end of file diff --git a/test/configuration/resource/configurationRoot/out.txt b/test/configuration/resource/configurationRoot/out.txt index 8cdd9bca..cca31c02 100644 --- a/test/configuration/resource/configurationRoot/out.txt +++ b/test/configuration/resource/configurationRoot/out.txt @@ -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 |