use of com.facebook.buck.jvm.java.classes.FileLike in project buck by facebook.
the class EstimateDexWeightStep method execute.
@Override
public StepExecutionResult execute(ExecutionContext context) {
Path path = filesystem.resolve(pathToJarOrClassesDirectory);
ClasspathTraversal traversal = new ClasspathTraversal(Collections.singleton(path), filesystem) {
private int totalWeightEstimate = 0;
@Override
public void visit(FileLike fileLike) throws IOException {
// in .class, which should be ignored.
if (!FileLikes.isClassFile(fileLike)) {
return;
}
totalWeightEstimate += dexWeightEstimator.getEstimate(fileLike);
}
@Override
public Integer getResult() {
return totalWeightEstimate;
}
};
try {
new DefaultClasspathTraverser().traverse(traversal);
} catch (IOException e) {
context.logError(e, "Error accumulating class names for %s.", pathToJarOrClassesDirectory);
return StepExecutionResult.ERROR;
}
this.weightEstimate = (Integer) traversal.getResult();
return StepExecutionResult.SUCCESS;
}
use of com.facebook.buck.jvm.java.classes.FileLike in project buck by facebook.
the class SecondaryDexHelper method getOutputToWriteTo.
ZIP_OUTPUT_STREAM_HELPER getOutputToWriteTo(FileLike entry) throws IOException {
// Going to write this entry to a secondary zip.
if (currentSecondaryOut == null || !currentSecondaryOut.canPutEntry(entry) || newSecondaryOutOnNextEntry) {
if (currentSecondaryOut != null) {
currentSecondaryOut.close();
}
currentSecondaryIndex++;
Path newSecondaryFile = outSecondaryDir.resolve(String.format(secondaryPattern, currentSecondaryIndex));
secondaryFiles.add(newSecondaryFile);
currentSecondaryOut = newZipOutput(newSecondaryFile);
newSecondaryOutOnNextEntry = false;
if (canaryStrategy == ZipSplitter.CanaryStrategy.INCLUDE_CANARIES) {
// Make sure the first class in the new secondary dex can be safely loaded.
FileLike canaryFile = CanaryFactory.create(storeName, currentSecondaryIndex);
currentSecondaryOut.putEntry(canaryFile);
}
// We've already tested for this. It really shouldn't happen.
Preconditions.checkState(currentSecondaryOut.canPutEntry(entry));
}
return currentSecondaryOut;
}
use of com.facebook.buck.jvm.java.classes.FileLike 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.FileLike in project buck by facebook.
the class AccumulateClassNamesStep method calculateClassHashes.
/**
* @return an Optional that will be absent if there was an error.
*/
public static Optional<ImmutableSortedMap<String, HashCode>> calculateClassHashes(ExecutionContext context, ProjectFilesystem filesystem, Path path) {
final Map<String, HashCode> classNames = new HashMap<>();
ClasspathTraversal traversal = new ClasspathTraversal(Collections.singleton(path), filesystem) {
@Override
public void visit(final FileLike fileLike) throws IOException {
// end in .class, which should be ignored.
if (!FileLikes.isClassFile(fileLike)) {
return;
}
String key = FileLikes.getFileNameWithoutClassSuffix(fileLike);
ByteSource input = new ByteSource() {
@Override
public InputStream openStream() throws IOException {
return fileLike.getInput();
}
};
HashCode value = input.hash(Hashing.sha1());
HashCode existing = classNames.putIfAbsent(key, value);
if (existing != null && !existing.equals(value)) {
throw new IllegalArgumentException(String.format("Multiple entries with same key but differing values: %1$s=%2$s and %1$s=%3$s", key, value, existing));
}
}
};
try {
new DefaultClasspathTraverser().traverse(traversal);
} catch (IOException e) {
context.logError(e, "Error accumulating class names for %s.", path);
return Optional.empty();
}
return Optional.of(ImmutableSortedMap.copyOf(classNames, Ordering.natural()));
}
use of com.facebook.buck.jvm.java.classes.FileLike 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