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