View Javadoc
1 /* 2 * The Apache Software License, Version 1.1 3 * 4 * Copyright (c) 2002 The Apache Software Foundation. All rights 5 * reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * 3. The end-user documentation included with the redistribution, 20 * if any, must include the following acknowledgment: 21 * "This product includes software developed by the 22 * Apache Software Foundation (http://www.apache.org/)." 23 * Alternately, this acknowledgment may appear in the software itself, 24 * if and wherever such third-party acknowledgments normally appear. 25 * 26 * 4. The names "Apache" and "Apache Software Foundation" must 27 * not be used to endorse or promote products derived from this 28 * software without prior written permission. For written 29 * permission, please contact apache@apache.org. 30 * 31 * 5. Products derived from this software may not be called "Apache", 32 * nor may "Apache" appear in their name, without prior written 33 * permission of the Apache Software Foundation. 34 * 35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 46 * SUCH DAMAGE. 47 * ==================================================================== 48 * 49 * This software consists of voluntary contributions made by many 50 * individuals on behalf of the Apache Software Foundation. For more 51 * information on the Apache Software Foundation, please see 52 * <http://www.apache.org/>;. 53 */ 54 package net.sf.cglib.core; 55 56 import java.io.*; 57 import java.util.*; 58 import org.objectweb.asm.*; 59 60 /*** 61 * @author Juozas Baliuka, Chris Nokleberg 62 */ 63 public class ClassEmitter extends ClassAdapter { 64 private int access; 65 private Type classType; 66 private Type superType; 67 private Map fieldInfo; 68 69 private static int hookCounter; 70 private CodeVisitor rawStaticInit; 71 private CodeEmitter staticInit; 72 private CodeEmitter staticHook; 73 private Signature staticHookSig; 74 75 public ClassEmitter(ClassVisitor cv) { 76 super(null); 77 setTarget(cv); 78 } 79 80 public ClassEmitter() { 81 super(null); 82 } 83 84 public void setTarget(ClassVisitor cv) { 85 this.cv = cv; 86 fieldInfo = new HashMap(); 87 88 // just to be safe 89 staticInit = staticHook = null; 90 staticHookSig = null; 91 } 92 93 synchronized private static int getNextHook() { 94 return ++hookCounter; 95 } 96 97 public void begin_class(int access, String className, Type superType, Type[] interfaces, String sourceFile) { 98 this.access = access; 99 this.classType = Type.getType("L" + className.replace('.', '/') + ";"); 100 this.superType = (superType != null) ? superType : Constants.TYPE_OBJECT; 101 cv.visit(access, 102 this.classType.getInternalName(), 103 this.superType.getInternalName(), 104 TypeUtils.toInternalNames(interfaces), 105 sourceFile); 106 init(); 107 } 108 109 public CodeEmitter getStaticHook() { 110 if (TypeUtils.isInterface(access)) { 111 throw new IllegalStateException("static hook is invalid for this class"); 112 } 113 if (staticHook == null) { 114 staticHookSig = new Signature("CGLIB$STATICHOOK" + getNextHook(), "()V"); 115 staticHook = begin_method(Constants.ACC_STATIC, 116 staticHookSig, 117 null, 118 null); 119 if (staticInit != null) { 120 staticInit.invoke_static_this(staticHookSig); 121 } 122 } 123 return staticHook; 124 } 125 126 protected void init() { 127 } 128 129 public int getAccess() { 130 return access; 131 } 132 133 public Type getClassType() { 134 return classType; 135 } 136 137 public Type getSuperType() { 138 return superType; 139 } 140 141 public void end_class() { 142 if (staticHook != null && staticInit == null) { 143 // force creation of static init 144 begin_static(); 145 } 146 if (staticInit != null) { 147 staticHook.return_value(); 148 staticHook.end_method(); 149 rawStaticInit.visitInsn(Constants.RETURN); 150 rawStaticInit.visitMaxs(0, 0); 151 staticInit = staticHook = null; 152 staticHookSig = null; 153 } 154 cv.visitEnd(); 155 } 156 157 public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions, Attribute attrs) { 158 if (classType == null) 159 throw new IllegalStateException("classtype is null! " + this); 160 CodeVisitor v = cv.visitMethod(access, 161 sig.getName(), 162 sig.getDescriptor(), 163 TypeUtils.toInternalNames(exceptions), 164 attrs); 165 if (sig.equals(Constants.SIG_STATIC) && !TypeUtils.isInterface(this.access)) { 166 rawStaticInit = v; 167 CodeVisitor wrapped = new CodeAdapter(v) { 168 public void visitMaxs(int maxStack, int maxLocals) { 169 // ignore 170 } 171 public void visitInsn(int insn) { 172 if (insn != Constants.RETURN) { 173 super.visitInsn(insn); 174 } 175 } 176 }; 177 staticInit = new CodeEmitter(this, wrapped, access, sig, exceptions); 178 if (staticHook == null) { 179 // force static hook creation 180 getStaticHook(); 181 } else { 182 staticInit.invoke_static_this(staticHookSig); 183 } 184 return staticInit; 185 } else if (sig.equals(staticHookSig)) { 186 return new CodeEmitter(this, v, access, sig, exceptions) { 187 public boolean isStaticHook() { 188 return true; 189 } 190 }; 191 } else { 192 return new CodeEmitter(this, v, access, sig, exceptions); 193 } 194 } 195 196 public CodeEmitter begin_static() { 197 return begin_method(Constants.ACC_STATIC, Constants.SIG_STATIC, null, null); 198 } 199 200 public void declare_field(int access, String name, Type type, Object value, Attribute attrs) { 201 FieldInfo existing = (FieldInfo)fieldInfo.get(name); 202 FieldInfo info = new FieldInfo(access, name, type, value); 203 if (existing != null) { 204 if (!info.equals(existing)) { 205 throw new IllegalArgumentException("Field \"" + name + "\" has been declared differently"); 206 } 207 } else { 208 fieldInfo.put(name, info); 209 cv.visitField(access, name, type.getDescriptor(), value, attrs); 210 } 211 } 212 213 public void define_attribute(Attribute attrs) { 214 cv.visitAttribute(attrs); 215 } 216 217 // TODO: make public? 218 boolean isFieldDeclared(String name) { 219 return fieldInfo.get(name) != null; 220 } 221 222 FieldInfo getFieldInfo(String name) { 223 FieldInfo field = (FieldInfo)fieldInfo.get(name); 224 if (field == null) { 225 throw new IllegalArgumentException("Field " + name + " is not declared in " + classType.getClassName()); 226 } 227 return field; 228 } 229 230 static class FieldInfo { 231 int access; 232 String name; 233 Type type; 234 Object value; 235 236 public FieldInfo(int access, String name, Type type, Object value) { 237 this.access = access; 238 this.name = name; 239 this.type = type; 240 this.value = value; 241 } 242 243 public boolean equals(Object o) { 244 if (o == null) 245 return false; 246 if (!(o instanceof FieldInfo)) 247 return false; 248 FieldInfo other = (FieldInfo)o; 249 if (access != other.access || 250 !name.equals(other.name) || 251 !type.equals(other.type)) { 252 return false; 253 } 254 if ((value == null) ^ (other.value == null)) 255 return false; 256 if (value != null && !value.equals(other.value)) 257 return false; 258 return true; 259 } 260 261 public int hashCode() { 262 return access ^ name.hashCode() ^ type.hashCode() ^ ((value == null) ? 0 : value.hashCode()); 263 } 264 } 265 266 public void visit(int access, String name, String superName, String[] interfaces, String sourceFile) { 267 begin_class(access, 268 name.replace('/', '.'), 269 TypeUtils.fromInternalName(superName), 270 TypeUtils.fromInternalNames(interfaces), 271 sourceFile); 272 } 273 274 public void visitEnd() { 275 end_class(); 276 } 277 278 public void visitField(int access, String name, String desc, Object value, Attribute attrs) { 279 declare_field(access, name, Type.getType(desc), value, attrs); 280 } 281 282 // TODO: handle visitInnerClass? 283 284 public CodeVisitor visitMethod(int access, String name, String desc, String[] exceptions, Attribute attrs) { 285 return begin_method(access, 286 new Signature(name, desc), 287 TypeUtils.fromInternalNames(exceptions), 288 attrs); 289 } 290 291 public void visitAttribute(Attribute attrs) { 292 define_attribute(attrs); 293 } 294 }

This page was automatically generated by Maven