1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.cf.direct; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dex.util.FileUtils; 203abdb48fdefcc3136a8d7f9c168a305d9be9690eYohann Roussel 21fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport java.io.ByteArrayOutputStream; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.File; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.InputStream; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList; 26fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport java.util.Arrays; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Collections; 28fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport java.util.Comparator; 29fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport java.util.zip.ZipEntry; 30fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport java.util.zip.ZipFile; 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Opens all the class files found in a class path element. Path elements 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can point to class files, {jar,zip,apk} files, or directories containing 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class files. 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class ClassPathOpener { 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} pathname to start with */ 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final String pathname; 4199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} callback interface */ 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final Consumer consumer; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If true, sort such that classes appear before their inner 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classes and "package-info" occurs before all other classes in that 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * package. 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final boolean sort; 494c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche private FileNameFilter filter; 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 5299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Callback interface for {@code ClassOpener}. 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public interface Consumer { 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Provides the file name and byte array for a class path element. 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 5999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param name {@code non-null;} filename of element. May not be a valid 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * filesystem path. 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 62dc86cd9edc8b80953c8b698a83cdaebf6825d798Jesse Wilson * @param lastModified milliseconds since 1970-Jan-1 00:00:00 GMT 6399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param bytes {@code non-null;} file data 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return true on success. Result is or'd with all other results 6599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * from {@code processFileBytes} and returned to the caller 6699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * of {@code process()}. 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 68dc86cd9edc8b80953c8b698a83cdaebf6825d798Jesse Wilson boolean processFileBytes(String name, long lastModified, byte[] bytes); 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Informs consumer that an exception occurred while processing 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this path element. Processing will continue if possible. 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 7499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param ex {@code non-null;} exception 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void onException(Exception ex); 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Informs consumer that processing of an archive file has begun. 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param file {@code non-null;} archive file being processed 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void onProcessArchiveStart(File file); 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 874c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * Filter interface for {@code ClassOpener}. 884c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche */ 894c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche public interface FileNameFilter { 904c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche 914c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche boolean accept(String path); 924c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche } 934c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche 944c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche /** 954c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * An accept all filter. 964c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche */ 974c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche public static final FileNameFilter acceptAll = new FileNameFilter() { 984c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche 994c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche @Override 1004c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche public boolean accept(String path) { 1014c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche return true; 1024c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche } 1034c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche }; 1044c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche 1054c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche /** 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param pathname {@code non-null;} path element to process 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param sort if true, sort such that classes appear before their inner 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classes and "package-info" occurs before all other classes in that 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * package. 11299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param consumer {@code non-null;} callback interface 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ClassPathOpener(String pathname, boolean sort, Consumer consumer) { 1154c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche this(pathname, sort, acceptAll, consumer); 1164c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche } 1174c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche 1184c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche /** 1194c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * Constructs an instance. 1204c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * 1214c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * @param pathname {@code non-null;} path element to process 1224c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * @param sort if true, sort such that classes appear before their inner 1234c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * classes and "package-info" occurs before all other classes in that 1244c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * package. 1254c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * @param consumer {@code non-null;} callback interface 1264c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche */ 1274c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche public ClassPathOpener(String pathname, boolean sort, FileNameFilter filter, 1284c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche Consumer consumer) { 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.pathname = pathname; 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.sort = sort; 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.consumer = consumer; 1324c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche this.filter = filter; 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Processes a path element. 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the OR of all return values 13999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * from {@code Consumer.processFileBytes()}. 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean process() { 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project File file = new File(pathname); 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return processOne(file, true); 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Processes one file. 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 15099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param file {@code non-null;} the file to process 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param topLevel whether this is a top-level file (that is, 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * specified directly on the commandline) 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return whether any processing actually happened 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private boolean processOne(File file, boolean topLevel) { 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (file.isDirectory()) { 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return processDirectory(file, topLevel); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String path = file.getPath(); 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (path.endsWith(".zip") || 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project path.endsWith(".jar") || 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project path.endsWith(".apk")) { 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return processArchive(file); 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1684c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche if (filter.accept(path)) { 1694c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche byte[] bytes = FileUtils.readFile(file); 1704c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche return consumer.processFileBytes(path, file.lastModified(), bytes); 1714c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche } else { 1724c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche return false; 1734c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche } 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (Exception ex) { 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project consumer.onException(ex); 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sorts java class names such that outer classes preceed their inner 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classes and "package-info" preceeds all other classes in its package. 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 18499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param a {@code non-null;} first class name 18599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param b {@code non-null;} second class name 18699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code compareTo()}-style result 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static int compareClassNames(String a, String b) { 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Ensure inner classes sort second 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project a = a.replace('$','0'); 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project b = b.replace('$','0'); 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Assuming "package-info" only occurs at the end, ensures package-info 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * sorts first. 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project a = a.replace("package-info", ""); 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project b = b.replace("package-info", ""); 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return a.compareTo(b); 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Processes a directory recursively. 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 20699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param dir {@code non-null;} file representing the directory 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param topLevel whether this is a top-level directory (that is, 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * specified directly on the commandline) 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return whether any processing actually happened 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private boolean processDirectory(File dir, boolean topLevel) { 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (topLevel) { 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dir = new File(dir, "."); 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project File[] files = dir.listFiles(); 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int len = files.length; 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean any = false; 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (sort) { 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Arrays.sort(files, new Comparator<File>() { 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int compare(File a, File b) { 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return compareClassNames(a.getName(), b.getName()); 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }); 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < len; i++) { 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project any |= processOne(files[i], false); 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return any; 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 23699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Processes the contents of an archive ({@code .zip}, 23799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code .jar}, or {@code .apk}). 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 23999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param file {@code non-null;} archive file to process 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return whether any processing actually happened 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException on i/o problem 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private boolean processArchive(File file) throws IOException { 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ZipFile zip = new ZipFile(file); 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 246de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro ArrayList<? extends java.util.zip.ZipEntry> entriesList 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project = Collections.list(zip.entries()); 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (sort) { 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Collections.sort(entriesList, new Comparator<ZipEntry>() { 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int compare (ZipEntry a, ZipEntry b) { 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return compareClassNames(a.getName(), b.getName()); 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }); 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project consumer.onProcessArchiveStart(file); 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2597736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath ByteArrayOutputStream baos = new ByteArrayOutputStream(40000); 2607736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath byte[] buf = new byte[20000]; 2617736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath boolean any = false; 2627736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath 26341aecd0a6bfea1e9a6713014b2b3d56fec8c552cDan Bornstein for (ZipEntry one : entriesList) { 2647736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath final boolean isDirectory = one.isDirectory(); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String path = one.getName(); 2673abdb48fdefcc3136a8d7f9c168a305d9be9690eYohann Roussel if (filter.accept(path)) { 2687736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath final byte[] bytes; 2697736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath if (!isDirectory) { 2707736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath InputStream in = zip.getInputStream(one); 2717736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath 2727736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath baos.reset(); 2737736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath int read; 2747736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath while ((read = in.read(buf)) != -1) { 2757736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath baos.write(buf, 0, read); 2763abdb48fdefcc3136a8d7f9c168a305d9be9690eYohann Roussel } 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2787736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath in.close(); 2797736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath bytes = baos.toByteArray(); 2807736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath } else { 2817736e8ff04c2974edd9de9ca150f12dc601b005dNarayan Kamath bytes = new byte[0]; 2823abdb48fdefcc3136a8d7f9c168a305d9be9690eYohann Roussel } 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2843abdb48fdefcc3136a8d7f9c168a305d9be9690eYohann Roussel any |= consumer.processFileBytes(path, one.getTime(), bytes); 2853abdb48fdefcc3136a8d7f9c168a305d9be9690eYohann Roussel } 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project zip.close(); 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return any; 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 292