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
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
testJavapCompare()49     public void testJavapCompare() throws Exception {
50         testClassOnPath("target/test-classes/Java8Example.class");
51     }
52 
testClassOnPath(final String javaClass)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
canonHashRef(String input)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 
exec(final File workDir, final String... args)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