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.MalformedObjectNameException;
15 import javax.management.ObjectName;
16 import java.util.Arrays;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.Hashtable;
21 import java.util.Map.Entry;
25 * Provides ObjectName creation. Each created ObjectName consists of domain that
26 * is defined as {@link #ON_DOMAIN} and at least one key-value pair. The only
27 * mandatory property is {@link #TYPE_KEY}. All transaction related mbeans have
28 * {@link #TRANSACTION_NAME_KEY} property set.
31 public class ObjectNameUtil {
32 private ObjectNameUtil() {
35 public static final String ON_DOMAIN = ConfigRegistryConstants.ON_DOMAIN;
36 public static final String MODULE_FACTORY_NAME_KEY = "moduleFactoryName";
37 public static final String SERVICE_QNAME_KEY = "serviceQName";
38 public static final String INSTANCE_NAME_KEY = "instanceName";
39 public static final String TYPE_KEY = ConfigRegistryConstants.TYPE_KEY;
40 public static final String TYPE_CONFIG_TRANSACTION = "ConfigTransaction";
41 public static final String TYPE_MODULE = "Module";
42 public static final String TYPE_SERVICE_REFERENCE = "ServiceReference";
43 public static final String TYPE_RUNTIME_BEAN = "RuntimeBean";
44 public static final String TRANSACTION_NAME_KEY = "TransactionName";
45 public static final String REF_NAME_KEY = "RefName";
46 private static final String REPLACED_QUOTATION_MARK = "\\?";
47 public static final String ON_WILDCARD = "*";
49 public static ObjectName createON(String on) {
51 return new ObjectName(on);
52 } catch (MalformedObjectNameException e) {
53 throw new IllegalArgumentException(e);
57 public static ObjectName createONWithDomainAndType(String type) {
58 return ConfigRegistryConstants.createONWithDomainAndType(type);
61 public static ObjectName createON(String name, String key, String value) {
62 return ConfigRegistryConstants.createON(name, key, value);
65 public static ObjectName createON(String domain, Map<String, String> attribs) {
66 Hashtable<String, String> table = new Hashtable<>(attribs);
68 return new ObjectName(domain, table);
69 } catch (MalformedObjectNameException e) {
70 throw new IllegalArgumentException(e);
75 public static ObjectName createTransactionControllerON(
76 String transactionName) {
77 Map<String, String> onParams = new HashMap<>();
78 onParams.put(TRANSACTION_NAME_KEY, transactionName);
79 onParams.put(TYPE_KEY, TYPE_CONFIG_TRANSACTION);
80 return createON(ON_DOMAIN, onParams);
83 public static ObjectName createTransactionModuleON(String transactionName,
84 ModuleIdentifier moduleIdentifier) {
85 return createTransactionModuleON(transactionName,
86 moduleIdentifier.getFactoryName(),
87 moduleIdentifier.getInstanceName());
90 public static ObjectName createTransactionModuleON(String transactionName,
91 String moduleName, String instanceName) {
92 Map<String, String> onParams = createModuleMap(moduleName, instanceName);
93 onParams.put(TRANSACTION_NAME_KEY, transactionName);
94 return createON(ON_DOMAIN, onParams);
97 public static ObjectName createTransactionModuleON(String transactionName,
99 return createTransactionModuleON(transactionName, getFactoryName(on),
100 getInstanceName(on));
103 public static ObjectName createReadOnlyModuleON(
104 ModuleIdentifier moduleIdentifier) {
105 return createReadOnlyModuleON(moduleIdentifier.getFactoryName(),
106 moduleIdentifier.getInstanceName());
109 public static ObjectName createReadOnlyServiceON(String serviceQName, String refName) {
110 Map<String, String> onParams = createServiceMap(serviceQName, refName);
111 return createON(ON_DOMAIN, onParams);
114 public static ObjectName createTransactionServiceON(String transactionName, String serviceQName, String refName) {
115 Map<String, String> onParams = createServiceON(transactionName, serviceQName, refName);
116 return createON(ON_DOMAIN, onParams);
119 public static String getServiceQName(ObjectName objectName) {
120 checkType(objectName, TYPE_SERVICE_REFERENCE);
121 String quoted = objectName.getKeyProperty(SERVICE_QNAME_KEY);
122 return unquoteAndUnescape(objectName, quoted);
125 // ObjectName supports quotation and ignores tokens like =, but fails to ignore ? sign.
126 // It must be replaced with another character that hopefully does not collide
127 // with actual value.
128 private static String unquoteAndUnescape(ObjectName objectName, String quoted) {
129 if (quoted == null) {
130 throw new IllegalArgumentException("Cannot find " + SERVICE_QNAME_KEY + " in " + objectName);
132 if (quoted.startsWith("\"") == false || quoted.endsWith("\"") == false) {
133 throw new IllegalArgumentException("Quotes not found in " + objectName);
135 String substring = quoted.substring(1);
136 substring = substring.substring(0, substring.length() - 1);
137 substring = substring.replace(REPLACED_QUOTATION_MARK, "?");
141 private static String quoteAndEscapeValue(String serviceQName) {
142 return "\"" + serviceQName.replace("?", REPLACED_QUOTATION_MARK) + "\"";
145 public static String getReferenceName(ObjectName objectName) {
146 checkType(objectName, TYPE_SERVICE_REFERENCE);
147 return objectName.getKeyProperty(REF_NAME_KEY);
150 private static Map<String, String> createServiceON(String transactionName, String serviceQName,
152 Map<String, String> result = new HashMap<>(createServiceMap(serviceQName, refName));
153 result.put(TRANSACTION_NAME_KEY, transactionName);
157 private static Map<String, String> createServiceMap(String serviceQName,
159 Map<String, String> onParams = new HashMap<>();
160 onParams.put(TYPE_KEY, TYPE_SERVICE_REFERENCE);
161 onParams.put(SERVICE_QNAME_KEY, quoteAndEscapeValue(serviceQName));
162 onParams.put(REF_NAME_KEY, refName);
167 public static ObjectName createReadOnlyModuleON(String moduleName,
168 String instanceName) {
169 Map<String, String> onParams = createModuleMap(moduleName, instanceName);
170 return createON(ON_DOMAIN, onParams);
173 private static Map<String, String> createModuleMap(String moduleName,
174 String instanceName) {
175 Map<String, String> onParams = new HashMap<>();
176 onParams.put(TYPE_KEY, TYPE_MODULE);
177 onParams.put(MODULE_FACTORY_NAME_KEY, moduleName);
178 onParams.put(INSTANCE_NAME_KEY, instanceName);
182 public static String getFactoryName(ObjectName objectName) {
183 checkTypeOneOf(objectName, TYPE_MODULE, TYPE_RUNTIME_BEAN);
184 return objectName.getKeyProperty(MODULE_FACTORY_NAME_KEY);
187 public static String getInstanceName(ObjectName objectName) {
188 checkTypeOneOf(objectName, TYPE_MODULE, TYPE_RUNTIME_BEAN);
189 return objectName.getKeyProperty(INSTANCE_NAME_KEY);
192 public static String getTransactionName(ObjectName objectName) {
193 return objectName.getKeyProperty(TRANSACTION_NAME_KEY);
197 * Sanitize on: keep only mandatory attributes of module + metadata.
199 public static ObjectName withoutTransactionName(ObjectName inputON) {
200 checkTypeOneOf(inputON, TYPE_MODULE, TYPE_SERVICE_REFERENCE);
201 if (getTransactionName(inputON) == null) {
202 throw new IllegalArgumentException(
203 "Expected ObjectName with transaction:" + inputON);
205 if (ON_DOMAIN.equals(inputON.getDomain()) == false) {
206 throw new IllegalArgumentException("Expected different domain: "
209 Map<String, String> outputProperties;
210 if (inputON.getKeyProperty(TYPE_KEY).equals(TYPE_MODULE)) {
211 String moduleName = getFactoryName(inputON);
212 String instanceName = getInstanceName(inputON);
213 outputProperties = new HashMap<>(createModuleMap(moduleName, instanceName));
215 String serviceQName = getServiceQName(inputON);
216 String refName = getReferenceName(inputON);
217 outputProperties = new HashMap<>(createServiceMap(serviceQName, refName));
219 Map<String, String> allProperties = getAdditionalProperties(inputON);
220 for (Entry<String, String> entry : allProperties.entrySet()) {
221 if (entry.getKey().startsWith("X-")) {
222 outputProperties.put(entry.getKey(), entry.getValue());
225 return createON(ON_DOMAIN, outputProperties);
228 public static ObjectName withTransactionName(ObjectName inputON, String transactionName) {
229 Map<String, String> additionalProperties = getAdditionalProperties(inputON);
230 additionalProperties.put(TRANSACTION_NAME_KEY, transactionName);
231 return createON(inputON.getDomain(), additionalProperties);
235 private static void assertDoesNotContain(
236 Map<String, String> additionalProperties, String key) {
237 if (additionalProperties.containsKey(key)) {
238 throw new IllegalArgumentException(
239 "Map 'additionalProperties' cannot overwrite attribute "
244 public static ObjectName createRuntimeBeanName(String moduleName,
245 String instanceName, Map<String, String> additionalProperties) {
246 // check that there is no overwriting of default attributes
247 assertDoesNotContain(additionalProperties, MODULE_FACTORY_NAME_KEY);
248 assertDoesNotContain(additionalProperties, INSTANCE_NAME_KEY);
249 assertDoesNotContain(additionalProperties, TYPE_KEY);
250 assertDoesNotContain(additionalProperties, TRANSACTION_NAME_KEY);
251 Map<String, String> map = new HashMap<>(additionalProperties);
252 map.put(MODULE_FACTORY_NAME_KEY, moduleName);
253 map.put(INSTANCE_NAME_KEY, instanceName);
254 map.put(TYPE_KEY, TYPE_RUNTIME_BEAN);
255 return createON(ON_DOMAIN, map);
258 private static Set<String> blacklist = new HashSet<>(Arrays.asList(
259 MODULE_FACTORY_NAME_KEY, INSTANCE_NAME_KEY, TYPE_KEY));
261 public static Map<String, String> getAdditionalPropertiesOfRuntimeBeanName(
263 checkType(on, TYPE_RUNTIME_BEAN);
264 Map<String, String> allProperties = getAdditionalProperties(on);
265 Map<String, String> result = new HashMap<>();
266 for (Entry<String, String> entry : allProperties.entrySet()) {
267 if (blacklist.contains(entry.getKey()) == false) {
268 result.put(entry.getKey(), entry.getValue());
274 public static Map<String, String> getAdditionalProperties(ObjectName on) {
275 Map<String, String> keyPropertyList = on.getKeyPropertyList();
276 Map<String, String> result = new HashMap<>();
277 for (Entry<String, String> entry : keyPropertyList.entrySet()) {
278 result.put(entry.getKey(), entry.getValue());
283 public static void checkDomain(ObjectName objectName) {
284 if (!ON_DOMAIN.equals(objectName.getDomain())) {
285 throw new IllegalArgumentException("Wrong domain " + objectName);
290 public static void checkType(ObjectName objectName, String type) {
291 if (!type.equals(objectName.getKeyProperty(TYPE_KEY))) {
292 throw new IllegalArgumentException("Wrong type, expected '" + type
293 + "', got " + objectName);
297 public static void checkTypeOneOf(ObjectName objectName, String... types) {
298 for (String type : types) {
299 if (type.equals(objectName.getKeyProperty(TYPE_KEY))) {
303 throw new IllegalArgumentException("Wrong type, expected one of " + Arrays.asList(types)
304 + ", got " + objectName);
307 public static ObjectName createModulePattern(String moduleName,
308 String instanceName) {
309 String finalModuleName = moduleName == null ? ON_WILDCARD : moduleName;
310 String finalInstanceName = instanceName == null ? ON_WILDCARD : instanceName;
312 // do not return object names containing transaction name
313 ObjectName namePattern = ObjectNameUtil
314 .createON(ObjectNameUtil.ON_DOMAIN + ":"
315 + ObjectNameUtil.TYPE_KEY + "="
316 + ObjectNameUtil.TYPE_MODULE + ","
317 + ObjectNameUtil.MODULE_FACTORY_NAME_KEY + "="
318 + finalModuleName + "," + ""
319 + ObjectNameUtil.INSTANCE_NAME_KEY + "=" + finalInstanceName);
323 public static ObjectName createModulePattern(String ifcName,
324 String instanceName, String transactionName) {
325 String finalIfcName = ifcName == null ? ON_WILDCARD : ifcName;
326 String finalInstanceName = instanceName == null ? ON_WILDCARD : instanceName;
327 String finalTransactionName = transactionName == null ? ON_WILDCARD : transactionName;
329 return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN
330 + ":type=Module," + ObjectNameUtil.MODULE_FACTORY_NAME_KEY
331 + "=" + finalIfcName + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "="
332 + finalInstanceName + "," + ObjectNameUtil.TRANSACTION_NAME_KEY
333 + "=" + finalTransactionName);
336 public static ObjectName createRuntimeBeanPattern(String moduleName,
337 String instanceName) {
338 String finalModuleName = moduleName == null ? ON_WILDCARD : moduleName;
339 String finalInstanceName = instanceName == null ? ON_WILDCARD : instanceName;
341 return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":"
342 + ObjectNameUtil.TYPE_KEY + "="
343 + ObjectNameUtil.TYPE_RUNTIME_BEAN + ","
344 + ObjectNameUtil.MODULE_FACTORY_NAME_KEY + "=" + finalModuleName
345 + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "=" + finalInstanceName
350 public static ModuleIdentifier fromON(ObjectName objectName,
351 String expectedType) {
352 checkType(objectName, expectedType);
353 String factoryName = getFactoryName(objectName);
354 if (factoryName == null) {
355 throw new IllegalArgumentException(
356 "ObjectName does not contain module name");
358 String instanceName = getInstanceName(objectName);
359 if (instanceName == null) {
360 throw new IllegalArgumentException(
361 "ObjectName does not contain instance name");
363 return new ModuleIdentifier(factoryName, instanceName);
366 public static boolean isServiceReference(ObjectName objectName) {
367 return TYPE_SERVICE_REFERENCE.equals(objectName.getKeyProperty(TYPE_KEY));