    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 *  Unless required by applicable law or agreed to in writing, software
    012 *  distributed under the License is distributed on an "AS IS" BASIS,
    013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 *  See the License for the specific language governing permissions and
    015 *  limitations under the License.
    016 */
    017package org.apache.bcel;
    018
    019import java.io.IOException;
    020
    021import org.apache.bcel.classfile.JavaClass;
    022import org.apache.bcel.util.ClassPath;
    023import org.apache.bcel.util.SyntheticRepository;
    024
    025/**
    026 * The repository maintains informations about class interdependencies, e.g., whether a class is a sub-class of another.
    027 * Delegates actual class loading to SyntheticRepository with current class path by default.
    028 *
    029 * @see org.apache.bcel.util.Repository
    030 * @see SyntheticRepository
    031 */
    032public abstract class Repository {
    033
    034    private static org.apache.bcel.util.Repository repository = SyntheticRepository.getInstance();
    035
    036    /**
    037     * Adds clazz to repository if there isn't an equally named class already in there.
    038     *
    039     * @return old entry in repository
    040     */
    041    public static JavaClass addClass(final JavaClass clazz) {
    042        final JavaClass old = repository.findClass(clazz.getClassName());
    043        repository.storeClass(clazz);
    044        return old;
    045    }
    046
    047    /**
    048     * Clears the repository.
    049     */
    050    public static void clearCache() {
    051        repository.clear();
    052    }
    053
    054    /**
    055     * @return all interfaces implemented by class and its super classes and the interfaces that those interfaces extend,
    056     *         and so on. (Some people call this a transitive hull).
    057     * @throws ClassNotFoundException if any of the class's superclasses or superinterfaces can't be found
    058     */
    059    public static JavaClass[] getInterfaces(final JavaClass clazz) throws ClassNotFoundException {
    060        return clazz.getAllInterfaces();
    061    }
    062
    063    /**
    064     * @return all interfaces implemented by class and its super classes and the interfaces that extend those interfaces,
    065     *         and so on
    066     * @throws ClassNotFoundException if the named class can't be found, or if any of its superclasses or superinterfaces
    067     *         can't be found
    068     */
    069    public static JavaClass[] getInterfaces(final String className) throws ClassNotFoundException {
    070        return getInterfaces(lookupClass(className));
    071    }
    072
    073    /**
    074     * @return currently used repository instance
    075     */
    076    public static org.apache.bcel.util.Repository getRepository() {
    077        return repository;
    078    }
    079
    080    /**
    081     * @return list of super classes of clazz in ascending order, i.e., Object is always the last element
    082     * @throws ClassNotFoundException if any of the superclasses can't be found
    083     */
    084    public static JavaClass[] getSuperClasses(final JavaClass clazz) throws ClassNotFoundException {
    085        return clazz.getSuperClasses();
    086    }
    087
    088    /**
    089     * @return list of super classes of clazz in ascending order, i.e., Object is always the last element.
    090     * @throws ClassNotFoundException if the named class or any of its superclasses can't be found
    091     */
    092    public static JavaClass[] getSuperClasses(final String className) throws ClassNotFoundException {
    093        return getSuperClasses(lookupClass(className));
    094    }
    095
    096    /**
    097     * @return true, if clazz is an implementation of interface inter
    098     * @throws ClassNotFoundException if any superclasses or superinterfaces of clazz can't be found
    099     */
    100    public static boolean implementationOf(final JavaClass clazz, final JavaClass inter) throws ClassNotFoundException {
    101        return clazz.implementationOf(inter);
    102    }
    103
    104    /**
    105     * @return true, if clazz is an implementation of interface inter
    106     * @throws ClassNotFoundException if inter or any superclasses or superinterfaces of clazz can't be found
    107     */
    108    public static boolean implementationOf(final JavaClass clazz, final String inter) throws ClassNotFoundException {
    109        return implementationOf(clazz, lookupClass(inter));
    110    }
    111
    112    /**
    113     * @return true, if clazz is an implementation of interface inter
    114     * @throws ClassNotFoundException if clazz or any superclasses or superinterfaces of clazz can't be found
    115     */
    116    public static boolean implementationOf(final String clazz, final JavaClass inter) throws ClassNotFoundException {
    117        return implementationOf(lookupClass(clazz), inter);
    118    }
    119
    120    /**
    121     * @return true, if clazz is an implementation of interface inter
    122     * @throws ClassNotFoundException if clazz, inter, or any superclasses or superinterfaces of clazz can't be found
    123     */
    124    public static boolean implementationOf(final String clazz, final String inter) throws ClassNotFoundException {
    125        return implementationOf(lookupClass(clazz), lookupClass(inter));
    126    }
    127
    128    /**
    129     * Equivalent to runtime "instanceof" operator.
    130     *
    131     * @return true, if clazz is an instance of superclass
    132     * @throws ClassNotFoundException if any superclasses or superinterfaces of clazz can't be found
    133     */
    134    public static boolean instanceOf(final JavaClass clazz, final JavaClass superclass) throws ClassNotFoundException {
    135        return clazz.instanceOf(superclass);
    136    }
    137
    138    /**
    139     * @return true, if clazz is an instance of superclass
    140     * @throws ClassNotFoundException if superclass can't be found
    141     */
    142    public static boolean instanceOf(final JavaClass clazz, final String superclass) throws ClassNotFoundException {
    143        return instanceOf(clazz, lookupClass(superclass));
    144    }
    145
    146    /**
    147     * @return true, if clazz is an instance of superclass
    148     * @throws ClassNotFoundException if clazz can't be found
    149     */
    150    public static boolean instanceOf(final String clazz, final JavaClass superclass) throws ClassNotFoundException {
    151        return instanceOf(lookupClass(clazz), superclass);
    152    }
    153
    154    /**
    155     * @return true, if clazz is an instance of superclass
    156     * @throws ClassNotFoundException if either clazz or superclass can't be found
    157     */
    158    public static boolean instanceOf(final String clazz, final String superclass) throws ClassNotFoundException {
    159        return instanceOf(lookupClass(clazz), lookupClass(superclass));
    160    }
    161
    162    /**
    163     * Tries to find class source using the internal repository instance.
    164     *
    165     * @see Class
    166     * @return JavaClass object for given runtime class
    167     * @throws ClassNotFoundException if the class could not be found or parsed correctly
    168     */
    169    public static JavaClass lookupClass(final Class<?> clazz) throws ClassNotFoundException {
    170        return repository.loadClass(clazz);
    171    }
    172
    173    /**
    174     * Lookups class somewhere found on your CLASSPATH, or whereever the repository instance looks for it.
    175     *
    176     * @return class object for given fully qualified class name
    177     * @throws ClassNotFoundException if the class could not be found or parsed correctly
    178     */
    179    public static JavaClass lookupClass(final String className) throws ClassNotFoundException {
    180        return repository.loadClass(className);
    181    }
    182
    183    /**
    184     * @return class file object for given Java class by looking on the system class path; returns null if the class file
    185     *         can't be found
    186     */
    187    public static ClassPath.ClassFile lookupClassFile(final String className) {
    188        try (ClassPath path = repository.getClassPath()) {
    189            return path == null ? null : path.getClassFile(className);
    190        } catch (final IOException e) {
    191            return null;
    192        }
    193    }
    194
    195    /**
    196     * Removes given class from repository.
    197     */
    198    public static void removeClass(final JavaClass clazz) {
    199        repository.removeClass(clazz);
    200    }
    201
    202    /**
    203     * Removes class with given (fully qualified) name from repository.
    204     */
    205    public static void removeClass(final String clazz) {
    206        repository.removeClass(repository.findClass(clazz));
    207    }
    208
    209    /**
    210     * Sets repository instance to be used for class loading
    211     */
    212    public static void setRepository(final org.apache.bcel.util.Repository rep) {
    213        repository = rep;
    214    }
    215}