/*
* 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));
// }
}