12cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom/*
22cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Copyright (C) 2011 The Android Open Source Project
32cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom *
42cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
52cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * you may not use this file except in compliance with the License.
62cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * You may obtain a copy of the License at
72cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom *
82cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
92cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom *
102cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Unless required by applicable law or agreed to in writing, software
112cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
122cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * See the License for the specific language governing permissions and
142cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * limitations under the License.
152cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */
162cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
172cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrompackage dalvik.system;
182cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
192cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.io.File;
202cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.net.URL;
212cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.util.ArrayList;
222cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.util.Enumeration;
232cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.util.List;
242cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
252cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom/**
262cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Base class for common functionality between various dex-based
272cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * {@link ClassLoader} implementations.
282cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */
292cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrompublic class BaseDexClassLoader extends ClassLoader {
302cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    private final DexPathList pathList;
312cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
322cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    /**
332cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * Constructs an instance.
342cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     *
352cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * @param dexPath the list of jar/apk files containing classes and
362cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * resources, delimited by {@code File.pathSeparator}, which
372cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * defaults to {@code ":"} on Android
382cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * @param optimizedDirectory directory where optimized dex files
392cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * should be written; may be {@code null}
402cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * @param libraryPath the list of directories containing native
412cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * libraries, delimited by {@code File.pathSeparator}; may be
422cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * {@code null}
432cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * @param parent the parent class loader
442cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     */
452cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    public BaseDexClassLoader(String dexPath, File optimizedDirectory,
462cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            String libraryPath, ClassLoader parent) {
472cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        super(parent);
482cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
492cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    }
502cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
512cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    @Override
522cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    protected Class<?> findClass(String name) throws ClassNotFoundException {
532cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
542cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        Class c = pathList.findClass(name, suppressedExceptions);
552cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        if (c == null) {
562cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
572cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            for (Throwable t : suppressedExceptions) {
582cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom                cnfe.addSuppressed(t);
592cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            }
602cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            throw cnfe;
612cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        }
622cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        return c;
632cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    }
642cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
652cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    @Override
662cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    protected URL findResource(String name) {
672cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        return pathList.findResource(name);
682cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    }
692cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
702cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    @Override
712cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    protected Enumeration<URL> findResources(String name) {
722cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        return pathList.findResources(name);
732cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    }
742cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
752cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    @Override
762cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    public String findLibrary(String name) {
772cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        return pathList.findLibrary(name);
782cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    }
792cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
802cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    /**
812cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * Returns package information for the given package.
822cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * Unfortunately, instances of this class don't really have this
832cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * information, and as a non-secure {@code ClassLoader}, it isn't
842cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * even required to, according to the spec. Yet, we want to
852cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * provide it, in order to make all those hopeful callers of
862cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * {@code myClass.getPackage().getName()} happy. Thus we construct
872cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * a {@code Package} object the first time it is being requested
882cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * and fill most of the fields with dummy values. The {@code
892cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * Package} object is then put into the {@code ClassLoader}'s
902cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * package cache, so we see the same one next time. We don't
912cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * create {@code Package} objects for {@code null} arguments or
922cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * for the default package.
932cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     *
942cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * <p>There is a limited chance that we end up with multiple
952cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * {@code Package} objects representing the same package: It can
962cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * happen when when a package is scattered across different JAR
972cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * files which were loaded by different {@code ClassLoader}
982cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * instances. This is rather unlikely, and given that this whole
992cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * thing is more or less a workaround, probably not worth the
1002cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * effort to address.
1012cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     *
1022cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * @param name the name of the class
1032cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * @return the package information for the class, or {@code null}
1042cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * if there is no package information available for it
1052cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     */
1062cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    @Override
1072cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    protected synchronized Package getPackage(String name) {
1082cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        if (name != null && !name.isEmpty()) {
1092cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            Package pack = super.getPackage(name);
1102cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
1112cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            if (pack == null) {
1122cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom                pack = definePackage(name, "Unknown", "0.0", "Unknown",
1132cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom                        "Unknown", "0.0", "Unknown", null);
1142cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            }
1152cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
1162cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            return pack;
1172cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        }
1182cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
1192cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        return null;
1202cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    }
1212cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
1222cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    /**
1232cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     * @hide
1242cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom     */
1252cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    public String getLdLibraryPath() {
1262cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        StringBuilder result = new StringBuilder();
1272cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        for (File directory : pathList.getNativeLibraryDirectories()) {
1282cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            if (result.length() > 0) {
1292cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom                result.append(':');
1302cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            }
1312cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom            result.append(directory);
1322cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        }
1332cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom
134f38cae4f22e46c49f5fba94e6e0579dedd2d8fd1Dmitriy Ivanov        return result.toString();
1357694b783f48e2cc57928b61c84fd90311cb0c35aDmitriy Ivanov    }
1367694b783f48e2cc57928b61c84fd90311cb0c35aDmitriy Ivanov
1372cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    @Override public String toString() {
1382cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom        return getClass().getName() + "[" + pathList + "]";
1392cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom    }
1402cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom}
141