From 0bbedd092a1f0f506d106943b4b400c7986c5f36 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Fri, 29 May 2020 00:17:20 +0200 Subject: [build] rewriting the build system --- .../javac/apt/Javac9BaseFileObjectWrapper.java | 111 ------ src/core/lombok/javac/apt/LombokFileObjects.java | 154 ++------ src/core/lombok/javac/apt/LombokProcessor.java | 26 +- .../javac/apt/Javac9BaseFileObjectWrapper.java | 111 ++++++ src/core8/lombok/javac/apt/Javac9Compiler.java | 157 ++++++++ src/stubs/java/lang/annotation/ElementType.java | 118 ++++++ src/stubsstubs/java/nio/file/Path.java | 4 + src/support/info.txt | 4 + src/support/log4j.properties | 6 + .../eclipseCreate/CreateEclipseDebugTarget.java | 177 +++++++++ src/support/lombok/website/CompileChangelog.java | 147 +++++++ src/support/lombok/website/Domain.java | 26 ++ .../lombok/website/FetchCurrentVersion.java | 36 ++ src/support/lombok/website/WebsiteMaker.java | 430 +++++++++++++++++++++ src/utils/lombok/core/SpiLoadUtil.java | 4 +- src/website/log4j.properties | 6 - src/website/lombok/website/CompileChangelog.java | 147 ------- .../lombok/website/FetchCurrentVersion.java | 37 -- src/website/lombok/website/WebsiteMaker.java | 403 ------------------- 19 files changed, 1261 insertions(+), 843 deletions(-) delete mode 100644 src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java create mode 100644 src/core8/lombok/javac/apt/Javac9BaseFileObjectWrapper.java create mode 100644 src/core8/lombok/javac/apt/Javac9Compiler.java create mode 100644 src/stubs/java/lang/annotation/ElementType.java create mode 100644 src/stubsstubs/java/nio/file/Path.java create mode 100644 src/support/info.txt create mode 100644 src/support/log4j.properties create mode 100644 src/support/lombok/eclipseCreate/CreateEclipseDebugTarget.java create mode 100644 src/support/lombok/website/CompileChangelog.java create mode 100644 src/support/lombok/website/Domain.java create mode 100644 src/support/lombok/website/FetchCurrentVersion.java create mode 100644 src/support/lombok/website/WebsiteMaker.java delete mode 100644 src/website/log4j.properties delete mode 100644 src/website/lombok/website/CompileChangelog.java delete mode 100644 src/website/lombok/website/FetchCurrentVersion.java delete mode 100644 src/website/lombok/website/WebsiteMaker.java (limited to 'src') diff --git a/src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java b/src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java deleted file mode 100644 index f71be366..00000000 --- a/src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2010-2018 The Project Lombok Authors. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package lombok.javac.apt; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.net.URI; -import java.nio.file.Path; - -import javax.lang.model.element.Modifier; -import javax.lang.model.element.NestingKind; - -import com.sun.tools.javac.file.BaseFileManager; - -class Javac9BaseFileObjectWrapper extends com.sun.tools.javac.file.PathFileObject { - private final LombokFileObject delegate; - - public Javac9BaseFileObjectWrapper(BaseFileManager fileManager, Path path, LombokFileObject delegate) { - super(fileManager, path); - this.delegate = delegate; - } - - @Override public boolean isNameCompatible(String simpleName, Kind kind) { - return delegate.isNameCompatible(simpleName, kind); - } - - @Override public URI toUri() { - return delegate.toUri(); - } - - @SuppressWarnings("all") - @Override public String getName() { - return delegate.getName(); - } - - @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { - return delegate.getCharContent(ignoreEncodingErrors); - } - - @Override public InputStream openInputStream() throws IOException { - return delegate.openInputStream(); - } - - @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { - return delegate.openReader(ignoreEncodingErrors); - } - - @Override public Writer openWriter() throws IOException { - return delegate.openWriter(); - } - - @Override public OutputStream openOutputStream() throws IOException { - return delegate.openOutputStream(); - } - - @Override public long getLastModified() { - return delegate.getLastModified(); - } - - @Override public boolean delete() { - return delegate.delete(); - } - - @Override public Kind getKind() { - return delegate.getKind(); - } - - @Override public NestingKind getNestingKind() { - return delegate.getNestingKind(); - } - - @Override public Modifier getAccessLevel() { - return delegate.getAccessLevel(); - } - - @Override public boolean equals(Object obj) { - if (!(obj instanceof Javac9BaseFileObjectWrapper)) return false; - return delegate.equals(((Javac9BaseFileObjectWrapper)obj).delegate); - } - - @Override public int hashCode() { - return delegate.hashCode(); - } - - @Override public String toString() { - return delegate.toString(); - } -} \ No newline at end of file diff --git a/src/core/lombok/javac/apt/LombokFileObjects.java b/src/core/lombok/javac/apt/LombokFileObjects.java index f6643db3..880ef1fd 100644 --- a/src/core/lombok/javac/apt/LombokFileObjects.java +++ b/src/core/lombok/javac/apt/LombokFileObjects.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2019 The Project Lombok Authors. + * Copyright (C) 2010-2020 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,23 +22,15 @@ package lombok.javac.apt; -import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.net.URI; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Arrays; -import java.util.Iterator; import java.util.List; -import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -import javax.tools.FileObject; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; -import javax.tools.JavaFileObject.Kind; - -import com.sun.tools.javac.file.BaseFileManager; import lombok.core.DiagnosticsReceiver; import lombok.permit.Permit; @@ -116,22 +108,20 @@ final class LombokFileObjects { if (jfmClassName.equals("com.sun.tools.javac.file.JavacFileManager")) { try { Class superType = Class.forName("com.sun.tools.javac.file.BaseFileManager"); - if (superType.isInstance(jfm)) { - return new Java9Compiler(jfm); - } + if (superType.isInstance(jfm)) return java9Compiler(jfm); } catch (Throwable e) {} return Compiler.JAVAC7; } if (KNOWN_JAVA9_FILE_MANAGERS.contains(jfmClassName)) { try { - return new Java9Compiler(jfm); + return java9Compiler(jfm); } catch (Throwable e) {} } try { if (Class.forName("com.sun.tools.javac.file.PathFileObject") == null) throw new NullPointerException(); - return new Java9Compiler(jfm); + return java9Compiler(jfm); } catch (Throwable e) {} try { if (Class.forName("com.sun.tools.javac.file.BaseFileObject") == null) throw new NullPointerException(); @@ -156,122 +146,24 @@ final class LombokFileObjects { return compiler.wrap(new InterceptingJavaFileObject(delegate, fileName, diagnostics, compiler.getDecoderMethod())); } - static class Java9Compiler implements Compiler { - private final BaseFileManager fileManager; - - public Java9Compiler(JavaFileManager jfm) { - fileManager = asBaseFileManager(jfm); - } - - @Override public JavaFileObject wrap(LombokFileObject fileObject) { - Path p; try { - p = toPath(fileObject); - } catch (Exception e) { - p = null; - } - - // J9BFOW extends javac's internal file base impl of javax.tools.JavaFileObject. - // J9JFOW just straight implements it. Probably J9JFOW is fine, but we decided to extend java's internal impl possibly for a reason. - // Some exotic build environments don't _have_ file objects and crash with FileNotFoundEx, so if that happens, let's try the alternative. - if (p != null) return new Javac9BaseFileObjectWrapper(fileManager, p, fileObject); - return new Javac9JavaFileObjectWrapper(fileObject); - } - - @Override public Method getDecoderMethod() { + private static Constructor j9CompilerConstructor = null; + private static Compiler java9Compiler(JavaFileManager jfm) { + try { + if (j9CompilerConstructor == null) j9CompilerConstructor = Class.forName("lombok.javac.apt.Java9Compiler").getConstructor(JavaFileManager.class); + return (Compiler) j9CompilerConstructor.newInstance(jfm); + } catch (ClassNotFoundException e) { return null; - } - - private static Path toPath(LombokFileObject fileObject) { - URI uri = fileObject.toUri(); - if (uri.getScheme() == null) { - uri = URI.create("file:///" + uri); - } - try { - return Paths.get(uri); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException("Problems in URI '" + uri + "' (" + fileObject.toUri() + ")", e); - } - } - - private static BaseFileManager asBaseFileManager(JavaFileManager jfm) { - if (jfm instanceof BaseFileManager) { - return (BaseFileManager) jfm; - } - return new FileManagerWrapper(jfm); - } - - static class FileManagerWrapper extends BaseFileManager { - JavaFileManager manager; - - public FileManagerWrapper(JavaFileManager manager) { - super(null); - this.manager = manager; - } - - @Override - public int isSupportedOption(String option) { - return manager.isSupportedOption(option); - } - - @Override - public ClassLoader getClassLoader(Location location) { - return manager.getClassLoader(location); - } - - @Override - public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException { - return manager.list(location, packageName, kinds, recurse); - } - - @Override - public String inferBinaryName(Location location, JavaFileObject file) { - return manager.inferBinaryName(location, file); - } - - @Override - public boolean isSameFile(FileObject a, FileObject b) { - return manager.isSameFile(a, b); - } - - @Override - public boolean handleOption(String current, Iterator remaining) { - return manager.handleOption(current, remaining); - } - - @Override - public boolean hasLocation(Location location) { - return manager.hasLocation(location); - } - - @Override - public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException { - return manager.getJavaFileForInput(location, className, kind); - } - - @Override - public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException { - return manager.getJavaFileForOutput(location, className, kind, sibling); - } - - @Override - public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { - return manager.getFileForInput(location, packageName, relativeName); - } - - @Override - public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException { - return manager.getFileForOutput(location, packageName, relativeName, sibling); - } - - @Override - public void flush() throws IOException { - manager.flush(); - } - - @Override - public void close() throws IOException { - manager.close(); - } + } catch (NoSuchMethodException e) { + return null; + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof RuntimeException) throw (RuntimeException) t; + if (t instanceof Error) throw (Error) t; + throw new RuntimeException(t); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); } } } diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java index c32e09d5..852e5de6 100644 --- a/src/core/lombok/javac/apt/LombokProcessor.java +++ b/src/core/lombok/javac/apt/LombokProcessor.java @@ -24,6 +24,7 @@ package lombok.javac.apt; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; @@ -42,7 +43,6 @@ import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; -import javax.lang.model.element.QualifiedNameable; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic.Kind; import javax.tools.JavaFileManager; @@ -371,7 +371,7 @@ public class LombokProcessor extends AbstractProcessor { private String getModuleNameFor(Element element) { while (element != null) { - if (element.getKind().name().equals("MODULE")) return ModuleNameOracle.getModuleName(element); + if (element.getKind().name().equals("MODULE")) return getModuleName(element); Element n = element.getEnclosingElement(); if (n == element) return null; element = n; @@ -379,12 +379,24 @@ public class LombokProcessor extends AbstractProcessor { return null; } - // QualifiedNameable is a java7 thing, so to remain compatible with java6, shove this into an inner class to avoid the ClassNotFoundError. - private static class ModuleNameOracle { - static String getModuleName(Element element) { - if (!(element instanceof QualifiedNameable)) return null; - String name = ((QualifiedNameable) element).getQualifiedName().toString().trim(); + private static Class qualifiedNamableClass = null; + private static Method qualifiedNamableQualifiedNameMethod = null; + // QualifiedNameable isn't in java 6, so to remain compatible with java6, use reflection. + private static String getModuleName(Element element) { + try { + if (qualifiedNamableClass == null) qualifiedNamableClass = Class.forName("javax.lang.model.element.QualifiedNamable"); + if (!qualifiedNamableClass.isInstance(element)) return null; + if (qualifiedNamableQualifiedNameMethod == null) qualifiedNamableQualifiedNameMethod = qualifiedNamableClass.getMethod("getQualifiedName"); + String name = qualifiedNamableQualifiedNameMethod.invoke(element).toString().trim(); return name.isEmpty() ? null : name; + } catch (ClassNotFoundException e) { + return null; + } catch (NoSuchMethodException e) { + return null; + } catch (InvocationTargetException e) { + return null; + } catch (IllegalAccessException e) { + return null; } } diff --git a/src/core8/lombok/javac/apt/Javac9BaseFileObjectWrapper.java b/src/core8/lombok/javac/apt/Javac9BaseFileObjectWrapper.java new file mode 100644 index 00000000..f71be366 --- /dev/null +++ b/src/core8/lombok/javac/apt/Javac9BaseFileObjectWrapper.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2010-2018 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package lombok.javac.apt; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.net.URI; +import java.nio.file.Path; + +import javax.lang.model.element.Modifier; +import javax.lang.model.element.NestingKind; + +import com.sun.tools.javac.file.BaseFileManager; + +class Javac9BaseFileObjectWrapper extends com.sun.tools.javac.file.PathFileObject { + private final LombokFileObject delegate; + + public Javac9BaseFileObjectWrapper(BaseFileManager fileManager, Path path, LombokFileObject delegate) { + super(fileManager, path); + this.delegate = delegate; + } + + @Override public boolean isNameCompatible(String simpleName, Kind kind) { + return delegate.isNameCompatible(simpleName, kind); + } + + @Override public URI toUri() { + return delegate.toUri(); + } + + @SuppressWarnings("all") + @Override public String getName() { + return delegate.getName(); + } + + @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return delegate.getCharContent(ignoreEncodingErrors); + } + + @Override public InputStream openInputStream() throws IOException { + return delegate.openInputStream(); + } + + @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { + return delegate.openReader(ignoreEncodingErrors); + } + + @Override public Writer openWriter() throws IOException { + return delegate.openWriter(); + } + + @Override public OutputStream openOutputStream() throws IOException { + return delegate.openOutputStream(); + } + + @Override public long getLastModified() { + return delegate.getLastModified(); + } + + @Override public boolean delete() { + return delegate.delete(); + } + + @Override public Kind getKind() { + return delegate.getKind(); + } + + @Override public NestingKind getNestingKind() { + return delegate.getNestingKind(); + } + + @Override public Modifier getAccessLevel() { + return delegate.getAccessLevel(); + } + + @Override public boolean equals(Object obj) { + if (!(obj instanceof Javac9BaseFileObjectWrapper)) return false; + return delegate.equals(((Javac9BaseFileObjectWrapper)obj).delegate); + } + + @Override public int hashCode() { + return delegate.hashCode(); + } + + @Override public String toString() { + return delegate.toString(); + } +} \ No newline at end of file diff --git a/src/core8/lombok/javac/apt/Javac9Compiler.java b/src/core8/lombok/javac/apt/Javac9Compiler.java new file mode 100644 index 00000000..c02e5929 --- /dev/null +++ b/src/core8/lombok/javac/apt/Javac9Compiler.java @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2010-2020 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package lombok.javac.apt; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URI; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Iterator; +import java.util.Set; + +import javax.tools.FileObject; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; + +import com.sun.tools.javac.file.BaseFileManager; + +class Java9Compiler implements lombok.javac.apt.LombokFileObjects.Compiler { + private final BaseFileManager fileManager; + + public Java9Compiler(JavaFileManager jfm) { + fileManager = asBaseFileManager(jfm); + } + + @Override public JavaFileObject wrap(LombokFileObject fileObject) { + Path p; try { + p = toPath(fileObject); + } catch (Exception e) { + p = null; + } + + // J9BFOW extends javac's internal file base impl of javax.tools.JavaFileObject. + // J9JFOW just straight implements it. Probably J9JFOW is fine, but we decided to extend java's internal impl possibly for a reason. + // Some exotic build environments don't _have_ file objects and crash with FileNotFoundEx, so if that happens, let's try the alternative. + if (p != null) return new Javac9BaseFileObjectWrapper(fileManager, p, fileObject); + return new Javac9JavaFileObjectWrapper(fileObject); + } + + @Override public Method getDecoderMethod() { + return null; + } + + private static Path toPath(LombokFileObject fileObject) { + URI uri = fileObject.toUri(); + if (uri.getScheme() == null) { + uri = URI.create("file:///" + uri); + } + try { + return Paths.get(uri); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Problems in URI '" + uri + "' (" + fileObject.toUri() + ")", e); + } + } + + private static BaseFileManager asBaseFileManager(JavaFileManager jfm) { + if (jfm instanceof BaseFileManager) { + return (BaseFileManager) jfm; + } + return new FileManagerWrapper(jfm); + } + + static class FileManagerWrapper extends BaseFileManager { + JavaFileManager manager; + + public FileManagerWrapper(JavaFileManager manager) { + super(null); + this.manager = manager; + } + + @Override + public int isSupportedOption(String option) { + return manager.isSupportedOption(option); + } + + @Override + public ClassLoader getClassLoader(Location location) { + return manager.getClassLoader(location); + } + + @Override + public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException { + return manager.list(location, packageName, kinds, recurse); + } + + @Override + public String inferBinaryName(Location location, JavaFileObject file) { + return manager.inferBinaryName(location, file); + } + + @Override + public boolean isSameFile(FileObject a, FileObject b) { + return manager.isSameFile(a, b); + } + + @Override + public boolean handleOption(String current, Iterator remaining) { + return manager.handleOption(current, remaining); + } + + @Override + public boolean hasLocation(Location location) { + return manager.hasLocation(location); + } + + @Override + public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException { + return manager.getJavaFileForInput(location, className, kind); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException { + return manager.getJavaFileForOutput(location, className, kind, sibling); + } + + @Override + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { + return manager.getFileForInput(location, packageName, relativeName); + } + + @Override + public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException { + return manager.getFileForOutput(location, packageName, relativeName, sibling); + } + + @Override + public void flush() throws IOException { + manager.flush(); + } + + @Override + public void close() throws IOException { + manager.close(); + } + } +} diff --git a/src/stubs/java/lang/annotation/ElementType.java b/src/stubs/java/lang/annotation/ElementType.java new file mode 100644 index 00000000..bbab9cda --- /dev/null +++ b/src/stubs/java/lang/annotation/ElementType.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.annotation; + +/** + * The constants of this enumerated type provide a simple classification of the + * syntactic locations where annotations may appear in a Java program. These + * constants are used in {@link java.lang.annotation.Target Target} + * meta-annotations to specify where it is legal to write annotations of a + * given type. + * + *

The syntactic locations where annotations may appear are split into + * declaration contexts , where annotations apply to declarations, and + * type contexts , where annotations apply to types used in + * declarations and expressions. + * + *

The constants {@link #ANNOTATION_TYPE}, {@link #CONSTRUCTOR}, {@link + * #FIELD}, {@link #LOCAL_VARIABLE}, {@link #METHOD}, {@link #PACKAGE}, {@link + * #MODULE}, {@link #PARAMETER}, {@link #TYPE}, and {@link #TYPE_PARAMETER} + * correspond to the declaration contexts in JLS 9.6.4.1. + * + *

For example, an annotation whose type is meta-annotated with + * {@code @Target(ElementType.FIELD)} may only be written as a modifier for a + * field declaration. + * + *

The constant {@link #TYPE_USE} corresponds to the type contexts in JLS + * 4.11, as well as to two declaration contexts: type declarations (including + * annotation type declarations) and type parameter declarations. + * + *

For example, an annotation whose type is meta-annotated with + * {@code @Target(ElementType.TYPE_USE)} may be written on the type of a field + * (or within the type of the field, if it is a nested, parameterized, or array + * type), and may also appear as a modifier for, say, a class declaration. + * + *

The {@code TYPE_USE} constant includes type declarations and type + * parameter declarations as a convenience for designers of type checkers which + * give semantics to annotation types. For example, if the annotation type + * {@code NonNull} is meta-annotated with + * {@code @Target(ElementType.TYPE_USE)}, then {@code @NonNull} + * {@code class C {...}} could be treated by a type checker as indicating that + * all variables of class {@code C} are non-null, while still allowing + * variables of other classes to be non-null or not non-null based on whether + * {@code @NonNull} appears at the variable's declaration. + * + * @author Joshua Bloch + * @since 1.5 + * @jls 9.6.4.1 @Target + * @jls 4.1 The Kinds of Types and Values + */ +public enum ElementType { + /** Class, interface (including annotation type), or enum declaration */ + TYPE, + + /** Field declaration (includes enum constants) */ + FIELD, + + /** Method declaration */ + METHOD, + + /** Formal parameter declaration */ + PARAMETER, + + /** Constructor declaration */ + CONSTRUCTOR, + + /** Local variable declaration */ + LOCAL_VARIABLE, + + /** Annotation type declaration */ + ANNOTATION_TYPE, + + /** Package declaration */ + PACKAGE, + + /** + * Type parameter declaration + * + * @since 1.8 + */ + TYPE_PARAMETER, + + /** + * Use of a type + * + * @since 1.8 + */ + TYPE_USE, + + /** + * Module declaration. + * + * @since 9 + */ + MODULE +} diff --git a/src/stubsstubs/java/nio/file/Path.java b/src/stubsstubs/java/nio/file/Path.java new file mode 100644 index 00000000..5fb2e7ec --- /dev/null +++ b/src/stubsstubs/java/nio/file/Path.java @@ -0,0 +1,4 @@ +package java.nio.file; + +public class Path { +} 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..d3b314cb --- /dev/null +++ b/src/support/lombok/eclipseCreate/CreateEclipseDebugTarget.java @@ -0,0 +1,177 @@ +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 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("\n"); + launchContent.append("\n"); + launchContent.append("\t\n"); + launchContent.append("\t\t\n"); + launchContent.append("\t\n"); + launchContent.append("\t\n"); + launchContent.append("\t\t\n"); + launchContent.append("\t\n"); + + if (getArgBoolean("favorite")) { + launchContent.append("\t\n"); + launchContent.append("\t\t\n"); + launchContent.append("\t\n"); + } + + launchContent.append("\t\n"); + launchContent.append("\t\n"); + launchContent.append("\t\n"); + launchContent.append("\t\n"); + launchContent.append("\t\n"); + } + + private void classpath() throws InvalidCommandLineException { + launchContent.append("\t\n"); + + String self; try { + self = new File("..").getCanonicalPath(); + } catch (IOException e) { + throw new InvalidCommandLineException("Cannot obtain canonical path to parent directory", e); + } + + launchContent.append("\t\t\n"); + for (Map.Entry 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\n"); + } + } + } + launchContent.append("\t\t\n"); + launchContent.append("\t\n"); + } + + private void epilogue() throws InvalidCommandLineException { + String type = getArgString("testType"); + + launchContent.append("\t\n"); + String jvmTarget = getArgString("jvmTarget"); + launchContent.append("\t\n"); + launchContent.append("\t\n"); + launchContent.append("\t\n"); + launchContent.append("\t\n"); + launchContent.append(" entry : args.entrySet()) { + if (!entry.getKey().startsWith("conf.")) continue; + launchContent.append(File.pathSeparator).append(entry.getValue()); + } + launchContent.append(" -Ddelombok.bootclasspath=lib/openjdk6_rt.jar\"/>\n"); + launchContent.append("\n"); + } + + 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" + + " 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 parseArgs(String[] args) throws IllegalArgumentException { + Map map = new LinkedHashMap(); + + 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/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> versions = readAllVersions(domain); + for (List v : versions) { + System.out.println(" " + v.get(1) + ""); + } + } + + 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 dataModel = new HashMap(); + 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 listHtmlNames(File dir) { + List out = new ArrayList(); + 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 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 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 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 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 createBasicDataModel() throws IOException { + Map data = new HashMap(); + + 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("^.*([^<]+).*$"); + private Map createExtendedDataModel(Domain domain, boolean newRelease) throws IOException { + Map data = new HashMap(); + + data.put("usages", new HtmlMaker(new File(baseDir, "usageExamples"))); + List> 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> readAllVersions(Domain domain) throws IOException { + InputStream in = domain.url("all-versions.html").openStream(); + ArrayList> links = new ArrayList>(); + 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(); + } + } +} diff --git a/src/utils/lombok/core/SpiLoadUtil.java b/src/utils/lombok/core/SpiLoadUtil.java index e685acd6..0feb7f12 100644 --- a/src/utils/lombok/core/SpiLoadUtil.java +++ b/src/utils/lombok/core/SpiLoadUtil.java @@ -129,9 +129,10 @@ public class SpiLoadUtil { private static void readServicesFromUrl(Collection list, URL url) throws IOException { InputStream in = url.openStream(); + BufferedReader r = null; try { if (in == null) return; - BufferedReader r = new BufferedReader(new InputStreamReader(in, "UTF-8")); + r = new BufferedReader(new InputStreamReader(in, "UTF-8")); while (true) { String line = r.readLine(); if (line == null) break; @@ -143,6 +144,7 @@ public class SpiLoadUtil { } } finally { try { + if (r != null) r.close(); if (in != null) in.close(); } catch (Throwable ignore) {} } diff --git a/src/website/log4j.properties b/src/website/log4j.properties deleted file mode 100644 index 9cafcc3b..00000000 --- a/src/website/log4j.properties +++ /dev/null @@ -1,6 +0,0 @@ -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/website/lombok/website/CompileChangelog.java b/src/website/lombok/website/CompileChangelog.java deleted file mode 100644 index 8912434e..00000000 --- a/src/website/lombok/website/CompileChangelog.java +++ /dev/null @@ -1,147 +0,0 @@ -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/website/lombok/website/FetchCurrentVersion.java b/src/website/lombok/website/FetchCurrentVersion.java deleted file mode 100644 index d32c45dd..00000000 --- a/src/website/lombok/website/FetchCurrentVersion.java +++ /dev/null @@ -1,37 +0,0 @@ -package lombok.website; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -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 == 0 || args[0].equals("full"))); - } - - public static String fetchVersionFromSite(boolean fetchFull) throws IOException { - InputStream in = new URL("https://projectlombok.org/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/website/lombok/website/WebsiteMaker.java b/src/website/lombok/website/WebsiteMaker.java deleted file mode 100644 index 87d6dcc6..00000000 --- a/src/website/lombok/website/WebsiteMaker.java +++ /dev/null @@ -1,403 +0,0 @@ -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.net.URL; -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 buildAll(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"); - } else { - out = new File(in, "output"); - } - } else { - out = new File(argOut); - } - WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out); - maker.buildWebsite(); - } - - 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; - - if (args.length < 2) { - version = VersionFinder.getVersion(); - fullVersion = VersionFinder.getFullVersion(); - } else { - version = args[0]; - fullVersion = args[1]; - } - - if (args.length < 3 || args[2].equalsIgnoreCase("all")) { - buildAll(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]); - } else if (args[2].equalsIgnoreCase("changelog")) { - buildChangelog(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]); - } else if (args[2].equalsIgnoreCase("download-edge")) { - buildDownloadEdge(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]); - } else if (args[2].equalsIgnoreCase("changelog-latest")) { - buildChangelogLatest(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]); - } else { - throw new IllegalArgumentException("3rd 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() throws Exception { - Configuration freemarkerConfig = makeFreemarkerConfig(); - - outputDir.mkdirs(); - convertTemplates(freemarkerConfig); - 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 dataModel = new HashMap(); - 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 listHtmlNames(File dir) { - List out = new ArrayList(); - 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 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 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(Configuration freemarker) throws Exception { - File basePagesLoc = new File(baseDir, "templates"); - Map dataModel = createBasicDataModel(); - dataModel.putAll(createExtendedDataModel()); - convertTemplates_(freemarker, "", basePagesLoc, outputDir, 0, dataModel); - } - - private void convertTemplates_(Configuration freemarker, String prefix, File from, File to, int depth, Map 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 createBasicDataModel() throws IOException { - Map data = new HashMap(); - - 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("^.*([^<]+).*$"); - private Map createExtendedDataModel() throws IOException { - Map data = new HashMap(); - - data.put("usages", new HtmlMaker(new File(baseDir, "usageExamples"))); - InputStream in = new URL("https://projectlombok.org/all-versions.html").openStream(); - ArrayList> links = new ArrayList>(); - 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()) links.add(Arrays.asList(m.group(1), m.group(2))); - } - } finally { - in.close(); - } - - data.put("linksToVersions", links); - - return data; - } - - 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(); - } - } -} -- cgit