Skip to content
Merged
5 changes: 5 additions & 0 deletions private/rules/java_export.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def java_export(
javadocopts = kwargs.pop("javadocopts", [])
doc_deps = kwargs.pop("doc_deps", [])
doc_url = kwargs.pop("doc_url", "")
doc_resources = kwargs.pop("doc_resources", [])
toolchains = kwargs.pop("toolchains", [])

# Construct the java_library we'll export from here.
Expand All @@ -112,6 +113,7 @@ def java_export(
classifier_artifacts = classifier_artifacts,
doc_deps = doc_deps,
doc_url = doc_url,
doc_resources = doc_resources,
toolchains = toolchains,
)

Expand All @@ -131,6 +133,7 @@ def maven_export(
*,
doc_deps = [],
doc_url = "",
doc_resources = [],
toolchains = None):
"""
All arguments are the same as java_export with the addition of:
Expand Down Expand Up @@ -189,6 +192,7 @@ def maven_export(
(if not using `tags = ["no-javadoc"]`)
doc_url: The URL at which the generated `javadoc` will be hosted (if not using
`tags = ["no-javadoc"]`).
doc_resources: Resources to be included in the javadoc jar.
visibility: The visibility of the target
kwargs: These are passed to [`java_library`](https://bazel.build/reference/be/java#java_library),
and so may contain any valid parameter for that rule.
Expand Down Expand Up @@ -257,6 +261,7 @@ def maven_export(
javadocopts = javadocopts,
doc_deps = doc_deps,
doc_url = doc_url,
doc_resources = doc_resources,
excluded_workspaces = excluded_workspaces.keys(),
additional_dependencies = additional_dependencies,
visibility = visibility,
Expand Down
16 changes: 16 additions & 0 deletions private/rules/javadoc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def generate_javadoc(
classpath,
javadocopts,
doc_deps,
doc_resources,
output,
element_list):
inputs = []
Expand All @@ -33,14 +34,22 @@ def generate_javadoc(
args.add("--element-list", element_list)
args.add_all(source_jars, before_each = "--in")
inputs.extend(source_jars)
args.add_all(ctx.files.doc_resources, before_each = "--resources")
inputs.extend(ctx.files.doc_resources)
args.add_all(classpath, before_each = "--cp")
transitive_inputs.append(classpath)

for dep in doc_deps:
dep_info = dep[_JavadocInfo]
args.add("-linkoffline")
args.add(dep_info.url)
args.add(dep_info.element_list.dirname)
inputs.append(dep_info.element_list)

javadocopts = [
ctx.expand_make_variables("javadocopts", opt, ctx.var)
for opt in javadocopts
]
args.add_all(javadocopts)

ctx.actions.run(
Expand Down Expand Up @@ -80,6 +89,7 @@ def _javadoc_impl(ctx):
classpath,
ctx.attr.javadocopts,
ctx.attr.doc_deps,
ctx.attr.doc_resources,
jar_file,
element_list,
)
Expand Down Expand Up @@ -137,6 +147,12 @@ javadoc = rule(
This information is only used by javadoc targets depending on this target.
""",
),
"doc_resources": attr.label_list(
doc = "Resources to include in the javadoc jar.",
allow_empty = True,
allow_files = True,
default = [],
),
"excluded_workspaces": attr.string_list(
doc = "A list of bazel workspace names to exclude from the generated jar",
allow_empty = True,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class JavadocJarMaker {

public static void main(String[] args) throws IOException {
Set<Path> sourceJars = new HashSet<>();
Set<Path> resources = new HashSet<>();
Path out = null;
Path elementList = null;
Set<Path> classpath = new HashSet<>();
Expand Down Expand Up @@ -89,6 +90,11 @@ public static void main(String[] args) throws IOException {
elementList = Paths.get(next);
break;

case "--resources":
next = args[++i];
resources.add(Paths.get(next));
break;

default:
options.add(flag);
break;
Expand Down Expand Up @@ -173,6 +179,12 @@ public static void main(String[] args) throws IOException {

sources.forEach(obj -> options.add(obj.getName()));

for (Path resource : resources) {
Path target = outputTo.resolve(resource.getFileName());
Files.createDirectories(target.getParent());
Files.copy(resource, target);
}

Writer writer = new StringWriter();
DocumentationTool.DocumentationTask task =
tool.getTask(writer, fileManager, null, null, options, sources);
Expand Down
11 changes: 11 additions & 0 deletions tests/com/github/bazelbuild/rules_jvm_external/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,14 @@ java_test(
artifact("org.hamcrest:hamcrest"),
],
)

java_library(
name = "zip_utils",
testonly = 1,
srcs = ["ZipUtils.java"],
visibility = ["//:__subpackages__"],
deps = [
artifact("com.google.guava:guava"),
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/zip",
],
)
52 changes: 52 additions & 0 deletions tests/com/github/bazelbuild/rules_jvm_external/ZipUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.github.bazelbuild.rules_jvm_external;

import com.github.bazelbuild.rules_jvm_external.zip.StableZipEntry;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.ByteStreams;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import static java.nio.charset.StandardCharsets.UTF_8;

public class ZipUtils {
public static void createJar(Path outputTo, Map<String, String> pathToContents) throws IOException {
try (OutputStream os = Files.newOutputStream(outputTo);
ZipOutputStream zos = new ZipOutputStream(os)) {

for (Map.Entry<String, String> entry : pathToContents.entrySet()) {
ZipEntry ze = new StableZipEntry(entry.getKey());
zos.putNextEntry(ze);
if (!ze.isDirectory()) {
zos.write(entry.getValue().getBytes(UTF_8));
}
zos.closeEntry();
}
}
}

public static Map<String, String> readJar(Path jar) throws IOException {
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();

try (InputStream is = Files.newInputStream(jar);
ZipInputStream zis = new ZipInputStream(is)) {

for (ZipEntry entry = zis.getNextEntry(); entry != null; entry = zis.getNextEntry()) {
if (entry.isDirectory()) {
continue;
}

builder.put(entry.getName(), new String(ByteStreams.toByteArray(zis), UTF_8));
}
}

return builder.build();
}
}
2 changes: 1 addition & 1 deletion tests/com/github/bazelbuild/rules_jvm_external/jar/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ java_test(
deps = [
"//private/tools/java/com/github/bazelbuild/rules_jvm_external",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/jar:MergeJars",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/zip",
"//tests/com/github/bazelbuild/rules_jvm_external:zip_utils",
artifact("com.google.guava:guava"),
artifact(
"junit:junit",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@

package com.github.bazelbuild.rules_jvm_external.jar;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.*;

import com.github.bazelbuild.rules_jvm_external.zip.StableZipEntry;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.ByteStreams;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -37,9 +36,13 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import static com.github.bazelbuild.rules_jvm_external.ZipUtils.createJar;
import static com.github.bazelbuild.rules_jvm_external.ZipUtils.readJar;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class MergeJarsTest {

Expand Down Expand Up @@ -683,39 +686,6 @@ public void mergedJarKeepsNonClassFilesFirstWinsStrategy() throws IOException {
assertEquals("log4j.rootLogger=ERROR,stdout", contents.get("log4j.properties"));
}

private void createJar(Path outputTo, Map<String, String> pathToContents) throws IOException {
try (OutputStream os = Files.newOutputStream(outputTo);
ZipOutputStream zos = new ZipOutputStream(os)) {

for (Map.Entry<String, String> entry : pathToContents.entrySet()) {
ZipEntry ze = new StableZipEntry(entry.getKey());
zos.putNextEntry(ze);
if (!ze.isDirectory()) {
zos.write(entry.getValue().getBytes(UTF_8));
}
zos.closeEntry();
}
}
}

private Map<String, String> readJar(Path jar) throws IOException {
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();

try (InputStream is = Files.newInputStream(jar);
ZipInputStream zis = new ZipInputStream(is)) {

for (ZipEntry entry = zis.getNextEntry(); entry != null; entry = zis.getNextEntry()) {
if (entry.isDirectory()) {
continue;
}

builder.put(entry.getName(), new String(ByteStreams.toByteArray(zis), UTF_8));
}
}

return builder.build();
}

private Map<String, Long> readJarTimeStamps(Path jar) throws IOException {
ImmutableMap.Builder<String, Long> builder = ImmutableMap.builder();

Expand Down
17 changes: 17 additions & 0 deletions tests/com/github/bazelbuild/rules_jvm_external/javadoc/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
load("//:defs.bzl", "artifact")

java_test(
name = "ResourceTest",
srcs = ["ResourceTest.java"],
test_class = "com.github.bazelbuild.rules_jvm_external.javadoc.ResourceTest",
deps = [
"//private/tools/java/com/github/bazelbuild/rules_jvm_external",
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/javadoc",
"//tests/com/github/bazelbuild/rules_jvm_external:zip_utils",
artifact(
"junit:junit",
repository_name = "regression_testing_coursier",
),
artifact("com.google.guava:guava"),
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.github.bazelbuild.rules_jvm_external.javadoc;

import com.google.common.collect.ImmutableMap;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;

import static com.github.bazelbuild.rules_jvm_external.ZipUtils.createJar;
import static com.github.bazelbuild.rules_jvm_external.ZipUtils.readJar;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;

public class ResourceTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();

@Test
public void shouldIncludeResourceFiles() throws Exception {
Path inputJar = temp.newFile("in.jar").toPath();
Path outputJar = temp.newFile("out.jar").toPath();
Path elementList = temp.newFile("element-list").toPath();
// deleting the file since JavadocJarMaker fails on existing files, we just need to supply the path.
elementList.toFile().delete();

Path license = temp.newFile("LICENSE").toPath();
Files.write(license, List.of("Apache License 2.0"), UTF_8);

createJar(
inputJar,
ImmutableMap.of("com/example/Main.java", "public class Main { public static void main(String[] args) {} }")
);

JavadocJarMaker.main(new String[]{
"--resources",
license.toAbsolutePath().toString(),
"--in",
inputJar.toAbsolutePath().toString(),
"--out",
outputJar.toAbsolutePath().toString(),
"--element-list",
elementList.toAbsolutePath().toString()
});

Map<String, String> contents = readJar(outputJar);
assertEquals("Apache License 2.0".strip(), contents.get("LICENSE").strip());
}
}