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.api.jmx;
10 import org.opendaylight.controller.config.api.ModuleIdentifier;
11 import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConstants;
13 import javax.annotation.concurrent.ThreadSafe;
14 import javax.management.ObjectName;
15 import java.util.Arrays;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Hashtable;
20 import java.util.Map.Entry;
24 * Provides ObjectName creation. Each created ObjectName consists of domain that
25 * is defined as {@link #ON_DOMAIN} and at least one key-value pair. The only
26 * mandatory property is {@link #TYPE_KEY}. All transaction related mbeans have
27 * {@link #TRANSACTION_NAME_KEY} property set.
30 public class ObjectNameUtil {
32 public static final String ON_DOMAIN = ConfigRegistryConstants.ON_DOMAIN;
33 public static final String MODULE_FACTORY_NAME_KEY = "moduleFactoryName";
34 public static final String SERVICE_QNAME_KEY = "serviceQName";
35 public static final String INSTANCE_NAME_KEY = "instanceName";
36 public static final String TYPE_KEY = ConfigRegistryConstants.TYPE_KEY;
37 public static final String TYPE_CONFIG_REGISTRY = ConfigRegistryConstants.TYPE_CONFIG_REGISTRY;
38 public static final String TYPE_CONFIG_TRANSACTION = "ConfigTransaction";
39 public static final String TYPE_MODULE = "Module";
40 public static final String TYPE_SERVICE_REFERENCE = "ServiceReference";
41 public static final String TYPE_RUNTIME_BEAN = "RuntimeBean";
42 public static final String TRANSACTION_NAME_KEY = "TransactionName";
43 public static final String REF_NAME_KEY = "RefName";
44 private static final String REPLACED_QUOTATION_MARK = "\\?";
46 public static ObjectName createON(String on) {
48 return new ObjectName(on);
49 } catch (Exception e) {
50 throw new RuntimeException(e);
54 public static ObjectName createONWithDomainAndType(String type) {
55 return ConfigRegistryConstants.createONWithDomainAndType(type);
58 public static ObjectName createON(String name, String key, String value) {
59 return ConfigRegistryConstants.createON(name, key, value);
62 public static ObjectName createON(String domain, Map<String, String> attribs) {
63 Hashtable<String, String> table = new Hashtable<>(attribs);
65 return new ObjectName(domain, table);
66 } catch (Exception e) {
67 throw new RuntimeException(e);
72 public static ObjectName createTransactionControllerON(
73 String transactionName) {
74 Map<String, String> onParams = new HashMap<>();
75 onParams.put(TRANSACTION_NAME_KEY, transactionName);
76 onParams.put(TYPE_KEY, TYPE_CONFIG_TRANSACTION);
77 return createON(ON_DOMAIN, onParams);
80 public static ObjectName createTransactionModuleON(String transactionName,
81 ModuleIdentifier moduleIdentifier) {
82 return createTransactionModuleON(transactionName,
83 moduleIdentifier.getFactoryName(),
84 moduleIdentifier.getInstanceName());
87 public static ObjectName createTransactionModuleON(String transactionName,
88 String moduleName, String instanceName) {
89 Map<String, String> onParams = createModuleMap(moduleName, instanceName);
90 onParams.put(TRANSACTION_NAME_KEY, transactionName);
91 return createON(ON_DOMAIN, onParams);
94 public static ObjectName createTransactionModuleON(String transactionName,
96 return createTransactionModuleON(transactionName, getFactoryName(on),
100 public static ObjectName createReadOnlyModuleON(
101 ModuleIdentifier moduleIdentifier) {
102 return createReadOnlyModuleON(moduleIdentifier.getFactoryName(),
103 moduleIdentifier.getInstanceName());
106 public static ObjectName createReadOnlyServiceON(String serviceQName, String refName) {
107 Map<String, String> onParams = createServiceMap(serviceQName, refName);
108 return createON(ON_DOMAIN, onParams);
111 public static ObjectName createTransactionServiceON(String transactionName, String serviceQName, String refName) {
112 Map<String, String> onParams = createServiceON(transactionName, serviceQName, refName);
113 return createON(ON_DOMAIN, onParams);
116 public static String getServiceQName(ObjectName objectName) {
117 checkType(objectName, TYPE_SERVICE_REFERENCE);
118 String quoted = objectName.getKeyProperty(SERVICE_QNAME_KEY);
119 String result = unquoteAndUnescape(objectName, quoted);
123 // ObjectName supports quotation and ignores tokens like =, but fails to ignore ? sign.
124 // It must be replaced with another character that hopefully does not collide
125 // with actual value.
126 private static String unquoteAndUnescape(ObjectName objectName, String quoted) {
127 if (quoted == null) {
128 throw new IllegalArgumentException("Cannot find " + SERVICE_QNAME_KEY + " in " + objectName);
130 if (quoted.startsWith("\"") == false || quoted.endsWith("\"") == false) {
131 throw new IllegalArgumentException("Quotes not found in " + objectName);
133 String substring = quoted.substring(1);
134 substring = substring.substring(0, substring.length() - 1);
135 substring = substring.replace(REPLACED_QUOTATION_MARK, "?");
139 private static String quoteAndEscapeValue(String serviceQName) {
140 return "\"" + serviceQName.replace("?", REPLACED_QUOTATION_MARK) + "\"";
143 public static String getReferenceName(ObjectName objectName) {
144 checkType(objectName, TYPE_SERVICE_REFERENCE);
145 return objectName.getKeyProperty(REF_NAME_KEY);
148 private static Map<String, String> createServiceON(String transactionName, String serviceQName,
150 Map<String, String> result = new HashMap<>(createServiceMap(serviceQName, refName));
151 result.put(TRANSACTION_NAME_KEY, transactionName);
155 private static Map<String, String> createServiceMap(String serviceQName,
157 Map<String, String> onParams = new HashMap<>();
158 onParams.put(TYPE_KEY, TYPE_SERVICE_REFERENCE);
159 onParams.put(SERVICE_QNAME_KEY, quoteAndEscapeValue(serviceQName));
160 onParams.put(REF_NAME_KEY, refName);
165 public static ObjectName createReadOnlyModuleON(String moduleName,
166 String instanceName) {
167 Map<String, String> onParams = createModuleMap(moduleName, instanceName);
168 return createON(ON_DOMAIN, onParams);
171 private static Map<String, String> createModuleMap(String moduleName,
172 String instanceName) {
173 Map<String, String> onParams = new HashMap<>();
174 onParams.put(TYPE_KEY, TYPE_MODULE);
175 onParams.put(MODULE_FACTORY_NAME_KEY, moduleName);
176 onParams.put(INSTANCE_NAME_KEY, instanceName);
180 public static String getFactoryName(ObjectName objectName) {
181 checkTypeOneOf(objectName, TYPE_MODULE, TYPE_RUNTIME_BEAN);
182 return objectName.getKeyProperty(MODULE_FACTORY_NAME_KEY);
185 public static String getInstanceName(ObjectName objectName) {
186 checkTypeOneOf(objectName, TYPE_MODULE, TYPE_RUNTIME_BEAN);
187 return objectName.getKeyProperty(INSTANCE_NAME_KEY);
190 public static String getTransactionName(ObjectName objectName) {
191 return objectName.getKeyProperty(TRANSACTION_NAME_KEY);
195 * Sanitize on: keep only mandatory attributes of module + metadata.
197 public static ObjectName withoutTransactionName(ObjectName inputON) {
198 checkTypeOneOf(inputON, TYPE_MODULE, TYPE_SERVICE_REFERENCE);
199 if (getTransactionName(inputON) == null) {
200 throw new IllegalArgumentException(
201 "Expected ObjectName with transaction:" + inputON);
203 if (ON_DOMAIN.equals(inputON.getDomain()) == false) {
204 throw new IllegalArgumentException("Expected different domain: "
207 Map<String, String> outputProperties;
208 if (inputON.getKeyProperty(TYPE_KEY).equals(TYPE_MODULE)) {
209 String moduleName = getFactoryName(inputON);
210 String instanceName = getInstanceName(inputON);
211 outputProperties = new HashMap<>(createModuleMap(moduleName, instanceName));
213 String serviceQName = getServiceQName(inputON);
214 String refName = getReferenceName(inputON);
215 outputProperties = new HashMap<>(createServiceMap(serviceQName, refName));
217 Map<String, String> allProperties = getAdditionalProperties(inputON);
218 for (Entry<String, String> entry : allProperties.entrySet()) {
219 if (entry.getKey().startsWith("X-")) {
220 outputProperties.put(entry.getKey(), entry.getValue());
223 return createON(ON_DOMAIN, outputProperties);
226 public static ObjectName withTransactionName(ObjectName inputON, String transactionName) {
227 Map<String, String> additionalProperties = getAdditionalProperties(inputON);
228 additionalProperties.put(TRANSACTION_NAME_KEY, transactionName);
229 return createON(inputON.getDomain(), additionalProperties);
233 private static void assertDoesNotContain(
234 Map<String, String> additionalProperties, String key) {
235 if (additionalProperties.containsKey(key)) {
236 throw new IllegalArgumentException(
237 "Map 'additionalProperties' cannot overwrite attribute "
242 public static ObjectName createRuntimeBeanName(String moduleName,
243 String instanceName, Map<String, String> additionalProperties) {
244 // check that there is no overwriting of default attributes
245 assertDoesNotContain(additionalProperties, MODULE_FACTORY_NAME_KEY);
246 assertDoesNotContain(additionalProperties, INSTANCE_NAME_KEY);
247 assertDoesNotContain(additionalProperties, TYPE_KEY);
248 assertDoesNotContain(additionalProperties, TRANSACTION_NAME_KEY);
249 Map<String, String> map = new HashMap<>(additionalProperties);
250 map.put(MODULE_FACTORY_NAME_KEY, moduleName);
251 map.put(INSTANCE_NAME_KEY, instanceName);
252 map.put(TYPE_KEY, TYPE_RUNTIME_BEAN);
253 return createON(ON_DOMAIN, map);
256 private static Set<String> blacklist = new HashSet<>(Arrays.asList(
257 MODULE_FACTORY_NAME_KEY, INSTANCE_NAME_KEY, TYPE_KEY));
259 public static Map<String, String> getAdditionalPropertiesOfRuntimeBeanName(
261 checkType(on, TYPE_RUNTIME_BEAN);
262 Map<String, String> allProperties = getAdditionalProperties(on);
263 Map<String, String> result = new HashMap<>();
264 for (Entry<String, String> entry : allProperties.entrySet()) {
265 if (blacklist.contains(entry.getKey()) == false) {
266 result.put(entry.getKey(), entry.getValue());
272 public static Map<String, String> getAdditionalProperties(ObjectName on) {
273 Hashtable<String, String> keyPropertyList = on.getKeyPropertyList();
274 Map<String, String> result = new HashMap<>();
275 for (Entry<String, String> entry : keyPropertyList.entrySet()) {
276 result.put(entry.getKey(), entry.getValue());
281 public static void checkDomain(ObjectName objectName) {
282 if (!ON_DOMAIN.equals(objectName.getDomain())) {
283 throw new IllegalArgumentException("Wrong domain " + objectName);
288 public static void checkType(ObjectName objectName, String type) {
289 if (!type.equals(objectName.getKeyProperty(TYPE_KEY))) {
290 throw new IllegalArgumentException("Wrong type, expected '" + type
291 + "', got " + objectName);
295 public static void checkTypeOneOf(ObjectName objectName, String ... types) {
296 for(String type: types) {
297 if (type.equals(objectName.getKeyProperty(TYPE_KEY))) {
301 throw new IllegalArgumentException("Wrong type, expected one of " + Arrays.asList(types)
302 + ", got " + objectName);
305 public static ObjectName createModulePattern(String moduleName,
306 String instanceName) {
307 if (moduleName == null)
309 if (instanceName == null)
311 // do not return object names containing transaction name
312 ObjectName namePattern = ObjectNameUtil
313 .createON(ObjectNameUtil.ON_DOMAIN + ":"
314 + ObjectNameUtil.TYPE_KEY + "="
315 + ObjectNameUtil.TYPE_MODULE + ","
316 + ObjectNameUtil.MODULE_FACTORY_NAME_KEY + "="
317 + moduleName + "," + ""
318 + ObjectNameUtil.INSTANCE_NAME_KEY + "=" + instanceName);
322 public static ObjectName createModulePattern(String ifcName,
323 String instanceName, String transactionName) {
324 return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN
325 + ":type=Module," + ObjectNameUtil.MODULE_FACTORY_NAME_KEY
326 + "=" + ifcName + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "="
327 + instanceName + "," + ObjectNameUtil.TRANSACTION_NAME_KEY
328 + "=" + transactionName);
331 public static ObjectName createRuntimeBeanPattern(String moduleName,
332 String instanceName) {
333 return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":"
334 + ObjectNameUtil.TYPE_KEY + "="
335 + ObjectNameUtil.TYPE_RUNTIME_BEAN + ","
336 + ObjectNameUtil.MODULE_FACTORY_NAME_KEY + "=" + moduleName
337 + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "=" + instanceName
342 public static ModuleIdentifier fromON(ObjectName objectName,
343 String expectedType) {
344 checkType(objectName, expectedType);
345 String factoryName = getFactoryName(objectName);
346 if (factoryName == null)
347 throw new IllegalArgumentException(
348 "ObjectName does not contain module name");
349 String instanceName = getInstanceName(objectName);
350 if (instanceName == null)
351 throw new IllegalArgumentException(
352 "ObjectName does not contain instance name");
353 return new ModuleIdentifier(factoryName, instanceName);
356 public static boolean isServiceReference(ObjectName objectName) {
357 return TYPE_SERVICE_REFERENCE.equals(objectName.getKeyProperty(TYPE_KEY));