001: /*
002: * $Id: DummyClassGenerator.java 3419 2006-01-19 00:07:02Z blackdrag $
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: 3419 $
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: public DummyClassGenerator(GeneratorContext context,
067: ClassVisitor classVisitor, ClassLoader classLoader,
068: String sourceFile) {
069: super (classLoader);
070: this .context = context;
071: this .cw = classVisitor;
072: this .sourceFile = sourceFile;
073: }
074:
075: // GroovyClassVisitor interface
076: //-------------------------------------------------------------------------
077: public void visitClass(ClassNode classNode) {
078: try {
079: this .classNode = classNode;
080: this .internalClassName = BytecodeHelper
081: .getClassInternalName(classNode);
082:
083: //System.out.println("Generating class: " + classNode.getName());
084:
085: this .internalBaseClassName = BytecodeHelper
086: .getClassInternalName(classNode.getSuperClass());
087:
088: cw.visit(asmJDKVersion, classNode.getModifiers(),
089: internalClassName, (String) null,
090: internalBaseClassName, BytecodeHelper
091: .getClassInternalNames(classNode
092: .getInterfaces()));
093:
094: classNode.visitContents(this );
095:
096: for (Iterator iter = innerClasses.iterator(); iter
097: .hasNext();) {
098: ClassNode innerClass = (ClassNode) iter.next();
099: ClassNode innerClassType = innerClass;
100: String innerClassInternalName = BytecodeHelper
101: .getClassInternalName(innerClassType);
102: String outerClassName = internalClassName; // default for inner classes
103: MethodNode enclosingMethod = innerClass
104: .getEnclosingMethod();
105: if (enclosingMethod != null) {
106: // local inner classes do not specify the outer class name
107: outerClassName = null;
108: }
109: cw.visitInnerClass(innerClassInternalName,
110: outerClassName, innerClassType.getName(),
111: innerClass.getModifiers());
112: }
113: cw.visitEnd();
114: } catch (GroovyRuntimeException e) {
115: e.setModule(classNode.getModule());
116: throw e;
117: }
118: }
119:
120: public void visitConstructor(ConstructorNode node) {
121:
122: visitParameters(node, node.getParameters());
123:
124: String methodType = BytecodeHelper.getMethodDescriptor(
125: ClassHelper.VOID_TYPE, node.getParameters());
126: cv = cw.visitMethod(node.getModifiers(), "<init>", methodType,
127: null, null);
128: cv.visitTypeInsn(NEW, "java/lang/RuntimeException");
129: cv.visitInsn(DUP);
130: cv.visitLdcInsn("not intended for execution");
131: cv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException",
132: "<init>", "(Ljava/lang/String;)V");
133: cv.visitInsn(ATHROW);
134: cv.visitMaxs(0, 0);
135: }
136:
137: public void visitMethod(MethodNode node) {
138:
139: visitParameters(node, node.getParameters());
140:
141: String methodType = BytecodeHelper.getMethodDescriptor(node
142: .getReturnType(), node.getParameters());
143: cv = cw.visitMethod(node.getModifiers(), node.getName(),
144: methodType, null, null);
145:
146: cv.visitTypeInsn(NEW, "java/lang/RuntimeException");
147: cv.visitInsn(DUP);
148: cv.visitLdcInsn("not intended for execution");
149: cv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException",
150: "<init>", "(Ljava/lang/String;)V");
151: cv.visitInsn(ATHROW);
152:
153: cv.visitMaxs(0, 0);
154: }
155:
156: public void visitField(FieldNode fieldNode) {
157:
158: cw.visitField(fieldNode.getModifiers(), 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: public void visitAnnotations(AnnotatedNode node) {
188: }
189: }
|