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     * @param clazz The class to add.
042     * @return old entry in repository.
043     */
044    public static JavaClass addClass(final JavaClass clazz) {
045        final JavaClass old = repository.findClass(clazz.getClassName());
046        repository.storeClass(clazz);
047        return old;
048    }
049
050    /**
051     * Clears the repository.
052     */
053    public static void clearCache() {
054        repository.clear();
055    }
056
057    /**
058     * Gets all interfaces implemented by the class.
059     *
060     * @param clazz The class.
061     * @return all interfaces implemented by class and its super classes and the interfaces that those interfaces extend,
062     *         and so on. (Some people call this a transitive hull).
063     * @throws ClassNotFoundException Thrown if any of the class's superclasses or superinterfaces can't be found.
064     */
065    public static JavaClass[] getInterfaces(final JavaClass clazz) throws ClassNotFoundException {
066        return clazz.getAllInterfaces();
067    }
068
069    /**
070     * Gets all interfaces implemented by the class.
071     *
072     * @param className The class name.
073     * @return all interfaces implemented by class and its super classes and the interfaces that extend those interfaces,
074     *         and so on.
075     * @throws ClassNotFoundException Thrown if the named class can't be found, or if any of its superclasses or superinterfaces
076     *         can't be found.
077     */
078    public static JavaClass[] getInterfaces(final String className) throws ClassNotFoundException {
079        return getInterfaces(lookupClass(className));
080    }
081
082    /**
083     * Gets the currently used repository instance.
084     *
085     * @return currently used repository instance.
086     */
087    public static org.apache.bcel.util.Repository getRepository() {
088        return repository;
089    }
090
091    /**
092     * Gets the list of super classes.
093     *
094     * @param clazz The class.
095     * @return list of super classes of clazz in ascending order, that is, Object is always the last element.
096     * @throws ClassNotFoundException Thrown if any of the superclasses can't be found.
097     */
098    public static JavaClass[] getSuperClasses(final JavaClass clazz) throws ClassNotFoundException {
099        return clazz.getSuperClasses();
100    }
101
102    /**
103     * Gets the list of super classes.
104     *
105     * @param className The class name.
106     * @return list of super classes of clazz in ascending order, that is, Object is always the last element.
107     * @throws ClassNotFoundException Thrown if the named class or any of its superclasses can't be found.
108     */
109    public static JavaClass[] getSuperClasses(final String className) throws ClassNotFoundException {
110        return getSuperClasses(lookupClass(className));
111    }
112
113    /**
114     * Tests if clazz is an implementation of interface inter.
115     *
116     * @param clazz The class to test.
117     * @param inter The interface.
118     * @return true, if clazz is an implementation of interface inter.
119     * @throws ClassNotFoundException Thrown if any superclasses or superinterfaces of clazz can't be found.
120     */
121    public static boolean implementationOf(final JavaClass clazz, final JavaClass inter) throws ClassNotFoundException {
122        return clazz.implementationOf(inter);
123    }
124
125    /**
126     * Tests if clazz is an implementation of interface inter.
127     *
128     * @param clazz The class to test.
129     * @param inter The interface name.
130     * @return true, if clazz is an implementation of interface inter.
131     * @throws ClassNotFoundException Thrown if inter or any superclasses or superinterfaces of clazz can't be found.
132     */
133    public static boolean implementationOf(final JavaClass clazz, final String inter) throws ClassNotFoundException {
134        return implementationOf(clazz, lookupClass(inter));
135    }
136
137    /**
138     * Tests if clazz is an implementation of interface inter.
139     *
140     * @param clazz The class name to test.
141     * @param inter The interface.
142     * @return true, if clazz is an implementation of interface inter.
143     * @throws ClassNotFoundException Thrown if clazz or any superclasses or superinterfaces of clazz can't be found.
144     */
145    public static boolean implementationOf(final String clazz, final JavaClass inter) throws ClassNotFoundException {
146        return implementationOf(lookupClass(clazz), inter);
147    }
148
149    /**
150     * Tests if clazz is an implementation of interface inter.
151     *
152     * @param clazz The class name to test.
153     * @param inter The interface name.
154     * @return true, if clazz is an implementation of interface inter.
155     * @throws ClassNotFoundException Thrown if clazz, inter, or any superclasses or superinterfaces of clazz can't be found.
156     */
157    public static boolean implementationOf(final String clazz, final String inter) throws ClassNotFoundException {
158        return implementationOf(lookupClass(clazz), lookupClass(inter));
159    }
160
161    /**
162     * Equivalent to runtime "instanceof" operator.
163     *
164     * @param clazz The class to test.
165     * @param superclass The superclass.
166     * @return true, if clazz is an instance of superclass.
167     * @throws ClassNotFoundException Thrown if any superclasses or superinterfaces of clazz can't be found.
168     */
169    public static boolean instanceOf(final JavaClass clazz, final JavaClass superclass) throws ClassNotFoundException {
170        return clazz.instanceOf(superclass);
171    }
172
173    /**
174     * Tests if clazz is an instance of superclass.
175     *
176     * @param clazz The class to test.
177     * @param superclass The superclass name.
178     * @return true, if clazz is an instance of superclass.
179     * @throws ClassNotFoundException Thrown if superclass can't be found.
180     */
181    public static boolean instanceOf(final JavaClass clazz, final String superclass) throws ClassNotFoundException {
182        return instanceOf(clazz, lookupClass(superclass));
183    }
184
185    /**
186     * Tests if clazz is an instance of superclass.
187     *
188     * @param clazz The class name to test.
189     * @param superclass The superclass.
190     * @return true, if clazz is an instance of superclass.
191     * @throws ClassNotFoundException Thrown if clazz can't be found.
192     */
193    public static boolean instanceOf(final String clazz, final JavaClass superclass) throws ClassNotFoundException {
194        return instanceOf(lookupClass(clazz), superclass);
195    }
196
197    /**
198     * Tests if clazz is an instance of superclass.
199     *
200     * @param clazz The class name to test.
201     * @param superclass The superclass name.
202     * @return true, if clazz is an instance of superclass.
203     * @throws ClassNotFoundException Thrown if either clazz or superclass can't be found.
204     */
205    public static boolean instanceOf(final String clazz, final String superclass) throws ClassNotFoundException {
206        return instanceOf(lookupClass(clazz), lookupClass(superclass));
207    }
208
209    /**
210     * Tries to find class source using the internal repository instance.
211     *
212     * @param clazz The class.
213     * @see Class
214     * @return JavaClass object for given runtime class.
215     * @throws ClassNotFoundException Thrown if the class could not be found or parsed correctly.
216     */
217    public static JavaClass lookupClass(final Class<?> clazz) throws ClassNotFoundException {
218        return repository.loadClass(clazz);
219    }
220
221    /**
222     * Lookups class somewhere found on your CLASSPATH, or wherever the repository instance looks for it.
223     *
224     * @param className The class name.
225     * @return class object for given fully qualified class name.
226     * @throws ClassNotFoundException Thrown if the class could not be found or parsed correctly.
227     */
228    public static JavaClass lookupClass(final String className) throws ClassNotFoundException {
229        return repository.loadClass(className);
230    }
231
232    /**
233     * Looks up the class file.
234     *
235     * @param className The class name.
236     * @return class file object for given Java class by looking on the system class path; returns null if the class file
237     *         can't be found.
238     */
239    public static ClassPath.ClassFile lookupClassFile(final String className) {
240        try (ClassPath path = repository.getClassPath()) {
241            return path == null ? null : path.getClassFile(className);
242        } catch (final IOException e) {
243            return null;
244        }
245    }
246
247    /**
248     * Removes given class from repository.
249     *
250     * @param clazz The class to remove.
251     */
252    public static void removeClass(final JavaClass clazz) {
253        repository.removeClass(clazz);
254    }
255
256    /**
257     * Removes class with given (fully qualified) name from repository.
258     *
259     * @param clazz The class name to remove.
260     */
261    public static void removeClass(final String clazz) {
262        repository.removeClass(repository.findClass(clazz));
263    }
264
265    /**
266     * Sets repository instance to be used for class loading.
267     *
268     * @param rep The repository instance.
269     */
270    public static void setRepository(final org.apache.bcel.util.Repository rep) {
271        repository = rep;
272    }
273
274    /**
275     * Constructs a new Repository.
276     */
277    public Repository() {
278    }
279}