/*
* 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 jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.catalina.mbeans.MBeanDumper;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.res.StringManager;
/**
* 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 = 1 L;
// 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;charset=" + Constants.CHARSET);
// 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);
}
}
}
Messung V0.5 in Prozent C=94 H=92 G=92
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland