001 /* 002 * $Id: DummyClassGenerator.java,v 1.6 2005/11/13 16:42:11 blackdrag Exp $ 003 * 004 * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved. 005 * 006 * Redistribution and use of this software and associated documentation 007 * ("Software"), with or without modification, are permitted provided that the 008 * following conditions are met: 1. Redistributions of source code must retain 009 * copyright statements and notices. Redistributions must also contain a copy 010 * of this document. 2. Redistributions in binary form must reproduce the above 011 * copyright notice, this list of conditions and the following disclaimer in 012 * the documentation and/or other materials provided with the distribution. 3. 013 * The name "groovy" must not be used to endorse or promote products derived 014 * from this Software without prior written permission of The Codehaus. For 015 * written permission, please contact info@codehaus.org. 4. Products derived 016 * from this Software may not be called "groovy" nor may "groovy" appear in 017 * their names without prior written permission of The Codehaus. "groovy" is a 018 * registered trademark of The Codehaus. 5. Due credit should be given to The 019 * Codehaus - http://groovy.codehaus.org/ 020 * 021 * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY 022 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 023 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 024 * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR 025 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 026 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 027 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 028 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 029 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 030 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 031 * DAMAGE. 032 * 033 */ 034 package org.codehaus.groovy.classgen; 035 036 import groovy.lang.GroovyRuntimeException; 037 import org.codehaus.groovy.ast.*; 038 import org.objectweb.asm.ClassVisitor; 039 import org.objectweb.asm.MethodVisitor; 040 041 import java.util.*; 042 043 /** 044 * To generate a class that has all the fields and methods, except that fields are not initilized 045 * and methods are empty. It's intended for being used as a place holder during code generation 046 * of reference to the "this" class itself. 047 * 048 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a> 049 * @author <a href="mailto:b55r@sina.com">Bing Ran</a> 050 * 051 * @version $Revision: 1.6 $ 052 */ 053 public class DummyClassGenerator extends ClassGenerator { 054 055 private ClassVisitor cw; 056 private MethodVisitor cv; 057 private GeneratorContext context; 058 059 private String sourceFile; 060 061 // current class details 062 private ClassNode classNode; 063 private String internalClassName; 064 private String internalBaseClassName; 065 066 067 public DummyClassGenerator( 068 GeneratorContext context, 069 ClassVisitor classVisitor, 070 ClassLoader classLoader, 071 String sourceFile) { 072 super(classLoader); 073 this.context = context; 074 this.cw = classVisitor; 075 this.sourceFile = sourceFile; 076 } 077 078 // GroovyClassVisitor interface 079 //------------------------------------------------------------------------- 080 public void visitClass(ClassNode classNode) { 081 try { 082 this.classNode = classNode; 083 this.internalClassName = BytecodeHelper.getClassInternalName(classNode); 084 085 //System.out.println("Generating class: " + classNode.getName()); 086 087 this.internalBaseClassName = BytecodeHelper.getClassInternalName(classNode.getSuperClass()); 088 089 cw.visit( 090 asmJDKVersion, 091 classNode.getModifiers(), 092 internalClassName, 093 (String)null, 094 internalBaseClassName, 095 BytecodeHelper.getClassInternalNames(classNode.getInterfaces()) 096 ); 097 098 classNode.visitContents(this); 099 100 for (Iterator iter = innerClasses.iterator(); iter.hasNext();) { 101 ClassNode innerClass = (ClassNode) iter.next(); 102 ClassNode innerClassType = innerClass; 103 String innerClassInternalName = BytecodeHelper.getClassInternalName(innerClassType); 104 String outerClassName = internalClassName; // default for inner classes 105 MethodNode enclosingMethod = innerClass.getEnclosingMethod(); 106 if (enclosingMethod != null) { 107 // local inner classes do not specify the outer class name 108 outerClassName = null; 109 } 110 cw.visitInnerClass( 111 innerClassInternalName, 112 outerClassName, 113 innerClassType.getName(), 114 innerClass.getModifiers()); 115 } 116 cw.visitEnd(); 117 } 118 catch (GroovyRuntimeException e) { 119 e.setModule(classNode.getModule()); 120 throw e; 121 } 122 } 123 124 public void visitConstructor(ConstructorNode node) { 125 126 visitParameters(node, node.getParameters()); 127 128 String methodType = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, node.getParameters()); 129 cv = cw.visitMethod(node.getModifiers(), "<init>", methodType, null, null); 130 cv.visitTypeInsn(NEW, "java/lang/RuntimeException"); 131 cv.visitInsn(DUP); 132 cv.visitLdcInsn("not intended for execution"); 133 cv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V"); 134 cv.visitInsn(ATHROW); 135 cv.visitMaxs(0, 0); 136 } 137 138 public void visitMethod(MethodNode node) { 139 140 visitParameters(node, node.getParameters()); 141 142 String methodType = BytecodeHelper.getMethodDescriptor(node.getReturnType(), node.getParameters()); 143 cv = cw.visitMethod(node.getModifiers(), node.getName(), methodType, null, null); 144 145 cv.visitTypeInsn(NEW, "java/lang/RuntimeException"); 146 cv.visitInsn(DUP); 147 cv.visitLdcInsn("not intended for execution"); 148 cv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V"); 149 cv.visitInsn(ATHROW); 150 151 cv.visitMaxs(0, 0); 152 } 153 154 public void visitField(FieldNode fieldNode) { 155 156 cw.visitField( 157 fieldNode.getModifiers(), 158 fieldNode.getName(), 159 BytecodeHelper.getTypeDescription(fieldNode.getType()), 160 null, //fieldValue, //br all the sudden that one cannot init the field here. init is done in static initilizer and instace intializer. 161 null); 162 } 163 164 /** 165 * Creates a getter, setter and field 166 */ 167 public void visitProperty(PropertyNode statement) { 168 } 169 170 protected CompileUnit getCompileUnit() { 171 CompileUnit answer = classNode.getCompileUnit(); 172 if (answer == null) { 173 answer = context.getCompileUnit(); 174 } 175 return answer; 176 } 177 178 protected void visitParameters(ASTNode node, Parameter[] parameters) { 179 for (int i = 0, size = parameters.length; i < size; i++ ) { 180 visitParameter(node, parameters[i]); 181 } 182 } 183 184 protected void visitParameter(ASTNode node, Parameter parameter) { 185 } 186 187 188 public void visitAnnotations(AnnotatedNode node) { 189 } 190 191 }