Skip to content

Commit

Permalink
Add command for extracting SDK api descriptors from archived sandboxe…
Browse files Browse the repository at this point in the history
…d SDKs.

This will later be used to generate sources targeting the archived SDK.

PiperOrigin-RevId: 565610907
Change-Id: I9738212b4558b07b7557d793ce3ae073eb30f67c
  • Loading branch information
lucasvtenorio authored and copybara-github committed Sep 15, 2023
1 parent 4e85104 commit 174706d
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.google.devtools.build.android.sandboxedsdktoolbox;

import com.google.devtools.build.android.sandboxedsdktoolbox.apidescriptors.ExtractApiDescriptorsCommand;
import com.google.devtools.build.android.sandboxedsdktoolbox.apidescriptors.ExtractApiDescriptorsFromAsarCommand;
import com.google.devtools.build.android.sandboxedsdktoolbox.clientsources.GenerateClientSourcesCommand;
import com.google.devtools.build.android.sandboxedsdktoolbox.sdkdependenciesmanifest.GenerateSdkDependenciesManifestCommand;
import picocli.CommandLine;
Expand All @@ -26,6 +27,7 @@
name = "sandboxed-sdk-toolbox",
subcommands = {
ExtractApiDescriptorsCommand.class,
ExtractApiDescriptorsFromAsarCommand.class,
GenerateSdkDependenciesManifestCommand.class,
GenerateClientSourcesCommand.class,
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2023 The Bazel 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.
*/
package com.google.devtools.build.android.sandboxedsdktoolbox.apidescriptors;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

/** Command for extracting API descriptors from a sandboxed SDK Archive. */
@Command(
name = "extract-api-descriptors-from-asar",
description = "Extract API descriptors from a sandboxed SDK Archive.")
public final class ExtractApiDescriptorsFromAsarCommand implements Runnable {

private static final String API_DESCRIPTOR_ZIP_ENTRY_PATH = "sdk-interface-descriptors.jar";

@Option(names = "--asar", required = true)
Path asarPath;

@Option(names = "--output-sdk-api-descriptors", required = true)
Path outputSdkApiDescriptorsPath;

@Override
public void run() {
URI uri = URI.create("jar:" + asarPath.toUri());
try (FileSystem zipfs = FileSystems.newFileSystem(uri, new HashMap<String, String>())) {
Path descriptorsInZip = zipfs.getPath(API_DESCRIPTOR_ZIP_ENTRY_PATH);
if (!Files.exists(descriptorsInZip)) {
throw new IllegalStateException(
String.format("Could not find %s in %s", API_DESCRIPTOR_ZIP_ENTRY_PATH, asarPath));
}
Files.copy(descriptorsInZip, outputSdkApiDescriptorsPath);
} catch (IOException e) {
throw new UncheckedIOException("Failed to extract SDK API descriptors.", e);
}
}

private ExtractApiDescriptorsFromAsarCommand() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2023 The Bazel 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.
*/
package com.google.devtools.build.android.sandboxedsdktoolbox.apidescriptors;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.android.sandboxedsdktoolbox.utils.Runner.runCommand;
import static com.google.devtools.build.android.sandboxedsdktoolbox.utils.Zip.createZipWithSingleEntry;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.devtools.build.android.sandboxedsdktoolbox.utils.CommandResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public final class ExtractApiDescriptorsFromAsarCommandTest {

@Rule public final TemporaryFolder testFolder = new TemporaryFolder();

@Test
public void extractApiDescriptors_fromValidAsar() throws Exception {
Path asar = Paths.get(testFolder.getRoot().getAbsolutePath(), "test.asar");
byte[] sdkApiDescriptorContents = "fake descriptor contents".getBytes(UTF_8);
Path outputDescriptors = Paths.get(testFolder.getRoot().getAbsolutePath(), "descriptors.jar");
createZipWithSingleEntry(asar, "sdk-interface-descriptors.jar", sdkApiDescriptorContents);

CommandResult result =
runCommand(
"extract-api-descriptors-from-asar",
"--asar",
asar.toString(),
"--output-sdk-api-descriptors",
outputDescriptors.toString());

assertThat(result.getStatusCode()).isEqualTo(0);
assertThat(result.getOutput()).isEmpty();
assertThat(Files.readAllBytes(outputDescriptors)).isEqualTo(sdkApiDescriptorContents);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2023 The Bazel 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.
*/
package com.google.devtools.build.android.sandboxedsdktoolbox.utils;

import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

/** Test utilities for zip files. */
public final class Zip {

/**
* Creates a zip file with a single entry inside of it.
*
* @param zipPath Path to the new zip file. If the file already exists {@link IOException} will be
* thrown.
*/
public static void createZipWithSingleEntry(Path zipPath, String entryName, byte[] entryContents)
throws IOException {
Map<String, String> env = new HashMap<>();
env.put("create", "true");

URI uri = URI.create("jar:" + zipPath.toUri());
try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
Files.write(zipfs.getPath(entryName), entryContents);
}
}

private Zip() {}
}

0 comments on commit 174706d

Please sign in to comment.