blob: 1d2cc1cd2ea392b056effa30d586961fcb46a838 [file] [log] [blame]
/*
* Copyright 2013-present Facebook, Inc.
*
* 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.facebook.buck.dalvik;
import com.facebook.buck.java.classes.FileLike;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* Helper to write to secondary DEX files.
*/
abstract class SecondaryDexHelper<ZIP_OUTPUT_STREAM_HELPER extends ZipOutputStreamHelper> {
private final File outSecondaryDir;
private final String secondaryPattern;
private final ZipSplitter.CanaryStrategy canaryStrategy;
private int currentSecondaryIndex;
private ZIP_OUTPUT_STREAM_HELPER currentSecondaryOut;
private boolean newSecondaryOutOnNextEntry;
private ImmutableList.Builder<File> secondaryFiles;
SecondaryDexHelper(
File outSecondaryDir,
String secondaryPattern,
ZipSplitter.CanaryStrategy canaryStrategy) {
this.outSecondaryDir = Preconditions.checkNotNull(outSecondaryDir);
this.secondaryPattern = Preconditions.checkNotNull(secondaryPattern);
this.canaryStrategy = Preconditions.checkNotNull(canaryStrategy);
this.secondaryFiles = ImmutableList.builder();
}
void reset() {
currentSecondaryIndex = 0;
currentSecondaryOut = null;
secondaryFiles = ImmutableList.builder();
}
ZIP_OUTPUT_STREAM_HELPER getCurrentOutput() {
return currentSecondaryOut;
}
void finishCurrentZipFile() {
newSecondaryOutOnNextEntry = true;
}
ZIP_OUTPUT_STREAM_HELPER getOutputToWriteTo(FileLike entry) throws IOException {
// Going to write this entry to a secondary zip.
if (currentSecondaryOut == null ||
!currentSecondaryOut.canPutEntry(entry) ||
newSecondaryOutOnNextEntry) {
if (currentSecondaryOut != null) {
currentSecondaryOut.close();
}
currentSecondaryIndex++;
File newSecondaryFile = new File(
outSecondaryDir,
String.format(secondaryPattern, currentSecondaryIndex));
secondaryFiles.add(newSecondaryFile);
currentSecondaryOut = newZipOutput(newSecondaryFile);
newSecondaryOutOnNextEntry = false;
if (canaryStrategy == ZipSplitter.CanaryStrategy.INCLUDE_CANARIES) {
// Make sure the first class in the new secondary dex can be safely loaded.
FileLike canaryFile = CanaryFactory.create(currentSecondaryIndex);
currentSecondaryOut.putEntry(canaryFile);
}
// We've already tested for this. It really shouldn't happen.
Preconditions.checkState(currentSecondaryOut.canPutEntry(entry));
}
return currentSecondaryOut;
}
void close() throws IOException {
if (currentSecondaryOut != null) {
currentSecondaryOut.close();
}
}
List<File> getFiles() {
return secondaryFiles.build();
}
protected abstract ZIP_OUTPUT_STREAM_HELPER newZipOutput(File file) throws IOException;
}