use of com.android.tools.build.bundletool.model.ZipPath in project bundletool by google.
the class SdkBundleSerializer method writeToDisk.
/**
* Writes the SDK Bundle on disk at the given location.
*/
public void writeToDisk(SdkBundle bundle, Path pathOnDisk) throws IOException {
ZipBuilder zipBuilder = new ZipBuilder();
zipBuilder.addFileWithProtoContent(ZipPath.create(BUNDLE_CONFIG_FILE_NAME), bundle.getBundleConfig());
// BUNDLE-METADATA
for (Entry<ZipPath, ByteSource> metadataEntry : bundle.getBundleMetadata().getFileContentMap().entrySet()) {
zipBuilder.addFile(METADATA_DIRECTORY.resolve(metadataEntry.getKey()), metadataEntry.getValue());
}
// Base module (the only module in an ASB)
BundleModule module = bundle.getModule();
ZipPath moduleDir = ZipPath.create(module.getName().toString());
for (ModuleEntry entry : module.getEntries()) {
ZipPath entryPath = moduleDir.resolve(entry.getPath());
zipBuilder.addFile(entryPath, entry.getContent());
}
// Special module files are not represented as module entries (above).
zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.ANDROID_MANIFEST.getPath()), module.getAndroidManifest().getManifestRoot().getProto());
module.getAssetsConfig().ifPresent(assetsConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.ASSETS_TABLE.getPath()), assetsConfig));
module.getNativeConfig().ifPresent(nativeConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.NATIVE_LIBS_TABLE.getPath()), nativeConfig));
module.getResourceTable().ifPresent(resourceTable -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.RESOURCE_TABLE.getPath()), resourceTable));
zipBuilder.writeTo(pathOnDisk);
}
use of com.android.tools.build.bundletool.model.ZipPath in project bundletool by google.
the class ZipBuilder method writeTo.
/**
* Writes the data into a zip file.
*
* <p>It is an error if the <code>target</code> file already exists.
*
* @return The path the .zip file was written to (ie. <code>target</code>).
* @throws IOException When an I/O error occurs.
*/
public synchronized Path writeTo(Path target) throws IOException {
// Create temp file and move to requested location when completely written. If the command
// fails, this prevents us from generating partial output at the user-specified location.
Path tempFile = Files.createTempFile("ZipBuilder-", ".zip.tmp");
try {
try (OutputStream out = BufferedIo.outputStream(tempFile);
ZipOutputStream outZip = new ZipOutputStream(out)) {
for (ZipPath path : entries.keySet()) {
Entry entry = entries.get(path);
if (entry.getIsDirectory()) {
// For directories, we append "/" at the end of the file path since that's what the
// ZipEntry class relies on.
ZipEntry zipEntry = new ZipEntry(path + "/");
zipEntry.setTime(EPOCH);
outZip.putNextEntry(zipEntry);
// Directories are represented as having empty content in a zip file, so we don't write
// any bytes to the outZip for this entry.
} else {
ZipEntry zipEntry = new ZipEntry(path.toString());
zipEntry.setTime(EPOCH);
if (entry.hasOption(EntryOption.UNCOMPRESSED)) {
zipEntry.setMethod(ZipEntry.STORED);
// ZipFile API requires us to set the following properties manually for uncompressed
// ZipEntries, just setting the compression method is not enough.
ByteSource originalData = entry.getContent().get();
// If entry is small enough it would be better to preload it into memory to not
// read it twice. Two reads are required because we need to know crc32 before we put
// entry content into zip.
ByteSource entryData = originalData.size() < PRELOAD_INTO_MEMORY_THRESHOLD ? preloadEntryData(originalData) : originalData;
zipEntry.setSize(entryData.size());
zipEntry.setCompressedSize(entryData.size());
zipEntry.setCrc(entryData.hash(Hashing.crc32()).padToLong());
outZip.putNextEntry(zipEntry);
entry.getContent().get().copyTo(outZip);
} else {
outZip.putNextEntry(zipEntry);
entry.getContent().get().copyTo(outZip);
}
}
outZip.closeEntry();
}
}
// Fails if the target file exists.
Files.move(tempFile, target);
} finally {
Files.deleteIfExists(tempFile);
}
return target;
}
use of com.android.tools.build.bundletool.model.ZipPath in project bundletool by google.
the class ZipFlingerApkSerializer method writeProtoApk.
/**
* Writes an APK for aapt2 to convert to binary.
*
* <p>This APK contains only files that aapt2 will convert from proto to binary, and the files
* needed for the conversion to succeed (e.g. all resources referenced in the resource table).
*
* <p>All files are left uncompressed to save aapt2 from re-compressing all the entries it
* generated since we prefer having control over which compression is used. This is effectively a
* tradeoff between local storage and CPU.
*
* <p>No entry is 4-byte aligned since it's only a temporary APK for aapt2 conversion which won't
* be actually stored or served to any device.
*/
private void writeProtoApk(ModuleSplit split, Path protoApkPath, TempDirectory tempDir) throws IOException {
try (ZipArchive apkWriter = new ZipArchive(protoApkPath)) {
apkWriter.add(new BytesSource(split.getAndroidManifest().getManifestRoot().getProto().toByteArray(), MANIFEST_FILENAME, NO_COMPRESSION.getValue()));
if (split.getResourceTable().isPresent()) {
BytesSource bytesSource = new BytesSource(split.getResourceTable().get().toByteArray(), SpecialModuleEntry.RESOURCE_TABLE.getPath().toString(), NO_COMPRESSION.getValue());
bytesSource.align(4);
apkWriter.add(bytesSource);
}
Map<String, Entry> bundleEntriesByName = bundleZipReader.getEntries();
ZipEntrySourceFactory sourceFactory = new ZipEntrySourceFactory(bundleZipReader, tempDir);
for (ModuleEntry moduleEntry : split.getEntries()) {
ZipPath pathInApk = ApkSerializerHelper.toApkEntryPath(moduleEntry.getPath());
if (!requiresAapt2Conversion(pathInApk)) {
continue;
}
if (moduleEntry.getBundleLocation().isPresent()) {
ZipPath pathInBundle = moduleEntry.getBundleLocation().get().entryPathInBundle();
Entry entry = bundleEntriesByName.get(pathInBundle.toString());
checkNotNull(entry, "Could not find entry '%s'.", pathInBundle);
apkWriter.add(sourceFactory.create(entry, pathInApk, NO_COMPRESSION));
} else {
apkWriter.add(new BytesSource(moduleEntry.getContent().read(), pathInApk.toString(), NO_COMPRESSION.getValue()));
}
}
}
}
use of com.android.tools.build.bundletool.model.ZipPath in project bundletool by google.
the class ApkSigner method signEmbeddedApks.
/**
* Returns a new {@link ModuleSplit} with the same entries as the one given as parameter but with
* embedded APKs signed.
*/
@CheckReturnValue
public ModuleSplit signEmbeddedApks(ModuleSplit split) {
ImmutableSet<ZipPath> wear1ApkPaths = ImmutableSet.copyOf(WearApkLocator.findEmbeddedWearApkPaths(split));
ImmutableList.Builder<ModuleEntry> newEntries = ImmutableList.builder();
for (ModuleEntry entry : split.getEntries()) {
ZipPath pathInApk = ApkSerializerHelper.toApkEntryPath(entry.getPath());
if (entry.getShouldSign() || wear1ApkPaths.contains(pathInApk)) {
newEntries.add(signModuleEntry(split, entry));
} else {
newEntries.add(entry);
}
}
return split.toBuilder().setEntries(newEntries.build()).build();
}
use of com.android.tools.build.bundletool.model.ZipPath in project bundletool by google.
the class AppBundleSerializer method writeToDisk.
/**
* Writes the App Bundle on disk at the given location.
*/
public void writeToDisk(AppBundle bundle, Path pathOnDisk) throws IOException {
ZipBuilder zipBuilder = new ZipBuilder();
EntryOption[] compression = allEntriesUncompressed ? new EntryOption[] { EntryOption.UNCOMPRESSED } : new EntryOption[0];
zipBuilder.addFileWithProtoContent(ZipPath.create(BUNDLE_CONFIG_FILE_NAME), bundle.getBundleConfig(), compression);
// APEX bundles do not have metadata files.
if (bundle.getFeatureModules().isEmpty() || !bundle.isApex()) {
for (Entry<ZipPath, ByteSource> metadataEntry : bundle.getBundleMetadata().getFileContentMap().entrySet()) {
zipBuilder.addFile(METADATA_DIRECTORY.resolve(metadataEntry.getKey()), metadataEntry.getValue(), compression);
}
}
for (BundleModule module : bundle.getModules().values()) {
ZipPath moduleDir = ZipPath.create(module.getName().toString());
for (ModuleEntry entry : module.getEntries()) {
ZipPath entryPath = moduleDir.resolve(entry.getPath());
zipBuilder.addFile(entryPath, entry.getContent(), compression);
}
// Special module files are not represented as module entries (above).
zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.ANDROID_MANIFEST.getPath()), module.getAndroidManifest().getManifestRoot().getProto(), compression);
module.getAssetsConfig().ifPresent(assetsConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.ASSETS_TABLE.getPath()), assetsConfig, compression));
module.getNativeConfig().ifPresent(nativeConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.NATIVE_LIBS_TABLE.getPath()), nativeConfig, compression));
module.getResourceTable().ifPresent(resourceTable -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.RESOURCE_TABLE.getPath()), resourceTable, compression));
module.getApexConfig().ifPresent(apexConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.APEX_TABLE.getPath()), apexConfig, compression));
module.getRuntimeEnabledSdkConfig().ifPresent(runtimeEnabledSdkConfig -> zipBuilder.addFileWithProtoContent(moduleDir.resolve(SpecialModuleEntry.RUNTIME_ENABLED_SDK_CONFIG.getPath()), runtimeEnabledSdkConfig, compression));
}
zipBuilder.writeTo(pathOnDisk);
}
Aggregations