REST Adapter Initial commit
1. Unit tested and working GET/POST interfaces
2. Unit tested and working JSON parser
--- /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
+