DebuggingClassWriter.java revision 674060f01e9090cd21b3c5656cc3204912ad17a6
1/*
2 * Copyright 2003,2004 The Apache Software Foundation
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.mockito.cglib.core;
17
18import org.mockito.asm.ClassReader;
19import org.mockito.asm.ClassWriter;
20import org.mockito.asm.util.TraceClassVisitor;
21
22import java.io.*;
23
24public class DebuggingClassWriter extends ClassWriter {
25
26    public static final String DEBUG_LOCATION_PROPERTY = "cglib.debugLocation";
27
28    private static String debugLocation;
29    private static boolean traceEnabled;
30
31    private String className;
32    private String superName;
33
34    static {
35        debugLocation = System.getProperty(DEBUG_LOCATION_PROPERTY);
36        if (debugLocation != null) {
37            System.err.println("CGLIB debugging enabled, writing to '" + debugLocation + "'");
38            try {
39                Class.forName("org.mockito.asm.util.TraceClassVisitor");
40                traceEnabled = true;
41            } catch (Throwable ignore) {
42            }
43        }
44    }
45
46    public DebuggingClassWriter(int flags) {
47        super(flags);
48    }
49
50    public void visit(int version,
51                      int access,
52                      String name,
53                      String signature,
54                      String superName,
55                      String[] interfaces) {
56        className = name.replace('/', '.');
57        this.superName = superName.replace('/', '.');
58        super.visit(version, access, name, signature, superName, interfaces);
59    }
60
61    public String getClassName() {
62        return className;
63    }
64
65    public String getSuperName() {
66        return superName;
67    }
68
69    public byte[] toByteArray() {
70
71      return (byte[]) java.security.AccessController.doPrivileged(
72        new java.security.PrivilegedAction() {
73            public Object run() {
74
75
76                byte[] b = DebuggingClassWriter.super.toByteArray();
77                if (debugLocation != null) {
78                    String dirs = className.replace('.', File.separatorChar);
79                    try {
80                        new File(debugLocation + File.separatorChar + dirs).getParentFile().mkdirs();
81
82                        File file = new File(new File(debugLocation), dirs + ".class");
83                        OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
84                        try {
85                            out.write(b);
86                        } finally {
87                            out.close();
88                        }
89
90                        if (traceEnabled) {
91                            file = new File(new File(debugLocation), dirs + ".asm");
92                            out = new BufferedOutputStream(new FileOutputStream(file));
93                            try {
94                                ClassReader cr = new ClassReader(b);
95                                PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
96                                TraceClassVisitor tcv = new TraceClassVisitor(null, pw);
97                                cr.accept(tcv, 0);
98                                pw.flush();
99                            } finally {
100                                out.close();
101                            }
102                        }
103                    } catch (IOException e) {
104                        throw new CodeGenerationException(e);
105                    }
106                }
107                return b;
108             }
109            });
110
111        }
112    }
113