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