View Javadoc

1   /*
2    * $Id: DummyClassGenerator.java,v 1.7 2006/01/19 00:07:00 blackdrag Exp $
3    *
4    * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5    *
6    * Redistribution and use of this software and associated documentation
7    * ("Software"), with or without modification, are permitted provided that the
8    * following conditions are met: 1. Redistributions of source code must retain
9    * copyright statements and notices. Redistributions must also contain a copy
10   * of this document. 2. Redistributions in binary form must reproduce the above
11   * copyright notice, this list of conditions and the following disclaimer in
12   * the documentation and/or other materials provided with the distribution. 3.
13   * The name "groovy" must not be used to endorse or promote products derived
14   * from this Software without prior written permission of The Codehaus. For
15   * written permission, please contact info@codehaus.org. 4. Products derived
16   * from this Software may not be called "groovy" nor may "groovy" appear in
17   * their names without prior written permission of The Codehaus. "groovy" is a
18   * registered trademark of The Codehaus. 5. Due credit should be given to The
19   * Codehaus - http://groovy.codehaus.org/
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
22   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24   * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
25   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31   * DAMAGE.
32   *
33   */
34  package org.codehaus.groovy.classgen;
35  
36  import groovy.lang.GroovyRuntimeException;
37  import org.codehaus.groovy.ast.*;
38  import org.objectweb.asm.ClassVisitor;
39  import org.objectweb.asm.MethodVisitor;
40  
41  import java.util.*;
42  
43  /***
44   * To generate a class that has all the fields and methods, except that fields are not initilized
45   * and methods are empty. It's intended for being used as a place holder during code generation
46   * of reference to the "this" class itself.
47   *
48   * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
49   * @author <a href="mailto:b55r@sina.com">Bing Ran</a>
50   *
51   * @version $Revision: 1.7 $
52   */
53  public class DummyClassGenerator extends ClassGenerator {
54  
55      private ClassVisitor cw;
56      private MethodVisitor cv;
57      private GeneratorContext context;
58  
59      private String sourceFile;
60  
61      // current class details
62      private ClassNode classNode;
63      private String internalClassName;
64      private String internalBaseClassName;
65  
66  
67      public DummyClassGenerator(
68          GeneratorContext context,
69          ClassVisitor classVisitor,
70          ClassLoader classLoader,
71          String sourceFile) {
72          super(classLoader);
73          this.context = context;
74          this.cw = classVisitor;
75          this.sourceFile = sourceFile;
76      }
77  
78      // GroovyClassVisitor interface
79      //-------------------------------------------------------------------------
80      public void visitClass(ClassNode classNode) {
81          try {
82              this.classNode = classNode;
83              this.internalClassName = BytecodeHelper.getClassInternalName(classNode);
84  
85              //System.out.println("Generating class: " + classNode.getName());
86  
87              this.internalBaseClassName = BytecodeHelper.getClassInternalName(classNode.getSuperClass());
88  
89              cw.visit(
90                  asmJDKVersion,
91                  classNode.getModifiers(),
92                  internalClassName,
93                  (String)null,
94                  internalBaseClassName,
95                  BytecodeHelper.getClassInternalNames(classNode.getInterfaces())
96                  );
97  
98              classNode.visitContents(this);
99  
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 }