REST Adapter Initial commit jmx-rest-api
authorhb
Tue, 29 Aug 2017 13:34:15 +0530
branchjmx-rest-api
changeset 55985 0c5a02edfdef
parent 55984 a43ae4e5fa0a
child 55986 d1fa2463bc02
REST Adapter Initial commit 1. Unit tested and working GET/POST interfaces 2. Unit tested and working JSON parser
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/http/GetRequestHandler.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/http/HttpResponse.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/http/PostRequestHandler.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/JSONArray.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/JSONElement.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/JSONObject.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/JSONPrimitive.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/JSONParser.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/JSONParserConstants.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/JSONParserTokenManager.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/JavaCharStream.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/JsonParser.jj
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/ParseException.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/Token.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/TokenMgrError.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/mapper/JSONDataException.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/mapper/JSONMapper.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/mapper/JSONMappingException.java
src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/mapper/JSONMappingFactory.java
src/java.management.rest/share/classes/javax/management/remote/rest/JmxRestAdapter.java
src/java.management.rest/share/classes/javax/management/remote/rest/JmxRestAdapterImpl.java
src/java.management.rest/share/classes/javax/management/remote/rest/PlatformRestAdapter.java
src/java.management.rest/share/classes/module-info.java
src/java.management/share/classes/module-info.java
src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java
src/jdk.management.agent/share/classes/module-info.java
test/javax/management/remote/rest/DefaultRestAdapter.java
test/javax/management/remote/rest/JsonParserTest.java
test/javax/management/remote/rest/PlatformAdapterTest.java
test/javax/management/remote/rest/PlatformMBeanTest.java
test/javax/management/remote/rest/RestAdapterSSLTest.java
test/javax/management/remote/rest/RunRestAdapter.java
test/javax/management/remote/rest/data/QueueSample.java
test/javax/management/remote/rest/data/QueueSampler.java
test/javax/management/remote/rest/data/QueueSamplerBean.java
test/javax/management/remote/rest/data/QueueSamplerBeanMBean.java
test/javax/management/remote/rest/data/QueueSamplerMXBean.java
test/javax/management/remote/rest/json/JSONTest.java
test/javax/management/remote/rest/management.properties
test/javax/management/remote/rest/management1.properties
test/javax/management/remote/rest/mgmt.properties
test/javax/management/remote/rest/mgmt1.properties
test/javax/management/remote/rest/password.properties
test/javax/management/remote/rest/server.cer
test/javax/management/remote/rest/sslConfigAgent
test/javax/management/remote/rest/sslConfigClient
test/javax/management/remote/rest/sslconfig
test/javax/management/remote/rest/sslconfigClient
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/http/GetRequestHandler.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,362 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.http;
+
+import javax.management.*;
+import com.oracle.jmx.remote.rest.json.JSONArray;
+import com.oracle.jmx.remote.rest.json.JSONObject;
+import com.oracle.jmx.remote.rest.json.JSONPrimitive;
+import com.oracle.jmx.remote.rest.mapper.JSONMappingException;
+import com.oracle.jmx.remote.rest.mapper.JSONMappingFactory;
+import java.net.HttpURLConnection;
+import java.util.*;
+
+import static javax.management.MBeanOperationInfo.*;
+
+/**
+ * @author harsha
+ */
+public class GetRequestHandler {
+
+    private final MBeanServer mbeanServer;
+    private final List<String> allowedMBeans;
+    public GetRequestHandler(MBeanServer mServer, List<String> allowedMBeans) {
+        this.mbeanServer = mServer;
+        this.allowedMBeans = allowedMBeans;
+    }
+
+    public synchronized JSONObject handle(String resource, String query) {
+
+        System.out.println("Resource = " + resource + ", Body = " + query);
+
+        try {
+            if ((query == null || query.isEmpty()) && (resource == null || resource.isEmpty())) {
+                return HttpResponse.getJsonObject(HttpURLConnection.HTTP_OK,
+                        new JSONPrimitive(resource + (query == null ? "" : query)),
+                        new JSONPrimitive("Nothing to see here.. move along"));
+            }
+            if (query != null && resource.isEmpty()) { // Handle default domain
+                String[] tokens = query.split(Tokens.FORWARD_SLASH);
+                if (tokens.length == 1 && tokens[0].equalsIgnoreCase(Tokens.DEFAULT_DOMAIN)) {
+                    // Get default domain
+                    return HttpResponse.getJsonObject(HttpURLConnection.HTTP_OK,
+                            new JSONPrimitive(resource + (query == null ? "" : query)),
+                            new JSONPrimitive(mbeanServer.getDefaultDomain()));
+
+                } else { // Get mbeans belonging to a domain
+
+                }
+            } else {
+                // handle string escaping for '/'
+                String[] tokens = resource.split("/");
+                switch (tokens[0]) {
+                    case Tokens.DOMAINS:
+                        String[] domains = mbeanServer.getDomains();
+                        JSONArray jarr = new JSONArray();
+                        Arrays.stream(domains).forEach(a -> jarr.add(new JSONPrimitive(a)));
+                        return HttpResponse.getJsonObject(HttpURLConnection.HTTP_OK,
+                                new JSONPrimitive(resource + (query == null ? "" : query)),
+                                jarr);
+                    case Tokens.MBEANS:
+
+                        //Set<ObjectInstance> mbeans = mbeanServer.queryMBeans(null, null);
+                        jarr = new JSONArray();
+                        //mbeans.stream()
+                        //.map(objIns -> objIns.getObjectName().toString())
+                        allowedMBeans.stream().forEach(a -> jarr.add(new JSONPrimitive(a)));
+                        return HttpResponse.getJsonObject(HttpURLConnection.HTTP_OK,
+                                new JSONPrimitive(resource + (query == null ? "" : query)),
+                                jarr);
+                    default:
+                        if (tokens.length == 2) {
+                            if (!allowedMBeans.contains(tokens[0])) {
+                                throw new InstanceNotFoundException("Invalid MBean");
+                            }
+                            ObjectName mbean = ObjectName.getInstance(tokens[0]);
+                            JSONObject jsonObject = getJSONObject(readAttributes(mbeanServer, mbean, tokens[1]));
+                            return HttpResponse.getJsonObject(HttpURLConnection.HTTP_OK,
+                                    new JSONPrimitive(resource + (query == null ? "" : query)),
+                                    jsonObject);
+                        } else if (tokens.length == 1 && query != null && !query.isEmpty()) {
+                            if (!allowedMBeans.contains(tokens[0])) {
+                                throw new InstanceNotFoundException("Invalid MBean");
+                            }
+                            ObjectName mbean = ObjectName.getInstance(tokens[0]);
+                            if (query.startsWith(Tokens.ATTRS)) {
+                                String attrs = query.split(Tokens.EQUALS)[1];
+                                JSONObject jsonObject = getJSONObject(readAttributes(mbeanServer, mbean, attrs));
+                                return HttpResponse.getJsonObject(HttpURLConnection.HTTP_OK,
+                                        new JSONPrimitive(resource + (query == null ? "" : query)),
+                                        jsonObject);
+                            }
+                        } else if (tokens.length == 1 && (query == null || query.isEmpty())) {
+                            if (!allowedMBeans.contains(tokens[0])) {
+                                throw new InstanceNotFoundException("Invalid MBean");
+                            }
+
+                            // We get MBeanInfo
+                            ObjectName mbeanObj = ObjectName.getInstance(tokens[0]);
+                            return HttpResponse.getJsonObject(HttpURLConnection.HTTP_OK,
+                                    new JSONPrimitive(resource + (query == null ? "" : query)),
+                                    getMBeanInfo(mbeanServer, mbeanObj));
+                        }
+                        System.out.println("Unrecognized token : " + tokens[0]);
+                }
+            }
+        } catch (MBeanException | JSONMappingException | IntrospectionException ex) {
+            return HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex),
+                    new JSONPrimitive(resource + (query == null ? "" : query)),
+                    new JSONPrimitive("Invalid Mbean attribute"));
+
+        } catch (AttributeNotFoundException ex) {
+            return HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex),
+                    new JSONPrimitive(resource + (query == null ? "" : query)),
+                    new JSONPrimitive(ex.getMessage()));
+        } catch (InstanceNotFoundException | ReflectionException | MalformedObjectNameException ex) {
+            return HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex),
+                    new JSONPrimitive(resource + (query == null ? "" : query)),
+                    new JSONPrimitive("Invalid Mbean"));
+        }
+        return HttpResponse.getJsonObject(HttpURLConnection.HTTP_OK,
+                new JSONPrimitive(resource + (query == null ? "" : query)),
+                new JSONPrimitive("Nothing to see here.. move along"));
+    }
+
+    private JSONObject getMBeanInfo(MBeanServer mbeanServer, ObjectName mbean) throws InstanceNotFoundException, IntrospectionException, ReflectionException {
+        JSONObject jobj = new JSONObject();
+        MBeanInfo mBeanInfo = mbeanServer.getMBeanInfo(mbean);
+        if (mBeanInfo == null) {
+            return jobj;
+        }
+        jobj.put("description", mBeanInfo.getDescription());
+
+        // Populate Attribute Info
+        MBeanAttributeInfo[] attributes = mBeanInfo.getAttributes();
+        JSONArray jarr = new JSONArray();
+        for (MBeanAttributeInfo attr : attributes) {
+            String access;
+            if (attr.isReadable()) {
+                if (attr.isWritable()) {
+                    access = "read/write";
+                } else {
+                    access = "read-only";
+                }
+            } else if (attr.isWritable()) {
+                access = "write-only";
+            } else {
+                access = "no-access";
+            }
+            JSONObject jobj1 = new JSONObject();
+            jobj1.put("description", attr.getDescription());
+            jobj1.put("name", attr.getName());
+            jobj1.put("type", attr.getType());
+            jobj1.put("access", access);
+            jobj1.put("descriptor", getDescriptorJSON(attr.getDescriptor()));
+            jarr.add(jobj1);
+        }
+        jobj.put("attributeInfo", jarr);
+
+        // Add constructor Info
+        MBeanConstructorInfo[] constructorInfo = mBeanInfo.getConstructors();
+        jarr = new JSONArray();
+        for (MBeanConstructorInfo constructor : constructorInfo) {
+            JSONObject jobj1 = new JSONObject();
+            jobj1.put("description", constructor.getDescription());
+            jobj1.put("name", constructor.getName());
+            JSONArray jarr1 = new JSONArray();
+            for (MBeanParameterInfo paramInfo : constructor.getSignature()) {
+                jarr1.add(getParamJSON(paramInfo));
+            }
+            jobj1.put("signature", jarr1);
+            if (constructor.getDescriptor().getFieldNames().length > 1) {
+                jobj1.put("descriptor", getDescriptorJSON(constructor.getDescriptor()));
+            }
+            jarr.add(jobj1);
+        }
+        jobj.put("constructorInfo", jarr);
+
+        MBeanOperationInfo[] opInfo = mBeanInfo.getOperations();
+        jarr = new JSONArray();
+
+        for (MBeanOperationInfo op : opInfo) {
+            String impactString;
+            switch (op.getImpact()) {
+                case ACTION:
+                    impactString = "action";
+                    break;
+                case ACTION_INFO:
+                    impactString = "action/info";
+                    break;
+                case INFO:
+                    impactString = "info";
+                    break;
+                case UNKNOWN:
+                    impactString = "unknown";
+                    break;
+                default:
+                    impactString = "(" + op.getImpact() + ")";
+            }
+
+            JSONObject jobj1 = new JSONObject();
+            jobj1.put("description", op.getDescription());
+            jobj1.put("name", op.getName());
+            jobj1.put("returnType", op.getReturnType());
+            JSONArray jarr1 = new JSONArray();
+            for (MBeanParameterInfo paramInfo : op.getSignature()) {
+                jarr1.add(getParamJSON(paramInfo));
+            }
+            jobj1.put("signature", jarr1);
+            jobj1.put("impact", impactString);
+            if (op.getDescriptor().getFieldNames().length > 1) {
+                jobj1.put("descriptor", getDescriptorJSON(op.getDescriptor()));
+            }
+            jarr.add(jobj1);
+        }
+        jobj.put("operationInfo", jarr);
+
+        MBeanNotificationInfo[] notifications = mBeanInfo.getNotifications();
+        jarr = new JSONArray();
+
+        for (MBeanNotificationInfo notification : notifications) {
+
+            JSONObject jobj1 = new JSONObject();
+            jobj1.put("description", notification.getDescription());
+            jobj1.put("name", notification.getName());
+
+            JSONArray jarr1 = new JSONArray();
+            for (String notifType : notification.getNotifTypes()) {
+                jarr1.add(new JSONPrimitive(notifType));
+            }
+            jobj1.put("notifTypes", jarr1);
+            if (notification.getDescriptor().getFieldNames().length > 1) {
+                jobj1.put("descriptor", getDescriptorJSON(notification.getDescriptor()));
+            }
+            jarr.add(jobj1);
+        }
+        jobj.put("notificationInfo", jarr);
+
+        jobj.put("descriptor", getDescriptorJSON(mBeanInfo.getDescriptor()));
+        return jobj;
+    }
+
+    private JSONObject getParamJSON(MBeanParameterInfo mParamInfo) {
+        JSONObject jobj1 = new JSONObject();
+        if (mParamInfo.getDescription() != null && !mParamInfo.getDescription().isEmpty()) {
+            jobj1.put("description", mParamInfo.getDescription());
+        }
+        jobj1.put("name", mParamInfo.getName());
+        jobj1.put("type", mParamInfo.getType());
+        if (mParamInfo.getDescriptor() != null && mParamInfo.getDescriptor().getFieldNames().length > 1) {
+            jobj1.put("descriptor", getDescriptorJSON(mParamInfo.getDescriptor()));
+        }
+        return jobj1;
+    }
+
+    private JSONObject getDescriptorJSON(Descriptor descriptor) {
+        JSONObject jobj2 = new JSONObject();
+        try {
+            String[] descNames = descriptor.getFieldNames();
+            for (String descName : descNames) {
+                Object fieldValue = descriptor.getFieldValue(descName);
+                jobj2.put(descName, fieldValue != null ? fieldValue.toString() : null);
+            }
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+        return jobj2;
+    }
+
+    private Map<String, Object> readAttributes(MBeanServer mbeanServer,
+                                               ObjectName objName, String requestStr)
+            throws InstanceNotFoundException, IntrospectionException,
+            ReflectionException, MBeanException, AttributeNotFoundException {
+        requestStr = requestStr.trim();
+        Map<String, Object> result = new HashMap<>();
+        if (requestStr.trim().equalsIgnoreCase("all")) {
+            MBeanInfo mInfo = mbeanServer.getMBeanInfo(objName);
+            String[] attrs = Arrays.stream(mInfo.getAttributes())
+                    .map(MBeanAttributeInfo::getName)
+                    .toArray(String[]::new);
+            AttributeList attrVals = mbeanServer.getAttributes(objName, attrs);
+            if (attrVals.size() != attrs.length) {
+                List<String> missingAttrs = new ArrayList<>(Arrays.asList(attrs));
+                for (Attribute a : attrVals.asList()) {
+                    missingAttrs.remove(a.getName());
+                    result.put(a.getName(), a.getValue());
+                }
+                for (String attr : missingAttrs) {
+                    try {
+                        Object attribute = mbeanServer.getAttribute(objName, attr);
+                    } catch (RuntimeException ex) {
+                        if (ex.getCause() instanceof UnsupportedOperationException) {
+                            result.put(attr, "< Attribute not supported >");
+                        } else if (ex.getCause() instanceof IllegalArgumentException) {
+                            result.put(attr, "< Invalid attributes >");
+                        }
+                        continue;
+                    }
+                    result.put(attr, "< Error: No such attribute >");
+                }
+            } else {
+                attrVals.asList().forEach((a) -> {
+                    result.put(a.getName(), a.getValue());
+                });
+            }
+        } else {
+            String[] attrs = Arrays.stream(requestStr.split(Tokens.COMMA))
+                    .map(String::trim)
+                    .toArray(String[]::new);
+
+            if (attrs.length == 1) {
+                result.put(attrs[0], mbeanServer.getAttribute(objName, attrs[0]));
+            } else {
+                AttributeList attrVals = mbeanServer.getAttributes(objName, attrs);
+                if (attrVals.size() != attrs.length) {
+                    List<String> missingAttrs = new ArrayList<>(Arrays.asList(attrs));
+                    for (Attribute a : attrVals.asList()) {
+                        missingAttrs.remove(a.getName());
+                        result.put(a.getName(), a.getValue());
+                    }
+                    for (String attr : missingAttrs) {
+                        result.put(attr, "< Error: No such attribute >");
+                    }
+                } else {
+                    attrVals.asList().forEach((a) -> {
+                        result.put(a.getName(), a.getValue());
+                    });
+                }
+            }
+        }
+        return result;
+    }
+
+    private JSONObject getJSONObject(Map<String, Object> attributeMap) throws JSONMappingException {
+        JSONObject jobject = new JSONObject();
+        JSONMappingFactory mappingFactory = JSONMappingFactory.INSTANCE;
+        for (String key : attributeMap.keySet()) {
+            Object attrVal = attributeMap.get(key);
+            if (attrVal == null) {
+                jobject.put(key, new JSONPrimitive());
+            } else if (mappingFactory.getTypeMapper(attrVal) != null) {
+                jobject.put(key, mappingFactory.getTypeMapper(attrVal).toJsonValue(attrVal));
+            }
+        }
+        return jobject;
+    }
+
+    private interface Tokens {
+
+        public static final String DOMAINS = "domains";
+        public static final String MBEANS = "mbeans";
+        public static final String ATTRS = "attributes";
+        public static final String DOMAIN = "domain";
+        public static final String DEFAULT_DOMAIN = "domain=default";
+        public static final String ALL = "all";
+        public static final String EQUALS = "=";
+        public static final String COMMA = ",";
+        public static final String FORWARD_SLASH = "/";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/http/HttpResponse.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,53 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.http;
+
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ReflectionException;
+import com.oracle.jmx.remote.rest.json.JSONElement;
+import com.oracle.jmx.remote.rest.json.JSONObject;
+import com.oracle.jmx.remote.rest.json.JSONPrimitive;
+import com.oracle.jmx.remote.rest.mapper.JSONDataException;
+import com.oracle.jmx.remote.rest.mapper.JSONMappingException;
+import com.oracle.jmx.remote.rest.json.parser.ParseException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.HttpURLConnection;
+
+/**
+ * @author harsha
+ */
+public class HttpResponse {
+
+    public static int getHttpErrorCode(Exception ex) {
+        if (ex instanceof JSONDataException
+                || ex instanceof ParseException || ex instanceof IllegalArgumentException) {
+            return HttpURLConnection.HTTP_BAD_REQUEST;
+        } else if (ex instanceof JSONMappingException) {
+            return HttpURLConnection.HTTP_INTERNAL_ERROR;
+        } else if (ex instanceof AttributeNotFoundException
+                || ex instanceof InstanceNotFoundException
+                || ex instanceof ReflectionException) {
+            return HttpURLConnection.HTTP_NOT_FOUND;
+        }
+        return HttpURLConnection.HTTP_BAD_REQUEST;
+    }
+
+    public static String getErrorMessage(Exception ex) {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        ex.printStackTrace(pw);
+        return sw.toString();
+    }
+
+    public static JSONObject getJsonObject(int code, JSONElement request, JSONElement response) {
+        JSONObject jobj = new JSONObject();
+        jobj.put("status", new JSONPrimitive(code));
+        jobj.put("request", request);
+        jobj.put("response", response);
+        return jobj;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/http/PostRequestHandler.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,328 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.http;
+
+import javax.management.*;
+import javax.management.openmbean.OpenMBeanAttributeInfo;
+import javax.management.openmbean.OpenMBeanParameterInfo;
+import javax.management.openmbean.OpenType;
+import com.oracle.jmx.remote.rest.json.JSONArray;
+import com.oracle.jmx.remote.rest.json.JSONElement;
+import com.oracle.jmx.remote.rest.json.JSONObject;
+import com.oracle.jmx.remote.rest.json.JSONPrimitive;
+import com.oracle.jmx.remote.rest.mapper.JSONDataException;
+import com.oracle.jmx.remote.rest.mapper.JSONMapper;
+import com.oracle.jmx.remote.rest.mapper.JSONMappingException;
+import com.oracle.jmx.remote.rest.mapper.JSONMappingFactory;
+import com.oracle.jmx.remote.rest.json.parser.JSONParser;
+import com.oracle.jmx.remote.rest.json.parser.ParseException;
+import java.net.HttpURLConnection;
+import java.util.*;
+
+/**
+ * @author harsha
+ */
+public class PostRequestHandler {
+
+    private static final String MBEAN_NAME = "name";
+    private static final String MBEAN_ARGUMENTS = "arguments";
+    private final static Map<String, Class<?>> primitiveToObject = new HashMap<>();
+
+    static {
+        primitiveToObject.put("int", Integer.TYPE);
+        primitiveToObject.put("long", Long.TYPE);
+        primitiveToObject.put("double", Double.TYPE);
+        primitiveToObject.put("float", Float.TYPE);
+        primitiveToObject.put("boolean", Boolean.TYPE);
+        primitiveToObject.put("char", Character.TYPE);
+        primitiveToObject.put("byte", Byte.TYPE);
+        primitiveToObject.put("void", Void.TYPE);
+        primitiveToObject.put("short", Short.TYPE);
+    }
+
+    private final MBeanServer mbeanServer;
+    private final List<String> allowedMbeans;
+
+    public PostRequestHandler(MBeanServer mServer, List<String> allowedMbeans) {
+        this.mbeanServer = mServer;
+        this.allowedMbeans = allowedMbeans;
+    }
+
+    public synchronized List<JSONObject> handle(String jsonStr) {
+
+        JSONElement object;
+        List<JSONObject> postResponse = new ArrayList<>();
+        try {
+            object = new JSONParser(jsonStr).parse();
+        } catch (ParseException ex) {
+            postResponse.add(HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex), new JSONPrimitive(jsonStr), new JSONPrimitive("Invalid JSON String")));
+            return postResponse;
+        }
+
+        if (object instanceof JSONObject) {
+            postResponse.add(handleIndividualRequest((JSONObject) object));
+            return postResponse;
+        } else if (object instanceof JSONArray) {
+            JSONArray jarr = (JSONArray) object;
+
+            for (JSONElement jval : jarr) {
+                if (jval instanceof JSONObject) {
+                    JSONObject resp = handleIndividualRequest((JSONObject) jval);
+                    postResponse.add(resp);
+                }
+            }
+            return postResponse;
+        } else {
+            postResponse.add(HttpResponse.getJsonObject(HttpURLConnection.HTTP_BAD_REQUEST, new JSONPrimitive(jsonStr), new JSONPrimitive("Invalid request")));
+            return postResponse;
+        }
+    }
+
+    private JSONObject handleIndividualRequest(JSONObject jobject) {
+
+        try {
+            JSONObject map = jobject;
+            ObjectName name = getObjectName(map);
+            MBeanOps operation = null;
+            for (MBeanOps op : MBeanOps.values()) {
+                if (map.containsKey(op.toString())) {
+                    operation = op;
+                    break;
+                }
+            }
+
+            if (operation == null) {
+                throw new JSONDataException("Invalid operation string");
+            }
+
+            JSONElement val = map.get(operation.toString());
+            if (!(val instanceof JSONPrimitive) || !(((JSONPrimitive) val).getValue() instanceof String)) {
+                throw new JSONDataException("Invalid JSON String");
+            }
+
+            String attrOrOperation = (String) ((JSONPrimitive) val).getValue();
+            JSONElement result = new JSONPrimitive("success");
+
+            val = map.get(MBEAN_ARGUMENTS);
+            if (val != null) {
+                if (!(val instanceof JSONArray)) {
+                    throw new JSONDataException("Invalid JSON String");
+                }
+            }
+
+            JSONArray args = (JSONArray) val;
+
+            switch (operation) {
+                case READ:
+                    result = readAttribute(name, attrOrOperation, args);
+                    break;
+                case WRITE:
+                    writeAttribute(name, attrOrOperation, args);
+                    break;
+                case EXEC:
+                    result = execOperation(name, attrOrOperation, args);
+                    break;
+            }
+            return HttpResponse.getJsonObject(HttpURLConnection.HTTP_OK, jobject, result);
+        } catch (JSONDataException | MBeanException | JSONMappingException | ClassNotFoundException | IntrospectionException | InvalidAttributeValueException | IllegalArgumentException ex) {
+            return HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex), jobject, new JSONPrimitive(ex.toString()));
+        } catch (AttributeNotFoundException ex) {
+            return HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex), jobject, new JSONPrimitive("Invalid Mbean attribute"));
+        } catch (InstanceNotFoundException | ReflectionException ex) {
+            return HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex), jobject, new JSONPrimitive("Invalid Mbean"));
+        }
+    }
+
+    private JSONElement readAttribute(ObjectName name, String attribute, JSONArray args)
+            throws InstanceNotFoundException, IntrospectionException, ReflectionException, ClassNotFoundException,
+            MBeanException, AttributeNotFoundException, JSONMappingException {
+        MBeanInfo mInfos = mbeanServer.getMBeanInfo(name);
+        MBeanAttributeInfo attrInfo = Arrays.stream(mInfos.getAttributes()).filter(a -> a.getName().equals(attribute)).findFirst().orElse(null);
+        if (attrInfo != null && attrInfo.isReadable()) {
+            JSONMapper mapper;
+            if (attrInfo instanceof OpenMBeanAttributeInfo) {
+                OpenType<?> type = ((OpenMBeanAttributeInfo) attrInfo).getOpenType();
+                mapper = JSONMappingFactory.INSTANCE.getTypeMapper(type);
+            } else {
+                mapper = JSONMappingFactory.INSTANCE.getTypeMapper(Class.forName(attrInfo.getType()));
+            }
+            Object attrVal = mbeanServer.getAttribute(name, attribute);
+            return mapper.toJsonValue(attrVal);
+        } else {
+            throw new AttributeNotFoundException();
+        }
+    }
+
+    private void writeAttribute(ObjectName name, String attribute, JSONArray args)
+            throws InstanceNotFoundException, IntrospectionException, ReflectionException, ClassNotFoundException,
+            JSONDataException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException {
+
+        if (args == null || args.isEmpty()) {
+            throw new JSONDataException("Null arguments for set attribute");
+        }
+
+        MBeanInfo mInfos = mbeanServer.getMBeanInfo(name);
+        MBeanAttributeInfo attrInfo = Arrays.stream(mInfos.getAttributes()).filter(a -> a.getName().equals(attribute)).findFirst().orElse(null);
+        if (attrInfo != null && attrInfo.isWritable()) {
+            JSONMapper mapper;
+            if (attrInfo instanceof OpenMBeanAttributeInfo) {
+                OpenType<?> type = ((OpenMBeanAttributeInfo) attrInfo).getOpenType();
+                mapper = JSONMappingFactory.INSTANCE.getTypeMapper(type);
+            } else {
+                mapper = JSONMappingFactory.INSTANCE.getTypeMapper(Class.forName(attrInfo.getType()));
+            }
+
+            JSONElement val = args.get(0);
+            Object argVal = mapper.toJavaObject(val);
+            Attribute attrObj = new Attribute(attribute, argVal);
+            mbeanServer.setAttribute(name, attrObj);
+
+        } else {
+            throw new AttributeNotFoundException();
+        }
+    }
+
+    private Object[] mapArgsToSignature(JSONArray args, MBeanParameterInfo[] signature) {
+        if (args.size() != signature.length) {
+            throw new IllegalArgumentException("Invalid parameters : expected - " + signature.length + " parameters, got - " + args.size());
+        }
+        if (signature.length == 0 && args.isEmpty()) {
+            return new Object[0];
+        }
+        int i = 0;
+        Object[] params = new Object[signature.length];
+        for (MBeanParameterInfo info : signature) {
+            if (info instanceof OpenMBeanParameterInfo) {
+                OpenType<?> openType = ((OpenMBeanParameterInfo) info).getOpenType();
+                JSONMapper typeMapper = JSONMappingFactory.INSTANCE.getTypeMapper(openType);
+                try {
+                    params[i] = typeMapper.toJavaObject(args.get(i));
+                } catch (JSONDataException ex) {
+                    throw new IllegalArgumentException("Invalid JSON String : " + args.get(i).toJsonString() + " for arguments");
+                }
+            } else {
+                Class<?> inputCls = primitiveToObject.get(info.getType());
+                try {
+                    if (inputCls == null) {
+                        inputCls = Class.forName(info.getType());
+                    }
+                } catch (ClassNotFoundException | ClassCastException ex) {
+                    throw new IllegalArgumentException("Invalid parameters : " + args.get(i).toJsonString() + " cannot be mapped to : " + info.getType());
+                }
+                JSONMapper typeMapper = JSONMappingFactory.INSTANCE.getTypeMapper(inputCls);
+                if (typeMapper == null) {
+                    throw new IllegalArgumentException("Invalid parameters : " + args.get(i).toJsonString() + " cannot be mapped to : " + info.getType());
+                }
+                try {
+                    params[i] = typeMapper.toJavaObject(args.get(i));
+                } catch (JSONDataException ex) {
+                    throw new IllegalArgumentException("Invalid JSON String : " + args.get(i).toJsonString() + " for arguments");
+                }
+            }
+            i++;
+        }
+        return params;
+    }
+
+    private JSONElement execOperation(ObjectName name, String opstr, JSONArray args)
+            throws MBeanException, JSONMappingException, IntrospectionException, ReflectionException {
+        if (args == null) {
+            args = new JSONArray();
+        }
+        MBeanInfo mBeanInfo;
+        try {
+            mBeanInfo = mbeanServer.getMBeanInfo(name);
+        } catch (InstanceNotFoundException ex) {
+            throw new IllegalArgumentException("Invalid Operation String");
+        }
+
+        MBeanOperationInfo[] opinfos = Arrays.stream(mBeanInfo.getOperations()).
+                filter(a -> a.getName().equals(opstr)).toArray(MBeanOperationInfo[]::new);
+
+        if (opinfos.length == 0) {
+            throw new IllegalArgumentException("Invalid Operation String");
+        }
+
+        String[] signature = null;
+        Object[] params = null;
+
+        if (opinfos.length == 1) {
+            MBeanParameterInfo[] sig = opinfos[0].getSignature();
+            params = mapArgsToSignature(args, sig);
+            signature = Arrays.asList(sig).stream().map(a -> a.getType()).toArray(a -> new String[a]);
+        } else if (opinfos.length > 1) {
+            IllegalArgumentException exception = null;
+            for (MBeanOperationInfo opInfo : opinfos) {
+                MBeanParameterInfo[] sig = opInfo.getSignature();
+                try {
+                    params = mapArgsToSignature(args, sig);
+                    signature = Arrays.asList(sig).stream().map(a -> a.getType()).toArray(a -> new String[a]);
+                    exception = null;
+                    break;
+                } catch (IllegalArgumentException ex) {
+                    exception = ex;
+                }
+            }
+            if (exception != null) {
+                throw exception;
+            }
+        }
+
+        Object invoke;
+        try {
+            invoke = mbeanServer.invoke(name, opstr, params, signature);
+        } catch (InstanceNotFoundException ex) {
+            throw new IllegalArgumentException("Invalid Operation String");
+        }
+        if (invoke != null) {
+            JSONMapper typeMapper = JSONMappingFactory.INSTANCE.getTypeMapper(invoke);
+            if (typeMapper != null) {
+                return typeMapper.toJsonValue(invoke);
+            } else {
+                return new JSONPrimitive();
+            }
+        } else {
+            return new JSONPrimitive();
+        }
+    }
+
+    private ObjectName getObjectName(JSONObject map) throws JSONDataException, InstanceNotFoundException {
+        do {
+            if (map.get(MBEAN_NAME) == null || !(map.get(MBEAN_NAME) instanceof JSONPrimitive)) {
+                break;
+            }
+            JSONPrimitive mbean_name = (JSONPrimitive) map.get(MBEAN_NAME);
+            if (!(mbean_name.getValue() instanceof String)) {
+                break;
+            }
+            if (!allowedMbeans.contains((String) mbean_name.getValue())) {
+                throw new InstanceNotFoundException("Invalid MBean");
+            }
+            try {
+                return ObjectName.getInstance((String) mbean_name.getValue());
+            } catch (MalformedObjectNameException ex) {
+            }
+        } while (false);
+        throw new JSONDataException("Invalid JSON String");
+    }
+
+    private static enum MBeanOps {
+        READ("read"),
+        WRITE("write"),
+        EXEC("exec");
+
+        private final String text;
+
+        private MBeanOps(final String text) {
+            this.text = text;
+        }
+
+        @Override
+        public String toString() {
+            return text;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/JSONArray.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,38 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.json;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * @author harsha
+ */
+public class JSONArray extends ArrayList<JSONElement> implements JSONElement {
+
+    private static final long serialVersionUID = -506975558678956426L;
+
+    @Override
+    public String toJsonString() {
+        if (isEmpty()) {
+            return null;
+        }
+        StringBuilder sbuild = new StringBuilder();
+        sbuild.append("[");
+        Iterator<JSONElement> itr = iterator();
+        while (itr.hasNext()) {
+            JSONElement val = itr.next();
+            if (val != null)
+                sbuild.append(val.toJsonString()).append(", ");
+            else
+                sbuild.append("null").append(", ");
+        }
+
+        sbuild.deleteCharAt(sbuild.lastIndexOf(","));
+        sbuild.append("]");
+        return sbuild.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/JSONElement.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,13 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.json;
+
+/**
+ * @author harsha
+ */
+public interface JSONElement {
+    public String toJsonString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/JSONObject.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,38 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.json;
+
+import java.util.LinkedHashMap;
+
+/**
+ * @author harsha
+ */
+public class JSONObject extends LinkedHashMap<String, JSONElement> implements JSONElement {
+
+    private static final long serialVersionUID = -9148596129640441014L;
+
+    public JSONElement put(String key, String value) {
+        return super.put(key, new JSONPrimitive(value)); //To change body of generated methods, choose Tools | Templates.
+    }
+
+    @Override
+    public String toJsonString() {
+        if (isEmpty()) {
+            return null;
+        }
+
+        StringBuilder sbuild = new StringBuilder();
+        sbuild.append("{");
+        keySet().forEach((s) -> {
+            sbuild.append("\"").append(s).append("\"").append(": ").
+                    append((get(s) != null) ? get(s).toJsonString() : "null").append(",");
+        });
+
+        sbuild.deleteCharAt(sbuild.lastIndexOf(","));
+        sbuild.append("}");
+        return sbuild.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/JSONPrimitive.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,118 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.json;
+
+/**
+ * @author harsha
+ */
+public class JSONPrimitive implements JSONElement {
+
+    private final Object value;
+
+    public JSONPrimitive(long i) {
+        value = i;
+    }
+
+    public JSONPrimitive(double i) {
+        value = i;
+    }
+
+    public JSONPrimitive(Boolean i) {
+        value = i;
+    }
+
+    public JSONPrimitive(String s) {
+        value = s != null ? unescape(s) : s;
+    }
+
+    public JSONPrimitive() {
+        value = null;
+    }
+
+    public static String escape(String s) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < s.length(); i++) {
+            char ch = s.charAt(i);
+            switch (ch) {
+                case '\\':
+                    sb.append("\\\\");
+                    break;
+                case '\b':
+                    sb.append("\\b");
+                    break;
+                case '\f':
+                    sb.append("\\f");
+                    break;
+                case '\n':
+                    sb.append("\\n");
+                    break;
+                case '\r':
+                    sb.append("\\r");
+                    break;
+                case '\t':
+                    sb.append("\\t");
+                    break;
+                case '"':
+                    sb.append("\\\"");
+                    break;
+                default:
+                    sb.append(s.charAt(i));
+            }
+        }
+        return sb.toString();
+    }
+
+    public static String unescape(String s) {
+        StringBuilder sb = new StringBuilder(s.length());
+        for (int i = 0; i < s.length(); ++i) {
+            if (s.charAt(i) == '\\') {
+                if (i + 1 < s.length() - 1) {
+                    ++i;
+                    switch (s.charAt(i)) {
+                        case '\\':
+                            sb.append('\\');
+                            break;
+                        case '\b':
+                            sb.append('\b');
+                            break;
+                        case '\f':
+                            sb.append('\f');
+                            break;
+                        case '\n':
+                            sb.append('\n');
+                            break;
+                        case '\r':
+                            sb.append('\r');
+                            break;
+                        case '\t':
+                            sb.append('\t');
+                            break;
+                        case '\"':
+                            sb.append('\"');
+                            break;
+                        default:
+                            sb.append(s.charAt(i));
+                    }
+                }
+            } else {
+                sb.append(s.charAt(i));
+            }
+        }
+        return sb.toString();
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    @Override
+    public String toJsonString() {
+        if (value instanceof String) {
+            return "\"" + escape(value.toString()) + "\"";
+        }
+        return value != null ? value.toString() : null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/JSONParser.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,337 @@
+/* Generated By:JavaCC: Do not edit this line. JSONParser.java */
+package com.oracle.jmx.remote.rest.json.parser;
+
+import java.io.StringReader;
+import com.oracle.jmx.remote.rest.json.*;
+
+public class JSONParser implements JSONParserConstants {
+
+    public JSONParser(String input) {
+        this(new StringReader(input));
+    }
+
+    public JSONElement parse() throws ParseException {
+        return jsonValue();
+    }
+
+  final public JSONElement jsonValue() throws ParseException {
+        JSONElement x;
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case 17:
+      x = object();
+      break;
+    case 21:
+      x = list();
+      break;
+    case QUOTED_STRING:
+      x = string();
+      break;
+    case INTEGER_LITERAL:
+    case FLOATING_POINT_LITERAL:
+      x = number();
+      break;
+    case BOOL_LITERAL:
+      x = boolVal();
+      break;
+    case NULL:
+      x = nullVal();
+      break;
+    default:
+      jj_la1[0] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+          {if (true) return x;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public JSONObject object() throws ParseException {
+        final JSONObject jobject = new JSONObject();
+        JSONPrimitive key;
+        JSONElement value;
+    jj_consume_token(17);
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case QUOTED_STRING:
+      key = string();
+      break;
+    case IDENTIFIER:
+      key = identifier();
+      break;
+    default:
+      jj_la1[1] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    jj_consume_token(18);
+    value = jsonValue();
+          jobject.put((String)key.getValue(), value);
+    label_1:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case 19:
+        ;
+        break;
+      default:
+        jj_la1[2] = jj_gen;
+        break label_1;
+      }
+      jj_consume_token(19);
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case QUOTED_STRING:
+        key = string();
+        break;
+      case IDENTIFIER:
+        key = identifier();
+        break;
+      default:
+        jj_la1[3] = jj_gen;
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      jj_consume_token(18);
+      value = jsonValue();
+                  jobject.put((String)key.getValue(), value);
+    }
+    jj_consume_token(20);
+      {if (true) return jobject;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public JSONArray list() throws ParseException {
+    final JSONArray jarray = new JSONArray();
+    JSONElement value;
+    jj_consume_token(21);
+    value = jsonValue();
+          jarray.add(value);
+    label_2:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case 19:
+        ;
+        break;
+      default:
+        jj_la1[4] = jj_gen;
+        break label_2;
+      }
+      jj_consume_token(19);
+      value = jsonValue();
+              jarray.add(value);
+    }
+    jj_consume_token(22);
+      {if (true) return jarray;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public JSONPrimitive nullVal() throws ParseException {
+    jj_consume_token(NULL);
+      {if (true) return null;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public JSONPrimitive boolVal() throws ParseException {
+    jj_consume_token(BOOL_LITERAL);
+     {if (true) return new JSONPrimitive(Boolean.parseBoolean(token.image));}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public JSONPrimitive number() throws ParseException {
+    Token t;
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case INTEGER_LITERAL:
+      t = jj_consume_token(INTEGER_LITERAL);
+                             {if (true) return new JSONPrimitive(Long.parseLong(t.image));}
+      break;
+    case FLOATING_POINT_LITERAL:
+      t = jj_consume_token(FLOATING_POINT_LITERAL);
+                                      {if (true) return new JSONPrimitive(Double.parseDouble(t.image));}
+      break;
+    default:
+      jj_la1[5] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public JSONPrimitive string() throws ParseException {
+    Token t;
+    t = jj_consume_token(QUOTED_STRING);
+      {if (true) return new JSONPrimitive(t.image.substring(1,t.image.length()-1));}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public JSONPrimitive identifier() throws ParseException {
+    jj_consume_token(IDENTIFIER);
+      {if (true) return new JSONPrimitive(token.image);}
+    throw new Error("Missing return statement in function");
+  }
+
+  /** Generated Token Manager. */
+  public JSONParserTokenManager token_source;
+  JavaCharStream jj_input_stream;
+  /** Current token. */
+  public Token token;
+  /** Next token. */
+  public Token jj_nt;
+  private int jj_ntk;
+  private int jj_gen;
+  final private int[] jj_la1 = new int[6];
+  static private int[] jj_la1_0;
+  static {
+      jj_la1_init_0();
+   }
+   private static void jj_la1_init_0() {
+      jj_la1_0 = new int[] {0x22e180,0x12000,0x80000,0x12000,0x80000,0x180,};
+   }
+
+  /** Constructor with InputStream. */
+  public JSONParser(java.io.InputStream stream) {
+     this(stream, null);
+  }
+  /** Constructor with InputStream and supplied encoding */
+  public JSONParser(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream = new JavaCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source = new JSONParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 6; i++) jj_la1[i] = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream stream) {
+     ReInit(stream, null);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 6; i++) jj_la1[i] = -1;
+  }
+
+  /** Constructor. */
+  public JSONParser(java.io.Reader stream) {
+    jj_input_stream = new JavaCharStream(stream, 1, 1);
+    token_source = new JSONParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 6; i++) jj_la1[i] = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader stream) {
+    jj_input_stream.ReInit(stream, 1, 1);
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 6; i++) jj_la1[i] = -1;
+  }
+
+  /** Constructor with generated Token Manager. */
+  public JSONParser(JSONParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 6; i++) jj_la1[i] = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(JSONParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 6; i++) jj_la1[i] = -1;
+  }
+
+  private Token jj_consume_token(int kind) throws ParseException {
+    Token oldToken;
+    if ((oldToken = token).next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    if (token.kind == kind) {
+      jj_gen++;
+      return token;
+    }
+    token = oldToken;
+    jj_kind = kind;
+    throw generateParseException();
+  }
+
+
+/** Get the next Token. */
+  final public Token getNextToken() {
+    if (token.next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    jj_gen++;
+    return token;
+  }
+
+/** Get the specific Token. */
+  final public Token getToken(int index) {
+    Token t = token;
+    for (int i = 0; i < index; i++) {
+      if (t.next != null) t = t.next;
+      else t = t.next = token_source.getNextToken();
+    }
+    return t;
+  }
+
+  private int jj_ntk() {
+    if ((jj_nt=token.next) == null)
+      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+    else
+      return (jj_ntk = jj_nt.kind);
+  }
+
+  private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
+  private int[] jj_expentry;
+  private int jj_kind = -1;
+
+  /** Generate ParseException. */
+  public ParseException generateParseException() {
+    jj_expentries.clear();
+    boolean[] la1tokens = new boolean[23];
+    if (jj_kind >= 0) {
+      la1tokens[jj_kind] = true;
+      jj_kind = -1;
+    }
+    for (int i = 0; i < 6; i++) {
+      if (jj_la1[i] == jj_gen) {
+        for (int j = 0; j < 32; j++) {
+          if ((jj_la1_0[i] & (1<<j)) != 0) {
+            la1tokens[j] = true;
+          }
+        }
+      }
+    }
+    for (int i = 0; i < 23; i++) {
+      if (la1tokens[i]) {
+        jj_expentry = new int[1];
+        jj_expentry[0] = i;
+        jj_expentries.add(jj_expentry);
+      }
+    }
+    int[][] exptokseq = new int[jj_expentries.size()][];
+    for (int i = 0; i < jj_expentries.size(); i++) {
+      exptokseq[i] = jj_expentries.get(i);
+    }
+    return new ParseException(token, exptokseq, tokenImage);
+  }
+
+  /** Enable tracing. */
+  final public void enable_tracing() {
+  }
+
+  /** Disable tracing. */
+  final public void disable_tracing() {
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/JSONParserConstants.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,64 @@
+/* Generated By:JavaCC: Do not edit this line. JSONParserConstants.java */
+package com.oracle.jmx.remote.rest.json.parser;
+
+
+/**
+ * Token literal values and constants.
+ * Generated by org.javacc.parser.OtherFilesGen#start()
+ */
+public interface JSONParserConstants {
+
+  /** End of File. */
+  int EOF = 0;
+  /** RegularExpression Id. */
+  int INTEGER_LITERAL = 7;
+  /** RegularExpression Id. */
+  int FLOATING_POINT_LITERAL = 8;
+  /** RegularExpression Id. */
+  int FRAC = 9;
+  /** RegularExpression Id. */
+  int EXPONENT = 10;
+  /** RegularExpression Id. */
+  int DIGITS = 11;
+  /** RegularExpression Id. */
+  int DIGIT = 12;
+  /** RegularExpression Id. */
+  int QUOTED_STRING = 13;
+  /** RegularExpression Id. */
+  int BOOL_LITERAL = 14;
+  /** RegularExpression Id. */
+  int NULL = 15;
+  /** RegularExpression Id. */
+  int IDENTIFIER = 16;
+
+  /** Lexical state. */
+  int DEFAULT = 0;
+
+  /** Literal token values. */
+  String[] tokenImage = {
+    "<EOF>",
+    "\" \"",
+    "\"\\b\"",
+    "\"\\t\"",
+    "\"\\n\"",
+    "\"\\r\"",
+    "\"\\f\"",
+    "<INTEGER_LITERAL>",
+    "<FLOATING_POINT_LITERAL>",
+    "<FRAC>",
+    "<EXPONENT>",
+    "<DIGITS>",
+    "<DIGIT>",
+    "<QUOTED_STRING>",
+    "<BOOL_LITERAL>",
+    "\"null\"",
+    "<IDENTIFIER>",
+    "\"{\"",
+    "\":\"",
+    "\",\"",
+    "\"}\"",
+    "\"[\"",
+    "\"]\"",
+  };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/JSONParserTokenManager.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,588 @@
+/* Generated By:JavaCC: Do not edit this line. JSONParserTokenManager.java */
+package com.oracle.jmx.remote.rest.json.parser;
+import java.io.StringReader;
+import com.oracle.jmx.remote.rest.json.*;
+
+/** Token Manager. */
+public class JSONParserTokenManager implements JSONParserConstants
+{
+
+  /** Debug output. */
+  public  java.io.PrintStream debugStream = System.out;
+  /** Set debug output. */
+  public  void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_0(int pos, long active0)
+{
+   switch (pos)
+   {
+      case 0:
+         if ((active0 & 0x8000L) != 0L)
+         {
+            jjmatchedKind = 16;
+            return 14;
+         }
+         return -1;
+      case 1:
+         if ((active0 & 0x8000L) != 0L)
+         {
+            jjmatchedKind = 16;
+            jjmatchedPos = 1;
+            return 14;
+         }
+         return -1;
+      case 2:
+         if ((active0 & 0x8000L) != 0L)
+         {
+            jjmatchedKind = 16;
+            jjmatchedPos = 2;
+            return 14;
+         }
+         return -1;
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_0(int pos, long active0)
+{
+   return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
+}
+private int jjStopAtPos(int pos, int kind)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   return pos + 1;
+}
+private int jjMoveStringLiteralDfa0_0()
+{
+   switch(curChar)
+   {
+      case 44:
+         return jjStopAtPos(0, 19);
+      case 58:
+         return jjStopAtPos(0, 18);
+      case 91:
+         return jjStopAtPos(0, 21);
+      case 93:
+         return jjStopAtPos(0, 22);
+      case 110:
+         return jjMoveStringLiteralDfa1_0(0x8000L);
+      case 123:
+         return jjStopAtPos(0, 17);
+      case 125:
+         return jjStopAtPos(0, 20);
+      default :
+         return jjMoveNfa_0(0, 0);
+   }
+}
+private int jjMoveStringLiteralDfa1_0(long active0)
+{
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(0, active0);
+      return 1;
+   }
+   switch(curChar)
+   {
+      case 117:
+         return jjMoveStringLiteralDfa2_0(active0, 0x8000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(0, active0);
+}
+private int jjMoveStringLiteralDfa2_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(0, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(1, active0);
+      return 2;
+   }
+   switch(curChar)
+   {
+      case 108:
+         return jjMoveStringLiteralDfa3_0(active0, 0x8000L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(1, active0);
+}
+private int jjMoveStringLiteralDfa3_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(1, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(2, active0);
+      return 3;
+   }
+   switch(curChar)
+   {
+      case 108:
+         if ((active0 & 0x8000L) != 0L)
+            return jjStartNfaWithStates_0(3, 15, 14);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_0(2, active0);
+}
+private int jjStartNfaWithStates_0(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_0(state, pos + 1);
+}
+static final long[] jjbitVec0 = {
+   0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec2 = {
+   0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+private int jjMoveNfa_0(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 31;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0x3ff000000000000L & l) != 0L)
+                  {
+                     if (kind > 7)
+                        kind = 7;
+                     jjCheckNAddStates(0, 6);
+                  }
+                  else if (curChar == 45)
+                     jjCheckNAddStates(7, 10);
+                  else if (curChar == 34)
+                     jjCheckNAddStates(11, 13);
+                  break;
+               case 1:
+                  if ((0xfffffffbffffffffL & l) != 0L)
+                     jjCheckNAddStates(11, 13);
+                  break;
+               case 3:
+                  if (curChar == 34)
+                     jjCheckNAddStates(11, 13);
+                  break;
+               case 4:
+                  if (curChar == 34 && kind > 13)
+                     kind = 13;
+                  break;
+               case 14:
+                  if ((0x3ff200000000000L & l) == 0L)
+                     break;
+                  if (kind > 16)
+                     kind = 16;
+                  jjstateSet[jjnewStateCnt++] = 14;
+                  break;
+               case 15:
+                  if (curChar == 45)
+                     jjCheckNAddStates(7, 10);
+                  break;
+               case 16:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAdd(16);
+                  break;
+               case 17:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(17, 18);
+                  break;
+               case 18:
+                  if (curChar == 46)
+                     jjCheckNAdd(19);
+                  break;
+               case 19:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 8)
+                     kind = 8;
+                  jjCheckNAdd(19);
+                  break;
+               case 20:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(20, 21);
+                  break;
+               case 22:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(23);
+                  break;
+               case 23:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 8)
+                     kind = 8;
+                  jjCheckNAdd(23);
+                  break;
+               case 24:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(24, 25);
+                  break;
+               case 25:
+                  if (curChar == 46)
+                     jjCheckNAdd(26);
+                  break;
+               case 26:
+                  if ((0x3ff000000000000L & l) != 0L)
+                     jjCheckNAddTwoStates(26, 27);
+                  break;
+               case 28:
+                  if ((0x280000000000L & l) != 0L)
+                     jjCheckNAdd(29);
+                  break;
+               case 29:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 8)
+                     kind = 8;
+                  jjCheckNAdd(29);
+                  break;
+               case 30:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 7)
+                     kind = 7;
+                  jjCheckNAddStates(0, 6);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0x7fffffe87fffffeL & l) != 0L)
+                  {
+                     if (kind > 16)
+                        kind = 16;
+                     jjCheckNAdd(14);
+                  }
+                  if (curChar == 102)
+                     jjstateSet[jjnewStateCnt++] = 11;
+                  else if (curChar == 116)
+                     jjstateSet[jjnewStateCnt++] = 7;
+                  break;
+               case 1:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjCheckNAddStates(11, 13);
+                  break;
+               case 2:
+                  if (curChar == 92)
+                     jjstateSet[jjnewStateCnt++] = 3;
+                  break;
+               case 3:
+                  if ((0x14404410000000L & l) != 0L)
+                     jjCheckNAddStates(11, 13);
+                  break;
+               case 5:
+                  if (curChar == 101 && kind > 14)
+                     kind = 14;
+                  break;
+               case 6:
+                  if (curChar == 117)
+                     jjCheckNAdd(5);
+                  break;
+               case 7:
+                  if (curChar == 114)
+                     jjstateSet[jjnewStateCnt++] = 6;
+                  break;
+               case 8:
+                  if (curChar == 116)
+                     jjstateSet[jjnewStateCnt++] = 7;
+                  break;
+               case 9:
+                  if (curChar == 115)
+                     jjCheckNAdd(5);
+                  break;
+               case 10:
+                  if (curChar == 108)
+                     jjstateSet[jjnewStateCnt++] = 9;
+                  break;
+               case 11:
+                  if (curChar == 97)
+                     jjstateSet[jjnewStateCnt++] = 10;
+                  break;
+               case 12:
+                  if (curChar == 102)
+                     jjstateSet[jjnewStateCnt++] = 11;
+                  break;
+               case 13:
+               case 14:
+                  if ((0x7fffffe87fffffeL & l) == 0L)
+                     break;
+                  if (kind > 16)
+                     kind = 16;
+                  jjCheckNAdd(14);
+                  break;
+               case 21:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(14, 15);
+                  break;
+               case 27:
+                  if ((0x2000000020L & l) != 0L)
+                     jjAddStates(16, 17);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 1:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     jjAddStates(11, 13);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 31 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+static final int[] jjnextStates = {
+   16, 17, 18, 20, 21, 24, 25, 16, 17, 20, 24, 1, 2, 4, 22, 23, 
+   28, 29, 
+};
+private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 0:
+         return ((jjbitVec2[i2] & l2) != 0L);
+      default :
+         if ((jjbitVec0[i1] & l1) != 0L)
+            return true;
+         return false;
+   }
+}
+
+/** Token literal values. */
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, null, null, null, null, null, null, null, null, 
+null, null, "\156\165\154\154", null, "\173", "\72", "\54", "\175", "\133", "\135", };
+
+/** Lexer state names. */
+public static final String[] lexStateNames = {
+   "DEFAULT",
+};
+static final long[] jjtoToken = {
+   0x7fe181L, 
+};
+static final long[] jjtoSkip = {
+   0x7eL, 
+};
+protected JavaCharStream input_stream;
+private final int[] jjrounds = new int[31];
+private final int[] jjstateSet = new int[62];
+protected char curChar;
+/** Constructor. */
+public JSONParserTokenManager(JavaCharStream stream){
+   if (JavaCharStream.staticFlag)
+      throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+   input_stream = stream;
+}
+
+/** Constructor. */
+public JSONParserTokenManager(JavaCharStream stream, int lexState){
+   this(stream);
+   SwitchTo(lexState);
+}
+
+/** Reinitialise parser. */
+public void ReInit(JavaCharStream stream)
+{
+   jjmatchedPos = jjnewStateCnt = 0;
+   curLexState = defaultLexState;
+   input_stream = stream;
+   ReInitRounds();
+}
+private void ReInitRounds()
+{
+   int i;
+   jjround = 0x80000001;
+   for (i = 31; i-- > 0;)
+      jjrounds[i] = 0x80000000;
+}
+
+/** Reinitialise parser. */
+public void ReInit(JavaCharStream stream, int lexState)
+{
+   ReInit(stream);
+   SwitchTo(lexState);
+}
+
+/** Switch to specified lex state. */
+public void SwitchTo(int lexState)
+{
+   if (lexState >= 1 || lexState < 0)
+      throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+   else
+      curLexState = lexState;
+}
+
+protected Token jjFillToken()
+{
+   final Token t;
+   final String curTokenImage;
+   final int beginLine;
+   final int endLine;
+   final int beginColumn;
+   final int endColumn;
+   String im = jjstrLiteralImages[jjmatchedKind];
+   curTokenImage = (im == null) ? input_stream.GetImage() : im;
+   beginLine = input_stream.getBeginLine();
+   beginColumn = input_stream.getBeginColumn();
+   endLine = input_stream.getEndLine();
+   endColumn = input_stream.getEndColumn();
+   t = Token.newToken(jjmatchedKind, curTokenImage);
+
+   t.beginLine = beginLine;
+   t.endLine = endLine;
+   t.beginColumn = beginColumn;
+   t.endColumn = endColumn;
+
+   return t;
+}
+
+int curLexState = 0;
+int defaultLexState = 0;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+/** Get the next Token. */
+public Token getNextToken() 
+{
+  Token matchedToken;
+  int curPos = 0;
+
+  EOFLoop :
+  for (;;)
+  {
+   try
+   {
+      curChar = input_stream.BeginToken();
+   }
+   catch(java.io.IOException e)
+   {
+      jjmatchedKind = 0;
+      matchedToken = jjFillToken();
+      return matchedToken;
+   }
+
+   try { input_stream.backup(0);
+      while (curChar <= 32 && (0x100003700L & (1L << curChar)) != 0L)
+         curChar = input_stream.BeginToken();
+   }
+   catch (java.io.IOException e1) { continue EOFLoop; }
+   jjmatchedKind = 0x7fffffff;
+   jjmatchedPos = 0;
+   curPos = jjMoveStringLiteralDfa0_0();
+   if (jjmatchedKind != 0x7fffffff)
+   {
+      if (jjmatchedPos + 1 < curPos)
+         input_stream.backup(curPos - jjmatchedPos - 1);
+      if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+      {
+         matchedToken = jjFillToken();
+         return matchedToken;
+      }
+      else
+      {
+         continue EOFLoop;
+      }
+   }
+   int error_line = input_stream.getEndLine();
+   int error_column = input_stream.getEndColumn();
+   String error_after = null;
+   boolean EOFSeen = false;
+   try { input_stream.readChar(); input_stream.backup(1); }
+   catch (java.io.IOException e1) {
+      EOFSeen = true;
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+      if (curChar == '\n' || curChar == '\r') {
+         error_line++;
+         error_column = 0;
+      }
+      else
+         error_column++;
+   }
+   if (!EOFSeen) {
+      input_stream.backup(1);
+      error_after = curPos <= 1 ? "" : input_stream.GetImage();
+   }
+   throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+  }
+}
+
+private void jjCheckNAdd(int state)
+{
+   if (jjrounds[state] != jjround)
+   {
+      jjstateSet[jjnewStateCnt++] = state;
+      jjrounds[state] = jjround;
+   }
+}
+private void jjAddStates(int start, int end)
+{
+   do {
+      jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+   } while (start++ != end);
+}
+private void jjCheckNAddTwoStates(int state1, int state2)
+{
+   jjCheckNAdd(state1);
+   jjCheckNAdd(state2);
+}
+
+private void jjCheckNAddStates(int start, int end)
+{
+   do {
+      jjCheckNAdd(jjnextStates[start]);
+   } while (start++ != end);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/JavaCharStream.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,617 @@
+/* Generated By:JavaCC: Do not edit this line. JavaCharStream.java Version 5.0 */
+/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package com.oracle.jmx.remote.rest.json.parser;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (with java-like unicode escape processing).
+ */
+
+public
+class JavaCharStream
+{
+  /** Whether parser is static. */
+  public static final boolean staticFlag = false;
+
+  static final int hexval(char c) throws java.io.IOException {
+    switch(c)
+    {
+       case '0' :
+          return 0;
+       case '1' :
+          return 1;
+       case '2' :
+          return 2;
+       case '3' :
+          return 3;
+       case '4' :
+          return 4;
+       case '5' :
+          return 5;
+       case '6' :
+          return 6;
+       case '7' :
+          return 7;
+       case '8' :
+          return 8;
+       case '9' :
+          return 9;
+
+       case 'a' :
+       case 'A' :
+          return 10;
+       case 'b' :
+       case 'B' :
+          return 11;
+       case 'c' :
+       case 'C' :
+          return 12;
+       case 'd' :
+       case 'D' :
+          return 13;
+       case 'e' :
+       case 'E' :
+          return 14;
+       case 'f' :
+       case 'F' :
+          return 15;
+    }
+
+    throw new java.io.IOException(); // Should never come here
+  }
+
+/** Position in buffer. */
+  public int bufpos = -1;
+  int bufsize;
+  int available;
+  int tokenBegin;
+  protected int bufline[];
+  protected int bufcolumn[];
+
+  protected int column = 0;
+  protected int line = 1;
+
+  protected boolean prevCharIsCR = false;
+  protected boolean prevCharIsLF = false;
+
+  protected java.io.Reader inputStream;
+
+  protected char[] nextCharBuf;
+  protected char[] buffer;
+  protected int maxNextCharInd = 0;
+  protected int nextCharInd = -1;
+  protected int inBuf = 0;
+  protected int tabSize = 8;
+
+  protected void setTabSize(int i) { tabSize = i; }
+  protected int getTabSize(int i) { return tabSize; }
+
+  protected void ExpandBuff(boolean wrapAround)
+  {
+    char[] newbuffer = new char[bufsize + 2048];
+    int newbufline[] = new int[bufsize + 2048];
+    int newbufcolumn[] = new int[bufsize + 2048];
+
+    try
+    {
+      if (wrapAround)
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+        bufcolumn = newbufcolumn;
+
+        bufpos += (bufsize - tokenBegin);
+    }
+    else
+    {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        bufcolumn = newbufcolumn;
+
+        bufpos -= tokenBegin;
+      }
+    }
+    catch (Throwable t)
+    {
+      throw new Error(t.getMessage());
+    }
+
+    available = (bufsize += 2048);
+    tokenBegin = 0;
+  }
+
+  protected void FillBuff() throws java.io.IOException
+  {
+    int i;
+    if (maxNextCharInd == 4096)
+      maxNextCharInd = nextCharInd = 0;
+
+    try {
+      if ((i = inputStream.read(nextCharBuf, maxNextCharInd,
+                                          4096 - maxNextCharInd)) == -1)
+      {
+        inputStream.close();
+        throw new java.io.IOException();
+      }
+      else
+         maxNextCharInd += i;
+      return;
+    }
+    catch(java.io.IOException e) {
+      if (bufpos != 0)
+      {
+        --bufpos;
+        backup(0);
+      }
+      else
+      {
+        bufline[bufpos] = line;
+        bufcolumn[bufpos] = column;
+      }
+      throw e;
+    }
+  }
+
+  protected char ReadByte() throws java.io.IOException
+  {
+    if (++nextCharInd >= maxNextCharInd)
+      FillBuff();
+
+    return nextCharBuf[nextCharInd];
+  }
+
+/** @return starting character for token. */
+  public char BeginToken() throws java.io.IOException
+  {
+    if (inBuf > 0)
+    {
+      --inBuf;
+
+      if (++bufpos == bufsize)
+        bufpos = 0;
+
+      tokenBegin = bufpos;
+      return buffer[bufpos];
+    }
+
+    tokenBegin = 0;
+    bufpos = -1;
+
+    return readChar();
+  }
+
+  protected void AdjustBuffSize()
+  {
+    if (available == bufsize)
+    {
+      if (tokenBegin > 2048)
+      {
+        bufpos = 0;
+        available = tokenBegin;
+      }
+      else
+        ExpandBuff(false);
+    }
+    else if (available > tokenBegin)
+      available = bufsize;
+    else if ((tokenBegin - available) < 2048)
+      ExpandBuff(true);
+    else
+      available = tokenBegin;
+  }
+
+  protected void UpdateLineColumn(char c)
+  {
+    column++;
+
+    if (prevCharIsLF)
+    {
+      prevCharIsLF = false;
+      line += (column = 1);
+    }
+    else if (prevCharIsCR)
+    {
+      prevCharIsCR = false;
+      if (c == '\n')
+      {
+        prevCharIsLF = true;
+      }
+      else
+        line += (column = 1);
+    }
+
+    switch (c)
+    {
+      case '\r' :
+        prevCharIsCR = true;
+        break;
+      case '\n' :
+        prevCharIsLF = true;
+        break;
+      case '\t' :
+        column--;
+        column += (tabSize - (column % tabSize));
+        break;
+      default :
+        break;
+    }
+
+    bufline[bufpos] = line;
+    bufcolumn[bufpos] = column;
+  }
+
+/** Read a character. */
+  public char readChar() throws java.io.IOException
+  {
+    if (inBuf > 0)
+    {
+      --inBuf;
+
+      if (++bufpos == bufsize)
+        bufpos = 0;
+
+      return buffer[bufpos];
+    }
+
+    char c;
+
+    if (++bufpos == available)
+      AdjustBuffSize();
+
+    if ((buffer[bufpos] = c = ReadByte()) == '\\')
+    {
+      UpdateLineColumn(c);
+
+      int backSlashCnt = 1;
+
+      for (;;) // Read all the backslashes
+      {
+        if (++bufpos == available)
+          AdjustBuffSize();
+
+        try
+        {
+          if ((buffer[bufpos] = c = ReadByte()) != '\\')
+          {
+            UpdateLineColumn(c);
+            // found a non-backslash char.
+            if ((c == 'u') && ((backSlashCnt & 1) == 1))
+            {
+              if (--bufpos < 0)
+                bufpos = bufsize - 1;
+
+              break;
+            }
+
+            backup(backSlashCnt);
+            return '\\';
+          }
+        }
+        catch(java.io.IOException e)
+        {
+	  // We are returning one backslash so we should only backup (count-1)
+          if (backSlashCnt > 1)
+            backup(backSlashCnt-1);
+
+          return '\\';
+        }
+
+        UpdateLineColumn(c);
+        backSlashCnt++;
+      }
+
+      // Here, we have seen an odd number of backslash's followed by a 'u'
+      try
+      {
+        while ((c = ReadByte()) == 'u')
+          ++column;
+
+        buffer[bufpos] = c = (char)(hexval(c) << 12 |
+                                    hexval(ReadByte()) << 8 |
+                                    hexval(ReadByte()) << 4 |
+                                    hexval(ReadByte()));
+
+        column += 4;
+      }
+      catch(java.io.IOException e)
+      {
+        throw new Error("Invalid escape character at line " + line +
+                                         " column " + column + ".");
+      }
+
+      if (backSlashCnt == 1)
+        return c;
+      else
+      {
+        backup(backSlashCnt - 1);
+        return '\\';
+      }
+    }
+    else
+    {
+      UpdateLineColumn(c);
+      return c;
+    }
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndColumn
+   */
+  public int getColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndLine
+   */
+  public int getLine() {
+    return bufline[bufpos];
+  }
+
+/** Get end column. */
+  public int getEndColumn() {
+    return bufcolumn[bufpos];
+  }
+
+/** Get end line. */
+  public int getEndLine() {
+    return bufline[bufpos];
+  }
+
+/** @return column of token start */
+  public int getBeginColumn() {
+    return bufcolumn[tokenBegin];
+  }
+
+/** @return line number of token start */
+  public int getBeginLine() {
+    return bufline[tokenBegin];
+  }
+
+/** Retreat. */
+  public void backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+      bufpos += bufsize;
+  }
+
+/** Constructor. */
+  public JavaCharStream(java.io.Reader dstream,
+                 int startline, int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    available = bufsize = buffersize;
+    buffer = new char[buffersize];
+    bufline = new int[buffersize];
+    bufcolumn = new int[buffersize];
+    nextCharBuf = new char[4096];
+  }
+
+/** Constructor. */
+  public JavaCharStream(java.io.Reader dstream,
+                                        int startline, int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+/** Constructor. */
+  public JavaCharStream(java.io.Reader dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+/** Reinitialise. */
+  public void ReInit(java.io.Reader dstream,
+                 int startline, int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    if (buffer == null || buffersize != buffer.length)
+    {
+      available = bufsize = buffersize;
+      buffer = new char[buffersize];
+      bufline = new int[buffersize];
+      bufcolumn = new int[buffersize];
+      nextCharBuf = new char[4096];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    nextCharInd = bufpos = -1;
+  }
+
+/** Reinitialise. */
+  public void ReInit(java.io.Reader dstream,
+                                        int startline, int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+/** Reinitialise. */
+  public void ReInit(java.io.Reader dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+/** Constructor. */
+  public JavaCharStream(java.io.InputStream dstream, String encoding, int startline,
+  int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+  {
+    this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+  }
+
+/** Constructor. */
+  public JavaCharStream(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+  }
+
+/** Constructor. */
+  public JavaCharStream(java.io.InputStream dstream, String encoding, int startline,
+                        int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, startline, startcolumn, 4096);
+  }
+
+/** Constructor. */
+  public JavaCharStream(java.io.InputStream dstream, int startline,
+                        int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+/** Constructor. */
+  public JavaCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, 1, 1, 4096);
+  }
+
+/** Constructor. */
+  public JavaCharStream(java.io.InputStream dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+/** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+  int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+  }
+
+/** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+/** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                     int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, startline, startcolumn, 4096);
+  }
+/** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+/** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, 1, 1, 4096);
+  }
+
+/** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+
+  /** @return token image as String */
+  public String GetImage()
+  {
+    if (bufpos >= tokenBegin)
+      return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+    else
+      return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+                              new String(buffer, 0, bufpos + 1);
+  }
+
+  /** @return suffix */
+  public char[] GetSuffix(int len)
+  {
+    char[] ret = new char[len];
+
+    if ((bufpos + 1) >= len)
+      System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+    else
+    {
+      System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                                                        len - bufpos - 1);
+      System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+    }
+
+    return ret;
+  }
+
+  /** Set buffers back to null when finished. */
+  public void Done()
+  {
+    nextCharBuf = null;
+    buffer = null;
+    bufline = null;
+    bufcolumn = null;
+  }
+
+  /**
+   * Method to adjust line and column numbers for the start of a token.
+   */
+  public void adjustBeginLineColumn(int newLine, int newCol)
+  {
+    int start = tokenBegin;
+    int len;
+
+    if (bufpos >= tokenBegin)
+    {
+      len = bufpos - tokenBegin + inBuf + 1;
+    }
+    else
+    {
+      len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+    }
+
+    int i = 0, j = 0, k = 0;
+    int nextColDiff = 0, columnDiff = 0;
+
+    while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+    {
+      bufline[j] = newLine;
+      nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+      bufcolumn[j] = newCol + columnDiff;
+      columnDiff = nextColDiff;
+      i++;
+    }
+
+    if (i < len)
+    {
+      bufline[j] = newLine++;
+      bufcolumn[j] = newCol + columnDiff;
+
+      while (i++ < len)
+      {
+        if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+          bufline[j] = newLine++;
+        else
+          bufline[j] = newLine;
+      }
+    }
+
+    line = bufline[j];
+    column = bufcolumn[j];
+  }
+
+}
+/* JavaCC - OriginalChecksum=3b79d8fd3ca02005c805e406bf89cd35 (do not edit this line) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/JsonParser.jj	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,130 @@
+
+options {
+    STATIC=false;
+    ERROR_REPORTING=true;
+    JAVA_UNICODE_ESCAPE=true;
+    UNICODE_INPUT=true;
+}
+
+PARSER_BEGIN(JSONParser)
+
+package com.oracle.jmx.remote.rest.json.parser;
+
+import java.io.StringReader;
+import com.oracle.jmx.remote.rest.json.*;
+
+public class JSONParser {
+
+    public JSONParser(String input) {
+        this(new StringReader(input));
+    }
+
+    public JSONElement parse() throws ParseException {
+        return jsonValue(); 
+    }
+}
+
+PARSER_END(JSONParser)
+
+SKIP: {
+    " " | "\b" | "\t" | "\n" | "\r" | "\f"
+}
+
+TOKEN:{
+   <INTEGER_LITERAL : (["-"])? (<DIGITS>)>
+|   < FLOATING_POINT_LITERAL:
+        <INTEGER_LITERAL> <FRAC>
+|       <INTEGER_LITERAL> <EXPONENT>
+|       <INTEGER_LITERAL> <FRAC> <EXPONENT>
+    >
+|   < #FRAC: "." <DIGITS>>
+|   < #EXPONENT: ["e","E"] (["+","-"])? <DIGITS> >
+|   < #DIGITS : (<DIGIT>)+>
+|   < #DIGIT: ["0"-"9"]>
+|   <QUOTED_STRING: "\"" ((~["\"","\\"]) | ("\\" ( ["n","t","b","r","f","\\","\""])))* "\"">
+|   <BOOL_LITERAL : "true" | "false">   
+|   <NULL: "null">
+|   <IDENTIFIER: ["_","a"-"z", "A"-"Z"] (["a"-"z", "A"-"Z","0"-"9","_","-"])* >
+}
+
+JSONElement jsonValue() : {
+	JSONElement x;
+}{
+	( x = object()
+	| x = list()
+	| x = string()
+	| x = number()
+	| x = boolVal()
+	| x = nullVal()
+	)
+	{ return x; }
+}
+
+JSONObject object() : {
+	final JSONObject jobject = new JSONObject();
+	JSONPrimitive key;
+	JSONElement value;
+}{
+    "{"
+        (key = string() | key = identifier())
+        ":"
+        value = jsonValue()
+        { jobject.put((String)key.getValue(), value);}
+        (
+                ","
+                (key = string() | key = identifier())
+                ":"
+                value = jsonValue()
+                { jobject.put((String)key.getValue(), value);}
+        )*
+    "}"
+    { return jobject; }
+}
+
+JSONArray list() : {
+    final JSONArray jarray = new JSONArray();
+    JSONElement value;
+}{
+    "["
+        value = jsonValue()
+        { jarray.add(value);}
+        (
+            ","
+            value = jsonValue()
+            { jarray.add(value); }
+        )*
+    "]"
+
+    { return jarray; }
+}
+
+JSONPrimitive nullVal(): {} {
+    <NULL>
+    { return null; }
+}
+
+JSONPrimitive boolVal(): {}
+{
+    <BOOL_LITERAL>
+    {return new JSONPrimitive(Boolean.parseBoolean(token.image));}
+}
+
+JSONPrimitive number(): {
+    Token t;
+}{
+    (t = <INTEGER_LITERAL> { return new JSONPrimitive(Long.parseLong(t.image));})
+    | (t = <FLOATING_POINT_LITERAL> { return new JSONPrimitive(Double.parseDouble(t.image));})
+}
+
+JSONPrimitive string() : {
+    Token t;
+}{
+    (t = <QUOTED_STRING>)
+    { return new JSONPrimitive(t.image.substring(1,t.image.length()-1)); }
+}
+
+JSONPrimitive identifier() : {}
+{
+    <IDENTIFIER>
+    { return new JSONPrimitive(token.image); }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/ParseException.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,187 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */
+/* JavaCCOptions:KEEP_LINE_COL=null */
+package com.oracle.jmx.remote.rest.json.parser;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends Exception {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * This constructor is used by the method "generateParseException"
+   * in the generated parser.  Calling this constructor generates
+   * a new object of this type with the fields "currentToken",
+   * "expectedTokenSequences", and "tokenImage" set.
+   */
+  public ParseException(Token currentTokenVal,
+                        int[][] expectedTokenSequencesVal,
+                        String[] tokenImageVal
+                       )
+  {
+    super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
+    currentToken = currentTokenVal;
+    expectedTokenSequences = expectedTokenSequencesVal;
+    tokenImage = tokenImageVal;
+  }
+
+  /**
+   * The following constructors are for use by you for whatever
+   * purpose you can think of.  Constructing the exception in this
+   * manner makes the exception behave in the normal way - i.e., as
+   * documented in the class "Throwable".  The fields "errorToken",
+   * "expectedTokenSequences", and "tokenImage" do not contain
+   * relevant information.  The JavaCC generated code does not use
+   * these constructors.
+   */
+
+  public ParseException() {
+    super();
+  }
+
+  /** Constructor with message. */
+  public ParseException(String message) {
+    super(message);
+  }
+
+
+  /**
+   * This is the last token that has been consumed successfully.  If
+   * this object has been created due to a parse error, the token
+   * followng this token will (therefore) be the first error token.
+   */
+  public Token currentToken;
+
+  /**
+   * Each entry in this array is an array of integers.  Each array
+   * of integers represents a sequence of tokens (by their ordinal
+   * values) that is expected at this point of the parse.
+   */
+  public int[][] expectedTokenSequences;
+
+  /**
+   * This is a reference to the "tokenImage" array of the generated
+   * parser within which the parse error occurred.  This array is
+   * defined in the generated ...Constants interface.
+   */
+  public String[] tokenImage;
+
+  /**
+   * It uses "currentToken" and "expectedTokenSequences" to generate a parse
+   * error message and returns it.  If this object has been created
+   * due to a parse error, and you do not catch it (it gets thrown
+   * from the parser) the correct error message
+   * gets displayed.
+   */
+  private static String initialise(Token currentToken,
+                           int[][] expectedTokenSequences,
+                           String[] tokenImage) {
+    String eol = System.getProperty("line.separator", "\n");
+    StringBuffer expected = new StringBuffer();
+    int maxSize = 0;
+    for (int i = 0; i < expectedTokenSequences.length; i++) {
+      if (maxSize < expectedTokenSequences[i].length) {
+        maxSize = expectedTokenSequences[i].length;
+      }
+      for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+        expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+      }
+      if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+        expected.append("...");
+      }
+      expected.append(eol).append("    ");
+    }
+    String retval = "Encountered \"";
+    Token tok = currentToken.next;
+    for (int i = 0; i < maxSize; i++) {
+      if (i != 0) retval += " ";
+      if (tok.kind == 0) {
+        retval += tokenImage[0];
+        break;
+      }
+      retval += " " + tokenImage[tok.kind];
+      retval += " \"";
+      retval += add_escapes(tok.image);
+      retval += " \"";
+      tok = tok.next;
+    }
+    retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+    retval += "." + eol;
+    if (expectedTokenSequences.length == 1) {
+      retval += "Was expecting:" + eol + "    ";
+    } else {
+      retval += "Was expecting one of:" + eol + "    ";
+    }
+    retval += expected.toString();
+    return retval;
+  }
+
+  /**
+   * The end of line string for this machine.
+   */
+  protected String eol = System.getProperty("line.separator", "\n");
+
+  /**
+   * Used to convert raw characters to their escaped version
+   * when these raw version cannot be used as part of an ASCII
+   * string literal.
+   */
+  static String add_escapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case 0 :
+              continue;
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.toString();
+   }
+
+}
+/* JavaCC - OriginalChecksum=90e796a5f303517657c1e544869a38af (do not edit this line) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/Token.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,131 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package com.oracle.jmx.remote.rest.json.parser;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * An integer that describes the kind of this token.  This numbering
+   * system is determined by JavaCCParser, and a table of these numbers is
+   * stored in the file ...Constants.java.
+   */
+  public int kind;
+
+  /** The line number of the first character of this Token. */
+  public int beginLine;
+  /** The column number of the first character of this Token. */
+  public int beginColumn;
+  /** The line number of the last character of this Token. */
+  public int endLine;
+  /** The column number of the last character of this Token. */
+  public int endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public String image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * An optional attribute value of the Token.
+   * Tokens which are not used as syntactic sugar will often contain
+   * meaningful values that will be used later on by the compiler or
+   * interpreter. This attribute value is often different from the image.
+   * Any subclass of Token that actually wants to return a non-null value can
+   * override this method as appropriate.
+   */
+  public Object getValue() {
+    return null;
+  }
+
+  /**
+   * No-argument constructor
+   */
+  public Token() {}
+
+  /**
+   * Constructs a new token for the specified Image.
+   */
+  public Token(int kind)
+  {
+    this(kind, null);
+  }
+
+  /**
+   * Constructs a new token for the specified Image and Kind.
+   */
+  public Token(int kind, String image)
+  {
+    this.kind = kind;
+    this.image = image;
+  }
+
+  /**
+   * Returns the image.
+   */
+  public String toString()
+  {
+    return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simply add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken(ofKind, image);
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use sit in your lexical actions.
+   */
+  public static Token newToken(int ofKind, String image)
+  {
+    switch(ofKind)
+    {
+      default : return new Token(ofKind, image);
+    }
+  }
+
+  public static Token newToken(int ofKind)
+  {
+    return newToken(ofKind, null);
+  }
+
+}
+/* JavaCC - OriginalChecksum=c043d4e4f754c76e793a50373160a703 (do not edit this line) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/json/parser/TokenMgrError.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,147 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
+/* JavaCCOptions: */
+package com.oracle.jmx.remote.rest.json.parser;
+
+/** Token Manager Error. */
+public class TokenMgrError extends Error
+{
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /*
+   * Ordinals for various reasons why an Error of this type can be thrown.
+   */
+
+  /**
+   * Lexical error occurred.
+   */
+  static final int LEXICAL_ERROR = 0;
+
+  /**
+   * An attempt was made to create a second instance of a static token manager.
+   */
+  static final int STATIC_LEXER_ERROR = 1;
+
+  /**
+   * Tried to change to an invalid lexical state.
+   */
+  static final int INVALID_LEXICAL_STATE = 2;
+
+  /**
+   * Detected (and bailed out of) an infinite loop in the token manager.
+   */
+  static final int LOOP_DETECTED = 3;
+
+  /**
+   * Indicates the reason why the exception is thrown. It will have
+   * one of the above 4 values.
+   */
+  int errorCode;
+
+  /**
+   * Replaces unprintable characters by their escaped (or unicode escaped)
+   * equivalents in the given string
+   */
+  protected static final String addEscapes(String str) {
+    StringBuffer retval = new StringBuffer();
+    char ch;
+    for (int i = 0; i < str.length(); i++) {
+      switch (str.charAt(i))
+      {
+        case 0 :
+          continue;
+        case '\b':
+          retval.append("\\b");
+          continue;
+        case '\t':
+          retval.append("\\t");
+          continue;
+        case '\n':
+          retval.append("\\n");
+          continue;
+        case '\f':
+          retval.append("\\f");
+          continue;
+        case '\r':
+          retval.append("\\r");
+          continue;
+        case '\"':
+          retval.append("\\\"");
+          continue;
+        case '\'':
+          retval.append("\\\'");
+          continue;
+        case '\\':
+          retval.append("\\\\");
+          continue;
+        default:
+          if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+            String s = "0000" + Integer.toString(ch, 16);
+            retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+          } else {
+            retval.append(ch);
+          }
+          continue;
+      }
+    }
+    return retval.toString();
+  }
+
+  /**
+   * Returns a detailed message for the Error when it is thrown by the
+   * token manager to indicate a lexical error.
+   * Parameters :
+   *    EOFSeen     : indicates if EOF caused the lexical error
+   *    curLexState : lexical state in which this error occurred
+   *    errorLine   : line number when the error occurred
+   *    errorColumn : column number when the error occurred
+   *    errorAfter  : prefix that was seen before this error occurred
+   *    curchar     : the offending character
+   * Note: You can customize the lexical error message by modifying this method.
+   */
+  protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+    return("Lexical error at line " +
+          errorLine + ", column " +
+          errorColumn + ".  Encountered: " +
+          (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+          "after : \"" + addEscapes(errorAfter) + "\"");
+  }
+
+  /**
+   * You can also modify the body of this method to customize your error messages.
+   * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+   * of end-users concern, so you can return something like :
+   *
+   *     "Internal Error : Please file a bug report .... "
+   *
+   * from this method for such cases in the release version of your parser.
+   */
+  public String getMessage() {
+    return super.getMessage();
+  }
+
+  /*
+   * Constructors of various flavors follow.
+   */
+
+  /** No arg constructor. */
+  public TokenMgrError() {
+  }
+
+  /** Constructor with message and reason. */
+  public TokenMgrError(String message, int reason) {
+    super(message);
+    errorCode = reason;
+  }
+
+  /** Full Constructor. */
+  public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+    this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+  }
+}
+/* JavaCC - OriginalChecksum=69448ec97987e87f0f4fc003d5ed03a3 (do not edit this line) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/mapper/JSONDataException.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,26 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.mapper;
+
+/**
+ * @author harsha
+ */
+public class JSONDataException extends Exception {
+
+    private static final long serialVersionUID = 2430707794210680967L;
+
+    public JSONDataException() {
+        super();
+    }
+
+    public JSONDataException(String s) {
+        super(s);
+    }
+
+    public JSONDataException(String s, Throwable ex) {
+        super(s, ex);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/mapper/JSONMapper.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,17 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.mapper;
+
+import com.oracle.jmx.remote.rest.json.JSONElement;
+
+/**
+ * @author harsha
+ */
+public interface JSONMapper {
+    public Object toJavaObject(JSONElement jsonValue) throws JSONDataException;
+
+    public JSONElement toJsonValue(Object data) throws JSONMappingException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/mapper/JSONMappingException.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,26 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.mapper;
+
+/**
+ * @author harsha
+ */
+public class JSONMappingException extends Exception {
+
+    private static final long serialVersionUID = -3099452281524742227L;
+
+    public JSONMappingException() {
+        super();
+    }
+
+    public JSONMappingException(String s) {
+        super(s);
+    }
+
+    public JSONMappingException(String s, Throwable ex) {
+        super(s, ex);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/mapper/JSONMappingFactory.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,638 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.jmx.remote.rest.mapper;
+
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.openmbean.*;
+import com.oracle.jmx.remote.rest.json.JSONArray;
+import com.oracle.jmx.remote.rest.json.JSONElement;
+import com.oracle.jmx.remote.rest.json.JSONObject;
+import com.oracle.jmx.remote.rest.json.JSONPrimitive;
+import java.lang.reflect.Array;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author harsha
+ */
+public final class JSONMappingFactory {
+
+    public static final JSONMappingFactory INSTANCE;
+    private static final Map<Class<?>, JSONMapper> typeMapper;
+    private static final Map<String, Class<?>> primitiveMap = new HashMap<>();
+
+    static {
+        // Make order of Initialization explicit
+        typeMapper = new HashMap<>();
+
+        primitiveMap.put("boolean", Boolean.TYPE);
+        primitiveMap.put("int", Integer.TYPE);
+        primitiveMap.put("long", Long.TYPE);
+        primitiveMap.put("double", Double.TYPE);
+        primitiveMap.put("float", Float.TYPE);
+        primitiveMap.put("bool", Boolean.TYPE);
+        primitiveMap.put("char", Character.TYPE);
+        primitiveMap.put("byte", Byte.TYPE);
+        primitiveMap.put("void", Void.TYPE);
+        primitiveMap.put("short", Short.TYPE);
+
+        INSTANCE = new JSONMappingFactory();
+    }
+
+    private JSONMappingFactory() {
+
+        typeMapper.put(void.class, null);
+        typeMapper.put(Void.class, null);
+
+        typeMapper.put(boolean.class, new BooleanMapper());
+        typeMapper.put(Boolean.class, new BooleanMapper());
+
+        typeMapper.put(byte.class, new ByteMapper());
+        typeMapper.put(Byte.class, new ByteMapper());
+
+        typeMapper.put(short.class, new ShortMapper());
+        typeMapper.put(Short.class, new ShortMapper());
+
+        typeMapper.put(int.class, new IntegerMapper());
+        typeMapper.put(Integer.class, new IntegerMapper());
+
+        typeMapper.put(long.class, new LongMapper());
+        typeMapper.put(Long.class, new LongMapper());
+
+        typeMapper.put(float.class, new FloatMapper());
+        typeMapper.put(Float.class, new FloatMapper());
+
+        typeMapper.put(double.class, new DoubleMapper());
+        typeMapper.put(Double.class, new DoubleMapper());
+
+        typeMapper.put(char.class, new CharacterMapper());
+        typeMapper.put(Character.class, new CharacterMapper());
+
+        typeMapper.put(String.class, new StringMapper());
+        typeMapper.put(BigInteger.class, new BigIntegerMapper());
+        typeMapper.put(BigDecimal.class, new BigDecimalMapper());
+        typeMapper.put(ObjectName.class, new ObjectNameMapper());
+        typeMapper.put(Date.class, new DateMapper());
+    }
+
+    private Class<?> getArrayComponent(Class<?> cls) {
+        if (cls == null) {
+            return cls;
+        }
+        Class<?> compType = cls;
+        // TODO: Add check for max array dimention of 15
+        while (compType.isArray()) {
+            compType = compType.getComponentType();
+        }
+        return compType;
+    }
+
+    private Object getArrayElement(Object arrayObj) {
+        if (arrayObj != null && arrayObj.getClass().isArray()) {
+            while (arrayObj.getClass().isArray()) {
+                Class<?> componentType = arrayObj.getClass().getComponentType();
+                if (Array.getLength(arrayObj) > 0) {
+                    Object component = null;
+                    for (int i = 0; i < Array.getLength(arrayObj); i++) {
+                        component = Array.get(arrayObj, i);
+                        if (component != null) {
+                            break;
+                        }
+                    }
+                    if (component == null) {
+                        return null;
+                    }
+                    if (componentType.isPrimitive()) {
+                        componentType = component.getClass();
+                    }
+                    arrayObj = componentType.cast(component);
+                } else {
+                    return null;
+                }
+            }
+        }
+        return arrayObj;
+    }
+
+    // TODO: This should be access controlled. Define new permissions
+    public void addMapping(Class<?> cls, JSONMapper mapper) {
+        Class<?> input = cls;
+        if (cls.isArray()) {
+            input = getArrayComponent(cls);
+        }
+        if (!typeMapper.containsKey(input)) {
+            typeMapper.put(input, mapper);
+        }
+    }
+
+    public JSONMapper getTypeMapper(Object object) {
+        Object obj = object;
+        Class<?> cls = object.getClass();
+        if (cls.isArray()) {
+            Object arrayElement = getArrayElement(obj);
+            if (arrayElement instanceof CompositeDataSupport) {
+                CompositeDataSupport cds = (CompositeDataSupport) arrayElement;
+                return new OpenArrayTypeMapper(cls, cds.getCompositeType());
+            } else if (arrayElement instanceof TabularDataSupport) {
+                TabularDataSupport tds = (TabularDataSupport) arrayElement;
+                return new OpenArrayTypeMapper(cls, tds.getTabularType());
+            }
+        }
+
+        if (object instanceof CompositeDataSupport) {
+            CompositeDataSupport cds = (CompositeDataSupport) object;
+            return getTypeMapper(cds.getCompositeType());
+        } else if (object instanceof TabularDataSupport) {
+            TabularDataSupport cds = (TabularDataSupport) object;
+            return getTypeMapper(cds.getTabularType());
+        } else {
+            return getTypeMapper(cls);
+        }
+    }
+
+    /*
+    Using class object is better than class name as class objects for same class
+    name differ for each classloader
+     */
+    public JSONMapper getTypeMapper(Class<?> type) {
+        if (type.isArray()) {
+            Class<?> compType = getArrayComponent(type);
+            if (typeMapper.get(compType) != null) {
+                return new GenericArrayMapper(type);
+            } else {
+                return null;
+            }
+        }
+        return typeMapper.get(type);
+    }
+
+    public JSONMapper getTypeMapper(OpenType<?> type) {
+        if (type instanceof CompositeType) {
+            return new OpenCompositeTypeMapper((CompositeType) type);
+        } else if (type instanceof SimpleType) {
+            try {
+                return getTypeMapper(Class.forName(((SimpleType) type).getClassName()));
+            } catch (ClassNotFoundException ex) { // This should not happen as SimpleTypes are always loaded
+                throw new RuntimeException(ex);
+            }
+        } else if (type instanceof ArrayType) {
+            try {
+                ArrayType<?> at = (ArrayType) type;
+                Class<?> arrayClass = Class.forName(type.getClassName());
+                return new OpenArrayTypeMapper(arrayClass, at.getElementOpenType());
+            } catch (ClassNotFoundException ex) { // This should not happen as SimpleTypes are always loaded
+                throw new RuntimeException(ex);
+            }
+        } else if (type instanceof TabularType) {
+            // TODO
+        }
+        return null; //keep compiler happy
+    }
+
+    public boolean isTypeMapped(String type) throws ClassNotFoundException {
+        if (primitiveMap.get(type) != null) {
+            return true;
+        }
+        Class<?> inputCls = Class.forName(type);
+        inputCls = getArrayComponent(inputCls);
+        if (inputCls.equals(CompositeData.class) || inputCls.equals(TabularData.class)
+                || inputCls.equals(CompositeDataSupport.class) || inputCls.equals(TabularDataSupport.class)) {
+            return true;
+        }
+        return JSONMappingFactory.INSTANCE.getTypeMapper(inputCls) != null;
+    }
+
+    private static class OpenArrayTypeMapper extends GenericArrayMapper {
+
+        public OpenArrayTypeMapper(Class<?> type, OpenType<?> elementOpenType) {
+            super(type);
+            mapper = JSONMappingFactory.INSTANCE.getTypeMapper(elementOpenType);
+        }
+    }
+
+    private static class GenericArrayMapper implements JSONMapper {
+
+        private final Class<?> type;
+        protected JSONMapper mapper;
+
+        GenericArrayMapper(Class<?> type) {
+            this.type = type;
+            mapper = JSONMappingFactory.INSTANCE.getTypeMapper(JSONMappingFactory.INSTANCE.getArrayComponent(type));
+        }
+
+        private Object handleArrayType(Class<?> classType, JSONElement jsonValue) throws JSONDataException {
+            if (!(jsonValue instanceof JSONArray)) {
+                throw new JSONDataException("Invald JSON data format");
+            }
+            JSONArray jarr = (JSONArray) jsonValue;
+            Class<?> compType = classType.getComponentType();
+            Object resultArray = Array.newInstance(compType, jarr.size());
+
+            for (int i = 0; i < jarr.size(); i++) {
+                if (compType != null && compType.isArray()) {
+                    Array.set(resultArray, i, handleArrayType(compType, jarr.get(i)));
+                } else {
+                    Array.set(resultArray, i, mapper.toJavaObject(jarr.get(i)));
+                }
+            }
+            return resultArray;
+        }
+
+        @Override
+        public Object toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            return handleArrayType(type, jsonValue);
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            if (data == null) {
+                return new JSONPrimitive();
+            }
+            if (!data.getClass().equals(type)) {
+                throw new JSONMappingException("Illegal type : " + data.getClass());
+            }
+            return getJasonValue(data);
+        }
+
+        private JSONElement getJasonValue(Object data) throws JSONMappingException {
+            if (data == null) {
+                return new JSONPrimitive();
+            }
+            if (!data.getClass().isArray()) {
+                return mapper.toJsonValue(data);
+            } else {
+                JSONArray jArray = new JSONArray();
+                for (int i = 0; i < Array.getLength(data); i++) {
+                    jArray.add(getJasonValue(Array.get(data, i)));
+                }
+                return jArray;
+            }
+        }
+    }
+
+    private static class OpenCompositeTypeMapper implements JSONMapper {
+
+        private final CompositeType type;
+
+        OpenCompositeTypeMapper(CompositeType type) {
+            this.type = type;
+        }
+
+        @Override
+        public CompositeDataSupport toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (!(jsonValue instanceof JSONObject)) {
+                throw new JSONDataException("JSON String not an object");
+            }
+
+            JSONObject jObject = (JSONObject) jsonValue;
+            Map<String, Object> compositeDataMap = new HashMap<>();
+            for (String itemName : type.keySet()) {
+                OpenType<?> oType = type.getType(itemName);
+                JSONMapper typeMapper = JSONMappingFactory.INSTANCE.getTypeMapper(oType);
+                compositeDataMap.put(itemName, typeMapper.toJavaObject(jObject.get(itemName)));
+            }
+            try {
+                return new CompositeDataSupport(type, compositeDataMap);
+            } catch (OpenDataException ex) {
+                throw new JSONDataException("Could not create CompositeData", ex);
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object d) throws JSONMappingException {
+            CompositeDataSupport data = (CompositeDataSupport) d;
+            if (data == null) {
+                return new JSONPrimitive();
+            }
+            JSONObject jObject = new JSONObject();
+            for (String itemName : type.keySet()) {
+                OpenType<?> oType = type.getType(itemName);
+                JSONMapper typeMapper = JSONMappingFactory.INSTANCE.getTypeMapper(oType);
+                if (typeMapper != null) {
+                    jObject.put(itemName, typeMapper.toJsonValue(data.get(itemName)));
+                } else {
+                    System.out.println("Unable to find mapper for : " + oType);
+                }
+            }
+            return jObject;
+        }
+    }
+
+    private static class OpenTabularTypeMapper implements JSONMapper {
+
+        private final TabularType type;
+
+        public OpenTabularTypeMapper(TabularType type) {
+            this.type = type;
+        }
+
+        /*
+        Tabular data in JSON can be represented in below format
+        [
+            {
+                "key" : [<list of elements>],
+                "value": { <CompositeData> }
+            },
+            {
+                "key" : [<list of elements>],
+                "value": { <CompositeData> }
+            }
+        ]
+         */
+        @Override
+        public TabularDataSupport toJavaObject(JSONElement jsonValue) throws JSONDataException {
+//            if(jsonValue instanceof JSONArray) {
+//                JSONArray jarr = (JSONArray) jsonValue;
+//                for(JSONValue jval : jarr) {
+//                    if(jval instanceof JSONObject) {
+//                        JSONObject jObject = (JSONObject) jval;
+//                        JSONValue jval1 = jObject.get("key");
+//                        Object[] key;
+//                        if(jval1 != null && jval1 instanceof JSONArray) {
+//                            JSONArray jarr1 = (JSONArray) jval1;
+//                            key = new Object[jarr1.size()];
+//                            int i=0;
+//                            for(JSONValue jval2: jarr1){
+//                                key[i++] = ((JSONPrimitive)jval2).getValue();
+//                            }
+//                        }
+//                        JSONValue jval2 = jObject.get("value");
+//                        
+//                        if(jval2 instanceof JSONObject) {
+//                            JSONObject jObj1 = (JSONObject) jval2;
+//                            JSONMapper typeMapper = JSONMappingFactory.INSTANCE.getTypeMapper(type.getRowType());
+//                            Object valueObj = typeMapper.toJavaObject(jObj1);
+//                        }
+//                    }
+//                }
+//            }
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private static class VoidMapper implements JSONMapper {
+
+        @Override
+        public Void toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            return null;
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive();
+        }
+    }
+
+    private static class BooleanMapper implements JSONMapper {
+
+        @Override
+        public Boolean toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof Boolean) {
+                return (Boolean) ((JSONPrimitive) jsonValue).getValue();
+            } else {
+                throw new JSONDataException("Invalid type convertion - cannot convert "
+                        + ((JSONPrimitive) jsonValue).getValue() + "(" + ((JSONPrimitive) jsonValue).getValue().getClass() + ")" + " to boolean");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive((Boolean) data);
+        }
+    }
+
+    private static class ByteMapper implements JSONMapper {
+
+        @Override
+        public Byte toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof Long) {
+                return ((Long) ((JSONPrimitive) jsonValue).getValue()).byteValue();
+            } else {
+                throw new JSONDataException("Invalid type convertion - cannot convert "
+                        + (((JSONPrimitive) jsonValue).getValue().getClass()) + " to byte");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive((Byte) data);
+        }
+    }
+
+    private static class ShortMapper implements JSONMapper {
+
+        @Override
+        public Short toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof Long) {
+                return ((Long) ((JSONPrimitive) jsonValue).getValue()).shortValue();
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive((Short) data);
+        }
+    }
+
+    private static class IntegerMapper implements JSONMapper {
+
+        @Override
+        public Integer toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof Long) {
+                return ((Long) ((JSONPrimitive) jsonValue).getValue()).intValue();
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive((Integer) data);
+        }
+    }
+
+    private static class LongMapper implements JSONMapper {
+
+        @Override
+        public Long toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof Long) {
+                return (Long) ((JSONPrimitive) jsonValue).getValue();
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive((Long) data);
+        }
+    }
+
+    private static class FloatMapper implements JSONMapper {
+
+        @Override
+        public Float toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof Double) {
+                return ((Double) ((JSONPrimitive) jsonValue).getValue()).floatValue();
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive((Float) data);
+        }
+    }
+
+    private static class DoubleMapper implements JSONMapper {
+
+        @Override
+        public Double toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof Long) {
+                return (Double) ((JSONPrimitive) jsonValue).getValue();
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive((Double) data);
+        }
+    }
+
+    private static class CharacterMapper implements JSONMapper {
+
+        @Override
+        public Character toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof String) {
+                String data = ((String) ((JSONPrimitive) jsonValue).getValue());
+                if (data.length() < 1) {
+                    throw new JSONDataException("Invalid char");
+                }
+                return data.charAt(0);
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive((Character) data);
+        }
+    }
+
+    private static class StringMapper implements JSONMapper {
+
+        @Override
+        public String toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof String) {
+                return (String) ((JSONPrimitive) jsonValue).getValue();
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive((String) data);
+        }
+    }
+
+    private static class BigDecimalMapper implements JSONMapper {
+
+        @Override
+        public BigDecimal toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof Double) {
+                return BigDecimal.valueOf((Double) ((JSONPrimitive) jsonValue).getValue());
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive(((BigDecimal) data).doubleValue());
+        }
+    }
+
+    private static class BigIntegerMapper implements JSONMapper {
+
+        @Override
+        public BigInteger toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof Long) {
+                return BigInteger.valueOf((Long) ((JSONPrimitive) jsonValue).getValue());
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive(((BigInteger) data).longValue());
+        }
+    }
+
+    private static class ObjectNameMapper implements JSONMapper {
+
+        @Override
+        public ObjectName toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof String) {
+                try {
+                    return new ObjectName((String) ((JSONPrimitive) jsonValue).getValue());
+                } catch (MalformedObjectNameException ex) {
+                    throw new JSONDataException("Invalid Objectname");
+                }
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive(data.toString());
+        }
+    }
+
+    private static class DateMapper implements JSONMapper {
+
+        private final DateFormat df = new SimpleDateFormat("YYYY-MM-DD");
+
+        @Override
+        public Date toJavaObject(JSONElement jsonValue) throws JSONDataException {
+            if (jsonValue instanceof JSONPrimitive && ((JSONPrimitive) jsonValue).getValue() instanceof String) {
+                String data = ((String) ((JSONPrimitive) jsonValue).getValue());
+                try {
+                    return df.parse(data);
+                } catch (ParseException ex) {
+                    throw new JSONDataException("Invalid Data " + data);
+                }
+            } else {
+                throw new JSONDataException("Invalid JSON");
+            }
+        }
+
+        @Override
+        public JSONElement toJsonValue(Object data) throws JSONMappingException {
+            return new JSONPrimitive(df.format((Date) data));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/javax/management/remote/rest/JmxRestAdapter.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,29 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package javax.management.remote.rest;
+
+import javax.management.MBeanServer;
+
+/**
+ * @author harsha
+ */
+public interface JmxRestAdapter {
+
+    public static final String AUTHENTICATOR
+            = "jmx.remote.authenticator";
+    public static final String LOGIN_CONFIG_PROP
+            = "jmx.remote.x.login.config";
+    public static final String PASSWORD_FILE_PROP
+            = "jmx.remote.x.password.file";
+
+    public void start();
+
+    public void stop();
+
+    public String getBaseUrl();
+
+    public MBeanServer getMBeanServer();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/javax/management/remote/rest/JmxRestAdapterImpl.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,396 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package javax.management.remote.rest;
+
+import com.oracle.jmx.remote.rest.http.PostRequestHandler;
+import com.oracle.jmx.remote.rest.http.GetRequestHandler;
+import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
+import com.sun.jmx.remote.security.JMXSubjectDomainCombiner;
+import com.sun.jmx.remote.security.SubjectDelegator;
+import com.sun.net.httpserver.*;
+
+import javax.management.*;
+import javax.management.relation.MBeanServerNotificationFilter;
+import javax.management.remote.JMXAuthenticator;
+import com.oracle.jmx.remote.rest.json.JSONArray;
+import com.oracle.jmx.remote.rest.json.JSONObject;
+import com.oracle.jmx.remote.rest.json.JSONPrimitive;
+import com.oracle.jmx.remote.rest.mapper.JSONMappingFactory;
+import javax.security.auth.Subject;
+import java.io.*;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.net.*;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import com.sun.net.httpserver.Authenticator;
+
+/**
+ * @author harsha
+ */
+public final class JmxRestAdapterImpl implements JmxRestAdapter, NotificationListener {
+
+    // TODO: These should be wrapped in ReadWriteLock
+    private static final Map<String, MBeanServer> authMBeanServer = new HashMap<>();
+    final List<String> allowedMbeans = new ArrayList<>();
+    private final HttpServer httpServer;
+    private final String contextStr;
+    private final Map<String, ?> env;
+    private final MBeanServer mbeanServer;
+    private final String realm = "";
+    private final GetRequestHandler getHandler;
+    private final PostRequestHandler postHandler;
+    private HttpContext httpContext;
+    private JMXAuthenticator authenticator = null;
+    private boolean started = false;
+
+    JmxRestAdapterImpl(HttpServer hServer, String context, Map<String, ?> env, MBeanServer mbeanServer) {
+        httpServer = hServer;
+        this.contextStr = context;
+        this.env = env;
+        this.mbeanServer = mbeanServer;
+        if (env.get("jmx.remote.x.authentication") != null) {
+            authenticator = (JMXAuthenticator) env.get(JmxRestAdapterImpl.AUTHENTICATOR);
+            if (authenticator == null) {
+                if (env.get("jmx.remote.x.password.file") != null
+                        || env.get("jmx.remote.x.login.config") != null) {
+                    authenticator = new JMXPluggableAuthenticator(env);
+                } else {
+                    // Throw exception for invalid authentication config
+                }
+            }
+        }
+        introspectMBeanTypes(mbeanServer);
+        MBeanServerNotificationFilter filter = new MBeanServerNotificationFilter();
+        filter.enableAllObjectNames();
+        try {
+            mbeanServer.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, this, filter, null);
+        } catch (InstanceNotFoundException ex) {
+        }
+        getHandler = new GetRequestHandler(mbeanServer, allowedMbeans);
+        postHandler = new PostRequestHandler(mbeanServer, allowedMbeans);
+    }
+
+    @Override
+    public synchronized void start() {
+        if (!started) {
+            httpContext = httpServer.createContext("/jmx/" + contextStr + "/", new DefaultHTTPHandler());
+            if (env.get("jmx.remote.x.authentication") != null) {
+                httpContext.setAuthenticator(new BasicAuthenticator());
+            }
+            started = true;
+        }
+    }
+
+    @Override
+    public synchronized void stop() {
+        if (!started) {
+            throw new IllegalStateException("Rest Adapter not started yet");
+        }
+        httpServer.removeContext(httpContext);
+        started = false;
+    }
+
+    @Override
+    public String getBaseUrl() {
+        if (!started) {
+            throw new IllegalStateException("Adapter not started");
+        }
+        try {
+            if (httpServer instanceof HttpsServer) {
+                return "https://" + InetAddress.getLocalHost().getHostName() + ":" + httpServer.getAddress().getPort() + "/jmx/" + contextStr + "/";
+            }
+            return "http://" + InetAddress.getLocalHost().getHostName() + ":" + httpServer.getAddress().getPort() + "/jmx/" + contextStr + "/";
+        } catch (UnknownHostException ex) {
+            return "http://localhost" + ":" + httpServer.getAddress().getPort() + "/jmx/" + contextStr + "/";
+        }
+    }
+
+    @Override
+    public MBeanServer getMBeanServer() {
+        return mbeanServer;
+    }
+
+    private boolean isMBeanAllowed(ObjectName objName) {
+        try {
+            MBeanInfo mInfo = mbeanServer.getMBeanInfo(objName);
+            MBeanAttributeInfo[] attrsInfo = mInfo.getAttributes();
+            for (MBeanAttributeInfo attrInfo : attrsInfo) {
+                String type = attrInfo.getType();
+                if (!JSONMappingFactory.INSTANCE.isTypeMapped(type)) {
+                    return false;
+                }
+            }
+            MBeanOperationInfo[] operations = mInfo.getOperations();
+            for (MBeanOperationInfo opInfo : operations) {
+                MBeanParameterInfo[] signature = opInfo.getSignature();
+                for (MBeanParameterInfo sig : signature) {
+                    if (!JSONMappingFactory.INSTANCE.isTypeMapped(sig.getType())) {
+                        return false;
+                    }
+                }
+                if (!JSONMappingFactory.INSTANCE.isTypeMapped(opInfo.getReturnType())) {
+                    return false;
+                }
+            }
+            return true;
+        } catch (InstanceNotFoundException | IntrospectionException | ReflectionException | ClassNotFoundException ex) {
+            ex.printStackTrace();
+            return false;
+        }
+    }
+
+    private void introspectMBeanTypes(MBeanServer server) {
+        if (allowedMbeans.isEmpty()) {
+            Set<ObjectInstance> allMBeans = server.queryMBeans(null, null); // get all Mbeans
+            allMBeans.stream().filter((objIns) -> (isMBeanAllowed(objIns.getObjectName())))
+                    .forEachOrdered(objIns -> allowedMbeans.add(objIns.getObjectName().toString()));
+        }
+    }
+
+    @Override
+    public void handleNotification(Notification notification, Object handback) {
+        try {
+            MBeanServerNotification mbs = (MBeanServerNotification) notification;
+            if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(mbs.getType())) {
+                ObjectName mBeanName = mbs.getMBeanName();
+                if (isMBeanAllowed(mBeanName)) {
+                    allowedMbeans.add(mBeanName.toString());
+                }
+            } else if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(mbs.getType())) {
+                if (allowedMbeans.contains(mbs.getMBeanName().toString())) {
+                    allowedMbeans.remove(mbs.getMBeanName().toString());
+                }
+            }
+        } catch (Exception e) {
+        }
+    }
+
+    private MBeanServer getMBeanServerProxy(MBeanServer mbeaServer, Subject subject) {
+        return (MBeanServer) Proxy.newProxyInstance(MBeanServer.class.getClassLoader(),
+                new Class<?>[]{MBeanServer.class},
+                new AuthInvocationHandler(mbeaServer, subject));
+    }
+
+    private static class HttpUtil {
+
+        public static String getRequestCharset(HttpExchange ex) {
+            String charset = null;
+            List<String> contentType = ex.getRequestHeaders().get("Content-type");
+            if (contentType != null) {
+                for (String kv : contentType) {
+                    for (String value : kv.split(";")) {
+                        value = value.trim();
+                        if (value.toLowerCase().startsWith("charset=")) {
+                            charset = value.substring("charset=".length());
+                        }
+                    }
+                }
+            }
+            return charset;
+        }
+
+        public static String getAcceptCharset(HttpExchange ex) {
+            List<String> acceptCharset = ex.getRequestHeaders().get("Accept-Charset");
+            if (acceptCharset != null && acceptCharset.size() > 0) {
+                return acceptCharset.get(0);
+            }
+            return null;
+        }
+
+        public static String getGetRequestResource(HttpExchange ex, String charset) throws UnsupportedEncodingException {
+            String httpHandlerPath = ex.getHttpContext().getPath();
+            String requestURIpath = ex.getRequestURI().getPath();
+            String getRequestPath = requestURIpath.substring(httpHandlerPath.length());
+            if (charset != null) {
+                return URLDecoder.decode(getRequestPath, charset);
+            } else {
+                return getRequestPath;
+            }
+        }
+
+        public static String getGetRequestQuery(HttpExchange ex, String charset) throws UnsupportedEncodingException {
+            String query = ex.getRequestURI().getQuery();
+            if (charset != null && query != null) {
+                return URLDecoder.decode(query, charset);
+            } else {
+                return query;
+            }
+        }
+    }
+
+    private class BasicAuthenticator extends Authenticator {
+
+        @Override
+        public Authenticator.Result authenticate(HttpExchange he) {
+            Headers rmap = he.getRequestHeaders();
+            String auth = rmap.getFirst("Authorization");
+            if (auth == null) {
+                Headers map = he.getResponseHeaders();
+                map.set("WWW-Authenticate", "Basic realm=" + realm);
+                return new Authenticator.Retry(401);
+            }
+            int sp = auth.indexOf(' ');
+            if (sp == -1 || !auth.substring(0, sp).equals("Basic")) {
+                return new Authenticator.Failure(401);
+            }
+            byte[] b = Base64.getDecoder().decode(auth.substring(sp + 1));
+            String credentials = new String(b);
+            int colon = credentials.indexOf(':');
+            String uname = credentials.substring(0, colon);
+            String pass = credentials.substring(colon + 1);
+
+            if (authMBeanServer.containsKey(credentials)) {
+                return new Authenticator.Success(new HttpPrincipal(uname, realm));
+            } else {
+                Subject subject = null;
+                if (authenticator != null) {
+                    String[] credential = new String[]{uname, pass};
+                    try {
+                        subject = authenticator.authenticate(credential);
+                    } catch (SecurityException e) {
+                        return new Authenticator.Failure(400);
+                    }
+                }
+                MBeanServer proxy = getMBeanServerProxy(mbeanServer, subject);
+                authMBeanServer.put(credentials, proxy);
+                return new Authenticator.Success(new HttpPrincipal(uname, realm));
+            }
+        }
+    }
+
+    private class AuthInvocationHandler implements InvocationHandler {
+
+        private final MBeanServer mbeanServer;
+        private final AccessControlContext acc;
+
+        public AuthInvocationHandler(MBeanServer server, Subject subject) {
+            this.mbeanServer = server;
+            if (subject == null) {
+                this.acc = null;
+            } else {
+                if (SubjectDelegator.checkRemoveCallerContext(subject)) {
+                    acc = JMXSubjectDomainCombiner.getDomainCombinerContext(subject);
+                } else {
+                    acc = JMXSubjectDomainCombiner.getContext(subject);
+                }
+            }
+        }
+
+        @Override
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            if (acc == null) {
+                return method.invoke(mbeanServer, args);
+            } else {
+                PrivilegedAction<Object> op = () -> {
+                    try {
+                        return method.invoke(mbeanServer, args);
+                    } catch (Exception ex) {
+                    }
+                    return null;
+                };
+                return AccessController.doPrivileged(op, acc);
+            }
+        }
+    }
+
+    private class DefaultHTTPHandler implements HttpHandler {
+
+        Map<String, List<String>> allowedMbeans = new HashMap<>();
+
+        DefaultHTTPHandler() {
+        }
+
+        @Override
+        public void handle(HttpExchange he) throws IOException {
+            MBeanServer server = mbeanServer;
+            if (env.get("jmx.remote.x.authentication") != null) {
+                Headers rmap = he.getRequestHeaders();
+                String auth = rmap.getFirst("Authorization");
+                int sp = auth.indexOf(' ');
+                byte[] b = Base64.getDecoder().decode(auth.substring(sp + 1));
+                String authCredentials = new String(b);
+                server = authMBeanServer.get(authCredentials);
+                if (server == null) {
+                    throw new IllegalArgumentException("Invalid HTTP request Headers");
+                }
+            }
+
+            String charset = HttpUtil.getRequestCharset(he);
+            try {
+                switch (he.getRequestMethod()) {
+                    case "GET":
+                        JSONObject resp = getHandler.handle(HttpUtil.getGetRequestResource(he, charset),
+                                HttpUtil.getGetRequestQuery(he, charset));
+                        sendResponse(he, resp.toJsonString(), ((Long) (((JSONPrimitive) resp.get("status")).getValue())).intValue(), charset);
+                        break;
+                    case "POST":
+                        String requestBody = readRequestBody(he, charset);
+                        List<JSONObject> responses = postHandler.handle(requestBody);
+                        if (responses.size() == 1) {
+                            JSONObject jobj = responses.get(0);
+                            sendResponse(he, jobj.toJsonString(), ((Long) (((JSONPrimitive) responses.get(0).get("status")).getValue())).intValue(), charset);
+                        } else {
+                            int finalCode = HttpURLConnection.HTTP_OK;
+                            boolean isHttpOkPresent = responses.stream()
+                                    .filter(r -> ((Long) (((JSONPrimitive) responses.get(0).get("status")).getValue())).intValue() == HttpURLConnection.HTTP_OK)
+                                    .findFirst().isPresent();
+                            if (!isHttpOkPresent) {
+                                finalCode = ((Long) (((JSONPrimitive) responses.get(0).get("status")).getValue())).intValue();
+                            }
+
+                            JSONArray jarr = new JSONArray();
+                            responses.forEach(r -> jarr.add(r));
+                            JSONObject jobj = new JSONObject();
+                            jobj.put("status", new JSONPrimitive(finalCode));
+                            jobj.put("result", jarr);
+                            String finalResult = jobj.toJsonString();
+                            sendResponse(he, finalResult, finalCode, charset);
+                        }
+                        break;
+                    default:
+                        sendResponse(he, "Not supported", HttpURLConnection.HTTP_BAD_METHOD, charset);
+                        break;
+                }
+            } catch (Throwable t) {
+                t.printStackTrace();
+            }
+        }
+
+        private String readRequestBody(HttpExchange he, String charset) throws IOException {
+            StringBuilder stringBuilder = new StringBuilder();
+            InputStreamReader in = charset != null ? new InputStreamReader(he.getRequestBody(), charset) : new InputStreamReader(he.getRequestBody());
+            BufferedReader br = new BufferedReader(in);
+            String line;
+            while ((line = br.readLine()) != null) {
+                String decode = charset != null ? URLDecoder.decode(line, charset) : line;
+                stringBuilder.append(decode);
+            }
+            return stringBuilder.toString();
+        }
+
+        private void sendResponse(HttpExchange exchange, String response, int code, String charset) throws IOException {
+            String acceptCharset = HttpUtil.getAcceptCharset(exchange);
+            if (acceptCharset != null) {
+                charset = acceptCharset;
+            }
+
+            // Set response headers explicitly
+            String msg = charset == null ? response : URLEncoder.encode(response, charset);
+            byte[] bytes = msg.getBytes();
+            Headers resHeaders = exchange.getResponseHeaders();
+            resHeaders.add("Content-Type", "application/json; charset=" + charset);
+
+            exchange.sendResponseHeaders(code, bytes.length);
+            try (OutputStream os = exchange.getResponseBody()) {
+                os.write(bytes);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/javax/management/remote/rest/PlatformRestAdapter.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,230 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package javax.management.remote.rest;
+
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsServer;
+
+import javax.management.MBeanServer;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.security.KeyStore;
+import java.util.*;
+
+/**
+ * @author harsha
+ */
+public class PlatformRestAdapter {
+
+    private static final Set<String> contextList = new HashSet<>();
+    /*
+     * Initializes HTTPServer with settings from config file
+     * acts as container for platform rest adapter
+     */
+    private static HttpServer httpServer = null;
+    private static JmxRestAdapter instance = null;
+
+    private PlatformRestAdapter() {
+    }
+
+    public static synchronized void init(String portStr, Properties props) throws IOException {
+        if (instance == null) {
+            final int port;
+            try {
+                port = Integer.parseInt(portStr);
+            } catch (NumberFormatException x) {
+                throw new IllegalArgumentException("Invalid string for port");
+            }
+            if (port < 0) {
+                throw new IllegalArgumentException("Invalid string for port");
+            }
+
+            boolean useSSL = Boolean.parseBoolean((String) props.get("com.sun.management.jmxremote.ssl"));
+            if (useSSL) {
+                final String sslConfigFileName
+                        = props.getProperty(PropertyNames.SSL_CONFIG_FILE_NAME);
+                SSLContext ctx = getSSlContext(sslConfigFileName);
+                if (ctx != null) {
+                    HttpsServer server = HttpsServer.create(new InetSocketAddress(port), 0);
+                    server.setHttpsConfigurator(new HttpsConfigurator(ctx));
+                    httpServer = server;
+                } else {
+                    httpServer = HttpServer.create(new InetSocketAddress(port), 0);
+                }
+            } else {
+                httpServer = HttpServer.create(new InetSocketAddress(port), 0);
+            }
+
+            // Initialize rest adapter
+            Map<String, Object> env = new HashMap<>();
+            // Do we use authentication?
+            final String useAuthenticationStr
+                    = props.getProperty(PropertyNames.USE_AUTHENTICATION,
+                            DefaultValues.USE_AUTHENTICATION);
+            final boolean useAuthentication
+                    = Boolean.valueOf(useAuthenticationStr);
+
+            String loginConfigName;
+            String passwordFileName;
+
+            if (useAuthentication) {
+                env.put("jmx.remote.x.authentication", Boolean.TRUE);
+                // Get non-default login configuration
+                loginConfigName
+                        = props.getProperty(PropertyNames.LOGIN_CONFIG_NAME);
+                env.put("jmx.remote.x.login.config", loginConfigName);
+
+                if (loginConfigName == null) {
+                    // Get password file
+                    passwordFileName
+                            = props.getProperty(PropertyNames.PASSWORD_FILE_NAME);
+                    env.put("jmx.remote.x.password.file", passwordFileName);
+                }
+            }
+
+            instance = new JmxRestAdapterImpl(httpServer, "default", env, ManagementFactory.getPlatformMBeanServer());
+            httpServer.start();
+        }
+    }
+
+    public static void stop() {
+        if (instance != null) {
+            instance.stop();
+            instance = null;
+        }
+        if (httpServer != null) {
+            httpServer.stop(0);
+            httpServer = null;
+        }
+    }
+
+    private static SSLContext getSSlContext(String sslConfigFileName) {
+        final String keyStore, keyStorePassword, trustStore, trustStorePassword;
+
+        try {
+            if (sslConfigFileName == null || sslConfigFileName.isEmpty()) {
+                keyStore = System.getProperty(PropertyNames.SSL_KEYSTORE_FILE);
+                keyStorePassword = System.getProperty(PropertyNames.SSL_KEYSTORE_PASSWORD);
+                trustStore = System.getProperty(PropertyNames.SSL_TRUSTSTORE_FILE);
+                trustStorePassword = System.getProperty(PropertyNames.SSL_TRUSTSTORE_PASSWORD);
+            } else {
+                Properties p = new Properties();
+                BufferedInputStream bin = new BufferedInputStream(new FileInputStream(sslConfigFileName));
+                p.load(bin);
+                keyStore = p.getProperty(PropertyNames.SSL_KEYSTORE_FILE);
+                keyStorePassword = p.getProperty(PropertyNames.SSL_KEYSTORE_PASSWORD);
+                trustStore = p.getProperty(PropertyNames.SSL_TRUSTSTORE_FILE);
+                trustStorePassword = p.getProperty(PropertyNames.SSL_TRUSTSTORE_PASSWORD);
+            }
+
+            char[] keyStorePasswd = null;
+            if (keyStorePassword.length() != 0) {
+                keyStorePasswd = keyStorePassword.toCharArray();
+            }
+
+            char[] trustStorePasswd = null;
+            if (trustStorePassword.length() != 0) {
+                trustStorePasswd = trustStorePassword.toCharArray();
+            }
+
+            KeyStore ks = null;
+            if (keyStore != null) {
+                ks = KeyStore.getInstance(KeyStore.getDefaultType());
+                FileInputStream ksfis = new FileInputStream(keyStore);
+                ks.load(ksfis, keyStorePasswd);
+
+            }
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance(
+                    KeyManagerFactory.getDefaultAlgorithm());
+            kmf.init(ks, keyStorePasswd);
+
+            KeyStore ts = null;
+            if (trustStore != null) {
+                ts = KeyStore.getInstance(KeyStore.getDefaultType());
+                FileInputStream tsfis = new FileInputStream(trustStore);
+                ts.load(tsfis, trustStorePasswd);
+            }
+            TrustManagerFactory tmf = TrustManagerFactory.getInstance(
+                    TrustManagerFactory.getDefaultAlgorithm());
+            tmf.init(ts);
+
+            SSLContext ctx = SSLContext.getInstance("SSL");
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+            return ctx;
+        } catch (Exception ex) {
+        }
+        return null;
+    }
+
+    public static JmxRestAdapter getInstance() {
+        if (instance == null) {
+            throw new IllegalStateException("PlatformRestAdapter not initialized");
+        }
+        return instance;
+    }
+
+    public static synchronized JmxRestAdapter newRestAdapter(String context, Map<String, ?> env, MBeanServer mbeanServer) {
+        if (!contextList.contains(context)) {
+            contextList.add(context);
+            return new JmxRestAdapterImpl(httpServer, context, env, mbeanServer);
+        }
+        throw new IllegalArgumentException(context + " is already taken");
+    }
+
+    /**
+     * Default values for JMX configuration properties.
+     */
+    public static interface DefaultValues {
+
+        public static final String PORT = "0";
+        public static final String CONFIG_FILE_NAME = "management.properties";
+        public static final String USE_SSL = "true";
+        public static final String USE_LOCAL_ONLY = "true";
+        public static final String USE_REGISTRY_SSL = "false";
+        public static final String USE_AUTHENTICATION = "true";
+        public static final String PASSWORD_FILE_NAME = "jmxremote.password";
+        public static final String ACCESS_FILE_NAME = "jmxremote.access";
+        public static final String SSL_NEED_CLIENT_AUTH = "false";
+    }
+
+    /**
+     * Names of JMX configuration properties.
+     */
+    public static interface PropertyNames {
+
+        public static final String PORT
+                = "com.sun.management.jmxremote.rest.port";
+        public static final String HOST
+                = "com.sun.management.jmxremote.host";
+        public static final String USE_SSL
+                = "com.sun.management.jmxremote.ssl";
+        public static final String USE_AUTHENTICATION
+                = "com.sun.management.jmxremote.authenticate";
+        public static final String PASSWORD_FILE_NAME
+                = "com.sun.management.jmxremote.password.file";
+        public static final String LOGIN_CONFIG_NAME
+                = "com.sun.management.jmxremote.login.config";
+        public static final String SSL_NEED_CLIENT_AUTH
+                = "com.sun.management.jmxremote.ssl.need.client.auth";
+        public static final String SSL_CONFIG_FILE_NAME
+                = "com.sun.management.jmxremote.ssl.config.file";
+        public static final String SSL_KEYSTORE_FILE
+                = "javax.net.ssl.keyStore";
+        public static final String SSL_TRUSTSTORE_FILE
+                = "javax.net.ssl.trustStore";
+        public static final String SSL_KEYSTORE_PASSWORD
+                = "javax.net.ssl.keyStorePassword";
+        public static final String SSL_TRUSTSTORE_PASSWORD
+                = "javax.net.ssl.trustStorePassword";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.management.rest/share/classes/module-info.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,10 @@
+
+module java.management.rest {
+
+    requires transitive java.management;
+    requires jdk.httpserver;
+
+    exports javax.management.remote.rest;
+    exports com.oracle.jmx.remote.rest.json;
+    exports com.oracle.jmx.remote.rest.json.parser;
+}
--- a/src/java.management/share/classes/module-info.java	Fri Dec 15 13:46:19 2017 +0530
+++ b/src/java.management/share/classes/module-info.java	Tue Aug 29 13:34:15 2017 +0530
@@ -52,6 +52,7 @@
         jdk.management.agent;
     exports com.sun.jmx.remote.security to
         java.management.rmi,
+        java.management.rest,
         jdk.management.agent;
     exports com.sun.jmx.remote.util to
         java.management.rmi;
--- a/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java	Fri Dec 15 13:46:19 2017 +0530
+++ b/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java	Tue Aug 29 13:34:15 2017 +0530
@@ -24,12 +24,16 @@
  */
 package jdk.internal.agent;
 
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
+import jdk.internal.agent.spi.AgentProvider;
+import jdk.internal.vm.VMSupport;
+import sun.management.jdp.JdpController;
+import sun.management.jdp.JdpException;
+import sun.management.jmxremote.ConnectorBootstrap;
+
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rest.PlatformRestAdapter;
+import java.io.*;
 import java.lang.management.ManagementFactory;
 import java.lang.reflect.Method;
 import java.net.InetAddress;
@@ -38,24 +42,11 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.MissingResourceException;
-import java.util.Properties;
-import java.util.ResourceBundle;
-import java.util.ServiceLoader;
+import java.util.*;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXServiceURL;
-
 import static jdk.internal.agent.AgentConfigurationError.*;
-import jdk.internal.agent.spi.AgentProvider;
-import jdk.internal.vm.VMSupport;
-import sun.management.jdp.JdpController;
-import sun.management.jdp.JdpException;
-import sun.management.jmxremote.ConnectorBootstrap;
 
 /**
  * This Agent is started by the VM when -Dcom.sun.management.snmp or
@@ -241,6 +232,8 @@
             "com.sun.management.config.file";
     private static final String SNMP_PORT =
             "com.sun.management.snmp.port";
+    private static final String REST_PORT =
+            "com.sun.management.jmxremote.rest.port";
     private static final String JMXREMOTE =
             "com.sun.management.jmxremote";
     private static final String JMXREMOTE_PORT =
@@ -419,6 +412,7 @@
 
     private static void startAgent(Properties props) throws Exception {
         String snmpPort = props.getProperty(SNMP_PORT);
+        String restPort = props.getProperty(REST_PORT);
         String jmxremote = props.getProperty(JMXREMOTE);
         String jmxremotePort = props.getProperty(JMXREMOTE_PORT);
 
@@ -435,6 +429,10 @@
                 loadSnmpAgent(props);
             }
 
+            if (restPort != null) {
+                loadRestAdapter(props);
+            }
+
             /*
              * If the jmxremote.port property is set then we start the
              * RMIConnectorServer for remote M&M.
@@ -534,10 +532,11 @@
         if (mgmtProps == null) {
             String configFile = System.getProperty(CONFIG_FILE);
             String snmpPort = System.getProperty(SNMP_PORT);
+            String restPort = System.getProperty(REST_PORT);
             String jmxremote = System.getProperty(JMXREMOTE);
             String jmxremotePort = System.getProperty(JMXREMOTE_PORT);
 
-            if (configFile == null && snmpPort == null
+            if (configFile == null && snmpPort == null && restPort == null
                     && jmxremote == null && jmxremotePort == null) {
                 // return if out-of-the-management option is not specified
                 return null;
@@ -547,6 +546,17 @@
         return mgmtProps;
     }
 
+    private static void loadRestAdapter(Properties props) {
+        try {
+            if (props.get(REST_PORT) != null) {
+                PlatformRestAdapter.init((String) props.get(REST_PORT), props);
+                PlatformRestAdapter.getInstance().start();
+            }
+        } catch (Throwable ex) {
+            ex.printStackTrace();
+        }
+    }
+
     private static void loadSnmpAgent(Properties props) {
         /*
          * Load the jdk.snmp service
--- a/src/jdk.management.agent/share/classes/module-info.java	Fri Dec 15 13:46:19 2017 +0530
+++ b/src/jdk.management.agent/share/classes/module-info.java	Tue Aug 29 13:34:15 2017 +0530
@@ -37,6 +37,7 @@
 module jdk.management.agent {
     requires java.management;
     requires java.management.rmi;
+    requires java.management.rest;
 
     exports jdk.internal.agent to jdk.jconsole;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/DefaultRestAdapter.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+ /*
+ * @test
+ * @run main/othervm -Dcom.sun.management.jmxremote.rest.port=8686 -Dcom.sun.management.config.file=/home/harsha/work/jdk10_rest/jdk/test/javax/management/remote/rest/mgmt1.properties DefaultRestAdapter
+ */
+import java.io.IOException;
+import java.util.Arrays;
+
+public class DefaultRestAdapter {
+
+    public static void main(String[] args) throws IOException, Exception {
+        Arrays.asList(args).stream().forEach(System.out::println);
+        Thread.sleep(1000000);
+    }
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/JsonParserTest.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,97 @@
+
+
+
+import javax.management.remote.rest.json.JSONElement;
+import javax.management.remote.rest.json.parser.JSONParser;
+import javax.management.remote.rest.json.parser.ParseException;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author harsha
+ */
+public class JsonParserTest {
+    
+    public JsonParserTest() {
+    }
+
+    // TODO add test methods here.
+    // The methods must be annotated with annotation @Test. For example:
+    //
+    // @Test
+    // public void hello() {}
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+    }
+
+    @BeforeMethod
+    public void setUpMethod() throws Exception {
+    }
+
+    @AfterMethod
+    public void tearDownMethod() throws Exception {
+    }
+    
+    @DataProvider
+    public Object[][] getJsonString() {
+        Object[][] data = new Object[2][1];
+        data[0][0] = "{organisms:[\n" +
+"        {\n" +
+"        id:10929,\n" +
+"        name:\"Bovine Rotavirus\"\n" +
+"        },\n" +
+"        {\n" +
+"        id:9606,\n" +
+"        name:\"Homo Sapiens\"\n" +
+"        }\n" +
+"        ],\n" +
+"proteins:[\n" +
+"        {\n" +
+"        label:\"NSP3\",\n" +
+"        description:\"Rotavirus Non Structural Protein 3\",\n" +
+"        organism-id: 10929,\n" +
+"        acc: \"ACB38353\"\n" +
+"        },\n" +
+"        {\n" +
+"        label:\"EIF4G\",\n" +
+"        description:\"eukaryotic translation initiation factor 4 gamma\",\n" +
+"        organism-id: 9606,\n" +
+"        boolflag: true,\n" +
+"        longFloat: 12351123.1235123e-10,\n" +                
+"        singleQuote: \'asd\',\n" +                                
+"        acc:\"AAI40897\"\n" +
+"        }\n" +
+"        ],\n" +
+"interactions:[\n" +
+"        {\n" +
+"        label:\"NSP3 interacts with EIF4G1\",\n" +
+"        pubmed-id:[77120248,38201627],\n" +
+"        proteins:[\"ACB38353\",\"AAI40897\"]\n" +
+"        }\n" +
+"        ]}";
+        
+        data[1][0] = "{\"name\":\"com.example:type=QueueSampler\",\"exec\":\"testMethod1\",\"params\":[[1,2,3],\"abc\",5,[\"asd\",\"3\",\"67\",\"778\"],[{date:\"2016-3-2\",size:3,head:\"head\"}],[{date:\"2016-3-2\",size:3,head:\"head\"}]]}";
+        return data;
+    }
+    
+    @Test (dataProvider = "getJsonString")
+    public void parserTest(String input) throws ParseException {
+        JSONParser jsonParser = new JSONParser(input);
+        JSONElement parse = jsonParser.parse();
+        String output = parse.toJsonString();
+        System.out.println("\t: " + input);
+        System.out.println("\t: " + output);
+//        Assert.assertEquals(input, output);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/PlatformAdapterTest.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,275 @@
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.util.Base64;
+import java.util.Properties;
+import javax.management.remote.rest.JmxRestAdapter;
+import javax.management.remote.rest.PlatformRestAdapter;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.TrustManagerFactory;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+/**
+ * @test 
+ * @modules java.management.rest
+ * @run testng/othervm PlatformAdapterTest
+ */
+@Test
+public class PlatformAdapterTest {
+
+    private static final String MBEANS = "mbeans";
+    private static String sslAgentConfig;
+    private static String sslClientConfig;
+    private static String passwordFile;
+    
+
+    @BeforeClass
+    public void setup() throws IOException {
+        String testSrcRoot = System.getProperty("test.src") + File.separator;
+        sslAgentConfig = testSrcRoot + "sslConfigAgent";
+        sslClientConfig = testSrcRoot + "sslConfigClient";
+        passwordFile = testSrcRoot + "password.properties";
+        createAgentSslConfigFile(sslAgentConfig);
+        createClientSslConfigFile(sslClientConfig);
+    }
+    
+    @Test
+    public void testHttpNoAuth() throws Exception {
+        Properties props = new Properties();
+        props.setProperty("com.sun.management.jmxremote.rest.port", "8686");
+        props.setProperty("com.sun.management.jmxremote.ssl", "false");
+        props.setProperty("com.sun.management.jmxremote.authenticate", "false");
+        if (props.get("com.sun.management.jmxremote.rest.port") != null) {
+            PlatformRestAdapter.init((String) props.get("com.sun.management.jmxremote.rest.port"), props);
+        }
+
+        JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+        adapter.start();
+        URL url = new URL(adapter.getBaseUrl() + MBEANS);
+        HttpURLConnection con = (HttpURLConnection) url.openConnection();
+        con.setDoOutput(false);
+        print_content(con);
+        PlatformRestAdapter.stop();
+    }
+
+    @Test
+    public void testHttpAuth() throws Exception {
+        Properties props = new Properties();
+        props.setProperty("com.sun.management.jmxremote.rest.port", "8686");
+        props.setProperty("com.sun.management.jmxremote.ssl", "false");
+        props.setProperty("com.sun.management.jmxremote.authenticate", "true");
+        props.setProperty("com.sun.management.jmxremote.password.file", passwordFile);
+        if (props.get("com.sun.management.jmxremote.rest.port") != null) {
+            PlatformRestAdapter.init((String) props.get("com.sun.management.jmxremote.rest.port"), props);
+        }
+
+        JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+        adapter.start();
+        URL url = new URL(adapter.getBaseUrl() + MBEANS);
+        HttpURLConnection con = (HttpURLConnection) url.openConnection();
+        con.setDoOutput(false);
+
+        String userCredentials = "username1:password1";
+
+        String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes());
+        con.setRequestProperty("Authorization", basicAuth);
+        print_content(con);
+
+        PlatformRestAdapter.stop();
+    }
+
+    private void createAgentSslConfigFile(String fileName) throws IOException {
+        Properties props = new Properties();
+        String testDir = System.getProperty("test.src");
+        props.setProperty("javax.net.ssl.keyStore", testDir + File.separator + "keystoreAgent");
+        props.setProperty("javax.net.ssl.keyStorePassword", "glopglop");
+        props.setProperty("javax.net.ssl.trustStore", testDir + File.separator + "truststoreAgent");
+        props.setProperty("javax.net.ssl.trustStorePassword","glopglop");
+
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
+            props.store(writer, "");
+        }
+    }
+
+    private void createClientSslConfigFile(String fileName) throws IOException {
+        Properties props = new Properties();
+        String testDir = System.getProperty("test.src");
+        props.setProperty("javax.net.ssl.keyStore", testDir + File.separator + "keystoreClient");
+        props.setProperty("javax.net.ssl.keyStorePassword", "glopglop");
+        props.setProperty("javax.net.ssl.trustStore", testDir + File.separator + "truststoreClient");
+        props.setProperty("javax.net.ssl.trustStorePassword", "glopglop");
+
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
+            props.store(writer, "");
+        }
+    }
+
+    @Test
+    public void testHttpsNoAuth() throws Exception {
+        Properties props = new Properties();
+        props.setProperty("com.sun.management.jmxremote.rest.port", "8686");
+        props.setProperty("com.sun.management.jmxremote.ssl", "true");
+        props.setProperty("com.sun.management.jmxremote.ssl.config.file", sslAgentConfig);
+        props.setProperty("com.sun.management.jmxremote.authenticate", "false");
+        if (props.get("com.sun.management.jmxremote.rest.port") != null) {
+            PlatformRestAdapter.init((String) props.get("com.sun.management.jmxremote.rest.port"), props);
+        }
+        JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+        adapter.start();
+        SSLContext ctx = getSSlContext(sslClientConfig);
+        HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
+        HttpsURLConnection.setDefaultHostnameVerifier(
+                (String hostname, javax.net.ssl.SSLSession sslSession) -> hostname.equals("Harsha-Wardhana-B"));
+
+        URL url = new URL(adapter.getBaseUrl() + MBEANS);
+        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
+        con.setDoOutput(false);
+        print_https_cert(con);
+        print_content(con);
+        PlatformRestAdapter.stop();
+    }
+
+    @Test
+    public void testHttpsAuth() throws Exception {
+        Properties props = new Properties();
+        props.setProperty("com.sun.management.jmxremote.rest.port", "8686");
+        props.setProperty("com.sun.management.jmxremote.ssl", "true");
+        props.setProperty("com.sun.management.jmxremote.ssl.config.file", sslAgentConfig);
+        props.setProperty("com.sun.management.jmxremote.authenticate", "true");
+        props.setProperty("com.sun.management.jmxremote.password.file", passwordFile);
+        if (props.get("com.sun.management.jmxremote.rest.port") != null) {
+            PlatformRestAdapter.init((String) props.get("com.sun.management.jmxremote.rest.port"), props);
+        }
+
+        JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+        adapter.start();
+        SSLContext ctx = getSSlContext(sslClientConfig);
+        HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
+        HttpsURLConnection.setDefaultHostnameVerifier(
+                (String hostname, javax.net.ssl.SSLSession sslSession) -> hostname.equals("Harsha-Wardhana-B"));
+
+        URL url = new URL(adapter.getBaseUrl() + MBEANS);
+        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
+        con.setDoOutput(false);
+
+        String userCredentials = "username1:password1";
+
+        String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes());
+        con.setRequestProperty("Authorization", basicAuth);
+        print_https_cert(con);
+        print_content(con);
+        PlatformRestAdapter.stop();
+    }
+
+    private void print_content(HttpURLConnection con) {
+        if (con != null) {
+            try {
+                System.out.println("****** Content of the URL ********");
+                int status = con.getResponseCode();
+                System.out.println("Status = " + status);
+                BufferedReader br
+                        = new BufferedReader(
+                                new InputStreamReader(con.getInputStream()));
+                String input;
+                while ((input = br.readLine()) != null) {
+                    System.out.println(input);
+                }
+                br.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void print_https_cert(HttpsURLConnection con) {
+        if (con != null) {
+            try {
+                System.out.println("Response Code : " + con.getResponseCode());
+                System.out.println("Cipher Suite : " + con.getCipherSuite());
+                System.out.println("\n");
+
+                Certificate[] certs = con.getServerCertificates();
+                for (Certificate cert : certs) {
+                    System.out.println("Cert Type : " + cert.getType());
+                    System.out.println("Cert Hash Code : " + cert.hashCode());
+                    System.out.println("Cert Public Key Algorithm : "
+                            + cert.getPublicKey().getAlgorithm());
+                    System.out.println("Cert Public Key Format : "
+                            + cert.getPublicKey().getFormat());
+                    System.out.println("\n");
+                }
+
+            } catch (SSLPeerUnverifiedException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private static SSLContext getSSlContext(String sslConfigFileName) {
+        String keyStore, keyStorePassword, trustStore, trustStorePassword;
+        System.out.println("SSL Config file : " + sslConfigFileName);
+
+        try {
+            Properties p = new Properties();
+            BufferedInputStream bin = new BufferedInputStream(new FileInputStream(sslConfigFileName));
+            p.load(bin);
+            keyStore = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_KEYSTORE_FILE);
+            keyStorePassword = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_KEYSTORE_PASSWORD);
+            trustStore = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_TRUSTSTORE_FILE);
+            trustStorePassword = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_TRUSTSTORE_PASSWORD);
+
+            char[] keyStorePasswd = null;
+            if (keyStorePassword.length() != 0) {
+                keyStorePasswd = keyStorePassword.toCharArray();
+            }
+
+            char[] trustStorePasswd = null;
+            if (trustStorePassword.length() != 0) {
+                trustStorePasswd = trustStorePassword.toCharArray();
+            }
+
+            KeyStore ks = null;
+            if (keyStore != null) {
+                ks = KeyStore.getInstance(KeyStore.getDefaultType());
+                FileInputStream ksfis = new FileInputStream(keyStore);
+                ks.load(ksfis, keyStorePasswd);
+
+            }
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance(
+                    KeyManagerFactory.getDefaultAlgorithm());
+            kmf.init(ks, keyStorePasswd);
+
+            KeyStore ts = null;
+            if (trustStore != null) {
+                ts = KeyStore.getInstance(KeyStore.getDefaultType());
+                FileInputStream tsfis = new FileInputStream(trustStore);
+                ts.load(tsfis, trustStorePasswd);
+            }
+            TrustManagerFactory tmf = TrustManagerFactory.getInstance(
+                    TrustManagerFactory.getDefaultAlgorithm());
+            tmf.init(ts);
+
+            SSLContext ctx = SSLContext.getInstance("SSL");
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+            return ctx;
+        } catch (Exception ex) {
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/PlatformMBeanTest.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,293 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package javax.management.remote.rest.test;
+
+import javax.management.remote.rest.JmxRestAdapter;
+import javax.management.remote.rest.PlatformRestAdapter;
+import javax.management.remote.rest.json.JSONArray;
+import javax.management.remote.rest.json.JSONElement;
+import javax.management.remote.rest.json.JSONObject;
+import javax.management.remote.rest.json.JSONPrimitive;
+import javax.management.remote.rest.json.parser.JSONParser;
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.security.KeyStore;
+import java.util.Base64;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.management.remote.rest.JmxRestAdapter;
+import javax.management.remote.rest.PlatformRestAdapter;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author harsha
+ */
+public class PlatformMBeanTest {
+
+    private static SSLContext getSSlContext(String sslConfigFileName) {
+        final String keyStore, keyStorePassword, trustStore, trustStorePassword;
+
+        try {
+            Properties p = new Properties();
+            BufferedInputStream bin = new BufferedInputStream(new FileInputStream(sslConfigFileName));
+            p.load(bin);
+            keyStore = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_KEYSTORE_FILE);
+            keyStorePassword = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_KEYSTORE_PASSWORD);
+            trustStore = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_TRUSTSTORE_FILE);
+            trustStorePassword = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_TRUSTSTORE_PASSWORD);
+
+            char[] keyStorePasswd = null;
+            if (keyStorePassword.length() != 0) {
+                keyStorePasswd = keyStorePassword.toCharArray();
+            }
+
+            char[] trustStorePasswd = null;
+            if (trustStorePassword.length() != 0) {
+                trustStorePasswd = trustStorePassword.toCharArray();
+            }
+
+            KeyStore ks = null;
+            if (keyStore != null) {
+                ks = KeyStore.getInstance(KeyStore.getDefaultType());
+                FileInputStream ksfis = new FileInputStream(keyStore);
+                ks.load(ksfis, keyStorePasswd);
+
+            }
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance(
+                    KeyManagerFactory.getDefaultAlgorithm());
+            kmf.init(ks, keyStorePasswd);
+
+            KeyStore ts = null;
+            if (trustStore != null) {
+                ts = KeyStore.getInstance(KeyStore.getDefaultType());
+                FileInputStream tsfis = new FileInputStream(trustStore);
+                ts.load(tsfis, trustStorePasswd);
+            }
+            TrustManagerFactory tmf = TrustManagerFactory.getInstance(
+                    TrustManagerFactory.getDefaultAlgorithm());
+            tmf.init(ts);
+
+            SSLContext ctx = SSLContext.getInstance("SSL");
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+            return ctx;
+        } catch (Exception ex) {
+            Logger.getLogger(PlatformRestAdapter.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        return null;
+    }
+
+    private static final String CHARSET = "UTF-8";
+
+    private String getFilePath(String filename) {
+        return System.getProperty("user.dir") + File.separator + filename;
+    }
+
+    @BeforeClass
+    public void setupAdapter() throws Exception {
+        File file = new File(getFilePath("management.properties"));
+        Properties props = new Properties();
+        props.load(new FileInputStream(file));
+        if (props.get("com.sun.management.jmxremote.rest.port") != null) {
+            PlatformRestAdapter.init((String) props.get("com.sun.management.jmxremote.rest.port"), props);
+        }
+        PlatformRestAdapter.getInstance().start();
+        SSLContext ctx = getSSlContext(getFilePath("sslconfigClient"));
+        HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
+        HttpsURLConnection.setDefaultHostnameVerifier(
+                (String hostname, javax.net.ssl.SSLSession sslSession) -> hostname.equals("Harsha-Wardhana-B"));
+    }
+
+    @AfterClass
+    public void tearDown() {
+        PlatformRestAdapter.stop();
+    }
+
+    private String executeHttpGetRequest(String inputUrl) throws MalformedURLException, IOException {
+        if (inputUrl != null && !inputUrl.isEmpty()) {
+            JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+            URL url = new URL(adapter.getBaseUrl() + inputUrl);
+            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
+            con.setDoOutput(false);
+            String userCredentials = "username1:password1";
+            String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes());
+            con.setRequestProperty("Authorization", basicAuth);
+            try {
+                int status = con.getResponseCode();
+                if (status == 200) {
+
+                    StringBuilder sbuf;
+                    try (BufferedReader br = new BufferedReader(
+                            new InputStreamReader(con.getInputStream()))) {
+                        sbuf = new StringBuilder();
+                        String input;
+                        while ((input = br.readLine()) != null) {
+                            sbuf.append(URLDecoder.decode(input, CHARSET));
+                        }
+                    }
+                    return sbuf.toString();
+                } else {
+                    StringBuilder sbuf;
+                    try (BufferedReader br = new BufferedReader(
+                            new InputStreamReader(con.getErrorStream()))) {
+                        sbuf = new StringBuilder();
+                        String input;
+                        while ((input = br.readLine()) != null) {
+                            sbuf.append(URLDecoder.decode(input, CHARSET));
+                        }
+                    }
+                    return sbuf.toString();
+                }
+            } catch (IOException e) {
+            }
+        }
+        return null;
+    }
+
+    private String executeHttpPostRequest(String postBody) throws MalformedURLException, IOException {
+        if (postBody != null && !postBody.isEmpty()) {
+            JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+            URL url = new URL(adapter.getBaseUrl());
+            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+            connection.setRequestProperty("Content-Type", "application/json; charset=" + CHARSET);
+            connection.setDoOutput(true);
+            connection.setRequestMethod("POST");
+            String userCredentials = "username1:password1";
+            String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes());
+            connection.setRequestProperty("Authorization", basicAuth);
+            try (OutputStreamWriter out = new OutputStreamWriter(
+                    connection.getOutputStream(), CHARSET)) {
+                out.write(URLEncoder.encode(postBody, CHARSET));
+                out.flush();
+            }
+            try {
+                int status = connection.getResponseCode();
+                if (status == 200) {
+
+                    StringBuilder sbuf;
+                    try (BufferedReader br = new BufferedReader(
+                            new InputStreamReader(connection.getInputStream()))) {
+                        sbuf = new StringBuilder();
+                        String input;
+                        while ((input = br.readLine()) != null) {
+                            sbuf.append(URLDecoder.decode(input, CHARSET));
+                        }
+                    }
+                    return sbuf.toString();
+                } else {
+                    StringBuilder sbuf;
+                    try (BufferedReader br = new BufferedReader(
+                            new InputStreamReader(connection.getErrorStream()))) {
+                        sbuf = new StringBuilder();
+                        String input;
+                        while ((input = br.readLine()) != null) {
+                            sbuf.append(URLDecoder.decode(input, CHARSET));
+                        }
+                    }
+                    return sbuf.toString();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+
+    @Test
+    public void testOperatingSystemMbean() throws Exception {
+        //  Get MBeanInfo
+        String osMbeanInfo = executeHttpGetRequest("java.lang:type=OperatingSystem");
+        System.out.println(osMbeanInfo);
+
+        // Read all attributes
+        JSONParser parser = new JSONParser(osMbeanInfo);
+        JSONObject docRoot = (JSONObject) parser.parse();
+        JSONArray attrJson = (JSONArray) ((JSONObject) docRoot.get("response")).get("attributeInfo");
+        for (JSONElement elem : attrJson) {
+            JSONObject attrElem = (JSONObject) elem;
+            JSONPrimitive a = (JSONPrimitive) attrElem.get("name");
+            JSONPrimitive access = (JSONPrimitive) attrElem.get("access");
+            String attrResponse = executeHttpGetRequest("java.lang:type=OperatingSystem/" + a.getValue());
+            parser = new JSONParser(attrResponse);
+            docRoot = (JSONObject) parser.parse();
+            JSONPrimitive result = (JSONPrimitive) ((JSONObject) docRoot.get("response")).get(a.getValue());
+            System.out.println("Attribute : " + a.getValue() + "(" + access.getValue() + ")" + " - " + result.getValue());
+        }
+    }
+
+    @Test
+    public void testHotSpotDiagMBean() throws Exception {
+        String mbeanName = "com.sun.management:type=HotSpotDiagnostic";
+        String osMbeanInfo = executeHttpGetRequest(mbeanName);
+        System.out.println(osMbeanInfo);
+
+        // Read all attributes
+        JSONParser parser = new JSONParser(osMbeanInfo);
+        JSONObject docRoot = (JSONObject) parser.parse();
+        JSONArray attrJson = (JSONArray) ((JSONObject) docRoot.get("response")).get("attributeInfo");
+        if (attrJson != null) {
+            for (JSONElement elem : attrJson) {
+                JSONObject attrElem = (JSONObject) elem;
+                JSONPrimitive a = (JSONPrimitive) attrElem.get("name");
+                JSONPrimitive access = (JSONPrimitive) attrElem.get("access");
+                String attrResponse = executeHttpGetRequest(mbeanName + "/" + a.getValue());
+                parser = new JSONParser(attrResponse);
+                docRoot = (JSONObject) parser.parse();
+                JSONObject response = (JSONObject) docRoot.get("response");
+                if (response != null) {
+                    JSONElement get = response.get(a.getValue());
+                    System.out.println("Attribute : " + a.getValue() + "(" + access.getValue() + ")" + " - " + get.toJsonString());
+                } else {
+                    System.out.println("Attribute : " + a.getValue() + "(" + access.getValue() + ")" + " - null");
+                }
+            }
+        }
+
+        String dumpHeap = "{\n"
+                + "  \"name\": \"com.sun.management:type=HotSpotDiagnostic\",\n"
+                + "  \"exec\": \"dumpHeap\",\n"
+                + "  \"arguments\": [\n"
+                + "			\"heapdump.hprof\",\n"
+                + "			false\n"
+                + "		]\n"
+                + "}";
+
+        String responseJson = executeHttpPostRequest(dumpHeap);
+        parser = new JSONParser(responseJson);
+        docRoot = (JSONObject) parser.parse();
+        JSONElement response = docRoot.get("response");
+        System.out.println(" DumpHeap op - " + (response != null ? response.toJsonString() : null));
+
+        String getVmOption = "{\n"
+                + "  \"name\": \"com.sun.management:type=HotSpotDiagnostic\",\n"
+                + "  \"exec\": \"getVMOption\",\n"
+                + "  \"arguments\": [\n"
+                + "	\"PrintGCDetails\"\n"
+                + "	]\n"
+                + "}";
+        responseJson = executeHttpPostRequest(getVmOption);
+        parser = new JSONParser(responseJson);
+        docRoot = (JSONObject) parser.parse();
+        response = docRoot.get("response");
+        System.out.println(" DumpHeap op - " + (response != null ? response.toJsonString() : null));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/RestAdapterSSLTest.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,484 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+import com.oracle.jmx.remote.rest.json.JSONArray;
+import com.oracle.jmx.remote.rest.json.JSONElement;
+import com.oracle.jmx.remote.rest.json.JSONObject;
+import com.oracle.jmx.remote.rest.json.JSONPrimitive;
+import com.oracle.jmx.remote.rest.json.parser.JSONParser;
+import com.oracle.jmx.remote.rest.json.parser.ParseException;
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.util.Base64;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.remote.rest.JmxRestAdapter;
+import javax.management.remote.rest.PlatformRestAdapter;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.TrustManagerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @modules java.logging
+ *          java.management
+ *          java.management.rest
+ * @run testng/othervm RestAdapterSSLTest
+ * 
+ */
+@Test
+public class RestAdapterSSLTest {
+
+    private static final String CHARSET = "UTF-8";
+    private static String sslAgentConfig;
+    private static String sslClientConfig;
+    private static String passwordFile;
+    private static String configFile;
+
+    private void createAgentSslConfigFile(String fileName) throws IOException {
+        File f = new File(fileName);
+        if (f.exists()) {
+            return;
+        }
+        Properties props = new Properties();
+        String testDir = System.getProperty("test.src");
+        props.setProperty("javax.net.ssl.keyStore", testDir + File.separator + "keystoreAgent");
+        props.setProperty("javax.net.ssl.keyStorePassword", "glopglop");
+        props.setProperty("javax.net.ssl.trustStore", testDir + File.separator + "truststoreAgent");
+        props.setProperty("javax.net.ssl.trustStorePassword", "glopglop");
+
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
+            props.store(writer, "");
+        }
+    }
+
+    private void createClientSslConfigFile(String fileName) throws IOException {
+        File f = new File(fileName);
+        if (f.exists()) {
+            return;
+        }
+        Properties props = new Properties();
+        String testDir = System.getProperty("test.src");
+        props.setProperty("javax.net.ssl.keyStore", testDir + File.separator + "keystoreClient");
+        props.setProperty("javax.net.ssl.keyStorePassword", "glopglop");
+        props.setProperty("javax.net.ssl.trustStore", testDir + File.separator + "truststoreClient");
+        props.setProperty("javax.net.ssl.trustStorePassword", "glopglop");
+
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
+            props.store(writer, "");
+        }
+    }
+
+    private void setupMgmtConfig(String fileName) throws IOException {
+        Properties props = new Properties();
+        
+        props.setProperty("com.sun.management.jmxremote.ssl", "true");
+        props.setProperty("com.sun.management.jmxremote.ssl.config.file", sslAgentConfig);
+        props.setProperty("com.sun.management.jmxremote.password.file", passwordFile);
+        props.setProperty("com.sun.management.jmxremote.rest.port", "0");
+
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
+            props.store(writer, "");
+        }
+    }
+
+    private void setupConfig() throws Exception {
+        String testSrcRoot = System.getProperty("test.src") + File.separator;
+        sslAgentConfig = testSrcRoot + "sslConfigAgent";
+        sslClientConfig = testSrcRoot + "sslConfigClient";
+        passwordFile = testSrcRoot + "password.properties";
+        configFile = testSrcRoot + "mgmt.properties";
+        createAgentSslConfigFile(sslAgentConfig);
+        createClientSslConfigFile(sslClientConfig);
+        setupMgmtConfig(configFile);
+    }
+
+    @BeforeClass
+    public void setupAdapter() throws Exception {
+        setupConfig();
+        File file = new File(configFile);
+        Properties props = new Properties();
+        props.load(new FileInputStream(file));
+        if (props.get("com.sun.management.jmxremote.rest.port") != null) {
+            PlatformRestAdapter.init((String) props.get("com.sun.management.jmxremote.rest.port"), props);
+        }
+        PlatformRestAdapter.getInstance().start();
+        SSLContext ctx = getSSlContext(sslClientConfig);
+        HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
+        HttpsURLConnection.setDefaultHostnameVerifier(
+                (String hostname, javax.net.ssl.SSLSession sslSession) -> hostname.equals("Harsha-Wardhana-B"));
+        setupMbean();
+    }
+
+    @AfterClass
+    public void tearDown() {
+        PlatformRestAdapter.stop();
+    }
+
+    @DataProvider
+    public Object[][] getUrlList() {
+        Object[][] data = new Object[7][1];
+        data[0][0] = "?domain=default";
+        data[1][0] = "mbeans";
+        data[2][0] = "domains";
+        data[3][0] = "java.lang:type=Memory";
+        data[4][0] = "java.lang:type=Memory/HeapMemoryUsage";
+        data[5][0] = "java.lang:type=Memory/?attributes=HeapMemoryUsage,ObjectPendingFinalizationCount,NonHeapMemoryUsage";
+        data[6][0] = "java.lang:type=Memory/?attributes=all";
+        return data;
+    }
+
+    @DataProvider
+    public Object[][] getMalformedUrlList() {
+        Object[][] data = new Object[1][1];
+        data[0][0] = "com.example:type=QueueSamplerMBean";
+        return data;
+    }
+
+    private String executeHttpRequest(String inputUrl) throws IOException {
+        return executeHttpRequest(inputUrl, null);
+    }
+
+    private String executeHttpRequest(String inputUrl, String charset) throws IOException {
+        if (inputUrl != null && !inputUrl.isEmpty()) {
+            JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+            URL url = new URL(adapter.getBaseUrl() + (charset != null ? URLEncoder.encode(inputUrl, charset) : inputUrl));
+            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
+            con.setDoOutput(false);
+            String userCredentials = "username1:password1";
+            String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes());
+            con.setRequestProperty("Authorization", basicAuth);
+            if (charset != null && !charset.isEmpty()) {
+                con.setRequestProperty("Content-Type", "application/json; charset=" + charset);
+            }
+            try {
+                int status = con.getResponseCode();
+                if (status == 200) {
+
+                    StringBuilder sbuf;
+                    try (BufferedReader br = new BufferedReader(
+                            new InputStreamReader(con.getInputStream()))) {
+                        sbuf = new StringBuilder();
+                        String input;
+                        while ((input = br.readLine()) != null) {
+                            sbuf.append(charset != null ? URLDecoder.decode(input, charset) : input);
+                        }
+                    }
+                    return sbuf.toString();
+                } else {
+                    StringBuilder sbuf;
+                    try (BufferedReader br = new BufferedReader(
+                            new InputStreamReader(con.getErrorStream()))) {
+                        sbuf = new StringBuilder();
+                        String input;
+                        while ((input = br.readLine()) != null) {
+                            sbuf.append(charset != null ? URLDecoder.decode(input, charset) : input);
+                        }
+                    }
+                    return sbuf.toString();
+                }
+            } catch (IOException e) {
+            }
+        }
+        return null;
+    }
+
+    @Test
+    public void testMisc() throws IOException, ParseException {
+        String mBeanInfo = executeHttpRequest("com.sun.management:type=DiagnosticCommand");
+        System.out.println(mBeanInfo);
+        JSONParser parser = new JSONParser(mBeanInfo);
+        JSONObject response = (JSONObject) parser.parse();
+        long status = (Long) ((JSONPrimitive) response.get("status")).getValue();
+        Assert.assertEquals(status, 200);
+    }
+
+    @Test(enabled = false)
+    public void testCharset() throws IOException {
+        String result1 = executeHttpRequest("?domain=default");
+        String result2 = executeHttpRequest("?domain=default", CHARSET);
+        Assert.assertEquals(result1, result2);
+    }
+
+    @Test
+    public void testPostMisc() throws IOException {
+        JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+        URL url = new URL(adapter.getBaseUrl());
+        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+        connection.setRequestProperty("Content-Type", "application/json; charset=" + CHARSET);
+        connection.setDoOutput(true);
+        connection.setRequestMethod("POST");
+        String userCredentials = "username1:password1";
+        String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes());
+        connection.setRequestProperty("Authorization", basicAuth);
+
+        String req = "{\n"
+                + "    \"name\":\"java.lang:type=Memory\"\n"
+                + "    \"write\":\"Verbose\"\n"
+                + "    \"arguments\" : [true]\n"
+                + "}";
+        try (OutputStreamWriter out = new OutputStreamWriter(
+                connection.getOutputStream(), CHARSET)) {
+            out.write(URLEncoder.encode(req, CHARSET));
+            out.flush();
+        }
+
+        print_content(connection);
+    }
+
+    @Test
+    public void testBasicHttps() throws Exception {
+        JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+        URL url = new URL(adapter.getBaseUrl());
+        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
+        con.setDoOutput(false);
+
+        String userCredentials = "username1:password1";
+
+        String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes());
+        con.setRequestProperty("Authorization", basicAuth);
+        print_https_cert(con);
+        print_content(con);
+    }
+
+    @Test(dataProvider = "getUrlList")
+    public void testGetRequests(String urlStr) throws Exception {
+        String input = executeHttpRequest(urlStr);
+        System.out.println("URL : [" + urlStr + "] ----> " + input);
+        System.out.println(input);
+        JSONParser parser = new JSONParser(input);
+        JSONElement parse = parser.parse();
+        JSONElement jstatus = ((JSONObject) parse).get("status");
+        long status = (Long) ((JSONPrimitive) jstatus).getValue();
+        Assert.assertEquals(status, 200);
+    }
+
+    @Test
+    public void testAllGetMBeanInfo() throws Exception {
+        String input = executeHttpRequest("mbeans");
+        JSONParser parser = new JSONParser(input);
+        JSONElement jsonObj = parser.parse();
+        if (jsonObj instanceof JSONObject) {
+            JSONElement jelem = ((JSONObject) jsonObj).get("response");
+            if (jelem instanceof JSONArray) {
+                for (JSONElement elem : ((JSONArray) jelem)) {
+                    String objName = (String) ((JSONPrimitive) elem).getValue();
+                    String mBeanInfo = executeHttpRequest(objName);
+                    System.out.println(mBeanInfo);
+                    parser = new JSONParser(mBeanInfo);
+                    JSONObject response = (JSONObject) parser.parse();
+                    long status = (Long) ((JSONPrimitive) response.get("status")).getValue();
+                    Assert.assertEquals(status, 200);
+                }
+            }
+        }
+    }
+
+    @Test(enabled = false, dataProvider = "getMalformedUrlList")
+    public void negTestGetRequests(String urlStr) throws Exception {
+        JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+        URL url = new URL(adapter.getBaseUrl() + urlStr);
+        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
+        con.setDoOutput(false);
+        String userCredentials = "username1:password1";
+        String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes());
+        con.setRequestProperty("Authorization", basicAuth);
+        print_content(con);
+    }
+
+    @Test
+    public void testPost() throws Exception {
+        JmxRestAdapter adapter = PlatformRestAdapter.getInstance();
+        URL url = new URL(adapter.getBaseUrl());
+        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+        connection.setRequestProperty("Content-Type", "application/json; charset=" + CHARSET);
+        connection.setDoOutput(true);
+        connection.setRequestMethod("POST");
+        String userCredentials = "username1:password1";
+        String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes());
+        connection.setRequestProperty("Authorization", basicAuth);
+
+        String postReq = "{\"name\":\"com.example:type=QueueSampler\",\"exec\":\"testMethod1\",\"arguments\":[[1,2,3],\"abc\",5,[\"asd\",\"3\",\"67\",\"778\"],[{date:\"2016-03-02\",size:3,head:\"head\"}],[{date:\"2016-03-02\",size:3,head:\"head\"}]]}";
+        JSONArray jarr = new JSONArray();
+
+        JSONObject jobject = new JSONObject();
+        jobject.put("name", "com.example:type=QueueSampler");
+        jobject.put("write", "QueueName");
+        JSONArray jarr1 = new JSONArray();
+        jarr1.add(new JSONPrimitive("Dequeue"));
+        jobject.put("arguments", jarr1);
+        jarr.add(jobject);
+
+        jobject = new JSONObject();
+        jobject.put("name", "com.example:type=QueueSampler");
+        jobject.put("read", "QueueName");
+        jarr.add(jobject);
+
+        jarr.add(new JSONParser(postReq).parse());
+
+        try (OutputStreamWriter out = new OutputStreamWriter(
+                connection.getOutputStream(), CHARSET)) {
+            out.write(URLEncoder.encode(jarr.toJsonString(), CHARSET));
+            out.flush();
+        }
+        print_content(connection);
+    }
+
+    @Test(enabled = false)
+    public void testMBeanFilter() throws MalformedObjectNameException {
+        // Add non-compliant MBean to platform mbean server
+        ObjectName mbeanName = new ObjectName("com.example:type=QueueSamplerMBean");
+    }
+
+    private void setupMbean() throws Exception {
+        // Get the Platform MBean Server
+//        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+//
+//        // Construct the ObjectName for the QueueSampler MXBean we will register
+//        ObjectName mxbeanName = new ObjectName("com.example:type=QueueSampler");
+//        ObjectName mbeanName = new ObjectName("com.example:type=QueueSamplerMBean");
+//
+//        // Create the Queue Sampler MXBean
+//        Queue<String> queue = new ArrayBlockingQueue<>(10);
+//        queue.add("Request-1");
+//        queue.add("Request-2");
+//        queue.add("Request-3");
+//        QueueSampler mxbean = new QueueSampler(queue);
+//        QueueSamplerBean mbean = new QueueSamplerBean(queue);
+//
+//        // Register the Queue Sampler MXBean
+//        mbs.registerMBean(mxbean, mxbeanName);
+//        mbs.registerMBean(mbean, mbeanName);
+    }
+
+    private void print_content(HttpURLConnection con) {
+        if (con != null) {
+            try {
+                System.out.println("****** Content of the URL ********");
+                int status = con.getResponseCode();
+
+                System.out.println("Status = " + status);
+                InputStream is;
+                if (status == HttpURLConnection.HTTP_OK) {
+                    is = con.getInputStream();
+                } else {
+                    is = con.getErrorStream();
+                }
+                BufferedReader br
+                        = new BufferedReader(new InputStreamReader(is));
+                String input;
+                while ((input = br.readLine()) != null) {
+                    System.out.println(URLDecoder.decode(input, CHARSET));
+                }
+                br.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void print_https_cert(HttpsURLConnection con) {
+        if (con != null) {
+            try {
+                System.out.println("Response Code : " + con.getResponseCode());
+                System.out.println("Cipher Suite : " + con.getCipherSuite());
+                System.out.println("\n");
+
+                Certificate[] certs = con.getServerCertificates();
+                for (Certificate cert : certs) {
+                    System.out.println("Cert Type : " + cert.getType());
+                    System.out.println("Cert Hash Code : " + cert.hashCode());
+                    System.out.println("Cert Public Key Algorithm : "
+                            + cert.getPublicKey().getAlgorithm());
+                    System.out.println("Cert Public Key Format : "
+                            + cert.getPublicKey().getFormat());
+                    System.out.println("\n");
+                }
+
+            } catch (SSLPeerUnverifiedException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private static SSLContext getSSlContext(String sslConfigFileName) {
+        final String keyStore, keyStorePassword, trustStore, trustStorePassword;
+
+        try {
+            Properties p = new Properties();
+            BufferedInputStream bin = new BufferedInputStream(new FileInputStream(sslConfigFileName));
+            p.load(bin);
+            keyStore = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_KEYSTORE_FILE);
+            keyStorePassword = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_KEYSTORE_PASSWORD);
+            trustStore = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_TRUSTSTORE_FILE);
+            trustStorePassword = p.getProperty(PlatformRestAdapter.PropertyNames.SSL_TRUSTSTORE_PASSWORD);
+
+            char[] keyStorePasswd = null;
+            if (keyStorePassword.length() != 0) {
+                keyStorePasswd = keyStorePassword.toCharArray();
+            }
+
+            char[] trustStorePasswd = null;
+            if (trustStorePassword.length() != 0) {
+                trustStorePasswd = trustStorePassword.toCharArray();
+            }
+
+            KeyStore ks = null;
+            if (keyStore != null) {
+                ks = KeyStore.getInstance(KeyStore.getDefaultType());
+                FileInputStream ksfis = new FileInputStream(keyStore);
+                ks.load(ksfis, keyStorePasswd);
+
+            }
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance(
+                    KeyManagerFactory.getDefaultAlgorithm());
+            kmf.init(ks, keyStorePasswd);
+
+            KeyStore ts = null;
+            if (trustStore != null) {
+                ts = KeyStore.getInstance(KeyStore.getDefaultType());
+                FileInputStream tsfis = new FileInputStream(trustStore);
+                ts.load(tsfis, trustStorePasswd);
+            }
+            TrustManagerFactory tmf = TrustManagerFactory.getInstance(
+                    TrustManagerFactory.getDefaultAlgorithm());
+            tmf.init(ts);
+
+            SSLContext ctx = SSLContext.getInstance("SSL");
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+            return ctx;
+        } catch (Exception ex) {
+            Logger.getLogger(PlatformRestAdapter.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/RunRestAdapter.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,96 @@
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Properties;
+import javax.management.remote.rest.PlatformRestAdapter;
+
+
+/**
+ * @test
+ * @modules java.logging
+ *          java.management.rest
+ * @run main RunRestAdapter
+ */
+public class RunRestAdapter {
+
+    private static String sslAgentConfig;
+    private static String sslClientConfig;
+    private static String configFile;
+
+    public static void main(String[] args) throws Exception {
+        RunRestAdapter rr = new RunRestAdapter();
+        rr.run();
+    }
+
+    private void createAgentSslConfigFile(String fileName) throws IOException {
+        File f = new File(fileName);
+        if (f.exists()) {
+            return;
+        }
+        Properties props = new Properties();
+        String testDir = System.getProperty("test.src");
+        props.setProperty("javax.net.ssl.keyStore", testDir + File.separator + "keystoreAgent");
+        props.setProperty("javax.net.ssl.keyStorePassword", "glopglop");
+        props.setProperty("javax.net.ssl.trustStore", testDir + File.separator + "truststoreAgent");
+        props.setProperty("javax.net.ssl.trustStorePassword", "glopglop");
+
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
+            props.store(writer, "");
+        }
+    }
+
+    private void createClientSslConfigFile(String fileName) throws IOException {
+        File f = new File(fileName);
+        if (f.exists()) {
+            return;
+        }
+        Properties props = new Properties();
+        String testDir = System.getProperty("test.src");
+        props.setProperty("javax.net.ssl.keyStore", testDir + File.separator + "keystoreClient");
+        props.setProperty("javax.net.ssl.keyStorePassword", "glopglop");
+        props.setProperty("javax.net.ssl.trustStore", testDir + File.separator + "truststoreClient");
+        props.setProperty("javax.net.ssl.trustStorePassword", "glopglop");
+
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
+            props.store(writer, "");
+        }
+    }
+
+    private void setupMgmtConfig(String fileName) throws IOException {
+        Properties props = new Properties();
+        props.setProperty("com.sun.management.jmxremote.ssl", "true");
+        props.setProperty("com.sun.management.jmxremote.ssl.config.file", sslAgentConfig);
+        props.setProperty("com.sun.management.jmxremote.authenticate", "false");
+        props.setProperty("com.sun.management.jmxremote.rest.port", "8686");
+
+        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
+            props.store(writer, "");
+        }
+    }
+
+    private void setupConfig() throws Exception {
+        String testSrcRoot = System.getProperty("test.src") + File.separator;
+        sslAgentConfig = testSrcRoot + "sslConfigAgent";
+        sslClientConfig = testSrcRoot + "sslConfigClient";
+
+        configFile = testSrcRoot + "mgmt1.properties";
+        createAgentSslConfigFile(sslAgentConfig);
+        createClientSslConfigFile(sslClientConfig);
+        setupMgmtConfig(configFile);
+    }
+
+    public void run() throws Exception {
+        setupConfig();
+        File file = new File(configFile);
+        Properties props = new Properties();
+        props.load(new FileInputStream(file));
+        if (props.get("com.sun.management.jmxremote.rest.port") != null) {
+            PlatformRestAdapter.init((String) props.get("com.sun.management.jmxremote.rest.port"), props);
+        }
+        PlatformRestAdapter.getInstance().start();
+        Thread.sleep(1000000);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/data/QueueSample.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,38 @@
+package javax.management.remote.rest.test.data;
+
+/*
+ * QueueSample.java - Java type representing a snapshot of a given queue.
+ * It bundles together the instant time the snapshot was taken, the queue
+ * size and the queue head.
+ */
+
+
+
+import java.beans.ConstructorProperties;
+import java.util.Date;
+
+public class QueueSample {
+    
+    private final Date date;
+    private final int size;
+    private final String head;
+
+    @ConstructorProperties({"date", "size", "head"})
+    public QueueSample(Date date, int size, String head) {
+        this.date = date;
+        this.size = size;
+        this.head = head;
+    }
+
+    public Date getDate() {
+        return date;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public String getHead() {
+        return head;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/data/QueueSampler.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,58 @@
+package javax.management.remote.rest.test.data;
+
+/*
+ * QueueSampler.java - MXBean implementation for the QueueSampler MXBean.
+ * This class must implement all the Java methods declared in the
+ * QueueSamplerMXBean interface, with the appropriate behavior for each one.
+ */
+
+
+import java.util.Date;
+import java.util.List;
+import java.util.Queue;
+
+public class QueueSampler implements QueueSamplerMXBean {
+
+    private Queue<String> queue;
+    private QueueSample sample;
+    private String name;
+
+    public QueueSampler(Queue<String> queue) {
+        this.queue = queue;
+        synchronized (queue) {
+            sample = new QueueSample(new Date(), queue.size(), queue.peek());
+        }
+        name = "BoogeyMan";
+    }
+
+    public QueueSample getQueueSample() {
+        return sample;
+    }
+    
+    public void clearQueue() {
+        synchronized (queue) {
+            queue.clear();
+        }
+    }
+
+    @Override
+    public String[] testMethod1(int[] param2, String param1, int sd34, String[] param3, QueueSample[] param4, List<QueueSample> param5) {
+        System.out.println("########## Invoke TestMethod1");
+        return new String[]{"1","2","3","4","5"};
+    }
+
+    @Override
+    public void setQueueSample(QueueSample sample) {
+        this.sample = sample;
+    }
+
+    @Override
+    public String getQueueName() {
+        return name;
+    }
+
+    @Override
+    public void setQueueName(String name) {
+        this.name = name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/data/QueueSamplerBean.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,59 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package javax.management.remote.rest.test.data;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Queue;
+
+/**
+ *
+ * @author harsha
+ */
+public class QueueSamplerBean implements QueueSamplerBeanMBean {
+
+    private Queue<String> queue;
+    private QueueSample sample;
+    private String name;
+
+    public QueueSamplerBean(Queue<String> queue) {
+        this.queue = queue;
+        synchronized (queue) {
+            sample = new QueueSample(new Date(), queue.size(), queue.peek());
+        }
+        name = "BoogeyMan";
+    }
+
+    public QueueSample getQueueSample() {
+        return sample;
+    }
+    
+    public void clearQueue() {
+        synchronized (queue) {
+            queue.clear();
+        }
+    }
+
+    @Override
+    public String[] testMethod1(int[] param2, String param1, int sd34, String[] param3, QueueSample[] param4, List<QueueSample> param5) {
+        return new String[]{"1","2","3","4","5"};
+    }
+
+    @Override
+    public void setQueueSample(QueueSample sample) {
+        this.sample = sample;
+    }
+
+    @Override
+    public String getQueueName() {
+        return name;
+    }
+
+    @Override
+    public void setQueueName(String name) {
+        this.name = name;
+    }    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/data/QueueSamplerBeanMBean.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,26 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package javax.management.remote.rest.test.data;
+
+import java.util.List;
+
+/**
+ *
+ * @author harsha
+ */
+public interface QueueSamplerBeanMBean {
+        public QueueSample getQueueSample();
+    
+    public void setQueueSample(QueueSample sample);
+
+    public String getQueueName();
+    
+    public void setQueueName(String name);
+    
+    public void clearQueue();
+
+    public String[] testMethod1(int[] param2, String param1, int sd34, String[] param3, QueueSample[] param4, List<QueueSample> param5);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/data/QueueSamplerMXBean.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,19 @@
+package javax.management.remote.rest.test.data;
+
+
+import java.util.List;
+
+public interface QueueSamplerMXBean {
+    
+    public QueueSample getQueueSample();
+    
+    public void setQueueSample(QueueSample sample);
+
+    public String getQueueName();
+    
+    public void setQueueName(String name);
+    
+    public void clearQueue();
+
+    public String[] testMethod1(int[] param2, String param1, int sd34, String[] param3, QueueSample[] param4, List<QueueSample> param5);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/json/JSONTest.java	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,408 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+import com.oracle.jmx.remote.rest.json.parser.JSONParser;
+import com.oracle.jmx.remote.rest.json.parser.ParseException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * @test @modules java.management.rest
+ * @run main JSONTest
+ */
+public class JSONTest {
+
+    public static void main(String[] args) throws ParseException {
+        JSONGraphGenerator graphGen = new JSONGraphGenerator(50);
+        JSONElement jElem = graphGen.generateJsonGraph(20000);
+        System.out.println("Graph Generated");
+        String str = jElem.toJsonString();
+        System.out.println(str);
+
+        JSONParser parser = new JSONParser(str);
+
+        com.oracle.jmx.remote.rest.json.JSONElement parse = parser.parse();
+        String resultJson = parse.toJsonString();
+        System.out.println(resultJson);
+    }
+}
+
+interface JSONElement {
+
+    String toJsonString();
+}
+
+interface Visitable {
+
+    public void accept(NodeVisitor visitor);
+}
+
+interface NodeVisitor {
+
+    public void visit(Node node);
+
+    //visit other concrete items
+    public void visit(Digit19 digit12);
+
+    public void visit(Digits dvd);
+}
+
+class Node implements Visitable {
+
+    final private String label;
+
+    public Node(String label) {
+        children = new LinkedList<>();
+        this.label = label;
+    }
+
+    public Node() {
+        this("");
+    }
+
+    public void add(Node node) {
+        if (!children.contains(node)) {
+            children.add(node);
+        }
+    }
+
+    public String getLabel() {
+        return label;
+    }
+    List<Node> children;
+
+    @Override
+    public void accept(NodeVisitor visitor) {
+        visitor.visit(this);
+    }
+}
+
+class Digit19 extends Node {
+
+    Random rnd = new Random();
+
+    public Digit19() {
+        super();
+    }
+
+    @Override
+    public String getLabel() {
+        return "" + (rnd.nextInt(9) + 1);
+    }
+}
+
+class Digits extends Node {
+
+    Random rnd = new Random();
+
+    public Digits() {
+        super();
+    }
+
+    @Override
+    public String getLabel() {
+        return "" + (rnd.nextInt(10));
+    }
+}
+
+class JSONNumberGenerator {
+
+    private final static Node root;
+    Number num;
+
+    static {
+        root = new Node("R");
+        Node minus1 = new Node("-");
+        Node zero = new Node("0");
+        Node digit19 = new Digit19();
+        Node digits1 = new Digits();
+        Node dot = new Node(".");
+        Node digits2 = new Digits();
+        Node e = new Node("e");
+        Node E = new Node("E");
+        Node plus = new Node("+");
+        Node minus2 = new Node("-");
+        Node digits3 = new Digits();
+        Node terminal = new Node("T");
+
+        root.add(zero);
+        root.add(minus1);
+        root.add(digit19);
+
+        minus1.add(zero);
+        minus1.add(digit19);
+
+        zero.add(dot);
+//        zero.add(e);
+//        zero.add(E);
+        zero.add(terminal);
+
+        digit19.add(dot);
+        digit19.add(digits1);
+//        digit19.add(e);
+//        digit19.add(E);
+        digit19.add(terminal);
+
+        digits1.add(dot);
+        digits1.add(digits1);
+//        digits1.add(e);
+//        digits1.add(E);
+        digits1.add(terminal);
+
+        dot.add(digits2);
+
+        digits2.add(digits2);
+        digits2.add(e);
+        digits2.add(E);
+        digits2.add(terminal);
+
+        e.add(plus);
+        e.add(minus2);
+        e.add(digits3);
+
+        E.add(plus);
+        E.add(minus2);
+        E.add(digits3);
+
+        plus.add(digits3);
+        minus2.add(digits3);
+
+        digits3.add(digits3);
+        digits3.add(terminal);
+    }
+
+    private static class NumberNodeVisitor implements NodeVisitor {
+
+        private final StringBuilder sbuf = new StringBuilder();
+        Random rnd = new Random();
+
+        public NumberNodeVisitor() {
+        }
+
+        @Override
+        public void visit(Node node) {
+            if (!node.getLabel().equals("R")) {
+                sbuf.append(node.getLabel());
+            }
+            if (node.children.size() > 0) {
+                Node child = node.children.get(rnd.nextInt(node.children.size()));
+                if (!child.getLabel().equals("T")) {
+                    visit(child);
+                }
+            } else {
+                System.out.println("Found node " + node.getLabel() + " with children : " + node.children.size());
+            }
+        }
+
+        @Override
+        public void visit(Digit19 digit12) {
+            sbuf.append(digit12.getLabel());
+            Node child = digit12.children.get(rnd.nextInt(digit12.children.size()));
+            if (!child.getLabel().equals("T")) {
+                visit(child);
+            }
+        }
+
+        @Override
+        public void visit(Digits digits) {
+            sbuf.append(digits.getLabel());
+            Node child = digits.children.get(rnd.nextInt(digits.children.size()));
+            if (!child.getLabel().equals("T")) {
+                visit(child);
+            }
+        }
+
+        public String getNumber() {
+            return sbuf.toString();
+        }
+
+    }
+
+    public String generate() {
+        NumberNodeVisitor visitor = new NumberNodeVisitor();
+        visitor.visit(root);
+        // System.out.println(visitor.getNumber());
+//        Double.parseDouble(visitor.getNumber());
+        return visitor.getNumber();
+    }
+}
+
+class TestJsonObject extends LinkedHashMap<String, JSONElement> implements JSONElement {
+
+    @Override
+    public String toJsonString() {
+        if (isEmpty()) {
+            return null;
+        }
+
+        StringBuilder sbuild = new StringBuilder();
+        sbuild.append("{");
+        keySet().forEach((elem) -> {
+            sbuild.append(elem).append(": ").
+                    append((get(elem) != null) ? get(elem).toJsonString() : "null").append(",");
+        });
+
+        sbuild.deleteCharAt(sbuild.lastIndexOf(","));
+        sbuild.append("}");
+        return sbuild.toString();
+    }
+}
+
+class TestJsonArray extends ArrayList<JSONElement> implements JSONElement {
+
+    @Override
+    public String toJsonString() {
+        if (isEmpty()) {
+            return null;
+        }
+        StringBuilder sbuild = new StringBuilder();
+        sbuild.append("[");
+        Iterator<JSONElement> itr = iterator();
+        while (itr.hasNext()) {
+            JSONElement val = itr.next();
+            if (val != null) {
+                sbuild.append(val.toJsonString()).append(", ");
+            } else {
+                sbuild.append("null").append(", ");
+            }
+        }
+
+        sbuild.deleteCharAt(sbuild.lastIndexOf(","));
+        sbuild.append("]");
+        return sbuild.toString();
+    }
+}
+
+class TestJsonPrimitive implements JSONElement {
+
+    private final String s;
+
+    public TestJsonPrimitive(String s) {
+        this.s = s;
+    }
+
+    @Override
+    public String toJsonString() {
+        return s;
+    }
+}
+
+class JSONStringGenerator {
+
+    private static final int minStringLength = 0;
+    private static final int maxStringLength = 10;
+
+    private final Random rnd = new Random(System.currentTimeMillis());
+
+    private static final String specials = "\b" + "\f" + "\n" + "\r" + "\t" + "\\" + "\"";    // TODO: Special characters '/', '\', '"', "\\uxxxx"
+    private static final String alphanums = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+    public String generate() {
+        char ch;
+        StringBuilder sbuf = new StringBuilder();
+        int len = minStringLength + rnd.nextInt(maxStringLength - minStringLength + 1);
+        sbuf.append("\"");
+        for (int i = 0; i < len; i++) {
+            if (rnd.nextInt(10) == 1) { // 1/10 chances of a control character
+                ch = specials.charAt(rnd.nextInt(specials.length()));
+            } else {
+//                ch = alphanums.charAt(rnd.nextInt(alphanums.length()));
+                ch = (char) rnd.nextInt(Character.MAX_VALUE + 1);
+            }
+            switch (ch) {
+                case '\"':
+                case '\\':
+                    sbuf.append('\\');
+            }
+            sbuf.append(ch);
+        }
+        sbuf.append("\"");
+        return sbuf.toString();
+    }
+}
+
+class JSONGraphGenerator {
+
+    JSONStringGenerator stringGen;
+    JSONNumberGenerator numGen;
+    private final int maxChildPerNode;
+    static Random rnd = new Random(System.currentTimeMillis());
+
+    public JSONGraphGenerator(int maxChildPerNode) {
+        this.maxChildPerNode = maxChildPerNode;
+        stringGen = new JSONStringGenerator();
+        numGen = new JSONNumberGenerator();
+    }
+
+    private TestJsonPrimitive generatePrimitiveData() {
+        int primitiveTypre = rnd.nextInt(10) + 1;
+        switch (primitiveTypre) {
+            case 1:
+            case 2:
+            case 3:
+            case 4:
+                return new TestJsonPrimitive(stringGen.generate());
+            case 5:
+            case 6:
+            case 7:
+            case 8:
+                return new TestJsonPrimitive(numGen.generate());
+            case 9:
+                return new TestJsonPrimitive(Boolean.toString(rnd.nextBoolean()));
+            case 10:
+                return null;
+        }
+        return null;
+    }
+
+    public TestJsonObject generateJsonObject(int size) {
+        TestJsonObject jobj = new TestJsonObject();
+        if (size <= maxChildPerNode) {
+            for (int i = 0; i < size; i++) {
+                jobj.put(stringGen.generate(), generatePrimitiveData());
+            }
+        } else {
+            int newSize = size;
+            do {
+                int childSize = rnd.nextInt(newSize);
+                jobj.put(stringGen.generate(), generateJsonGraph(childSize));
+                newSize = newSize - childSize;
+            } while (newSize > maxChildPerNode);
+            jobj.put(stringGen.generate(), generateJsonGraph(newSize));
+        }
+        return jobj;
+    }
+
+    public TestJsonArray generateJsonArray(int size) {
+        TestJsonArray array = new TestJsonArray();
+        if (size <= maxChildPerNode) {
+            for (int i = 0; i < size; i++) {
+                array.add(generatePrimitiveData());
+            }
+        } else if (size >= maxChildPerNode) {
+            int newSize = size;
+            do {
+                int childSize = rnd.nextInt(newSize);
+                array.add(generateJsonGraph(childSize));
+                newSize = newSize - childSize;
+            } while (newSize > maxChildPerNode);
+            array.add(generateJsonGraph(newSize));
+        }
+        return array;
+    }
+
+    public JSONElement generateJsonGraph(int size) {
+        if (rnd.nextBoolean()) {
+            return generateJsonArray(size);
+        } else {
+            return generateJsonObject(size);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/management.properties	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,6 @@
+com.sun.management.jmxremote.ssl=true
+com.sun.management.jmxremote.ssl.config.file=sslconfig
+# com.sun.management.jmxremote.login.config=<config-name>
+com.sun.management.jmxremote.password.file=password.properties
+# com.sun.management.jmxremote.host=<host-or-interface-name>
+com.sun.management.jmxremote.rest.port=8686
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/management1.properties	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,7 @@
+com.sun.management.jmxremote.ssl=true
+com.sun.management.jmxremote.ssl.config.file=/home/harsha/work/jdk10_rest/jdk/test/sun/management/jmxremote/rest/sslconfig
+# com.sun.management.jmxremote.login.config=<config-name>
+com.sun.management.jmxremote.authenticate=false
+com.sun.management.jmxremote.password.file=/home/harsha/work/jdk10_rest/jdk/test/sun/management/jmxremote/rest/password.properties
+# com.sun.management.jmxremote.host=<host-or-interface-name>
+com.sun.management.jmxremote.rest.port=8686
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/mgmt.properties	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,6 @@
+#
+#Tue Aug 29 13:30:12 IST 2017
+com.sun.management.jmxremote.ssl=true
+com.sun.management.jmxremote.rest.port=0
+com.sun.management.jmxremote.ssl.config.file=/home/harsha/work/sandbox/jdk/test/javax/management/remote/rest/sslConfigAgent
+com.sun.management.jmxremote.password.file=/home/harsha/work/sandbox/jdk/test/javax/management/remote/rest/password.properties
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/mgmt1.properties	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,6 @@
+#
+#Sun Aug 27 13:25:24 IST 2017
+com.sun.management.jmxremote.ssl=true
+com.sun.management.jmxremote.rest.port=8686
+com.sun.management.jmxremote.ssl.config.file=/home/harsha/work/jdk10_rest/jdk/test/javax/management/remote/rest/sslConfigAgent
+com.sun.management.jmxremote.authenticate=false
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/password.properties	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,12 @@
+# Password file for default SQE username.
+SQE_username SQE_password
+
+# Functional authorization tests
+username1 password1
+username2 password2
+username3 password3
+username4 password4
+username5 password5
+username6 password6
+
+usernameFileLoginModule passwordFileLoginModule
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/server.cer	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZECBEDtdcwwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCRlIxDjAM
+BgNVBAgTBUlzZXJlMREwDwYDVQQHEwhHcmVub2JsZTEMMAoGA1UEChMDU3VuMQ0w
+CwYDVQQLEwRKMlNFMQwwCgYDVQQDEwNKTVgwHhcNMDQwNzA4MTYyNjUyWhcNMzkw
+NjMwMTYyNjUyWjBbMQswCQYDVQQGEwJGUjEOMAwGA1UECBMFSXNlcmUxETAPBgNV
+BAcTCEdyZW5vYmxlMQwwCgYDVQQKEwNTdW4xDTALBgNVBAsTBEoyU0UxDDAKBgNV
+BAMTA0pNWDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnbqRH7+SCpPA2z06
+DCwDwVaJmkc5mg1nX1j8lebEnDY0OrwlZBikirt3m/cIUnRWLepIgaoFd6HfAIaP
+Lx7AyGqwEv0LqHjTo/hgehmi+oK9oJsMaDqCdIQ+Lb53Lo9ECHDHP84gkCgmQqy6
+EvKR16wiI46d9D8BDe7huIJaUGkCAwEAATANBgkqhkiG9w0BAQQFAAOBgQARo5Fr
+4lFOzLDwUn9lH/3We+4wCbpzvHFOZBKUizv+rTk5oeZHQc+0yXHZMuzTUYShlTvK
+sYLXGUF9BahM2YFvLp40lnIfEYPlNptbJWceN5K2a41A0JoxmuoS2dhegzY6p4ED
+EpoEySMQZS3ZW2AsOQsozGW02E3GaJB7TI93gg==
+-----END CERTIFICATE-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/sslConfigAgent	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,6 @@
+#
+#Tue Aug 29 12:26:55 IST 2017
+javax.net.ssl.trustStore=/home/harsha/work/sandbox/jdk/test/javax/management/remote/rest/truststoreAgent
+javax.net.ssl.keyStorePassword=glopglop
+javax.net.ssl.trustStorePassword=glopglop
+javax.net.ssl.keyStore=/home/harsha/work/sandbox/jdk/test/javax/management/remote/rest/keystoreAgent
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/sslConfigClient	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,6 @@
+#
+#Tue Aug 29 12:26:55 IST 2017
+javax.net.ssl.trustStore=/home/harsha/work/sandbox/jdk/test/javax/management/remote/rest/truststoreClient
+javax.net.ssl.keyStorePassword=glopglop
+javax.net.ssl.trustStorePassword=glopglop
+javax.net.ssl.keyStore=/home/harsha/work/sandbox/jdk/test/javax/management/remote/rest/keystoreClient
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/sslconfig	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,5 @@
+javax.net.ssl.keyStore=keystoreAgent
+javax.net.ssl.keyStorePassword=glopglop
+javax.net.ssl.trustStore=truststoreAgent
+javax.net.ssl.trustStorePassword=glopglop
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/management/remote/rest/sslconfigClient	Tue Aug 29 13:34:15 2017 +0530
@@ -0,0 +1,5 @@
+javax.net.ssl.keyStore=keystoreClient
+javax.net.ssl.keyStorePassword=glopglop
+javax.net.ssl.trustStore=truststoreClient
+javax.net.ssl.trustStorePassword=glopglop
+