public class ClassDep extends Object
jar
tool, to create a JAR file containing precisely
those classes.
The following items are discussed below:
java -jar install_dir/lib/classdep.jar \ -cp input_classpath processing_options output_options
where install_dir is the directory where the Apache River release is installed. Note that the options for this tool can be specified in any order, and can be intermixed.
The -cp
class path value,
input_classpath,
is an argument to the ClassDep
tool itself and should
include all of the classes that might need to be included in the
dependency analysis. Typically this will include all of your application
classes, classes from the Apache River release, and any other classes on which
your classes might depend. It is safe to include more classes than are
actually necessary (since the purpose of this tool is, after all, to
determine which subset of these classes is actually necessary), but it is
not necessary to include any classes that are part of the Java 2 SDK.
The class path should be in the form of a list of directories or JAR
files, delimited by a colon (":") on UNIX platforms and a semi-colon
(";") on Microsoft Windows platforms. The order of locations in the path
does not matter. If you use JAR files, any Class-Path
manifest entries in those JAR files are ignored, so you must include the
values of those manifest entries explicitly in the path, or errors may
result. For example, if you include jini-ext.jar
then you
should explicitly include jini-core.jar
as well, because
jini-core.jar
is in the Class-Path
manifest
entry of jini-ext.jar
.
In general, you only need to specify concrete classes as roots, not
interface types. When analyzing classes for the class path of an
application, you typically need to include the top-level class (the one
with the main
method). When analyzing classes for the
codebase of a service, you typically need to include the top-level proxy
classes used by the service, any trust verifier classes for those
proxies, and any custom entry classes used by the service for lookup
service attributes. Also when analyzing classes for the codebase of a
service, if the service's proxy can return leases, registration objects,
or other proxies, or if your service generates events, and if those
objects are only referenced by interface type in the top-level proxy, not
by concrete class, then you also need to include the concrete classes of
those other objects. In all cases, you typically need to include any stub
classes that you generated with the rmic
tool.
-newdirbehavior
options is specified. The directory must
contain at least one filename separator character and be one of the
directories specified in input_classpath, or when the old
behavior is effective it can be a subdirectory of one of the directories on
the input_classpath. Each class in the tree needs to be in
a package that is defined to be "inside" the graph (as described further
below).
When the -newdirbehavior
options is set the -inroot
and -outroot
options can be used to include/exclude particular
subtrees from the potential set of roots. When the old behavior is effective
all classes are considered as root, but can be excluded through the
-prune
option.
-inroot
package-prefix (only valid with
-newdirbehavior
)
-out
, -skip
or -outroot
options. If not specified all found classes are considered roots. This option
can be specified zero or more times. Note that the argument to
-inroot
is a package namespace (delimited by "."), not a
directory.
-outroot
package-prefix (only valid with
-newdirbehavior
)
rootdir
element, any classes that are in the given package or a
subpackage of it are not treated as roots. This option can be specified zero
or more times. Note that the argument to -outroot
is a package
namespace (delimited by "."), not a directory.
-prune
package-prefix (old behavior only)
-prune
is a package
namespace (delimited by "."), not a directory.
The -skip
option (described further below) can be used to
exclude specific classes from the set of roots.
Starting with the root classes, a dependency graph is constructed by examining the compiled class file for a class, finding all of the classes it references, and then in turn examining those classes. The extent of the graph is determined by which packages are defined to be "inside" the graph and which are defined to be "outside" the graph. If a referenced class is in a package that is defined to be outside the graph, that class is not included in the graph, and none of classes that it references are examined. All of the root classes must be in packages that are defined to be "inside" the graph.
The inside and outside packages are specified by using the following options. Each of these options may be specified zero or more times. Some variations are illustrated in the Examples section of this page.
-in
package-prefix
-out
or -skip
options. This
option can be specified zero or more times. If no -in
options are specified, the default is that all packages are considered to
be inside packages. Note that the argument to -in
is a
namespace, so none of its subpackages need to be specified as an argument
to -in
.
If you use this option, you will likely need to use it multiple
times. For example, if your application classes are in the
com.corp.foo
namespace, and you also use some classes in the
com.sun.jini
and net.jini
namespaces, then you
might specify:
-in com.corp.foo -in com.sun.jini -in net.jini
-out
package-prefix
-in
options,
then each -out
namespace should be a subspace of some
-in
namespace. Note that the argument to -out
is a namespace, so none of its subpackages need to be specified as an
argument to -out
.
If you use this option, you will likely need to use it multiple
times. For example, if you do not specify any -in
options,
then all packages are considered inside the graph, including packages
defined in the Java 2 SDK that you typically want to exclude, so you
might exclude them by specifying:
-out java -out javaxAs another example, if you have specified
-in com.corp.foo
but you don't want to include any of the classes in the
com.corp.foo.test
or com.corp.foo.qa
namespaces
in the dependency graph, then you would specify:
-out com.corp.foo.test -out com.corp.foo.qa
-skip
class
-outer
-newdirbehavior
-inroot
and -outroot
options specified. When
this option is set subdirectories of the specified directory are no longer
considered as root for finding classes. When this option is not set, the
default, the utility maintains the old behavior with respect to the semantics
for the directories passed in and the -prune
option must be
used. You are advised to set this option as there are some edge cases for
which the old behavior won't work as expected, especially when no
-in
options are set.-edges
For example, you might exclude classes from the Java 2 SDK from the
dependency graph because you don't want to include them in your JAR file,
but you might be interested in knowing which classes from the Java 2 SDK
are referenced directly by the classes in your JAR file. The
-edges
option can be used to display this information.
-show
package-prefix
-show
options are specified, the default is that all classes
in the dependency graph are displayed (or all edge classes, if
-edges
is specified). Note that the argument to
-show
is a namespace, so none of its subpackages need to be
specified as an argument to -show
.
For example, to determine which classes from the Java 2 SDK your
application depends on, you might not specify any -in
options, but limit the output by specifying:
-show java -show javax
-hide
package-prefix
-show
options, then each -hide
namespace should
be a subspace of some -show
namespace. Note that the
argument to -hide
is a namespace, so none of its subpackages
need to be specified as an argument to -hide
.
For example, to determine which non-core classes from the
net.jini
namespace you use, you might specify:
-show net.jini -hide net.jini.core
-files
com\corp\foo\Bar.class
instead of
com.corp.foo.Bar
. This option should be used to generate
output suitable as input to the jar
tool.
For more information on the jar
tool, see:
-tell
class
classes
directory. Alternatively, if you have compiled from
the source code, substitute source/classes
for
classes
in the examples.)
The following example computes the classes required for a codebase JAR
file, starting with a smart proxy class and a stub class as roots, and
displays them in filename format. (A more complete example would include
additional roots for leases, registrations, events, and lookup service
attributes, and would exclude platform classes such as those in
jsk-platform.jar
.)
java -jar install_dir/lib/classdep.jar \ -cp install_dir/classes \ com.sun.jini.reggie.RegistrarProxy com.sun.jini.reggie.RegistrarImpl_Stub \ -in com.sun.jini -in net.jini \ -files
The following example computes the classes required for a classpath JAR
file, starting with all of the classes in a directory as roots, and
displays them in class name format. (A more complete example would exclude
platform classes such as those in jsk-platform.jar
.)
java -jar install_dir/lib/classdep.jar \ -cp install_dir/classes \ install_dir/classes/com/sun/jini/reggie \ -in com.sun.jini -in net.jini
The following example computes the com.sun.jini
classes used
by a service implementation, and displays the net.jini
classes that are immediately referenced by those classes.
java -jar install_dir/lib/classdep.jar \ -cp install_dir/classes \ com.sun.jini.reggie.RegistrarImpl \ -in com.sun.jini \ -edges \ -show net.jini
The following example computes all of the classes used by a service
implementation that are not part of the Java 2 SDK, and displays the
classes that directly reference the class java.awt.Image
.
java -jar install_dir/lib/classdep.jar \ -cp install_dir/classes \ com.sun.jini.reggie.RegistrarImpl \ -out java -out javax \ -tell java.awt.Image
The following example computes all of the classes to include in
jini-ext.jar
and displays them in filename format. Note
that both -out
and -prune
options are needed
for the net.jini.core
namespace; -out
to
exclude classes from the dependency graph, and -prune
to
prevent classes from being used as roots.
java -jar install_dir/lib/classdep.jar \ -cp install_dir/classes \ -in net.jini -out net.jini.core -in com.sun.jini \ install_dir/classes/net/jini -prune net.jini.core \ -files
Modifier and Type | Class and Description |
---|---|
private static class |
ClassDep.Compare |
Modifier and Type | Field and Description |
---|---|
private ClassDepend |
cd |
private ArrayList |
classes
Class set to look at for dependencies.
|
private String |
classpath
Set of paths to find class definitions in order to determine
dependencies.
|
private boolean |
edges
Flag to determine whether there is interest
in dependencies that go outside the set of
interested classes.
|
private boolean |
failed
Indicates whether a failure has been encountered during deep dependency
checking.
|
private boolean |
files
If true class names are printed using
the system's File.separator, else the
fully qualified class name is printed.
|
private ArrayList |
hides
Suppress display of found dependencies that are under
the provided package prefixes subset.
|
private boolean |
ignoreOuter
Static inner classes have a dependency on their outer
parent class.
|
private ArrayList |
inside
Package set that we have interest to work in.
|
private ArrayList |
insideRoots
Set of packages to include when classes are found through the specified
root directories.
|
private boolean |
newRootDirBehavior
Indicates whether the root directories specified for finding classes
for dependency checking must be traversed in the 'old' way, or that the
new behavior must be effective.
|
private ArrayList |
outside
Package set to not work with.
|
private ArrayList |
outsideRoots
Set of packages to exclude when classes are found through the specified
root directories.
|
private ArrayList |
prunes
Set of packages to skip over in the processing of dependencies.
|
private static boolean |
resinit |
private static ResourceBundle |
resources |
private SortedSet |
results
Container for found dependency classes.
|
private ArrayList |
roots
Set of directories to find dependencies in.
|
private ArrayList |
shows
Only display found dependencies that fall under the provided
roots subset. |
private ArrayList |
skips
Set of classes to skip over in the processing of dependencies.
|
private ArrayList |
tells
Given a specific fully qualified classes, what other classes
in the roots list depend on it.
|
Constructor and Description |
---|
ClassDep()
No argument constructor.
|
ClassDep(String[] cmdLine)
Constructor that takes command line arguments and fills in the
appropriate fields.
|
Modifier and Type | Method and Description |
---|---|
private static void |
add(String arg,
ArrayList elts)
Take the given argument and add it to the provided container.
|
void |
addClasses(String className)
Add an entry into the set of classes that
dependencies are going to be computed on.
|
private List |
addClassesRecursively(List list)
Add all classes in Packages and subpackages recursively by appending **
as per the syntax requirements of the ClassDepend API.
|
void |
addHides(String packagePrefix)
Add an entry into the set of package prefixes that
are to remain hidden from processing.
|
void |
addInside(String packagePrefix)
Add an entry into the working set of package prefixes
that will make up the working domain space.
|
void |
addInsideRoot(String packagePrefix)
Adds an entry into the set of package prefixes for which classes found
through the specified root directories will be considered for dependency
generation.
|
void |
addOutside(String packagePrefix)
Add an entry into the set of package prefixes
that will bypassed during dependency checking.
|
void |
addOutsideRoot(String packagePrefix)
Adds an entry into the set of package prefixes for which classes found
through the specified root directories, and that are part of the inside
root namespace, will be skipped as part of the dependency generation.
|
void |
addPrune(String packagePrefix)
Add an entry into the set of package prefixes
that will be skipped as part of the dependency
generation.
|
void |
addRoots(String rootName)
Add an entry into the set of directories to
look under for the classes that fall within
the working domain space as defined by the
intersection of the following sets:
inside,outside,prune,show, and hide.
|
void |
addShow(String packagePrefix)
Add an entry into the set of package prefixes
that we want to display.
|
void |
addSkip(String packagePrefix)
Add an entry into the set of classes that
should be skipped during dependency generation.
|
void |
addTells(String className)
Add an entry in to the set of classes whose dependents
that lie with the inside set are listed.
|
String[] |
compute()
Method that takes the user provided switches that
logically define the domain in which to look for
dependencies.
|
boolean |
getFiles()
If true classnames will be separated using
File.separator, else it will use dots.
|
String[] |
getResults()
Accessor method for the found dependencies.
|
private static String |
getString(String key)
Get the strings from our resource localization bundle.
|
boolean |
hasFailed()
Indicates whether computing the dependent classes as result of the last
call to
compute() resulted in one or more failures. |
static void |
main(String[] args)
Command line interface for generating the list of classes that
a set of classes depends upon.
|
private static void |
print(String key,
Object val)
Print out string according to resourceBundle format.
|
private static void |
print(String key,
Object val1,
Object val2)
Print out string according to resourceBundle format.
|
void |
setClassPath(String classpath)
Set the classpath to use for finding our class definitions.
|
void |
setEdges(boolean edges)
Determines whether to include package references
that lie outside the declared set of interest.
|
void |
setFiles(boolean files)
Determines how to print out the fully qualified
class names.
|
void |
setRootDirBehavior(boolean newBehavior)
Controls whether the behavior for finding class files in the specified
directories, if any, must be based on the old behavior (the default) or
the new behavior that solves some of the problems with the old behavior.
|
void |
setupOptions(String[] args)
Convenience method for initializing an instance with specific
command line arguments.
|
private void |
traverse(String path)
Recursively traverse a given path, finding all the classes that
make up the set to work with.
|
private void |
traverse(String path,
String rootPath)
Recursively traverse a given path, finding all the classes that make up
the set of classes to work with.
|
static void |
usage()
Print out the usage for this utility.
|
private ClassDepend cd
private boolean files
private String classpath
private boolean edges
net.jini.core.lease
a reference to a class in net.jini
is found it
will be noted if the flag is set to true, else
it will be ignored. Note: these edge case dependencies must be included in the classpath in order to find their definitions.
private boolean ignoreOuter
Note: This is an optimization for those who plan on doing work with the output of this utility. It does not impact this utility, but the work done on its generated output may have an impact. This will have to be implemented in ClassDepend note the above description conflicts with the variable name.
private final ArrayList inside
private final ArrayList outside
private final ArrayList classes
inside
.private final ArrayList roots
private final ArrayList prunes
private boolean newRootDirBehavior
private final ArrayList insideRoots
private final ArrayList outsideRoots
private final ArrayList skips
private final ArrayList tells
private final ArrayList shows
roots
subset.private final ArrayList hides
private final SortedSet results
private boolean failed
private static ResourceBundle resources
private static boolean resinit
public ClassDep()
public ClassDep(String[] cmdLine)
cmdLine
- private static void add(String arg, ArrayList elts)
a.b
should not match
a.bx
and a.b
,
just a.b
.arg
- the package-prefix in string formelts
- container to add elements toprivate void traverse(String path)
This implementation is here to maintain the old behavior with regard to how root directories were interpreted.
path
- path to traverse down fromprivate void traverse(String path, String rootPath)
path
- path to traverse down fromrootPath
- path to the directory that serves as the root for the
class files found, any path component below the root is part of
the full qualified name of the classpublic String[] compute()
Whether a failure has occurred during computing the dependent classes
can be found out with a call to hasFailed()
.
private List addClassesRecursively(List list)
public static void usage()
public void setClassPath(String classpath)
classpath
- public void setFiles(boolean files)
true
it will use
File.separator
, else .
's
will be used.
If not set the default is false
.files
- public void addHides(String packagePrefix)
packagePrefix
- public void addInside(String packagePrefix)
packagePrefix
- public void setEdges(boolean edges)
If true edges will be processed as well, else
they will be ignored. If not set the default
will be false
.
Note: These edge classes must included in the classpath for this utility.
edges
- public void addOutside(String packagePrefix)
packagePrefix
- public void addPrune(String packagePrefix)
This method has no impact if the new behavior is effective for the interpretation of the root directories for finding class files to include for dependency checking.
packagePrefix
- public void setRootDirBehavior(boolean newBehavior)
newBehavior
- public void addInsideRoot(String packagePrefix)
Adding entries without a call to setRootDirBehavior(boolean)
with true
as the argument will cause compute()
to
fail.
packagePrefix
- public void addOutsideRoot(String packagePrefix)
Adding entries without a call to setRootDirBehavior(boolean)
with true
as the argument will cause compute()
to
fail.
packagePrefix
- public void addShow(String packagePrefix)
packagePrefix
- public void addSkip(String packagePrefix)
packagePrefix
- public void addTells(String className)
className
- public void addRoots(String rootName)
rootName
- public void addClasses(String className)
className
- public boolean getFiles()
public String[] getResults()
public boolean hasFailed()
compute()
resulted in one or more failures.true
in case a failure has happened, such as a
class not being found, false
otherwisepublic void setupOptions(String[] args)
args
- private static String getString(String key)
private static void print(String key, Object val)
private static void print(String key, Object val1, Object val2)
public static void main(String[] args)
Copyright 2007-2013, multiple authors.
Licensed under the Apache License, Version 2.0, see the NOTICE file for attributions.