Java Code Examples for javax.management.MBeanOperationInfo#getSignature()

The following examples show how to use javax.management.MBeanOperationInfo#getSignature() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: JMXProxyServlet.java    From Tomcat8-Source-Read with MIT License 6 votes vote down vote up
/**
 * 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.
 */
private Object invokeOperationInternal(String onameStr, String operation, String[] parameters)
        throws OperationsException, MBeanException, ReflectionException {
    ObjectName oname = new ObjectName(onameStr);
    MBeanOperationInfo methodInfo = registry.getMethodInfo(oname, operation);
    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);
}
 
Example 2
Source File: JMXResource.java    From karyon with Apache License 2.0 6 votes vote down vote up
/**
 * Generate JSON for the MBean operations
 *
 * @param objName
 * @return
 * @throws Exception
 */
private JSONArray emitOperations(ObjectName objName) throws Exception {
    MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
    MBeanInfo mBeanInfo = mBeanServer.getMBeanInfo(objName);
    JSONArray ar = new JSONArray();

    MBeanOperationInfo[] operations = mBeanInfo.getOperations();
    for (MBeanOperationInfo operation : operations) {
        JSONObject obj = new JSONObject();
        obj.put("name", operation.getName());
        obj.put("description", operation.getDescription());
        obj.put("returnType", operation.getReturnType());
        obj.put("impact", operation.getImpact());

        JSONArray params = new JSONArray();
        for (MBeanParameterInfo param : operation.getSignature()) {
            JSONObject p = new JSONObject();
            p.put("name", param.getName());
            p.put("type", param.getType());
            params.put(p);
        }
        obj.put("params", params);
        ar.put(obj);
    }
    return ar;
}
 
Example 3
Source File: Server.java    From ironjacamar with Eclipse Public License 1.0 6 votes vote down vote up
/**
 * Invoke an operation
 * @param name The bean name
 * @param index The method index
 * @param args The arguments
 * @return The result
 * @exception JMException Thrown if an error occurs
 */
public static OpResultInfo invokeOp(String name, int index, String[] args) throws JMException
{
   MBeanServer server = getMBeanServer();
   ObjectName objName = new ObjectName(name);
   MBeanInfo info = server.getMBeanInfo(objName);
   MBeanOperationInfo[] opInfo = info.getOperations();
   MBeanOperationInfo op = opInfo[index];
   MBeanParameterInfo[] paramInfo = op.getSignature();
   String[] argTypes = new String[paramInfo.length];

   for (int p = 0; p < paramInfo.length; p++)
      argTypes[p] = paramInfo[p].getType();
 
   return invokeOpByName(name, op.getName(), argTypes, args);
}
 
Example 4
Source File: JMXProxyServlet.java    From Tomcat7.0.67 with Apache License 2.0 6 votes vote down vote up
/**
 * 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 reuested operation.
 * @return The value returned by the requested operation.
 */
private Object invokeOperationInternal(String onameStr,
                                       String operation,
                                       String[] parameters)
    throws OperationsException, MBeanException, ReflectionException {
    ObjectName oname=new ObjectName( onameStr );
    MBeanOperationInfo methodInfo = registry.getMethodInfo(oname,operation);
    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);
}
 
Example 5
Source File: JMXProxyServlet.java    From tomcatsrc with Apache License 2.0 6 votes vote down vote up
/**
 * 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 reuested operation.
 * @return The value returned by the requested operation.
 */
private Object invokeOperationInternal(String onameStr,
                                       String operation,
                                       String[] parameters)
    throws OperationsException, MBeanException, ReflectionException {
    ObjectName oname=new ObjectName( onameStr );
    MBeanOperationInfo methodInfo = registry.getMethodInfo(oname,operation);
    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);
}
 
