001package org.apache.commons.digester3.binder; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import static org.apache.commons.digester3.binder.BinderClassLoader.createBinderClassLoader; 023import static org.junit.Assert.assertArrayEquals; 024import static org.junit.Assert.assertEquals; 025import static org.junit.Assert.assertFalse; 026import static org.junit.Assert.assertNotNull; 027import static org.junit.Assert.assertNotSame; 028import static org.junit.Assert.assertSame; 029 030import java.io.ByteArrayInputStream; 031import java.io.ByteArrayOutputStream; 032import java.io.FileNotFoundException; 033import java.io.IOException; 034import java.io.InputStream; 035import java.io.UnsupportedEncodingException; 036import java.net.MalformedURLException; 037import java.net.URL; 038import java.net.URLConnection; 039import java.net.URLStreamHandler; 040import java.net.URLStreamHandlerFactory; 041import java.util.HashMap; 042import java.util.Map; 043 044import org.junit.Test; 045 046/** 047 * DIGESTER-155 048 */ 049public final class BinderClassLoaderTestCase 050{ 051 052 private BinderClassLoader classLoader = createBinderClassLoader( new ExtendedClassLoader() ); 053 054 @Test 055 public void loadBoolean() 056 throws Exception 057 { 058 typeFound( "boolean", boolean.class ); 059 } 060 061 @Test 062 public void loadByte() 063 throws Exception 064 { 065 typeFound( "byte", byte.class ); 066 } 067 068 @Test 069 public void loadShort() 070 throws Exception 071 { 072 typeFound( "short", short.class ); 073 } 074 075 @Test 076 public void loadInt() 077 throws Exception 078 { 079 typeFound( "int", int.class ); 080 } 081 082 @Test 083 public void loadChar() 084 throws Exception 085 { 086 typeFound( "char", char.class ); 087 } 088 089 @Test 090 public void loadLong() 091 throws Exception 092 { 093 typeFound( "long", long.class ); 094 } 095 096 @Test 097 public void loadFloat() 098 throws Exception 099 { 100 typeFound( "float", float.class ); 101 } 102 103 @Test 104 public void loadDouble() 105 throws Exception 106 { 107 typeFound( "double", double.class ); 108 } 109 110 private void typeFound( String name, Class<?> expected ) 111 throws Exception 112 { 113 Class<?> actual = classLoader.loadClass( name ); 114 assertSame( expected, actual ); 115 } 116 117 @Test 118 public void testGetResource() 119 { 120 ClassLoader clToAdapt = new ClassLoader() 121 { 122 123 @Override 124 public URL getResource( String name ) 125 { 126 if ( "xxx".equals( name ) ) 127 { 128 return super.getResource( "org/apache/commons/digester3/binder/BinderClassLoaderTestCase.class" ); 129 } 130 return super.getResource( name ); 131 } 132 133 }; 134 ClassLoader binderCl = createBinderClassLoader( clToAdapt ); 135 assertNotNull( binderCl.getResource( "xxx" ) ); 136 } 137 138 @Test 139 public void testLoadClass() 140 throws Exception 141 { 142 Class<?> dummyClass1 = Dummy.class; 143 Class<?> dummyClass2 = classLoader.loadClass( dummyClass1.getName() ); 144 145 assertEquals( dummyClass1.getName(), dummyClass2.getName() ); 146 assertFalse( dummyClass2.getDeclaredConstructor().newInstance() instanceof Dummy ); 147 assertNotSame( dummyClass1, dummyClass2 ); 148 assertNotSame( dummyClass1.getClassLoader(), dummyClass2.getClassLoader() ); 149 assertSame( classLoader.getAdaptedClassLoader(), dummyClass2.getClassLoader() ); 150 } 151 152 @Test 153 public void testGetPrefixedResource() 154 throws Exception 155 { 156 URL resource = classLoader.getResource( "inmemory:dummyResource" ); 157 assertNotNull( resource ); 158 assertEquals( resource.getPath(), "dummyResource" ); 159 InputStream input = resource.openStream(); 160 try 161 { 162 byte[] bytes = toByteArray( input ); 163 assertArrayEquals( bytes, IN_MEMORY_RESOURCES.get( "dummyResource" ) ); 164 } 165 finally 166 { 167 input.close(); 168 } 169 } 170 171 private static byte[] toByteArray( InputStream input ) 172 throws IOException 173 { 174 ByteArrayOutputStream result = new ByteArrayOutputStream( 512 ); 175 int n; 176 while ( ( n = input.read() ) != -1 ) 177 { 178 result.write( n ); 179 } 180 return result.toByteArray(); 181 } 182 183 private static final Map<String, byte[]> IN_MEMORY_RESOURCES = new HashMap<String, byte[]>(); 184 185 static 186 { 187 try 188 { 189 IN_MEMORY_RESOURCES.put( "dummyResource", "Resource data".getBytes( "UTF-8" ) ); 190 191 // put bytes of Dummy class 192 String dummyClassName = Dummy.class.getName(); 193 String resourceName = dummyClassName.replace( '.', '/' ) + ".class"; 194 InputStream input = Dummy.class.getClassLoader().getResourceAsStream( resourceName ); 195 try 196 { 197 IN_MEMORY_RESOURCES.put( resourceName, toByteArray( input ) ); 198 } 199 finally 200 { 201 input.close(); 202 } 203 } 204 catch ( UnsupportedEncodingException e ) 205 { 206 throw new ExceptionInInitializerError( e ); 207 } 208 catch ( IOException e ) 209 { 210 throw new ExceptionInInitializerError( e ); 211 } 212 } 213 214 private static class ExtendedClassLoader 215 extends ClassLoader 216 { 217 218 private final InMemoryURLStreamHandlerFactory streamHandlerFactory = new InMemoryURLStreamHandlerFactory(); 219 220 @Override 221 protected Class<?> loadClass( String name, boolean resolve ) 222 throws ClassNotFoundException 223 { 224 String dummyClassName = Dummy.class.getName(); 225 if ( dummyClassName.equals( name ) ) { 226 Class<?> result = findLoadedClass( name ); 227 if ( result == null ) 228 { 229 byte[] byteCode = IN_MEMORY_RESOURCES.get( dummyClassName.replace( '.', '/' ) + ".class" ); 230 result = defineClass( name, byteCode, 0, byteCode.length ); 231 resolveClass( result ); 232 } 233 return result; 234 } 235 return super.loadClass( name, resolve ); 236 } 237 238 @Override 239 public URL getResource( String name ) 240 { 241 if ( name.startsWith( "inmemory:" ) ) 242 { 243 try 244 { 245 return new URL( null, name, streamHandlerFactory.createURLStreamHandler( "inmemory" ) ); 246 } 247 catch ( MalformedURLException e ) 248 { 249 throw new RuntimeException( e ); 250 } 251 } 252 return super.getResource( name ); 253 } 254 255 private static class InMemoryURLStreamHandlerFactory 256 implements URLStreamHandlerFactory 257 { 258 public URLStreamHandler createURLStreamHandler( String protocol ) 259 { 260 return new URLStreamHandler() 261 { 262 @Override 263 protected URLConnection openConnection( URL u ) 264 throws IOException 265 { 266 return new URLConnection( u ) 267 { 268 private InputStream inputStream; 269 270 @Override 271 public void connect() 272 throws IOException 273 { 274 if ( !connected ) { 275 byte[] data = IN_MEMORY_RESOURCES.get( url.getPath() ); 276 if ( data != null ) 277 { 278 inputStream = new ByteArrayInputStream( data ); 279 } 280 connected = true; 281 } 282 } 283 284 @Override 285 public InputStream getInputStream() 286 throws IOException 287 { 288 connect(); 289 if ( inputStream == null ) 290 { 291 throw new FileNotFoundException( url.getPath() ); 292 } 293 return inputStream; 294 } 295 }; 296 } 297 }; 298 } 299 } 300 } 301 302 public static class Dummy 303 { 304 } 305 306}