Home | History | Annotate | Download | only in util
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  */
     18 package org.apache.bcel.util;
     19 
     20 import static org.junit.Assert.*;
     21 
     22 import java.io.BufferedInputStream;
     23 import java.io.ByteArrayOutputStream;
     24 import java.io.File;
     25 import java.io.FileOutputStream;
     26 import java.io.InputStream;
     27 import java.io.OutputStream;
     28 import org.apache.bcel.classfile.JavaClass;
     29 import org.junit.Test;
     30 
     31 
     32 public class BCELifierTestCase {
     33 
     34     @Test
     35     public void test() throws Exception {
     36         final OutputStream os = new ByteArrayOutputStream();
     37         final JavaClass java_class = BCELifier.getJavaClass("Java8Example");
     38         assertNotNull(java_class);
     39         final BCELifier bcelifier = new BCELifier(java_class, os);
     40         bcelifier.start();
     41     }
     42 
     43     /*
     44      * Dump a class using "javap" and compare with the same class recreated
     45      * using BCELifier, "javac", "java" and dumped with "javap"
     46      * TODO: detect if JDK present and skip test if not
     47      */
     48     @Test
     49     public void testJavapCompare() throws Exception {
     50         testClassOnPath("target/test-classes/Java8Example.class");
     51     }
     52 
     53     private void testClassOnPath(final String javaClass) throws Exception {
     54         // Get javap of the input class
     55         final String initial = exec(null, "javap", "-p", "-c", javaClass);
     56 
     57         final File workDir = new File("target");
     58         final File infile = new File(javaClass);
     59         final JavaClass java_class = BCELifier.getJavaClass(infile.getName().replace(".class", ""));
     60         assertNotNull(java_class);
     61         final File outfile = new File(workDir, infile.getName().replace(".class", "Creator.java"));
     62         try (FileOutputStream fos = new FileOutputStream(outfile)) {
     63             final BCELifier bcelifier = new BCELifier(java_class, fos);
     64             bcelifier.start();
     65         }
     66         exec(workDir, "javac", "-cp", "classes", outfile.getName());
     67         exec(workDir, "java", "-cp", "." + File.pathSeparator + "classes", outfile.getName().replace(".java", ""));
     68         final String output = exec(workDir, "javap", "-p", "-c", infile.getName());
     69         assertEquals(canonHashRef(initial), canonHashRef(output));
     70     }
     71 
     72     // Canonicalise the javap output so it compares better
     73     private String canonHashRef(String input) {
     74         input = input.replaceAll("#\\d+", "#n"); // numbers may vary in length
     75         input = input.replaceAll(" +", " "); // collapse spaces
     76         input = input.replaceAll("//.+",""); // comments may vary
     77         return input;
     78     }
     79 
     80     private String exec(final File workDir, final String... args) throws Exception {
     81         // System.err.println(java.util.Arrays.toString(args));
     82         final ProcessBuilder pb = new ProcessBuilder(args);
     83         pb.directory(workDir);
     84         final Process proc = pb.start();
     85         try (BufferedInputStream is = new BufferedInputStream(proc.getInputStream());
     86                 InputStream es = proc.getErrorStream()) {
     87             proc.waitFor();
     88             final byte[] buff = new byte[2048];
     89             int len;
     90             while ((len = es.read(buff)) != -1) {
     91                 System.err.print(new String(buff, 0, len));
     92             }
     93 
     94             final StringBuilder sb = new StringBuilder();
     95             while ((len = is.read(buff)) != -1) {
     96                 sb.append(new String(buff, 0, len));
     97             }
     98             return sb.toString();
     99         }
    100     }
    101 
    102 }
    103