Example 6
Source File: DynamicMBeanFactoryOperationsTest.java    From datakernel with Apache License 2.0 6 votes vote down vote up
public static Matcher<MBeanOperationInfo> hasParameter(String name, String type) {
	return new BaseMatcher<MBeanOperationInfo>() {
		@Override
		public boolean matches(Object item) {
			if (item == null) {
				return false;
			}
			MBeanOperationInfo operation = (MBeanOperationInfo) item;
			for (MBeanParameterInfo param : operation.getSignature()) {
				if (param.getName().equals(name) && param.getType().equals(type)) {
					return true;
				}
			}
			return false;
		}

		@Override
		public void describeTo(Description description) {
			description.appendText("has parameter with name \"" + name + "\" and type \"" + type + "\"");
		}
	};
}
 
Example 7
Source File: IgniteStandardMXBean.java    From ignite with Apache License 2.0 6 votes vote down vote up
/**
 * Gets method by operation info.
 *
 * @param op MBean operation info.
 * @return Method.
 * @throws ClassNotFoundException Thrown if parameter type is unknown.
 * @throws SecurityException Thrown if method access is not allowed.
 */
private Method getMethod(MBeanOperationInfo op) throws ClassNotFoundException, SecurityException {
    String mtdName = op.getName();

    MBeanParameterInfo[] signature = op.getSignature();

    Class<?>[] params = new Class<?>[signature.length];

    for (int i = 0; i < signature.length; i++) {
        // Parameter type is either a primitive type or class. Try both.
        Class<?> type = primCls.get(signature[i].getType().toLowerCase());

        if (type == null)
            type = Class.forName(signature[i].getType());

        params[i] = type;
    }

    return findMethod(getMBeanInterface(), mtdName, params);
}
 
Example 8
Source File: GroovyMBean.java    From groovy with Apache License 2.0 6 votes vote down vote up
/**
 * Description of the operation.
 *
 * @param operation the operation to describe
 * @return pretty-printed description
 */
protected String describeOperation(MBeanOperationInfo operation) {
    StringBuilder buf = new StringBuilder();
    buf.append(operation.getReturnType())
            .append(" ")
            .append(operation.getName())
            .append("(");

    MBeanParameterInfo[] params = operation.getSignature();
    for (int j = 0; j < params.length; j++) {
        MBeanParameterInfo param = params[j];
        if (j != 0) {
            buf.append(", ");
        }
        buf.append(param.getType())
                .append(" ")
                .append(param.getName());
    }
    buf.append(")");
    return buf.toString();
}
 
Example 9
Source File: JmxClientTest.java    From simplejmx with ISC License 5 votes vote down vote up
@Test
public void testGetOperationInfo() throws Exception {
	MBeanOperationInfo info = client.getOperationInfo(objectName, "times");
	assertNotNull(info);
	MBeanParameterInfo[] params = info.getSignature();
	assertEquals(2, params.length);
	assertEquals(short.class.getName(), params[0].getType());
	assertEquals(int.class.getName(), params[1].getType());
	assertEquals(long.class.getName(), info.getReturnType());
}
 
Example 10
Source File: CommandLineJmxClient.java    From simplejmx with ISC License 5 votes vote down vote up
private void listOperations(String[] parts) {
	ObjectName currentName = getObjectName("opers", parts);
	if (currentName == null) {
		return;
	}
	if (parts.length != 2) {
		System.out.println("Error.  Usage: ops objectName");
		return;
	}

	MBeanOperationInfo[] opers;
	try {
		opers = jmxClient.getOperationsInfo(currentName);
	} catch (Exception e) {
		System.out.println("Error.  Problems getting information about name: " + e.getMessage());
		return;
	}
	for (MBeanOperationInfo info : opers) {
		System.out.print("  " + info.getReturnType() + " " + info.getName() + "(");
		boolean first = true;
		for (MBeanParameterInfo param : info.getSignature()) {
			if (first) {
				first = false;
			} else {
				System.out.print(", ");
			}
			System.out.print(param.getType());
		}
		System.out.println(")");
	}
}
 
