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