Merge sources from S-Core's RSA git (release)
[sdk/ide/common-eplugin.git] / org.tizen.common / test / src / org / tizen / common / UnsafeClassLoader.java
1 /*
2  * 
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: 
7  * BonYong Lee <bonyong.lee@samsung.com>
8  * 
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Contributors:
22  * - S-Core Co., Ltd
23  *
24  */
25 package org.tizen.common;
26
27 import static org.tizen.common.util.IOUtil.getBytes;
28 import static org.tizen.common.util.IOUtil.tryClose;
29
30 import java.io.ByteArrayInputStream;
31 import java.io.File;
32 import java.io.FileOutputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.lang.instrument.ClassFileTransformer;
36 import java.lang.instrument.IllegalClassFormatException;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42 import org.tizen.common.util.IOUtil;
43
44
45 /**
46  * <p>
47  * UnsafeClassLoader.
48  * 
49  * Classloader for untestable class
50  * 
51  * FIXME add {@link Package} info and {@link #getResource(String)}, {@link #getResourceAsStream(String)}, {@link #getResources(String)}
52  * </p>
53  * 
54  * @author BonYong Lee{@literal <bonyong.lee@samsung.com>} (S-Core)
55  */
56 public class
57 UnsafeClassLoader
58 extends ClassLoader
59 {
60         /**
61          * Logger for this instance
62          */
63         protected final Logger logger = LoggerFactory.getLogger( getClass() );
64         
65         /**
66          * Parent classloader
67          */
68         protected final ClassLoader parent;
69         
70         protected ClassFileTransformer transformer = new Transformer();
71
72         /**
73          * {@link ClassSource}s providing class contents
74          */
75         protected final ArrayList<ClassSource> sources = new ArrayList<ClassSource>();
76
77         /**
78          * Constructor with {@link ClassSource}s
79          * @param source
80          */
81         public
82         UnsafeClassLoader(
83                 final ClassSource... source
84         )
85         {
86                 this( null, source );
87         }
88
89         /**
90          * Constructor with parent class loader and class source
91          * 
92          * @param parent {@link ClassLoader}
93          * @param sources {@link ClassSource}s
94          */
95         public
96         UnsafeClassLoader(
97                 final ClassLoader parent,
98                 final ClassSource... sources
99         )
100         {
101                 this.parent = parent;
102                 this.sources.addAll( Arrays.asList( sources ) );
103         }
104
105         /* (non-Javadoc)
106          * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
107          */
108         @Override
109         synchronized protected
110         Class<?>
111         loadClass(
112                 final String name,
113                 final boolean resolve
114         )
115         throws ClassNotFoundException
116         {
117                 // First, check if the class has already been loaded
118                 Class<?> c = findLoadedClass( name );
119                 if ( c == null )
120                 {
121                         if ( name.startsWith( "java." ) )
122                         {
123                                 return ClassLoader.getSystemClassLoader().loadClass( name );
124                         }
125                         try
126                         {
127                                 c = findClass( name );
128                         } catch (ClassNotFoundException e) {
129                                 if ( null != parent )
130                                 {
131                                         c = parent.loadClass( name );
132                                 }
133                                 else
134                                 {
135                                         throw new ClassNotFoundException();
136                                 }
137                         }
138                 }
139                 if ( resolve )
140                 {
141                         resolveClass( c );
142                 }
143                 return c;
144         }
145
146         /* (non-Javadoc)
147          * @see java.lang.ClassLoader#findClass(java.lang.String)
148          */
149         @Override
150         protected
151         Class<?>
152         findClass(
153                 final String name
154         )
155         throws ClassNotFoundException
156         {
157                 logger.trace( "Class name :{}", name );
158                 final String path = name.replace( '.', '/' ) + ".class";
159                 for ( final ClassSource source : sources )
160                 {
161                         logger.trace( "Source :{}", source );
162                         InputStream in = null;;
163                         try
164                         {
165                                 in = source.getResource( path );
166                                 final Class<?> clazz = define( name, in );
167                                 if ( null != clazz )
168                                 {
169                                         return clazz;
170                                 }
171                         }
172                         catch ( final IOException e )
173                         {
174                         }
175                         finally
176                         {
177                                 tryClose( in );
178                         }
179                 }
180                 
181 //              final ClassLoader loader = getClass().getClassLoader();
182 //              
183 //              final InputStream in = loader.getResourceAsStream( path );
184 //              try
185 //              {
186 //                      final Class<?> clazz = define( name, in );
187 //                      if ( null != clazz )
188 //                      {
189 //                              return clazz;
190 //                      }
191 //              }
192 //              finally
193 //              {
194 //                      tryClose( in );
195 //              }
196 //
197                 throw new ClassNotFoundException();
198
199         }
200         
201         protected Class<?> define(
202                 final String name,
203                 final InputStream in
204         )
205         {
206                 try {
207                         if ( null == in )
208                         {
209                                 return null;
210                         }
211                         byte[] bytes = getBytes( in );
212                         final String qn = name.replace( '.', '/' );
213                         bytes = transformer.transform( this, qn, null, null, bytes );
214                         logger.trace( "{} bytes read", bytes.length );
215                         return defineClass( name, bytes, 0, bytes.length );
216                 } catch ( final IOException e )
217                 {
218                 } catch ( final IllegalClassFormatException e )
219                 {
220                 }
221                 
222                 return null;
223         }
224
225         /**
226          * Write log file about converted class
227          * 
228          * @param path file path to write
229          * @param bytes class contents
230          * 
231          * @throws IOException If file can't be write
232          */
233         protected
234         void
235         writeLog(
236                 final String path,
237                 byte[] bytes
238         )
239         throws IOException
240         {
241                 FileOutputStream fileOut = null;
242                 try
243                 {
244                         File logFile = new File( "test/log/" + path );
245                         logFile.getParentFile().mkdirs();
246                         fileOut = new FileOutputStream( logFile );
247                         IOUtil.redirect( new ByteArrayInputStream( bytes ), fileOut );
248                 }
249                 finally
250                 {
251                         tryClose( fileOut);
252                 }
253         }
254
255 }