Example 11
Source File: PluggableMBeanServerImpl.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
private boolean isOperationReadOnly(ObjectName name, String operationName, String[] signature) {
    MBeanInfo info;
    try {
        info = getMBeanInfo(name, false, true);
    } catch (Exception e) {
        //This should not happen, just in case say it is not RO
        return false;
    }
    if (info == null) {
        //Default to not RO
        return false;
    }
    for (MBeanOperationInfo op : info.getOperations()) {
        if (op.getName().equals(operationName)) {
            MBeanParameterInfo[] params = op.getSignature();
            if (params.length != signature.length) {
                continue;
            }
            boolean same = true;
            for (int i = 0 ; i < params.length ; i++) {
                if (!params[i].getType().equals(signature[i])) {
                    same = false;
                    break;
                }
            }
            if (same) {
                return op.getImpact() == MBeanOperationInfo.INFO;
            }
        }
    }
    //Default to not RO
    return false;
}
 
Example 12
Source File: GroovyMBean.java    From groovy with Apache License 2.0 5 votes vote down vote up
protected String[] createSignature(MBeanOperationInfo info) {
    MBeanParameterInfo[] params = info.getSignature();
    String[] answer = new String[params.length];
    for (int i = 0; i < params.length; i++) {
        answer[i] = params[i].getType();
    }
    return answer;
}
 
Example 13
Source File: OperationKey.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
public OperationKey(final MBeanOperationInfo info) {
  checkNotNull(info);
  this.name = info.getName();
  ImmutableList.Builder<String> builder = ImmutableList.builder();
  for (MBeanParameterInfo pinfo : info.getSignature()) {
    builder.add(pinfo.getType());
  }
  this.types = builder.build();
}
 
Example 14
Source File: MBeanCommand.java    From arthas with Apache License 2.0 5 votes vote down vote up
private void drawOperationInfo(MBeanOperationInfo[] operations, TableElement table) {
    for (MBeanOperationInfo operation : operations) {
        table.row(new LabelElement("MBeanOperationInfo").style(Decoration.bold.fg(Color.red)));
        table.row(new LabelElement("Operation:").style(Decoration.bold.fg(Color.yellow)));
        table.row("Name", operation.getName());
        table.row("Description", operation.getDescription());
        String impact = "";
        switch (operation.getImpact()) {
            case ACTION:
                impact = "action";
                break;
            case ACTION_INFO:
                impact = "action/info";
                break;
            case INFO:
                impact = "info";
                break;
            case UNKNOWN:
                impact = "unknown";
                break;
        }
        table.row("Impact", impact);
        table.row("ReturnType", operation.getReturnType());
        MBeanParameterInfo[] signature = operation.getSignature();
        if (signature.length > 0) {
            for (int i = 0; i < signature.length; i++) {
                table.row(new LabelElement("Parameter-" + i).style(Decoration.bold.fg(Color.yellow)));
                table.row("Name", signature[i].getName());
                table.row("Type", signature[i].getType());
                table.row("Description", signature[i].getDescription());
            }
        }
        drawDescriptorInfo("Operation Descriptor:", operation, table);
    }
}
 
Example 15
Source File: Client.java    From vjtools with Apache License 2.0 5 votes vote down vote up
protected static Object doBeanOperation(MBeanServerConnection mbsc, ObjectInstance instance, String command,
		MBeanOperationInfo[] infos) throws Exception {
	// Parse command line.
	CommandParse parse = new CommandParse(command);

	// Get first method of name 'cmd'. Assumption is no method
	// overrides. Then, look at the method and use its signature
	// to make sure client sends over parameters of the correct type.
	MBeanOperationInfo op = (MBeanOperationInfo) getFeatureInfo(infos, parse.getCmd());
	Object result = null;
	if (op == null) {
		result = "Operation " + parse.getCmd() + " not found.";
	} else {
		MBeanParameterInfo[] paraminfos = op.getSignature();
		int paraminfosLength = (paraminfos == null) ? 0 : paraminfos.length;
		int objsLength = (parse.getArgs() == null) ? 0 : parse.getArgs().length;
		if (paraminfosLength != objsLength) {
			result = "Passed param count does not match signature count";
		} else {
			String[] signature = new String[paraminfosLength];
			Object[] params = (paraminfosLength == 0) ? null : new Object[paraminfosLength];
			for (int i = 0; i < paraminfosLength; i++) {
				MBeanParameterInfo paraminfo = paraminfos[i];
				java.lang.reflect.Constructor c = Class.forName(paraminfo.getType())
						.getConstructor(new Class[] { String.class });
				params[i] = c.newInstance(new Object[] { parse.getArgs()[i] });
				signature[i] = paraminfo.getType();
			}
			result = mbsc.invoke(instance.getObjectName(), parse.getCmd(), params, signature);
		}
	}
	return result;
}
 
