summaryrefslogtreecommitdiffstats
path: root/test-runner/src/android/test/ClassPathPackageInfoSource.java
diff options
context:
space:
mode:
Diffstat (limited to 'test-runner/src/android/test/ClassPathPackageInfoSource.java')
-rw-r--r--test-runner/src/android/test/ClassPathPackageInfoSource.java323
1 files changed, 0 insertions, 323 deletions
diff --git a/test-runner/src/android/test/ClassPathPackageInfoSource.java b/test-runner/src/android/test/ClassPathPackageInfoSource.java
deleted file mode 100644
index 877075f..0000000
--- a/test-runner/src/android/test/ClassPathPackageInfoSource.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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 android.test;
-
-import android.util.Config;
-import android.util.Log;
-import com.google.android.collect.Maps;
-import com.google.android.collect.Sets;
-import dalvik.system.DexFile;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.regex.Pattern;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-/**
- * Generate {@link ClassPathPackageInfo}s by scanning apk paths.
- *
- * {@hide} Not needed for 1.0 SDK.
- */
-public class ClassPathPackageInfoSource {
-
- private static final String CLASS_EXTENSION = ".class";
-
- private static final ClassLoader CLASS_LOADER
- = ClassPathPackageInfoSource.class.getClassLoader();
-
- private final SimpleCache<String, ClassPathPackageInfo> cache =
- new SimpleCache<String, ClassPathPackageInfo>() {
- @Override
- protected ClassPathPackageInfo load(String pkgName) {
- return createPackageInfo(pkgName);
- }
- };
-
- // The class path of the running application
- private final String[] classPath;
- private static String[] apkPaths;
-
- // A cache of jar file contents
- private final Map<File, Set<String>> jarFiles = Maps.newHashMap();
- private ClassLoader classLoader;
-
- ClassPathPackageInfoSource() {
- classPath = getClassPath();
- }
-
-
- public static void setApkPaths(String[] apkPaths) {
- ClassPathPackageInfoSource.apkPaths = apkPaths;
- }
-
- public ClassPathPackageInfo getPackageInfo(String pkgName) {
- return cache.get(pkgName);
- }
-
- private ClassPathPackageInfo createPackageInfo(String packageName) {
- Set<String> subpackageNames = new TreeSet<String>();
- Set<String> classNames = new TreeSet<String>();
- Set<Class<?>> topLevelClasses = Sets.newHashSet();
- findClasses(packageName, classNames, subpackageNames);
- for (String className : classNames) {
- if (className.endsWith(".R") || className.endsWith(".Manifest")) {
- // Don't try to load classes that are generated. They usually aren't in test apks.
- continue;
- }
-
- try {
- // We get errors in the emulator if we don't use the caller's class loader.
- topLevelClasses.add(Class.forName(className, false,
- (classLoader != null) ? classLoader : CLASS_LOADER));
- } catch (ClassNotFoundException e) {
- // Should not happen unless there is a generated class that is not included in
- // the .apk.
- Log.w("ClassPathPackageInfoSource", "Cannot load class. "
- + "Make sure it is in your apk. Class name: '" + className
- + "'. Message: " + e.getMessage(), e);
- }
- }
- return new ClassPathPackageInfo(this, packageName, subpackageNames,
- topLevelClasses);
- }
-
- /**
- * Finds all classes and sub packages that are below the packageName and
- * add them to the respective sets. Searches the package on the whole class
- * path.
- */
- private void findClasses(String packageName, Set<String> classNames,
- Set<String> subpackageNames) {
- String packagePrefix = packageName + '.';
- String pathPrefix = packagePrefix.replace('.', '/');
-
- for (String entryName : classPath) {
- File classPathEntry = new File(entryName);
-
- // Forge may not have brought over every item in the classpath. Be
- // polite and ignore missing entries.
- if (classPathEntry.exists()) {
- try {
- if (entryName.endsWith(".apk")) {
- findClassesInApk(entryName, packageName, classNames, subpackageNames);
- } else if ("true".equals(System.getProperty("android.vm.dexfile", "false"))) {
- // If the vm supports dex files then scan the directories that contain
- // apk files.
- for (String apkPath : apkPaths) {
- File file = new File(apkPath);
- scanForApkFiles(file, packageName, classNames, subpackageNames);
- }
- } else if (entryName.endsWith(".jar")) {
- findClassesInJar(classPathEntry, pathPrefix,
- classNames, subpackageNames);
- } else if (classPathEntry.isDirectory()) {
- findClassesInDirectory(classPathEntry, packagePrefix, pathPrefix,
- classNames, subpackageNames);
- } else {
- throw new AssertionError("Don't understand classpath entry " +
- classPathEntry);
- }
- } catch (IOException e) {
- throw new AssertionError("Can't read classpath entry " +
- entryName + ": " + e.getMessage());
- }
- }
- }
- }
-
- private void scanForApkFiles(File source, String packageName,
- Set<String> classNames, Set<String> subpackageNames) throws IOException {
- if (source.getPath().endsWith(".apk")) {
- findClassesInApk(source.getPath(), packageName, classNames, subpackageNames);
- } else {
- File[] files = source.listFiles();
- if (files != null) {
- for (File file : files) {
- scanForApkFiles(file, packageName, classNames, subpackageNames);
- }
- }
- }
- }
-
- /**
- * Finds all classes and sub packages that are below the packageName and
- * add them to the respective sets. Searches the package in a class directory.
- */
- private void findClassesInDirectory(File classDir,
- String packagePrefix, String pathPrefix, Set<String> classNames,
- Set<String> subpackageNames)
- throws IOException {
- File directory = new File(classDir, pathPrefix);
-
- if (directory.exists()) {
- for (File f : directory.listFiles()) {
- String name = f.getName();
- if (name.endsWith(CLASS_EXTENSION) && isToplevelClass(name)) {
- classNames.add(packagePrefix + getClassName(name));
- } else if (f.isDirectory()) {
- subpackageNames.add(packagePrefix + name);
- }
- }
- }
- }
-
- /**
- * Finds all classes and sub packages that are below the packageName and
- * add them to the respective sets. Searches the package in a single jar file.
- */
- private void findClassesInJar(File jarFile, String pathPrefix,
- Set<String> classNames, Set<String> subpackageNames)
- throws IOException {
- Set<String> entryNames = getJarEntries(jarFile);
- // check if the Jar contains the package.
- if (!entryNames.contains(pathPrefix)) {
- return;
- }
- int prefixLength = pathPrefix.length();
- for (String entryName : entryNames) {
- if (entryName.startsWith(pathPrefix)) {
- if (entryName.endsWith(CLASS_EXTENSION)) {
- // check if the class is in the package itself or in one of its
- // subpackages.
- int index = entryName.indexOf('/', prefixLength);
- if (index >= 0) {
- String p = entryName.substring(0, index).replace('/', '.');
- subpackageNames.add(p);
- } else if (isToplevelClass(entryName)) {
- classNames.add(getClassName(entryName).replace('/', '.'));
- }
- }
- }
- }
- }
-
- /**
- * Finds all classes and sub packages that are below the packageName and
- * add them to the respective sets. Searches the package in a single apk file.
- */
- private void findClassesInApk(String apkPath, String packageName,
- Set<String> classNames, Set<String> subpackageNames)
- throws IOException {
-
- DexFile dexFile = null;
- try {
- dexFile = new DexFile(apkPath);
- Enumeration<String> apkClassNames = dexFile.entries();
- while (apkClassNames.hasMoreElements()) {
- String className = apkClassNames.nextElement();
-
- if (className.startsWith(packageName)) {
- String subPackageName = packageName;
- int lastPackageSeparator = className.lastIndexOf('.');
- if (lastPackageSeparator > 0) {
- subPackageName = className.substring(0, lastPackageSeparator);
- }
- if (subPackageName.length() > packageName.length()) {
- subpackageNames.add(subPackageName);
- } else if (isToplevelClass(className)) {
- classNames.add(className);
- }
- }
- }
- } catch (IOException e) {
- if (Config.LOGV) {
- Log.w("ClassPathPackageInfoSource",
- "Error finding classes at apk path: " + apkPath, e);
- }
- } finally {
- if (dexFile != null) {
- // Todo: figure out why closing causes a dalvik error resulting in vm shutdown.
-// dexFile.close();
- }
- }
- }
-
- /**
- * Gets the class and package entries from a Jar.
- */
- private Set<String> getJarEntries(File jarFile)
- throws IOException {
- Set<String> entryNames = jarFiles.get(jarFile);
- if (entryNames == null) {
- entryNames = Sets.newHashSet();
- ZipFile zipFile = new ZipFile(jarFile);
- Enumeration<? extends ZipEntry> entries = zipFile.entries();
- while (entries.hasMoreElements()) {
- String entryName = entries.nextElement().getName();
- if (entryName.endsWith(CLASS_EXTENSION)) {
- // add the entry name of the class
- entryNames.add(entryName);
-
- // add the entry name of the classes package, i.e. the entry name of
- // the directory that the class is in. Used to quickly skip jar files
- // if they do not contain a certain package.
- //
- // Also add parent packages so that a JAR that contains
- // pkg1/pkg2/Foo.class will be marked as containing pkg1/ in addition
- // to pkg1/pkg2/ and pkg1/pkg2/Foo.class. We're still interested in
- // JAR files that contains subpackages of a given package, even if
- // an intermediate package contains no direct classes.
- //
- // Classes in the default package will cause a single package named
- // "" to be added instead.
- int lastIndex = entryName.lastIndexOf('/');
- do {
- String packageName = entryName.substring(0, lastIndex + 1);
- entryNames.add(packageName);
- lastIndex = entryName.lastIndexOf('/', lastIndex - 1);
- } while (lastIndex > 0);
- }
- }
- jarFiles.put(jarFile, entryNames);
- }
- return entryNames;
- }
-
- /**
- * Checks if a given file name represents a toplevel class.
- */
- private static boolean isToplevelClass(String fileName) {
- return fileName.indexOf('$') < 0;
- }
-
- /**
- * Given the absolute path of a class file, return the class name.
- */
- private static String getClassName(String className) {
- int classNameEnd = className.length() - CLASS_EXTENSION.length();
- return className.substring(0, classNameEnd);
- }
-
- /**
- * Gets the class path from the System Property "java.class.path" and splits
- * it up into the individual elements.
- */
- private static String[] getClassPath() {
- String classPath = System.getProperty("java.class.path");
- String separator = System.getProperty("path.separator", ":");
- return classPath.split(Pattern.quote(separator));
- }
-
- public void setClassLoader(ClassLoader classLoader) {
- this.classLoader = classLoader;
- }
-}