diff options
author | 2018-01-08 15:15:58 -0800 | |
---|---|---|
committer | 2018-01-08 15:18:06 -0800 | |
commit | 233807ec94189c4a322c203322163a154d90aa8f (patch) | |
tree | 3acadefc34a94f4395d52f79bdcb94a568db281c /src/tools/android/java/com/google/devtools/build/android/aapt2 | |
parent | 5a7d2575d3527a35b8ac541ae09591b6a040f67b (diff) |
Serialize and package xml attributes from resources xml tags in values folders for aapt2.
RELNOTES: none
PiperOrigin-RevId: 181226483
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/aapt2')
-rw-r--r-- | src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java | 97 |
1 files changed, 90 insertions, 7 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java b/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java index e51192ce1e..50c5ff5b13 100644 --- a/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java +++ b/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java @@ -14,6 +14,7 @@ package com.google.devtools.build.android.aapt2; +import com.android.SdkConstants; import com.android.builder.core.VariantType; import com.android.repository.Revision; import com.google.common.base.Preconditions; @@ -22,6 +23,15 @@ import com.google.common.collect.ImmutableList.Builder; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.devtools.build.android.AaptCommandBuilder; +import com.google.devtools.build.android.AndroidDataSerializer; +import com.google.devtools.build.android.DataResourceXml; +import com.google.devtools.build.android.FullyQualifiedName; +import com.google.devtools.build.android.FullyQualifiedName.Factory; +import com.google.devtools.build.android.FullyQualifiedName.VirtualType; +import com.google.devtools.build.android.XmlResourceValues; +import com.google.devtools.build.android.xml.Namespaces; +import com.google.devtools.build.android.xml.ResourcesAttribute; +import java.io.FileInputStream; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -29,11 +39,17 @@ import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.logging.Logger; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; /** Invokes aapt2 to compile resources. */ public class ResourceCompiler { @@ -58,7 +74,7 @@ public class ResourceCompiler { private final CompilingVisitor compilingVisitor; - private static class CompileTask implements Callable<Path> { + private static class CompileTask implements Callable<List<Path>> { private final Path file; private final Path compiledResourcesOut; @@ -66,7 +82,10 @@ public class ResourceCompiler { private final Revision buildToolsVersion; private CompileTask( - Path file, Path compiledResourcesOut, Path aapt2, Revision buildToolsVersion) { + Path file, + Path compiledResourcesOut, + Path aapt2, + Revision buildToolsVersion) { this.file = file; this.compiledResourcesOut = compiledResourcesOut; this.aapt2 = aapt2; @@ -74,7 +93,7 @@ public class ResourceCompiler { } @Override - public Path call() throws Exception { + public List<Path> call() throws Exception { logger.fine( new AaptCommandBuilder(aapt2) .forBuildToolsVersion(buildToolsVersion) @@ -88,10 +107,34 @@ public class ResourceCompiler { String type = file.getParent().getFileName().toString(); String filename = file.getFileName().toString(); + + List<Path> results = new ArrayList<>(); if (type.startsWith("values")) { filename = (filename.indexOf('.') != -1 ? filename.substring(0, filename.indexOf('.')) : filename) + ".arsc"; + + XMLEventReader xmlEventReader = null; + try { + // aapt2 compile strips out namespaces and attributes from the resources tag. + // Read them here separately and package them with the other flat files. + xmlEventReader = + XMLInputFactory.newInstance() + .createXMLEventReader(new FileInputStream(file.toString())); + + StartElement rootElement = xmlEventReader.nextTag().asStartElement(); + Iterator<Attribute> attributeIterator = + XmlResourceValues.iterateAttributesFrom(rootElement); + + if (attributeIterator.hasNext()) { + results.add( + createAttributesProto(type, filename, attributeIterator)); + } + } finally { + if (xmlEventReader != null) { + xmlEventReader.close(); + } + } } final Path compiledResourcePath = @@ -100,7 +143,47 @@ public class ResourceCompiler { Files.exists(compiledResourcePath), "%s does not exists after aapt2 ran.", compiledResourcePath); - return compiledResourcePath; + results.add(compiledResourcePath); + return results; + } + + private Path createAttributesProto( + String type, + String filename, + Iterator<Attribute> attributeIterator) + throws IOException { + + AndroidDataSerializer serializer = AndroidDataSerializer.create(); + final Path resourcesAttributesPath = + compiledResourcesOut.resolve(type + "_" + filename + ".attributes"); + + while (attributeIterator.hasNext()) { + Attribute attribute = attributeIterator.next(); + String namespaceUri = attribute.getName().getNamespaceURI(); + String localPart = attribute.getName().getLocalPart(); + String prefix = attribute.getName().getPrefix(); + QName qName = new QName(namespaceUri, localPart, prefix); + + Namespaces namespaces = Namespaces.from(qName); + String attributeName = + namespaceUri.isEmpty() + ? localPart + : prefix + ":" + localPart; + + final String[] dirNameAndQualifiers = type.split(SdkConstants.RES_QUALIFIER_SEP); + Factory fqnFactory = Factory.fromDirectoryName(dirNameAndQualifiers); + FullyQualifiedName fqn = + fqnFactory.create(VirtualType.RESOURCES_ATTRIBUTE, qName.toString()); + ResourcesAttribute resourceAttribute = + ResourcesAttribute.of(fqn, attributeName, attribute.getValue()); + DataResourceXml resource = + DataResourceXml.createWithNamespaces(file, resourceAttribute, namespaces); + + serializer.queueForSerialization(fqn, resource); + } + + serializer.flushTo(resourcesAttributesPath); + return resourcesAttributesPath; } @Override @@ -113,7 +196,7 @@ public class ResourceCompiler { private final ListeningExecutorService executorService; private final Path compiledResources; - private final List<ListenableFuture<Path>> tasks = new ArrayList<>(); + private final List<ListenableFuture<List<Path>>> tasks = new ArrayList<>(); private final Path aapt2; private final Revision buildToolsVersion; @@ -152,9 +235,9 @@ public class ResourceCompiler { List<Path> getCompiledArtifacts() throws InterruptedException, ExecutionException { Builder<Path> builder = ImmutableList.builder(); List<Throwable> compilationErrors = new ArrayList<>(); - for (ListenableFuture<Path> task : tasks) { + for (ListenableFuture<List<Path>> task : tasks) { try { - builder.add(task.get()); + builder.addAll(task.get()); } catch (InterruptedException | ExecutionException e) { compilationErrors.add(Optional.ofNullable(e.getCause()).orElse(e)); } |