001: /*
002: * @(#)BytecodeLoaderUtil.java
003: *
004: * Copyright (C) 2003 Matt Albrecht
005: * groboclown@users.sourceforge.net
006: * http://groboutils.sourceforge.net
007: *
008: * Permission is hereby granted, free of charge, to any person obtaining a
009: * copy of this software and associated documentation files (the "Software"),
010: * to deal in the Software without restriction, including without limitation
011: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
012: * and/or sell copies of the Software, and to permit persons to whom the
013: * Software is furnished to do so, subject to the following conditions:
014: *
015: * The above copyright notice and this permission notice shall be included in
016: * all copies or substantial portions of the Software.
017: *
018: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
019: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
020: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
021: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
022: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
023: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
024: * DEALINGS IN THE SOFTWARE.
025: */
026:
027: package net.sourceforge.groboutils.codecoverage.v2;
028:
029: import java.io.ByteArrayInputStream;
030: import java.io.IOException;
031: import java.io.InputStream;
032:
033: import junit.framework.Assert;
034: import net.sourceforge.groboutils.util.io.v1.ReadByteStream;
035:
036: import org.apache.bcel.classfile.ClassParser;
037: import org.apache.bcel.classfile.Code;
038: import org.apache.bcel.classfile.JavaClass;
039: import org.apache.bcel.generic.ConstantPoolGen;
040:
041: /**
042: * Helper for loading bytecode.
043: *
044: * @author Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
045: * @version $Date: 2004/04/15 05:48:27 $
046: * @since January 7, 2003
047: */
048: public class BytecodeLoaderUtil {
049: private static final Class THIS_CLASS = BytecodeLoaderUtil.class;
050:
051: public static String getClassFilename(Class c) {
052: Assert.assertNotNull("Null class.", c);
053: return getClassFilename(c.getName());
054: }
055:
056: public static String getClassFilename(String name) {
057: Assert.assertNotNull("Null class name.", name);
058: String filename = name.replace('.', '/') + ".class";
059: return filename;
060: }
061:
062: public static InputStream loadBytecodeStream(String filename)
063: throws IOException {
064: Assert.assertNotNull("Null filename.", filename);
065: ClassLoader cl = THIS_CLASS.getClassLoader();
066: InputStream is = cl.getSystemResourceAsStream(filename);
067: Assert.assertNotNull("resource '" + filename
068: + "' could not be found.", is);
069: return is;
070: }
071:
072: public static byte[] loadBytecode(String filename)
073: throws IOException {
074: Assert.assertNotNull("Null filename.", filename);
075: InputStream is = loadBytecodeStream(filename);
076: return ReadByteStream.readByteStream(is);
077: }
078:
079: public static JavaClass loadJavaClass(String className)
080: throws IOException {
081: String filename = getClassFilename(className);
082: InputStream is = loadBytecodeStream(filename);
083: ClassParser cp = new ClassParser(is, filename);
084: JavaClass jc = cp.parse();
085: return jc;
086: }
087:
088: public static JavaClass loadJavaClass(String className,
089: byte[] bytecode) throws IOException {
090: String filename = getClassFilename(className);
091: ByteArrayInputStream is = new ByteArrayInputStream(bytecode);
092: ClassParser cp = new ClassParser(is, filename);
093: JavaClass jc = cp.parse();
094: return jc;
095: }
096:
097: public static Class loadClassFromBytecode(String className, byte[] b)
098: throws ClassNotFoundException {
099: ArrayClassLoader acl = new ArrayClassLoader();
100: acl.addClass(className, b);
101: Class c = acl.loadClass(className);
102: return c;
103: }
104:
105: public static void runMain(Class cz) throws Exception {
106: String s[] = new String[0];
107: java.lang.reflect.Method m = cz.getMethod("main",
108: new Class[] { s.getClass() });
109: m.invoke(null, new Object[] { s });
110: }
111:
112: public static void verifyClass(String className, byte[] b)
113: throws Exception {
114: JavaClass jc = loadJavaClass(className, b);
115:
116: // ensure the integrety of the class file.
117: org.apache.bcel.generic.ClassGen modClass = new org.apache.bcel.generic.ClassGen(
118: jc);
119: ConstantPoolGen constantPool = modClass.getConstantPool();
120: org.apache.bcel.classfile.Method mL[] = modClass.getMethods();
121:
122: for (int i = 0; i < mL.length; ++i) {
123: verifyMethod(mL[i], constantPool);
124: }
125: }
126:
127: public static void verifyMethod(org.apache.bcel.classfile.Method m,
128: ConstantPoolGen cp) throws Exception {
129: Code c = m.getCode();
130: org.apache.bcel.classfile.CodeException ce[] = c
131: .getExceptionTable();
132: for (int i = 0; i < ce.length; ++i) {
133: /* this isn't an error - it can really happen
134: Assert.assertTrue(
135: "Method "+m+" includes a '0' catch type in code exception.",
136: ce[i].getCatchType() != 0);
137: */
138:
139: // a better test is to check this catch type against the
140: // original catch type.
141: }
142: }
143: }
|