Initial code drop of yang model driven configuration system
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / dynamicmbean / DynamicWritableWrapper.java
1 /*
2  * Copyright (c) 2013 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
12 import javax.annotation.concurrent.ThreadSafe;
13 import javax.management.Attribute;
14 import javax.management.AttributeList;
15 import javax.management.AttributeNotFoundException;
16 import javax.management.DynamicMBean;
17 import javax.management.InstanceNotFoundException;
18 import javax.management.InvalidAttributeValueException;
19 import javax.management.MBeanException;
20 import javax.management.MBeanOperationInfo;
21 import javax.management.MBeanServer;
22 import javax.management.ObjectName;
23 import javax.management.ReflectionException;
24
25 import org.opendaylight.controller.config.api.ModuleIdentifier;
26 import org.opendaylight.controller.config.api.ValidationException;
27 import org.opendaylight.controller.config.api.annotations.RequireInterface;
28 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
29 import org.opendaylight.controller.config.manager.impl.TransactionIdentifier;
30 import org.opendaylight.controller.config.spi.Module;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 /**
35  * Wraps {@link org.opendaylight.controller.config.spi.Module} instance in a
36  * {@link DynamicMBean} interface. Inspects dependency attributes, identified by
37  * ObjectName getter/setter and {@link RequireInterface} annotation. Used to
38  * simplify client calls - to set a dependency, only instance name is needed.
39  * This class creates new writable String attribute for each dependency with
40  * 'Name' suffix backed by the actual ObjectName attribute.
41  * <p>
42  * Thread safety - setting attributes is synchronized on 'this'. Synchronization
43  * of {@link org.opendaylight.controller.config.spi.Module#validate()} and
44  * {@link org.opendaylight.controller.config.spi.Module#getInstance()} is also
45  * guaranteed by
46  * {@link org.opendaylight.controller.config.manager.impl.ConfigTransactionControllerInternal}
47  * so the actual {@link org.opendaylight.controller.config.spi.Module} needs not
48  * to be thread safe.
49  * </p>
50  */
51 @ThreadSafe
52 public class DynamicWritableWrapper extends AbstractDynamicWrapper {
53     private static final Logger logger = LoggerFactory
54             .getLogger(DynamicWritableWrapper.class);
55
56     private final ReadOnlyAtomicBoolean configBeanModificationDisabled;
57
58     public DynamicWritableWrapper(Module module,
59             ModuleIdentifier moduleIdentifier,
60             TransactionIdentifier transactionIdentifier,
61             ReadOnlyAtomicBoolean configBeanModificationDisabled,
62             MBeanServer internalServer, MBeanServer configMBeanServer) {
63         super(module, true, moduleIdentifier, ObjectNameUtil
64                 .createTransactionModuleON(transactionIdentifier.getName(), moduleIdentifier), getOperations(moduleIdentifier),
65                 internalServer, configMBeanServer);
66         this.configBeanModificationDisabled = configBeanModificationDisabled;
67     }
68
69     private static MBeanOperationInfo[] getOperations(
70             ModuleIdentifier moduleIdentifier) {
71         Method validationMethod;
72         try {
73             validationMethod = DynamicWritableWrapper.class.getMethod(
74                     "validate", new Class<?>[0]);
75         } catch (NoSuchMethodException e) {
76             throw new IllegalStateException("No such method exception on "
77                     + moduleIdentifier, e);
78         }
79         return new MBeanOperationInfo[] { new MBeanOperationInfo("Validation",
80                 validationMethod) };
81     }
82
83     @Override
84     public synchronized void setAttribute(Attribute attribute)
85             throws AttributeNotFoundException, InvalidAttributeValueException,
86             MBeanException, ReflectionException {
87         if (configBeanModificationDisabled.get() == true)
88             throw new IllegalStateException("Operation is not allowed now");
89
90         if (attribute.getName().equals("Attribute")) {
91             setAttribute((Attribute) attribute.getValue());
92             return;
93         }
94
95         try {
96             if (attribute.getValue() instanceof ObjectName) {
97                 AttributeHolder attributeHolder = attributeHolderMap
98                         .get(attribute.getName());
99                 if (attributeHolder.getRequireInterfaceOrNull() != null) {
100                     attribute = new Attribute(attribute.getName(),
101                             fixObjectName((ObjectName) attribute.getValue()));
102                 } else {
103                     attribute = new Attribute(attribute.getName(),
104                             attribute.getValue());
105                 }
106             }
107             internalServer.setAttribute(objectNameInternal, attribute);
108         } catch (InstanceNotFoundException e) {
109             throw new MBeanException(e);
110         }
111
112     }
113
114     @Override
115     public AttributeList setAttributes(AttributeList attributes) {
116         AttributeList result = new AttributeList();
117         for (Object attributeObject : attributes) {
118             Attribute attribute = (Attribute) attributeObject;
119             try {
120                 setAttribute(attribute);
121                 result.add(attribute);
122             } catch (Exception e) {
123                 logger.warn("Setting attribute {} failed on {}",
124                         attribute.getName(), moduleIdentifier, e);
125                 throw new IllegalArgumentException(
126                         "Setting attribute failed - " + attribute.getName()
127                                 + " on " + moduleIdentifier, e);
128             }
129         }
130         return result;
131     }
132
133     @Override
134     public Object invoke(String actionName, Object[] params, String[] signature)
135             throws MBeanException, ReflectionException {
136         if ("validate".equals(actionName)
137                 && (params == null || params.length == 0)
138                 && (signature == null || signature.length == 0)) {
139             try {
140                 validate();
141             } catch (Exception e) {
142                 throw ValidationException.createForSingleException(
143                         moduleIdentifier, e);
144             }
145             return Void.TYPE;
146         }
147         return super.invoke(actionName, params, signature);
148     }
149
150     public void validate() {
151         module.validate();
152     }
153 }