1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/*
2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright 2003,2004 The Apache Software Foundation
3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *  Licensed under the Apache License, Version 2.0 (the "License");
5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * you may not use this file except in compliance with the License.
6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * You may obtain a copy of the License at
7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *      http://www.apache.org/licenses/LICENSE-2.0
9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *  Unless required by applicable law or agreed to in writing, software
11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * distributed under the License is distributed on an "AS IS" BASIS,
12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * See the License for the specific language governing permissions and
14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * limitations under the License.
15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */
16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpackage org.mockito.cglib.transform;
17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.Attribute;
19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.ClassReader;
20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.ClassWriter;
21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.asm.util.*;
22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.cglib.core.ClassGenerator;
23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.cglib.core.CodeGenerationException;
24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.cglib.core.DebuggingClassWriter;
25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.io.IOException;
27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenabstract public class AbstractClassLoader extends ClassLoader {
29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private ClassFilter filter;
30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private ClassLoader classPath;
31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static java.security.ProtectionDomain DOMAIN ;
32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    static{
34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        DOMAIN = (java.security.ProtectionDomain)
36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        java.security.AccessController.doPrivileged(
37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen          new java.security.PrivilegedAction() {
38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            public Object run() {
39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen               return AbstractClassLoader.class.getProtectionDomain();
40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        });
42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     }
43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    protected AbstractClassLoader(ClassLoader parent, ClassLoader classPath, ClassFilter filter) {
45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        super(parent);
46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.filter = filter;
47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.classPath = classPath;
48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public Class loadClass(String name) throws ClassNotFoundException {
51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Class loaded = findLoadedClass(name);
53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if( loaded != null ){
55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if( loaded.getClassLoader() == this ){
56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen               return loaded;
57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }//else reload with this class loader
58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!filter.accept(name)) {
61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return super.loadClass(name);
62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        ClassReader r;
64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        try {
65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen           java.io.InputStream is = classPath.getResourceAsStream(
67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                       name.replace('.','/') + ".class"
68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                  );
69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen           if (is == null) {
71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen              throw new ClassNotFoundException(name);
73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen           }
75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen           try {
76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen              r = new ClassReader(is);
78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen           } finally {
80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen              is.close();
82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen           }
84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } catch (IOException e) {
85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new ClassNotFoundException(name + ":" + e.getMessage());
86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        try {
89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ClassWriter w =  new DebuggingClassWriter(ClassWriter.COMPUTE_MAXS);
90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            getGenerator(r).generateClass(w);
91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            byte[] b = w.toByteArray();
92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Class c = super.defineClass(name, b, 0, b.length, DOMAIN);
93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            postProcess(c);
94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return c;
95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } catch (RuntimeException e) {
96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw e;
97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } catch (Error e) {
98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw e;
99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } catch (Exception e) {
100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new CodeGenerationException(e);
101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    protected ClassGenerator getGenerator(ClassReader r) {
105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return new ClassReaderGenerator(r, attributes(), getFlags());
106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    protected int getFlags() {
109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return 0;
110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    protected Attribute[] attributes() {
113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return null;
114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    protected void postProcess(Class c) {
117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen}
119