summaryrefslogtreecommitdiffstats
path: root/dalvik
diff options
context:
space:
mode:
authorBrian Carlstrom <bdc@google.com>2013-05-13 10:19:39 -0700
committerBrian Carlstrom <bdc@google.com>2013-05-13 12:53:43 -0700
commit895bba44ff59d2225532a1fe9842c8b9a70a9f9a (patch)
tree55e6cfe041d8c68afd7adb97d0c2f52e80eeb902 /dalvik
parent8245506ebe0cbeba47c99e1e109c8da31c1626bc (diff)
downloadlibcore-895bba44ff59d2225532a1fe9842c8b9a70a9f9a.zip
libcore-895bba44ff59d2225532a1fe9842c8b9a70a9f9a.tar.gz
libcore-895bba44ff59d2225532a1fe9842c8b9a70a9f9a.tar.bz2
Move some files with dalvik dependencies to libdvm
Change-Id: I04498d8d8c4b065dbda8d7b30b8b77ce53e63a77
Diffstat (limited to 'dalvik')
-rw-r--r--dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java132
-rw-r--r--dalvik/src/main/java/dalvik/system/DexFile.java296
-rw-r--r--dalvik/src/main/java/dalvik/system/DexPathList.java473
3 files changed, 0 insertions, 901 deletions
diff --git a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
deleted file mode 100644
index d3ec95a..0000000
--- a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2011 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 dalvik.system;
-
-import java.io.File;
-import java.net.URL;
-import java.util.Enumeration;
-
-/**
- * Base class for common functionality between various dex-based
- * {@link ClassLoader} implementations.
- */
-public class BaseDexClassLoader extends ClassLoader {
- private final DexPathList pathList;
-
- /**
- * Constructs an instance.
- *
- * @param dexPath the list of jar/apk files containing classes and
- * resources, delimited by {@code File.pathSeparator}, which
- * defaults to {@code ":"} on Android
- * @param optimizedDirectory directory where optimized dex files
- * should be written; may be {@code null}
- * @param libraryPath the list of directories containing native
- * libraries, delimited by {@code File.pathSeparator}; may be
- * {@code null}
- * @param parent the parent class loader
- */
- public BaseDexClassLoader(String dexPath, File optimizedDirectory,
- String libraryPath, ClassLoader parent) {
- super(parent);
- this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
- }
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- Class c = pathList.findClass(name);
- if (c == null) {
- throw new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
- }
- return c;
- }
-
- @Override
- protected URL findResource(String name) {
- return pathList.findResource(name);
- }
-
- @Override
- protected Enumeration<URL> findResources(String name) {
- return pathList.findResources(name);
- }
-
- @Override
- public String findLibrary(String name) {
- return pathList.findLibrary(name);
- }
-
- /**
- * Returns package information for the given package.
- * Unfortunately, instances of this class don't really have this
- * information, and as a non-secure {@code ClassLoader}, it isn't
- * even required to, according to the spec. Yet, we want to
- * provide it, in order to make all those hopeful callers of
- * {@code myClass.getPackage().getName()} happy. Thus we construct
- * a {@code Package} object the first time it is being requested
- * and fill most of the fields with dummy values. The {@code
- * Package} object is then put into the {@code ClassLoader}'s
- * package cache, so we see the same one next time. We don't
- * create {@code Package} objects for {@code null} arguments or
- * for the default package.
- *
- * <p>There is a limited chance that we end up with multiple
- * {@code Package} objects representing the same package: It can
- * happen when when a package is scattered across different JAR
- * files which were loaded by different {@code ClassLoader}
- * instances. This is rather unlikely, and given that this whole
- * thing is more or less a workaround, probably not worth the
- * effort to address.
- *
- * @param name the name of the class
- * @return the package information for the class, or {@code null}
- * if there is no package information available for it
- */
- @Override
- protected synchronized Package getPackage(String name) {
- if (name != null && !name.isEmpty()) {
- Package pack = super.getPackage(name);
-
- if (pack == null) {
- pack = definePackage(name, "Unknown", "0.0", "Unknown",
- "Unknown", "0.0", "Unknown", null);
- }
-
- return pack;
- }
-
- return null;
- }
-
- /**
- * @hide
- */
- public String getLdLibraryPath() {
- StringBuilder result = new StringBuilder();
- for (File directory : pathList.getNativeLibraryDirectories()) {
- if (result.length() > 0) {
- result.append(':');
- }
- result.append(directory);
- }
- return result.toString();
- }
-
- @Override public String toString() {
- return getClass().getName() + "[" + pathList + "]";
- }
-}
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
deleted file mode 100644
index 18b730b..0000000
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (C) 2007 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 dalvik.system;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Enumeration;
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-import libcore.io.StructStat;
-
-/**
- * Manipulates DEX files. The class is similar in principle to
- * {@link java.util.zip.ZipFile}. It is used primarily by class loaders.
- * <p>
- * Note we don't directly open and read the DEX file here. They're memory-mapped
- * read-only by the VM.
- */
-public final class DexFile {
- private int mCookie;
- private final String mFileName;
- private final CloseGuard guard = CloseGuard.get();
-
- /**
- * Opens a DEX file from a given File object. This will usually be a ZIP/JAR
- * file with a "classes.dex" inside.
- *
- * The VM will generate the name of the corresponding file in
- * /data/dalvik-cache and open it, possibly creating or updating
- * it first if system permissions allow. Don't pass in the name of
- * a file in /data/dalvik-cache, as the named file is expected to be
- * in its original (pre-dexopt) state.
- *
- * @param file
- * the File object referencing the actual DEX file
- *
- * @throws IOException
- * if an I/O error occurs, such as the file not being found or
- * access rights missing for opening it
- */
- public DexFile(File file) throws IOException {
- this(file.getPath());
- }
-
- /**
- * Opens a DEX file from a given filename. This will usually be a ZIP/JAR
- * file with a "classes.dex" inside.
- *
- * The VM will generate the name of the corresponding file in
- * /data/dalvik-cache and open it, possibly creating or updating
- * it first if system permissions allow. Don't pass in the name of
- * a file in /data/dalvik-cache, as the named file is expected to be
- * in its original (pre-dexopt) state.
- *
- * @param fileName
- * the filename of the DEX file
- *
- * @throws IOException
- * if an I/O error occurs, such as the file not being found or
- * access rights missing for opening it
- */
- public DexFile(String fileName) throws IOException {
- mCookie = openDexFile(fileName, null, 0);
- mFileName = fileName;
- guard.open("close");
- //System.out.println("DEX FILE cookie is " + mCookie);
- }
-
- /**
- * Opens a DEX file from a given filename, using a specified file
- * to hold the optimized data.
- *
- * @param sourceName
- * Jar or APK file with "classes.dex".
- * @param outputName
- * File that will hold the optimized form of the DEX data.
- * @param flags
- * Enable optional features.
- */
- private DexFile(String sourceName, String outputName, int flags) throws IOException {
- if (outputName != null) {
- try {
- String parent = new File(outputName).getParent();
- if (Libcore.os.getuid() != Libcore.os.stat(parent).st_uid) {
- throw new IllegalArgumentException("Optimized data directory " + parent
- + " is not owned by the current user. Shared storage cannot protect"
- + " your application from code injection attacks.");
- }
- } catch (ErrnoException ignored) {
- // assume we'll fail with a more contextual error later
- }
- }
-
- mCookie = openDexFile(sourceName, outputName, flags);
- mFileName = sourceName;
- guard.open("close");
- //System.out.println("DEX FILE cookie is " + mCookie);
- }
-
- /**
- * Open a DEX file, specifying the file in which the optimized DEX
- * data should be written. If the optimized form exists and appears
- * to be current, it will be used; if not, the VM will attempt to
- * regenerate it.
- *
- * This is intended for use by applications that wish to download
- * and execute DEX files outside the usual application installation
- * mechanism. This function should not be called directly by an
- * application; instead, use a class loader such as
- * dalvik.system.DexClassLoader.
- *
- * @param sourcePathName
- * Jar or APK file with "classes.dex". (May expand this to include
- * "raw DEX" in the future.)
- * @param outputPathName
- * File that will hold the optimized form of the DEX data.
- * @param flags
- * Enable optional features. (Currently none defined.)
- * @return
- * A new or previously-opened DexFile.
- * @throws IOException
- * If unable to open the source or output file.
- */
- static public DexFile loadDex(String sourcePathName, String outputPathName,
- int flags) throws IOException {
-
- /*
- * TODO: we may want to cache previously-opened DexFile objects.
- * The cache would be synchronized with close(). This would help
- * us avoid mapping the same DEX more than once when an app
- * decided to open it multiple times. In practice this may not
- * be a real issue.
- */
- return new DexFile(sourcePathName, outputPathName, flags);
- }
-
- /**
- * Gets the name of the (already opened) DEX file.
- *
- * @return the file name
- */
- public String getName() {
- return mFileName;
- }
-
- /**
- * Closes the DEX file.
- * <p>
- * This may not be able to release any resources. If classes from this
- * DEX file are still resident, the DEX file can't be unmapped.
- *
- * @throws IOException
- * if an I/O error occurs during closing the file, which
- * normally should not happen
- */
- public void close() throws IOException {
- guard.close();
- closeDexFile(mCookie);
- mCookie = 0;
- }
-
- /**
- * Loads a class. Returns the class on success, or a {@code null} reference
- * on failure.
- * <p>
- * If you are not calling this from a class loader, this is most likely not
- * going to do what you want. Use {@link Class#forName(String)} instead.
- * <p>
- * The method does not throw {@link ClassNotFoundException} if the class
- * isn't found because it isn't reasonable to throw exceptions wildly every
- * time a class is not found in the first DEX file we look at.
- *
- * @param name
- * the class name, which should look like "java/lang/String"
- *
- * @param loader
- * the class loader that tries to load the class (in most cases
- * the caller of the method
- *
- * @return the {@link Class} object representing the class, or {@code null}
- * if the class cannot be loaded
- */
- public Class loadClass(String name, ClassLoader loader) {
- String slashName = name.replace('.', '/');
- return loadClassBinaryName(slashName, loader);
- }
-
- /**
- * See {@link #loadClass(String, ClassLoader)}.
- *
- * This takes a "binary" class name to better match ClassLoader semantics.
- *
- * @hide
- */
- public Class loadClassBinaryName(String name, ClassLoader loader) {
- return defineClass(name, loader, mCookie);
- }
-
- private native static Class defineClass(String name, ClassLoader loader, int cookie);
-
- /**
- * Enumerate the names of the classes in this DEX file.
- *
- * @return an enumeration of names of classes contained in the DEX file, in
- * the usual internal form (like "java/lang/String").
- */
- public Enumeration<String> entries() {
- return new DFEnum(this);
- }
-
- /*
- * Helper class.
- */
- private class DFEnum implements Enumeration<String> {
- private int mIndex;
- private String[] mNameList;
-
- DFEnum(DexFile df) {
- mIndex = 0;
- mNameList = getClassNameList(mCookie);
- }
-
- public boolean hasMoreElements() {
- return (mIndex < mNameList.length);
- }
-
- public String nextElement() {
- return mNameList[mIndex++];
- }
- }
-
- /* return a String array with class names */
- native private static String[] getClassNameList(int cookie);
-
- /**
- * Called when the class is finalized. Makes sure the DEX file is closed.
- *
- * @throws IOException
- * if an I/O error occurs during closing the file, which
- * normally should not happen
- */
- @Override protected void finalize() throws Throwable {
- try {
- if (guard != null) {
- guard.warnIfOpen();
- }
- close();
- } finally {
- super.finalize();
- }
- }
-
- /*
- * Open a DEX file. The value returned is a magic VM cookie. On
- * failure, an IOException is thrown.
- */
- native private static int openDexFile(String sourceName, String outputName,
- int flags) throws IOException;
-
- /*
- * Close DEX file.
- */
- native private static void closeDexFile(int cookie);
-
- /**
- * Returns true if the VM believes that the apk/jar file is out of date
- * and should be passed through "dexopt" again.
- *
- * @param fileName the absolute path to the apk/jar file to examine.
- * @return true if dexopt should be called on the file, false otherwise.
- * @throws java.io.FileNotFoundException if fileName is not readable,
- * not a file, or not present.
- * @throws java.io.IOException if fileName is not a valid apk/jar file or
- * if problems occur while parsing it.
- * @throws java.lang.NullPointerException if fileName is null.
- * @throws dalvik.system.StaleDexCacheError if the optimized dex file
- * is stale but exists on a read-only partition.
- */
- native public static boolean isDexOptNeeded(String fileName)
- throws FileNotFoundException, IOException;
-}
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/dalvik/src/main/java/dalvik/system/DexPathList.java
deleted file mode 100644
index 3d9ee3e..0000000
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * Copyright (C) 2011 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 dalvik.system;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.regex.Pattern;
-import java.util.zip.ZipFile;
-import libcore.io.ErrnoException;
-import libcore.io.IoUtils;
-import libcore.io.Libcore;
-import libcore.io.StructStat;
-import static libcore.io.OsConstants.*;
-
-/**
- * A pair of lists of entries, associated with a {@code ClassLoader}.
- * One of the lists is a dex/resource path &mdash; typically referred
- * to as a "class path" &mdash; list, and the other names directories
- * containing native code libraries. Class path entries may be any of:
- * a {@code .jar} or {@code .zip} file containing an optional
- * top-level {@code classes.dex} file as well as arbitrary resources,
- * or a plain {@code .dex} file (with no possibility of associated
- * resources).
- *
- * <p>This class also contains methods to use these lists to look up
- * classes and resources.</p>
- */
-/*package*/ final class DexPathList {
- private static final String DEX_SUFFIX = ".dex";
- private static final String JAR_SUFFIX = ".jar";
- private static final String ZIP_SUFFIX = ".zip";
- private static final String APK_SUFFIX = ".apk";
-
- /** class definition context */
- private final ClassLoader definingContext;
-
- /**
- * List of dex/resource (class path) elements.
- * Should be called pathElements, but the Facebook app uses reflection
- * to modify 'dexElements' (http://b/7726934).
- */
- private final Element[] dexElements;
-
- /** List of native library directories. */
- private final File[] nativeLibraryDirectories;
-
- /**
- * Constructs an instance.
- *
- * @param definingContext the context in which any as-yet unresolved
- * classes should be defined
- * @param dexPath list of dex/resource path elements, separated by
- * {@code File.pathSeparator}
- * @param libraryPath list of native library directory path elements,
- * separated by {@code File.pathSeparator}
- * @param optimizedDirectory directory where optimized {@code .dex} files
- * should be found and written to, or {@code null} to use the default
- * system directory for same
- */
- public DexPathList(ClassLoader definingContext, String dexPath,
- String libraryPath, File optimizedDirectory) {
- if (definingContext == null) {
- throw new NullPointerException("definingContext == null");
- }
-
- if (dexPath == null) {
- throw new NullPointerException("dexPath == null");
- }
-
- if (optimizedDirectory != null) {
- if (!optimizedDirectory.exists()) {
- throw new IllegalArgumentException(
- "optimizedDirectory doesn't exist: "
- + optimizedDirectory);
- }
-
- if (!(optimizedDirectory.canRead()
- && optimizedDirectory.canWrite())) {
- throw new IllegalArgumentException(
- "optimizedDirectory not readable/writable: "
- + optimizedDirectory);
- }
- }
-
- this.definingContext = definingContext;
- this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory);
- this.nativeLibraryDirectories = splitLibraryPath(libraryPath);
- }
-
- @Override public String toString() {
- return "DexPathList[" + Arrays.toString(dexElements) +
- ",nativeLibraryDirectories=" + Arrays.toString(nativeLibraryDirectories) + "]";
- }
-
- /**
- * For BaseDexClassLoader.getLdLibraryPath.
- */
- public File[] getNativeLibraryDirectories() {
- return nativeLibraryDirectories;
- }
-
- /**
- * Splits the given dex path string into elements using the path
- * separator, pruning out any elements that do not refer to existing
- * and readable files. (That is, directories are not included in the
- * result.)
- */
- private static ArrayList<File> splitDexPath(String path) {
- return splitPaths(path, null, false);
- }
-
- /**
- * Splits the given library directory path string into elements
- * using the path separator ({@code File.pathSeparator}, which
- * defaults to {@code ":"} on Android, appending on the elements
- * from the system library path, and pruning out any elements that
- * do not refer to existing and readable directories.
- */
- private static File[] splitLibraryPath(String path) {
- /*
- * Native libraries may exist in both the system and
- * application library paths, and we use this search order:
- *
- * 1. this class loader's library path for application
- * libraries
- * 2. the VM's library path from the system
- * property for system libraries
- *
- * This order was reversed prior to Gingerbread; see http://b/2933456.
- */
- ArrayList<File> result = splitPaths(
- path, System.getProperty("java.library.path", "."), true);
- return result.toArray(new File[result.size()]);
- }
-
- /**
- * Splits the given path strings into file elements using the path
- * separator, combining the results and filtering out elements
- * that don't exist, aren't readable, or aren't either a regular
- * file or a directory (as specified). Either string may be empty
- * or {@code null}, in which case it is ignored. If both strings
- * are empty or {@code null}, or all elements get pruned out, then
- * this returns a zero-element list.
- */
- private static ArrayList<File> splitPaths(String path1, String path2,
- boolean wantDirectories) {
- ArrayList<File> result = new ArrayList<File>();
-
- splitAndAdd(path1, wantDirectories, result);
- splitAndAdd(path2, wantDirectories, result);
- return result;
- }
-
- /**
- * Helper for {@link #splitPaths}, which does the actual splitting
- * and filtering and adding to a result.
- */
- private static void splitAndAdd(String searchPath, boolean directoriesOnly,
- ArrayList<File> resultList) {
- if (searchPath == null) {
- return;
- }
- for (String path : searchPath.split(":")) {
- try {
- StructStat sb = Libcore.os.stat(path);
- if (!directoriesOnly || S_ISDIR(sb.st_mode)) {
- resultList.add(new File(path));
- }
- } catch (ErrnoException ignored) {
- }
- }
- }
-
- /**
- * Makes an array of dex/resource path elements, one per element of
- * the given array.
- */
- private static Element[] makeDexElements(ArrayList<File> files,
- File optimizedDirectory) {
- ArrayList<Element> elements = new ArrayList<Element>();
-
- /*
- * Open all files and load the (direct or contained) dex files
- * up front.
- */
- for (File file : files) {
- File zip = null;
- DexFile dex = null;
- String name = file.getName();
-
- if (name.endsWith(DEX_SUFFIX)) {
- // Raw dex file (not inside a zip/jar).
- try {
- dex = loadDexFile(file, optimizedDirectory);
- } catch (IOException ex) {
- System.logE("Unable to load dex file: " + file, ex);
- }
- } else if (name.endsWith(APK_SUFFIX) || name.endsWith(JAR_SUFFIX)
- || name.endsWith(ZIP_SUFFIX)) {
- zip = file;
-
- try {
- dex = loadDexFile(file, optimizedDirectory);
- } catch (IOException ignored) {
- /*
- * IOException might get thrown "legitimately" by
- * the DexFile constructor if the zip file turns
- * out to be resource-only (that is, no
- * classes.dex file in it). Safe to just ignore
- * the exception here, and let dex == null.
- */
- }
- } else if (file.isDirectory()) {
- // We support directories for looking up resources.
- // This is only useful for running libcore tests.
- elements.add(new Element(file, true, null, null));
- } else {
- System.logW("Unknown file type for: " + file);
- }
-
- if ((zip != null) || (dex != null)) {
- elements.add(new Element(file, false, zip, dex));
- }
- }
-
- return elements.toArray(new Element[elements.size()]);
- }
-
- /**
- * Constructs a {@code DexFile} instance, as appropriate depending
- * on whether {@code optimizedDirectory} is {@code null}.
- */
- private static DexFile loadDexFile(File file, File optimizedDirectory)
- throws IOException {
- if (optimizedDirectory == null) {
- return new DexFile(file);
- } else {
- String optimizedPath = optimizedPathFor(file, optimizedDirectory);
- return DexFile.loadDex(file.getPath(), optimizedPath, 0);
- }
- }
-
- /**
- * Converts a dex/jar file path and an output directory to an
- * output file path for an associated optimized dex file.
- */
- private static String optimizedPathFor(File path,
- File optimizedDirectory) {
- /*
- * Get the filename component of the path, and replace the
- * suffix with ".dex" if that's not already the suffix.
- *
- * We don't want to use ".odex", because the build system uses
- * that for files that are paired with resource-only jar
- * files. If the VM can assume that there's no classes.dex in
- * the matching jar, it doesn't need to open the jar to check
- * for updated dependencies, providing a slight performance
- * boost at startup. The use of ".dex" here matches the use on
- * files in /data/dalvik-cache.
- */
- String fileName = path.getName();
- if (!fileName.endsWith(DEX_SUFFIX)) {
- int lastDot = fileName.lastIndexOf(".");
- if (lastDot < 0) {
- fileName += DEX_SUFFIX;
- } else {
- StringBuilder sb = new StringBuilder(lastDot + 4);
- sb.append(fileName, 0, lastDot);
- sb.append(DEX_SUFFIX);
- fileName = sb.toString();
- }
- }
-
- File result = new File(optimizedDirectory, fileName);
- return result.getPath();
- }
-
- /**
- * Finds the named class in one of the dex files pointed at by
- * this instance. This will find the one in the earliest listed
- * path element. If the class is found but has not yet been
- * defined, then this method will define it in the defining
- * context that this instance was constructed with.
- *
- * @return the named class or {@code null} if the class is not
- * found in any of the dex files
- */
- public Class findClass(String name) {
- for (Element element : dexElements) {
- DexFile dex = element.dexFile;
-
- if (dex != null) {
- Class clazz = dex.loadClassBinaryName(name, definingContext);
- if (clazz != null) {
- return clazz;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Finds the named resource in one of the zip/jar files pointed at
- * by this instance. This will find the one in the earliest listed
- * path element.
- *
- * @return a URL to the named resource or {@code null} if the
- * resource is not found in any of the zip/jar files
- */
- public URL findResource(String name) {
- for (Element element : dexElements) {
- URL url = element.findResource(name);
- if (url != null) {
- return url;
- }
- }
-
- return null;
- }
-
- /**
- * Finds all the resources with the given name, returning an
- * enumeration of them. If there are no resources with the given
- * name, then this method returns an empty enumeration.
- */
- public Enumeration<URL> findResources(String name) {
- ArrayList<URL> result = new ArrayList<URL>();
-
- for (Element element : dexElements) {
- URL url = element.findResource(name);
- if (url != null) {
- result.add(url);
- }
- }
-
- return Collections.enumeration(result);
- }
-
- /**
- * Finds the named native code library on any of the library
- * directories pointed at by this instance. This will find the
- * one in the earliest listed directory, ignoring any that are not
- * readable regular files.
- *
- * @return the complete path to the library or {@code null} if no
- * library was found
- */
- public String findLibrary(String libraryName) {
- String fileName = System.mapLibraryName(libraryName);
- for (File directory : nativeLibraryDirectories) {
- String path = new File(directory, fileName).getPath();
- if (IoUtils.canOpenReadOnly(path)) {
- return path;
- }
- }
- return null;
- }
-
- /**
- * Element of the dex/resource file path
- */
- /*package*/ static class Element {
- private final File file;
- private final boolean isDirectory;
- private final File zip;
- private final DexFile dexFile;
-
- private ZipFile zipFile;
- private boolean initialized;
-
- public Element(File file, boolean isDirectory, File zip, DexFile dexFile) {
- this.file = file;
- this.isDirectory = isDirectory;
- this.zip = zip;
- this.dexFile = dexFile;
- }
-
- @Override public String toString() {
- if (isDirectory) {
- return "directory \"" + file + "\"";
- } else if (zip != null) {
- return "zip file \"" + zip + "\"";
- } else {
- return "dex file \"" + dexFile + "\"";
- }
- }
-
- public synchronized void maybeInit() {
- if (initialized) {
- return;
- }
-
- initialized = true;
-
- if (isDirectory || zip == null) {
- return;
- }
-
- try {
- zipFile = new ZipFile(zip);
- } catch (IOException ioe) {
- /*
- * Note: ZipException (a subclass of IOException)
- * might get thrown by the ZipFile constructor
- * (e.g. if the file isn't actually a zip/jar
- * file).
- */
- System.logE("Unable to open zip file: " + file, ioe);
- zipFile = null;
- }
- }
-
- public URL findResource(String name) {
- maybeInit();
-
- // We support directories so we can run tests and/or legacy code
- // that uses Class.getResource.
- if (isDirectory) {
- File resourceFile = new File(file, name);
- if (resourceFile.exists()) {
- try {
- return resourceFile.toURI().toURL();
- } catch (MalformedURLException ex) {
- throw new RuntimeException(ex);
- }
- }
- }
-
- if (zipFile == null || zipFile.getEntry(name) == null) {
- /*
- * Either this element has no zip/jar file (first
- * clause), or the zip/jar file doesn't have an entry
- * for the given name (second clause).
- */
- return null;
- }
-
- try {
- /*
- * File.toURL() is compliant with RFC 1738 in
- * always creating absolute path names. If we
- * construct the URL by concatenating strings, we
- * might end up with illegal URLs for relative
- * names.
- */
- return new URL("jar:" + file.toURL() + "!/" + name);
- } catch (MalformedURLException ex) {
- throw new RuntimeException(ex);
- }
- }
- }
-}