/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright 2008 Pentaho Corporation. All rights reserved. * */ package org.pentaho.test.platform.plugin.pluginmgr; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Enumeration; import org.junit.Before; import org.junit.Test; import org.pentaho.platform.plugin.services.pluginmgr.PluginClassLoader; @SuppressWarnings("nls") public class PluginClassLoaderTest { private PluginClassLoader pluginLoader; @Before public void init() { // now load a class pluginLoader = new PluginClassLoader(new File("./plugin-mgr/test-res/PluginClassLoaderTest/"), getClass().getClassLoader()); } @SuppressWarnings("unchecked") @Test public void testOverrideLoad() throws ClassNotFoundException, SecurityException, InstantiationException, IllegalAccessException { pluginLoader.setOverrideLoad(true); String className = "org.pentaho.test.platform.plugin.pluginmgr.ClassToOverride"; Class clazz = Class.forName(className, true, getClass().getClassLoader()); Object o = clazz.newInstance(); assertEquals("I am the original class from the parent class loader", o.toString()); Class overridenClazz = Class.forName(className, true, pluginLoader); Object o2 = overridenClazz.newInstance(); assertEquals("I am the overridden class from the plugin class loader", o2.toString()); } private Object getContainerFromPrivateClassLoader() throws ClassNotFoundException, InstantiationException, IllegalAccessException { String className = "org.pentaho.test.platform.plugin.pluginmgr.ClassToOverrideContainer"; Class<?> t = Class.forName(className, true, pluginLoader); return t.newInstance(); } @Test public void testImplicitLoad() throws ClassNotFoundException, InstantiationException, IllegalAccessException { pluginLoader.setOverrideLoad(true); // //1. Implicitly create an instance of ClassToOverride and check that it was loaded by the default loader. // ClassToOverride cto = new ClassToOverride(); assertNotSame(PluginClassLoader.class.getName(), cto.getClass().getClassLoader().getClass().getName()); assertEquals("failed to load original class", "I am the original class from the parent class loader", cto .toString()); //NOTE: implicit loading of a class (i.e. "new" or static method access) is always performed by the //classloader of the enclosing class (the "current" classloader), so if we set //Thread.currentThread().setContextClassLoader(pluginLoader) and then did a new ClassToOverride(), //the pluginLoader would *not* be asked to load ClassToOverride, rather the current classloader //will be asked to load it. // //2. Ask a class that we are certain was loaded by the private loader to implicitly create an instance // of ClassToOverride and check that the class was loaded by the private loader // Object explicitlyLoadedContainer = getContainerFromPrivateClassLoader(); assertEquals(PluginClassLoader.class.getName(), explicitlyLoadedContainer.getClass().getClassLoader().getClass().getName()); assertEquals("failed to load override class", "I am the overridden class from the plugin class loader", explicitlyLoadedContainer .toString()); } @Test public void testLoadClass() throws IOException, ClassNotFoundException { // now try getting it as a class Class<?> testClass = pluginLoader.loadClass("org.pentaho.test.platform.engine.services.TestClassForClassloader"); assertNotNull("class is null", testClass); assertEquals("wrong class", "org.pentaho.test.platform.engine.services.TestClassForClassloader", testClass .getName()); } @Test public void testLoadClassAsResource() throws IOException, ClassNotFoundException { // test the byte array first InputStream in = pluginLoader .getResourceAsStream("org/pentaho/test/platform/engine/services/TestClassForClassloader.class"); assertNotNull("Could not find class TestClassForClassloader in jar file", in); byte b[] = toBytes(in); String classBytes = new String(b); assertTrue("method is missing", classBytes .contains("org/pentaho/test/platform/engine/services/TestClassForClassloader")); } private byte[] toBytes(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte b[] = new byte[2048]; int n = in.read(b); while (n != -1) { out.write(b, 0, n); n = in.read(b); } return out.toByteArray(); } @Test public void testLoadXml() throws IOException { InputStream in = pluginLoader.getResourceAsStream("test1.xml"); assertNotNull("input stream is null", in); byte b[] = toBytes(in); String xml = new String(b); assertTrue("xml is wrong", xml.contains("<test1>")); } @Test public void testLoadBadResource() throws IOException { InputStream in = pluginLoader.getResourceAsStream("bogus.xml"); assertNull("input stream should be null", in); } @Test public void testLoadBadClass() throws IOException { // now try getting it as a class try { pluginLoader.loadClass("bogus"); assertFalse("Exception expected", true); } catch (ClassNotFoundException e) { assertTrue("Exception expected", true); } } @Test public void testLoadProperties_fromJar() throws IOException { InputStream in = pluginLoader.getResourceAsStream("org/pentaho/test/platform/engine/services/test.properties"); assertNotNull("input stream is null", in); byte b[] = toBytes(in); String classBytes = new String(b); assertTrue("property is missing", classBytes.contains("test_setting=test")); } @Test public void testLoadProperties_fromDir() throws IOException { InputStream in = pluginLoader.getResourceAsStream("resources/plugin-classloader-test-inresourcesdir.properties"); assertNotNull("input stream is null", in); byte b[] = toBytes(in); String classBytes = new String(b); assertTrue("property is missing", classBytes.contains("name=")); } @Test public void testFindXmlResource() throws IOException { URL url = pluginLoader.getResource("test1.xml"); assertNotNull("URL is null", url); InputStream in = url.openStream(); assertNotNull("input stream is null", in); byte b[] = toBytes(in); String xml = new String(b); assertTrue("xml is wrong", xml.contains("<test1>")); } @Test public void testFindClassResource() throws IOException { InputStream in = pluginLoader .getResourceAsStream("org/pentaho/test/platform/engine/services/TestClassForClassloader.class"); assertNotNull("input stream is null", in); byte b[] = toBytes(in); String xml = new String(b); assertTrue("xml is wrong", xml.contains("TestClassForClassloader")); } @Test public void testFindBadResource() throws IOException { URL url = pluginLoader.getResource("bogus.xml"); assertNull("URL should be null", url); } @Test public void testFindResources() throws IOException { Enumeration<URL> urls = pluginLoader.getResources("test1.xml"); assertNotNull("URLS is null", urls); int count = 0; while (urls.hasMoreElements()) { URL url = urls.nextElement(); InputStream in = url.openStream(); assertNotNull("input stream is null", in); byte b[] = toBytes(in); String xml = new String(b); assertTrue("xml is wrong", xml.contains("<test1>")); count++; } assertEquals("Wrong number of URLS", 1, count); } @Test public void testFindBadResources() throws IOException { Enumeration<URL> urls = pluginLoader.getResources("bogus.xml"); assertNotNull("URLS is null", urls); int count = 0; while (urls.hasMoreElements()) { count++; } assertEquals("Wrong number of URLS", 0, count); } @Test public void testJarListedInClassLoader() throws ClassNotFoundException { boolean jarFound = false; for (URL url : pluginLoader.getURLs()) { if (url.toString().contains("test-jar.jar")) { jarFound = true; } } assertTrue("test-jar.jar not found in classloader", jarFound); //now load a class from the jar pluginLoader.loadClass("org.pentaho.test.platform.engine.services.TestClassForClassloader"); } // @Test // public void testIsPluginClass() throws ClassNotFoundException { // Class testClass = loader.loadClass("org/pentaho/test/platform/engine/services/TestClassForClassloader"); // assertTrue("Class should have been identified as a plugin class", loader.isPluginClass(testClass)); // // assertFalse("Class should NOT have been identified as a plugin class", loader.isPluginClass(String.class)); // } }