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    
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    }