use of com.facebook.buck.jvm.java.classes.ClasspathTraverser in project buck by facebook.
the class APKModuleGraph method getAPKModuleToClassesMap.
/**
* Group the classes in the input jars into a multimap based on the APKModule they belong to
*
* @param apkModuleToJarPathMap the mapping of APKModules to the path for the jar files
* @param translatorFunction function used to translate obfuscated names
* @param filesystem filesystem representation for resolving paths
* @return The mapping of APKModules to the class names they contain
* @throws IOException
*/
public static ImmutableMultimap<APKModule, String> getAPKModuleToClassesMap(final ImmutableMultimap<APKModule, Path> apkModuleToJarPathMap, final Function<String, String> translatorFunction, final ProjectFilesystem filesystem) throws IOException {
final ImmutableMultimap.Builder<APKModule, String> builder = ImmutableMultimap.builder();
if (!apkModuleToJarPathMap.isEmpty()) {
for (final APKModule dexStore : apkModuleToJarPathMap.keySet()) {
for (Path jarFilePath : apkModuleToJarPathMap.get(dexStore)) {
ClasspathTraverser classpathTraverser = new DefaultClasspathTraverser();
classpathTraverser.traverse(new ClasspathTraversal(ImmutableSet.of(jarFilePath), filesystem) {
@Override
public void visit(FileLike entry) {
if (!entry.getRelativePath().endsWith(".class")) {
// ignore everything but class files in the jar.
return;
}
builder.put(dexStore, translatorFunction.apply(entry.getRelativePath()));
}
});
}
}
}
return builder.build();
}
use of com.facebook.buck.jvm.java.classes.ClasspathTraverser in project buck by facebook.
the class DalvikAwareZipSplitter method execute.
@Override
public ImmutableMultimap<APKModule, Path> execute() throws IOException {
ClasspathTraverser classpathTraverser = new DefaultClasspathTraverser();
final Set<String> secondaryTail = new HashSet<String>();
// Start out by writing the primary zip and recording which entries were added to it.
primaryOut = newZipOutput(outPrimary);
secondaryDexWriter.reset();
final ImmutableMap.Builder<String, FileLike> entriesBuilder = ImmutableMap.builder();
final List<String> additionalDexStoreEntries = new ArrayList<>();
// Iterate over all of the inFiles and add all entries that match the requiredInPrimaryZip
// predicate.
LOG.debug("Traversing classpath for primary zip");
classpathTraverser.traverse(new ClasspathTraversal(inFiles, filesystem) {
@Override
public void visit(FileLike entry) throws IOException {
LOG.debug("Visiting " + entry.getRelativePath());
String relativePath = entry.getRelativePath();
if (!relativePath.endsWith(".class")) {
// We don't need resources in dex jars, so just drop them.
return;
}
Preconditions.checkNotNull(primaryOut);
Preconditions.checkNotNull(classPathToDexStore);
if (requiredInPrimaryZip.apply(relativePath)) {
primaryOut.putEntry(entry);
} else if (wantedInPrimaryZip.contains(relativePath) || (secondaryHeadSet != null && secondaryHeadSet.contains(relativePath))) {
entriesBuilder.put(relativePath, new BufferedFileLike(entry));
} else if (secondaryTailSet != null && secondaryTailSet.contains(relativePath)) {
entriesBuilder.put(relativePath, new BufferedFileLike(entry));
secondaryTail.add(relativePath);
} else {
ImmutableCollection<APKModule> containingModule = classPathToDexStore.get(relativePath);
if (!containingModule.isEmpty()) {
if (containingModule.size() > 1) {
throw new IllegalStateException(String.format("classpath %s is contained in multiple dex stores: %s", relativePath, classPathToDexStore.get(relativePath).asList().toString()));
}
APKModule dexStore = containingModule.iterator().next();
if (!dexStore.equals(apkModuleGraph.getRootAPKModule())) {
MySecondaryDexHelper dexHelper = additionalDexWriters.get(dexStore);
Preconditions.checkNotNull(dexHelper);
dexHelper.getOutputToWriteTo(entry).putEntry(entry);
additionalDexStoreEntries.add(relativePath);
}
}
}
}
});
// Put as many of the items wanted in the primary dex as we can into the primary dex.
ImmutableMap<String, FileLike> entries = entriesBuilder.build();
for (String wanted : wantedInPrimaryZip) {
FileLike entry = entries.get(wanted);
if ((entry != null) && !primaryOut.containsEntry(entry) && primaryOut.canPutEntry(entry)) {
primaryOut.putEntry(entry);
}
}
if (secondaryHeadSet != null) {
for (String head : secondaryHeadSet) {
FileLike headEntry = entries.get(head);
if ((headEntry != null) && !primaryOut.containsEntry(headEntry)) {
secondaryDexWriter.getOutputToWriteTo(headEntry).putEntry(headEntry);
}
}
}
LOG.debug("Traversing classpath for secondary zip");
// Now that all of the required entries have been added to the primary zip, fill the rest of
// the zip up with the remaining entries.
classpathTraverser.traverse(new ClasspathTraversal(inFiles, filesystem) {
@Override
public void visit(FileLike entry) throws IOException {
Preconditions.checkNotNull(primaryOut);
String relativePath = entry.getRelativePath();
// skip if it is the primary dex, is part of a modular dex store, or is not a class file
if (primaryOut.containsEntry(entry) || additionalDexStoreEntries.contains(relativePath)) {
return;
}
LOG.debug("Visiting " + entry.getRelativePath());
// room in the primary dex for the current entry in the traversal.
if (dexSplitStrategy == DexSplitStrategy.MAXIMIZE_PRIMARY_DEX_SIZE && primaryOut.canPutEntry(entry)) {
primaryOut.putEntry(entry);
} else {
if (secondaryHeadSet != null && secondaryHeadSet.contains(relativePath)) {
return;
}
if (secondaryTail.contains(relativePath)) {
return;
}
secondaryDexWriter.getOutputToWriteTo(entry).putEntry(entry);
}
}
});
if (secondaryTailSet != null) {
for (String tail : secondaryTailSet) {
FileLike tailEntry = entries.get(tail);
if ((tailEntry != null) && !primaryOut.containsEntry(tailEntry) && secondaryTail.contains(tail)) {
secondaryDexWriter.getOutputToWriteTo(tailEntry).putEntry(tailEntry);
}
}
}
primaryOut.close();
secondaryDexWriter.close();
ImmutableMultimap.Builder<APKModule, Path> outputFilesBuilder = ImmutableMultimap.builder();
APKModule secondaryDexStore = apkModuleGraph.getRootAPKModule();
outputFilesBuilder.putAll(secondaryDexStore, secondaryDexWriter.getFiles());
for (Map.Entry<APKModule, MySecondaryDexHelper> entry : additionalDexWriters.entrySet()) {
if (!entry.getKey().equals(secondaryDexStore)) {
entry.getValue().close();
outputFilesBuilder.putAll(entry.getKey(), entry.getValue().getFiles());
}
}
return outputFilesBuilder.build();
}
Aggregations