diff options
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java')
-rw-r--r-- | src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java | 76 |
1 files changed, 66 insertions, 10 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java b/src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java index b4ba3761fe..711a8bb098 100644 --- a/src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java +++ b/src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java @@ -15,7 +15,9 @@ package com.google.devtools.build.android; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Predicates.not; +import static com.google.common.collect.ImmutableSetMultimap.toImmutableSetMultimap; import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; import android.aapt.pb.internal.ResourcesInternal.CompiledFile; import com.android.SdkConstants; @@ -78,6 +80,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.io.LittleEndianDataInputStream; import com.google.devtools.build.android.FullyQualifiedName.Factory; +import com.google.devtools.build.android.aapt2.CompiledResources; import com.google.devtools.build.android.proto.SerializeFormat; import com.google.devtools.build.android.proto.SerializeFormat.Header; import com.google.devtools.build.android.xml.ResourcesAttribute.AttributeType; @@ -88,9 +91,11 @@ import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.file.FileSystem; +import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -99,9 +104,12 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; import java.util.logging.Logger; +import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.annotation.concurrent.NotThreadSafe; @@ -574,11 +582,14 @@ public class AndroidCompiledDataDeserializer implements AndroidDataDeserializer } private void readAttributesFile( - InputStream resourceFileStream, FileSystem fileSystem, KeyValueConsumers consumers) + InputStream resourceFileStream, + FileSystem fileSystem, + BiConsumer<DataKey, DataResource> combine, + BiConsumer<DataKey, DataResource> overwrite) throws IOException { Header header = Header.parseDelimitedFrom(resourceFileStream); - List<DataKey> fullyQualifiedNames = new ArrayList<>(); + List<FullyQualifiedName> fullyQualifiedNames = new ArrayList<>(); for (int i = 0; i < header.getEntryCount(); i++) { SerializeFormat.DataKey protoKey = SerializeFormat.DataKey.parseDelimitedFrom(resourceFileStream); @@ -587,7 +598,7 @@ public class AndroidCompiledDataDeserializer implements AndroidDataDeserializer DataSourceTable sourceTable = DataSourceTable.read(resourceFileStream, fileSystem, header); - for (DataKey fullyQualifiedName : fullyQualifiedNames) { + for (FullyQualifiedName fullyQualifiedName : fullyQualifiedNames) { SerializeFormat.DataValue protoValue = SerializeFormat.DataValue.parseDelimitedFrom(resourceFileStream); DataSource source = sourceTable.sourceFromId(protoValue.getSourceId()); @@ -595,13 +606,54 @@ public class AndroidCompiledDataDeserializer implements AndroidDataDeserializer AttributeType attributeType = AttributeType.valueOf(protoValue.getXmlValue().getValueType()); if (attributeType.isCombining()) { - consumers.combiningConsumer.accept(fullyQualifiedName, dataResourceXml); + combine.accept(fullyQualifiedName, dataResourceXml); } else { - consumers.overwritingConsumer.accept(fullyQualifiedName, dataResourceXml); + overwrite.accept(fullyQualifiedName, dataResourceXml); } } } + public Map<DataKey, DataResource> readAttributes(CompiledResources resources) { + try (ZipFile zipFile = new ZipFile(resources.getZip().toFile())) { + return zipFile + .stream() + .filter(e -> e.getName().endsWith(".attributes")) + .flatMap( + entry -> { + try { + final Stream.Builder<Entry<DataKey, DataResource>> builder = Stream.builder(); + final BiConsumer<DataKey, DataResource> consumeToStream = + (k, v) -> builder.add(new SimpleImmutableEntry<>(k, v)); + readAttributesFile( + zipFile.getInputStream(entry), + FileSystems.getDefault(), + consumeToStream, + consumeToStream); + return builder.build(); + } catch (IOException e) { + throw new DeserializationException(e); + } + }) + .collect(toImmutableSetMultimap(Entry::getKey, Entry::getValue)) + .asMap() + .entrySet() + .stream() + .collect( + toMap( + Entry::getKey, + e -> + e.getValue() + .stream() + .reduce( + ((FullyQualifiedName) e.getKey()).isOverwritable() + ? DataResource::overwrite + : DataResource::combineWith) + .orElseThrow(IllegalStateException::new))); + } catch (IOException e) { + throw new DeserializationException(e); + } + } + public void readTable(InputStream in, KeyValueConsumers consumers) throws IOException { final ResourceTable resourceTable = ResourceTable.parseFrom(in); readPackages(consumers, resourceTable); @@ -640,7 +692,11 @@ public class AndroidCompiledDataDeserializer implements AndroidDataDeserializer Factory fqnFactory = Factory.fromDirectoryName(dirNameAndQualifiers); if (fileZipPath.endsWith(".attributes")) { - readAttributesFile(resourceFileStream, inPath.getFileSystem(), consumers); + readAttributesFile( + resourceFileStream, + inPath.getFileSystem(), + consumers.combiningConsumer, + consumers.overwritingConsumer); } else { LittleEndianDataInputStream dataInputStream = new LittleEndianDataInputStream(resourceFileStream); @@ -699,14 +755,14 @@ public class AndroidCompiledDataDeserializer implements AndroidDataDeserializer ((characterCount & 0x7F) << 8) | (byteBuffer.get(stringOffset + 1) & 0xFF); } - stringOffset += (characterCount >= (0x80) ? 2 : 1); + stringOffset += (characterCount >= 0x80 ? 2 : 1); int length = byteBuffer.get(stringOffset) & 0xFF; if ((length & 0x80) != 0) { length = ((length & 0x7F) << 8) | (byteBuffer.get(stringOffset + 1) & 0xFF); } - stringOffset += (length >= (0x80) ? 2 : 1); + stringOffset += (length >= 0x80 ? 2 : 1); strings.add(new String(bytes, stringOffset, length, "UTF8")); } else { @@ -716,14 +772,14 @@ public class AndroidCompiledDataDeserializer implements AndroidDataDeserializer ((characterCount & 0x7FFF) << 16) | (byteBuffer.get(stringOffset + 2) & 0xFFFF); } - stringOffset += 2 * (characterCount >= (0x8000) ? 2 : 1); + stringOffset += 2 * (characterCount >= 0x8000 ? 2 : 1); int length = byteBuffer.get(stringOffset) & 0xFFFF; if ((length & 0x8000) != 0) { length = ((length & 0x7FFF) << 16) | (byteBuffer.get(stringOffset + 2) & 0xFFFF); } - stringOffset += 2 * (length >= (0x8000) ? 2 : 1); + stringOffset += 2 * (length >= 0x8000 ? 2 : 1); strings.add(new String(bytes, stringOffset, length, "UTF16")); } |