blob: 5198e631aa33c67ddedcd39e02c5cc0b740681b3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tomee.website;
import org.apache.openejb.loader.Files;
import org.apache.openejb.loader.IO;
import org.apache.openejb.util.Join;
import org.apache.openejb.util.Pipe;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.apache.openejb.loader.Files.mkdirs;
/**
* For each git repo (source) it will collects the `src/main/java` contents
* into one large source tree and use the Javadoc proccessor directly in code
* to (with Asciidoclet configured) to generate a single javadoc for that repo.
*
* The examples/ directory for each repo will be filtered out and not included
* in the final aggregated javadoc.
*/
public class Javadocs {
private final Sources sources;
private final List<JavadocSource> javadocSources = new ArrayList<>();
public Javadocs(final Sources sources) {
this.sources = sources;
}
/**
* Method is called for each git repo configured
* as a codebase that contributes to the documentation
*
* This is currently active branches of TomEE, but will
* be other sources in the future such as Sheldon
* and Chatterbox
*
* This method recurssively walks the already cloned
* git repo (the Source) and collects all `src/main/java`
* directories.
*
* All the files in these directories are aggregated into
* one single director at `target/<source.name>-java`.
* For example `target/tomee-8.0-java`
*
* We then run the javadoc processor on `target/<source.name>-java`
* and ensure all generated javadoc is placed at:
*
* - `<sources.generated>/<source.name>/javadoc/`
*
* For example if the Source instance represents TomEE 8.0
* and the Sources.getGenerated() returns `target/site-1.0-SNAPSHOT`
* we would generate all the javadoc into this location:
*
* - `target/site-1.0-SNAPSHOT/tomee-8.0/javadoc`
*
* @param source
*/
public void prepare(final Source source) {
final File javaSources = mkdirs(new File(String.format("target/javadocs/%s-src", source.getName())));
copySource(source, source, javaSources);
for (final Source related : source.getRelated()) {
copySource(source, related, javaSources);
}
// This part will be completed later when the perform stage is executed
source.addPerform(() -> {
final File javadocOutput = sources.getGeneratedDestFor(source, "javadoc");
final ProcessBuilder cmd = new ProcessBuilder(
getJavadocCommand().getAbsolutePath(),
"-sourcepath",
javaSources.getAbsolutePath(),
"-d",
javadocOutput.getAbsolutePath()
);
Stream.of(javaSources.listFiles())
.filter(File::isDirectory)
.forEach(file -> {
cmd.command().add("-subpackages");
cmd.command().add(file.getName());
});
try {
final Process process = cmd.start();
Pipe.pipe(process);
process.waitFor();
} catch (IOException e) {
throw new IllegalStateException("Command failed");
} catch (InterruptedException e) {
Thread.interrupted();
throw new IllegalStateException("Command failed");
}
// Scrub generated timestamps as it causes 26k needless file updates
// on the svn commit for every time the generator runs
try {
java.nio.file.Files.walk(javadocOutput.toPath())
.map(Path::toFile)
.filter(File::isFile)
.filter(this::isHtml)
.forEach(Javadocs::removeGeneratedDate);
} catch (IOException e) {
throw new IllegalStateException("Failed to remove timestamp from generated javadoc html");
}
});
}
public List<JavadocSource> getJavadocSources() {
return javadocSources;
}
public static void removeGeneratedDate(final File file) {
try {
final List<String> lines = Stream.of(IO.slurp(file).split("\n"))
.filter(line -> !line.contains("<!-- Generated by javadoc"))
.filter(line -> !line.contains("<meta name=\"date\" content=\""))
.collect(Collectors.toList());
final String updated = Join.join("\n", lines) + "\n";
// Write the cleaned version to disk
IO.copy(IO.read(updated), file);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private void copySource(final Source parent, final Source source, final File javaSources) {
final JavadocSources javadocSources = new JavadocSources();
source.setComponent(JavadocSources.class, javadocSources);
final Predicate<String> wanted = wanted(parent, source);
try {
java.nio.file.Files.walk(source.getDir().toPath())
.map(Path::toFile)
.filter(File::isFile)
.filter(this::isJava)
.filter(source.getJavadocFilter()::include)
.filter(source.getJavadocFilter()::exclude)
.forEach(file -> {
try {
final String relativePath = file.getAbsolutePath().replaceAll(".*/src/main/java/", "");
if (!wanted.test(relativePath)) return;
final File dest = new File(javaSources, relativePath);
Files.mkdirs(dest.getParentFile());
IO.copy(file, dest);
javadocSources.add(new JavadocSource(relativePath, dest));
} catch (IOException e) {
throw new IllegalStateException(e);
}
});
} catch (IOException e) {
throw new IllegalStateException("Failed to aggregate java sources");
}
}
private Predicate<String> wanted(final Source parent, final Source source) {
if (source.getJavadocPackages() != null) return source.getJavadocPackages().asPredicate();
if (parent.getJavadocPackages() != null) return parent.getJavadocPackages().asPredicate();
return s -> true;
}
public static File getJavadocCommand() {
final File java_home = System.getenv("JAVA_HOME") != null ? new File(System.getenv("JAVA_HOME")) : new File("");
final File javaHome = new File(System.getProperty("java.home"));
final Supplier<File>[] locations = new Supplier[]{
() -> new File(java_home, "bin/javadoc"),
() -> new File(java_home, "bin/javadoc.exe"),
() -> new File(java_home.getParentFile(), "bin/javadoc"),
() -> new File(java_home.getParentFile(), "bin/javadoc.exe"),
() -> new File(javaHome, "bin/javadoc"),
() -> new File(javaHome, "bin/javadoc.exe"),
() -> new File(javaHome.getParentFile(), "bin/javadoc"),
() -> new File(javaHome.getParentFile(), "bin/javadoc.exe"),
};
return Stream.of(locations)
.map(Supplier::get)
.filter(File::exists)
.filter(File::canExecute)
.findFirst().orElseThrow(() -> new IllegalStateException("Cannot find javadoc command"));
}
public static void main(String[] args) {
}
private static void copy(final File file, File javaSources) {
}
private boolean isJava(final File file) {
return file.getName().endsWith(".java");
}
private boolean isHtml(final File file) {
return file.getName().endsWith(".html");
}
}