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.HashMap;
13 import java.util.HashSet;
14 import java.util.List;
16 import java.util.Map.Entry;
18 import java.util.regex.Pattern;
20 import javax.management.InstanceNotFoundException;
21 import javax.management.MalformedObjectNameException;
22 import javax.management.ObjectName;
24 import org.jolokia.client.J4pClient;
25 import org.jolokia.client.exception.J4pException;
26 import org.jolokia.client.exception.J4pRemoteException;
27 import org.jolokia.client.request.J4pExecRequest;
28 import org.jolokia.client.request.J4pListRequest;
29 import org.jolokia.client.request.J4pQueryParameter;
30 import org.jolokia.client.request.J4pReadRequest;
31 import org.jolokia.client.request.J4pRequest;
32 import org.jolokia.client.request.J4pResponse;
33 import org.json.simple.JSONArray;
34 import org.json.simple.JSONObject;
35 import org.opendaylight.controller.config.api.ConflictingVersionException;
36 import org.opendaylight.controller.config.api.ValidationException;
37 import org.opendaylight.controller.config.api.ValidationException.ExceptionMessageWithStackTrace;
38 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
39 import org.opendaylight.controller.config.util.AttributeEntry;
41 abstract class ListableJolokiaClient {
42 protected final J4pClient j4pClient;
43 protected final String url;
44 protected final ObjectName objectName;
46 public ListableJolokiaClient(String url, ObjectName objectName) {
48 throw new NullPointerException("Parameter 'url' is null");
50 if (!url.endsWith("/")) {
51 throw new IllegalArgumentException(
52 "Parameter 'url' must end with '/'");
56 this.j4pClient = new J4pClient(url);
57 this.objectName = objectName;
60 public ObjectName getObjectName() {
64 protected <R extends J4pResponse<T>, T extends J4pRequest> R execute(
67 Map<J4pQueryParameter, String> pProcessingOptions = new HashMap<J4pQueryParameter, String>();
69 .put(J4pQueryParameter.INCLUDE_STACKTRACE, "true");
70 pProcessingOptions.put(J4pQueryParameter.SERIALIZE_EXCEPTION,
72 return j4pClient.execute(pRequest, "POST", pProcessingOptions);
73 } catch (J4pRemoteException e) {
74 tryToConvertException(e.getRemoteStackTrace(), e.getErrorValue());
75 throw new RuntimeException(e.getRemoteStackTrace(), e);
76 } catch (J4pException e) {
77 throw new RuntimeException(e);
81 protected void tryToConvertException(String remoteStackTrace,
82 JSONObject errorValue) {
83 String conflictPrefix = ConflictingVersionException.class.getName()
85 if (remoteStackTrace.startsWith(conflictPrefix)) {
86 remoteStackTrace = remoteStackTrace.substring(conflictPrefix
88 Pattern p = Pattern.compile("\r?\n");
89 remoteStackTrace = Arrays.asList(p.split(remoteStackTrace))
91 throw new ConflictingVersionException(remoteStackTrace);
93 String validationExceptionPrefix = ValidationException.class.getName();
94 if (remoteStackTrace.startsWith(validationExceptionPrefix)) {
95 throw createValidationExceptionFromJSONObject(errorValue);
99 static ValidationException createValidationExceptionFromJSONObject(
100 JSONObject errorValue) {
101 String fValsKey = "failedValidations";
102 JSONObject failedVals = (JSONObject) errorValue.get(fValsKey);
105 !failedVals.isEmpty(),
106 fValsKey + " was not present in received JSON: "
107 + errorValue.toJSONString());
108 Map<String, Map<String, ExceptionMessageWithStackTrace>> failedValsMap = new HashMap<String, Map<String, ExceptionMessageWithStackTrace>>();
110 for (Object key : failedVals.keySet()) {
111 checkArgument(key instanceof String, "Unexpected key " + key
112 + ", expected instance of String");
113 Map<String, ExceptionMessageWithStackTrace> innerMap = new HashMap<String, ValidationException.ExceptionMessageWithStackTrace>();
114 for (Object innerKey : ((JSONObject) failedVals.get(key)).keySet()) {
115 checkArgument(innerKey instanceof String, "Unexpected key "
116 + innerKey + ", expected instance of String");
117 JSONObject exWithStackTraceVal = (JSONObject) (((JSONObject) failedVals
118 .get(key)).get(innerKey));
119 Object mess = exWithStackTraceVal.get("message");
120 Object stack = exWithStackTraceVal.get("trace");
121 checkArgument(mess != null && stack != null,
122 "\"Message\" and \"trace\" elements expected in received json: "
123 + errorValue.toJSONString());
124 innerMap.put(innerKey.toString(),
125 new ExceptionMessageWithStackTrace((String) mess,
128 failedValsMap.put((String) key, innerMap);
130 return new ValidationException(failedValsMap);
133 private static void checkArgument(boolean b, String string) {
135 throw new IllegalArgumentException(string);
138 public String getUrl() {
142 public Map<String, AttributeEntry> getAttributes(ObjectName on) {
143 J4pListRequest req = new J4pListRequest(on);
144 J4pResponse<J4pListRequest> response = execute(req);
145 JSONObject listJSONResponse = response.getValue();
146 JSONObject attributes = (JSONObject) listJSONResponse.get("attr");
147 Map<String, JSONObject> listMap = new HashMap<String, JSONObject>();
148 for (Object entryObject : attributes.entrySet()) {
149 Entry<String, Object> entry = (Entry<String, Object>) entryObject;
150 JSONObject entryVal = (JSONObject) entry.getValue();
153 listMap.put(entry.getKey(), entryVal);
155 J4pReadRequest j4pReadRequest = new J4pReadRequest(on, listMap.keySet()
156 .toArray(new String[0]));
157 J4pResponse<J4pReadRequest> readResponse = execute(j4pReadRequest);
158 Object readResponseValue = readResponse.getValue();
159 // readResponseValue can be String if there is just one attribute or
161 Map<String, Object> attribsToValues = new HashMap<String, Object>();
162 if (readResponseValue instanceof JSONObject) {
163 JSONObject readJSONResponse = (JSONObject) readResponseValue;
164 for (Object entryObject : readJSONResponse.entrySet()) {
165 Entry<String, Object> entry = (Entry<String, Object>) entryObject;
166 String key = entry.getKey();
167 Object value = entry.getValue();
168 attribsToValues.put(key, value);
172 Map<String, AttributeEntry> resultMap = new HashMap<String, AttributeEntry>();
173 for (Entry<String, JSONObject> entry : listMap.entrySet()) {
174 String key = entry.getKey();
175 Object value = attribsToValues.size() > 0 ? attribsToValues
176 .get(key) : readResponseValue;
177 JSONObject listJSON = entry.getValue();
178 String description = (String) listJSON.get("desc");
179 String type = (String) listJSON.get("type");
180 boolean rw = (Boolean) listJSON.get("rw");
181 AttributeEntry attributeEntry = new AttributeEntry(key,
182 description, value, type, rw);
183 resultMap.put(key, attributeEntry);
189 public String getConfigBeanDescripton(ObjectName on) {
190 J4pListRequest req = new J4pListRequest(on);
191 J4pResponse<J4pListRequest> response = execute(req);
192 JSONObject jsonDesc = response.getValue();
193 Object description = jsonDesc.get("desc");
194 return description == null ? null : description.toString();
197 protected List<ObjectName> jsonArrayToObjectNames(JSONArray jsonArray) {
198 List<ObjectName> result = new ArrayList<>(jsonArray.size());
199 for (Object entry : jsonArray) {
200 JSONObject jsonObject = (JSONObject) entry;
201 String objectNameString = (String) jsonObject.get("objectName");
203 result.add(new ObjectName(objectNameString));
204 } catch (MalformedObjectNameException e) {
205 throw new IllegalStateException("Cannot convert "
206 + objectNameString + " to ObjectName", e);
212 protected ObjectName extractObjectName(J4pResponse<J4pExecRequest> resp) {
213 JSONObject jsonResponse = resp.getValue();
214 return extractObjectName(jsonResponse);
217 protected ObjectName extractObjectName(JSONObject jsonResponse) {
218 String result = jsonResponse.get("objectName").toString();
219 return ObjectNameUtil.createON(result);
222 protected Set<ObjectName> lookupSomething(String signature,
223 Object[] parameters) {
224 J4pExecRequest req = new J4pExecRequest(objectName, signature,
226 JSONArray jsonArray = execute(req).getValue();
227 return new HashSet<>(jsonArrayToObjectNames(jsonArray));
230 public Set<ObjectName> lookupConfigBeans() {
231 return lookupSomething("lookupConfigBeans()", new Object[0]);
234 public Set<ObjectName> lookupConfigBeans(String ifcName) {
235 return lookupSomething("lookupConfigBeans(java.lang.String)",
236 new Object[] { ifcName });
239 public Set<ObjectName> lookupConfigBeans(String ifcName, String instanceName) {
240 return lookupSomething(
241 "lookupConfigBeans(java.lang.String,java.lang.String)",
242 new Object[] { ifcName, instanceName });
245 public ObjectName lookupConfigBean(String ifcName, String instanceName)
246 throws InstanceNotFoundException {
247 J4pExecRequest req = new J4pExecRequest(objectName,
248 "lookupConfigBean(java.lang.String,java.lang.String)",
249 new Object[] { ifcName, instanceName });
251 J4pResponse<J4pExecRequest> resp = execute(req);
252 return extractObjectName(resp);
253 } catch (RuntimeException e) {
254 if (e.getMessage() != null
255 && e.getMessage().startsWith(
256 InstanceNotFoundException.class.getName()))
257 throw new InstanceNotFoundException();
262 public Set<String> getAvailableModuleNames() {
263 J4pReadRequest req = new J4pReadRequest(objectName,
264 "AvailableModuleNames");
265 List<String> value = execute(req).getValue();
266 return new HashSet<>(value);