Example 16
Source File: Client.java    From vjtools with Apache License 2.0 5 votes vote down vote up
protected static Object doBeanOperation(MBeanServerConnection mbsc, ObjectInstance instance, String command,
		MBeanOperationInfo[] infos) throws Exception {
	// Parse command line.
	CommandParse parse = new CommandParse(command);

	// Get first method of name 'cmd'. Assumption is no method
	// overrides. Then, look at the method and use its signature
	// to make sure client sends over parameters of the correct type.
	MBeanOperationInfo op = (MBeanOperationInfo) getFeatureInfo(infos, parse.getCmd());
	Object result = null;
	if (op == null) {
		result = "Operation " + parse.getCmd() + " not found.";
	} else {
		MBeanParameterInfo[] paraminfos = op.getSignature();
		int paraminfosLength = (paraminfos == null) ? 0 : paraminfos.length;
		int objsLength = (parse.getArgs() == null) ? 0 : parse.getArgs().length;
		if (paraminfosLength != objsLength) {
			result = "Passed param count does not match signature count";
		} else {
			String[] signature = new String[paraminfosLength];
			Object[] params = (paraminfosLength == 0) ? null : new Object[paraminfosLength];
			for (int i = 0; i < paraminfosLength; i++) {
				MBeanParameterInfo paraminfo = paraminfos[i];
				java.lang.reflect.Constructor c = Class.forName(paraminfo.getType())
						.getConstructor(new Class[] { String.class });
				params[i] = c.newInstance(new Object[] { parse.getArgs()[i] });
				signature[i] = paraminfo.getType();
			}
			result = mbsc.invoke(instance.getObjectName(), parse.getCmd(), params, signature);
		}
	}
	return result;
}
 
Example 17
Source File: JMXInterpreter.java    From sql-layer with GNU Affero General Public License v3.0 4 votes vote down vote up
public Object makeBeanCall(String host,
                           int port,
                           String objectName,
                           String method,
                           Object[] parameters,
                           String callType) throws Exception {
    ensureConnection(host, port);
    if(adapter == null) {
        throw new Exception("Can't connect");
    }
    MBeanServerConnection mbs = adapter.getConnection();
    ObjectName mxbeanName = new ObjectName(objectName);

    MBeanInfo info = mbs.getMBeanInfo(mxbeanName);
    String[] signature = null;
    if(callType.equalsIgnoreCase("method")) {
        for(MBeanOperationInfo op : info.getOperations()) {
            if(method.equalsIgnoreCase(op.getDescription())) {
                signature = new String[op.getSignature().length];
                for(int a = 0; a < op.getSignature().length; a++) {
                    signature[a] = op.getSignature()[a].getType();
                }
                break;
            }
        }
    }
    Object data = null;
    if(callType.equalsIgnoreCase("method")) {
        data = mbs.invoke(mxbeanName, method, parameters, signature);
    } else if(callType.equalsIgnoreCase("get")) {
        data = mbs.getAttribute(mxbeanName, method);
    } else {
        Attribute attr = null;
        for(int x = 0; x < info.getAttributes().length; x++) {
            if(method.equalsIgnoreCase(info.getAttributes()[x].getName())) {
                if(info.getAttributes()[x].getType().equalsIgnoreCase(double.class.getName())) {
                    attr = new Attribute(method, new Double(String.valueOf(parameters[0])));
                } else if(info.getAttributes()[x].getType().equalsIgnoreCase(long.class.getName())) {
                    attr = new Attribute(method, new Long(String.valueOf(parameters[0])));
                } else if(info.getAttributes()[x].getType().equalsIgnoreCase(int.class.getName())) {
                    attr = new Attribute(method, new Integer(String.valueOf(parameters[0])));
                } else if(info.getAttributes()[x].getType().equalsIgnoreCase(String.class.getName())) {
                    attr = new Attribute(method, String.valueOf(parameters[0]));
                } else if(info.getAttributes()[x].getType().equalsIgnoreCase(Boolean.class.getName())) {
                    attr = new Attribute(method, Boolean.valueOf(String.valueOf(parameters[0])));
                } else {
                    throw new Exception("Unknown Attribute type found as " + info.getAttributes()[x].getType());
                }
                break;
            }
        }
        mbs.setAttribute(mxbeanName, attr);
    }

    return data;
}
 
