    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 *   https://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019package org.apache.bcel;
    020
    021import java.io.IOException;
    022
    023import org.apache.bcel.classfile.JavaClass;
    024import org.apache.bcel.util.ClassPath;
    025import org.apache.bcel.util.SyntheticRepository;
    026
    027/**
    028 * The repository maintains informations about class interdependencies, for example, whether a class is a sub-class of another.
    029 * Delegates actual class loading to SyntheticRepository with current class path by default.
    030 *
    031 * @see org.apache.bcel.util.Repository
    032 * @see SyntheticRepository
    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, that is, 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, that is, 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 superclass.
    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 superclass) throws ClassNotFoundException {
    137        return clazz.instanceOf(superclass);
    138    }
    139
    140    /**
    141     * @return true, if clazz is an instance of superclass.
    142     * @throws ClassNotFoundException if superclass can't be found
    143     */
    144    public static boolean instanceOf(final JavaClass clazz, final String superclass) throws ClassNotFoundException {
    145        return instanceOf(clazz, lookupClass(superclass));
    146    }
    147
    148    /**
    149     * @return true, if clazz is an instance of superclass.
    150     * @throws ClassNotFoundException if clazz can't be found
    151     */
    152    public static boolean instanceOf(final String clazz, final JavaClass superclass) throws ClassNotFoundException {
    153        return instanceOf(lookupClass(clazz), superclass);
    154    }
    155
    156    /**
    157     * @return true, if clazz is an instance of superclass.
    158     * @throws ClassNotFoundException if either clazz or superclass can't be found
    159     */
    160    public static boolean instanceOf(final String clazz, final String superclass) throws ClassNotFoundException {
    161        return instanceOf(lookupClass(clazz), lookupClass(superclass));
    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 (ClassPath path = repository.getClassPath()) {
    191            return path == null ? null : path.getClassFile(className);
    192        } catch (final IOException e) {
    193            return null;
    194        }
    195    }
    196
    197    /**
    198     * Removes given class from repository.
    199     */
    200    public static void removeClass(final JavaClass clazz) {
    201        repository.removeClass(clazz);
    202    }
    203
    204    /**
    205     * Removes class with given (fully qualified) name from repository.
    206     */
    207    public static void removeClass(final String clazz) {
    208        repository.removeClass(repository.findClass(clazz));
    209    }
    210
    211    /**
    212     * Sets repository instance to be used for class loading
    213     */
    214    public static void setRepository(final org.apache.bcel.util.Repository rep) {
    215        repository = rep;
    216    }
    217}