* @author David Jencks
*/
public class JNDIView
extends ServiceMBeanSupport
implements JNDIViewMBean
{
/**
* Provided for JMX compliance.
*/
public JNDIView()
{
}
/**
* List deployed application java:comp namespaces, the java:
* namespace as well as the global InitialContext JNDI namespace.
*
* @jmx:managed-operation
*
* @param verbose, if true, list the class of each object in addition to its name
*/
public String list(boolean verbose)
{
StringBuffer buffer = new StringBuffer(4096);
Set ejbModules = null;
Context context = null;
ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
// Get all deployed applications so that we can list their
// java: namespaces which are ClassLoader local
try
{
ejbModules = server.queryNames(EjbModule.EJB_MODULE_QUERY_NAME, null);
}
catch (Throwable e)
{
log.error("getDeployedApplications failed", e);
buffer.append("Failed to getDeployedApplications\n");
formatException(buffer, e);
buffer.insert(0, "");
buffer.append(" ");
return buffer.toString();
}
// List each application JNDI namespace
for (Iterator i = ejbModules.iterator(); i.hasNext();)
{
ObjectName app = (ObjectName) i.next();
String module = app.getKeyProperty("module");
if( module == null )
module = app.toString();
buffer.append("Ejb Module: " + module + " \n");
try
{
Collection containers = (Collection) server.getAttribute(app, "Containers");
for (Iterator iter = containers.iterator(); iter.hasNext();)
{
Container con = (Container) iter.next();
/* Set the thread class loader to that of the container as
the class loader is used by the java: context object
factory to partition the container namespaces.
*/
Thread.currentThread().setContextClassLoader(con.getClassLoader());
String bean = con.getBeanMetaData().getEjbName();
buffer.append("java:comp namespace of the " + bean + " bean: \n");
try
{
context = new InitialContext();
context = (Context) context.lookup("java:comp");
}
catch (NamingException e)
{
buffer.append("Failed on lookup, " + e.toString(true));
formatException(buffer, e);
continue;
}
buffer.append("\n");
list(context, " ", buffer, verbose);
buffer.append(" \n");
}
}
catch (Throwable e)
{
log.error("getConainers failed", e);
buffer.append("");
buffer.append("Failed to get ejbs in module\n");
formatException(buffer, e);
buffer.append(" ");
}
}
// List the java: namespace
Thread.currentThread().setContextClassLoader(currentLoader);
try
{
context = new InitialContext();
context = (Context) context.lookup("java:");
buffer.append("java: Namespace \n");
buffer.append("\n");
list(context, " ", buffer, verbose);
buffer.append(" \n");
}
catch (NamingException e)
{
log.error("lookup for java: failed", e);
buffer.append("Failed to get InitialContext, " + e.toString(true));
formatException(buffer, e);
}
// List the global JNDI namespace
try
{
context = new InitialContext();
buffer.append("Global JNDI Namespace \n");
buffer.append("\n");
list(context, " ", buffer, verbose);
buffer.append(" \n");
}
catch (NamingException e)
{
log.error("Failed to get InitialContext", e);
buffer.append("Failed to get InitialContext, " + e.toString(true));
formatException(buffer, e);
}
return buffer.toString();
}
/**
* List deployed application java:comp namespaces, the java:
* namespace as well as the global InitialContext JNDI namespace in a
* XML Format.
*
* @jmx:managed-operation
*
* @param verbose, if true, list the class of each object in addition to its name
**/
public String listXML()
{
StringBuffer buffer = new StringBuffer(4096);
Set ejbModules = null;
Context context = null;
ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
/* Get all deployed applications so that we can list their
java: namespaces which are ClassLoader local
*/
try
{
ejbModules = server.queryNames(EjbModule.EJB_MODULE_QUERY_NAME, null);
}
catch (Exception e)
{
log.error("getDeployedApplications failed", e);
openJndiTag(buffer);
appendErrorTag(buffer,
"Failed to getDeployedApplications " + e.toString());
closeJndiTag(buffer);
return buffer.toString();
}
openJndiTag(buffer);
// List each application JNDI namespace
for (Iterator i = ejbModules.iterator(); i.hasNext();)
{
ObjectName app = (ObjectName) i.next();
openEjbModuleTag(buffer, app.getKeyProperty("url"));
listModuleContainers(buffer, app);
closeEjbModuleTag(buffer);
}
// List the java: namespace
Thread.currentThread().setContextClassLoader(currentLoader);
try
{
context = new InitialContext();
context = (Context) context.lookup("java:");
}
catch (NamingException e)
{
log.error("Failed to get InitialContext for (java:)", e);
appendErrorTag(buffer,
"Failed to get InitialContext for (java:), " +
e.toString(true));
}
if (context != null)
{
openContextTag(buffer);
appendJavaNameTag(buffer);
try
{
listXML(context, buffer);
}
catch (Throwable t)
{
log.error("Failed to list contents of (java:)", t);
appendErrorTag(buffer,
"Failed to list contents of (java:), " +
t.toString());
}
closeContextTag(buffer);
} // if ( context != null )
// List the global JNDI namespace
try
{
context = new InitialContext();
}
catch (NamingException e)
{
log.error("Failed to get InitialContext", e);
appendErrorTag(buffer,
"Failed to get InitialContext, " + e.toString(true));
}
if (context != null)
{
openContextTag(buffer);
appendGlobalNameTag(buffer);
try
{
listXML(context, buffer);
}
catch (Throwable t)
{
log.error("Failed to list global contents ", t);
appendErrorTag(buffer,
"Failed to list global contents, " + t.toString());
}
closeContextTag(buffer);
} // if ( context != null )
closeJndiTag(buffer);
return buffer.toString();
}
protected ObjectName getObjectName(MBeanServer server, ObjectName name)
throws javax.management.MalformedObjectNameException
{
return name == null ? OBJECT_NAME : name;
}
private void list(Context ctx, String indent, StringBuffer buffer, boolean verbose)
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try
{
NamingEnumeration ne = ctx.list("");
while (ne.hasMore())
{
NameClassPair pair = (NameClassPair) ne.next();
log.trace("pair: " + pair);
String name = pair.getName();
String className = pair.getClassName();
boolean recursive = false;
boolean isLinkRef = false;
boolean isProxy = false;
Class c = null;
try
{
c = loader.loadClass(className);
log.trace("type: " + c);
if (Context.class.isAssignableFrom(c))
recursive = true;
if (LinkRef.class.isAssignableFrom(c))
isLinkRef = true;
isProxy = Proxy.isProxyClass(c);
}
catch (ClassNotFoundException cnfe)
{
// If this is a $Proxy* class its a proxy
if (className.startsWith("$Proxy"))
{
isProxy = true;
// We have to get the class from the binding
try
{
Object p = ctx.lookup(name);
c = p.getClass();
}
catch (NamingException e)
{
Throwable t = e.getRootCause();
if (t instanceof ClassNotFoundException)
{
// Get the class name from the exception msg
String msg = t.getMessage();
if (msg != null)
{
// Reset the class name to the CNFE class
className = msg;
}
}
}
}
}
buffer.append(indent + " +- " + name);
// Display reference targets
if (isLinkRef)
{
// Get the
try
{
log.trace("looking up LinkRef; name=" + name);
Object obj = ctx.lookupLink(name);
log.trace("Object type: " + obj.getClass());
LinkRef link = (LinkRef) obj;
buffer.append("[link -> ");
buffer.append(link.getLinkName());
buffer.append(']');
}
catch (Throwable t)
{
log.debug("Invalid LinkRef for: " + name, t);
buffer.append("invalid]");
}
}
// Display proxy interfaces
if (isProxy)
{
buffer.append(" (proxy: " + pair.getClassName());
if (c != null)
{
Class[] ifaces = c.getInterfaces();
buffer.append(" implements ");
for (int i = 0; i < ifaces.length; i++)
{
buffer.append(ifaces[i]);
buffer.append(',');
}
buffer.setCharAt(buffer.length() - 1, ')');
}
else
{
buffer.append(" implements " + className + ")");
}
}
else if (verbose)
{
buffer.append(" (class: " + pair.getClassName() + ")");
}
buffer.append('\n');
if (recursive)
{
try
{
Object value = ctx.lookup(name);
if (value instanceof Context)
{
Context subctx = (Context) value;
list(subctx, indent + " | ", buffer, verbose);
}
else
{
buffer.append(indent + " | NonContext: " + value);
buffer.append('\n');
}
}
catch (Throwable t)
{
buffer.append("Failed to lookup: " + name + ", errmsg=" + t.getMessage());
buffer.append('\n');
}
}
}
ne.close();
}
catch (NamingException ne)
{
buffer.append("error while listing context " + ctx.toString() + ": " + ne.toString(true));
formatException(buffer, ne);
}
}
private void listXML(Context ctx, StringBuffer buffer)
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try
{
NamingEnumeration ne = ctx.list("");
while (ne.hasMore())
{
NameClassPair pair = (NameClassPair) ne.next();
boolean recursive = false;
boolean isLinkRef = false;
try
{
Class c = loader.loadClass(pair.getClassName());
if (Context.class.isAssignableFrom(c))
recursive = true;
if (LinkRef.class.isAssignableFrom(c))
isLinkRef = true;
}
catch (ClassNotFoundException cnfe)
{
}
String name = pair.getName();
if (isLinkRef)
{
Object obj = null;
LinkRef link = null;
try
{
obj = ctx.lookupLink(name);
link = (LinkRef) obj;
}
catch (Throwable t)
{
log.error("Invalid LinkRef for: " + name, t);
appendLinkRefErrorTag(buffer);
}
appendLinkRefTag(buffer, link, pair);
}
else
{
if (recursive)
{
Object value = null;
try
{
value = ctx.lookup(name);
}
catch (Throwable t)
{
appendErrorTag(buffer,
"Failed to lookup: " + name +
", errmsg=" + t.getMessage());
}
if (value instanceof Context)
{
Context subctx = (Context) value;
openContextTag(buffer);
appendNCPTag(buffer, pair);
try
{
listXML(subctx, buffer);
}
catch (Throwable t)
{
appendErrorTag(buffer,
"Failed to list contents of: " + name +
", errmsg=" + t.getMessage());
}
closeContextTag(buffer);
}
else
{
appendNonContextTag(buffer, pair);
}
}
else
{
appendLeafTag(buffer, pair);
}
}
}
ne.close();
}
catch (NamingException ne)
{
appendErrorTag(buffer,
"error while listing context " +
ctx.toString() + ": " + ne.toString(true));
}
}
private void listModuleContainers(StringBuffer buffer, ObjectName app)
{
Collection containers = null;
try
{
containers = (Collection) server.getAttribute(app, "Containers");
}
catch (Throwable t)
{
log.error("getContainers failed", t);
appendPreExceptionTag(buffer, "Failed to get ejbs in module", t);
}
for (Iterator iter = containers.iterator(); iter.hasNext();)
{
listContainerContext(buffer, (Container) iter.next());
}
} // listModuleContainers()
private void listContainerContext(StringBuffer buffer, Container con)
{
/* Set the thread class loader to that of the container as
the class loader is used by the java: context object
factory to partition the container namespaces.
*/
Thread.currentThread().setContextClassLoader(con.getClassLoader());
String bean = con.getBeanMetaData().getEjbName();
openContextTag(buffer);
appendBeanTag(buffer, bean);
Context context = null;
try
{
context = new InitialContext();
context = (Context) context.lookup("java:comp");
}
catch (NamingException e)
{
appendErrorTag(buffer,
"Failed on lookup " + e.toString(true));
context = null;
}
if (context != null)
{
try
{
listXML(context, buffer);
}
catch (Throwable t)
{
appendErrorTag(buffer,
"Failed on list contents, " + t.toString());
}
} // if ( context != null )
closeContextTag(buffer);
} // listContainerContext()
private void openJndiTag(StringBuffer buffer)
{
buffer.append("\n");
}
private void closeJndiTag(StringBuffer buffer)
{
buffer.append(" \n");
}
private void openEjbModuleTag(StringBuffer buffer, String file)
{
buffer.append("\n");
buffer.append("" + file + " \n");
}
private void closeEjbModuleTag(StringBuffer buffer)
{
buffer.append(" \n");
}
private void appendPreExceptionTag(StringBuffer buffer,
String msg,
Throwable t)
{
buffer.append("\n" + msg+"\n");
formatException(buffer, t);
buffer.append(" \n");
}
private void appendBeanTag(StringBuffer buffer, String bean)
{
buffer.append("java:comp \n");
buffer.append("" + bean + " \n");
}
private void appendJavaNameTag(StringBuffer buffer)
{
buffer.append("java: \n");
}
private void appendGlobalNameTag(StringBuffer buffer)
{
buffer.append("Global \n");
}
private void appendLinkRefTag(StringBuffer buffer,
LinkRef link,
NameClassPair ncp)
{
buffer.append("\n");
buffer.append("" + ncp.getName() + " \n");
try
{
String lName = link.getLinkName();
buffer.append(" " + lName + "\n");
}
catch (NamingException e)
{
appendErrorTag(buffer,
"Failed to getLinkName, " + e.toString(true));
}
buffer.append("" + ncp.getClassName() +
" \n");
buffer.append(" \n");
}
private void appendLinkRefErrorTag(StringBuffer buffer)
{
buffer.append("\n");
buffer.append("Invalid \n");
buffer.append(" \n");
}
private void openContextTag(StringBuffer buffer)
{
buffer.append("\n");
}
private void closeContextTag(StringBuffer buffer)
{
buffer.append(" \n");
}
private void appendNonContextTag(StringBuffer buffer, NameClassPair ncp)
{
buffer.append("\n");
appendNCPTag(buffer, ncp);
buffer.append(" \n");
}
private void appendLeafTag(StringBuffer buffer, NameClassPair ncp)
{
buffer.append("\n");
appendNCPTag(buffer, ncp);
buffer.append(" \n");
}
private void appendNCPTag(StringBuffer buffer, NameClassPair ncp)
{
buffer.append("" + ncp.getName() + " \n");
buffer.append("" + ncp.getClassName() +
" \n");
}
private void appendErrorTag(StringBuffer buffer, String msg)
{
buffer.append("\n");
buffer.append("" + msg + " \n");
buffer.append(" \n");
}
private void formatException(StringBuffer buffer, Throwable t)
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
buffer.append("\n");
t.printStackTrace(pw);
buffer.append(sw.toString());
buffer.append(" \n");
}
}