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}