Home | History | Annotate | Download | only in system
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package dalvik.system;
     18 
     19 import java.io.File;
     20 import java.net.URL;
     21 import java.util.Enumeration;
     22 
     23 /**
     24  * Base class for common functionality between various dex-based
     25  * {@link ClassLoader} implementations.
     26  */
     27 public class BaseDexClassLoader extends ClassLoader {
     28     /** originally specified path (just used for {@code toString()}) */
     29     private final String originalPath;
     30 
     31     /** structured lists of path elements */
     32     private final DexPathList pathList;
     33 
     34     /**
     35      * Constructs an instance.
     36      *
     37      * @param dexPath the list of jar/apk files containing classes and
     38      * resources, delimited by {@code File.pathSeparator}, which
     39      * defaults to {@code ":"} on Android
     40      * @param optimizedDirectory directory where optimized dex files
     41      * should be written; may be {@code null}
     42      * @param libraryPath the list of directories containing native
     43      * libraries, delimited by {@code File.pathSeparator}; may be
     44      * {@code null}
     45      * @param parent the parent class loader
     46      */
     47     public BaseDexClassLoader(String dexPath, File optimizedDirectory,
     48             String libraryPath, ClassLoader parent) {
     49         super(parent);
     50 
     51         this.originalPath = dexPath;
     52         this.pathList =
     53             new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
     54     }
     55 
     56     @Override
     57     protected Class<?> findClass(String name) throws ClassNotFoundException {
     58         Class clazz = pathList.findClass(name);
     59 
     60         if (clazz == null) {
     61             throw new ClassNotFoundException(name);
     62         }
     63 
     64         return clazz;
     65     }
     66 
     67     @Override
     68     protected URL findResource(String name) {
     69         return pathList.findResource(name);
     70     }
     71 
     72     @Override
     73     protected Enumeration<URL> findResources(String name) {
     74         return pathList.findResources(name);
     75     }
     76 
     77     @Override
     78     public String findLibrary(String name) {
     79         return pathList.findLibrary(name);
     80     }
     81 
     82     /**
     83      * Returns package information for the given package.
     84      * Unfortunately, instances of this class don't really have this
     85      * information, and as a non-secure {@code ClassLoader}, it isn't
     86      * even required to, according to the spec. Yet, we want to
     87      * provide it, in order to make all those hopeful callers of
     88      * {@code myClass.getPackage().getName()} happy. Thus we construct
     89      * a {@code Package} object the first time it is being requested
     90      * and fill most of the fields with dummy values. The {@code
     91      * Package} object is then put into the {@code ClassLoader}'s
     92      * package cache, so we see the same one next time. We don't
     93      * create {@code Package} objects for {@code null} arguments or
     94      * for the default package.
     95      *
     96      * <p>There is a limited chance that we end up with multiple
     97      * {@code Package} objects representing the same package: It can
     98      * happen when when a package is scattered across different JAR
     99      * files which were loaded by different {@code ClassLoader}
    100      * instances. This is rather unlikely, and given that this whole
    101      * thing is more or less a workaround, probably not worth the
    102      * effort to address.
    103      *
    104      * @param name the name of the class
    105      * @return the package information for the class, or {@code null}
    106      * if there is no package information available for it
    107      */
    108     @Override
    109     protected synchronized Package getPackage(String name) {
    110         if (name != null && !name.isEmpty()) {
    111             Package pack = super.getPackage(name);
    112 
    113             if (pack == null) {
    114                 pack = definePackage(name, "Unknown", "0.0", "Unknown",
    115                         "Unknown", "0.0", "Unknown", null);
    116             }
    117 
    118             return pack;
    119         }
    120 
    121         return null;
    122     }
    123 
    124     @Override
    125     public String toString() {
    126         return getClass().getName() + "[" + originalPath + "]";
    127     }
    128 }
    129