2 * Copyright (c) 2013, 2017 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 java.util.Arrays;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.Hashtable;
15 import java.util.Map.Entry;
17 import javax.annotation.concurrent.ThreadSafe;
18 import javax.management.MalformedObjectNameException;
19 import javax.management.ObjectName;
20 import org.opendaylight.controller.config.api.ModuleIdentifier;
21 import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConstants;
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 final 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_TRANSACTION = "ConfigTransaction";
38 public static final String TYPE_MODULE = "Module";
39 public static final String TYPE_SERVICE_REFERENCE = "ServiceReference";
40 public static final String TYPE_RUNTIME_BEAN = "RuntimeBean";
41 public static final String TRANSACTION_NAME_KEY = "TransactionName";
42 public static final String REF_NAME_KEY = "RefName";
43 private static final String REPLACED_QUOTATION_MARK = "\\?";
44 public static final String ON_WILDCARD = "*";
46 private ObjectNameUtil() {
49 public static ObjectName createON(final String on) {
51 return new ObjectName(on);
52 } catch (final MalformedObjectNameException e) {
53 throw new IllegalArgumentException(e);
57 public static ObjectName createON(final String name, final String key, final String value) {
58 return ConfigRegistryConstants.createON(name, key, value);
61 public static ObjectName createON(final String domain, final Map<String, String> attribs) {
62 Hashtable<String, String> table = new Hashtable<>(attribs);
64 return new ObjectName(domain, table);
65 } catch (final MalformedObjectNameException e) {
66 throw new IllegalArgumentException(e);
71 public static ObjectName createONWithDomainAndType(final String type) {
72 return ConfigRegistryConstants.createONWithDomainAndType(type);
75 public static ObjectName createTransactionControllerON(final String transactionName) {
76 Map<String, String> onParams = new HashMap<>();
77 onParams.put(TRANSACTION_NAME_KEY, transactionName);
78 onParams.put(TYPE_KEY, TYPE_CONFIG_TRANSACTION);
79 return createON(ON_DOMAIN, onParams);
82 public static ObjectName createTransactionModuleON(final String transactionName,
83 final ModuleIdentifier moduleIdentifier) {
84 return createTransactionModuleON(transactionName, moduleIdentifier.getFactoryName(),
85 moduleIdentifier.getInstanceName());
88 public static ObjectName createTransactionModuleON(final String transactionName, final String moduleName,
89 final String instanceName) {
90 Map<String, String> onParams = createModuleMap(moduleName, instanceName);
91 onParams.put(TRANSACTION_NAME_KEY, transactionName);
92 return createON(ON_DOMAIN, onParams);
95 public static ObjectName createTransactionModuleON(final String transactionName, final ObjectName on) {
96 return createTransactionModuleON(transactionName, getFactoryName(on), getInstanceName(on));
99 public static ObjectName createReadOnlyModuleON(final ModuleIdentifier moduleIdentifier) {
100 return createReadOnlyModuleON(moduleIdentifier.getFactoryName(), moduleIdentifier.getInstanceName());
103 public static ObjectName createReadOnlyModuleON(final String moduleName, final String instanceName) {
104 Map<String, String> onParams = createModuleMap(moduleName, instanceName);
105 return createON(ON_DOMAIN, onParams);
108 public static ObjectName createReadOnlyServiceON(final String serviceQName, final String refName) {
109 Map<String, String> onParams = createServiceMap(serviceQName, refName);
110 return createON(ON_DOMAIN, onParams);
113 public static ObjectName createTransactionServiceON(final String transactionName, final String serviceQName,
114 final String refName) {
115 Map<String, String> onParams = createServiceON(transactionName, serviceQName, refName);
116 return createON(ON_DOMAIN, onParams);
119 public static String getServiceQName(final 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
127 // It must be replaced with another character that hopefully does not collide
128 // with actual value.
129 private static String unquoteAndUnescape(final ObjectName objectName, final String quoted) {
130 if (quoted == null) {
131 throw new IllegalArgumentException("Cannot find " + SERVICE_QNAME_KEY + " in " + objectName);
133 if (!quoted.startsWith("\"") || !quoted.endsWith("\"")) {
134 throw new IllegalArgumentException("Quotes not found in " + objectName);
136 String substring = quoted.substring(1);
137 substring = substring.substring(0, substring.length() - 1);
138 substring = substring.replace(REPLACED_QUOTATION_MARK, "?");
142 private static String quoteAndEscapeValue(final String serviceQName) {
143 return "\"" + serviceQName.replace("?", REPLACED_QUOTATION_MARK) + "\"";
146 public static String getReferenceName(final ObjectName objectName) {
147 checkType(objectName, TYPE_SERVICE_REFERENCE);
148 return objectName.getKeyProperty(REF_NAME_KEY);
151 private static Map<String, String> createServiceON(final String transactionName, final String serviceQName,
152 final String refName) {
153 Map<String, String> result = new HashMap<>(createServiceMap(serviceQName, refName));
154 result.put(TRANSACTION_NAME_KEY, transactionName);
158 private static Map<String, String> createServiceMap(final String serviceQName, final String refName) {
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);
166 private static Map<String, String> createModuleMap(final String moduleName, final String instanceName) {
167 Map<String, String> onParams = new HashMap<>();
168 onParams.put(TYPE_KEY, TYPE_MODULE);
169 onParams.put(MODULE_FACTORY_NAME_KEY, moduleName);
170 onParams.put(INSTANCE_NAME_KEY, instanceName);
174 public static String getFactoryName(final ObjectName objectName) {
175 checkTypeOneOf(objectName, TYPE_MODULE, TYPE_RUNTIME_BEAN);
176 return objectName.getKeyProperty(MODULE_FACTORY_NAME_KEY);
179 public static String getInstanceName(final ObjectName objectName) {
180 checkTypeOneOf(objectName, TYPE_MODULE, TYPE_RUNTIME_BEAN);
181 return objectName.getKeyProperty(INSTANCE_NAME_KEY);
184 public static String getTransactionName(final ObjectName objectName) {
185 return objectName.getKeyProperty(TRANSACTION_NAME_KEY);
189 * Sanitize on: keep only mandatory attributes of module + metadata.
191 public static ObjectName withoutTransactionName(final ObjectName inputON) {
192 checkTypeOneOf(inputON, TYPE_MODULE, TYPE_SERVICE_REFERENCE);
193 if (getTransactionName(inputON) == null) {
194 throw new IllegalArgumentException("Expected ObjectName with transaction:" + inputON);
196 if (!ON_DOMAIN.equals(inputON.getDomain())) {
197 throw new IllegalArgumentException("Expected different domain: " + inputON);
199 Map<String, String> outputProperties;
200 if (inputON.getKeyProperty(TYPE_KEY).equals(TYPE_MODULE)) {
201 String moduleName = getFactoryName(inputON);
202 String instanceName = getInstanceName(inputON);
203 outputProperties = new HashMap<>(createModuleMap(moduleName, instanceName));
205 String serviceQName = getServiceQName(inputON);
206 String refName = getReferenceName(inputON);
207 outputProperties = new HashMap<>(createServiceMap(serviceQName, refName));
209 Map<String, String> allProperties = getAdditionalProperties(inputON);
210 for (Entry<String, String> entry : allProperties.entrySet()) {
211 if (entry.getKey().startsWith("X-")) {
212 outputProperties.put(entry.getKey(), entry.getValue());
215 return createON(ON_DOMAIN, outputProperties);
218 public static ObjectName withTransactionName(final ObjectName inputON, final String transactionName) {
219 Map<String, String> additionalProperties = getAdditionalProperties(inputON);
220 additionalProperties.put(TRANSACTION_NAME_KEY, transactionName);
221 return createON(inputON.getDomain(), additionalProperties);
225 private static void assertDoesNotContain(final Map<String, String> additionalProperties, final String key) {
226 if (additionalProperties.containsKey(key)) {
227 throw new IllegalArgumentException("Map 'additionalProperties' cannot overwrite attribute " + key);
231 public static ObjectName createRuntimeBeanName(final String moduleName, final String instanceName,
232 final Map<String, String> additionalProperties) {
233 // check that there is no overwriting of default attributes
234 assertDoesNotContain(additionalProperties, MODULE_FACTORY_NAME_KEY);
235 assertDoesNotContain(additionalProperties, INSTANCE_NAME_KEY);
236 assertDoesNotContain(additionalProperties, TYPE_KEY);
237 assertDoesNotContain(additionalProperties, TRANSACTION_NAME_KEY);
238 Map<String, String> map = new HashMap<>(additionalProperties);
239 map.put(MODULE_FACTORY_NAME_KEY, moduleName);
240 map.put(INSTANCE_NAME_KEY, instanceName);
241 map.put(TYPE_KEY, TYPE_RUNTIME_BEAN);
242 return createON(ON_DOMAIN, map);
245 private static Set<String> blacklist = new HashSet<>(
246 Arrays.asList(MODULE_FACTORY_NAME_KEY, INSTANCE_NAME_KEY, TYPE_KEY));
248 public static Map<String, String> getAdditionalPropertiesOfRuntimeBeanName(final ObjectName on) {
249 checkType(on, TYPE_RUNTIME_BEAN);
250 Map<String, String> allProperties = getAdditionalProperties(on);
251 Map<String, String> result = new HashMap<>();
252 for (Entry<String, String> entry : allProperties.entrySet()) {
253 if (!blacklist.contains(entry.getKey())) {
254 result.put(entry.getKey(), entry.getValue());
260 public static Map<String, String> getAdditionalProperties(final ObjectName on) {
261 Map<String, String> keyPropertyList = on.getKeyPropertyList();
262 Map<String, String> result = new HashMap<>();
263 for (Entry<String, String> entry : keyPropertyList.entrySet()) {
264 result.put(entry.getKey(), entry.getValue());
269 public static void checkDomain(final ObjectName objectName) {
270 if (!ON_DOMAIN.equals(objectName.getDomain())) {
271 throw new IllegalArgumentException("Wrong domain " + objectName);
276 public static void checkType(final ObjectName objectName, final String type) {
277 if (!type.equals(objectName.getKeyProperty(TYPE_KEY))) {
278 throw new IllegalArgumentException("Wrong type, expected '" + type + "', got " + objectName);
282 public static void checkTypeOneOf(final ObjectName objectName, final String... types) {
283 for (String type : types) {
284 if (type.equals(objectName.getKeyProperty(TYPE_KEY))) {
288 throw new IllegalArgumentException(
289 "Wrong type, expected one of " + Arrays.asList(types) + ", got " + objectName);
292 public static ObjectName createModulePattern(final String moduleName, final String instanceName) {
293 String finalModuleName = moduleName == null ? ON_WILDCARD : moduleName;
294 String finalInstanceName = instanceName == null ? ON_WILDCARD : instanceName;
296 // do not return object names containing transaction name
297 ObjectName namePattern = ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":" + ObjectNameUtil.TYPE_KEY + "="
298 + ObjectNameUtil.TYPE_MODULE + "," + ObjectNameUtil.MODULE_FACTORY_NAME_KEY + "=" + finalModuleName
299 + "," + "" + ObjectNameUtil.INSTANCE_NAME_KEY + "=" + finalInstanceName);
303 public static ObjectName createModulePattern(final String ifcName, final String instanceName,
304 final String transactionName) {
305 String finalIfcName = ifcName == null ? ON_WILDCARD : ifcName;
306 String finalInstanceName = instanceName == null ? ON_WILDCARD : instanceName;
307 String finalTransactionName = transactionName == null ? ON_WILDCARD : transactionName;
309 return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":type=Module,"
310 + ObjectNameUtil.MODULE_FACTORY_NAME_KEY + "=" + finalIfcName + "," + ObjectNameUtil.INSTANCE_NAME_KEY
311 + "=" + finalInstanceName + "," + ObjectNameUtil.TRANSACTION_NAME_KEY + "=" + finalTransactionName);
314 public static ObjectName createRuntimeBeanPattern(final String moduleName, final String instanceName) {
315 String finalModuleName = moduleName == null ? ON_WILDCARD : moduleName;
316 String finalInstanceName = instanceName == null ? ON_WILDCARD : instanceName;
318 return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":" + ObjectNameUtil.TYPE_KEY + "="
319 + ObjectNameUtil.TYPE_RUNTIME_BEAN + "," + ObjectNameUtil.MODULE_FACTORY_NAME_KEY + "="
320 + finalModuleName + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "=" + finalInstanceName + ",*");
324 public static ModuleIdentifier fromON(final ObjectName objectName, final String expectedType) {
325 checkType(objectName, expectedType);
326 String factoryName = getFactoryName(objectName);
327 if (factoryName == null) {
328 throw new IllegalArgumentException("ObjectName does not contain module name");
330 String instanceName = getInstanceName(objectName);
331 if (instanceName == null) {
332 throw new IllegalArgumentException("ObjectName does not contain instance name");
334 return new ModuleIdentifier(factoryName, instanceName);
337 public static boolean isServiceReference(final ObjectName objectName) {
338 return TYPE_SERVICE_REFERENCE.equals(objectName.getKeyProperty(TYPE_KEY));