Skip to content

Commit

Permalink
Generate javadoc JARs.
Browse files Browse the repository at this point in the history
  • Loading branch information
tecarter94 committed May 8, 2024
1 parent a4581eb commit a0fe6cf
Show file tree
Hide file tree
Showing 13 changed files with 339 additions and 88 deletions.
13 changes: 13 additions & 0 deletions builder/src/main/java/dev/sashimono/builder/Sashimono.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
import dev.sashimono.builder.config.RepositoryConfig;
import dev.sashimono.builder.dependencies.DownloadDependencyTask;
import dev.sashimono.builder.dependencies.ResolvedDependency;
import dev.sashimono.builder.documenter.DocumentationResult;
import dev.sashimono.builder.documenter.JavaDocumenterTask;
import dev.sashimono.builder.jar.DigestTask;
import dev.sashimono.builder.jar.FileOutput;
import dev.sashimono.builder.jar.JarResult;
import dev.sashimono.builder.jar.JarTask;
import dev.sashimono.builder.jar.JavadocJarTask;
import dev.sashimono.builder.jar.PomTask;
import dev.sashimono.builder.jar.SourcesJarTask;
import dev.sashimono.builder.util.Task;
Expand Down Expand Up @@ -52,6 +55,7 @@ public void buildProject() {
Task<Void> digestTask = runner.newTask(Void.class, new DigestTask());
Map<GAV, Task<FileOutput>> pomTasks = new HashMap<>();
Map<GAV, Task<FileOutput>> sourcesJarTasks = new HashMap<>();
Map<GAV, Task<FileOutput>> javadocJarTasks = new HashMap<>();
//first we need to figure out what we are building locally, so we don't try and download it
for (var m : config.moduleConfigs()) {
if (m.packaging().equals(JAR)) {
Expand All @@ -65,6 +69,9 @@ public void buildProject() {
Task<FileOutput> sourcesJarTask = runner.newTask(FileOutput.class,
new SourcesJarTask(outputDir, m.gav(), m.filteredResourcesDir(), m.sourceDirectories()));
sourcesJarTasks.put(m.gav(), sourcesJarTask);
Task<FileOutput> javadocJarTask = runner.newTask(FileOutput.class,
new JavadocJarTask(outputDir, m.gav(), m.filteredResourcesDir()));
javadocJarTasks.put(m.gav(), javadocJarTask);
}
}
for (var m : config.moduleConfigs()) {
Expand Down Expand Up @@ -92,8 +99,11 @@ public void buildProject() {
if (m.packaging().equals(JAR)) {
Task<CompileResult> compileTask = runner.newTask(CompileResult.class,
new JavaCompilerTask(m.sourceDirectories()));
Task<DocumentationResult> documentationTask = runner.newTask(DocumentationResult.class,
new JavaDocumenterTask(m.sourceDirectories()));
for (var i : moduleDependencies) {
compileTask.addDependency(i);
documentationTask.addDependency(i);
}
Task<JarResult> jarTask = jarTasks.get(m.gav());
jarTask.addDependency(compileTask);
Expand All @@ -102,6 +112,9 @@ public void buildProject() {
digestTask.addDependency(pomTask);
Task<FileOutput> sourcesJarTask = sourcesJarTasks.get(m.gav());
digestTask.addDependency(sourcesJarTask);
Task<FileOutput> javadocJarTask = javadocJarTasks.get(m.gav());
javadocJarTask.addDependency(documentationTask);
digestTask.addDependency(javadocJarTask);
}
}
runner.run();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,107 +2,63 @@

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

import dev.sashimono.builder.tool.AbstractJavaTool;
import dev.sashimono.builder.util.Log;

public class JavaCompiler {
public class JavaCompiler extends AbstractJavaTool {

static final Log log = Log.of(JavaCompiler.class);
private static final Log log = Log.of(JavaCompiler.class);

private final javax.tools.JavaCompiler compiler;
private final List<String> compilerFlags;
private final List<Path> dependencies;
private final List<Path> sourceDirectories;

public static JavaCompiler build(List<Path> dependencies, List<Path> sourceDirectories) {
return new JavaCompiler(ToolProvider.getSystemJavaCompiler(), List.of(), dependencies, sourceDirectories);
}

JavaCompiler(javax.tools.JavaCompiler compiler, List<String> compilerFlags, List<Path> dependencies,
List<Path> sourceDirectories) {
this.compiler = compiler;
this.compilerFlags = compilerFlags;
this.dependencies = dependencies;
this.sourceDirectories = sourceDirectories;
public JavaCompiler(final javax.tools.JavaCompiler compiler, final List<String> flags, final List<Path> dependencies,
final List<Path> sourceDirectories) {
super(compiler, flags, dependencies, sourceDirectories);
if (compiler == null) {
throw new RuntimeException("No system java compiler provided");
}
}

public Path compile() {

StandardJavaFileManager fileManager = compiler.getStandardFileManager((DiagnosticListener) null, (Locale) null,
StandardCharsets.UTF_8);
@Override
protected Log getLogger() {
return log;
}

List<File> sourceFiles = new ArrayList<>();
sourceDirectories.forEach(s -> {
try {
Files.walkFileTree(s, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (file.getFileName().toString().endsWith(".java")) {
sourceFiles.add(file.toFile());
}
return FileVisitResult.CONTINUE;
}
public static JavaCompiler build(final List<Path> dependencies, final List<Path> sourceDirectories) {
return new JavaCompiler(ToolProvider.getSystemJavaCompiler(), List.of(), dependencies, sourceDirectories);
}

});
} catch (IOException e) {
throw new RuntimeException(e);
}
});
//we sort the source files to help with reproducibility
sourceFiles.sort(Comparator.comparing(Object::toString));
@Override
public Path process() {
final javax.tools.JavaCompiler compiler = (javax.tools.JavaCompiler) tool;
final StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null,
StandardCharsets.UTF_8);
final List<File> sourceFiles = collectSourceFiles();
try {
var output = Files.createTempDirectory("output");
fileManager.setLocation(StandardLocation.CLASS_PATH,
dependencies.stream().map(Path::toFile).collect(Collectors.toSet()));
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, List.of(output.toFile()));

DiagnosticCollector<JavaFileObject> diagnosticsCollector = new DiagnosticCollector();
var sources = fileManager
final Path output = configureFileManager(fileManager, StandardLocation.CLASS_OUTPUT);
final DiagnosticCollector<JavaFileObject> diagnosticsCollector = new DiagnosticCollector<>();
final var sources = fileManager
.getJavaFileObjectsFromFiles(sourceFiles);
javax.tools.JavaCompiler.CompilationTask task = this.compiler.getTask((Writer) null, fileManager,
final javax.tools.JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager,
diagnosticsCollector,
this.compilerFlags, (Iterable) null, sources);
boolean compilationTaskSucceed = task.call();

for (Diagnostic<? extends JavaFileObject> diagnostic : diagnosticsCollector.getDiagnostics()) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
log.error(diagnostic.getMessage(Locale.getDefault()));
} else {
log.info(diagnostic.getMessage(Locale.getDefault()));
}
}

this.flags, null, sources);
final boolean compilationTaskSucceed = task.call();
processDiagnostics(diagnosticsCollector);
if (!compilationTaskSucceed) {
throw new RuntimeException("compilation failed");
}
log.infof("Compiled classes to %s", output);
return output;
} catch (IOException e) {
} catch (final IOException e) {
throw new RuntimeException("Cannot initialize file manager", e);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,21 @@
import java.util.function.Function;

import dev.sashimono.builder.dependencies.ResolvedDependency;
import dev.sashimono.builder.tool.AbstractJavaToolTask;
import dev.sashimono.builder.util.TaskMap;

public class JavaCompilerTask implements Function<TaskMap, CompileResult> {
public class JavaCompilerTask extends AbstractJavaToolTask implements Function<TaskMap, CompileResult> {

private final List<Path> sourceDirectories;

public JavaCompilerTask(List<Path> sourceDirectories) {
this.sourceDirectories = sourceDirectories;
public JavaCompilerTask(final List<Path> sourceDirectories) {
super(sourceDirectories);
}

@Override
public CompileResult apply(TaskMap taskMap) {
public CompileResult apply(final TaskMap taskMap) {
//grab both the downloaded and compiled dependencies
var deps = taskMap.results(ResolvedDependency.class).stream().map(ResolvedDependency::path).toList();
var compiler = JavaCompiler.build(deps, sourceDirectories);
final List<Path> deps = taskMap.results(ResolvedDependency.class).stream().map(ResolvedDependency::path).toList();
final JavaCompiler compiler = JavaCompiler.build(deps, sourceDirectories);

return new CompileResult(compiler.compile());
return new CompileResult(compiler.process());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dev.sashimono.builder.documenter;

import java.nio.file.Path;

/**
* The results of documenting, basically just a temp directory with javadoc files
*
* @param documentationDirectory
*/
public record DocumentationResult(Path documentationDirectory) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package dev.sashimono.builder.documenter;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.List;

import javax.tools.DiagnosticCollector;
import javax.tools.DocumentationTool;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import dev.sashimono.builder.compiler.JavaCompiler;
import dev.sashimono.builder.tool.AbstractJavaTool;
import dev.sashimono.builder.util.Log;

public class JavaDocumenter extends AbstractJavaTool {

private static final Log log = Log.of(JavaCompiler.class);

public JavaDocumenter(final javax.tools.DocumentationTool documenter, final List<String> flags,
final List<Path> dependencies, final List<Path> sourceDirectories) {
super(documenter, flags, dependencies, sourceDirectories);
if (documenter == null) {
throw new RuntimeException("No system java documenter provided");
}
}

@Override
protected Log getLogger() {
return log;
}

public static JavaDocumenter build(final List<Path> dependencies, final List<Path> sourceDirectories) {
// '-notimestamp' prevents timestamp from being written to .html files, ensures that hashes are identical between builds
return new JavaDocumenter(ToolProvider.getSystemDocumentationTool(), List.of("-notimestamp"), dependencies,
sourceDirectories);
}

@Override
public Path process() {
final javax.tools.DocumentationTool documenter = (DocumentationTool) tool;
final StandardJavaFileManager fileManager = documenter.getStandardFileManager(null, null,
StandardCharsets.UTF_8);
final List<File> sourceFiles = collectSourceFiles();
try {
final Path output = configureFileManager(fileManager, DocumentationTool.Location.DOCUMENTATION_OUTPUT);
final DiagnosticCollector<JavaFileObject> diagnosticsCollector = new DiagnosticCollector<>();
final Iterable<? extends JavaFileObject> sources = fileManager
.getJavaFileObjectsFromFiles(sourceFiles);
final DocumentationTool.DocumentationTask task = documenter.getTask(null, fileManager,
diagnosticsCollector,
null, this.flags, sources);
final boolean documentationTaskSucceeded = task.call();
processDiagnostics(diagnosticsCollector);
if (!documentationTaskSucceeded) {
throw new RuntimeException("documenting failed");
}
log.infof("Documented classes to %s", output);
return output;
} catch (final IOException e) {
throw new RuntimeException("Cannot initialize file manager", e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.sashimono.builder.documenter;

import java.nio.file.Path;
import java.util.List;
import java.util.function.Function;

import dev.sashimono.builder.dependencies.ResolvedDependency;
import dev.sashimono.builder.tool.AbstractJavaToolTask;
import dev.sashimono.builder.util.TaskMap;

public class JavaDocumenterTask extends AbstractJavaToolTask implements Function<TaskMap, DocumentationResult> {

public JavaDocumenterTask(final List<Path> sourceDirectories) {
super(sourceDirectories);
}

@Override
public DocumentationResult apply(final TaskMap taskMap) {
//grab both the downloaded and compiled dependencies
final List<Path> deps = taskMap.results(ResolvedDependency.class).stream().map(ResolvedDependency::path).toList();
final JavaDocumenter documenter = JavaDocumenter.build(deps, sourceDirectories);

return new DocumentationResult(documenter.process());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,22 @@
import dev.sashimono.builder.util.FileUtil;
import dev.sashimono.builder.util.Log;

public class AbstractJarTask {
public abstract class AbstractJarTask {

private static final Log log = Log.of(AbstractJarTask.class);
public static final String DELIMITER = "-";
protected final Path outputDir;
protected final GAV gav;
protected final Path filteredResourcesDir;
protected final Map<Path, List<Path>> toJar = new TreeMap<>();
protected final Map<Path, List<Path>> toJarFilesByDir = new TreeMap<>();

public AbstractJarTask(final Path outputDir, final GAV gav, final Path filteredResourcesDir) {
this.outputDir = outputDir;
this.gav = gav;
this.filteredResourcesDir = filteredResourcesDir;
}

protected abstract Log getLogger();

protected Path createJar() throws IOException {
return createJar("");
}
Expand All @@ -47,7 +48,7 @@ protected Path createJar(final String suffix) throws IOException {
artifactName += ".jar";
final Path target = parentDir.resolve(artifactName);
try (final JarOutputStream out = new JarOutputStream(Files.newOutputStream(target))) {
toJar.forEach((dir, files) -> {
toJarFilesByDir.forEach((dir, files) -> {
try {
files.sort(Comparator.comparing(Object::toString));
for (final Path file : files) {
Expand All @@ -65,13 +66,13 @@ protected Path createJar(final String suffix) throws IOException {
}
});
}
log.infof("created jar %s", target);
getLogger().infof("created jar %s", target);
return target;
}

protected void collectFiles(final Path... dirs) throws IOException {
for (final Path dir : dirs) {
toJar.put(dir, FileUtil.collectFiles(dir));
toJarFilesByDir.put(dir, FileUtil.collectFiles(dir));
}
}
}
Loading

0 comments on commit a0fe6cf

Please sign in to comment.