diff options
Diffstat (limited to 'src/support/lombok')
-rw-r--r-- | src/support/lombok/eclipseCreate/CreateEclipseDebugTarget.java | 194 | ||||
-rw-r--r-- | src/support/lombok/website/CompileChangelog.java | 147 | ||||
-rw-r--r-- | src/support/lombok/website/Domain.java | 26 | ||||
-rw-r--r-- | src/support/lombok/website/FetchCurrentVersion.java | 36 | ||||
-rw-r--r-- | src/support/lombok/website/RunSite.java | 103 | ||||
-rw-r--r-- | src/support/lombok/website/WebsiteMaker.java | 430 |
6 files changed, 936 insertions, 0 deletions
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=\"<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/lombok/bin" path="3" type="2"/> \"/>\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=\"<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive=""); + launchContent.append(n.substring(self.length())); + launchContent.append("" path="3" type="2"/> \"/>\n"); + } + } + } + if (bootpath != null) launchContent.append("\t\t<listEntry value=\"<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/lombok/" + bootpath + "" path="5" type="2"/> \"/>\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(""", "\""); + } + 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(); + } + } +} |