View Javadoc
1 package org.apache.bcel.util; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache BCEL" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * "Apache BCEL", nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>;. 55 */ 56 57 import java.util.Hashtable; 58 import java.io.*; 59 import org.apache.bcel.*; 60 import org.apache.bcel.classfile.*; 61 62 /*** 63 * <p>Drop in replacement for the standard class loader of the JVM. You can use it 64 * in conjunction with the JavaWrapper to dynamically modify/create classes 65 * as they're requested.</p> 66 * 67 * <p>This class loader recognizes special requests in a distinct 68 * format, i.e., when the name of the requested class contains with 69 * "$$BCEL$$" it calls the createClass() method with that name 70 * (everything bevor the $$BCEL$$ is considered to be the package 71 * name. You can subclass the class loader and override that 72 * method. "Normal" classes class can be modified by overriding the 73 * modifyClass() method which is called just before defineClass().</p> 74 * 75 * <p>There may be a number of packages where you have to use the default 76 * class loader (which may also be faster). You can define the set of packages 77 * where to use the system class loader in the constructor. The default value contains 78 * "java.", "sun.", "javax."</p> 79 * 80 * @version $Id: ClassLoader.java,v 1.6 2002/06/13 09:32:50 enver Exp $ 81 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> 82 * @see JavaWrapper 83 * @see ClassPath 84 */ 85 public class ClassLoader extends java.lang.ClassLoader { 86 private Hashtable classes = new Hashtable(); // Hashtable is synchronized thus thread-safe 87 private String[] ignored_packages = {/package-summary.html">b> String[] ignored_packages = { 88 "java.", "javax.", "sun." 89 }; 90 private Repository repository = SyntheticRepository.getInstance(); 91 private java.lang.ClassLoader deferTo = ClassLoader.getSystemClassLoader(); 92 93 public ClassLoader() { 94 } 95 96 public ClassLoader(java.lang.ClassLoader deferTo) { 97 this.deferTo = deferTo; 98 this.repository = new ClassLoaderRepository(deferTo); 99 } 100 101 /*** @param ignored_packages classes contained in these packages will be loaded 102 * with the system class loader 103 */ 104 public ClassLoader(String[] ignored_packages) {/package-summary.html">b> ClassLoader(String[] ignored_packages) { 105 addIgnoredPkgs(ignored_packages); 106 } 107 108 public ClassLoader(java/lang/ClassLoader deferTo, String [] ignored_packages) {/package-summary.html">b> ClassLoader(java.lang.ClassLoader deferTo, String [] ignored_packages) { 109 this.deferTo = deferTo; 110 this.repository = new ClassLoaderRepository(deferTo); 111 112 addIgnoredPkgs(ignored_packages); 113 } 114 115 private void addIgnoredPkgs(String[] ignored_packages) {/package-summary.html">b> void addIgnoredPkgs(String[] ignored_packages) { 116 String[] new_p = new String[ignored_packages.length + this.ignored_packages.length]; 117 118 System.arraycopy(this.ignored_packages, 0, new_p, 0, this.ignored_packages.length); 119 System.arraycopy(ignored_packages, 0, new_p, this.ignored_packages.length, 120 ignored_packages.length); 121 122 this.ignored_packages = new_p; 123 } 124 125 protected Class loadClass(String class_name, boolean resolve) 126 throws ClassNotFoundException 127 { 128 Class cl = null; 129 130 /* First try: lookup hash table. 131 */ 132 if((cl=(Class)classes.get(class_name)) == null) { 133 /* Second try: Load system class using system class loader. You better 134 * don't mess around with them. 135 */ 136 for(int i=0; i < ignored_packages.length; i++) { 137 if(class_name.startsWith(ignored_packages[i])) { 138 cl = deferTo.loadClass(class_name); 139 break; 140 } 141 } 142 143 if(cl == null) { 144 JavaClass clazz = null; 145 146 /* Third try: Special request? 147 */ 148 if(class_name.indexOf("$$BCEL$$") >= 0) 149 clazz = createClass(class_name); 150 else { // Fourth try: Load classes via repository 151 if ((clazz = repository.loadClass(class_name)) != null) { 152 clazz = modifyClass(clazz); 153 } 154 else 155 throw new ClassNotFoundException(class_name); 156 } 157 158 if(clazz != null) { 159 byte[] bytes = clazz.getBytes(); 160 cl = defineClass(class_name, bytes, 0, bytes.length); 161 } else // Fourth try: Use default class loader 162 cl = Class.forName(class_name); 163 } 164 165 if(resolve) 166 resolveClass(cl); 167 } 168 169 classes.put(class_name, cl); 170 171 return cl; 172 } 173 174 /*** Override this method if you want to alter a class before it gets actually 175 * loaded. Does nothing by default. 176 */ 177 protected JavaClass modifyClass(JavaClass clazz) { 178 return clazz; 179 } 180 181 /*** 182 * Override this method to create you own classes on the fly. The 183 * name contains the special token $$BCEL$$. Everything before that 184 * token is consddered to be a package name. You can encode you own 185 * arguments into the subsequent string. You must regard however not 186 * to use any "illegal" characters, i.e., characters that may not 187 * appear in a Java class name too<br> 188 * 189 * The default implementation interprets the string as a encoded compressed 190 * Java class, unpacks and decodes it with the Utility.decode() method, and 191 * parses the resulting byte array and returns the resulting JavaClass object. 192 * 193 * @param class_name compressed byte code with "$$BCEL$$" in it 194 */ 195 protected JavaClass createClass(String class_name) { 196 int index = class_name.indexOf("$$BCEL$$"); 197 String real_name = class_name.substring(index + 8); 198 199 JavaClass clazz = null; 200 try { 201 byte[] bytes = Utility.decode(real_name, true); 202 ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo"); 203 204 clazz = parser.parse(); 205 } catch(Throwable e) { 206 e.printStackTrace(); 207 return null; 208 } 209 210 // Adapt the class name to the passed value 211 ConstantPool cp = clazz.getConstantPool(); 212 213 ConstantClass cl = (ConstantClass)cp.getConstant(clazz.getClassNameIndex(), 214 Constants.CONSTANT_Class); 215 ConstantUtf8 name = (ConstantUtf8)cp.getConstant(cl.getNameIndex(), 216 Constants.CONSTANT_Utf8); 217 name.setBytes(class_name.replace('.', '/')); 218 219 return clazz; 220 } 221 }

This page was automatically generated by Maven