001    /*
002      Renaud Pawlak, pawlak@cnam.fr, CEDRIC Laboratory, Paris, France.
003      Lionel Seinturier, Lionel.Seinturier@lip6.fr, LIP6, Paris, France.
004    
005      JAC-Core is free software. You can redistribute it and/or modify it
006      under the terms of the GNU Library General Public License as
007      published by the Free Software Foundation.
008      
009      JAC-Core is distributed in the hope that it will be useful, but
010      WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
012    
013      This work uses the Javassist system - Copyright (c) 1999-2000
014      Shigeru Chiba, University of Tsukuba, Japan.  All Rights Reserved.  */
015    
016    package org.objectweb.jac.core.utils;
017    
018    import java.io.ByteArrayInputStream;
019    import java.io.ByteArrayOutputStream;
020    import java.io.BufferedInputStream;
021    import java.io.File;
022    import java.io.FileInputStream;
023    import java.io.InputStream;
024    import java.io.ObjectInputStream;
025    import java.io.ObjectOutputStream;
026    import java.io.OutputStream;
027    import java.lang.reflect.Field;
028    
029    import java.util.Enumeration;
030    import java.util.Hashtable;
031    import java.util.StringTokenizer;
032    import java.util.Vector;
033    
034    
035    /**
036     * Lib is a container class for various utility method used by org.objectweb.jac.
037     *
038     * None of these methods is attached to any particular jac files but
039     * should be, in an ideal world, provided by the JDK.
040     */
041     
042     
043    public class Lib {
044    
045       /**
046        * Execute a command in a process and dump its standard output and error.
047        *
048        * @param command  the command to execute
049        */
050       
051       public static void exec(String command) {
052       
053           Runtime runtime = Runtime.getRuntime();
054           
055           try {
056              
057              Process p = runtime.exec(command);
058              
059              byte[] buf = new byte[1024];
060              int len;
061              
062              
063              /** Dump the output stream of the process */
064              
065              InputStream in = new BufferedInputStream( p.getInputStream() );
066              for ( len=in.read(buf) ; len != -1 ; len=in.read(buf) )
067                 System.out.write( buf, 0, len );
068              
069    
070              /** Dump the error stream of the process */
071              
072              in = new BufferedInputStream( p.getErrorStream() );
073              for ( len=in.read(buf) ; len != -1 ; len=in.read(buf) )
074                 System.err.write( buf, 0, len );
075              
076              
077              /** Wait for the end of the process */
078              
079              p.waitFor();
080              
081            }
082            catch ( Exception e ) {
083               e.printStackTrace();
084               System.exit(1);
085            }
086       }
087       
088       
089       /**
090        * Transform strings stored as a enumeration object into
091        * a space-separated string.
092        *
093        * @param stringsEnum  the enumeration object containing the strings
094        * @return             a space-separated string composed of
095        *                     the string contained in <I>stringsEnum</I>
096        */
097       
098       public static String stringsEnumToString(Enumeration stringsEnum) {
099       
100          String str = "";
101          
102          while ( stringsEnum.hasMoreElements() ) {
103             str += (String) stringsEnum.nextElement() + " ";
104          }
105          
106          return str;
107       }
108    
109    
110       /**
111        * Transform strings stored as a enumeration object into
112        * an array of strings.
113        *
114        * @param stringsEnum  the enumeration object containing the strings
115        * @return             an array of strings composed of
116        *                     the string contained in <I>stringsEnum</I>
117        */
118       
119       public static String[] stringsEnumToStringArray(Enumeration stringsEnum) {
120       
121          String str = stringsEnumToString(stringsEnum);     
122          StringTokenizer strTok = new StringTokenizer(str);
123          int len = strTok.countTokens();
124          
125          String[] strArray = new String[len];
126          
127          for (int i=0; i<len ; i++) {
128             strArray[i] = new String(strTok.nextToken());
129          }
130          
131          return strArray;
132       }
133    
134    
135       /**
136        * Transform object stored as a enumeration object into
137        * an array of object.
138        *
139        * @param enum  the enumeration object containing the objects
140        * @return      an array of objects composed of
141        *              the objects contained in <I>enum</I>
142        */
143       
144       public static Object[] enumToArray(Enumeration enum) {
145       
146          Vector elements = new Vector();
147          
148          while ( enum.hasMoreElements() )
149             elements.add( enum.nextElement() );
150       
151          return elements.toArray();
152       }
153    
154    
155       /**
156        * Transform a string composed of substrings separated by spaces into
157        * an array composed of the substrings.
158        *
159        * @param str the string composed of substrings separated by spaces 
160        * @return an array composed of the substrings
161        */
162       
163       public static String[] stringToStringArray(String str) {
164       
165          StringTokenizer strTok = new StringTokenizer(str);
166          int len = strTok.countTokens();
167          
168          String[] strArray = new String[len];
169          
170          for (int i=0; i<len ; i++) {
171             strArray[i] = new String(strTok.nextToken());
172          }
173          
174          return strArray;
175       }
176    
177    
178       /**
179        * Store a string array into a hashtable.
180        *
181        * @param strs  the string array
182        * @return      the hashtable
183        */
184       
185       public static Hashtable stringArrayToHashtable(String[] strs) {
186       
187          Hashtable ret = new Hashtable();
188          
189          for (int i=0; i<strs.length; i++) {
190             ret.put(strs[i], "");
191          }
192          
193          return ret;
194       }
195    
196    
197       /**
198        * Return the byte code contained in file
199        * <I>dirName</I>.<I>fileName</I>.class
200        *
201        * @param dirName   the directory where the file is stored
202        * @param fileName  the file name
203        * @return          the byte code
204        */
205       
206       public static byte[] loadByteCodeFromFile(String dirName, String fileName)
207       {
208       
209          byte[] byteCode = null;
210       
211          try {
212          
213             String fullFileName =
214                dirName + new String(fileName).replace('.','/') + ".class";
215    
216             File file = new File( fullFileName );
217             long fileSize = file.length();
218             if ( fileSize == 0 )  return null;
219             
220             byteCode = new byte[ (int) fileSize ];
221             InputStream in = new BufferedInputStream( new FileInputStream(file) );
222             if ( in.read(byteCode) != fileSize )  return null;
223    
224          }
225          catch( Exception e ) { e.printStackTrace(); }
226    
227          return byteCode;
228       }
229    
230       
231       /**
232        * Serialize an object into an array of bytes.
233        *
234        * @param src  the object to serialize
235        * @return     an array of bytes
236        */
237        
238       public static byte[] serialize(Object src) {
239       
240          return serialize(src, ObjectOutputStream.class);
241       }
242       
243       
244       /**
245        * Serialize an object into an array of bytes.
246        *
247        * @param src       the object to serialize
248        * @param oosClass  the subclass of ObjectOutputStream
249        *                  to use for serializing src
250        * @return          an array of bytes
251        */
252        
253       public static byte[] serialize(Object src, Class oosClass) {
254    
255          ByteArrayOutputStream baos = new ByteArrayOutputStream();
256          
257          ObjectOutputStream oos = null;
258          byte[] ret = null;
259          
260          try {
261          
262             oos = 
263                (ObjectOutputStream)
264                   oosClass.
265                   getConstructor( new Class[]{OutputStream.class} ).
266                   newInstance( new Object[]{baos} );
267    
268             oos.writeObject( src );
269             oos.close();
270          
271             ret = baos.toByteArray();
272             baos.close();
273          
274          }
275          catch( Exception e ) { e.printStackTrace(); }
276          
277          return ret;
278       }
279       
280       
281       /**
282        * Deserialize an object from an array of bytes.
283        *
284        * @param buf  the array of bytes
285        * @return     the object or null if a error has been encountered
286        */
287        
288       public static Object deserialize(byte[] buf) {
289       
290          return deserialize( buf, ObjectInputStream.class );
291       }
292       
293       
294       /**
295        * Deserialize an object from an array of bytes.
296        *
297        * @param data      the array of bytes
298        * @param oisClass  the subclass of ObjectInputStream
299        *                  to use for deserializing src
300        * @return          the object or null if a error has been encountered
301        */
302        
303       public static Object deserialize( byte[] data, Class oisClass ) {
304       
305          ByteArrayInputStream bais = new ByteArrayInputStream(data);
306          
307          ObjectInputStream ois = null;
308          Object ret = null;
309          
310          try {
311          
312             ois = 
313                (ObjectInputStream)
314                   oisClass.
315                   getConstructor( new Class[]{InputStream.class} ).
316                   newInstance( new Object[]{bais} );
317    
318             ret = ois.readObject();
319             ois.close();
320             bais.close();
321          
322          }
323          catch( Exception e ) { e.printStackTrace(); }
324          
325          return ret;
326       }
327    
328    
329       /**
330        * Get fields name.
331        *
332        * @param src  the source object containing the fields
333        * @return     the fields name as an array of strings
334        */
335       
336       public static String[] getFieldsName( Object src ) {
337       
338          String[] fieldsName = null;
339          
340          try {
341          
342             Field[] fields = src.getClass().getFields();
343             fieldsName = new String[ fields.length ];
344                
345             for ( int i=0 ; i < fields.length ; i++ ) {
346                fieldsName[i] = fields[i].getName();
347             }
348    
349          }
350          catch( Exception e ) { e.printStackTrace(); }
351          
352          return fieldsName;
353       }
354          
355    
356       /**
357        * Get fields value.
358        *
359        * @param src  the source object containing the fields
360        * @return     the fields value as an array of objects
361        */
362       
363       public static Object[] getFieldsValue( Object src ) {
364       
365          Object[] fieldsValue = null;
366          
367          try {
368          
369             Field[] fields = src.getClass().getFields();
370             fieldsValue = new Object[ fields.length ];
371                
372             for ( int i=0 ; i < fields.length ; i++ ) {
373                fieldsValue[i] = fields[i].get( src );
374             }
375    
376          }
377          catch( Exception e ) { e.printStackTrace(); }
378          
379          return fieldsValue;
380       }
381       
382       
383       /**
384        * Get fields value.
385        *
386        * @param src         the source object containing the fields
387        * @param fieldsName  the fields name
388        * @return            the fields value as an array of objects
389        */
390       
391       public static Object[] getFieldsValue( Object src, String[] fieldsName ) {
392       
393          Object[] fieldsValue = null;
394          
395          try {
396          
397             Class cl = src.getClass();
398             fieldsValue = new Object[ fieldsName.length ];
399                
400             for ( int i=0 ; i < fieldsName.length ; i++ ) {
401                fieldsValue[i] = cl.getField(fieldsName[i]).get( src );
402             }
403    
404          }
405          catch( Exception e ) { e.printStackTrace(); }
406          
407          return fieldsValue;
408       }
409       
410       
411       /**
412        * Set fields value.
413        *
414        * @param src the source object
415        * @param fieldsName the fields name
416        * @param fieldsValue the fields value
417        */
418        
419       public static void setFieldsValue(Object src, String[] fieldsName, Object[] fieldsValue) {
420          try {
421             Class cl = src.getClass();
422             for (int i=0; i<fieldsName.length; i++) {
423                cl.getField(fieldsName[i]).set(src, fieldsValue[i]);
424             }
425          } catch (Exception e) { 
426             e.printStackTrace(); 
427          }
428       }
429       
430       /**
431        * Get classes.
432        *
433        * @param objs  the objects as an array
434        * @return      the array of classes where each element is the class
435        *              of the corresponding object
436        */
437       
438       public static Class[] getClasses( Object[] objs ) {
439       
440          Class cl;
441          Field fieldTYPE;
442          Class[] cls = new Class[ objs.length ];
443          
444          for ( int i=0 ; i < objs.length ; i++ ) {
445          
446             if( objs[i] != null ) {
447                cl = objs[i].getClass();
448    
449                /**
450                 * Check whether the class is a wrapper for a primitive type.
451                 * Heuristic used: search for a field called TYPE.
452                 */
453                
454                try {
455                   fieldTYPE = cl.getField("TYPE");
456                   cls[i] = (Class) fieldTYPE.get( objs[i] );
457                }
458                catch( NoSuchFieldException e )   { cls[i] = cl; }
459                catch( IllegalAccessException e ) { cls[i] = cl; }
460             } else {
461                cls[i] = Object.class;
462             }
463          }
464          return cls;
465       }
466    
467    
468       /**
469        * Recursively pretty prints an array.
470        *
471        * @param o  the array
472        */
473       
474       public static void printArray( Object o ) {
475    
476          if ( o == null ) {
477             System.out.print ( " <null> " );
478             return;
479          }
480    
481          if ( o.getClass().isArray() ) {
482    
483             System.out.print ( "[ " );
484    
485             for ( int i = 0; i < ((Object[])o).length; i++ ) {
486                printArray( ((Object[])o)[i] );
487             }
488    
489             System.out.print ( "]" );
490    
491          } else {
492             System.out.print ( o + " " );
493          }
494      
495       }    
496          
497    }