Remove yang-test
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / dynamicmbean / DynamicWritableWrapper.java
1 /*
2  * Copyright (c) 2013, 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.config.manager.impl.dynamicmbean;
9
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;
30
31 /**
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.
38  * <p>
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
42  * guaranteed by
43  * org.opendaylight.controller.config.manager.impl.ConfigTransactionControllerInternal
44  * so the actual {@link org.opendaylight.controller.config.spi.Module} needs not
45  * to be thread safe.
46  * </p>
47  */
48 @ThreadSafe
49 public class DynamicWritableWrapper extends AbstractDynamicWrapper {
50     private static final Logger LOG = LoggerFactory.getLogger(DynamicWritableWrapper.class);
51
52     private final ReadOnlyAtomicBoolean configBeanModificationDisabled;
53
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;
61     }
62
63     private static MBeanOperationInfo[] getOperations(final ModuleIdentifier moduleIdentifier) {
64         Method validationMethod;
65         try {
66             validationMethod = DynamicWritableWrapper.class.getMethod("validate");
67         } catch (final NoSuchMethodException e) {
68             throw new IllegalStateException("No such method exception on " + moduleIdentifier, e);
69         }
70         return new MBeanOperationInfo[] { new MBeanOperationInfo("Validation", validationMethod) };
71     }
72
73     @Override
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");
79         }
80
81         if ("Attribute".equals(newAttribute.getName())) {
82             setAttribute((Attribute) newAttribute.getValue());
83             return;
84         }
85
86         try {
87             if (newAttribute.getValue() instanceof ObjectName) {
88                 newAttribute = fixDependencyAttribute(newAttribute);
89             } else if (newAttribute.getValue() instanceof ObjectName[]) {
90                 newAttribute = fixDependencyListAttribute(newAttribute);
91             }
92
93             internalServer.setAttribute(objectNameInternal, newAttribute);
94         } catch (final InstanceNotFoundException e) {
95             throw new MBeanException(e);
96         }
97
98     }
99
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()));
106         }
107         return newAttribute;
108     }
109
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()));
115         } else {
116             newAttribute = new Attribute(newAttribute.getName(), newAttribute.getValue());
117         }
118         return newAttribute;
119     }
120
121     private ObjectName[] fixObjectNames(final ObjectName[] dependencies) {
122         int index = 0;
123
124         for (ObjectName dependencyOn : dependencies) {
125             dependencies[index++] = fixObjectName(dependencyOn);
126         }
127
128         return dependencies;
129     }
130
131     @Override
132     public AttributeList setAttributes(final AttributeList attributes) {
133         AttributeList result = new AttributeList();
134         for (Object attributeObject : attributes) {
135             Attribute attribute = (Attribute) attributeObject;
136             try {
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);
144             }
145         }
146         return result;
147     }
148
149     @SuppressWarnings("IllegalCatch")
150     @Override
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)) {
155             try {
156                 validate();
157             } catch (final Exception e) {
158                 throw new MBeanException(ValidationException.createForSingleException(moduleIdentifier, e));
159             }
160             return Void.TYPE;
161         }
162         return super.invoke(actionName, params, signature);
163     }
164
165     public void validate() {
166         module.validate();
167     }
168 }