View Javadoc
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      // Canonicalise the javap output so it compares better
35      private String canonHashRef(String input) {
36          input = input.replaceAll("#\\d+", "#n"); // numbers may vary in length
37          input = input.replaceAll(" +", " "); // collapse spaces
38          input = input.replaceAll("//.+",""); // comments may vary
39          return input;
40      }
41  
42      private String exec(final File workDir, final String... args) throws Exception {
43          // System.err.println(java.util.Arrays.toString(args));
44          final ProcessBuilder pb = new ProcessBuilder(args);
45          pb.directory(workDir);
46          final Process proc = pb.start();
47          try (BufferedInputStream is = new BufferedInputStream(proc.getInputStream());
48                  InputStream es = proc.getErrorStream()) {
49              proc.waitFor();
50              final byte[] buff = new byte[2048];
51              int len;
52              while ((len = es.read(buff)) != -1) {
53                  System.err.print(new String(buff, 0, len));
54              }
55  
56              final StringBuilder sb = new StringBuilder();
57              while ((len = is.read(buff)) != -1) {
58                  sb.append(new String(buff, 0, len));
59              }
60              return sb.toString();
61          }
62      }
63  
64      private void testClassOnPath(final String javaClass) throws Exception {
65          // Get javap of the input class
66          final String initial = exec(null, "javap", "-p", "-c", javaClass);
67  
68          final File workDir = new File("target");
69          final File infile = new File(javaClass);
70          final JavaClass java_class = BCELifier.getJavaClass(infile.getName().replace(".class", ""));
71          assertNotNull(java_class);
72          final File outfile = new File(workDir, infile.getName().replace(".class", "Creator.java"));
73          try (FileOutputStream fos = new FileOutputStream(outfile)) {
74              final BCELifier bcelifier = new BCELifier(java_class, fos);
75              bcelifier.start();
76          }
77          exec(workDir, "javac", "-cp", "classes", outfile.getName(), "-source", "1.8", "-target", "1.8");
78          exec(workDir, "java", "-cp", "." + File.pathSeparator + "classes", outfile.getName().replace(".java", ""));
79          final String output = exec(workDir, "javap", "-p", "-c", infile.getName());
80          assertEquals(canonHashRef(initial), canonHashRef(output));
81      }
82  
83      /*
84       * Dump a class using "javap" and compare with the same class recreated
85       * using BCELifier, "javac", "java" and dumped with "javap"
86       * TODO: detect if JDK present and skip test if not
87       */
88      @Test
89      public void testJavapCompare() throws Exception {
90          testClassOnPath("target/test-classes/Java8Example.class");
91      }
92  
93      @Test
94      public void testStart() throws Exception {
95          final OutputStream os = new ByteArrayOutputStream();
96          final JavaClass java_class = BCELifier.getJavaClass("Java8Example");
97          assertNotNull(java_class);
98          final BCELifier bcelifier = new BCELifier(java_class, os);
99          bcelifier.start();
100     }
101 
102 }