src/java.management.rest/share/classes/com/oracle/jmx/remote/rest/http/PostRequestHandler.java
author hb
Tue, 29 Aug 2017 13:34:15 +0530
branchjmx-rest-api
changeset 55985 0c5a02edfdef
permissions -rw-r--r--
REST Adapter Initial commit 1. Unit tested and working GET/POST interfaces 2. Unit tested and working JSON parser
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
55985
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
     1
/*
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
     2
 * To change this license header, choose License Headers in Project Properties.
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
     3
 * To change this template file, choose Tools | Templates
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
     4
 * and open the template in the editor.
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
     5
 */
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
     6
package com.oracle.jmx.remote.rest.http;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
     7
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
     8
import javax.management.*;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
     9
import javax.management.openmbean.OpenMBeanAttributeInfo;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    10
import javax.management.openmbean.OpenMBeanParameterInfo;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    11
import javax.management.openmbean.OpenType;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    12
import com.oracle.jmx.remote.rest.json.JSONArray;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    13
import com.oracle.jmx.remote.rest.json.JSONElement;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    14
import com.oracle.jmx.remote.rest.json.JSONObject;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    15
import com.oracle.jmx.remote.rest.json.JSONPrimitive;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    16
import com.oracle.jmx.remote.rest.mapper.JSONDataException;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    17
import com.oracle.jmx.remote.rest.mapper.JSONMapper;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    18
import com.oracle.jmx.remote.rest.mapper.JSONMappingException;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    19
import com.oracle.jmx.remote.rest.mapper.JSONMappingFactory;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    20
import com.oracle.jmx.remote.rest.json.parser.JSONParser;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    21
import com.oracle.jmx.remote.rest.json.parser.ParseException;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    22
import java.net.HttpURLConnection;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    23
import java.util.*;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    24
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    25
/**
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    26
 * @author harsha
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    27
 */
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    28
public class PostRequestHandler {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    29
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    30
    private static final String MBEAN_NAME = "name";
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    31
    private static final String MBEAN_ARGUMENTS = "arguments";
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    32
    private final static Map<String, Class<?>> primitiveToObject = new HashMap<>();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    33
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    34
    static {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    35
        primitiveToObject.put("int", Integer.TYPE);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    36
        primitiveToObject.put("long", Long.TYPE);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    37
        primitiveToObject.put("double", Double.TYPE);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    38
        primitiveToObject.put("float", Float.TYPE);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    39
        primitiveToObject.put("boolean", Boolean.TYPE);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    40
        primitiveToObject.put("char", Character.TYPE);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    41
        primitiveToObject.put("byte", Byte.TYPE);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    42
        primitiveToObject.put("void", Void.TYPE);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    43
        primitiveToObject.put("short", Short.TYPE);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    44
    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    45
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    46
    private final MBeanServer mbeanServer;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    47
    private final List<String> allowedMbeans;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    48
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    49
    public PostRequestHandler(MBeanServer mServer, List<String> allowedMbeans) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    50
        this.mbeanServer = mServer;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    51
        this.allowedMbeans = allowedMbeans;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    52
    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    53
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    54
    public synchronized List<JSONObject> handle(String jsonStr) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    55
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    56
        JSONElement object;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    57
        List<JSONObject> postResponse = new ArrayList<>();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    58
        try {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    59
            object = new JSONParser(jsonStr).parse();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    60
        } catch (ParseException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    61
            postResponse.add(HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex), new JSONPrimitive(jsonStr), new JSONPrimitive("Invalid JSON String")));
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    62
            return postResponse;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    63
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    64
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    65
        if (object instanceof JSONObject) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    66
            postResponse.add(handleIndividualRequest((JSONObject) object));
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    67
            return postResponse;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    68
        } else if (object instanceof JSONArray) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    69
            JSONArray jarr = (JSONArray) object;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    70
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    71
            for (JSONElement jval : jarr) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    72
                if (jval instanceof JSONObject) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    73
                    JSONObject resp = handleIndividualRequest((JSONObject) jval);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    74
                    postResponse.add(resp);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    75
                }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    76
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    77
            return postResponse;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    78
        } else {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    79
            postResponse.add(HttpResponse.getJsonObject(HttpURLConnection.HTTP_BAD_REQUEST, new JSONPrimitive(jsonStr), new JSONPrimitive("Invalid request")));
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    80
            return postResponse;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    81
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    82
    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    83
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    84
    private JSONObject handleIndividualRequest(JSONObject jobject) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    85
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    86
        try {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    87
            JSONObject map = jobject;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    88
            ObjectName name = getObjectName(map);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    89
            MBeanOps operation = null;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    90
            for (MBeanOps op : MBeanOps.values()) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    91
                if (map.containsKey(op.toString())) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    92
                    operation = op;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    93
                    break;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    94
                }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    95
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    96
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    97
            if (operation == null) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    98
                throw new JSONDataException("Invalid operation string");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
    99
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   100
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   101
            JSONElement val = map.get(operation.toString());
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   102
            if (!(val instanceof JSONPrimitive) || !(((JSONPrimitive) val).getValue() instanceof String)) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   103
                throw new JSONDataException("Invalid JSON String");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   104
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   105
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   106
            String attrOrOperation = (String) ((JSONPrimitive) val).getValue();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   107
            JSONElement result = new JSONPrimitive("success");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   108
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   109
            val = map.get(MBEAN_ARGUMENTS);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   110
            if (val != null) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   111
                if (!(val instanceof JSONArray)) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   112
                    throw new JSONDataException("Invalid JSON String");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   113
                }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   114
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   115
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   116
            JSONArray args = (JSONArray) val;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   117
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   118
            switch (operation) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   119
                case READ:
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   120
                    result = readAttribute(name, attrOrOperation, args);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   121
                    break;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   122
                case WRITE:
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   123
                    writeAttribute(name, attrOrOperation, args);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   124
                    break;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   125
                case EXEC:
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   126
                    result = execOperation(name, attrOrOperation, args);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   127
                    break;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   128
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   129
            return HttpResponse.getJsonObject(HttpURLConnection.HTTP_OK, jobject, result);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   130
        } catch (JSONDataException | MBeanException | JSONMappingException | ClassNotFoundException | IntrospectionException | InvalidAttributeValueException | IllegalArgumentException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   131
            return HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex), jobject, new JSONPrimitive(ex.toString()));
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   132
        } catch (AttributeNotFoundException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   133
            return HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex), jobject, new JSONPrimitive("Invalid Mbean attribute"));
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   134
        } catch (InstanceNotFoundException | ReflectionException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   135
            return HttpResponse.getJsonObject(HttpResponse.getHttpErrorCode(ex), jobject, new JSONPrimitive("Invalid Mbean"));
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   136
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   137
    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   138
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   139
    private JSONElement readAttribute(ObjectName name, String attribute, JSONArray args)
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   140
            throws InstanceNotFoundException, IntrospectionException, ReflectionException, ClassNotFoundException,
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   141
            MBeanException, AttributeNotFoundException, JSONMappingException {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   142
        MBeanInfo mInfos = mbeanServer.getMBeanInfo(name);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   143
        MBeanAttributeInfo attrInfo = Arrays.stream(mInfos.getAttributes()).filter(a -> a.getName().equals(attribute)).findFirst().orElse(null);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   144
        if (attrInfo != null && attrInfo.isReadable()) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   145
            JSONMapper mapper;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   146
            if (attrInfo instanceof OpenMBeanAttributeInfo) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   147
                OpenType<?> type = ((OpenMBeanAttributeInfo) attrInfo).getOpenType();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   148
                mapper = JSONMappingFactory.INSTANCE.getTypeMapper(type);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   149
            } else {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   150
                mapper = JSONMappingFactory.INSTANCE.getTypeMapper(Class.forName(attrInfo.getType()));
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   151
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   152
            Object attrVal = mbeanServer.getAttribute(name, attribute);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   153
            return mapper.toJsonValue(attrVal);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   154
        } else {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   155
            throw new AttributeNotFoundException();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   156
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   157
    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   158
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   159
    private void writeAttribute(ObjectName name, String attribute, JSONArray args)
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   160
            throws InstanceNotFoundException, IntrospectionException, ReflectionException, ClassNotFoundException,
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   161
            JSONDataException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   162
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   163
        if (args == null || args.isEmpty()) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   164
            throw new JSONDataException("Null arguments for set attribute");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   165
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   166
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   167
        MBeanInfo mInfos = mbeanServer.getMBeanInfo(name);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   168
        MBeanAttributeInfo attrInfo = Arrays.stream(mInfos.getAttributes()).filter(a -> a.getName().equals(attribute)).findFirst().orElse(null);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   169
        if (attrInfo != null && attrInfo.isWritable()) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   170
            JSONMapper mapper;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   171
            if (attrInfo instanceof OpenMBeanAttributeInfo) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   172
                OpenType<?> type = ((OpenMBeanAttributeInfo) attrInfo).getOpenType();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   173
                mapper = JSONMappingFactory.INSTANCE.getTypeMapper(type);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   174
            } else {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   175
                mapper = JSONMappingFactory.INSTANCE.getTypeMapper(Class.forName(attrInfo.getType()));
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   176
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   177
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   178
            JSONElement val = args.get(0);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   179
            Object argVal = mapper.toJavaObject(val);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   180
            Attribute attrObj = new Attribute(attribute, argVal);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   181
            mbeanServer.setAttribute(name, attrObj);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   182
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   183
        } else {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   184
            throw new AttributeNotFoundException();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   185
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   186
    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   187
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   188
    private Object[] mapArgsToSignature(JSONArray args, MBeanParameterInfo[] signature) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   189
        if (args.size() != signature.length) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   190
            throw new IllegalArgumentException("Invalid parameters : expected - " + signature.length + " parameters, got - " + args.size());
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   191
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   192
        if (signature.length == 0 && args.isEmpty()) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   193
            return new Object[0];
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   194
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   195
        int i = 0;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   196
        Object[] params = new Object[signature.length];
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   197
        for (MBeanParameterInfo info : signature) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   198
            if (info instanceof OpenMBeanParameterInfo) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   199
                OpenType<?> openType = ((OpenMBeanParameterInfo) info).getOpenType();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   200
                JSONMapper typeMapper = JSONMappingFactory.INSTANCE.getTypeMapper(openType);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   201
                try {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   202
                    params[i] = typeMapper.toJavaObject(args.get(i));
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   203
                } catch (JSONDataException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   204
                    throw new IllegalArgumentException("Invalid JSON String : " + args.get(i).toJsonString() + " for arguments");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   205
                }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   206
            } else {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   207
                Class<?> inputCls = primitiveToObject.get(info.getType());
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   208
                try {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   209
                    if (inputCls == null) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   210
                        inputCls = Class.forName(info.getType());
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   211
                    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   212
                } catch (ClassNotFoundException | ClassCastException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   213
                    throw new IllegalArgumentException("Invalid parameters : " + args.get(i).toJsonString() + " cannot be mapped to : " + info.getType());
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   214
                }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   215
                JSONMapper typeMapper = JSONMappingFactory.INSTANCE.getTypeMapper(inputCls);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   216
                if (typeMapper == null) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   217
                    throw new IllegalArgumentException("Invalid parameters : " + args.get(i).toJsonString() + " cannot be mapped to : " + info.getType());
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   218
                }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   219
                try {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   220
                    params[i] = typeMapper.toJavaObject(args.get(i));
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   221
                } catch (JSONDataException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   222
                    throw new IllegalArgumentException("Invalid JSON String : " + args.get(i).toJsonString() + " for arguments");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   223
                }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   224
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   225
            i++;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   226
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   227
        return params;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   228
    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   229
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   230
    private JSONElement execOperation(ObjectName name, String opstr, JSONArray args)
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   231
            throws MBeanException, JSONMappingException, IntrospectionException, ReflectionException {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   232
        if (args == null) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   233
            args = new JSONArray();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   234
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   235
        MBeanInfo mBeanInfo;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   236
        try {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   237
            mBeanInfo = mbeanServer.getMBeanInfo(name);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   238
        } catch (InstanceNotFoundException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   239
            throw new IllegalArgumentException("Invalid Operation String");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   240
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   241
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   242
        MBeanOperationInfo[] opinfos = Arrays.stream(mBeanInfo.getOperations()).
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   243
                filter(a -> a.getName().equals(opstr)).toArray(MBeanOperationInfo[]::new);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   244
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   245
        if (opinfos.length == 0) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   246
            throw new IllegalArgumentException("Invalid Operation String");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   247
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   248
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   249
        String[] signature = null;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   250
        Object[] params = null;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   251
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   252
        if (opinfos.length == 1) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   253
            MBeanParameterInfo[] sig = opinfos[0].getSignature();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   254
            params = mapArgsToSignature(args, sig);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   255
            signature = Arrays.asList(sig).stream().map(a -> a.getType()).toArray(a -> new String[a]);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   256
        } else if (opinfos.length > 1) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   257
            IllegalArgumentException exception = null;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   258
            for (MBeanOperationInfo opInfo : opinfos) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   259
                MBeanParameterInfo[] sig = opInfo.getSignature();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   260
                try {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   261
                    params = mapArgsToSignature(args, sig);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   262
                    signature = Arrays.asList(sig).stream().map(a -> a.getType()).toArray(a -> new String[a]);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   263
                    exception = null;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   264
                    break;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   265
                } catch (IllegalArgumentException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   266
                    exception = ex;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   267
                }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   268
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   269
            if (exception != null) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   270
                throw exception;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   271
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   272
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   273
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   274
        Object invoke;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   275
        try {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   276
            invoke = mbeanServer.invoke(name, opstr, params, signature);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   277
        } catch (InstanceNotFoundException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   278
            throw new IllegalArgumentException("Invalid Operation String");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   279
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   280
        if (invoke != null) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   281
            JSONMapper typeMapper = JSONMappingFactory.INSTANCE.getTypeMapper(invoke);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   282
            if (typeMapper != null) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   283
                return typeMapper.toJsonValue(invoke);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   284
            } else {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   285
                return new JSONPrimitive();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   286
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   287
        } else {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   288
            return new JSONPrimitive();
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   289
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   290
    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   291
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   292
    private ObjectName getObjectName(JSONObject map) throws JSONDataException, InstanceNotFoundException {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   293
        do {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   294
            if (map.get(MBEAN_NAME) == null || !(map.get(MBEAN_NAME) instanceof JSONPrimitive)) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   295
                break;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   296
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   297
            JSONPrimitive mbean_name = (JSONPrimitive) map.get(MBEAN_NAME);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   298
            if (!(mbean_name.getValue() instanceof String)) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   299
                break;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   300
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   301
            if (!allowedMbeans.contains((String) mbean_name.getValue())) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   302
                throw new InstanceNotFoundException("Invalid MBean");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   303
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   304
            try {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   305
                return ObjectName.getInstance((String) mbean_name.getValue());
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   306
            } catch (MalformedObjectNameException ex) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   307
            }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   308
        } while (false);
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   309
        throw new JSONDataException("Invalid JSON String");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   310
    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   311
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   312
    private static enum MBeanOps {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   313
        READ("read"),
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   314
        WRITE("write"),
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   315
        EXEC("exec");
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   316
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   317
        private final String text;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   318
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   319
        private MBeanOps(final String text) {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   320
            this.text = text;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   321
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   322
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   323
        @Override
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   324
        public String toString() {
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   325
            return text;
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   326
        }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   327
    }
0c5a02edfdef REST Adapter Initial commit
hb
parents:
diff changeset
   328
}