aboutsummaryrefslogtreecommitdiff
path: root/src/support
diff options
context:
space:
mode:
authorRawi01 <Rawi01@users.noreply.github.com>2020-08-31 09:57:29 +0200
committerRawi01 <Rawi01@users.noreply.github.com>2020-08-31 09:57:29 +0200
commit82ac8aad1d0e3e152db4ce328184c40c73700cee (patch)
tree3d5abb9072d43b87f19e5faf88a3d09b6c6da8e4 /src/support
parent3d90a51163354930eeea0e26c2b0a567af8e96be (diff)
parent9148294f78a8e646ee131ca182a9b692bc028fdb (diff)
downloadlombok-82ac8aad1d0e3e152db4ce328184c40c73700cee.tar.gz
lombok-82ac8aad1d0e3e152db4ce328184c40c73700cee.tar.bz2
lombok-82ac8aad1d0e3e152db4ce328184c40c73700cee.zip
Merge branch 'master' into extensionmethod
Conflicts: build.xml
Diffstat (limited to 'src/support')
-rw-r--r--src/support/info.txt4
-rw-r--r--src/support/log4j.properties6
-rw-r--r--src/support/lombok/eclipseCreate/CreateEclipseDebugTarget.java194
-rw-r--r--src/support/lombok/website/CompileChangelog.java147
-rw-r--r--src/support/lombok/website/Domain.java26
-rw-r--r--src/support/lombok/website/FetchCurrentVersion.java36
-rw-r--r--src/support/lombok/website/RunSite.java103
-rw-r--r--src/support/lombok/website/WebsiteMaker.java430
8 files changed, 946 insertions, 0 deletions
diff --git a/src/support/info.txt b/src/support/info.txt
new file mode 100644
index 00000000..1723bffe
--- /dev/null
+++ b/src/support/info.txt
@@ -0,0 +1,4 @@
+These classes are not part of lombok itself, but used during the build. For example:
+* Code to turn the changelog into HTML ready to ship to projectlombok.org
+* Code to create eclipse debug targets
+
diff --git a/src/support/log4j.properties b/src/support/log4j.properties
new file mode 100644
index 00000000..9cafcc3b
--- /dev/null
+++ b/src/support/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootLogger=INFO, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
diff --git a/src/support/lombok/eclipseCreate/CreateEclipseDebugTarget.java b/src/support/lombok/eclipseCreate/CreateEclipseDebugTarget.java
new file mode 100644
index 00000000..e5e48c49
--- /dev/null
+++ b/src/support/lombok/eclipseCreate/CreateEclipseDebugTarget.java
@@ -0,0 +1,194 @@
+package lombok.eclipseCreate;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+public class CreateEclipseDebugTarget {
+ private Map<String, String> args;
+ private StringBuilder launchContent = new StringBuilder();
+
+ private static class InvalidCommandLineException extends Exception {
+ InvalidCommandLineException(String msg) {
+ super(msg);
+
+ }
+ InvalidCommandLineException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ CreateEclipseDebugTarget instance = new CreateEclipseDebugTarget();
+ try {
+ instance.args = parseArgs(args);
+ if (instance.args.isEmpty()) throw new InvalidCommandLineException("");
+ instance.go();
+ } catch (InvalidCommandLineException e) {
+ String msg = e.getMessage();
+ if (!msg.isEmpty()) System.err.println("ERROR: " + msg);
+ if (e.getCause() != null) {
+ e.getCause().printStackTrace();
+ }
+ printCommandLineHelp();
+ System.exit(1);
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private void go() throws InvalidCommandLineException, IOException {
+ prologue();
+ classpath();
+ epilogue();
+ String n = getArgString("name");
+ File f = new File(n + ".launch").getCanonicalFile();
+
+ OutputStream out = new FileOutputStream(f);
+ try {
+ out.write(launchContent.toString().getBytes("UTF-8"));
+ } finally {
+ out.close();
+ }
+
+ System.out.println("Debug target created: " + f);
+ }
+
+ private void prologue() throws InvalidCommandLineException {
+ String type = getArgString("testType");
+
+ launchContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
+ launchContent.append("<launchConfiguration type=\"org.eclipse.jdt.junit.launchconfig\">\n");
+ launchContent.append("\t<listAttribute key=\"org.eclipse.debug.core.MAPPED_RESOURCE_PATHS\">\n");
+ launchContent.append("\t\t<listEntry value=\"/lombok/test/core/src/").append(type.replace(".", "/")).append(".java\"/>\n");
+ launchContent.append("\t</listAttribute>\n");
+ launchContent.append("\t<listAttribute key=\"org.eclipse.debug.core.MAPPED_RESOURCE_TYPES\">\n");
+ launchContent.append("\t\t<listEntry value=\"1\"/>\n");
+ launchContent.append("\t</listAttribute>\n");
+
+ if (getArgBoolean("favorite")) {
+ launchContent.append("\t<listAttribute key=\"org.eclipse.debug.ui.favoriteGroups\">\n");
+ launchContent.append("\t\t<listEntry value=\"org.eclipse.debug.ui.launchGroup.debug\"/>\n");
+ launchContent.append("\t</listAttribute>\n");
+ }
+
+ launchContent.append("\t<stringAttribute key=\"org.eclipse.jdt.junit.CONTAINER\" value=\"\"/>\n");
+ launchContent.append("\t<booleanAttribute key=\"org.eclipse.jdt.junit.KEEPRUNNING_ATTR\" value=\"false\"/>\n");
+ launchContent.append("\t<stringAttribute key=\"org.eclipse.jdt.junit.TESTNAME\" value=\"\"/>\n");
+ launchContent.append("\t<stringAttribute key=\"org.eclipse.jdt.junit.TEST_KIND\" value=\"org.eclipse.jdt.junit.loader.junit4\"/>\n");
+ launchContent.append("\t<booleanAttribute key=\"org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD\" value=\"true\"/>\n");
+ }
+
+ private void classpath() throws InvalidCommandLineException {
+ launchContent.append("\t<listAttribute key=\"org.eclipse.jdt.launching.CLASSPATH\">\n");
+
+ String self; try {
+ self = new File("..").getCanonicalPath();
+ } catch (IOException e) {
+ throw new InvalidCommandLineException("Cannot obtain canonical path to parent directory", e);
+ }
+
+ String bootpath = getBootPath();
+
+ launchContent.append("\t\t<listEntry value=\"&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/lombok/bin&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;\"/>\n");
+ for (Map.Entry<String, String> entry : args.entrySet()) {
+ if (!entry.getKey().startsWith("conf.")) continue;
+ String[] files = entry.getValue().split(Pattern.quote(File.pathSeparator));
+ for (String file : files) {
+ String n;
+ try {
+ n = new File(file).getCanonicalPath();
+ } catch (IOException e) {
+ throw new InvalidCommandLineException("Cannot obtain canonical path to dependency " + file, e);
+ }
+ if (n.startsWith(self)) {
+ launchContent.append("\t\t<listEntry value=\"&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;");
+ launchContent.append(n.substring(self.length()));
+ launchContent.append("&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;\"/>\n");
+ }
+ }
+ }
+ if (bootpath != null) launchContent.append("\t\t<listEntry value=\"&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/lombok/" + bootpath + "&quot; path=&quot;5&quot; type=&quot;2&quot;/&gt;&#10;\"/>\n");
+ launchContent.append("\t</listAttribute>\n");
+ }
+
+ private void epilogue() throws InvalidCommandLineException {
+ String type = getArgString("testType");
+
+ launchContent.append("\t<booleanAttribute key=\"org.eclipse.jdt.launching.DEFAULT_CLASSPATH\" value=\"false\"/>\n");
+ String jvmTarget = getArgString("jvmTarget");
+ String bootpath = getBootPath();
+ launchContent.append("\t<stringAttribute key=\"org.eclipse.jdt.launching.JRE_CONTAINER\" value=\"org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-").append(jvmTarget).append("\"/>\n");
+ launchContent.append("\t<stringAttribute key=\"org.eclipse.jdt.launching.MAIN_TYPE\" value=\"").append(type).append("\"/>\n");
+ launchContent.append("\t<listAttribute key=\"org.eclipse.jdt.launching.MODULEPATH\"/>\n");
+ launchContent.append("\t<stringAttribute key=\"org.eclipse.jdt.launching.PROJECT_ATTR\" value=\"lombok\"/>\n");
+ if (getArgBoolean("shadowLoaderBased")) {
+ launchContent.append("<stringAttribute key=\"org.eclipse.jdt.launching.VM_ARGUMENTS\" value=\"-javaagent:dist/lombok.jar -Dshadow.override.lombok=${project_loc:lombok}/bin");
+ for (Map.Entry<String, String> entry : args.entrySet()) {
+ if (!entry.getKey().startsWith("conf.")) continue;
+ launchContent.append(File.pathSeparator).append(entry.getValue());
+ }
+ if (bootpath != null) launchContent.append(" -Ddelombok.bootclasspath=" + bootpath);
+ }
+ launchContent.append("\"/>\n</launchConfiguration>\n");
+ }
+
+ private String getBootPath() {
+ String bp = args.get("bootpath");
+ if (bp == null || bp.isEmpty() || bp.equals("0")) return null;
+ File f = new File(bp);
+ if (!f.isAbsolute()) return bp;
+ String r = new File(".").getAbsolutePath();
+ if (r.endsWith(".")) r = r.substring(0, r.length() - 1);
+ if (bp.startsWith(r)) return bp.substring(r.length());
+ throw new IllegalStateException("Cannot reconstruct relative path; base: " + r + " is not a parent of " + bp);
+ }
+
+ private String getArgString(String key) throws InvalidCommandLineException {
+ String v = args.get(key);
+ if (v == null) throw new InvalidCommandLineException("mandatory argument '" + key + "' missing");
+ return v;
+ }
+
+ private boolean getArgBoolean(String key) throws InvalidCommandLineException {
+ String v = args.get(key);
+ if (v == null) return false;
+ if (v.equalsIgnoreCase("false") || v.equalsIgnoreCase("f")) return false;
+ return true;
+ }
+
+ private static void printCommandLineHelp() {
+ System.err.println("CreateEclipseDebugTarget\n" +
+ " name=Lombok-test BaseJavac 11 # Sets the name of the debug target to make\n" +
+ " testType=lombok.RunJavacAndBaseTests # The test class file that this debug target should run\n" +
+ " shadowLoaderBased # Add the VM options to use lombok as an agent and pass the classpath to the shadow loader. Needed for ECJ/Eclipse.\n" +
+ " conf.test=foo:bar:baz # Where 'test' is an ivy conf name, and 'foo' is a path to a jar, relativized vs. current directory.\n" +
+ " favorite # Should the debug target be marked as favourite?\n" +
+ "");
+ }
+
+ private static Map<String, String> parseArgs(String[] args) throws IllegalArgumentException {
+ Map<String, String> map = new LinkedHashMap<String, String>();
+
+ for (String arg : args) {
+ int idx = arg.indexOf('=');
+ String key = (idx == -1 ? arg : arg.substring(0, idx)).trim();
+ String value = (idx == -1 ? "" : arg.substring(idx + 1)).trim();
+ String existing = map.get(key);
+ if (existing != null) {
+ if (key.startsWith("conf.")) {
+ value = existing + File.pathSeparator + value;
+ } else {
+ throw new IllegalArgumentException("Duplicate argument not allowed: " + key);
+ }
+ }
+ map.put(key, value);
+ }
+ return map;
+ }
+} \ No newline at end of file
diff --git a/src/support/lombok/website/CompileChangelog.java b/src/support/lombok/website/CompileChangelog.java
new file mode 100644
index 00000000..8912434e
--- /dev/null
+++ b/src/support/lombok/website/CompileChangelog.java
@@ -0,0 +1,147 @@
+package lombok.website;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.petebevin.markdown.MarkdownProcessor;
+
+public class CompileChangelog {
+ public static void main(String[] args) {
+ String fileIn = args[0];
+ String fileOut = args[1];
+ boolean edge = args.length > 3 && "-edge".equals(args[2]);
+ boolean latest = args.length > 3 && "-latest".equals(args[2]);
+ String version = args.length > 3 ? args[3] : null;
+
+ try {
+ FileInputStream in = new FileInputStream(fileIn);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ byte[] b = new byte[65536];
+ while (true) {
+ int r = in.read(b);
+ if ( r == -1 ) break;
+ out.write(b, 0, r);
+ }
+ in.close();
+ String markdown = new String(out.toByteArray(), "UTF-8");
+
+ String result;
+ if (edge) {
+ result = buildEdge(sectionByVersion(markdown, version));
+ } else if (latest) {
+ result = buildLatest(sectionByVersion(markdown, version));
+ } else {
+ result = markdownToHtml(sectionStartingAt(markdown, version));
+ }
+
+ FileOutputStream file = new FileOutputStream(fileOut);
+ file.write(result.getBytes("UTF-8"));
+ file.close();
+ System.exit(0);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ public static String getHtmlForEdge(File root, String edgeVersion) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return buildEdge(sectionByVersion(raw, edgeVersion));
+ }
+
+ public static String getHtmlForLatest(File root, String latestVersion) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return buildLatest(sectionByVersion(raw, latestVersion));
+ }
+
+ public static String getHtml(File root) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return markdownToHtml(raw);
+ }
+
+ public static String getHtmlStartingAtSection(File root, String version) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return markdownToHtml(sectionStartingAt(raw, version));
+ }
+
+ private static String readFile(File f) throws IOException {
+ byte[] b = new byte[65536];
+ FileInputStream in = new FileInputStream(f);
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ while (true) {
+ int r = in.read(b);
+ if ( r == -1 ) break;
+ out.write(b, 0, r);
+ }
+ in.close();
+ return new String(out.toByteArray(), "UTF-8");
+ } finally {
+ in.close();
+ }
+ }
+
+ private static String markdownToHtml(String markdown) {
+ return new MarkdownProcessor().markdown(markdown);
+ }
+
+ private static String buildEdge(String section) {
+ String latest = section != null ? section : "* No changelog records for this edge release.";
+ return markdownToHtml(latest);
+ }
+
+ private static String buildLatest(String section) {
+ String latest = section != null ? section : "* No changelog records for this release.";
+ String noIssueLinks = latest.replaceAll("\\[[^]]*[Ii]ssue[^]]*\\]\\([^)]*\\)", "");
+ String noLinks = noIssueLinks.replaceAll("\\[([^]]*)\\]\\([^)]*\\)", "$1");
+ return markdownToHtml(noLinks);
+ }
+
+ private static String sectionStartingAt(String markdown, String version) {
+ if (version.toUpperCase().endsWith("-HEAD") || version.toUpperCase().endsWith("-EDGE")) {
+ version = version.substring(0, version.length() - 5);
+ }
+
+ Pattern p = Pattern.compile("^.*###\\s*v(.*)$");
+ BufferedReader br = new BufferedReader(new StringReader(markdown));
+ StringBuilder out = new StringBuilder();
+ int state = 0;
+ try {
+ for (String line = br.readLine(); line != null; line = br.readLine()) {
+ if (state < 2) {
+ Matcher m = p.matcher(line);
+ if (m.matches()) state = m.group(1).startsWith(version) ? 2 : 1;
+ }
+ if (state != 1) {
+ out.append(line);
+ out.append("\n");
+ }
+ }
+ return out.toString();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static String sectionByVersion(String markdown, String version) {
+ if (version.toUpperCase().endsWith("-HEAD") || version.toUpperCase().endsWith("-EDGE")) {
+ version = version.substring(0, version.length() - 5);
+ }
+
+ Pattern p = Pattern.compile("(?is-m)^.*###\\s*v" + version + ".*?\n(.*?)(?:###\\s*v.*)?$");
+ Matcher m = p.matcher(markdown);
+ return m.matches() ? m.group(1) : null;
+ }
+} \ No newline at end of file
diff --git a/src/support/lombok/website/Domain.java b/src/support/lombok/website/Domain.java
new file mode 100644
index 00000000..103c7377
--- /dev/null
+++ b/src/support/lombok/website/Domain.java
@@ -0,0 +1,26 @@
+package lombok.website;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class Domain {
+ private static final String DEFAULT = "https://projectlombok.org/";
+ private final String prefix;
+
+ public Domain(String arg) {
+ if (arg == null || arg.isEmpty()) this.prefix = DEFAULT;
+ else {
+ if (!arg.contains("://")) arg = "https://" + arg;
+ if (!arg.endsWith("/")) arg += "/";
+ this.prefix = arg;
+ }
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public URL url(String path) throws MalformedURLException {
+ return new URL(prefix + path);
+ }
+}
diff --git a/src/support/lombok/website/FetchCurrentVersion.java b/src/support/lombok/website/FetchCurrentVersion.java
new file mode 100644
index 00000000..ec8d833a
--- /dev/null
+++ b/src/support/lombok/website/FetchCurrentVersion.java
@@ -0,0 +1,36 @@
+package lombok.website;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class FetchCurrentVersion {
+ private FetchCurrentVersion() {}
+
+ private static final Pattern VERSION_PATTERN = Pattern.compile("^.*<\\s*span\\s+id\\s*=\\s*[\"'](currentVersion|currentVersionFull)[\"'](?:\\s+style\\s*=\\s*[\"']display\\s*:\\s*none;?[\"'])?\\s*>\\s*([^\t<]+)\\s*<\\s*/\\s*span\\s*>.*$");
+
+ public static void main(String[] args) throws IOException {
+ System.out.print(fetchVersionFromSite(args.length < 2 || args[1].equals("full"), new Domain(args.length < 1 ? "" : args[0])));
+ }
+
+ public static String fetchVersionFromSite(boolean fetchFull, Domain domain) throws IOException {
+ InputStream in = domain.url("download").openStream();
+ try {
+ BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+ try {
+ for (String line = br.readLine(); line != null; line = br.readLine()) {
+ Matcher m = VERSION_PATTERN.matcher(line);
+ if (m.matches() && m.group(1).equals("currentVersionFull") == fetchFull) return m.group(2).replace("&quot;", "\"");
+ }
+ throw new IOException("Expected a span with id 'currentVersion'");
+ } finally {
+ br.close();
+ }
+ } finally {
+ in.close();
+ }
+ }
+}
diff --git a/src/support/lombok/website/RunSite.java b/src/support/lombok/website/RunSite.java
new file mode 100644
index 00000000..17e158c0
--- /dev/null
+++ b/src/support/lombok/website/RunSite.java
@@ -0,0 +1,103 @@
+package lombok.website;
+
+import static spark.Spark.*;
+
+import java.awt.Desktop;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import spark.Request;
+import spark.Response;
+import spark.Route;
+
+public class RunSite {
+ private static final int DEFAULT_PORT = 4569;
+ private final Path base;
+
+ public RunSite(Path base) {
+ this.base = base;
+ }
+
+ public static void main(String[] args) throws Exception {
+ boolean open = args.length > 1 && args[1].equals("open");
+ new RunSite(Paths.get(args[0])).go(open);
+ }
+
+ private void go(boolean open) throws Exception {
+ port(DEFAULT_PORT);
+ get("/", serve("main.html"));
+ get("/setup/overview", serve("setup/main.html"));
+ get("/setup", serve("setup/main.html"));
+ get("/features", serve("features/index.html"));
+ get("/features/all", serve("features/index.html"));
+ get("/features/experimental/all", serve("features/experimental/index.html"));
+ get("/features/experimental", serve("features/experimental/index.html"));
+
+ serveDir("/", base);
+
+ System.out.println("Serving page from " + base + " -- hit enter to stop");
+ if (open) Opener.open("http://localhost:" + DEFAULT_PORT + "/");
+ System.in.read();
+ System.exit(0);
+ }
+
+ private void serveDir(String sub, Path dir) throws IOException {
+ DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
+ try {
+ for (Path c : ds) {
+ String n = c.getFileName().toString();
+ if (n.equals(".") || n.equals("..")) continue;
+ if (Files.isDirectory(c)) {
+ serveDir(sub + n + "/", c);
+ continue;
+ }
+ String rel = base.relativize(c).toString();
+ get(sub + n, serve(rel));
+ if (n.endsWith(".html")) get(sub + n.substring(0, n.length() - 5), serve(rel));
+ }
+ } finally {
+ ds.close();
+ }
+ }
+
+ private static class Opener {
+ public static void open(String url) throws Exception {
+ Desktop.getDesktop().browse(new URI(url));
+ }
+ }
+
+ private Route serve(final String path) {
+ final Path tgt = base.resolve(path);
+
+ return new Route() {
+ @Override public Object handle(Request req, Response res) throws Exception {
+ res.type(mapMime(path));
+ return Files.readAllBytes(tgt);
+ }
+ };
+ }
+
+ private String mapMime(String path) {
+ if (path.endsWith(".css")) return "text/css; charset=UTF-8";
+ if (path.endsWith(".js")) return "text/javascript; charset=UTF-8";
+ if (path.endsWith(".png")) return "image/png";
+ if (path.endsWith(".gif")) return "image/gif";
+ if (path.endsWith(".jpg")) return "image/jpeg";
+ if (path.endsWith(".mp4")) return "video/mp4";
+ if (path.endsWith(".m4v")) return "video/mp4";
+ if (path.endsWith(".ogv")) return "video/ogg";
+ if (path.endsWith(".webm")) return "video/webm";
+ if (path.endsWith(".ico")) return "image/x-icon";
+ if (path.endsWith(".pdf")) return "application/pdf";
+ if (path.endsWith(".json")) return "application/json";
+ if (path.endsWith(".xml")) return "text/xml";
+ if (path.endsWith(".woff")) return "font/woff";
+ if (path.endsWith(".woff2")) return "font/woff2";
+ if (path.endsWith(".html")) return "text/html; charset=UTF-8";
+ return "text/plain; charset=UTF-8";
+ }
+}
diff --git a/src/support/lombok/website/WebsiteMaker.java b/src/support/lombok/website/WebsiteMaker.java
new file mode 100644
index 00000000..d786e605
--- /dev/null
+++ b/src/support/lombok/website/WebsiteMaker.java
@@ -0,0 +1,430 @@
+package lombok.website;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.java2html.Java2Html;
+import freemarker.cache.FileTemplateLoader;
+import freemarker.cache.TemplateLoader;
+import freemarker.core.HTMLOutputFormat;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateExceptionHandler;
+
+public class WebsiteMaker {
+ private final String version, fullVersion;
+ private final File baseDir, outputDir;
+
+ public WebsiteMaker(String version, String fullVersion, File baseDir, File outputDir) {
+ this.version = version;
+ this.fullVersion = fullVersion;
+ this.baseDir = baseDir;
+ this.outputDir = outputDir;
+ }
+
+ private static final class VersionFinder {
+ public static String getVersion() {
+ return getVersion0("getVersion");
+ }
+
+ public static String getFullVersion() {
+ return getVersion0("getFullVersion");
+ }
+
+ private static String getVersion0(String mName) {
+ try {
+ Class<?> c = Class.forName("lombok.core.Version");
+ Method m = c.getMethod(mName);
+ return (String) m.invoke(null);
+ } catch (ClassNotFoundException e) {
+ System.err.println("You need to specify the version string, and the full version string, as first 2 arguments.");
+ System.exit(1);
+ return null;
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private static void printAllVersions(Domain domain) throws Exception {
+ List<List<String>> versions = readAllVersions(domain);
+ for (List<String> v : versions) {
+ System.out.println(" <a href=\"" + v.get(0) + "\">" + v.get(1) + "</a>");
+ }
+ }
+
+ private static void buildAll(Domain domain, String version, String fullVersion, String argIn, String argOut, boolean newRelease) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/website");
+ } else {
+ out = new File(in, "output");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out);
+ maker.buildWebsite(domain, newRelease);
+ }
+
+ private static void buildChangelog(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/website/changelog.html");
+ } else {
+ out = new File(in, "output/changelog.html");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out.getParentFile());
+ maker.buildChangelog(out);
+ }
+
+ private static void buildDownloadEdge(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/website-edge/download-edge.html");
+ } else {
+ out = new File(in, "output/download-edge.html");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out.getParentFile());
+ maker.buildDownloadEdge(out);
+ }
+
+ private static void buildChangelogLatest(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/latestchanges.html");
+ } else {
+ out = new File(in, "output/latestchanges.html");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out.getParentFile());
+ maker.buildChangelogLatest(out);
+ }
+
+ public static void main(String[] args) throws Exception {
+ String version, fullVersion;
+ Domain domain = new Domain(args.length < 1 ? "" : args[0]);
+
+ if (args.length < 3) {
+ version = VersionFinder.getVersion();
+ fullVersion = VersionFinder.getFullVersion();
+ } else {
+ version = args[1];
+ fullVersion = args[2];
+ }
+
+ String argIn = args.length < 5 ? null : args[4];
+ String argOut = args.length < 6 ? null : args[5];
+ if (args.length < 4 || args[3].equalsIgnoreCase("all")) {
+ buildAll(domain, version, fullVersion, argIn, argOut, false);
+ } else if (args.length < 4 || args[3].equalsIgnoreCase("all-newrelease")) {
+ buildAll(domain, version, fullVersion, argIn, argOut, true);
+ } else if (args[3].equalsIgnoreCase("changelog")) {
+ buildChangelog(version, fullVersion, argIn, argOut);
+ } else if (args[3].equalsIgnoreCase("download-edge")) {
+ buildDownloadEdge(version, fullVersion, argIn, argOut);
+ } else if (args[3].equalsIgnoreCase("changelog-latest")) {
+ buildChangelogLatest(version, fullVersion, argIn, argOut);
+ } else if (args[3].equalsIgnoreCase("print-allversions")) {
+ printAllVersions(domain);
+ } else {
+ throw new IllegalArgumentException("4th argument must be one of 'all', 'changelog', 'download-edge', 'changelog-latest'");
+ }
+ }
+
+ private Configuration makeFreemarkerConfig() throws IOException {
+ Configuration freemarkerConfig = new Configuration(Configuration.VERSION_2_3_25);
+ freemarkerConfig.setEncoding(Locale.ENGLISH, "UTF-8");
+ freemarkerConfig.setOutputEncoding("UTF-8");
+ freemarkerConfig.setOutputFormat(HTMLOutputFormat.INSTANCE);
+ freemarkerConfig.setTemplateLoader(createLoader());
+ freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+ return freemarkerConfig;
+ }
+
+ public void buildChangelog(File out) throws Exception {
+ Configuration freemarkerConfig = makeFreemarkerConfig();
+ outputDir.mkdirs();
+ convertChangelog(freemarkerConfig, out);
+ }
+
+ public void buildChangelogLatest(File out) throws Exception {
+ outputDir.mkdirs();
+ String htmlForLatest = CompileChangelog.getHtmlForLatest(baseDir.getParentFile(), version);
+ FileOutputStream fos = new FileOutputStream(out);
+ try {
+ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));
+ bw.write(htmlForLatest);
+ bw.close();
+ } finally {
+ fos.close();
+ }
+ }
+
+ public void buildDownloadEdge(File out) throws Exception {
+ Configuration freemarkerConfig = makeFreemarkerConfig();
+
+ outputDir.mkdirs();
+ convertDownloadEdge(freemarkerConfig, out);
+ }
+
+ public void buildHtAccess(File out) throws Exception {
+ Configuration freemarkerConfig = new Configuration(Configuration.VERSION_2_3_25);
+ freemarkerConfig.setEncoding(Locale.ENGLISH, "UTF-8");
+ freemarkerConfig.setOutputEncoding("UTF-8");
+ freemarkerConfig.setOutputFormat(HTMLOutputFormat.INSTANCE);
+ freemarkerConfig.setTemplateLoader(createLoader("extra"));
+ freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+
+ outputDir.mkdirs();
+ convertHtAccess(freemarkerConfig, out);
+ }
+
+ public void buildWebsite(Domain domain, boolean newRelease) throws Exception {
+ Configuration freemarkerConfig = makeFreemarkerConfig();
+
+ outputDir.mkdirs();
+ convertTemplates(domain, freemarkerConfig, newRelease);
+ buildHtAccess(new File(outputDir, ".htaccess"));
+ }
+
+ private TemplateLoader createLoader() throws IOException {
+ return createLoader("templates");
+ }
+
+ private TemplateLoader createLoader(String base) throws IOException {
+ return new FileTemplateLoader(new File(baseDir, base));
+ }
+
+ private void convertHtAccess(Configuration freemarker, File outFile) throws Exception {
+ Map<String, Object> dataModel = new HashMap<String, Object>();
+ dataModel.put("setupPages", listHtmlNames(new File(outputDir, "setup")));
+ dataModel.put("featurePages", listHtmlNames(new File(outputDir, "features")));
+ dataModel.put("experimentalPages", listHtmlNames(new File(outputDir, "features/experimental")));
+ Template template = freemarker.getTemplate("htaccess");
+ FileOutputStream fileOut = new FileOutputStream(outFile);
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+
+ private List<String> listHtmlNames(File dir) {
+ List<String> out = new ArrayList<String>();
+ for (String s : dir.list()) {
+ if (s.endsWith(".html") && !s.equals("index.html")) out.add(s.substring(0, s.length() - 5));
+ }
+ return out;
+ }
+
+ private void convertChangelog(Configuration freemarker, File outFile) throws Exception {
+ Map<String, Object> dataModel = createBasicDataModel();
+
+ Template template = freemarker.getTemplate("changelog.html");
+ FileOutputStream fileOut = new FileOutputStream(outFile);
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+
+ private void convertDownloadEdge(Configuration freemarker, File outFile) throws Exception {
+ Map<String, Object> dataModel = createBasicDataModel();
+
+ Template template = freemarker.getTemplate("_download-edge.html");
+ FileOutputStream fileOut = new FileOutputStream(outFile);
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+
+ private void convertTemplates(Domain domain, Configuration freemarker, boolean newRelease) throws Exception {
+ File basePagesLoc = new File(baseDir, "templates");
+ Map<String, Object> dataModel = createBasicDataModel();
+ dataModel.putAll(createExtendedDataModel(domain, newRelease));
+ convertTemplates_(freemarker, "", basePagesLoc, outputDir, 0, dataModel);
+ }
+
+ private void convertTemplates_(Configuration freemarker, String prefix, File from, File to, int depth, Map<String, Object> dataModel) throws Exception {
+ if (depth > 50) throw new IllegalArgumentException("50 levels is too deep: " + from);
+
+ for (File f : from.listFiles()) {
+ if (f.isDirectory()) convertTemplates_(freemarker, prefix + f.getName() + "/", f, new File(to, f.getName()), depth + 1, dataModel);
+ if (!f.isFile() || f.getName().startsWith("_")) continue;
+ to.mkdirs();
+ Template template = freemarker.getTemplate(prefix + f.getName());
+ FileOutputStream fileOut = new FileOutputStream(new File(to, f.getName()));
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+ }
+
+ private Map<String, Object> createBasicDataModel() throws IOException {
+ Map<String, Object> data = new HashMap<String, Object>();
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss 'UTC'");
+ sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+ String currentTime = sdf.format(new Date());
+
+ data.put("version", version);
+ data.put("fullVersion", fullVersion);
+ data.put("timestampString", currentTime);
+ data.put("year", "" + new GregorianCalendar().get(Calendar.YEAR));
+ data.put("changelog", CompileChangelog.getHtmlStartingAtSection(baseDir.getParentFile(), version));
+ data.put("changelogEdge", CompileChangelog.getHtmlForEdge(baseDir.getParentFile(), version));
+
+ return data;
+ }
+
+ private static final Pattern LOMBOK_LINK = Pattern.compile("^.*<a(?: (?:id|class|rel|rev|download|target|type)(?:=\"[^\"]*\")?)* href=\"(downloads/[^\"]+)\"(?: (?:id|class|rel|rev|download|target|type)(?:=\"[^\"]*\")?)*>([^<]+)</a>.*$");
+ private Map<String, Object> createExtendedDataModel(Domain domain, boolean newRelease) throws IOException {
+ Map<String, Object> data = new HashMap<String, Object>();
+
+ data.put("usages", new HtmlMaker(new File(baseDir, "usageExamples")));
+ List<List<String>> allVersions = readAllVersions(domain);
+ if (!newRelease && !allVersions.isEmpty()) allVersions.remove(0); // remove current version; it will be 're-added' as current version automatically.
+ data.put("linksToVersions", allVersions);
+
+ return data;
+ }
+
+ private static List<List<String>> readAllVersions(Domain domain) throws IOException {
+ InputStream in = domain.url("all-versions.html").openStream();
+ ArrayList<List<String>> links = new ArrayList<List<String>>();
+ try {
+ BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+ for (String line = br.readLine(); line != null; line = br.readLine()) {
+ Matcher m = LOMBOK_LINK.matcher(line);
+ if (m.matches()) {
+ String url = m.group(1);
+ String name = m.group(2);
+ if (name.endsWith(" [Current Version]")) {
+ name = "lombok-" + name.substring(0, name.length() - " [Current Version]".length()) + ".jar";
+ url = url.replace("lombok.jar", name);
+ }
+ links.add(Arrays.asList(name, url));
+ }
+ }
+ } finally {
+ in.close();
+ }
+
+ return links;
+ }
+
+ public static class HtmlMaker {
+ private final File usagesDir;
+
+ HtmlMaker(File usagesDir) {
+ this.usagesDir = usagesDir;
+ }
+
+ public String pre(String name) throws IOException {
+ return convert(new File(usagesDir, name + "Example_pre.jpage"));
+ }
+
+ public String post(String name) throws IOException {
+ return convert(new File(usagesDir, name + "Example_post.jpage"));
+ }
+
+ public String convert(File file) throws IOException {
+ String rawJava = readFully(file);
+ return Java2Html.convertToHtml(rawJava);
+ }
+ }
+
+ public static String readFully(File file) throws IOException {
+ FileInputStream fis = new FileInputStream(file);
+ try {
+ InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
+ StringBuilder out = new StringBuilder();
+ char[] b = new char[65536];
+ while (true) {
+ int r = isr.read(b);
+ if (r == -1) break;
+ out.append(b, 0, r);
+ }
+ return out.toString();
+ } finally {
+ fis.close();
+ }
+ }
+}