Уря, я это сделал!!! Теперь тестирование синглтонов становиться для меня реальностью:)
MockClassLoader.java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
package com.vvavrychuk.test;
import sun.tools.javap.JavapPrinter;
import sun.tools.javap.JavapEnvironment;
import sun.net.www.ParseUtil;
import java.util.Map;
import java.util.HashMap;
import java.util.AbstractList;
import java.util.ArrayList;
import java.lang.reflect.Modifier;
import java.io.*;
import java.net.URLClassLoader;
import java.net.URL;
import java.net.MalformedURLException;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.Repository;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
/**
* User: vvavrychuk
* Date: 27/9/2006
* Time: 7:59:41
*/
public class MockClassLoader extends URLClassLoader {
private ClassLoader parent;
private String rootDir;
private Map<String, String> mockObjets = new HashMap<String, String>();
private AbstractList<String> exceptClasses = new ArrayList<String>();
private byte [] findClassBytes(String className) {
try {
String pathName = rootDir + File.separatorChar + className.replace('.', File.separatorChar) + ".class";
FileInputStream inFile = new FileInputStream(pathName);
byte [] classBytes = new byte [inFile.available()];
inFile.read(classBytes);
return classBytes;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null ;
}
private static URL getFileURL(File file) {
try {
file = file.getCanonicalFile();
} catch (IOException e) {}
try {
return ParseUtil.fileToEncodedURL(file);
} catch (MalformedURLException e) {
// Should never happen since we specify the protocol...
throw new InternalError();
}
}
private static File[] getClassPath(String cp) {
File[] path;
if (cp != null ) {
int count = 0 , maxCount = 1 ;
int pos = 0 , lastPos = 0 ;
// Count the number of separators first
while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != - 1 ) {
maxCount++;
lastPos = pos + 1 ;
}
path = new File[maxCount];
lastPos = pos = 0 ;
// Now scan for each path component
while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != - 1 ) {
if (pos - lastPos > 0 ) {
path[count++] = new File(cp.substring(lastPos, pos));
} else {
// empty path component translates to "."
path[count++] = new File(".");
}
lastPos = pos + 1 ;
}
// Make sure we include the last path component
if (lastPos < cp.length()) {
path[count++] = new File(cp.substring(lastPos));
} else {
path[count++] = new File(".");
}
// Trim array to correct size
if (count != maxCount) {
File[] tmp = new File[count];
System.arraycopy(path, 0 , tmp, 0 , count);
path = tmp;
}
} else {
path = new File[ 0 ];
}
// DEBUG
//for (int i = 0; i < path.length; i++) {
// System.out.println("path[" + i + "] = " + '"' + path[i] + '"');
//}
return path;
}
private static URL[] pathToURLs(File[] path) {
URL[] urls = new URL[path.length];
for ( int i = 0 ; i < path.length; i++) {
urls[i] = getFileURL(path[i]);
}
return urls;
}
public MockClassLoader(ClassLoader parent) {
super ( new URL[ 0 ], parent);
this .parent = parent;
final String s = System.getProperty("java.class.path");
final File[] path = (s == null ) ? new File[ 0 ] : getClassPath(s);
final URL[] urls = (s == null ) ? new URL[ 0 ] : pathToURLs(path);
for (URL url : urls) {
addURL(url);
}
exceptClasses.add( this .getClass().getName());
}
private static void writeClass( byte [] bytes, String fileName) throws IOException {
PrintStream file = new PrintStream( new FileOutputStream(fileName));
for ( byte b : bytes) {
file.print(( char )b);
}
file.close();
}
private static void printDisasmClass(FileInputStream fileIn) {
System.out.println("== Begin disassembled code");
JavapEnvironment env = new JavapEnvironment();
env.showLineAndLocal = true;
env.showAccess = env. PRIVATE ;
env.showDisassembled = true;
env.nothingToDo = false;
PrintWriter out = new PrintWriter( new OutputStreamWriter(System.out));
JavapPrinter javap = new JavapPrinter(fileIn, out, env);
javap.print();
out.flush();
System.out.println("== End disassembled code");
}
public synchronized Class <?> findClass(String name) throws ClassNotFoundException {
if (name.startsWith("java")) {
//DEBUG
//System.out.println("ClassLoader system = "+name);
return parent.loadClass(name);
} else if (exceptClasses.contains(name)) {
//DEBUG
//System.out.println("ClassLoader system = "+name);
return parent.loadClass(name);
} else {
if (mockObjets.keySet().contains(name)) {
System.out.printf("MockClassLoader fired: %s => %s\n", name, mockObjets.get(name));
JavaClass javac = Repository.lookupClass(mockObjets.get(name));
/*
try {
//writeClass(javac.getBytes(), "C:\\Temp\\MainServlet.class");
javac.dump("C:\\Temp\\MainServlet.class");
FileInputStream fileIn = new FileInputStream("C:\\Temp\\MainServlet.class");
printDisasmClass(fileIn);
} catch (IOException e) {
e.printStackTrace();
}
*/
//System.out.println("loaded class="+javac.getClassName());
//javac.setClassName(name);
ClassModifier cm = new ClassModifier(javac);
cm.newClassName = name;
cm.start();
javac = cm.getResult();
/*
System.out.println("after changing name="+javac.getClassName());
try {
javac.dump("C:\\Temp\\MainServlet2.class");
FileInputStream fileIn = new FileInputStream("C:\\Temp\\MainServlet2.class");
printDisasmClass(fileIn);
} catch (IOException e) {
e.printStackTrace();
}
*/
return defineClass(name, javac.getBytes(), 0 , javac.getBytes().length);
} else {
Class c = null ;
try {
c = super .findClass(name);
} catch (ClassNotFoundException e) {
c = null ;
//System.err.println("Class loader super failed="+e.getMessage());
}
if (c != null ) {
//DEBUG
//System.out.println("ClassLoader super = "+name);
return c;
} else {
//DEBUG
//System.out.println("ClassLoader system (super failed) = "+name);
return parent.loadClass(name);
}
}
}
}
protected synchronized Class <?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class c = findClass(name);
if ((c != null )&&resolve) {
resolveClass(c);
}
return c;
}
public Class <?> loadClass(String name) throws ClassNotFoundException {
return findClass(name);
}
public void add(String name, String mockName) {
mockObjets.put(name, mockName);
}
public String getRootDir() {
return rootDir;
}
public void setRootDir(String rootDir) throws FileNotFoundException {
File f = new File(rootDir);
if (f.isDirectory()) {
this .rootDir = rootDir;
} else {
throw new FileNotFoundException();
}
}
}
class ClassModifier {
private JavaClass clazz;
private ClassGen classGen;
private ConstantPoolGen cp;
String newClassName;
public ClassModifier(JavaClass clazz) {
this .clazz = clazz;
this .classGen = new ClassGen( this .clazz);
this .cp = this .classGen.getConstantPool();
}
public void start() {
//Method[] methods = classGen.getJavaClass().getMethods();
classGen.setClassName(newClassName);
}
public JavaClass getResult() {
return classGen.getJavaClass();
}
}
MockLoaderTest.java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
package com.vvavrychuk.test;
import junit.framework.TestCase;
import java.io.File;
/**
* User: vvavrychuk
* Date: 2/10/2006
* Time: 13:00:04
*/
class MockLoaderA {
public String getParam(String name) {
return "Getting param failed: u must use mock-objects";
}
}
public class MockLoaderTest extends TestCase {
protected void setUp() throws Exception {
String systemCL = ClassLoader.getSystemClassLoader().getClass().getName();
String contextCL = Thread.currentThread().getContextClassLoader().getClass().getName();
String currentCL = MockLoaderTest. class .getClassLoader().getClass().getName();
assertEquals(systemCL, systemCL, "com.vvavrychuk.test.MockClassLoader");
assertEquals(contextCL, contextCL, "com.vvavrychuk.test.MockClassLoader");
assertEquals(currentCL, currentCL, "com.vvavrychuk.test.MockClassLoader");
MockClassLoader mcl = (MockClassLoader) ClassLoader.getSystemClassLoader();
File f = new File(".");
mcl.setRootDir(f.getAbsolutePath()+File.separatorChar+"WEB-INF\\classes");
mcl.add("com.vvavrychuk.test.MockLoaderA", "com.vvavrychuk.test.mock.MockLoaderA");
}
public void testMockLoader() {
MockLoaderA a = new MockLoaderA();
assertEquals(a.getParam(""), a.getParam(""), "root");
}
}
com.vvavrychuk.test.mock.MockLoaderA.java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
package com.vvavrychuk.test.mock;
/**
* User: vvavrychuk
* Date: 2/10/2006
* Time: 12:57:18
*/
public class MockLoaderA {
public String getParam(String name) {
return "root";
}
}
build.xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
[junit] Running com.vvavrychuk.test.MockLoaderTest
[junit] Tests run: 1 , Failures: 0 , Errors: 0 , Time elapsed: 0 , 312 sec
[junit] Testsuite: com.vvavrychuk.test.MockLoaderTest
[junit] Tests run: 1 , Failures: 0 , Errors: 0 , Time elapsed: 0 , 312 sec
[junit] ------------- Standard Output ---------------
[junit] MockClassLoader fired: com.vvavrychuk.test.MockLoaderA => com.vvavrychuk.test.mock.MockLoaderA
[junit] ------------- ---------------- ---------------
[junit] Testcase: testMockLoader took 0 , 093 sec
output
[src]
[junit] Running com.vvavrychuk.test.MockLoaderTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0,312 sec
[junit] Testsuite: com.vvavrychuk.test.MockLoaderTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0,312 sec
[junit] ------------- Standard Output ---------------
[junit] MockClassLoader fired: com.vvavrychuk.test.MockLoaderA => com.vvavrychuk.test.mock.MockLoaderA
[junit] ------------- ---------------- ---------------
[junit] Testcase: testMockLoader took 0,093 sec
[/SRC]