Example 18
Source File: JMXResource.java    From karyon with Apache License 2.0 4 votes vote down vote up
/**
 * Return all the attributes and operations for a single mbean
 *
 * @param key
 *            Exact object name of MBean in String form
 * @param jsonp
 */
@GET
@Path("{key}")
public Response getMBean(@PathParam("key") String key,
                         @QueryParam("jsonp") @DefaultValue("") String jsonp)
        throws Exception {
    LOG.info("key: " + key);

    JSONObject json = new JSONObject();

    ObjectName name = new ObjectName(key);
    json.put("domain", name.getDomain());
    json.put("property", name.getKeyPropertyList());

    if (key.contains("*")) {
        JSONObject keys = new JSONObject();
        for (Entry<String, Map<String, String>> attrs : jmx
                .getMBeanAttributesByRegex(key).entrySet()) {
            keys.put(attrs.getKey(), attrs.getValue());
        }
        json.put("attributes", keys);
        json.put("multikey", true);
    } else {
        json.put("attributes", jmx.getMBeanAttributes(key));
        json.put("multikey", false);

        MBeanOperationInfo[] operations = jmx.getMBeanOperations(key);
        JSONArray ar = new JSONArray();
        for (MBeanOperationInfo operation : operations) {
            JSONObject obj = new JSONObject();
            obj.put("name", operation.getName());
            obj.put("description", operation.getDescription());
            obj.put("returnType", operation.getReturnType());
            obj.put("impact", operation.getImpact());

            JSONArray params = new JSONArray();
            for (MBeanParameterInfo param : operation.getSignature()) {
                JSONObject p = new JSONObject();
                p.put("name", param.getName());
                p.put("type", param.getType());
                params.put(p);
            }
            obj.put("params", params);
            ar.put(obj);
        }
        json.put("operations", ar);
    }

    StringWriter out = new StringWriter();
    if (jsonp.isEmpty()) {
        json.write(out);
    } else {
        out.append(jsonp).append("(");
        json.write(out);
        out.append(");");
    }
    return Response.ok(out.toString()).type(MediaType.APPLICATION_JSON)
            .build();
}
 
Example 19
Source File: JmxClient.java    From simplejmx with ISC License 4 votes vote down vote up
private String[] lookupParamTypes(ObjectName objectName, String operName, Object[] params) throws JMException {
	checkClientConnected();
	MBeanOperationInfo[] operations;
	try {
		operations = mbeanConn.getMBeanInfo(objectName).getOperations();
	} catch (Exception e) {
		throw createJmException("Cannot get attribute info from " + objectName, e);
	}
	String[] paramTypes = new String[params.length];
	for (int i = 0; i < params.length; i++) {
		paramTypes[i] = params[i].getClass().getName();
	}
	int nameC = 0;
	String[] first = null;
	for (MBeanOperationInfo info : operations) {
		if (!info.getName().equals(operName)) {
			continue;
		}
		MBeanParameterInfo[] mbeanParams = info.getSignature();
		if (params.length != mbeanParams.length) {
			continue;
		}
		String[] signatureTypes = new String[mbeanParams.length];
		for (int i = 0; i < params.length; i++) {
			signatureTypes[i] = mbeanParams[i].getType();
		}
		if (paramTypes.length == signatureTypes.length) {
			boolean found = true;
			for (int i = 0; i < paramTypes.length; i++) {
				if (!isClassNameEquivalent(paramTypes[i], signatureTypes[i])) {
					found = false;
					break;
				}
			}
			if (found) {
				return signatureTypes;
			}
		}
		first = signatureTypes;
		nameC++;
	}

	if (first == null) {
		throw new IllegalArgumentException("Cannot find operation named '" + operName + "'");
	} else if (nameC > 1) {
		throw new IllegalArgumentException(
				"Cannot find operation named '" + operName + "' with matching argument types");
	} else {
		// return the first one we found that matches the name
		return first;
	}
}
 
