diff options
author | 2016-06-02 18:20:24 +0000 | |
---|---|---|
committer | 2016-06-03 12:53:37 +0000 | |
commit | 1bfa4017954f723e31c10c21b7510dae2ac3c8e6 (patch) | |
tree | 747ab0adbd3bca1ac778593d150e8db8a20bd1e8 /src/tools/android/java/com/google/devtools/build/android/ziputils | |
parent | d9f3e89326b4f6e3d19968fa5034b02b0568fc6c (diff) |
Add support for an "inclusion filter" to DexMapper tool
--
MOS_MIGRATED_REVID=123887669
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/ziputils')
4 files changed, 88 insertions, 11 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/ziputils/BUILD b/src/tools/android/java/com/google/devtools/build/android/ziputils/BUILD index cc578b7397..4f88bf774e 100644 --- a/src/tools/android/java/com/google/devtools/build/android/ziputils/BUILD +++ b/src/tools/android/java/com/google/devtools/build/android/ziputils/BUILD @@ -25,6 +25,7 @@ java_library( "DexMapper.java", "DexReducer.java", "SplitZip.java", + "SplitZipFilters.java", "Splitter.java", ], ), @@ -37,12 +38,11 @@ java_library( java_library( name = "splitter_lib", - srcs = glob( - [ - "SplitZip.java", - "Splitter.java", - ], - ), + srcs = [ + "SplitZip.java", + "SplitZipFilters.java", + "Splitter.java", + ], visibility = ["//visibility:public"], deps = [ ":ziputils_lib", @@ -61,6 +61,7 @@ java_binary( deps = [ ":splitter_lib", "//src/main/java/com/google/devtools/common/options", + "//third_party:guava", ], ) @@ -88,5 +89,6 @@ java_binary( ":splitter_lib", ":ziputils_lib", "//src/main/java/com/google/devtools/common/options", + "//third_party:guava", ], ) diff --git a/src/tools/android/java/com/google/devtools/build/android/ziputils/DexMapper.java b/src/tools/android/java/com/google/devtools/build/android/ziputils/DexMapper.java index 1e788678a6..694a00156a 100644 --- a/src/tools/android/java/com/google/devtools/build/android/ziputils/DexMapper.java +++ b/src/tools/android/java/com/google/devtools/build/android/ziputils/DexMapper.java @@ -14,6 +14,8 @@ package com.google.devtools.build.android.ziputils; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import com.google.devtools.common.options.Option; import com.google.devtools.common.options.OptionsBase; import com.google.devtools.common.options.OptionsParser; @@ -42,12 +44,17 @@ public class DexMapper { String resourceFile = options.outputResources; try { + Predicate<String> inputFilter = Predicates.alwaysTrue(); + if (options.inclusionFilterJar != null) { + inputFilter = SplitZipFilters.entriesIn(options.inclusionFilterJar); + } new SplitZip() .setVerbose(false) .useDefaultEntryDate() .setSplitDexedClasses(options.splitDexedClasses) .addInputs(inputs) .addOutputs(outputs) + .setInputFilter(inputFilter) .setMainClassListFile(filterFile) .setResourceFile(resourceFile) .run() @@ -99,5 +106,11 @@ public class DexMapper { defaultValue = "false", help = "Split X.class.dex like X.class if true. Treated as resources if false.") public boolean splitDexedClasses; + + @Option(name = "inclusion_filter_jar", + defaultValue = "null", + help = "Only copy entries that are listed in the given Jar file. By default, all entries " + + "are copied over.") + public String inclusionFilterJar; } } diff --git a/src/tools/android/java/com/google/devtools/build/android/ziputils/SplitZip.java b/src/tools/android/java/com/google/devtools/build/android/ziputils/SplitZip.java index 4fd1f154b3..dabe4dd34b 100644 --- a/src/tools/android/java/com/google/devtools/build/android/ziputils/SplitZip.java +++ b/src/tools/android/java/com/google/devtools/build/android/ziputils/SplitZip.java @@ -25,6 +25,9 @@ import static com.google.devtools.build.android.ziputils.LocalFileHeader.LOCTIM; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Sets; import java.io.BufferedReader; import java.io.File; @@ -67,6 +70,7 @@ public class SplitZip implements EntryHandler { private final Map<String, ZipOut> assignments = new HashMap<>(); private final Map<String, CentralDirectory> centralDirectories; private final Set<String> classes = new TreeSet<>(); + private Predicate<String> inputFilter = Predicates.alwaysTrue(); /** * Creates an un-configured {@code SplitZip} instance. @@ -257,6 +261,16 @@ public class SplitZip implements EntryHandler { } /** + * Set a predicate to only include files with matching filenames in any of the outputs. <b>Other + * zip entries are dropped</b>, regardless of whether they're classes or resources and regardless + * of whether they're listed in {@link #setMainClassListFile}. + */ + public SplitZip setInputFilter(Predicate<String> inputFilter) { + this.inputFilter = Preconditions.checkNotNull(inputFilter); + return this; + } + + /** * Executes this {@code SplitZip}, reading content from the configured input locations, creating * the specified number of archives, in the configured output directory. * @@ -305,7 +319,8 @@ public class SplitZip implements EntryHandler { ZipOut out = assignments.remove(normalizedFilename(header.getFilename())); if (out == null) { // Skip unassigned file; includes a file with the same name as a previously processed one. - // This in particular picks the first .class or .dex file encountered for a given class name. + // This in particular picks the first .class or .dex file encountered for a given class name + // and drops any file not matched by inputFilter. return; } if (dirEntry == null) { @@ -391,6 +406,9 @@ public class SplitZip implements EntryHandler { CentralDirectory cdir = centralDirectories.get(in.getFilename()); for (DirectoryEntry entry : cdir.list()) { String filename = normalizedFilename(entry.getFilename()); + if (!inputFilter.apply(filename)) { + continue; + } if (filename.endsWith(".class")) { // Only pass classes to the splitter, so that it can do the best job // possible distributing them across output files. @@ -402,15 +420,15 @@ public class SplitZip implements EntryHandler { } } } - Splitter entryFilter = new Splitter(outputs.size(), classes.size()); + Splitter splitter = new Splitter(outputs.size(), classes.size()); if (filter != null) { // Assign files in the filter to the first output file. - entryFilter.assign(filter); - entryFilter.nextShard(); // minimal initial shard + splitter.assign(Sets.filter(filter, inputFilter)); + splitter.nextShard(); // minimal initial shard } for (String path : classes) { // Use normalized filename so the filter file doesn't have to change - int assignment = entryFilter.assign(path); + int assignment = splitter.assign(path); Preconditions.checkState(assignment >= 0 && assignment < zipOuts.length); assignments.put(path, zipOuts[assignment]); } diff --git a/src/tools/android/java/com/google/devtools/build/android/ziputils/SplitZipFilters.java b/src/tools/android/java/com/google/devtools/build/android/ziputils/SplitZipFilters.java new file mode 100644 index 0000000000..07c38e8889 --- /dev/null +++ b/src/tools/android/java/com/google/devtools/build/android/ziputils/SplitZipFilters.java @@ -0,0 +1,44 @@ +// Copyright 2015 The Bazel Authors. All rights reserved. +// +// 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.google.devtools.build.android.ziputils; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableSet; + +import java.io.FileInputStream; +import java.io.IOException; + +/** + * Custom filters intended for {@link SplitZip#setInputFilter}. + */ +public class SplitZipFilters { + + /** + * Returns a predicate that returns true for filenames contained in the given zip file. + */ + public static Predicate<String> entriesIn(String filterZip) throws IOException { + // Aggregate filenames into a set so Predicates.in is efficient + ImmutableSet.Builder<String> filenames = ImmutableSet.builder(); + @SuppressWarnings("resource") // ZipIn takes ownership but isn't Closable + ZipIn zip = new ZipIn(new FileInputStream(filterZip).getChannel(), filterZip); + for (DirectoryEntry entry : zip.centralDirectory().list()) { + filenames.add(entry.getFilename()); + } + return Predicates.in(filenames.build()); + } + + private SplitZipFilters() { + } +} |