Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/management/DiagnosticCommandImpl.java
38827 views
/*1* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.management;2627import com.sun.management.DiagnosticCommandMBean;28import java.lang.reflect.Constructor;29import java.lang.reflect.InvocationTargetException;30import java.security.Permission;31import java.util.*;32import javax.management.*;3334/**35* Implementation class for the diagnostic commands subsystem.36*37* @since 838*/39class DiagnosticCommandImpl extends NotificationEmitterSupport40implements DiagnosticCommandMBean {4142private final VMManagement jvm;43private volatile Map<String, Wrapper> wrappers = null;44private static final String strClassName = "".getClass().getName();45private static final String strArrayClassName = String[].class.getName();46private final boolean isSupported;4748@Override49public Object getAttribute(String attribute) throws AttributeNotFoundException,50MBeanException, ReflectionException {51throw new AttributeNotFoundException(attribute);52}5354@Override55public void setAttribute(Attribute attribute) throws AttributeNotFoundException,56InvalidAttributeValueException, MBeanException, ReflectionException {57throw new AttributeNotFoundException(attribute.getName());58}5960@Override61public AttributeList getAttributes(String[] attributes) {62return new AttributeList();63}6465@Override66public AttributeList setAttributes(AttributeList attributes) {67return new AttributeList();68}6970private class Wrapper {7172String name;73String cmd;74DiagnosticCommandInfo info;75Permission permission;7677Wrapper(String name, String cmd, DiagnosticCommandInfo info)78throws InstantiationException {79this.name = name;80this.cmd = cmd;81this.info = info;82this.permission = null;83Exception cause = null;84if (info.getPermissionClass() != null) {85try {86Class c = Class.forName(info.getPermissionClass());87if (info.getPermissionAction() == null) {88try {89Constructor constructor = c.getConstructor(String.class);90permission = (Permission) constructor.newInstance(info.getPermissionName());9192} catch (InstantiationException | IllegalAccessException93| IllegalArgumentException | InvocationTargetException94| NoSuchMethodException | SecurityException ex) {95cause = ex;96}97}98if (permission == null) {99try {100Constructor constructor = c.getConstructor(String.class, String.class);101permission = (Permission) constructor.newInstance(102info.getPermissionName(),103info.getPermissionAction());104} catch (InstantiationException | IllegalAccessException105| IllegalArgumentException | InvocationTargetException106| NoSuchMethodException | SecurityException ex) {107cause = ex;108}109}110} catch (ClassNotFoundException ex) { }111if (permission == null) {112InstantiationException iex =113new InstantiationException("Unable to instantiate required permission");114iex.initCause(cause);115}116}117}118119public String execute(String[] args) {120if (permission != null) {121SecurityManager sm = System.getSecurityManager();122if (sm != null) {123sm.checkPermission(permission);124}125}126if(args == null) {127return executeDiagnosticCommand(cmd);128} else {129StringBuilder sb = new StringBuilder();130sb.append(cmd);131for(int i=0; i<args.length; i++) {132if(args[i] == null) {133throw new IllegalArgumentException("Invalid null argument");134}135sb.append(" ");136sb.append(args[i]);137}138return executeDiagnosticCommand(sb.toString());139}140}141}142143DiagnosticCommandImpl(VMManagement jvm) {144this.jvm = jvm;145isSupported = jvm.isRemoteDiagnosticCommandsSupported();146}147148private static class OperationInfoComparator implements Comparator<MBeanOperationInfo> {149@Override150public int compare(MBeanOperationInfo o1, MBeanOperationInfo o2) {151return o1.getName().compareTo(o2.getName());152}153}154155@Override156public MBeanInfo getMBeanInfo() {157SortedSet<MBeanOperationInfo> operations = new TreeSet<>(new OperationInfoComparator());158Map<String, Wrapper> wrappersmap;159if (!isSupported) {160wrappersmap = (Map<String, Wrapper>) Collections.EMPTY_MAP;161} else {162try {163String[] command = getDiagnosticCommands();164DiagnosticCommandInfo[] info = getDiagnosticCommandInfo(command);165MBeanParameterInfo stringArgInfo[] = new MBeanParameterInfo[]{166new MBeanParameterInfo("arguments", strArrayClassName,167"Array of Diagnostic Commands Arguments and Options")168};169wrappersmap = new HashMap<>();170for (int i = 0; i < command.length; i++) {171String name = transform(command[i]);172try {173Wrapper w = new Wrapper(name, command[i], info[i]);174wrappersmap.put(name, w);175operations.add(new MBeanOperationInfo(176w.name,177w.info.getDescription(),178(w.info.getArgumentsInfo() == null179|| w.info.getArgumentsInfo().isEmpty())180? null : stringArgInfo,181strClassName,182MBeanOperationInfo.ACTION_INFO,183commandDescriptor(w)));184} catch (InstantiationException ex) {185// If for some reasons the creation of a diagnostic command186// wrappers fails, the diagnostic command is just ignored187// and won't appear in the DynamicMBean188}189}190} catch (IllegalArgumentException | UnsupportedOperationException e) {191wrappersmap = (Map<String, Wrapper>) Collections.EMPTY_MAP;192}193}194wrappers = Collections.unmodifiableMap(wrappersmap);195HashMap<String, Object> map = new HashMap<>();196map.put("immutableInfo", "false");197map.put("interfaceClassName","com.sun.management.DiagnosticCommandMBean");198map.put("mxbean", "false");199Descriptor desc = new ImmutableDescriptor(map);200return new MBeanInfo(201this.getClass().getName(),202"Diagnostic Commands",203null, // attributes204null, // constructors205operations.toArray(new MBeanOperationInfo[operations.size()]), // operations206getNotificationInfo(), // notifications207desc);208}209210@Override211public Object invoke(String actionName, Object[] params, String[] signature)212throws MBeanException, ReflectionException {213if (!isSupported) {214throw new UnsupportedOperationException();215}216if (wrappers == null) {217getMBeanInfo();218}219Wrapper w = wrappers.get(actionName);220if (w != null) {221if (w.info.getArgumentsInfo().isEmpty()222&& (params == null || params.length == 0)223&& (signature == null || signature.length == 0)) {224return w.execute(null);225} else if((params != null && params.length == 1)226&& (signature != null && signature.length == 1227&& signature[0] != null228&& signature[0].compareTo(strArrayClassName) == 0)) {229return w.execute((String[]) params[0]);230}231}232throw new ReflectionException(new NoSuchMethodException(actionName));233}234235private static String transform(String name) {236StringBuilder sb = new StringBuilder();237boolean toLower = true;238boolean toUpper = false;239for (int i = 0; i < name.length(); i++) {240char c = name.charAt(i);241if (c == '.' || c == '_') {242toLower = false;243toUpper = true;244} else {245if (toUpper) {246toUpper = false;247sb.append(Character.toUpperCase(c));248} else if(toLower) {249sb.append(Character.toLowerCase(c));250} else {251sb.append(c);252}253}254}255return sb.toString();256}257258private Descriptor commandDescriptor(Wrapper w) throws IllegalArgumentException {259HashMap<String, Object> map = new HashMap<>();260map.put("dcmd.name", w.info.getName());261map.put("dcmd.description", w.info.getDescription());262map.put("dcmd.vmImpact", w.info.getImpact());263map.put("dcmd.permissionClass", w.info.getPermissionClass());264map.put("dcmd.permissionName", w.info.getPermissionName());265map.put("dcmd.permissionAction", w.info.getPermissionAction());266map.put("dcmd.enabled", w.info.isEnabled());267StringBuilder sb = new StringBuilder();268sb.append("help ");269sb.append(w.info.getName());270map.put("dcmd.help", executeDiagnosticCommand(sb.toString()));271if (w.info.getArgumentsInfo() != null && !w.info.getArgumentsInfo().isEmpty()) {272HashMap<String, Object> allargmap = new HashMap<>();273for (DiagnosticCommandArgumentInfo arginfo : w.info.getArgumentsInfo()) {274HashMap<String, Object> argmap = new HashMap<>();275argmap.put("dcmd.arg.name", arginfo.getName());276argmap.put("dcmd.arg.type", arginfo.getType());277argmap.put("dcmd.arg.description", arginfo.getDescription());278argmap.put("dcmd.arg.isMandatory", arginfo.isMandatory());279argmap.put("dcmd.arg.isMultiple", arginfo.isMultiple());280boolean isOption = arginfo.isOption();281argmap.put("dcmd.arg.isOption", isOption);282if(!isOption) {283argmap.put("dcmd.arg.position", arginfo.getPosition());284} else {285argmap.put("dcmd.arg.position", -1);286}287allargmap.put(arginfo.getName(), new ImmutableDescriptor(argmap));288}289map.put("dcmd.arguments", new ImmutableDescriptor(allargmap));290}291return new ImmutableDescriptor(map);292}293294private final static String notifName =295"javax.management.Notification";296297private final static String[] diagFramNotifTypes = {298"jmx.mbean.info.changed"299};300301private MBeanNotificationInfo[] notifInfo = null;302303@Override304public MBeanNotificationInfo[] getNotificationInfo() {305synchronized (this) {306if (notifInfo == null) {307notifInfo = new MBeanNotificationInfo[1];308notifInfo[0] =309new MBeanNotificationInfo(diagFramNotifTypes,310notifName,311"Diagnostic Framework Notification");312}313}314return notifInfo.clone();315}316317private static long seqNumber = 0;318private static long getNextSeqNumber() {319return ++seqNumber;320}321322private void createDiagnosticFrameworkNotification() {323324if (!hasListeners()) {325return;326}327ObjectName on = null;328try {329on = ObjectName.getInstance(ManagementFactoryHelper.HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME);330} catch (MalformedObjectNameException e) { }331Notification notif = new Notification("jmx.mbean.info.changed",332on,333getNextSeqNumber());334notif.setUserData(getMBeanInfo());335sendNotification(notif);336}337338@Override339public synchronized void addNotificationListener(NotificationListener listener,340NotificationFilter filter,341Object handback) {342boolean before = hasListeners();343super.addNotificationListener(listener, filter, handback);344boolean after = hasListeners();345if (!before && after) {346setNotificationEnabled(true);347}348}349350@Override351public synchronized void removeNotificationListener(NotificationListener listener)352throws ListenerNotFoundException {353boolean before = hasListeners();354super.removeNotificationListener(listener);355boolean after = hasListeners();356if (before && !after) {357setNotificationEnabled(false);358}359}360361@Override362public synchronized void removeNotificationListener(NotificationListener listener,363NotificationFilter filter,364Object handback)365throws ListenerNotFoundException {366boolean before = hasListeners();367super.removeNotificationListener(listener, filter, handback);368boolean after = hasListeners();369if (before && !after) {370setNotificationEnabled(false);371}372}373374private native void setNotificationEnabled(boolean enabled);375private native String[] getDiagnosticCommands();376private native DiagnosticCommandInfo[] getDiagnosticCommandInfo(String[] commands);377private native String executeDiagnosticCommand(String command);378379}380381382