2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.config.util.jolokia;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
17 import java.util.Map.Entry;
19 import java.util.regex.Pattern;
21 import javax.management.InstanceNotFoundException;
22 import javax.management.MalformedObjectNameException;
23 import javax.management.ObjectName;
25 import org.jolokia.client.J4pClient;
26 import org.jolokia.client.exception.J4pException;
27 import org.jolokia.client.exception.J4pRemoteException;
28 import org.jolokia.client.request.J4pExecRequest;
29 import org.jolokia.client.request.J4pListRequest;
30 import org.jolokia.client.request.J4pQueryParameter;
31 import org.jolokia.client.request.J4pReadRequest;
32 import org.jolokia.client.request.J4pRequest;
33 import org.jolokia.client.request.J4pResponse;
34 import org.json.simple.JSONArray;
35 import org.json.simple.JSONObject;
36 import org.opendaylight.controller.config.api.ConflictingVersionException;
37 import org.opendaylight.controller.config.api.ValidationException;
38 import org.opendaylight.controller.config.api.ValidationException.ExceptionMessageWithStackTrace;
39 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
40 import org.opendaylight.controller.config.util.AttributeEntry;
43 abstract class ListableJolokiaClient {
44 protected final J4pClient j4pClient;
45 protected final String url;
46 protected final ObjectName objectName;
48 public ListableJolokiaClient(String url, ObjectName objectName) {
50 throw new NullPointerException("Parameter 'url' is null");
52 if (!url.endsWith("/")) {
53 throw new IllegalArgumentException(
54 "Parameter 'url' must end with '/'");
58 this.j4pClient = new J4pClient(url);
59 this.objectName = objectName;
62 public ObjectName getObjectName() {
66 protected <R extends J4pResponse<T>, T extends J4pRequest> R execute(
69 Map<J4pQueryParameter, String> pProcessingOptions = new HashMap<J4pQueryParameter, String>();
71 .put(J4pQueryParameter.INCLUDE_STACKTRACE, "true");
72 pProcessingOptions.put(J4pQueryParameter.SERIALIZE_EXCEPTION,
74 return j4pClient.execute(pRequest, "POST", pProcessingOptions);
75 } catch (J4pRemoteException e) {
76 tryToConvertException(e.getRemoteStackTrace(), e.getErrorValue());
77 throw new RuntimeException(e.getRemoteStackTrace(), e);
78 } catch (J4pException e) {
79 throw new RuntimeException(e);
83 protected void tryToConvertException(String remoteStackTrace,
84 JSONObject errorValue) {
85 String conflictPrefix = ConflictingVersionException.class.getName()
87 if (remoteStackTrace.startsWith(conflictPrefix)) {
88 remoteStackTrace = remoteStackTrace.substring(conflictPrefix
90 Pattern p = Pattern.compile("\r?\n");
91 remoteStackTrace = Arrays.asList(p.split(remoteStackTrace))
93 throw new ConflictingVersionException(remoteStackTrace);
95 String validationExceptionPrefix = ValidationException.class.getName();
96 if (remoteStackTrace.startsWith(validationExceptionPrefix)) {
97 throw createValidationExceptionFromJSONObject(errorValue);
101 static ValidationException createValidationExceptionFromJSONObject(
102 JSONObject errorValue) {
103 String fValsKey = "failedValidations";
104 JSONObject failedVals = (JSONObject) errorValue.get(fValsKey);
107 !failedVals.isEmpty(),
108 fValsKey + " was not present in received JSON: "
109 + errorValue.toJSONString());
110 Map<String, Map<String, ExceptionMessageWithStackTrace>> failedValsMap = new HashMap<String, Map<String, ExceptionMessageWithStackTrace>>();
112 for (Object key : failedVals.keySet()) {
113 checkArgument(key instanceof String, "Unexpected key " + key
114 + ", expected instance of String");
115 Map<String, ExceptionMessageWithStackTrace> innerMap = new HashMap<String, ValidationException.ExceptionMessageWithStackTrace>();
116 for (Object innerKey : ((JSONObject) failedVals.get(key)).keySet()) {
117 checkArgument(innerKey instanceof String, "Unexpected key "
118 + innerKey + ", expected instance of String");
119 JSONObject exWithStackTraceVal = (JSONObject) (((JSONObject) failedVals
120 .get(key)).get(innerKey));
121 Object mess = exWithStackTraceVal.get("message");
122 Object stack = exWithStackTraceVal.get("trace");
123 checkArgument(mess != null && stack != null,
124 "\"Message\" and \"trace\" elements expected in received json: "
125 + errorValue.toJSONString());
126 innerMap.put(innerKey.toString(),
127 new ExceptionMessageWithStackTrace((String) mess,
130 failedValsMap.put((String) key, innerMap);
132 return new ValidationException(failedValsMap);
135 private static void checkArgument(boolean b, String string) {
137 throw new IllegalArgumentException(string);
140 public String getUrl() {
144 public Map<String, AttributeEntry> getAttributes(ObjectName on) {
145 J4pListRequest req = new J4pListRequest(on);
146 J4pResponse<J4pListRequest> response = execute(req);
147 JSONObject listJSONResponse = response.getValue();
148 JSONObject attributes = (JSONObject) listJSONResponse.get("attr");
150 // Empty attributes list
151 if(attributes == null)
152 return Collections.emptyMap();
154 Map<String, JSONObject> listMap = new HashMap<>();
156 for (Object entryObject : attributes.entrySet()) {
157 Entry<String, Object> entry = (Entry<String, Object>) entryObject;
158 JSONObject entryVal = (JSONObject) entry.getValue();
161 listMap.put(entry.getKey(), entryVal);
163 J4pReadRequest j4pReadRequest = new J4pReadRequest(on, listMap.keySet()
164 .toArray(new String[0]));
165 J4pResponse<J4pReadRequest> readResponse = execute(j4pReadRequest);
166 Object readResponseValue = readResponse.getValue();
167 // readResponseValue can be String if there is just one attribute or
169 Map<String, Object> attribsToValues = new HashMap<String, Object>();
170 if (readResponseValue instanceof JSONObject) {
171 JSONObject readJSONResponse = (JSONObject) readResponseValue;
172 for (Object entryObject : readJSONResponse.entrySet()) {
173 Entry<String, Object> entry = (Entry<String, Object>) entryObject;
174 String key = entry.getKey();
175 Object value = entry.getValue();
176 attribsToValues.put(key, value);
180 Map<String, AttributeEntry> resultMap = new HashMap<String, AttributeEntry>();
181 for (Entry<String, JSONObject> entry : listMap.entrySet()) {
182 String key = entry.getKey();
183 Object value = attribsToValues.size() > 0 ? attribsToValues
184 .get(key) : readResponseValue;
185 JSONObject listJSON = entry.getValue();
186 String description = (String) listJSON.get("desc");
187 String type = (String) listJSON.get("type");
188 boolean rw = (Boolean) listJSON.get("rw");
189 AttributeEntry attributeEntry = new AttributeEntry(key,
190 description, value, type, rw);
191 resultMap.put(key, attributeEntry);
197 public String getConfigBeanDescripton(ObjectName on) {
198 J4pListRequest req = new J4pListRequest(on);
199 J4pResponse<J4pListRequest> response = execute(req);
200 JSONObject jsonDesc = response.getValue();
201 Object description = jsonDesc.get("desc");
202 return description == null ? null : description.toString();
205 protected List<ObjectName> jsonArrayToObjectNames(JSONArray jsonArray) {
206 List<ObjectName> result = new ArrayList<>(jsonArray.size());
207 for (Object entry : jsonArray) {
208 JSONObject jsonObject = (JSONObject) entry;
209 String objectNameString = (String) jsonObject.get("objectName");
211 result.add(new ObjectName(objectNameString));
212 } catch (MalformedObjectNameException e) {
213 throw new IllegalStateException("Cannot convert "
214 + objectNameString + " to ObjectName", e);
220 protected ObjectName extractObjectName(J4pResponse<J4pExecRequest> resp) {
221 JSONObject jsonResponse = resp.getValue();
222 return extractObjectName(jsonResponse);
225 protected ObjectName extractObjectName(JSONObject jsonResponse) {
226 String result = jsonResponse.get("objectName").toString();
227 return ObjectNameUtil.createON(result);
230 protected Set<ObjectName> lookupSomething(String signature,
231 Object[] parameters) {
232 J4pExecRequest req = new J4pExecRequest(objectName, signature,
234 JSONArray jsonArray = execute(req).getValue();
235 return new HashSet<>(jsonArrayToObjectNames(jsonArray));
238 public Set<ObjectName> lookupConfigBeans() {
239 return lookupSomething("lookupConfigBeans()", new Object[0]);
242 public Set<ObjectName> lookupConfigBeans(String ifcName) {
243 return lookupSomething("lookupConfigBeans(java.lang.String)",
244 new Object[] { ifcName });
247 public Set<ObjectName> lookupConfigBeans(String ifcName, String instanceName) {
248 return lookupSomething(
249 "lookupConfigBeans(java.lang.String,java.lang.String)",
250 new Object[] { ifcName, instanceName });
253 public ObjectName lookupConfigBean(String ifcName, String instanceName)
254 throws InstanceNotFoundException {
255 J4pExecRequest req = new J4pExecRequest(objectName,
256 "lookupConfigBean(java.lang.String,java.lang.String)",
257 new Object[] { ifcName, instanceName });
259 J4pResponse<J4pExecRequest> resp = execute(req);
260 return extractObjectName(resp);
261 } catch (RuntimeException e) {
262 if (e.getMessage() != null
263 && e.getMessage().startsWith(
264 InstanceNotFoundException.class.getName()))
265 throw new InstanceNotFoundException();
270 public Set<String> getAvailableModuleNames() {
271 J4pReadRequest req = new J4pReadRequest(objectName,
272 "AvailableModuleNames");
273 List<String> value = execute(req).getValue();
274 return new HashSet<>(value);