001/*
002 * Copyright 2002-2007 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.jmx.export;
018
019import javax.management.Attribute;
020import javax.management.AttributeList;
021import javax.management.AttributeNotFoundException;
022import javax.management.InstanceNotFoundException;
023import javax.management.InvalidAttributeValueException;
024import javax.management.MBeanException;
025import javax.management.ReflectionException;
026import javax.management.RuntimeOperationsException;
027import javax.management.modelmbean.InvalidTargetObjectTypeException;
028import javax.management.modelmbean.ModelMBeanInfo;
029import javax.management.modelmbean.RequiredModelMBean;
030
031/**
032 * Extension of the {@link RequiredModelMBean} class that ensures the
033 * {@link Thread#getContextClassLoader() thread context ClassLoader} is switched
034 * for the managed resource's {@link ClassLoader} before any invocations occur.
035 *
036 * @author Rob Harrop
037 * @since 2.0
038 * @see RequiredModelMBean
039 */
040public class SpringModelMBean extends RequiredModelMBean {
041
042        /**
043         * Stores the {@link ClassLoader} to use for invocations. Defaults
044         * to the current thread {@link ClassLoader}.
045         */
046        private ClassLoader managedResourceClassLoader = Thread.currentThread().getContextClassLoader();
047
048
049        /**
050         * Construct a new SpringModelMBean instance with an empty {@link ModelMBeanInfo}.
051         * @see javax.management.modelmbean.RequiredModelMBean#RequiredModelMBean()
052         */
053        public SpringModelMBean() throws MBeanException, RuntimeOperationsException {
054                super();
055        }
056
057        /**
058         * Construct a new SpringModelMBean instance with the given {@link ModelMBeanInfo}.
059         * @see javax.management.modelmbean.RequiredModelMBean#RequiredModelMBean(ModelMBeanInfo)
060         */
061        public SpringModelMBean(ModelMBeanInfo mbi) throws MBeanException, RuntimeOperationsException {
062                super(mbi);
063        }
064
065
066        /**
067         * Sets managed resource to expose and stores its {@link ClassLoader}.
068         */
069        @Override
070        public void setManagedResource(Object managedResource, String managedResourceType)
071                        throws MBeanException, InstanceNotFoundException, InvalidTargetObjectTypeException {
072
073                this.managedResourceClassLoader = managedResource.getClass().getClassLoader();
074                super.setManagedResource(managedResource, managedResourceType);
075        }
076
077
078        /**
079         * Switches the {@link Thread#getContextClassLoader() context ClassLoader} for the
080         * managed resources {@link ClassLoader} before allowing the invocation to occur.
081         * @see javax.management.modelmbean.ModelMBean#invoke
082         */
083        @Override
084        public Object invoke(String opName, Object[] opArgs, String[] sig)
085                        throws MBeanException, ReflectionException {
086
087                ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
088                try {
089                        Thread.currentThread().setContextClassLoader(this.managedResourceClassLoader);
090                        return super.invoke(opName, opArgs, sig);
091                }
092                finally {
093                        Thread.currentThread().setContextClassLoader(currentClassLoader);
094                }
095        }
096
097        /**
098         * Switches the {@link Thread#getContextClassLoader() context ClassLoader} for the
099         * managed resources {@link ClassLoader} before allowing the invocation to occur.
100         * @see javax.management.modelmbean.ModelMBean#getAttribute
101         */
102        @Override
103        public Object getAttribute(String attrName)
104                        throws AttributeNotFoundException, MBeanException, ReflectionException {
105
106                ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
107                try {
108                        Thread.currentThread().setContextClassLoader(this.managedResourceClassLoader);
109                        return super.getAttribute(attrName);
110                }
111                finally {
112                        Thread.currentThread().setContextClassLoader(currentClassLoader);
113                }
114        }
115
116        /**
117         * Switches the {@link Thread#getContextClassLoader() context ClassLoader} for the
118         * managed resources {@link ClassLoader} before allowing the invocation to occur.
119         * @see javax.management.modelmbean.ModelMBean#getAttributes
120         */
121        @Override
122        public AttributeList getAttributes(String[] attrNames) {
123                ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
124                try {
125                        Thread.currentThread().setContextClassLoader(this.managedResourceClassLoader);
126                        return super.getAttributes(attrNames);
127                }
128                finally {
129                        Thread.currentThread().setContextClassLoader(currentClassLoader);
130                }
131        }
132
133        /**
134         * Switches the {@link Thread#getContextClassLoader() context ClassLoader} for the
135         * managed resources {@link ClassLoader} before allowing the invocation to occur.
136         * @see javax.management.modelmbean.ModelMBean#setAttribute
137         */
138        @Override
139        public void setAttribute(Attribute attribute)
140                        throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
141
142                ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
143                try {
144                        Thread.currentThread().setContextClassLoader(this.managedResourceClassLoader);
145                        super.setAttribute(attribute);
146                }
147                finally {
148                        Thread.currentThread().setContextClassLoader(currentClassLoader);
149                }
150        }
151
152        /**
153         * Switches the {@link Thread#getContextClassLoader() context ClassLoader} for the
154         * managed resources {@link ClassLoader} before allowing the invocation to occur.
155         * @see javax.management.modelmbean.ModelMBean#setAttributes
156         */
157        @Override
158        public AttributeList setAttributes(AttributeList attributes) {
159                ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
160                try {
161                        Thread.currentThread().setContextClassLoader(this.managedResourceClassLoader);
162                        return super.setAttributes(attributes);
163                }
164                finally {
165                        Thread.currentThread().setContextClassLoader(currentClassLoader);
166                }
167        }
168
169}