Search in sources :

Example 1 with ClasspathTraverser

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();
}
Also used : Path(java.nio.file.Path) ClasspathTraversal(com.facebook.buck.jvm.java.classes.ClasspathTraversal) DefaultClasspathTraverser(com.facebook.buck.jvm.java.classes.DefaultClasspathTraverser) ClasspathTraverser(com.facebook.buck.jvm.java.classes.ClasspathTraverser) DefaultClasspathTraverser(com.facebook.buck.jvm.java.classes.DefaultClasspathTraverser) ImmutableMultimap(com.google.common.collect.ImmutableMultimap) FileLike(com.facebook.buck.jvm.java.classes.FileLike)

Example 2 with ClasspathTraverser

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();
}
Also used : Path(java.nio.file.Path) ClasspathTraversal(com.facebook.buck.jvm.java.classes.ClasspathTraversal) ImmutableCollection(com.google.common.collect.ImmutableCollection) DefaultClasspathTraverser(com.facebook.buck.jvm.java.classes.DefaultClasspathTraverser) ClasspathTraverser(com.facebook.buck.jvm.java.classes.ClasspathTraverser) DefaultClasspathTraverser(com.facebook.buck.jvm.java.classes.DefaultClasspathTraverser) ArrayList(java.util.ArrayList) APKModule(com.facebook.buck.android.APKModule) IOException(java.io.IOException) AbstractFileLike(com.facebook.buck.jvm.java.classes.AbstractFileLike) FileLike(com.facebook.buck.jvm.java.classes.FileLike) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMultimap(com.google.common.collect.ImmutableMultimap) HashMap(java.util.HashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashSet(java.util.HashSet)

Aggregations

ClasspathTraversal (com.facebook.buck.jvm.java.classes.ClasspathTraversal)2 ClasspathTraverser (com.facebook.buck.jvm.java.classes.ClasspathTraverser)2 DefaultClasspathTraverser (com.facebook.buck.jvm.java.classes.DefaultClasspathTraverser)2 FileLike (com.facebook.buck.jvm.java.classes.FileLike)2 ImmutableMultimap (com.google.common.collect.ImmutableMultimap)2 Path (java.nio.file.Path)2 APKModule (com.facebook.buck.android.APKModule)1 AbstractFileLike (com.facebook.buck.jvm.java.classes.AbstractFileLike)1 ImmutableCollection (com.google.common.collect.ImmutableCollection)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Map (java.util.Map)1