Example 20
Source File: MBeanInfoRenderer.java    From text-ui with GNU General Public License v3.0 4 votes vote down vote up
@Override
public LineRenderer renderer(Iterator<MBeanInfo> stream) {

  List<LineRenderer> renderers = new ArrayList<LineRenderer>();

  while (stream.hasNext()) {
    MBeanInfo info = stream.next();

    //
    TreeElement root = new TreeElement(info.getClassName());

    // Descriptor
    TableElement descriptor = new TableElement().
        overflow(Overflow.HIDDEN).
        rightCellPadding(1);
    Descriptor descriptorInfo = info.getDescriptor();
    if (descriptorInfo != null) {
      for (String fieldName : descriptorInfo.getFieldNames()) {
        String fieldValue = String.valueOf(descriptorInfo.getFieldValue(fieldName));
        descriptor.row(fieldName, fieldValue);
      }
    }

    // Attributes
    TableElement attributes = new TableElement().
        overflow(Overflow.HIDDEN).
        rightCellPadding(1).
        add(new RowElement().style(Decoration.bold.fg(Color.black).bg(Color.white)).add("NAME", "TYPE", "DESCRIPTION"));
    for (MBeanAttributeInfo attributeInfo : info.getAttributes()) {
      attributes.row(attributeInfo.getName(), attributeInfo.getType(), attributeInfo.getDescription());
    }

    // Operations
    TreeElement operations = new TreeElement("Operations");
    for (MBeanOperationInfo operationInfo : info.getOperations()) {
      TableElement signature = new TableElement().
          overflow(Overflow.HIDDEN).
          rightCellPadding(1);
      MBeanParameterInfo[] parameterInfos = operationInfo.getSignature();
      for (MBeanParameterInfo parameterInfo : parameterInfos) {
        signature.row(parameterInfo.getName(), parameterInfo.getType(), parameterInfo.getDescription());
      }
      TreeElement operation = new TreeElement(operationInfo.getName());
      String impact;
      switch (operationInfo.getImpact()) {
        case MBeanOperationInfo.ACTION:
          impact = "ACTION";
          break;
        case MBeanOperationInfo.INFO:
          impact = "INFO";
          break;
        case MBeanOperationInfo.ACTION_INFO:
          impact = "ACTION_INFO";
          break;
        default:
          impact = "UNKNOWN";
      }
      operation.addChild(new TableElement().
          add(
              new RowElement().add("Type: ", operationInfo.getReturnType()),
              new RowElement().add("Description: ", operationInfo.getDescription()),
              new RowElement().add("Impact: ", impact),
              new RowElement().add(new LabelElement("Signature: "), signature)
          )
      );

      operations.addChild(operation);
    }

    //
    root.addChild(
      new TableElement().leftCellPadding(1).overflow(Overflow.HIDDEN).
        row("ClassName", info.getClassName()).
        row("Description", info.getDescription()
      )
    );
    root.addChild(new TreeElement("Descriptor").addChild(descriptor));
    root.addChild(new TreeElement("Attributes").addChild(attributes));
    root.addChild(operations);

    //
    renderers.add(root.renderer());
  }




  return LineRenderer.vertical(renderers);
}