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;
42 abstract class ListableJolokiaClient {
43 protected final J4pClient j4pClient;
44 protected final String url;
45 protected final ObjectName objectName;
47 public ListableJolokiaClient(String url, ObjectName objectName) {
49 throw new NullPointerException("Parameter 'url' is null");
51 if (!url.endsWith("/")) {
52 throw new IllegalArgumentException(
53 "Parameter 'url' must end with '/'");
57 this.j4pClient = new J4pClient(url);
58 this.objectName = objectName;
61 public ObjectName getObjectName() {
65 protected <R extends J4pResponse<T>, T extends J4pRequest> R execute(
68 Map<J4pQueryParameter, String> pProcessingOptions = new HashMap<J4pQueryParameter, String>();
70 .put(J4pQueryParameter.INCLUDE_STACKTRACE, "true");
71 pProcessingOptions.put(J4pQueryParameter.SERIALIZE_EXCEPTION,
73 return j4pClient.execute(pRequest, "POST", pProcessingOptions);
74 } catch (J4pRemoteException e) {
75 tryToConvertException(e.getRemoteStackTrace(), e.getErrorValue());
76 throw new RuntimeException(e.getRemoteStackTrace(), e);
77 } catch (J4pException e) {
78 throw new RuntimeException(e);
82 protected void tryToConvertException(String remoteStackTrace,
83 JSONObject errorValue) {
84 String conflictPrefix = ConflictingVersionException.class.getName()
86 if (remoteStackTrace.startsWith(conflictPrefix)) {
87 remoteStackTrace = remoteStackTrace.substring(conflictPrefix
89 Pattern p = Pattern.compile("\r?\n");
90 remoteStackTrace = Arrays.asList(p.split(remoteStackTrace))
92 throw new ConflictingVersionException(remoteStackTrace);
94 String validationExceptionPrefix = ValidationException.class.getName();
95 if (remoteStackTrace.startsWith(validationExceptionPrefix)) {
96 throw createValidationExceptionFromJSONObject(errorValue);
100 static ValidationException createValidationExceptionFromJSONObject(
101 JSONObject errorValue) {
102 String fValsKey = "failedValidations";
103 JSONObject failedVals = (JSONObject) errorValue.get(fValsKey);
106 !failedVals.isEmpty(),
107 fValsKey + " was not present in received JSON: "
108 + errorValue.toJSONString());
109 Map<String, Map<String, ExceptionMessageWithStackTrace>> failedValsMap = new HashMap<String, Map<String, ExceptionMessageWithStackTrace>>();
111 for (Object key : failedVals.keySet()) {
112 checkArgument(key instanceof String, "Unexpected key " + key
113 + ", expected instance of String");
114 Map<String, ExceptionMessageWithStackTrace> innerMap = new HashMap<String, ValidationException.ExceptionMessageWithStackTrace>();
115 for (Object innerKey : ((JSONObject) failedVals.get(key)).keySet()) {
116 checkArgument(innerKey instanceof String, "Unexpected key "
117 + innerKey + ", expected instance of String");
118 JSONObject exWithStackTraceVal = (JSONObject) (((JSONObject) failedVals
119 .get(key)).get(innerKey));
120 Object mess = exWithStackTraceVal.get("message");
121 Object stack = exWithStackTraceVal.get("trace");
122 checkArgument(mess != null && stack != null,
123 "\"Message\" and \"trace\" elements expected in received json: "
124 + errorValue.toJSONString());
125 innerMap.put(innerKey.toString(),
126 new ExceptionMessageWithStackTrace((String) mess,
129 failedValsMap.put((String) key, innerMap);
131 return new ValidationException(failedValsMap);
134 private static void checkArgument(boolean b, String string) {
136 throw new IllegalArgumentException(string);
139 public String getUrl() {
143 public Map<String, AttributeEntry> getAttributes(ObjectName on) {
144 J4pListRequest req = new J4pListRequest(on);
145 J4pResponse<J4pListRequest> response = execute(req);
146 JSONObject listJSONResponse = response.getValue();
147 JSONObject attributes = (JSONObject) listJSONResponse.get("attr");
149 // Empty attributes list
150 if(attributes == null)
151 return Collections.emptyMap();
153 Map<String, JSONObject> listMap = new HashMap<>();
155 for (Object entryObject : attributes.entrySet()) {
156 Entry<String, Object> entry = (Entry<String, Object>) entryObject;
157 JSONObject entryVal = (JSONObject) entry.getValue();
160 listMap.put(entry.getKey(), entryVal);
162 J4pReadRequest j4pReadRequest = new J4pReadRequest(on, listMap.keySet()
163 .toArray(new String[0]));
164 J4pResponse<J4pReadRequest> readResponse = execute(j4pReadRequest);
165 Object readResponseValue = readResponse.getValue();
166 // readResponseValue can be String if there is just one attribute or
168 Map<String, Object> attribsToValues = new HashMap<String, Object>();
169 if (readResponseValue instanceof JSONObject) {
170 JSONObject readJSONResponse = (JSONObject) readResponseValue;
171 for (Object entryObject : readJSONResponse.entrySet()) {
172 Entry<String, Object> entry = (Entry<String, Object>) entryObject;
173 String key = entry.getKey();
174 Object value = entry.getValue();
175 attribsToValues.put(key, value);
179 Map<String, AttributeEntry> resultMap = new HashMap<String, AttributeEntry>();
180 for (Entry<String, JSONObject> entry : listMap.entrySet()) {
181 String key = entry.getKey();
182 Object value = attribsToValues.size() > 0 ? attribsToValues
183 .get(key) : readResponseValue;
184 JSONObject listJSON = entry.getValue();
185 String description = (String) listJSON.get("desc");
186 String type = (String) listJSON.get("type");
187 boolean rw = (Boolean) listJSON.get("rw");
188 AttributeEntry attributeEntry = new AttributeEntry(key,
189 description, value, type, rw);
190 resultMap.put(key, attributeEntry);
196 public String getConfigBeanDescripton(ObjectName on) {
197 J4pListRequest req = new J4pListRequest(on);
198 J4pResponse<J4pListRequest> response = execute(req);
199 JSONObject jsonDesc = response.getValue();
200 Object description = jsonDesc.get("desc");
201 return description == null ? null : description.toString();
204 protected List<ObjectName> jsonArrayToObjectNames(JSONArray jsonArray) {
205 List<ObjectName> result = new ArrayList<>(jsonArray.size());
206 for (Object entry : jsonArray) {
207 JSONObject jsonObject = (JSONObject) entry;
208 String objectNameString = (String) jsonObject.get("objectName");
210 result.add(new ObjectName(objectNameString));
211 } catch (MalformedObjectNameException e) {
212 throw new IllegalStateException("Cannot convert "
213 + objectNameString + " to ObjectName", e);
219 protected ObjectName extractObjectName(J4pResponse<J4pExecRequest> resp) {
220 JSONObject jsonResponse = resp.getValue();
221 return extractObjectName(jsonResponse);
224 protected ObjectName extractObjectName(JSONObject jsonResponse) {
225 String result = jsonResponse.get("objectName").toString();
226 return ObjectNameUtil.createON(result);
229 protected Set<ObjectName> lookupSomething(String signature,
230 Object[] parameters) {
231 J4pExecRequest req = new J4pExecRequest(objectName, signature,
233 JSONArray jsonArray = execute(req).getValue();
234 return new HashSet<>(jsonArrayToObjectNames(jsonArray));
237 public Set<ObjectName> lookupConfigBeans() {
238 return lookupSomething("lookupConfigBeans()", new Object[0]);
241 public Set<ObjectName> lookupConfigBeans(String ifcName) {
242 return lookupSomething("lookupConfigBeans(java.lang.String)",
243 new Object[] { ifcName });
246 public Set<ObjectName> lookupConfigBeans(String ifcName, String instanceName) {
247 return lookupSomething(
248 "lookupConfigBeans(java.lang.String,java.lang.String)",
249 new Object[] { ifcName, instanceName });
252 public ObjectName lookupConfigBean(String ifcName, String instanceName)
253 throws InstanceNotFoundException {
254 J4pExecRequest req = new J4pExecRequest(objectName,
255 "lookupConfigBean(java.lang.String,java.lang.String)",
256 new Object[] { ifcName, instanceName });
258 J4pResponse<J4pExecRequest> resp = execute(req);
259 return extractObjectName(resp);
260 } catch (RuntimeException e) {
261 if (e.getMessage() != null
262 && e.getMessage().startsWith(
263 InstanceNotFoundException.class.getName()))
264 throw new InstanceNotFoundException();
269 public Set<String> getAvailableModuleNames() {
270 J4pReadRequest req = new J4pReadRequest(objectName,
271 "AvailableModuleNames");
272 List<String> value = execute(req).getValue();
273 return new HashSet<>(value);