init
This commit is contained in:
314
java/org/apache/catalina/manager/JMXProxyServlet.java
Normal file
314
java/org/apache/catalina/manager/JMXProxyServlet.java
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.catalina.manager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.Attribute;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanOperationInfo;
|
||||
import javax.management.MBeanParameterInfo;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.OperationsException;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.catalina.mbeans.MBeanDumper;
|
||||
import org.apache.catalina.tribes.util.StringManager;
|
||||
import org.apache.tomcat.util.modeler.Registry;
|
||||
|
||||
/**
|
||||
* This servlet will dump JMX attributes in a simple format and implement proxy
|
||||
* services for modeler.
|
||||
*
|
||||
* @author Costin Manolache
|
||||
*/
|
||||
public class JMXProxyServlet extends HttpServlet {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// Constant for "no parameters" when invoking a JMX operation
|
||||
// without any parameters.
|
||||
private static final String[] NO_PARAMETERS = new String[0];
|
||||
|
||||
private static final StringManager sm = StringManager.getManager(JMXProxyServlet.class);
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
/**
|
||||
* MBean server.
|
||||
*/
|
||||
protected transient MBeanServer mBeanServer = null;
|
||||
protected transient Registry registry;
|
||||
|
||||
|
||||
// --------------------------------------------------------- Public Methods
|
||||
/**
|
||||
* Initialize this servlet.
|
||||
*/
|
||||
@Override
|
||||
public void init() throws ServletException {
|
||||
// Retrieve the MBean server
|
||||
registry = Registry.getRegistry(null, null);
|
||||
mBeanServer = Registry.getRegistry(null, null).getMBeanServer();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process a GET request for the specified resource.
|
||||
*
|
||||
* @param request The servlet request we are processing
|
||||
* @param response The servlet response we are creating
|
||||
*
|
||||
* @exception IOException if an input/output error occurs
|
||||
* @exception ServletException if a servlet-specified error occurs
|
||||
*/
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException {
|
||||
response.setContentType("text/plain");
|
||||
// Stop older versions of IE thinking they know best. We set text/plain
|
||||
// in the line above for a reason. IE's behaviour is unwanted at best
|
||||
// and dangerous at worst.
|
||||
response.setHeader("X-Content-Type-Options", "nosniff");
|
||||
PrintWriter writer = response.getWriter();
|
||||
|
||||
if (mBeanServer == null) {
|
||||
writer.println("Error - No mbean server");
|
||||
return;
|
||||
}
|
||||
|
||||
String qry = request.getParameter("set");
|
||||
if (qry != null) {
|
||||
String name = request.getParameter("att");
|
||||
String val = request.getParameter("val");
|
||||
|
||||
setAttribute(writer, qry, name, val);
|
||||
return;
|
||||
}
|
||||
qry = request.getParameter("get");
|
||||
if (qry != null) {
|
||||
String name = request.getParameter("att");
|
||||
getAttribute(writer, qry, name, request.getParameter("key"));
|
||||
return;
|
||||
}
|
||||
qry = request.getParameter("invoke");
|
||||
if (qry != null) {
|
||||
String opName = request.getParameter("op");
|
||||
String[] params = getInvokeParameters(request.getParameter("ps"));
|
||||
invokeOperation(writer, qry, opName, params);
|
||||
return;
|
||||
}
|
||||
qry = request.getParameter("qry");
|
||||
if (qry == null) {
|
||||
qry = "*:*";
|
||||
}
|
||||
|
||||
listBeans(writer, qry);
|
||||
}
|
||||
|
||||
|
||||
public void getAttribute(PrintWriter writer, String onameStr, String att, String key) {
|
||||
try {
|
||||
ObjectName oname = new ObjectName(onameStr);
|
||||
Object value = mBeanServer.getAttribute(oname, att);
|
||||
|
||||
if (null != key && value instanceof CompositeData)
|
||||
value = ((CompositeData) value).get(key);
|
||||
|
||||
String valueStr;
|
||||
if (value != null) {
|
||||
valueStr = value.toString();
|
||||
} else {
|
||||
valueStr = "<null>";
|
||||
}
|
||||
|
||||
writer.print("OK - Attribute get '");
|
||||
writer.print(onameStr);
|
||||
writer.print("' - ");
|
||||
writer.print(att);
|
||||
|
||||
if (null != key) {
|
||||
writer.print(" - key '");
|
||||
writer.print(key);
|
||||
writer.print("'");
|
||||
}
|
||||
|
||||
writer.print(" = ");
|
||||
|
||||
writer.println(MBeanDumper.escape(valueStr));
|
||||
} catch (Exception ex) {
|
||||
writer.println("Error - " + ex.toString());
|
||||
ex.printStackTrace(writer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setAttribute(PrintWriter writer, String onameStr, String att, String val) {
|
||||
try {
|
||||
setAttributeInternal(onameStr, att, val);
|
||||
writer.println("OK - Attribute set");
|
||||
} catch (Exception ex) {
|
||||
writer.println("Error - " + ex.toString());
|
||||
ex.printStackTrace(writer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void listBeans(PrintWriter writer, String qry) {
|
||||
|
||||
Set<ObjectName> names = null;
|
||||
try {
|
||||
names = mBeanServer.queryNames(new ObjectName(qry), null);
|
||||
writer.println("OK - Number of results: " + names.size());
|
||||
writer.println();
|
||||
} catch (Exception ex) {
|
||||
writer.println("Error - " + ex.toString());
|
||||
ex.printStackTrace(writer);
|
||||
return;
|
||||
}
|
||||
|
||||
String dump = MBeanDumper.dumpBeans(mBeanServer, names);
|
||||
writer.print(dump);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines if a type is supported by the {@link JMXProxyServlet}.
|
||||
*
|
||||
* @param type The type to check
|
||||
* @return Always returns <code>true</code>
|
||||
*/
|
||||
public boolean isSupported(String type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void invokeOperation(PrintWriter writer, String onameStr, String op,
|
||||
String[] valuesStr) {
|
||||
try {
|
||||
Object retVal = invokeOperationInternal(onameStr, op, valuesStr);
|
||||
if (retVal != null) {
|
||||
writer.println("OK - Operation " + op + " returned:");
|
||||
output("", writer, retVal);
|
||||
} else {
|
||||
writer.println("OK - Operation " + op + " without return value");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
writer.println("Error - " + ex.toString());
|
||||
ex.printStackTrace(writer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses parameter values from a parameter string.
|
||||
*
|
||||
* @param paramString The string containing comma-separated
|
||||
* operation-invocation parameters, or <code>null</code> if there
|
||||
* are no parameters.
|
||||
* @return An array of String parameters (empty array if
|
||||
* <code>paramString</code> was <code>null</code>).
|
||||
*/
|
||||
private String[] getInvokeParameters(String paramString) {
|
||||
if (paramString == null)
|
||||
return NO_PARAMETERS;
|
||||
else
|
||||
return paramString.split(",");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets an MBean attribute's value.
|
||||
*/
|
||||
private void setAttributeInternal(String onameStr, String attributeName, String value)
|
||||
throws OperationsException, MBeanException, ReflectionException {
|
||||
ObjectName oname = new ObjectName(onameStr);
|
||||
String type = registry.getType(oname, attributeName);
|
||||
Object valueObj = registry.convertValue(type, value);
|
||||
mBeanServer.setAttribute(oname, new Attribute(attributeName, valueObj));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invokes an operation on an MBean.
|
||||
*
|
||||
* @param onameStr The name of the MBean.
|
||||
* @param operation The name of the operation to invoke.
|
||||
* @param parameters An array of Strings containing the parameters to the
|
||||
* operation. They will be converted to the appropriate types to
|
||||
* call the requested operation.
|
||||
* @return The value returned by the requested operation.
|
||||
*/
|
||||
@SuppressWarnings("null") // parameters can't be null if signature.length > 0
|
||||
private Object invokeOperationInternal(String onameStr, String operation, String[] parameters)
|
||||
throws OperationsException, MBeanException, ReflectionException {
|
||||
ObjectName oname = new ObjectName(onameStr);
|
||||
int paramCount = null == parameters ? 0 : parameters.length;
|
||||
MBeanOperationInfo methodInfo = registry.getMethodInfo(oname, operation, paramCount);
|
||||
if(null == methodInfo) {
|
||||
// getMethodInfo returns null for both "object not found" and "operation not found"
|
||||
MBeanInfo info = null;
|
||||
try {
|
||||
info = registry.getMBeanServer().getMBeanInfo(oname);
|
||||
} catch (InstanceNotFoundException infe) {
|
||||
throw infe;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(sm.getString("jmxProxyServlet.noBeanFound", onameStr), e);
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
sm.getString("jmxProxyServlet.noOperationOnBean",
|
||||
operation, Integer.valueOf(paramCount), onameStr, info.getClassName()));
|
||||
}
|
||||
|
||||
MBeanParameterInfo[] signature = methodInfo.getSignature();
|
||||
String[] signatureTypes = new String[signature.length];
|
||||
Object[] values = new Object[signature.length];
|
||||
for (int i = 0; i < signature.length; i++) {
|
||||
MBeanParameterInfo pi = signature[i];
|
||||
signatureTypes[i] = pi.getType();
|
||||
values[i] = registry.convertValue(pi.getType(), parameters[i]);
|
||||
}
|
||||
|
||||
return mBeanServer.invoke(oname, operation, values, signatureTypes);
|
||||
}
|
||||
|
||||
|
||||
private void output(String indent, PrintWriter writer, Object result) {
|
||||
if (result instanceof Object[]) {
|
||||
for (Object obj : (Object[]) result) {
|
||||
output(" " + indent, writer, obj);
|
||||
}
|
||||
} else {
|
||||
String strValue;
|
||||
if (result != null) {
|
||||
strValue = result.toString();
|
||||
} else {
|
||||
strValue = "<null>";
|
||||
}
|
||||
writer.println(indent + strValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user