package org.jboss.console.plugins;
import gnu.trove.TLongObjectHashMap;
import org.jboss.aop.AspectManager;
import org.jboss.aop.CallerConstructorInfo;
import org.jboss.aop.CallerMethodInfo;
import org.jboss.aop.ClassAdvisor;
import org.jboss.aop.MethodInfo;
import org.jboss.aop.advice.AdviceBinding;
import org.jboss.aop.advice.Interceptor;
import org.jboss.aop.advice.AbstractAdvice;
import org.jboss.aop.advice.CFlowInterceptor;
import org.jboss.aop.introduction.InterfaceIntroduction;
import org.jboss.aop.standalone.Package;
import org.jboss.console.manager.interfaces.ManageableResource;
import org.jboss.console.manager.interfaces.TreeNode;
import org.jboss.console.plugins.helpers.AbstractPluginWrapper;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletConfig;
public class AOPLister
extends AbstractPluginWrapper
{
Thread refreshPoller;
public AOPLister()
{
super();
}
TreeNode[] createMetaDataTree(org.jboss.aop.metadata.SimpleMetaData metaData, String description, String baseUrl) throws Exception
{
HashSet groups = metaData.tags();
if (groups.size() == 0)
{
return null;
}
TreeNode[] nodes = new TreeNode[groups.size()];
Iterator it = groups.iterator();
for (int i = 0; it.hasNext(); i++)
{
String group = (String) it.next();
nodes[i] = createTreeNode(
group, description,
"images/database.gif", baseUrl + "&group=" + group,
null, null, null );
}
return nodes;
}
TreeNode[] loadDefaultMetaData(ClassAdvisor advisor, String classname) throws Exception
{
org.jboss.aop.metadata.SimpleMetaData metaData = advisor.getDefaultMetaData();
return createMetaDataTree(metaData,
"Default metadata for " + classname,
"AOPDefaultMetaData.jsp?classname=" + classname);
}
TreeNode[] loadClassMetaData(ClassAdvisor advisor, String classname) throws Exception
{
org.jboss.aop.metadata.SimpleMetaData metaData = advisor.getClassMetaData();
return createMetaDataTree(metaData,
"Class metadata for " + classname,
"AOPClassMetaData.jsp?classname=" + classname);
}
TreeNode[] loadMethodMetaData(ClassAdvisor advisor, String classname) throws Exception
{
org.jboss.aop.metadata.MethodMetaData metaData = advisor.getMethodMetaData();
Iterator it = metaData.getMethods();
if (!it.hasNext()) return null;
ArrayList methods = new ArrayList();
while (it.hasNext())
{
String method = (String) it.next();
org.jboss.aop.metadata.SimpleMetaData methodData = metaData.getMethodMetaData(method);
TreeNode[] methodNodes = createMetaDataTree(methodData,
"Metadata for method " + method,
"AOPMethodMetaData.jsp?classname=" + classname + "&method=" + java.net.URLEncoder.encode(method));
methods.add(createTreeNode(
method, "Metadata for method " + method,
"images/starfolder.gif", null,
null, methodNodes, null ));
}
return (TreeNode[]) methods.toArray(new TreeNode[methods.size()]);
}
TreeNode[] loadFieldMetaData(ClassAdvisor advisor, String classname) throws Exception
{
org.jboss.aop.metadata.FieldMetaData metaData = advisor.getFieldMetaData();
Iterator it = metaData.getFields();
if (!it.hasNext()) return null;
ArrayList fields = new ArrayList();
while (it.hasNext())
{
String field = (String) it.next();
org.jboss.aop.metadata.SimpleMetaData fieldData = metaData.getFieldMetaData(field);
TreeNode[] fieldNodes = createMetaDataTree(fieldData,
"Metadata for field " + field,
"AOPFieldMetaData.jsp?classname=" + classname + "&field=" + field);
fields.add(createTreeNode(
field, "Metadata for field " + field,
"images/starfolder.gif", null,
null, fieldNodes, null ));
}
return (TreeNode[]) fields.toArray(new TreeNode[fields.size()]);
}
TreeNode[] loadConstructorMetaData(ClassAdvisor advisor, String classname) throws Exception
{
org.jboss.aop.metadata.ConstructorMetaData metaData = advisor.getConstructorMetaData();
Iterator it = metaData.getConstructors();
if (!it.hasNext()) return null;
ArrayList constructors = new ArrayList();
while (it.hasNext())
{
String signature = (String)it.next();
org.jboss.aop.metadata.SimpleMetaData constructorData = metaData.getConstructorMetaData(signature);
TreeNode[] constructorNodes = createMetaDataTree(constructorData,
"Metadata for constructor",
"AOPConstructorMetaData.jsp?classname=" + classname + "&constructor=" + java.net.URLEncoder.encode(signature));
constructors.add(createTreeNode(
signature, "Metaata for constructor " + signature,
"images/starfolder.gif", null,
null, constructorNodes, null ));
}
return (TreeNode[]) constructors.toArray(new TreeNode[constructors.size()]);
}
TreeNode getMetaData(String classname) throws Exception
{
ClassAdvisor advisor = (ClassAdvisor) AspectManager.instance().getAdvisor(classname);
ArrayList nodes = new ArrayList();
TreeNode[] defaultMetaData = loadDefaultMetaData(advisor, classname);
if (defaultMetaData != null)
{
nodes.add(createTreeNode(
"Default",
"Default metadata for for " + classname, "images/starfolder.gif", null,
null, defaultMetaData, null ));
}
TreeNode[] classMetaData = loadClassMetaData(advisor, classname);
if (classMetaData != null)
{
nodes.add(createTreeNode(
"Class",
"Class metadata for for " + classname, "images/starfolder.gif", null,
null, classMetaData, null ));
}
TreeNode[] methodMetaData = loadMethodMetaData(advisor, classname);
if (methodMetaData != null)
{
nodes.add(createTreeNode(
"Methods",
"Method metadata for for " + classname, "images/starfolder.gif", null,
null, methodMetaData, null ));
}
TreeNode[] fieldMetaData = loadFieldMetaData(advisor, classname);
if (fieldMetaData != null)
{
nodes.add(createTreeNode(
"Fields",
"Field metadata for for " + classname, "images/starfolder.gif", null,
null, fieldMetaData, null ));
}
TreeNode[] constructorMetaData = loadConstructorMetaData(advisor, classname);
if (constructorMetaData != null)
{
nodes.add(createTreeNode(
"Constructors",
"Constructor metadata for for " + classname, "images/starfolder.gif", null,
null, constructorMetaData, null ));
}
if (nodes.size() == 0) return null;
TreeNode[] subnodes = (TreeNode[]) nodes.toArray(new TreeNode[nodes.size()]);
return createTreeNode(
"Metadata", "Metadata for " + classname, "images/starfolder.gif", null,
null, subnodes, null );
}
TreeNode[] getIntroductions(ClassAdvisor advisor) throws Exception
{
ArrayList introductions = advisor.getInterfaceIntroductions();
if (introductions == null || introductions.size() == 0) return null;
TreeNode[] nodes = new TreeNode[introductions.size()];
for (int i = 0; i < introductions.size(); i++)
{
InterfaceIntroduction introduction = (InterfaceIntroduction) introductions.get(i);
nodes[i] = createTreeNode(
"Introduction " + i, "Introduction for " + advisor.getName(), "images/service.gif", "AOPIntroductionPointcut.jsp?pointcut=" + java.net.URLEncoder.encode(introduction.getName()), null, null, null );
}
return nodes;
}
public static String shortenMethod(String classname, Method method)
{
return method.toString().replaceAll(classname + "." + method.getName(), method.getName());
}
public static String shortenConstructor(String classname, Constructor constructor)
{
String base = classname.substring(classname.lastIndexOf('.') + 1);
return constructor.toString().replaceAll(classname, base);
}
public static String shortenField(String classname, Field field)
{
return field.toString().replaceAll(classname + "." + field.getName(), field.getName());
}
public TreeNode[] createAdvisorNodes(ClassAdvisor advisor) throws Exception
{
ArrayList nodes = new ArrayList();
populateIntroductions(advisor, nodes);
populateConstructors(advisor, nodes);
populateMethods(advisor, nodes);
populateFields(advisor, nodes);
TreeNode metadata = getMetaData(advisor.getName());
if (metadata != null) nodes.add(metadata);
return (TreeNode[]) nodes.toArray(new TreeNode[nodes.size()]);
}
private void populateFields(ClassAdvisor advisor, ArrayList nodes) throws Exception
{
if (advisor.getAdvisedFields() == null) return;
ArrayList fieldWriteNodes = new ArrayList();
ArrayList fieldReadNodes = new ArrayList();
for (int i = 0; i < advisor.getAdvisedFields().length; i++)
{
Field f = advisor.getAdvisedFields()[i];
Interceptor[] chain = advisor.getFieldWriteInterceptors()[i];
if (chain != null && chain.length > 0)
{
fieldWriteNodes.add(createTreeNode(
shortenField(advisor.getName(), f),
"Field write interceptor chain",
"images/service.gif", "AOPFieldChain.jsp?classname=" + java.net.URLEncoder.encode(advisor.getName())
+ "&field=" + i
+ "&mode=write",
null, null, null ));
}
chain = advisor.getFieldReadInterceptors()[i];
if (chain != null && chain.length > 0)
{
fieldReadNodes.add(createTreeNode(
shortenField(advisor.getName(), f),
"Field read interceptor chain",
"images/service.gif", "AOPFieldChain.jsp?classname=" + java.net.URLEncoder.encode(advisor.getName())
+ "&field=" + i
+ "&mode=read",
null, null, null ));
}
}
if (fieldWriteNodes.size() > 0 && fieldWriteNodes.size() > 0)
{
ArrayList fieldReadWriteNodes = new ArrayList();
if (fieldWriteNodes.size() > 0)
{
TreeNode[] cnodes = (TreeNode[]) fieldWriteNodes.toArray(new TreeNode[fieldWriteNodes.size()]);
fieldReadWriteNodes.add(createTreeNode(
"write interceptors", "field write info", "images/starfolder.gif", null,
null, cnodes, null ));
}
if (fieldReadNodes.size() > 0)
{
TreeNode[] cnodes = (TreeNode[]) fieldReadNodes.toArray(new TreeNode[fieldReadNodes.size()]);
fieldReadWriteNodes.add(createTreeNode(
"read interceptors", "field read info", "images/starfolder.gif", null,
null, cnodes, null ));
}
TreeNode[] fieldRwNodes = (TreeNode[]) fieldReadWriteNodes.toArray(new TreeNode[fieldReadWriteNodes.size()]);
nodes.add(createTreeNode(
"Fields", "field info", "images/starfolder.gif", null,
null, fieldRwNodes, null ));
}
}
private void populateConstructors(ClassAdvisor advisor, ArrayList nodes) throws Exception
{
if (advisor.getConstructors() == null) return;
if (advisor.getConstructorInterceptors() == null) return;
if (advisor.getMethodCalledByConInterceptors() == null) return;
ArrayList constructorNodes = new ArrayList();
for (int i = 0; i < advisor.getConstructors().length; i++)
{
Constructor con = advisor.getConstructors()[i];
Interceptor[] chain = advisor.getConstructorInterceptors()[i];
HashMap methodCallers = advisor.getMethodCalledByConInterceptors()[i];
HashMap conCallers = advisor.getConCalledByConInterceptors()[i];
if ((chain != null && chain.length > 0) || methodCallers != null || conCallers != null)
{
ArrayList conNodes = new ArrayList();
if (chain != null && chain.length > 0)
{
conNodes.add(createTreeNode(
"Interceptors",
"Execution Interceptors",
"images/service.gif", "AOPConstructorChain.jsp?classname=" + java.net.URLEncoder.encode(con.getDeclaringClass().getName())
+ "&constructor=" + i,
null, null, null ));
}
if (conCallers != null)
{
conNodes.add(createTreeNode(
"constructor callers",
"constructor caller interceptions",
"images/starfolder.gif", null,
null, createConstructorConstructorCallers(i, advisor, conCallers), null ));
}
if (methodCallers != null)
{
conNodes.add(createTreeNode(
"method callers",
"method caller interceptions",
"images/starfolder.gif", null,
null, createConstructorMethodCallers(i, advisor, methodCallers), null ));
}
TreeNode[] cnodes = (TreeNode[]) conNodes.toArray(new TreeNode[conNodes.size()]);
constructorNodes.add(createTreeNode(
shortenConstructor(advisor.getName(), con), "constructor info", "images/starfolder.gif", null,
null, cnodes, null ));
}
}
if (constructorNodes.size() > 0)
{
TreeNode[] cnodes = (TreeNode[]) constructorNodes.toArray(new TreeNode[constructorNodes.size()]);
nodes.add(createTreeNode(
"Constructors", "constructor info", "images/starfolder.gif", null,
null, cnodes, null ));
}
}
private void populateMethods(ClassAdvisor advisor, ArrayList nodes) throws Exception
{
if (advisor.getMethodInterceptors() == null) return;
ArrayList methodNodes = new ArrayList();
long[] keys = advisor.getMethodInterceptors().keys();
for (int i = 0; i < keys.length; i++)
{
long key = keys[i];
MethodInfo method = (MethodInfo) advisor.getMethodInterceptors().get(key);
HashMap methodCallers = (HashMap) advisor.getMethodCalledByMethodInterceptors().get(key);
HashMap conCallers = (HashMap) advisor.getConCalledByMethodInterceptors().get(key);
if (method == null && methodCallers == null) continue;
if (method != null && methodCallers == null && (method.interceptors == null || method.interceptors.length < 1)) continue;
ArrayList mNodes = new ArrayList();
if (method.interceptors != null && method.interceptors.length > 0 || methodCallers != null || conCallers != null)
{
mNodes.add(createTreeNode(
"Interceptors",
"Execution Interceptors",
"images/service.gif", "AOPMethodChain.jsp?classname=" + java.net.URLEncoder.encode(advisor.getName())
+ "&method=" + keys[i],
null, null, null ));
}
if (conCallers != null)
{
mNodes.add(createTreeNode(
"constructor callers",
"constructor caller interceptions",
"images/starfolder.gif", null,
null, createMethodConstructorCallers(key, advisor, conCallers), null ));
}
if (methodCallers != null)
{
mNodes.add(createTreeNode(
"method callers",
"method caller interceptions",
"images/starfolder.gif", null,
null, createMethodMethodCallers(key, advisor, methodCallers), null ));
}
TreeNode[] mnodes = (TreeNode[]) mNodes.toArray(new TreeNode[mNodes.size()]);
methodNodes.add(createTreeNode(
shortenMethod(advisor.getName(), method.advisedMethod), "method info", "images/starfolder.gif", null,
null, mnodes, null ));
}
if (methodNodes.size() > 0)
{
TreeNode[] cnodes = (TreeNode[]) methodNodes.toArray(new TreeNode[methodNodes.size()]);
nodes.add(createTreeNode(
"Methods", "method info", "images/starfolder.gif", null,
null, cnodes, null ));
}
}
private void populateIntroductions(ClassAdvisor advisor, ArrayList nodes) throws Exception
{
ArrayList introductions = advisor.getInterfaceIntroductions();
if (introductions != null && introductions.size() > 0)
{
TreeNode[] introductionNodes = getIntroductions(advisor);
TreeNode introductionsNode = createTreeNode(
"Introductions", "Introductions for " + advisor.getName(), "images/starfolder.gif", null,
null, introductionNodes, null );
nodes.add(introductionsNode);
}
}
public TreeNode[] createConstructorMethodCallers(int index, ClassAdvisor advisor, HashMap called) throws Exception
{
ArrayList nodes = new ArrayList();
Iterator it = called.keySet().iterator();
while (it.hasNext())
{
String calledClass = (String) it.next();
TLongObjectHashMap map = (TLongObjectHashMap) called.get(calledClass);
Object[] values = map.getValues();
long[] keys = map.keys();
for (int i = 0; i < values.length; i++)
{
CallerMethodInfo caller = (CallerMethodInfo) values[i];
nodes.add(createTreeNode(
caller.method.toString(),
"caller interceptions",
"images/service.gif", "AOPConstructorMethodCallerChain.jsp?index=" + index + "&hash=" + java.net.URLEncoder.encode(Long.toString(keys[i])) + "&classname=" + java.net.URLEncoder.encode(advisor.getName()) + "&calledclassname=" + java.net.URLEncoder.encode(calledClass),
null, null, null ));
}
}
return (TreeNode[]) nodes.toArray(new TreeNode[nodes.size()]);
}
public TreeNode[] createConstructorConstructorCallers(int index, ClassAdvisor advisor, HashMap called) throws Exception
{
ArrayList nodes = new ArrayList();
Iterator it = called.keySet().iterator();
while (it.hasNext())
{
String calledClass = (String) it.next();
TLongObjectHashMap map = (TLongObjectHashMap) called.get(calledClass);
Object[] values = map.getValues();
long[] keys = map.keys();
for (int i = 0; i < values.length; i++)
{
CallerConstructorInfo caller = (CallerConstructorInfo) values[i];
nodes.add(createTreeNode(
caller.constructor.toString(),
"caller interceptions",
"images/service.gif", "AOPConstructorConstructorCallerChain.jsp?index=" + index + "&hash=" + java.net.URLEncoder.encode(Long.toString(keys[i])) + "&classname=" + java.net.URLEncoder.encode(advisor.getName()) + "&calledclassname=" + java.net.URLEncoder.encode(calledClass),
null, null, null ));
}
}
return (TreeNode[]) nodes.toArray(new TreeNode[nodes.size()]);
}
public TreeNode[] createMethodMethodCallers(long callingHash, ClassAdvisor advisor, HashMap called) throws Exception
{
ArrayList nodes = new ArrayList();
Iterator it = called.keySet().iterator();
while (it.hasNext())
{
String calledClass = (String) it.next();
TLongObjectHashMap map = (TLongObjectHashMap) called.get(calledClass);
Object[] values = map.getValues();
long[] keys = map.keys();
for (int i = 0; i < values.length; i++)
{
CallerMethodInfo caller = (CallerMethodInfo) values[i];
nodes.add(createTreeNode(
caller.method.toString(),
"caller interceptions",
"images/service.gif", "AOPMethodMethodCallerChain.jsp?callinghash=" + callingHash + "&hash=" + java.net.URLEncoder.encode(Long.toString(keys[i])) + "&classname=" + java.net.URLEncoder.encode(advisor.getName()) + "&calledclassname=" + java.net.URLEncoder.encode(calledClass),
null, null, null ));
}
}
return (TreeNode[]) nodes.toArray(new TreeNode[nodes.size()]);
}
public TreeNode[] createMethodConstructorCallers(long callingHash, ClassAdvisor advisor, HashMap called) throws Exception
{
ArrayList nodes = new ArrayList();
Iterator it = called.keySet().iterator();
while (it.hasNext())
{
String calledClass = (String) it.next();
TLongObjectHashMap map = (TLongObjectHashMap) called.get(calledClass);
Object[] values = map.getValues();
long[] keys = map.keys();
for (int i = 0; i < values.length; i++)
{
CallerConstructorInfo caller = (CallerConstructorInfo) values[i];
nodes.add(createTreeNode(
caller.constructor.toString(),
"caller interceptions",
"images/service.gif", "AOPMethodConstructorCallerChain.jsp?callinghash=" + callingHash + "&hash=" + java.net.URLEncoder.encode(Long.toString(keys[i])) + "&classname=" + java.net.URLEncoder.encode(advisor.getName()) + "&calledclassname=" + java.net.URLEncoder.encode(calledClass),
null, null, null ));
}
}
return (TreeNode[]) nodes.toArray(new TreeNode[nodes.size()]);
}
public TreeNode[] getUnboundBindings() throws Exception
{
ArrayList unbounded = new ArrayList();
Iterator it = AspectManager.instance().getBindings().values().iterator();
while (it.hasNext())
{
AdviceBinding binding = (AdviceBinding) it.next();
if (!binding.hasAdvisors())
{
unbounded.add(createTreeNode(
binding.getName(),
"Unbounded Binding",
"images/service.gif", "AOPBinding.jsp?binding=" + java.net.URLEncoder.encode(binding.getName()),
null, null, null ));
}
}
if (unbounded.size() == 0) return null;
return (TreeNode[])unbounded.toArray(new TreeNode[unbounded.size()]);
}
TreeNode[] createAOPNodes(Package root) throws Exception
{
ArrayList nodes = new ArrayList();
Iterator it = root.packages.entrySet().iterator();
while (it.hasNext())
{
Map.Entry entry = (Map.Entry) it.next();
String pkgName = (String) entry.getKey();
Package p = (Package) entry.getValue();
nodes.add(createTreeNode(
pkgName, "Package " + pkgName, "images/starfolder.gif", null, null, createAOPNodes(p), null ));
}
it = root.advisors.entrySet().iterator();
while (it.hasNext())
{
Map.Entry entry = (Map.Entry) it.next();
String classname = (String) entry.getKey();
ClassAdvisor advisor = (ClassAdvisor) entry.getValue();
nodes.add(createTreeNode(
classname, "Class " + classname, "images/serviceset.gif", null,
null, createAdvisorNodes(advisor), null )
);
}
TreeNode[] result;
if (nodes.size() == 0)
{
result = null;
}
else
{
result = (TreeNode[]) nodes.toArray(new TreeNode[nodes.size()]);
}
return result;
}
protected TreeNode getTreeForResource(String profile, ManageableResource resource)
{
try
{
TreeNode[] unbounded = getUnboundBindings();
TreeNode[] children = new TreeNode[2];
children[0] = createTreeNode(
"Classes", "Display all Classes", "images/serviceset.gif", null, null,
createAOPNodes(Package.aopClassMap()), null );
children[1] = createTreeNode(
"Unbound Bindings", "Unbound Bindings", "images/serviceset.gif", null, null,
unbounded, null );
return createTreeNode (
"AOP", "AOP Management", "images/spirale32.gif", null, null,
children,
null);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
public static String outputChain(Interceptor[] chain)
{
String output = "";
for (int i = 0; i < chain.length; i++)
{
output += "<tr>";
if (chain[i] instanceof AbstractAdvice)
{
output +="<td><font size=\"1\">advice</font></td><td><font size=\"1\">" + chain[i].getName() + "</font></td>";
}
else if (chain[i] instanceof CFlowInterceptor)
{
output +="<td><font size=\"1\">cflow</font></td><td><font size=\"1\">" + ((CFlowInterceptor) chain[i]).getCFlowString() + "</font></td>";
}
else
{
output +="<td><font size=\"1\">interceptor</font></td><td><font size=\"1\">" + chain[i].getClass().getName() + "</font></td>";
}
output += "</tr>";
}
return output;
}
public void init(ServletConfig servletConfig) throws Exception
{
super.init(servletConfig);
final AOPLister lister = this;
refreshPoller = new Thread(
new Runnable()
{
public void run()
{
try
{
int advisorCount = 0;
while (true)
{
int count = AspectManager.instance().getAdvisors().size();
if (count != advisorCount)
{
lister.pm.regenerateAdminTree();
}
advisorCount = count;
Thread.sleep(20000);
}
}
catch (Throwable e)
{
return;
}
}
}
);
refreshPoller.setDaemon(true);
refreshPoller.start();
}
public void destroy()
{
super.destroy();
try
{
}
catch (Exception e)
{
}
}
}