src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/http/MBeanCollectionResource.java
branchjmx-rest-api
changeset 55996 e8d4ccaf6877
parent 55995 a798bdd52997
child 55997 f881344569d9
equal deleted inserted replaced
55995:a798bdd52997 55996:e8d4ccaf6877
     1 package com.oracle.jmx.remote.rest.http;
     1 package com.oracle.jmx.remote.rest.http;
     2 
     2 
     3 import com.oracle.jmx.remote.rest.json.JSONElement;
     3 import com.oracle.jmx.remote.rest.json.JSONElement;
     4 import com.oracle.jmx.remote.rest.json.JSONObject;
     4 import com.oracle.jmx.remote.rest.json.JSONObject;
       
     5 import com.oracle.jmx.remote.rest.json.parser.JSONParser;
       
     6 import com.oracle.jmx.remote.rest.json.parser.ParseException;
     5 import com.oracle.jmx.remote.rest.mapper.JSONMapper;
     7 import com.oracle.jmx.remote.rest.mapper.JSONMapper;
     6 import com.oracle.jmx.remote.rest.mapper.JSONMappingException;
     8 import com.oracle.jmx.remote.rest.mapper.JSONMappingException;
     7 import com.oracle.jmx.remote.rest.mapper.JSONMappingFactory;
     9 import com.oracle.jmx.remote.rest.mapper.JSONMappingFactory;
     8 import com.sun.net.httpserver.HttpExchange;
    10 import com.sun.net.httpserver.HttpExchange;
     9 
    11 
    10 import javax.management.*;
    12 import javax.management.*;
    11 import javax.management.remote.rest.PlatformRestAdapter;
    13 import javax.management.remote.rest.PlatformRestAdapter;
    12 import java.io.IOException;
    14 import java.io.IOException;
    13 import java.io.UnsupportedEncodingException;
    15 import java.io.UnsupportedEncodingException;
       
    16 import java.net.HttpURLConnection;
    14 import java.util.*;
    17 import java.util.*;
    15 import java.util.concurrent.ConcurrentHashMap;
    18 import java.util.concurrent.ConcurrentHashMap;
    16 import java.util.concurrent.CopyOnWriteArrayList;
    19 import java.util.concurrent.CopyOnWriteArrayList;
    17 import java.util.concurrent.CopyOnWriteArraySet;
       
    18 import java.util.regex.Matcher;
    20 import java.util.regex.Matcher;
    19 import java.util.regex.Pattern;
    21 import java.util.regex.Pattern;
    20 
    22 
    21 public class MBeanCollectionResource implements RestResource, NotificationListener {
    23 public class MBeanCollectionResource implements RestResource, NotificationListener {
    22 
    24 
    23     private List<ObjectName> allowedMbeans;
    25     private List<ObjectName> allowedMbeans;
    24     private final MBeanServer mBeanServer;
    26     private final MBeanServer mBeanServer;
    25     private final Map<String, MBeanResource> mBeanResourceMap = new ConcurrentHashMap<>();
    27     private final Map<String, MBeanResource> mBeanResourceMap = new ConcurrentHashMap<>();
    26     private static final int pageSize = 10;
    28     private static final int pageSize = 10;
       
    29     private static final String pathPrefix = "^/?jmx/servers/[a-zA-Z0-9\\-\\.]+/mbeans";
    27 
    30 
    28     private boolean isMBeanAllowed(ObjectName objName) {
    31     private boolean isMBeanAllowed(ObjectName objName) {
    29         try {
    32         try {
    30             MBeanInfo mInfo = mBeanServer.getMBeanInfo(objName);
    33             MBeanInfo mInfo = mBeanServer.getMBeanInfo(objName);
    31             MBeanAttributeInfo[] attrsInfo = mInfo.getAttributes();
    34             MBeanAttributeInfo[] attrsInfo = mInfo.getAttributes();
    90     }
    93     }
    91 
    94 
    92     @Override
    95     @Override
    93     public void handle(HttpExchange exchange) throws IOException {
    96     public void handle(HttpExchange exchange) throws IOException {
    94         String path = exchange.getRequestURI().getPath();
    97         String path = exchange.getRequestURI().getPath();
    95         String pathPrefix = "^/?jmx/servers/[a-zA-Z0-9\\-\\.]+/mbeans";
       
    96         if (path.matches(pathPrefix + "/?$")) {
    98         if (path.matches(pathPrefix + "/?$")) {
    97             RestResource.super.handle(exchange);
    99             RestResource.super.handle(exchange);
    98         } else if (path.matches(pathPrefix + "/[^/]+/?.*")) {
   100         } else if (path.matches(pathPrefix + "/[^/]+/?.*")) {
    99             // Extract mbean name
   101             // Extract mbean name
   100             // Forward the request to its corresponding rest resource
   102             // Forward the request to its corresponding rest resource
   123 
   125 
   124         final String path = PlatformRestAdapter.getAuthority() + exchange.getRequestURI().getPath().replaceAll("\\/$", "");
   126         final String path = PlatformRestAdapter.getAuthority() + exchange.getRequestURI().getPath().replaceAll("\\/$", "");
   125         try {
   127         try {
   126             List<ObjectName> mbeans = allowedMbeans;
   128             List<ObjectName> mbeans = allowedMbeans;
   127             Map<String, String> queryMap = HttpUtil.getGetRequestQueryMap(exchange);
   129             Map<String, String> queryMap = HttpUtil.getGetRequestQueryMap(exchange);
   128             if(queryMap.containsKey("query")) {
   130             if (queryMap.containsKey("query")) {
   129                 Set<ObjectName> queryMBeans = mBeanServer.queryNames(new ObjectName(queryMap.get("query")),null);
   131                 Set<ObjectName> queryMBeans = mBeanServer.queryNames(new ObjectName(queryMap.get("query")), null);
   130                 queryMBeans.retainAll(allowedMbeans);
   132                 queryMBeans.retainAll(allowedMbeans);
   131                 mbeans = new ArrayList<>(queryMBeans);
   133                 mbeans = new ArrayList<>(queryMBeans);
   132             }
   134             }
   133 
   135 
   134             JSONObject _links = HttpUtil.getPaginationLinks(exchange, mbeans, pageSize);
   136             JSONObject _links = HttpUtil.getPaginationLinks(exchange, mbeans, pageSize);
   151             JSONMapper typeMapper2 = JSONMappingFactory.INSTANCE.getTypeMapper(properties);
   153             JSONMapper typeMapper2 = JSONMappingFactory.INSTANCE.getTypeMapper(properties);
   152 
   154 
   153             JSONElement linkElem = typeMapper1.toJsonValue(items);
   155             JSONElement linkElem = typeMapper1.toJsonValue(items);
   154             JSONElement propElem = typeMapper2.toJsonValue(properties);
   156             JSONElement propElem = typeMapper2.toJsonValue(properties);
   155             JSONObject jobj = new JSONObject();
   157             JSONObject jobj = new JSONObject();
   156             if(_links != null && !_links.isEmpty()) {
   158             if (_links != null && !_links.isEmpty()) {
   157                 jobj.put("_links",_links);
   159                 jobj.put("_links", _links);
   158             }
   160             }
   159 
   161 
   160             jobj.putAll((JSONObject) propElem);
   162             jobj.putAll((JSONObject) propElem);
   161             jobj.put("items", linkElem);
   163             jobj.put("items", linkElem);
   162 
   164 
   175         return null;
   177         return null;
   176     }
   178     }
   177 
   179 
   178     @Override
   180     @Override
   179     public HttpResponse doPost(HttpExchange exchange) {
   181     public HttpResponse doPost(HttpExchange exchange) {
   180         return null;
   182         String path = exchange.getRequestURI().getPath();
       
   183         String reqBody = null;
       
   184         try {
       
   185             if (path.matches(pathPrefix + "/?$")) { // POST to current URL
       
   186                 reqBody = HttpUtil.readRequestBody(exchange);
       
   187                 if (reqBody == null || reqBody.isEmpty()) { // No Parameters
       
   188                     return HttpResponse.BAD_REQUEST;
       
   189                 }
       
   190 
       
   191                 JSONParser parser = new JSONParser(reqBody);
       
   192                 JSONElement jsonElement = parser.parse();
       
   193                 if (!(jsonElement instanceof JSONObject)) {
       
   194                     return new HttpResponse(HttpResponse.BAD_REQUEST,
       
   195                             "Invalid parameters : [" + reqBody + "]");
       
   196                 }
       
   197 
       
   198                 JSONObject jsonObject = (JSONObject) jsonElement;
       
   199                 JSONObject result = new JSONObject();
       
   200                 for (String mBeanName : jsonObject.keySet()) {
       
   201                     MBeanResource mBeanResource = mBeanResourceMap.get(mBeanName);
       
   202                     try {
       
   203                     if (mBeanResource == null) {
       
   204                         result.put(mBeanName, "Invalid MBean");
       
   205                     } else {
       
   206                         JSONElement element = jsonObject.get(mBeanName);
       
   207                         if (element instanceof JSONObject) {
       
   208                             JSONElement res = mBeanResource.handleBulkRequest(exchange, (JSONObject) element);
       
   209                             result.put(mBeanName, res);
       
   210                         } else {
       
   211                             result.put(mBeanName, "Invalid input");
       
   212                         }
       
   213                     }} catch (Throwable e) {
       
   214                         e.printStackTrace();
       
   215                     }
       
   216                 }
       
   217                 return new HttpResponse(HttpURLConnection.HTTP_OK, result.toJsonString());
       
   218             } else {
       
   219                 return HttpResponse.METHOD_NOT_ALLOWED;
       
   220             }
       
   221         } catch (ParseException e) {
       
   222             return new HttpResponse(HttpResponse.BAD_REQUEST, "Invalid JSON String for request body");
       
   223         } catch (IOException e) {
       
   224             return HttpResponse.BAD_REQUEST;
       
   225         }
   181     }
   226     }
   182 
   227 
   183     @Override
   228     @Override
   184     public HttpResponse doDelete(HttpExchange exchange) {
   229     public HttpResponse doDelete(HttpExchange exchange) {
   185         return null;
   230         return null;