1 package org.apache.commons.digester3.binder;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import static org.apache.commons.digester3.binder.BinderClassLoader.createBinderClassLoader;
23 import static org.junit.Assert.assertArrayEquals;
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertFalse;
26 import static org.junit.Assert.assertNotNull;
27 import static org.junit.Assert.assertNotSame;
28 import static org.junit.Assert.assertSame;
29
30 import java.io.ByteArrayInputStream;
31 import java.io.ByteArrayOutputStream;
32 import java.io.FileNotFoundException;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.UnsupportedEncodingException;
36 import java.net.MalformedURLException;
37 import java.net.URL;
38 import java.net.URLConnection;
39 import java.net.URLStreamHandler;
40 import java.net.URLStreamHandlerFactory;
41 import java.util.HashMap;
42 import java.util.Map;
43
44 import org.junit.Test;
45
46
47
48
49 public final class BinderClassLoaderTestCase
50 {
51
52 private BinderClassLoader classLoader = createBinderClassLoader( new ExtendedClassLoader() );
53
54 @Test
55 public void loadBoolean()
56 throws Exception
57 {
58 typeFound( "boolean", boolean.class );
59 }
60
61 @Test
62 public void loadByte()
63 throws Exception
64 {
65 typeFound( "byte", byte.class );
66 }
67
68 @Test
69 public void loadShort()
70 throws Exception
71 {
72 typeFound( "short", short.class );
73 }
74
75 @Test
76 public void loadInt()
77 throws Exception
78 {
79 typeFound( "int", int.class );
80 }
81
82 @Test
83 public void loadChar()
84 throws Exception
85 {
86 typeFound( "char", char.class );
87 }
88
89 @Test
90 public void loadLong()
91 throws Exception
92 {
93 typeFound( "long", long.class );
94 }
95
96 @Test
97 public void loadFloat()
98 throws Exception
99 {
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
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 }