Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jreversepro/common/Helper.java


1   /*
2    * @(#)Helper.java
3    *
4    * JReversePro - Java Decompiler / Disassembler.
5    * Copyright (C) 2000 2001 Karthik Kumar.
6    * EMail: akkumar@users.sourceforge.net
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it , under the terms of the GNU General Public License as published
10   * by the Free Software Foundation; either version 2 of the License,
11   * or (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16   * See the GNU General Public License for more details.
17   * You should have received a copy of the GNU General Public License
18   * along with this program.If not, write to
19   *  The Free Software Foundation, Inc.,
20   *  59 Temple Place - Suite 330,
21   *  Boston, MA 02111-1307, USA.
22   */
23  package jreversepro.common;
24  
25  import java.util.List;
26  import java.util.ArrayList;
27  
28  /**
29   * Helper contains a list of assorted methods that 'helps'
30   * in manipulating the data present in the class file.
31   * @author Karthik Kumar
32   **/
33  public class Helper implements KeyWords {
34  
35      /**
36       * Private constructor to prevent any instance from being created.
37       **/
38      private Helper() { }
39  
40      /**
41       * Working Version Could be compromised    
42       **/
43      static final String DEFAULT_VERSION = "1.2.2";
44  
45  
46      /** Debug flag    
47       * Default value = false.
48       **/
49      static boolean debugFlag;
50  
51      /**
52       * static initializer method.
53       **/
54      static {
55          debugFlag = false;
56      }
57  
58      /**
59       * @param logMsg Message to be logged.
60       **/
61      public static void log(String logMsg) {
62          if (debugFlag) {
63              System.out.println(logMsg);
64          }
65      }
66  
67      /**
68       * @param ex Exception to be logged.
69       **/
70      public static void log(Exception ex) {
71          if (debugFlag) {
72              ex.printStackTrace(System.out);
73          }
74      }
75  
76      /**
77       * Log without end-of-line at the end.
78       * @param logMsg Message to be logged.
79       **/
80      public static void logNoEol(String logMsg) {
81          if (debugFlag) {
82              System.out.print(logMsg);
83          }
84      }
85  
86      /**
87       * Toggles the debug flag.
88       * @return Returns the new debug flag after toggling.
89       **/
90      public static boolean toggleDebug() {
91          debugFlag  = !debugFlag;
92          return debugFlag;
93      }
94  
95      /**
96       * @return the value of debug flag.
97       **/
98      public static boolean isDebug() {
99          return debugFlag;
100     }
101 
102     /**
103      * Returns the Package name alone from a fully qualified name.
104      * <p>
105      * For Example , if <code>FullName = java/lang/StringBuffer,</code>
106      * <br>then a call to <code>getPackageName(arg)</code> returns the
107      * value <code>java.lang</code>.
108      * <p>
109      *
110      * @param   aFullName    A Fully Qualified Name.
111      * @return  the package name , alone with the dots separating the
112      * classes.
113      **/
114     public static String getPackageName(String aFullName) {
115         aFullName  = Helper.getJavaDataType(aFullName, false);
116         aFullName = aFullName.replace('/', '.');
117         int dotIndex = aFullName.lastIndexOf(".");
118         if (dotIndex != -1)  {
119             return aFullName.substring(0, dotIndex);
120         } else {
121             return "";
122         }
123     }
124 
125 
126     /**
127      * Determines the Java representation , given the JVM representation
128      * of data types.
129      * <p>
130      * <table>
131      * <tr><th><code>dataType</code> </th>
132      * <th><code>formatDataType(dataType)</code></th></tr>
133      * <tr><td><code>B</code></td><td>byte</td></tr>
134      * <tr><td><code>C</code></td><td>char</td></tr>
135      * <tr><td><code>D</code></td><td>double</td></tr>
136      * <tr><td><code>F</code></td><td>float</td></tr>
137      * <tr><td><code>I</code></td><td>int</td></tr>
138      * <tr><td><code>J</code></td><td>long</td></tr>
139      * <tr><td><code>S</code></td><td>short</td></tr>
140      * <tr><td><code>V</code></td><td>void</td></tr>
141      * <tr><td><code>Z</code></td><td>boolean</td></tr>
142      * <tr><td><code>[Z</code></td><td>boolean [] , array representation
143      * </td></tr>
144      * <tr><td><code>Ljava/lang/String </code></td><td>
145      * <code> java/lang/String</code> </td></tr>
146      * </table>
147      * @param   aDataType  JVM representation of the data type.
148      * @param associated If set, then an array representation is returned.ñ
149      * @return  Java Language representation of aDataType.
150      **/
151     public static String getJavaDataType(String aDataType,
152                                             boolean associated) {
153 
154         char firstChar = aDataType.charAt(0);
155 
156         if (aDataType.length() == 1)  {
157             switch (firstChar) {
158                 case 'B': return "byte";
159                 case 'C': return "char";
160                 case 'D': return "double";
161                 case 'F': return "float";
162                 case 'I': return "int";
163                 case 'J': return "long";
164                 case 'S': return "short";
165                 case 'V': return "void";
166                 case 'Z': return "boolean";
167                 default:
168                         return "invalid";                        
169             }
170         } else if (firstChar == '[') {
171             String type = getJavaDataType(aDataType.substring(1),
172                                          associated);
173             if (!associated) {
174                 return type + "[]";
175             } else {
176                 return type;
177             }
178         } else if (firstChar == 'L') {
179             int len = aDataType.length();
180             if (aDataType.indexOf(";") == -1) {
181                 return aDataType.substring(1);
182             } else {
183                 return aDataType.substring(1, len - 1);
184             }
185         }
186         return aDataType;
187     }
188 
189     /**
190      * Determines the length of the JVM datatype representation
191      * given the JVM signature.
192      * <p>
193      * <table>
194      * <tr><th><code>dataType</code> </th>
195      * <th><code>getSignTokenLength(dataType)(dataType)</code></th></tr>
196      * <tr><td><code>all basic data types</code></td><td>1</td></tr>
197      * <tr><td><code>[XYZ</code></td><td>len(XYZ) + 1
198      * </td></tr>
199      * <tr><td><code>Ljava/lang/String </code></td><td>
200      * <code> len(Ljava/lang/String)</code> </td></tr>
201      * </table>
202      * @param   aDataType Signature of a method as present in
203      * the class file in JVM representation, containing a list
204      * of datatypes.
205      * @return  the length of the first valid datatype.
206      **/
207     public static int getSignTokenLength(String aDataType) {
208         char ch = aDataType.charAt(0);
209         switch(ch) {
210             case 'B':
211             case 'C':
212             case 'D':
213             case 'F':
214             case 'I':
215             case 'J':
216             case 'S':
217             case 'V':
218             case 'Z':
219                 return 1;
220             case '[':
221                 return (
222                     getSignTokenLength(aDataType.substring(1)) + 1);
223             case 'L':
224                 int semiColon = aDataType.indexOf(";");
225                 if (semiColon == -1)  {
226                     return aDataType.length();
227                 } else {
228                     return (semiColon + 1);
229                 }
230             default:
231                 return 0;
232         }
233     }
234 
235     /**
236      * Returns the arguments in array form
237      * given the JVM signature.
238      * <p>
239      * For example , <code>IILjava/lang/String</code>
240      * could be returned as <br>
241      * <code>( int , int , java/lang/String )</code>.
242      * @param   aSignature Signature of the method.
243      * @return  The method arguments as a List
244      **/
245     public static List getArguments(String aSignature) {
246         List  args = new ArrayList();
247         int endIndex = aSignature.indexOf(")");
248         if (endIndex != 1) {
249             aSignature = aSignature.substring(1 , endIndex);
250 
251             String origStr = aSignature;
252             int length = origStr.length();
253             //Start Processing Rhs
254             int curIndex = 0;
255 
256             while (curIndex < length) {
257                 aSignature = origStr.substring(curIndex);
258                 int tokenLength = getSignTokenLength(aSignature);
259                 String tokenString =
260                         aSignature.substring(0, tokenLength);
261                 int semiColon = tokenString.indexOf(";");
262                 if (semiColon != -1) {
263                     tokenString = tokenString.substring(0, semiColon);
264                 }
265                 args.add(tokenString);
266                 curIndex += tokenLength;
267             }
268         }
269         return args;
270     }
271 
272 
273     /**
274      * Given the Signature of the method , this provides us the
275      * return type.
276      * <p>
277      * @param  aSignature Signature of the method.
278      * @return the return type associated with the method signature,
279      * The type returned corresponds to JVM representation.
280      **/
281     public static String getReturnType(String aSignature) {
282         int index = aSignature.indexOf(")");
283         return aSignature.substring(index + 1);
284     }
285 
286     /**
287      * Extracts the value of a particular number of bits.
288      * <p>
289      * For example <code>lowNBits(169 , 5 )</code>
290      * returns <code> (10101001,5) -> 10101 i.e  21 </code> <br>.
291      * @param  aValue Value containing the integer in string form.
292      * @param  aNumBits Number of bits that is to be extracted.
293      * @return the masked value of the N Bit Number.
294      **/
295     public static String lowNbits(String aValue, int aNumBits) {
296         int val = Integer.parseInt(aValue);
297         if (val == 0)  {
298             return aValue;
299         } else {
300             int res =  0;
301             for (int i = 0; i < aNumBits; i++) {
302                 int mask = (int) Math.pow(2, i);
303                 if ((val & mask) != 0) {
304                     res += mask;
305                 }
306             }
307             return (String.valueOf(res));
308         }
309     }
310 
311     /**
312      * Inserts a '\' before all the escape characters ,
313      * line '\n' , '\t' to provide better readability.
314      * <p>
315      * @param  aLiteral String containing the escape characters.
316      * @return the new String containing the new escape sequence
317      * of characters.
318      **/
319     public static String replaceEscapeChars(String aLiteral) {
320         StringBuffer result = new StringBuffer("");
321         for (int i = 0 ; i < aLiteral.length() ; i++) {
322             result.append(representChar(aLiteral.charAt(i)));
323         }
324         return result.toString();
325     }
326 
327     /**
328      * Returns the String representation of the character .
329      * @param  aChar - Character.
330      * @return the new String representing the character.
331      **/
332     private static String representChar(char aChar) {
333         switch(aChar) {
334             case '\n':  return "\\n";
335             case '\t':  return "\\t";
336             case '\\':  return "\\\\";
337             case '"':   return "\\" + "\"";
338             default:    return String.valueOf(aChar);
339         }
340     }
341 
342 
343 
344     /**
345      * Checks for the version compatibility between the system JRE
346      * and the JRE for which the application is written for.
347      * @return true , if System JRE is >= DEFAULT_VERISON ( 1.2.2 ).<br>
348      *          false , otherwise.
349      **/
350     public static boolean versionCheck() {
351         String version = System.getProperty("java.version");
352         for (int i = 0 ; i <= 5 ; i += 2) {
353             int versionVal = (int) (version.charAt(i));
354             int workingVal = (int) (DEFAULT_VERSION.charAt(i));
355             if (versionVal > workingVal) {
356                 return true;
357             } else if (versionVal < workingVal) {
358                 System.err.println(
359                                    "This Software is designed to run under "
360                                    +  DEFAULT_VERSION);
361                 System.err.println("Please upgrade your JRE" 
362                                 + " from http://java.sun.com/products/j2se" 
363                                 + " for your operating system");
364                 return false;
365             }
366         }
367         return true;
368     }
369 
370 
371     /**
372      * Checks if the given datatype is a basic data type or not.
373      * @param type the datatype to be checked.
374      * @return true , if it is.
375      *          false , otherwise.
376      **/
377     public static boolean isBasicType(String type) {
378         return (type.equals(KeyWords.INT)  
379             || type.equals(KeyWords.BOOLEAN) 
380             || type.equals(KeyWords.BYTE) 
381             || type.equals(KeyWords.CHAR) 
382             || type.equals(KeyWords.SHORT) 
383             || type.equals(KeyWords.FLOAT) 
384             || type.equals(KeyWords.LONG) 
385             || type.equals(KeyWords.DOUBLE));
386     }
387 
388     /**
389      * Both boolean and char are represented as integers .
390      * This takes care of the conversions
391      * @param value Old Value.
392      * @param datatype Datatype of the value.
393      * @return Returns the new value after making appropriate 
394      * changes.
395      **/
396     public static String getValue(String  value, String datatype) {
397         if (datatype == null) {
398             return value;
399         }
400         int lastQIndex = value.lastIndexOf('?');
401         int lastColonIndex = value.lastIndexOf(":");
402 
403         if (lastQIndex == -1 
404             || lastColonIndex == -1 
405             || lastQIndex > lastColonIndex) {
406             return getAtomicValue(value, datatype);
407         }
408         String condition = value.substring(0, lastQIndex);
409         String val1 = value.substring(lastQIndex + 1, lastColonIndex);
410         String val2 = value.substring(lastColonIndex + 1);
411 
412         StringBuffer result =  new StringBuffer(condition);
413         result.append("? " + getAtomicValue(val1, datatype));
414         result.append(": " + getAtomicValue(val2, datatype));
415 
416         return result.toString();
417     }
418 
419 
420     /**
421      * Both boolean and char are represented as integers .
422      * This takes care of the conversions
423      * @param value Old Value.
424      * @param datatype Datatype of the value.
425      * @return Returns the new value after making appropriate 
426      * changes.
427      **/
428     private static String getAtomicValue(String value , String datatype) {
429         value = value.trim();
430         if (datatype.equals(JVM_BOOLEAN)) { //boolean
431             if (value.compareTo("1") == 0) {
432                 return TRUE;
433             } else if (value.compareTo("0") == 0) {
434                 return FALSE;
435             } else {
436                 return value;
437             }
438         } else if (datatype.equals(JVM_CHAR))  {  //Character
439             try {
440                 StringBuffer sb = new StringBuffer("");
441                 int intvalue = Integer.parseInt(value);
442                 sb.append("'" + (char) intvalue + "'");
443                 return sb.toString();
444             } catch (NumberFormatException _ex) {
445                 return value;
446             }
447         }
448         return value;
449     }
450 
451     /**
452      * Converts a signed 'byte' to an unsigned integer.
453      * <p>
454      * @param aByteVal a Byte Value.
455      * @return unsigned integer equivalent of aByteVal.
456      **/
457     public static int signedToUnsigned(int aByteVal) {
458         return (aByteVal < 0) ? (aByteVal += 256) : aByteVal;
459     }
460 }