diff --git a/buildSrc/src/main/java/google/registry/gradle/plugin/CoverPageGenerator.java b/buildSrc/src/main/java/google/registry/gradle/plugin/CoverPageGenerator.java index b29cf794c..28120f2bc 100644 --- a/buildSrc/src/main/java/google/registry/gradle/plugin/CoverPageGenerator.java +++ b/buildSrc/src/main/java/google/registry/gradle/plugin/CoverPageGenerator.java @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableSetMultimap; import com.google.template.soy.SoyFileSet; import com.google.template.soy.tofu.SoyTofu; import google.registry.gradle.plugin.ProjectData.TaskData; +import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.util.function.Supplier; @@ -148,10 +149,14 @@ final class CoverPageGenerator { /** returns a soy-friendly version of the given task data. */ static ImmutableMap taskDataToSoy(TaskData task) { + // Note that all instances of File.separator are replaced with forward slashes so that we can + // generate a valid href on Windows. return new ImmutableMap.Builder() .put("uniqueName", task.uniqueName()) .put("description", task.description()) - .put("log", task.log().isPresent() ? getLogPath(task).toString() : "") + .put( + "log", + task.log().isPresent() ? getLogPath(task).toString().replace(File.separator, "/") : "") .put( "reports", task.reports().entrySet().stream() @@ -161,7 +166,11 @@ final class CoverPageGenerator { entry -> entry.getValue().files().isEmpty() ? "" - : entry.getValue().entryPoint().toString()))) + : entry + .getValue() + .entryPoint() + .toString() + .replace(File.separator, "/")))) .build(); } @@ -188,8 +197,10 @@ final class CoverPageGenerator { } private static Path getLogPath(TaskData task) { - // TODO(guyben):escape uniqueName to guarantee legal file name. - return Paths.get("logs", task.uniqueName() + ".log"); + // We replace colons with dashes so that the resulting filename is always valid, even in + // Windows. As a dash is not a valid character in Java identifies, a task name cannot include + // it, so the uniqueness of the name is perserved. + return Paths.get("logs", task.uniqueName().replace(":", "-") + ".log"); } private static Supplier resourceLoader(Path path) { diff --git a/buildSrc/src/main/java/google/registry/gradle/plugin/GcsPluginUtils.java b/buildSrc/src/main/java/google/registry/gradle/plugin/GcsPluginUtils.java index afb47b9a5..91181514f 100644 --- a/buildSrc/src/main/java/google/registry/gradle/plugin/GcsPluginUtils.java +++ b/buildSrc/src/main/java/google/registry/gradle/plugin/GcsPluginUtils.java @@ -64,7 +64,8 @@ final class GcsPluginUtils { static void uploadFileToGcs( Storage storage, String bucket, Path path, Supplier dataSupplier) { - String filename = path.toString(); + // Replace Windows file separators with forward slashes. + String filename = path.toString().replace(File.separator, "/"); storage.create( BlobInfo.newBuilder(bucket, filename).setContentType(getContentType(filename)).build(), dataSupplier.get()); diff --git a/buildSrc/src/test/java/google/registry/gradle/plugin/CoverPageGeneratorTest.java b/buildSrc/src/test/java/google/registry/gradle/plugin/CoverPageGeneratorTest.java index 26c7f193d..30efe40ba 100644 --- a/buildSrc/src/test/java/google/registry/gradle/plugin/CoverPageGeneratorTest.java +++ b/buildSrc/src/test/java/google/registry/gradle/plugin/CoverPageGeneratorTest.java @@ -20,9 +20,11 @@ import static com.google.common.truth.Truth8.assertThat; import static google.registry.gradle.plugin.GcsPluginUtils.toByteArraySupplier; import static java.nio.charset.StandardCharsets.UTF_8; +import com.google.common.base.Joiner; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import google.registry.gradle.plugin.ProjectData.TaskData; +import java.io.File; import java.nio.file.Paths; import org.junit.Test; import org.junit.runner.RunWith; @@ -63,6 +65,8 @@ public final class CoverPageGeneratorTest { .setState(TaskData.State.UP_TO_DATE) .build(); + private static final Joiner filenameJoiner = Joiner.on(File.separator); + private ImmutableMap getGeneratedFiles(ProjectData project) { CoverPageGenerator coverPageGenerator = new CoverPageGenerator(project); FilesWithEntryPoint files = coverPageGenerator.getFilesToUpload(); @@ -172,8 +176,8 @@ public final class CoverPageGeneratorTest { @Test public void testGetFilesToUpload_containsCssFile() { ImmutableMap files = getGeneratedFiles(EMPTY_PROJECT); - assertThat(files).containsKey("css/style.css"); - assertThat(files.get("css/style.css")).contains("body {"); + assertThat(files).containsKey(filenameJoiner.join("css", "style.css")); + assertThat(files.get(filenameJoiner.join("css", "style.css"))).contains("body {"); assertThat(files.get("index.html")) .contains(""); } @@ -191,8 +195,8 @@ public final class CoverPageGeneratorTest { .setLog(toByteArraySupplier("my log data")) .build()) .build()); - assertThat(files).containsEntry("logs/my:name.log", "my log data"); - assertThat(files.get("index.html")).contains("[log]"); + assertThat(files).containsEntry(filenameJoiner.join("logs", "my-name.log"), "my log data"); + assertThat(files.get("index.html")).contains("[log]"); } @Test @@ -203,7 +207,7 @@ public final class CoverPageGeneratorTest { .toBuilder() .addTask(EMPTY_TASK_SUCCESS.toBuilder().setUniqueName("my:name").build()) .build()); - assertThat(files).doesNotContainKey("logs/my:name.log"); + assertThat(files).doesNotContainKey("logs/my-name.log"); assertThat(files.get("index.html")).contains("[log]"); } @@ -225,7 +229,7 @@ public final class CoverPageGeneratorTest { Paths.get("path", "report.txt"))) .build()) .build()); - assertThat(files).containsEntry("path/report.txt", "report content"); + assertThat(files).containsEntry(filenameJoiner.join("path", "report.txt"), "report content"); assertThat(files.get("index.html")).contains("[someReport]"); } @@ -244,7 +248,7 @@ public final class CoverPageGeneratorTest { ImmutableMap.of(), Paths.get("path", "report.txt"))) .build()) .build()); - assertThat(files).doesNotContainKey("path/report.txt"); + assertThat(files).doesNotContainKey(filenameJoiner.join("path", "report.txt")); assertThat(files.get("index.html")) .contains("[someReport]"); } @@ -275,12 +279,15 @@ public final class CoverPageGeneratorTest { ImmutableMap.of(), Paths.get("path-empty", "report.txt"))) .build()) .build()); - assertThat(files).containsEntry("path-filled/report.txt", "report content"); - assertThat(files).containsEntry("path-filled/other/file.txt", "some other content"); - assertThat(files).containsEntry("logs/my:name.log", "log data"); + assertThat(files) + .containsEntry(filenameJoiner.join("path-filled", "report.txt"), "report content"); + assertThat(files) + .containsEntry( + filenameJoiner.join("path-filled", "other", "file.txt"), "some other content"); + assertThat(files).containsEntry(filenameJoiner.join("logs", "my-name.log"), "log data"); assertThat(files.get("index.html")) .contains("[filledReport]"); - assertThat(files.get("index.html")).contains("[log]"); + assertThat(files.get("index.html")).contains("[log]"); assertThat(files.get("index.html")) .contains("[emptyReport]"); } diff --git a/buildSrc/src/test/java/google/registry/gradle/plugin/GcsPluginUtilsTest.java b/buildSrc/src/test/java/google/registry/gradle/plugin/GcsPluginUtilsTest.java index c087a1c18..070eafbad 100644 --- a/buildSrc/src/test/java/google/registry/gradle/plugin/GcsPluginUtilsTest.java +++ b/buildSrc/src/test/java/google/registry/gradle/plugin/GcsPluginUtilsTest.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import com.google.cloud.storage.BlobInfo; import com.google.cloud.storage.Storage; +import com.google.common.base.Joiner; import com.google.common.collect.ImmutableMap; import java.io.File; import java.nio.file.Files; @@ -45,6 +46,8 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class GcsPluginUtilsTest { + private static final Joiner filenameJoiner = Joiner.on(File.separator); + @Rule public final TemporaryFolder folder = new TemporaryFolder(); @Test @@ -155,8 +158,10 @@ public final class GcsPluginUtilsTest { FilesWithEntryPoint files = readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root); - assertThat(files.entryPoint().toString()).isEqualTo("some/path/file.txt"); - assertThat(readAllFiles(files)).containsExactly("some/path/file.txt", "some data"); + assertThat(files.entryPoint().toString()) + .isEqualTo(filenameJoiner.join("some", "path", "file.txt")); + assertThat(readAllFiles(files)) + .containsExactly(filenameJoiner.join("some", "path", "file.txt"), "some data"); } @Test @@ -171,7 +176,7 @@ public final class GcsPluginUtilsTest { FilesWithEntryPoint files = readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root); - assertThat(files.entryPoint().toString()).isEqualTo("non/existing.txt"); + assertThat(files.entryPoint().toString()).isEqualTo(filenameJoiner.join("non", "existing.txt")); assertThat(files.files()).isEmpty(); } @@ -187,7 +192,7 @@ public final class GcsPluginUtilsTest { FilesWithEntryPoint files = readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root); - assertThat(files.entryPoint().toString()).isEqualTo("some/path"); + assertThat(files.entryPoint().toString()).isEqualTo(filenameJoiner.join("some", "path")); assertThat(files.files()).isEmpty(); } @@ -205,8 +210,10 @@ public final class GcsPluginUtilsTest { FilesWithEntryPoint files = readFilesWithEntryPoint(destination, Optional.of(ignoredHint), root); - assertThat(files.entryPoint().toString()).isEqualTo("some/path/a/file.txt"); - assertThat(readAllFiles(files)).containsExactly("some/path/a/file.txt", "some data"); + assertThat(files.entryPoint().toString()) + .isEqualTo(filenameJoiner.join("some", "path", "a", "file.txt")); + assertThat(readAllFiles(files)) + .containsExactly(filenameJoiner.join("some", "path", "a", "file.txt"), "some data"); } /** @@ -232,8 +239,10 @@ public final class GcsPluginUtilsTest { FilesWithEntryPoint files = readFilesWithEntryPoint(destination, Optional.empty(), root); - assertThat(files.entryPoint().toString()).isEqualTo("some/path/path.zip"); - assertThat(readAllFiles(files).keySet()).containsExactly("some/path/path.zip"); + assertThat(files.entryPoint().toString()) + .isEqualTo(filenameJoiner.join("some", "path", "path.zip")); + assertThat(readAllFiles(files).keySet()) + .containsExactly(filenameJoiner.join("some", "path", "path.zip")); } /** @@ -261,8 +270,10 @@ public final class GcsPluginUtilsTest { FilesWithEntryPoint files = readFilesWithEntryPoint(destination, Optional.of(badEntryPoint), root); - assertThat(files.entryPoint().toString()).isEqualTo("some/path/path.zip"); - assertThat(readAllFiles(files).keySet()).containsExactly("some/path/path.zip"); + assertThat(files.entryPoint().toString()) + .isEqualTo(filenameJoiner.join("some", "path", "path.zip")); + assertThat(readAllFiles(files).keySet()) + .containsExactly(filenameJoiner.join("some", "path", "path.zip")); } @Test @@ -285,12 +296,13 @@ public final class GcsPluginUtilsTest { FilesWithEntryPoint files = readFilesWithEntryPoint(destination, Optional.of(goodEntryPoint), root); - assertThat(files.entryPoint().toString()).isEqualTo("some/path/index.html"); + assertThat(files.entryPoint().toString()) + .isEqualTo(filenameJoiner.join("some", "path", "index.html")); assertThat(readAllFiles(files)) .containsExactly( - "some/path/index.html", "some data", - "some/path/a/index.html", "wrong index", - "some/path/c/style.css", "css file", - "some/path/my_image.png", "images"); + filenameJoiner.join("some", "path", "index.html"), "some data", + filenameJoiner.join("some", "path", "a", "index.html"), "wrong index", + filenameJoiner.join("some", "path", "c", "style.css"), "css file", + filenameJoiner.join("some", "path", "my_image.png"), "images"); } } diff --git a/core/build.gradle b/core/build.gradle index 160907558..2a32ea237 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -76,9 +76,9 @@ sourceSets { main { java { srcDirs += generatedDir - // Javadoc API is deprecated and removed in Java 12. + // Javadoc API is deprecated in Java 11 and removed in Java 12. // TODO(jianglai): re-enable after migrating to the new Javadoc API - if ((JavaVersion.current().majorVersion as Integer) > 11) { + if ((JavaVersion.current().majorVersion as Integer) >= 11) { exclude 'google/registry/documentation/**' } } @@ -88,9 +88,9 @@ sourceSets { } test { java { - // Javadoc API is deprecated and removed in Java 12. + // Javadoc API is deprecated in Java 11 and removed in Java 12. // TODO(jianglai): re-enable after migrating to the new Javadoc API - if ((JavaVersion.current().majorVersion as Integer) > 11) { + if ((JavaVersion.current().majorVersion as Integer) >= 11) { exclude 'google/registry/documentation/**' } } @@ -290,12 +290,12 @@ dependencies { task jaxbToJava { def xsdFilesDir = "${javaDir}/google/registry/xml/xsd" def bindingsFile = "${javaDir}/google/registry/xjc/bindings.xjb" - def pkgInfoGenerator = "${javaDir}/google/registry/xjc/make_pkginfo.sh" def pkgInfoTemplate = "${javaDir}/google/registry/xjc/package-info.java.in" + def pkgInfoMap = "${javaDir}/google/registry/xjc/package-info.map" def outputDir = "${generatedDir}/google/registry/xjc" inputs.dir xsdFilesDir - inputs.files bindingsFile, pkgInfoTemplate, pkgInfoGenerator + inputs.files bindingsFile, pkgInfoTemplate, pkgInfoMap outputs.dir outputDir doLast { @@ -333,11 +333,17 @@ task jaxbToJava { // below. arg(line: '-npa -quiet -extension') } - exec { - workingDir "${generatedDir}" - - executable pkgInfoGenerator - args pkgInfoTemplate, outputDir + new File(pkgInfoMap).eachLine { line -> + def (packageName, namespace) = line.split() + ant.copy( + tofile: "${outputDir}/${packageName}/package-info.java", + overwrite: true, + file: "${pkgInfoTemplate}") { + filterSet() { + filter(token: 'PACKAGE', value: packageName) + filter(token: 'NAMESPACE', value: namespace) + } + } } } } @@ -413,8 +419,10 @@ task soyToJS { "--allowExternalCalls", "false", "--srcs", "${soyFiles.join(',')}", "--shouldProvideRequireSoyNamespaces", "true", - "--compileTimeGlobalsFile", "${resourcesSourceDir}/google/registry/ui/globals.txt", - "--deps", "${deps.join(',')}" + "--compileTimeGlobalsFile", "${resourcesSourceDir}/google/registry/ui/globals.txt" + if (deps != "") { + args "--deps", "${deps.join(',')}" + } } } @@ -526,7 +534,12 @@ task compileProdJS(type: JavaExec) { compileJava.dependsOn jaxbToJava compileJava.dependsOn soyToJava -compileJava.dependsOn compileProdJS +// The Closure JS compiler does not support Windows. It is fine to disable it if all we want to do +// is to complile the Java code on Windows. +if (!System.properties['os.name'].toLowerCase().contains('windows')) { + compileJava.dependsOn compileProdJS + assemble.dependsOn compileProdJS +} // stylesheetsToJavascript must happen after processResources, which wipes the // resources folder before copying data into it. @@ -537,7 +550,6 @@ compileProdJS.dependsOn rootProject.npmInstall compileProdJS.dependsOn processResources compileProdJS.dependsOn processTestResources compileProdJS.dependsOn soyToJS -assemble.dependsOn compileProdJS task karmaTest(type: Exec) { dependsOn ':npmInstall' diff --git a/core/src/main/java/google/registry/xjc/list_generated_files.sh b/core/src/main/java/google/registry/xjc/list_generated_files.sh deleted file mode 100755 index 454bcf5c8..000000000 --- a/core/src/main/java/google/registry/xjc/list_generated_files.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh -# Copyright 2017 The Nomulus Authors. All Rights Reserved. -# -# Licensed 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. - - -tmp="$(mktemp -d "${TMPDIR:-/tmp}/list_generated_files.XXXXXXXX")" -[[ "${tmp}" != "" ]] || exit 1 -trap "rm -rf ${tmp}" EXIT - -base="${PWD}" -export LC_ALL=C - -cd "${tmp}" -cp "${base}/java/google/registry/xjc/bindings.xjb" . -cp "${base}"/java/google/registry/xml/xsd/*.xsd . -"${base}/third_party/java/jaxb/jaxb-xjc" -extension -d "${tmp}" -b *.xjb *.xsd \ - | sed -ne s@google/registry/xjc/@@p \ - | grep -v package-info.java \ - | sort \ - > xjc_generated_files - -cat <&2; exit 1; } - -template="$1" -outdir="$2" - -create() { - package=$1 - namespace=$2 - sed -e "s,@PACKAGE@,${package},g" \ - -e "s,@NAMESPACE@,${namespace},g" \ - < "${template}" \ - > "${outdir}/${package}/package-info.java" -} - -create contact urn:ietf:params:xml:ns:contact-1.0 -create domain urn:ietf:params:xml:ns:domain-1.0 -create dsig http://www.w3.org/2000/09/xmldsig# -create epp urn:ietf:params:xml:ns:epp-1.0 -create eppcom urn:ietf:params:xml:ns:eppcom-1.0 -create fee06 urn:ietf:params:xml:ns:fee-0.6 -create fee11 urn:ietf:params:xml:ns:fee-0.11 -create fee12 urn:ietf:params:xml:ns:fee-0.12 -create host urn:ietf:params:xml:ns:host-1.0 -create iirdea urn:ietf:params:xml:ns:iirdea-1.0 -create launch urn:ietf:params:xml:ns:launch-1.0 -create mark urn:ietf:params:xml:ns:mark-1.0 -create rde urn:ietf:params:xml:ns:rde-1.0 -create rdecontact urn:ietf:params:xml:ns:rdeContact-1.0 -create rdedomain urn:ietf:params:xml:ns:rdeDomain-1.0 -create rdeeppparams urn:ietf:params:xml:ns:rdeEppParams-1.0 -create rdeheader urn:ietf:params:xml:ns:rdeHeader-1.0 -create rdehost urn:ietf:params:xml:ns:rdeHost-1.0 -create rdeidn urn:ietf:params:xml:ns:rdeIDN-1.0 -create rdenndn urn:ietf:params:xml:ns:rdeNNDN-1.0 -create rdenotification urn:ietf:params:xml:ns:rdeNotification-1.0 -create rdepolicy urn:ietf:params:xml:ns:rdePolicy-1.0 -create rderegistrar urn:ietf:params:xml:ns:rdeRegistrar-1.0 -create rdereport urn:ietf:params:xml:ns:rdeReport-1.0 -create rgp urn:ietf:params:xml:ns:rgp-1.0 -create secdns urn:ietf:params:xml:ns:secDNS-1.1 -create smd urn:ietf:params:xml:ns:signedMark-1.0 diff --git a/core/src/main/java/google/registry/xjc/package-info.java.in b/core/src/main/java/google/registry/xjc/package-info.java.in index 8a2fecc50..fa19ab0ad 100644 --- a/core/src/main/java/google/registry/xjc/package-info.java.in +++ b/core/src/main/java/google/registry/xjc/package-info.java.in @@ -1,4 +1,3 @@ -// See build.xml and make_pkginfo.sh which preprocess this into actual files. @XmlSchema( elementFormDefault = XmlNsForm.QUALIFIED, namespace = "@NAMESPACE@", diff --git a/core/src/main/java/google/registry/xjc/package-info.map b/core/src/main/java/google/registry/xjc/package-info.map new file mode 100644 index 000000000..55b700c04 --- /dev/null +++ b/core/src/main/java/google/registry/xjc/package-info.map @@ -0,0 +1,27 @@ +contact urn:ietf:params:xml:ns:contact-1.0 +domain urn:ietf:params:xml:ns:domain-1.0 +dsig http://www.w3.org/2000/09/xmldsig# +epp urn:ietf:params:xml:ns:epp-1.0 +eppcom urn:ietf:params:xml:ns:eppcom-1.0 +fee06 urn:ietf:params:xml:ns:fee-0.6 +fee11 urn:ietf:params:xml:ns:fee-0.11 +fee12 urn:ietf:params:xml:ns:fee-0.12 +host urn:ietf:params:xml:ns:host-1.0 +iirdea urn:ietf:params:xml:ns:iirdea-1.0 +launch urn:ietf:params:xml:ns:launch-1.0 +mark urn:ietf:params:xml:ns:mark-1.0 +rde urn:ietf:params:xml:ns:rde-1.0 +rdecontact urn:ietf:params:xml:ns:rdeContact-1.0 +rdedomain urn:ietf:params:xml:ns:rdeDomain-1.0 +rdeeppparams urn:ietf:params:xml:ns:rdeEppParams-1.0 +rdeheader urn:ietf:params:xml:ns:rdeHeader-1.0 +rdehost urn:ietf:params:xml:ns:rdeHost-1.0 +rdeidn urn:ietf:params:xml:ns:rdeIDN-1.0 +rdenndn urn:ietf:params:xml:ns:rdeNNDN-1.0 +rdenotification urn:ietf:params:xml:ns:rdeNotification-1.0 +rdepolicy urn:ietf:params:xml:ns:rdePolicy-1.0 +rderegistrar urn:ietf:params:xml:ns:rdeRegistrar-1.0 +rdereport urn:ietf:params:xml:ns:rdeReport-1.0 +rgp urn:ietf:params:xml:ns:rgp-1.0 +secdns urn:ietf:params:xml:ns:secDNS-1.1 +smd urn:ietf:params:xml:ns:signedMark-1.0 \ No newline at end of file