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