Author: simonetripodi Date: Fri Sep 7 18:03:12 2012 New Revision: 1382106 URL: http://svn.apache.org/viewvc?rev=1382106&view=rev Log: [DIGESTER-169] Problem when including rules XML file with classpath: URL prefix - patch submitted by Eugene Fedotov
Modified: commons/proper/digester/trunk/core/src/main/java/org/apache/commons/digester3/binder/BinderClassLoader.java commons/proper/digester/trunk/core/src/test/java/org/apache/commons/digester3/binder/BinderClassLoaderTestCase.java commons/proper/digester/trunk/src/changes/changes.xml Modified: commons/proper/digester/trunk/core/src/main/java/org/apache/commons/digester3/binder/BinderClassLoader.java URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/core/src/main/java/org/apache/commons/digester3/binder/BinderClassLoader.java?rev=1382106&r1=1382105&r2=1382106&view=diff ============================================================================== --- commons/proper/digester/trunk/core/src/main/java/org/apache/commons/digester3/binder/BinderClassLoader.java (original) +++ commons/proper/digester/trunk/core/src/main/java/org/apache/commons/digester3/binder/BinderClassLoader.java Fri Sep 7 18:03:12 2012 @@ -22,6 +22,7 @@ package org.apache.commons.digester3.bin import static java.lang.System.getSecurityManager; import static java.security.AccessController.doPrivileged; +import java.net.URL; import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashMap; @@ -89,4 +90,13 @@ final class BinderClassLoader return getParent().loadClass( name ); } + /** + * {@inheritDoc} + */ + @Override + public URL getResource( String name ) + { + return getAdaptedClassLoader().getResource( name ); + } + } Modified: commons/proper/digester/trunk/core/src/test/java/org/apache/commons/digester3/binder/BinderClassLoaderTestCase.java URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/core/src/test/java/org/apache/commons/digester3/binder/BinderClassLoaderTestCase.java?rev=1382106&r1=1382105&r2=1382106&view=diff ============================================================================== --- commons/proper/digester/trunk/core/src/test/java/org/apache/commons/digester3/binder/BinderClassLoaderTestCase.java (original) +++ commons/proper/digester/trunk/core/src/test/java/org/apache/commons/digester3/binder/BinderClassLoaderTestCase.java Fri Sep 7 18:03:12 2012 @@ -20,10 +20,26 @@ package org.apache.commons.digester3.bin */ import static org.apache.commons.digester3.binder.BinderClassLoader.createBinderClassLoader; -import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertArrayEquals; +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.assertSame; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; +import java.util.HashMap; +import java.util.Map; import org.junit.Test; @@ -33,7 +49,7 @@ import org.junit.Test; public final class BinderClassLoaderTestCase { - private ClassLoader classLoader = createBinderClassLoader( getClass().getClassLoader() ); + private BinderClassLoader classLoader = createBinderClassLoader( new ExtendedClassLoader() ); @Test public void loadBoolean() @@ -119,4 +135,172 @@ public final class BinderClassLoaderTest assertNotNull( binderCl.getResource( "xxx" ) ); } + @Test + public void testLoadClass() + throws Exception + { + Class<?> dummyClass1 = Dummy.class; + Class<?> dummyClass2 = classLoader.loadClass( dummyClass1.getName() ); + + assertEquals( dummyClass1.getName(), dummyClass2.getName() ); + assertFalse( dummyClass2.getDeclaredConstructor().newInstance() instanceof Dummy ); + assertNotSame( dummyClass1, dummyClass2 ); + assertNotSame( dummyClass1.getClassLoader(), dummyClass2.getClassLoader() ); + assertSame( classLoader.getAdaptedClassLoader(), dummyClass2.getClassLoader() ); + } + + @Test + public void testGetPrefixedResource() + throws Exception + { + URL resource = classLoader.getResource( "inmemory:dummyResource" ); + assertNotNull( resource ); + assertEquals( resource.getPath(), "dummyResource" ); + InputStream input = resource.openStream(); + try + { + byte[] bytes = toByteArray( input ); + assertArrayEquals( bytes, IN_MEMORY_RESOURCES.get( "dummyResource" ) ); + } + finally + { + input.close(); + } + } + + private static byte[] toByteArray( InputStream input ) + throws IOException + { + ByteArrayOutputStream result = new ByteArrayOutputStream( 512 ); + int n; + while ( ( n = input.read() ) != -1 ) + { + result.write( n ); + } + return result.toByteArray(); + } + + private static final Map<String, byte[]> IN_MEMORY_RESOURCES = new HashMap<String, byte[]>(); + + static + { + try + { + IN_MEMORY_RESOURCES.put( "dummyResource", "Resource data".getBytes( "UTF-8" ) ); + + // put bytes of Dummy class + String dummyClassName = Dummy.class.getName(); + String resourceName = dummyClassName.replace( '.', '/' ) + ".class"; + InputStream input = Dummy.class.getClassLoader().getResourceAsStream( resourceName ); + try + { + IN_MEMORY_RESOURCES.put( resourceName, toByteArray( input ) ); + } + finally + { + input.close(); + } + } + catch ( UnsupportedEncodingException e ) + { + throw new ExceptionInInitializerError( e ); + } + catch ( IOException e ) + { + throw new ExceptionInInitializerError( e ); + } + } + + private static class ExtendedClassLoader + extends ClassLoader + { + + private final InMemoryURLStreamHandlerFactory streamHandlerFactory = new InMemoryURLStreamHandlerFactory(); + + @Override + protected Class<?> loadClass( String name, boolean resolve ) + throws ClassNotFoundException + { + String dummyClassName = Dummy.class.getName(); + if ( dummyClassName.equals( name ) ) { + Class<?> result = findLoadedClass( name ); + if ( result == null ) + { + byte[] byteCode = IN_MEMORY_RESOURCES.get( dummyClassName.replace( '.', '/' ) + ".class" ); + result = defineClass( name, byteCode, 0, byteCode.length ); + resolveClass( result ); + } + return result; + } + return super.loadClass( name, resolve ); + } + + @Override + public URL getResource( String name ) + { + if ( name.startsWith( "inmemory:" ) ) + { + try + { + return new URL( null, name, streamHandlerFactory.createURLStreamHandler( "inmemory" ) ); + } + catch ( MalformedURLException e ) + { + throw new RuntimeException( e ); + } + } + return super.getResource( name ); + } + + private static class InMemoryURLStreamHandlerFactory + implements URLStreamHandlerFactory + { + public URLStreamHandler createURLStreamHandler( String protocol ) + { + return new URLStreamHandler() + { + @Override + protected URLConnection openConnection( URL u ) + throws IOException + { + return new URLConnection( u ) + { + private InputStream inputStream; + + @Override + public void connect() + throws IOException + { + if ( !connected ) { + byte[] data = IN_MEMORY_RESOURCES.get( url.getPath() ); + if ( data != null ) + { + inputStream = new ByteArrayInputStream( data ); + } + connected = true; + } + } + + @Override + public InputStream getInputStream() + throws IOException + { + connect(); + if ( inputStream == null ) + { + throw new FileNotFoundException( url.getPath() ); + } + return inputStream; + } + }; + } + }; + } + } + } + + public static class Dummy + { + } + } Modified: commons/proper/digester/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/changes/changes.xml?rev=1382106&r1=1382105&r2=1382106&view=diff ============================================================================== --- commons/proper/digester/trunk/src/changes/changes.xml (original) +++ commons/proper/digester/trunk/src/changes/changes.xml Fri Sep 7 18:03:12 2012 @@ -23,8 +23,8 @@ </properties> <body> <release version="3.3" date="201?-??-??" description="Maintenance release."> - <action dev="elijah" type="fix" issue="DIGESTER-166"> - Link to core APIs page in documentation was broken + <action dev="simonetripodi" type="fix" issue="DIGESTER-169" due-to="Eugene Fedotov"> + Problem when including rules XML file with "classpath:" URL prefix </action> <action dev="simonetripodi" type="fix" issue="DIGESTER-165" due-to="Dirk Schaube"> BinderClassLoader does not override getResource