001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.test.jbossmx.implementation.server;
023:
024: import java.io.File;
025: import java.io.FileInputStream;
026: import java.io.FileOutputStream;
027: import java.io.InputStream;
028: import java.net.URL;
029: import java.util.jar.JarOutputStream;
030: import java.util.jar.Manifest;
031: import java.util.zip.ZipEntry;
032: import javax.management.MBeanServer;
033: import javax.management.MBeanServerFactory;
034: import javax.management.ObjectName;
035: import javax.management.RuntimeErrorException;
036:
037: import junit.framework.Test;
038: import junit.framework.TestSuite;
039:
040: import org.apache.log4j.Category;
041: import org.apache.log4j.PatternLayout;
042: import org.apache.log4j.WriterAppender;
043:
044: import org.jboss.mx.loading.UnifiedLoaderRepository3;
045: import org.jboss.mx.loading.UnifiedClassLoader3;
046: import org.jboss.test.jbossmx.implementation.TestCase;
047:
048: /** Test of the mbean operation invocation thread context class loader. This
049: *test case simulates the problem originally seen in Bug#516649. Reproducing the
050: *steps here requires a number of contrived steps including simulated reloading
051: *of the mbean from different jars and the loading of the TestData class by
052: *the main MBeanClassLoader using Class.forName(). These are the actions that
053: *occur when reloading a sar that contains an ejb-jar.
054: *
055: * @author Scott.Stark@jboss.org
056: * @version $Revision: 57211 $
057: */
058: public class ContextCLTestCase extends TestCase {
059: private static URL dataClassURL;
060: private static File dataJar;
061: private static UnifiedLoaderRepository3 repo;
062: private static UnifiedClassLoader3 deployLoader;
063: private static UnifiedClassLoader3 noLoader;
064: static Object data0;
065: private static URL jarUrl;
066:
067: public ContextCLTestCase(String name) {
068: super (name);
069: }
070:
071: public void testInvokeNeedingTCL() throws Exception {
072: ClassLoader entryCL = Thread.currentThread()
073: .getContextClassLoader();
074: /* Install the mainLoader to simulate how the MBeanServer would be
075: *running under JBoss
076: */
077: Thread.currentThread().setContextClassLoader(deployLoader);
078: MBeanServer server = MBeanServerFactory.createMBeanServer();
079:
080: // Create the ContextCL MBean using the TestClassLoader
081: try {
082: repo.newClassLoader(jarUrl, true);
083: ObjectName beanName = new ObjectName(
084: "org.jboss.test.jbossmx.implementation.server.support:test=ContextCLTestCase");
085: server
086: .createMBean(
087: "org.jboss.test.jbossmx.implementation.server.support.ContextCL",
088: beanName);
089: getLog().info("Created ContextCL MBean");
090:
091: // Invoke the useTestData op to test the thread context class loader
092: server.invoke(beanName, "useTestData", null, null);
093: getLog().info("Invoked ContextCL.useTestData");
094: } catch (RuntimeErrorException e) {
095: getLog().error("NestedError", e.getTargetError());
096: throw e;
097: } finally {
098: Thread.currentThread().setContextClassLoader(entryCL);
099:
100: }
101:
102: MBeanServerFactory.releaseMBeanServer(server);
103: }
104:
105: /** This creates two mbean deployment jars, testdata.jar and testdata1.jar.
106: *A redeployment is simulated by loading
107: *
108: * @exception Exception Description of Exception
109: */
110: public void createTestDataJar() throws Exception {
111: repo = new UnifiedLoaderRepository3();
112: dataJar = new File("testdata.jar");
113: // Find the TestData class
114: dataClassURL = getClass()
115: .getResource(
116: "/org/jboss/test/jbossmx/implementation/server/support/TestData.class");
117: if (dataClassURL == null && dataJar.exists() == false)
118: fail("Failed to find /org/jboss/test/jbossmx/implementation/server/support/TestData.class");
119: if (dataClassURL != null) {
120: getLog().info("Found TestData at: " + dataClassURL);
121: // Build a jar file containing only the TestData.class and ContextCL mbean
122: FileOutputStream fos = new FileOutputStream(dataJar);
123: Manifest mf = new Manifest();
124: JarOutputStream jos = new JarOutputStream(fos, mf);
125:
126: ZipEntry entry = new ZipEntry(
127: "org/jboss/test/jbossmx/implementation/server/support/TestData.class");
128: jos.putNextEntry(entry);
129: InputStream dataIS = dataClassURL.openStream();
130: byte[] bytes = new byte[512];
131: int read = 0;
132: while ((read = dataIS.read(bytes)) > 0)
133: jos.write(bytes, 0, read);
134: jos.closeEntry();
135: dataIS.close();
136:
137: URL mbeanURL = getClass()
138: .getResource(
139: "/org/jboss/test/jbossmx/implementation/server/support/ContextCL.class");
140: entry = new ZipEntry(
141: "org/jboss/test/jbossmx/implementation/server/support/ContextCL.class");
142: jos.putNextEntry(entry);
143: dataIS = mbeanURL.openStream();
144: while ((read = dataIS.read(bytes)) > 0)
145: jos.write(bytes, 0, read);
146: jos.closeEntry();
147: dataIS.close();
148:
149: URL imbeanURL = getClass()
150: .getResource(
151: "/org/jboss/test/jbossmx/implementation/server/support/ContextCLMBean.class");
152: entry = new ZipEntry(
153: "org/jboss/test/jbossmx/implementation/server/support/ContextCLMBean.class");
154: jos.putNextEntry(entry);
155: dataIS = imbeanURL.openStream();
156: while ((read = dataIS.read(bytes)) > 0)
157: jos.write(bytes, 0, read);
158: jos.closeEntry();
159: dataIS.close();
160:
161: getLog().info(
162: "Created mbean jar at: "
163: + dataJar.getAbsolutePath());
164: jos.close();
165:
166: // Now remote the class files from this classpath
167: File dataClassFile = new File(dataClassURL.getFile());
168: getLog().info(
169: "Removed TestData.class File: "
170: + dataClassFile.delete());
171: File mbeanClassFile = new File(mbeanURL.getFile());
172: getLog().info(
173: "Removed ContextCL.class File: "
174: + mbeanClassFile.delete());
175: File imbeanClassFile = new File(imbeanURL.getFile());
176: getLog().info(
177: "Removed ContextCLMBean.class File: "
178: + imbeanClassFile.delete());
179: }
180:
181: // Create a copy of the jar
182: FileInputStream fis = new FileInputStream("testdata.jar");
183: FileOutputStream fos = new FileOutputStream("testdata1.jar");
184: byte[] bytes = new byte[512];
185: int read = 0;
186: while ((read = fis.read(bytes)) > 0)
187: fos.write(bytes, 0, read);
188: fis.close();
189: fos.close();
190:
191: noLoader = (UnifiedClassLoader3) repo
192: .newClassLoader(null, true);
193: deployLoader = (UnifiedClassLoader3) repo.newClassLoader(
194: dataJar.toURL(), true);
195: Class c0 = deployLoader
196: .loadClass("org.jboss.test.jbossmx.implementation.server.support.TestData");
197: getLog().info(
198: "TestData #0 ProtectionDomain: "
199: + c0.getProtectionDomain());
200: Class c1 = Class
201: .forName(
202: "org.jboss.test.jbossmx.implementation.server.support.TestData",
203: false, noLoader);
204: getLog().info(
205: "TestData #1 ProtectionDomain: "
206: + c1.getProtectionDomain());
207: repo.removeClassLoader(deployLoader);
208: // Simulate a redeploy
209: File data1Jar = new File("testdata1.jar");
210: jarUrl = data1Jar.toURL();
211: deployLoader = (UnifiedClassLoader3) repo.newClassLoader(
212: jarUrl, true);
213: c0 = deployLoader
214: .loadClass("org.jboss.test.jbossmx.implementation.server.support.TestData");
215: getLog().info(
216: "Reloaded TestData #0 ProtectionDomain: "
217: + c0.getProtectionDomain());
218: data0 = c0.newInstance();
219: }
220:
221: /** Setup the test suite.
222: */
223: public static Test suite() {
224: TestSuite suite = new TestSuite();
225: /* If this is running under java5 just return as there is no guarentee
226: of what the class loader of the mbean is.
227: */
228: try {
229: Class annotationClass = Class
230: .forName("java.lang.annotation.Annotation");
231: // Running under java5+, use an empty suite
232: } catch (ClassNotFoundException e) {
233: // Running under jdk1.4.x, continue
234: suite.addTest(new ContextCLTestCase("createTestDataJar"));
235: suite
236: .addTest(new ContextCLTestCase(
237: "testInvokeNeedingTCL"));
238: }
239: return suite;
240: }
241:
242: /** Allow the test case to run standalone
243: */
244: public static void main(java.lang.String[] args) {
245: // Set up a simple configuration that logs on the console.
246: Category root = Category.getRoot();
247: root.addAppender(new WriterAppender(
248: new PatternLayout("%x%m%n"), System.out));
249: Test suite = ContextCLTestCase.suite();
250: junit.textui.TestRunner.run(suite);
251: }
252: }
|