You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by gt...@apache.org on 2011/06/03 22:37:26 UTC
svn commit: r1131212 - in /river/jtsk/skunk/surrogate: nbproject/
src/org/apache/river/container/ test/org/apache/river/container/
Author: gtrasuk
Date: Fri Jun 3 20:37:26 2011
New Revision: 1131212
URL: http://svn.apache.org/viewvc?rev=1131212&view=rev
Log:
Continued work on the container classloading infrastructure. Now have settable-codebase class loader that uses jar files held in a commons-vfs file system, as will be required when loading classes from a surrogate jar without unpacking.
Added:
river/jtsk/skunk/surrogate/nbproject/build-impl.xml~
- copied unchanged from r1044769, incubator/river/jtsk/skunk/surrogate/nbproject/build-impl.xml
Modified:
river/jtsk/skunk/surrogate/src/org/apache/river/container/LocalizedRuntimeException.java
river/jtsk/skunk/surrogate/src/org/apache/river/container/MessageNames.java
river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties
river/jtsk/skunk/surrogate/src/org/apache/river/container/Strings.java
river/jtsk/skunk/surrogate/src/org/apache/river/container/VirtualFileSystemClassLoader.java
river/jtsk/skunk/surrogate/test/org/apache/river/container/VFSClassLoaderTest.java
Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/LocalizedRuntimeException.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/LocalizedRuntimeException.java?rev=1131212&r1=1131211&r2=1131212&view=diff
==============================================================================
--- river/jtsk/skunk/surrogate/src/org/apache/river/container/LocalizedRuntimeException.java (original)
+++ river/jtsk/skunk/surrogate/src/org/apache/river/container/LocalizedRuntimeException.java Fri Jun 3 20:37:26 2011
@@ -29,6 +29,18 @@ import java.util.ResourceBundle;
public class LocalizedRuntimeException extends RuntimeException {
private String messageBundleName;
private String messageKey;
+
+ public String getMessageBundleName() {
+ return messageBundleName;
+ }
+
+ public String getMessageKey() {
+ return messageKey;
+ }
+
+ public Object[] getMessageParameters() {
+ return messageParameters;
+ }
private Object[] messageParameters;
/**
@@ -54,7 +66,7 @@ public class LocalizedRuntimeException e
public LocalizedRuntimeException(Throwable rootCause,
String messageBundleName,
String messageKey,
- Object[] messageParameters) {
+ Object ... messageParameters) {
super(rootCause);
this.messageBundleName=messageBundleName;
this.messageKey=messageKey;
Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/MessageNames.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/MessageNames.java?rev=1131212&r1=1131211&r2=1131212&view=diff
==============================================================================
--- river/jtsk/skunk/surrogate/src/org/apache/river/container/MessageNames.java (original)
+++ river/jtsk/skunk/surrogate/src/org/apache/river/container/MessageNames.java Fri Jun 3 20:37:26 2011
@@ -52,6 +52,7 @@ public class MessageNames {
ILLEGAL_ARGUMENT_EXCEPTION="illegalArgumentException",
ILLEGAL_ACCESS_EXCEPTION="illegalAccessException",
INITIALIZATION_EXCEPTION="initializationException",
+ INVALID_CLASSPATH_ENTRY="invalidClasspathEntry",
INVOCATION_TARGET_EXCEPTION="invocationTargetException",
INIT_METHOD_HAS_PARAMETERS="initMethodHasParameters",
INIT_METHOD_NOT_VOID="initMethodIsntVoid",
Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties?rev=1131212&r1=1131211&r2=1131212&view=diff
==============================================================================
--- river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties (original)
+++ river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties Fri Jun 3 20:37:26 2011
@@ -30,6 +30,7 @@ exceptionThrown=Exception thrown:
failedDeployService=Deployment of service archive at ''{0}'' failed.
illegalArgumentException=An operation threw an IllegalArgumentException.
illegalAccessException=An operation threw an IllegalAccessException.
+invalidClasspathEntry=Invalid classpath entry: {0}
invocationTargetException=An operation threw an InvocationTargetException.
initializationException=An exception has occured while initializing the container.
initMethodHasParameters=A method flagged as @Init must take no parameters. \
Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/Strings.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/Strings.java?rev=1131212&r1=1131211&r2=1131212&view=diff
==============================================================================
--- river/jtsk/skunk/surrogate/src/org/apache/river/container/Strings.java (original)
+++ river/jtsk/skunk/surrogate/src/org/apache/river/container/Strings.java Fri Jun 3 20:37:26 2011
@@ -33,6 +33,8 @@ public class Strings {
DASH = "-",
DEFAULT = "default",
DEFAULT_DISCOVERY_CONTEXT = "defaultDiscoveryContext",
+ DOT=".",
+ DOT_CLASS=".class",
DOT_SSAR=".ssar",
EMPTY = "",
INIT_COMPLETE="initComplete",
@@ -42,6 +44,7 @@ public class Strings {
PUT = "put",
SSAR="ssar",
SET = "set",
+ SLASH="/",
TYPE="type",
WHITESPACE_SEPARATORS=" \t\n\r",
WORK="work";
Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/VirtualFileSystemClassLoader.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/VirtualFileSystemClassLoader.java?rev=1131212&r1=1131211&r2=1131212&view=diff
==============================================================================
--- river/jtsk/skunk/surrogate/src/org/apache/river/container/VirtualFileSystemClassLoader.java (original)
+++ river/jtsk/skunk/surrogate/src/org/apache/river/container/VirtualFileSystemClassLoader.java Fri Jun 3 20:37:26 2011
@@ -5,9 +5,16 @@
package org.apache.river.container;
+import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileUtil;
/**
*
@@ -15,11 +22,114 @@ import org.apache.commons.vfs.FileObject
*/
public class VirtualFileSystemClassLoader extends URLClassLoader {
+ private FileObject fileSystemRoot=null;
+
+ private List<FileObject> classpathFileObjects=new ArrayList<FileObject>();
+
public VirtualFileSystemClassLoader(FileObject fileSystemRoot, ClassLoader parent) {
super(new URL[0], parent);
+ this.fileSystemRoot=fileSystemRoot;
+ }
+
+ void addClassPathEntry(String fileName) {
+ try {
+ /* Classpath entry is a jar file. */
+ /* Create a nested file system from it and add it to the file objects.
+ */
+ FileObject entryObject = fileSystemRoot.resolveFile(fileName);
+ FileObject entryFileSystem=
+ fileSystemRoot.getFileSystem().getFileSystemManager()
+ .createFileSystem(entryObject);
+ classpathFileObjects.add(entryFileSystem);
+ } catch (FileSystemException ex) {
+ throw new LocalizedRuntimeException(ex, MessageNames.BUNDLE_NAME, MessageNames.INVALID_CLASSPATH_ENTRY, fileName);
+ }
}
- void addClassPathEntry(String string) {
+ /**
+ Find a resource by searching through all the classpath entries that have
+ been set up.
+ @param name
+ @return
+ */
+ @Override
+ public URL findResource(String name) {
+ try {
+ return findResourceFileObject(name).getURL();
+ } catch (FileSystemException ex) {
+ Logger.getLogger(VirtualFileSystemClassLoader.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ return null;
+ }
+
+ /**
+ Find the file object for a resource by searching through all the classpath
+ entries that have been set up.
+ @param name
+ @return
+ */
+ public FileObject findResourceFileObject(String name) {
+ for (FileObject cpFileSys:classpathFileObjects) {
+ try {
+ FileObject fo = cpFileSys.resolveFile(name);
+ if (fo!=null &&fo.isReadable()) {
+ return fo;
+ }
+ } catch (FileSystemException ex) {
+ Logger.getLogger(VirtualFileSystemClassLoader.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+ return null;
+ }
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ String resourceName=name.replace(Strings.DOT, Strings.SLASH).concat(Strings.DOT_CLASS);
+ FileObject resourceFileObject=findResourceFileObject(resourceName);
+ if (resourceFileObject==null) {
+ throw new ClassNotFoundException(name+"(" + resourceName + ")");
+ }
+ try {
+ byte[] bytes=FileUtil.getContent(resourceFileObject);
+ return defineClass(name,bytes,0,bytes.length);
+ } catch(IOException ioe) {
+ throw new ClassNotFoundException(name, ioe);
+ }
}
+
+ /**
+ * Set the codebase URLs to an arbitrary list of URLs. These URLs form the
+ * codebase annotation for classes loaded through this classloader.
+ * For the sake of general paranoia, sets the codebase to a copy of the
+ * provided array.
+ * @param codebase
+ */
+ public void setCodebase(URL[] codebase) {
+ if (codebase == null || codebase.length==0) {
+ codebaseURLs = new URL[]{};
+ return;
+ }
+
+ codebaseURLs = new URL[codebase.length];
+ System.arraycopy(codebase, 0, codebaseURLs, 0, codebase.length);
+
+ }
+
+ /**
+ * Get the list of URLs that are used for the codebase annotation.
+ * Note that this list is not the actual classpath (that is in the
+ * superclass). The codebase URLs are imposed to match whatever the Jini
+ * service wants to expose as its codebase annotation.
+ * @return
+ */
+ @Override
+ public URL[] getURLs() {
+ return codebaseURLs;
+ }
+
+ /** Stores the codebase that will be returned as the codebase annotation.
+ *
+ */
+ private URL codebaseURLs[] = new URL[0];
+
}
Modified: river/jtsk/skunk/surrogate/test/org/apache/river/container/VFSClassLoaderTest.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/test/org/apache/river/container/VFSClassLoaderTest.java?rev=1131212&r1=1131211&r2=1131212&view=diff
==============================================================================
--- river/jtsk/skunk/surrogate/test/org/apache/river/container/VFSClassLoaderTest.java (original)
+++ river/jtsk/skunk/surrogate/test/org/apache/river/container/VFSClassLoaderTest.java Fri Jun 3 20:37:26 2011
@@ -4,6 +4,7 @@
*/
package org.apache.river.container;
+import java.net.URL;
import java.io.InputStream;
import java.io.File;
import org.apache.commons.vfs.FileObject;
@@ -23,8 +24,8 @@ import static org.junit.Assert.*;
public class VFSClassLoaderTest {
FileSystemManager fileSystemManager = null;
- FileObject reggieModuleRoot=null;
- ClassLoader extensionLoader=Bootstrap.class.getClassLoader().getParent();
+ FileObject reggieModuleRoot = null;
+ ClassLoader extensionLoader = Bootstrap.class.getClassLoader().getParent();
public VFSClassLoaderTest() {
}
@@ -39,58 +40,117 @@ public class VFSClassLoaderTest {
@Before
public void setUp() throws Exception {
- fileSystemManager=VFS.getManager();
- FileObject currentDir=fileSystemManager.toFileObject(new File("."));
- FileObject reggieModuleJar=
+ fileSystemManager = VFS.getManager();
+ FileObject currentDir = fileSystemManager.toFileObject(new File("."));
+ FileObject reggieModuleJar =
currentDir.resolveFile("../../build/test/files/reggie-module.jar");
- reggieModuleRoot=fileSystemManager.createFileSystem(reggieModuleJar);
+ reggieModuleRoot = fileSystemManager.createFileSystem(reggieModuleJar);
}
@After
public void tearDown() {
-
}
-
+
/**
- Just to make sure that we have the base setup correct, ensure that we
- can read the 'start.properties' file inside the reggie-module jar.
- @throws Exception
+ Just to make sure that we have the base setup correct, ensure that we
+ can read the 'start.properties' file inside the reggie-module jar.
+ @throws Exception
*/
@Test
public void testCanReadStartDotProperties() throws Exception {
- FileObject startProperties=reggieModuleRoot.resolveFile("start.properties");
+ FileObject startProperties = reggieModuleRoot.resolveFile("start.properties");
assertNotNull(startProperties);
- assertTrue("Properties file unreadable:"
+ assertTrue("Properties file unreadable:"
+ startProperties.toString() + " type=" + startProperties.getType(),
startProperties.isReadable());
}
/**
- Create a VFSClassLoader and see if we can read a resource file from it.
- As shown below, we're just adding a classpath entry with no filters or
- codebase.
- @throws Exception
+ Create a VFSClassLoader and make sure it throws an exception if we try
+ to add a non-existent jar file to it.
+ @throws Exception
+ */
+ @Test
+ public void testNonExistentJarFile() throws Exception {
+ VirtualFileSystemClassLoader UUT =
+ new VirtualFileSystemClassLoader(reggieModuleRoot, extensionLoader);
+ try {
+ UUT.addClassPathEntry("nonexistent.jar");
+ fail("Should have thrown an invalid classpath entry exception");
+ } catch (LocalizedRuntimeException ex) {
+ assertEquals(MessageNames.INVALID_CLASSPATH_ENTRY, ex.getMessageKey());
+ }
+ }
+
+ /**
+ Create a VFSClassLoader and see if we can read a resource file from it.
+ As shown below, we're just adding a classpath entry with no filters or
+ codebase.
+ @throws Exception
*/
@Test
public void testClassLoaderResourceLoading() throws Exception {
- VirtualFileSystemClassLoader UUT=
+ VirtualFileSystemClassLoader UUT =
new VirtualFileSystemClassLoader(reggieModuleRoot, extensionLoader);
UUT.addClassPathEntry("reggie.jar");
- InputStream is=UUT.getResourceAsStream("META-INF/PREFERRED.LIST");
+ InputStream is = UUT.getResourceAsStream("META-INF/PREFERRED.LIST");
assertNotNull("Failed to get resource stream for META-INF/PREFERRED.LIST",
is);
}
+ /* Note to self- test for exception cases - bad fsroot, directory not jar, etc.
+ */
+
+ /**
+ The classloader should be able to load a class that's in the jar file,
+ and when we get an instance of that class, it should have the UUT
+ as its classloader.
+ @throws Exception
+ */
@Test
public void testClassLoading() throws Exception {
+ VirtualFileSystemClassLoader UUT =
+ new VirtualFileSystemClassLoader(reggieModuleRoot, extensionLoader);
+ UUT.addClassPathEntry("reggie.jar");
+ Class c = UUT.loadClass("com.sun.jini.reggie.ClassMapper");
+ assertNotNull(c);
+ assertTrue("Class had wrong classloader:" + c.getClassLoader(),
+ c.getClassLoader()==UUT);
+ }
- fail("Write me. Should test that we can load a class.");
+ /**
+ The classloader should be able to load a class that's in the jar file,
+ and when we get an instance of that class, it should have the UUT
+ as its classloader.
+ @throws Exception
+ */
+ @Test
+ public void testParentClassLoading() throws Exception {
+ VirtualFileSystemClassLoader UUT =
+ new VirtualFileSystemClassLoader(reggieModuleRoot, extensionLoader);
+ UUT.addClassPathEntry("reggie.jar");
+ Class c = UUT.loadClass("java.util.List");
+ assertNotNull(c);
+ assertTrue("Class had wrong classloader:" + c.getClassLoader(),
+ c.getClassLoader()==null);
+ assertTrue("java.util.List".equals(c.getName()));
}
@Test
public void testCodebaseAnnotation() throws Exception {
- fail("Write me. Should test that the codebase annotation can be set"
- + " externally.");
+ VirtualFileSystemClassLoader UUT =
+ new VirtualFileSystemClassLoader(reggieModuleRoot, extensionLoader);
+ UUT.addClassPathEntry("reggie.jar");
+ /* At this point, there should be no urls on the reported codebase. */
+ URL[] actual=UUT.getURLs();
+ assertTrue("Should be no urls, but got " + Utils.format(actual),
+ actual.length==0);
+ URL[] a={ new URL("http://localhost:8080/a.jar")};
+ UUT.setCodebase(a);
+ actual=UUT.getURLs();
+ assertEquals("Should be one urls, but got " + Utils.format(actual),
+ 1, actual.length);
+
}
@Test