blob: 8341921b761c0ece89df87525b122ba30a36ead5 [file] [log] [blame]
// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
import static com.android.tools.r8.utils.FileUtils.isArchive;
import static com.android.tools.r8.utils.FileUtils.isClassFile;
import static com.android.tools.r8.utils.FileUtils.isDexFile;
import com.android.tools.r8.Resource;
import com.android.tools.r8.errors.CompilationError;
import com.google.common.io.ByteStreams;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipInputStream;
class ProgramFileArchiveReader {
private final Path archive;
private boolean ignoreDexInArchive;
private List<Resource> dexResources = null;
private List<Resource> classResources = null;
ProgramFileArchiveReader(Path archive, boolean ignoreDexInArchive) {
this.archive = archive;
this.ignoreDexInArchive = ignoreDexInArchive;
}
private void readArchive() throws IOException {
assert isArchive(archive);
dexResources = new ArrayList<>();
classResources = new ArrayList<>();
try (ZipInputStream stream = new ZipInputStream(new FileInputStream(archive.toFile()))) {
ZipEntry entry;
while ((entry = stream.getNextEntry()) != null) {
Path name = Paths.get(entry.getName());
if (isDexFile(name)) {
if (!ignoreDexInArchive) {
Resource resource =
new OneShotByteResource(Resource.Kind.DEX, ByteStreams.toByteArray(stream), null);
dexResources.add(resource);
}
} else if (isClassFile(name)) {
String descriptor = PreloadedClassFileProvider.guessTypeDescriptor(name);
Resource resource = new OneShotByteResource(Resource.Kind.CLASSFILE,
ByteStreams.toByteArray(stream), Collections.singleton(descriptor));
classResources.add(resource);
}
}
} catch (ZipException e) {
throw new CompilationError(
"Zip error while reading '" + archive + "': " + e.getMessage(), e);
}
if (!dexResources.isEmpty() && !classResources.isEmpty()) {
throw new CompilationError(
"Cannot create android app from an archive '" + archive
+ "' containing both DEX and Java-bytecode content");
}
}
public Collection<Resource> getDexProgramResources() throws IOException {
if (dexResources == null) {
readArchive();
}
List<Resource> result = dexResources;
dexResources = null;
return result;
}
public Collection<Resource> getClassProgramResources() throws IOException {
if (classResources == null) {
readArchive();
}
List<Resource> result = classResources;
classResources = null;
return result;
}
}