View Javadoc

1   package org.apache.commons.digester3.binder;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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   * DIGESTER-155
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             // 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 }