return null;
}
// we will need the super class name any outer class name and the name of the interfaces the class implements
ClassChecker checker = getClassChecker(newBuffer);// new ClassChecker(newBuffer);
if (checker == null || checker.isInterface()) {
return null;
}
/*
if (checker.hasOuterClass()) {
// we don't transform inner classes for now
// TODO -- see if we can match and transform inner classes via the outer class
return null;
}
*/
// TODO-- reconsider this as it is a bit dodgy as far as security is concerned
if (loader == null) {
loader = ClassLoader.getSystemClassLoader();
}
// if we need to traverse the interfaces then we have a DAG to deal with so
// we had better find a way to avoid doing things twice
LinkedList<String> toVisit = null;
HashSet<String> visited = null;
// ok, we need to check whether there are any class scripts associated with this class and if so
// we will consider transforming the byte code
// TODO -- there are almost certainly concurrency issues to deal with here if rules are being loaded/unloaded
newBuffer = tryTransform(newBuffer, internalName, loader, internalName, false);
int dotIdx = internalName.lastIndexOf('.');
if (dotIdx > 0) {
newBuffer = tryTransform(newBuffer, internalName, loader, internalName.substring(dotIdx + 1), false);
}
if (scriptRepository.checkInterfaces()) {
// now we need to do the same for any interface scripts
// n.b. resist the temptation to call classBeingRedefined.getInterfaces() as this will
// cause the class to be resolved, losing any changes we install
// we need to check the transitive closure of the binary links
// Class implements Interface and Interface extends Interface for this class
// which in general is a DAG.
toVisit = new LinkedList<String>();
visited = new HashSet<String>();
// we start with the original list of implemented interfaces
int interfaceCount = checker.getInterfaceCount();
for (int i = 0; i < interfaceCount; i++) {
String interfaceName = checker.getInterface(i);
toVisit.add(interfaceName);
}
// ok now check each interface in turn while pushing its super interfaces
// until we no longer have any new interfaces to check
while (!toVisit.isEmpty()) {
String interfaceName = toVisit.pop();
String internalInterfaceName = TypeHelper.internalizeClass(interfaceName);
if (!visited.contains(interfaceName)) {
// avoid visiting this interface again
visited.add(interfaceName);
// now see if we have any rules for this interface
newBuffer = tryTransform(newBuffer, internalName, loader, internalInterfaceName, true);
dotIdx = internalInterfaceName.lastIndexOf('.');
if (dotIdx >= 0) {
newBuffer = tryTransform(newBuffer, internalName, loader, internalInterfaceName.substring(dotIdx + 1), true);
}
// check the extends list of this interface for new interfaces to consider
ClassChecker newChecker = getClassChecker(interfaceName, originalLoader);
if (newChecker != null) {
interfaceCount = newChecker.getInterfaceCount();
for (int i = 0; i < interfaceCount; i++) {
interfaceName = newChecker.getInterface(i);
toVisit.add(interfaceName);
}
}
}
}
}
// checking supers is expensive so we obey the switch which disables it
if (!skipOverrideRules()) {
// ok, now check the superclass for this class and so on
String superName = checker.getSuper();
while (superName != null) {
// we need to check the super class structure
// n.b. we use the original loader here because we don't want to search the system loader
// when we have a class in the bootstrap loader
checker = getClassChecker(superName, originalLoader);
if (checker == null || checker.hasOuterClass()) {
// we don't transform inner classes for now
// TODO -- see if we can match and transform inner classes via the outer class
break;
}
newBuffer = tryTransform(newBuffer, internalName, loader, superName, false, true);
dotIdx = superName.lastIndexOf('.');
if (dotIdx > 0) {
newBuffer = tryTransform(newBuffer, internalName, loader, superName.substring(dotIdx + 1), false, true);
}
if (scriptRepository.checkInterfaces()) {
// we need to do another DAG visit but only for interfaces not already considered
int interfaceCount = checker.getInterfaceCount();
for (int i = 0; i < interfaceCount; i++) {
String interfaceName = checker.getInterface(i);
toVisit.add(interfaceName);
}
// ok now check each interface in turn while pushing its super interfaces
// until we no longer have any new interfaces to check
while(!toVisit.isEmpty()) {
String interfaceName = toVisit.pop();
String internalInterfaceName = TypeHelper.internalizeClass(interfaceName);
if (!visited.contains(interfaceName)) {
// avoid visiting this interface again
visited.add(interfaceName);
// now see if we have any rules for this interface
newBuffer = tryTransform(newBuffer, internalName, loader, internalInterfaceName, true, true);
dotIdx = interfaceName.lastIndexOf('.');
if (dotIdx >= 0) {
newBuffer = tryTransform(newBuffer, internalName, loader, internalInterfaceName.substring(dotIdx + 1), true, true);
}
// check the extends list of this interface for new interfaces to consider
ClassChecker newChecker = getClassChecker(interfaceName, originalLoader);
if (newChecker != null) {
interfaceCount = newChecker.getInterfaceCount();
for (int i = 0; i < interfaceCount; i++) {
interfaceName = newChecker.getInterface(i);
toVisit.add(interfaceName);
}
}
}
}