/*
* 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.
*
* 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.
*
*/
/**
<p> This class finds transitive closure of dependencies from a given
root set of classes. If your project has lots of .class files and you
want to ship only those .class files which are used (transitively)
from a root set of classes, then you can use this utility. </p> <p>
How does it work?</p>
<p> We walk through all constant pool entries of a given class and
find all modified UTF-8 entries. Anything that looks like a class name is
considered as a class and we search for that class in the given
classpath. If we find a .class of that name, then we add that class to
list.</p>
<p> We could have used CONSTANT_ClassInfo type constants only. But
that will miss classes used through Class.forName or xyz.class
construct. But, if you refer to a class name in some other string we
would include it as dependency :(. But this is quite unlikely
anyway. To look for exact Class.forName argument(s) would involve
bytecode analysis. Also, we handle only simple reflection. If you
accept name of a class from externally (for eg properties file or
command line args for example, this utility will not be able to find
that dependency. In such cases, include those classes in the root set.
</p>
*/
public class ClosureFinder {
}
// parse classPath into pathComponents array
private void parseClassPath() {
while (st.hasMoreTokens())
}
// if output is aleady not computed, compute it now
// result is a map from class file name to base path where the .class was found
if (visitedClasses == null) {
visitedClasses = new HashMap();
}
return visitedClasses;
}
// compute closure for all given root classes
private void computeClosure() {
}
}
// looks up for .class in pathComponents and returns
// base path if found, else returns null
classNameAsPath + ".class");
if (f.exists()) {
if (isWindows) {
// Windows reports special devices AUX,NUL,CON as files
// under any directory. It does not care about file extention :-(
return null;
}
}
return pathComponents[i];
}
}
return null;
}
// from JVM spec. 2'nd edition section 4.4
// whether a given string may be a class name?
for (int s = 0; s < len; s++) {
char c = internalClassName.charAt(s);
return false;
}
return true;
}
// compute closure for a given class
try {
// look for .class signature
return;
}
// ignore major and minor version numbers
// read number of constant pool constants
// zero'th entry is unused
switch (constType) {
case CONSTANT_Class:
case CONSTANT_String:
break;
case CONSTANT_FieldRef:
case CONSTANT_MethodRef:
case CONSTANT_NameAndType:
case CONSTANT_Integer:
case CONSTANT_Float:
// all these are 4 byte constants
break;
case CONSTANT_Long:
case CONSTANT_Double:
// 8 byte constants
// occupies 2 cp entries
cpIndex++;
break;
case CONSTANT_Utf8: {
break;
}
default:
return;
}
}
// now walk thru the string constants and look for class names
for (int s = 0; s < numConsts; s++) {
}
} catch (IOException exp) {
// ignore for now
}
}
}
// a sample main that accepts roots classes in a file and classpath as args
}
try {
if (isWindows) {
}
}
} catch (IOException exp) {
}
}
}
}