/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* A framework for determining {@link Dependency dependencies} between class files.
*
* A {@link Dependency.Finder finder} is used to identify the dependencies of
* individual classes. Some finders may return subtypes of {@code Dependency} to
* further characterize the type of dependency, such as a dependency on a
* method within a class.
*
* A {@link Dependency.Filter filter} may be used to restrict the set of
* dependencies found by a finder.
*
* Dependencies that are found may be passed to a {@link Dependencies.Recorder
* recorder} so that the dependencies can be stored in a custom data structure.
*/
public class Dependencies {
/**
* Thrown when a class file cannot be found.
*/
super(className);
}
this(className);
}
}
/**
* Thrown when an exception is found processing a class file.
*/
}
}
/**
* Service provider interface to locate and read class files.
*/
public interface ClassFileReader {
/**
* Get the ClassFile object for a specified class.
* @param className the name of the class to be returned.
* @return the ClassFile for the given class
* @throws Dependencies#ClassFileNotFoundException if the classfile cannot be
* found
*/
throws ClassFileNotFoundException;
}
/**
* Service provide interface to handle results.
*/
public interface Recorder {
/**
* Record a dependency that has been found.
* @param d
*/
}
/**
* Get the default finder used to locate the dependencies for a class.
* @return the default finder
*/
}
/**
* Get a finder used to locate the API dependencies for a class.
* These include the superclass, superinterfaces, and classes referenced in
* the declarations of fields and methods. The fields and methods that
* are checked can be limited according to a specified access.
* The access parameter must be one of {@link AccessFlags#ACC_PUBLIC ACC_PUBLIC},
* {@link AccessFlags#ACC_PRIVATE ACC_PRIVATE},
* {@link AccessFlags#ACC_PROTECTED ACC_PROTECTED}, or 0 for
* package private access. Members with greater than or equal accessibility
* to that specified will be searched for dependencies.
* @param access the access of members to be checked
* @return an API finder
*/
return new APIDependencyFinder(access);
}
/**
* Get the finder used to locate the dependencies for a class.
* @return the finder
*/
finder = getDefaultFinder();
return finder;
}
/**
* Set the finder used to locate the dependencies for a class.
* @param f the finder
*/
f.getClass(); // null check
finder = f;
}
/**
* Get the default filter used to determine included when searching
* the transitive closure of all the dependencies.
* Unless overridden, the default filter accepts all dependencies.
* @return the default filter.
*/
return DefaultFilter.instance();
}
/**
* Get a filter which uses a regular expression on the target's class name
* to determine if a dependency is of interest.
* @param pattern the pattern used to match the target's class name
* @return a filter for matching the target class name with a regular expression
*/
return new TargetRegexFilter(pattern);
}
/**
* Get a filter which checks the package of a target's class name
* to determine if a dependency is of interest. The filter checks if the
* package of the target's class matches any of a set of given package
* names. The match may optionally match subpackages of the given names as well.
* @param packageNames the package names used to match the target's class name
* @param matchSubpackages whether or not to match subpackages as well
* @return a filter for checking the target package name against a list of package names
*/
}
/**
* Get the filter used to determine the dependencies included when searching
* the transitive closure of all the dependencies.
* Unless overridden, the default filter accepts all dependencies.
* @return the filter
*/
filter = getDefaultFilter();
return filter;
}
/**
* Set the filter used to determine the dependencies included when searching
* the transitive closure of all the dependencies.
* @param f the filter
*/
f.getClass(); // null check
filter = f;
}
/**
* Find the dependencies of a class, using the current
* {@link Dependencies#getFinder finder} and
* {@link Dependencies#getFilter filter}.
* The search may optionally include the transitive closure of all the
* filtered dependencies, by also searching in the classes named in those
* dependencies.
* @param classFinder a finder to locate class files
* @param rootClassNames the names of the root classes from which to begin
* searching
* @param transitiveClosure whether or not to also search those classes
* named in any filtered dependencies that are found.
* @return the set of dependencies that were found
* @throws ClassFileNotFoundException if a required class file cannot be found
* @throws ClassFileError if an error occurs while processing a class file,
* such as an error in the internal class file structure.
*/
boolean transitiveClosure)
throws ClassFileNotFoundException {
public void addDependency(Dependency d) {
}
};
return results;
}
/**
* Find the dependencies of a class, using the current
* {@link Dependencies#getFinder finder} and
* {@link Dependencies#getFilter filter}.
* The search may optionally include the transitive closure of all the
* filtered dependencies, by also searching in the classes named in those
* dependencies.
* @param classFinder a finder to locate class files
* @param rootClassNames the names of the root classes from which to begin
* searching
* @param transitiveClosure whether or not to also search those classes
* named in any filtered dependencies that are found.
* @param recorder a recorder for handling the results
* @throws ClassFileNotFoundException if a required class file cannot be found
* @throws ClassFileError if an error occurs while processing a class file,
* such as an error in the internal class file structure.
*/
public void findAllDependencies(
throws ClassFileNotFoundException {
getFinder(); // ensure initialized
getFilter(); // ensure initialized
// Work queue of names of classfiles to be searched.
// Entries will be unique, and for classes that do not yet have
// dependencies in the results map.
// The following code just applies the filter to the dependencies
// followed for the transitive closure.
}
}
}
}
/**
* A location identifying a class.
*/
}
/**
* Get the name of the class being depended on. This name will be used to
* locate the class file for transitive dependency analysis.
* @return the name of the class being depended on
*/
return className;
}
if (this == other)
return true;
if (!(other instanceof SimpleLocation))
return false;
}
public int hashCode() {
}
return className;
}
}
/**
* A dependency of one class on another.
*/
}
return origin;
}
return target;
}
if (this == other)
return true;
if (!(other instanceof SimpleDependency))
return false;
}
public int hashCode() {
}
}
}
/**
* This class accepts all dependencies.
*/
instance = new DefaultFilter();
return instance;
}
return true;
}
}
/**
* This class accepts those dependencies whose target's class name matches a
* regular expression.
*/
}
}
}
/**
* This class accepts those dependencies whose class name is in a given
* package.
*/
throw new IllegalArgumentException();
}
this.packageNames = packageNames;
this.matchSubpackages = matchSubpackages;
}
return true;
if (matchSubpackages) {
for (String n: packageNames) {
return true;
}
}
return false;
}
private final boolean matchSubpackages;
}
/**
* This class identifies class names directly or indirectly in the constant pool.
*/
}
return v.deps;
}
}
/**
* This class identifies class names in the signatures of classes, fields,
* and methods in a class.
*/
switch (access) {
case AccessFlags.ACC_PUBLIC:
case AccessFlags.ACC_PROTECTED:
case AccessFlags.ACC_PRIVATE:
case 0:
showAccess = access;
break;
default:
throw new IllegalArgumentException("invalid access 0x"
}
}
try {
// inner classes?
if (checkAccess(f.access_flags))
}
if (checkAccess(m.access_flags)) {
if (e != null)
}
}
return v.deps;
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
}
// code copied from javap.Options.checkAccess
return false;
return false;
return false;
else
return true;
}
private int showAccess;
}
if (l == null)
return l;
}
try {
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
}
try {
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
}
}
}
if (index != 0) {
}
}
for (int i: indices)
addClass(i);
}
}
// ConstantPool.Visitor methods
try {
else
return null;
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
}
return null;
}
}
return null;
}
return null;
}
}
return null;
}
return null;
}
return null;
}
return null;
}
}
try {
return null;
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
}
return null;
}
return null;
}
try {
return null;
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
}
// Type.Visitor methods
if (t != null)
}
}
}
return null;
}
return null;
}
return null;
}
return null;
}
return null;
}
return null;
}
return null;
}
}
}
}