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.manager.impl.dynamicmbean;
10 import java.lang.reflect.Method;
11 import javax.annotation.concurrent.ThreadSafe;
12 import javax.management.Attribute;
13 import javax.management.AttributeList;
14 import javax.management.AttributeNotFoundException;
15 import javax.management.DynamicMBean;
16 import javax.management.InstanceNotFoundException;
17 import javax.management.InvalidAttributeValueException;
18 import javax.management.MBeanException;
19 import javax.management.MBeanOperationInfo;
20 import javax.management.MBeanServer;
21 import javax.management.ObjectName;
22 import javax.management.ReflectionException;
23 import org.opendaylight.controller.config.api.ModuleIdentifier;
24 import org.opendaylight.controller.config.api.ValidationException;
25 import org.opendaylight.controller.config.api.annotations.RequireInterface;
26 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
27 import org.opendaylight.controller.config.spi.Module;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
32 * Wraps {@link org.opendaylight.controller.config.spi.Module} instance in a
33 * {@link DynamicMBean} interface. Inspects dependency attributes, identified by
34 * ObjectName getter/setter and {@link RequireInterface} annotation. Used to
35 * simplify client calls - to set a dependency, only instance name is needed.
36 * This class creates new writable String attribute for each dependency with
37 * 'Name' suffix backed by the actual ObjectName attribute.
39 * Thread safety - setting attributes is synchronized on 'this'. Synchronization
40 * of {@link org.opendaylight.controller.config.spi.Module#validate()} and
41 * {@link org.opendaylight.controller.config.spi.Module#getInstance()} is also
43 * org.opendaylight.controller.config.manager.impl.ConfigTransactionControllerInternal
44 * so the actual {@link org.opendaylight.controller.config.spi.Module} needs not
49 public class DynamicWritableWrapper extends AbstractDynamicWrapper {
50 private static final Logger LOG = LoggerFactory.getLogger(DynamicWritableWrapper.class);
52 private final ReadOnlyAtomicBoolean configBeanModificationDisabled;
54 public DynamicWritableWrapper(final Module module, final ModuleIdentifier moduleIdentifier,
55 final String transactionIdentifier, final ReadOnlyAtomicBoolean configBeanModificationDisabled,
56 final MBeanServer internalServer, final MBeanServer configMBeanServer) {
57 super(module, true, moduleIdentifier,
58 ObjectNameUtil.createTransactionModuleON(transactionIdentifier, moduleIdentifier),
59 getOperations(moduleIdentifier), internalServer, configMBeanServer);
60 this.configBeanModificationDisabled = configBeanModificationDisabled;
63 private static MBeanOperationInfo[] getOperations(final ModuleIdentifier moduleIdentifier) {
64 Method validationMethod;
66 validationMethod = DynamicWritableWrapper.class.getMethod("validate");
67 } catch (final NoSuchMethodException e) {
68 throw new IllegalStateException("No such method exception on " + moduleIdentifier, e);
70 return new MBeanOperationInfo[] { new MBeanOperationInfo("Validation", validationMethod) };
74 public synchronized void setAttribute(final Attribute attribute)
75 throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
76 Attribute newAttribute = attribute;
77 if (configBeanModificationDisabled.get()) {
78 throw new IllegalStateException("Operation is not allowed now");
81 if ("Attribute".equals(newAttribute.getName())) {
82 setAttribute((Attribute) newAttribute.getValue());
87 if (newAttribute.getValue() instanceof ObjectName) {
88 newAttribute = fixDependencyAttribute(newAttribute);
89 } else if (newAttribute.getValue() instanceof ObjectName[]) {
90 newAttribute = fixDependencyListAttribute(newAttribute);
93 internalServer.setAttribute(objectNameInternal, newAttribute);
94 } catch (final InstanceNotFoundException e) {
95 throw new MBeanException(e);
100 private Attribute fixDependencyListAttribute(final Attribute attribute) {
101 Attribute newAttribute = attribute;
102 AttributeHolder attributeHolder = attributeHolderMap.get(newAttribute.getName());
103 if (attributeHolder.getRequireInterfaceOrNull() != null) {
104 newAttribute = new Attribute(newAttribute.getName(),
105 fixObjectNames((ObjectName[]) newAttribute.getValue()));
110 private Attribute fixDependencyAttribute(final Attribute attribute) {
111 Attribute newAttribute = attribute;
112 AttributeHolder attributeHolder = attributeHolderMap.get(newAttribute.getName());
113 if (attributeHolder.getRequireInterfaceOrNull() != null) {
114 newAttribute = new Attribute(newAttribute.getName(), fixObjectName((ObjectName) newAttribute.getValue()));
116 newAttribute = new Attribute(newAttribute.getName(), newAttribute.getValue());
121 private ObjectName[] fixObjectNames(final ObjectName[] dependencies) {
124 for (ObjectName dependencyOn : dependencies) {
125 dependencies[index++] = fixObjectName(dependencyOn);
132 public AttributeList setAttributes(final AttributeList attributes) {
133 AttributeList result = new AttributeList();
134 for (Object attributeObject : attributes) {
135 Attribute attribute = (Attribute) attributeObject;
137 setAttribute(attribute);
138 result.add(attribute);
139 } catch (final InvalidAttributeValueException | AttributeNotFoundException | MBeanException
140 | ReflectionException e) {
141 LOG.warn("Setting attribute {} failed on {}", attribute.getName(), moduleIdentifier, e);
142 throw new IllegalArgumentException(
143 "Setting attribute failed - " + attribute.getName() + " on " + moduleIdentifier, e);
149 @SuppressWarnings("IllegalCatch")
151 public Object invoke(final String actionName, final Object[] params, final String[] signature)
152 throws MBeanException, ReflectionException {
153 if ("validate".equals(actionName) && (params == null || params.length == 0)
154 && (signature == null || signature.length == 0)) {
157 } catch (final Exception e) {
158 throw new MBeanException(ValidationException.createForSingleException(moduleIdentifier, e));
162 return super.invoke(actionName, params, signature);
165 public void validate() {