diff options
author | Brian Carlstrom <bdc@google.com> | 2013-05-13 10:19:39 -0700 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2013-05-13 12:53:43 -0700 |
commit | 895bba44ff59d2225532a1fe9842c8b9a70a9f9a (patch) | |
tree | 55e6cfe041d8c68afd7adb97d0c2f52e80eeb902 /dalvik | |
parent | 8245506ebe0cbeba47c99e1e109c8da31c1626bc (diff) | |
download | libcore-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.java | 132 | ||||
-rw-r--r-- | dalvik/src/main/java/dalvik/system/DexFile.java | 296 | ||||
-rw-r--r-- | dalvik/src/main/java/dalvik/system/DexPathList.java | 473 |
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 — typically referred - * to as a "class path" — 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); - } - } - } -} |