001    /*
002     * Copyright (C) 2006-2007 the original author or authors.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.codehaus.gmaven.runtime.v1_7;
018    
019    import groovy.lang.GroovyClassLoader;
020    import org.codehaus.groovy.ast.ClassNode;
021    import org.codehaus.groovy.ast.ModuleNode;
022    import org.codehaus.groovy.classgen.GeneratorContext;
023    import org.codehaus.groovy.control.CompilationFailedException;
024    import org.codehaus.groovy.control.CompilationUnit;
025    import org.codehaus.groovy.control.CompilerConfiguration;
026    import org.codehaus.groovy.control.Phases;
027    import org.codehaus.groovy.control.SourceUnit;
028    import org.codehaus.groovy.tools.javac.JavaAwareResolveVisitor;
029    import org.codehaus.groovy.tools.javac.JavaCompiler;
030    import org.codehaus.groovy.tools.javac.JavaStubGenerator;
031    
032    import java.io.File;
033    import java.io.FileNotFoundException;
034    import java.net.URL;
035    import java.util.Iterator;
036    import java.util.Map;
037    
038    /**
039     * Java-stub-only compilation unit.
040     *
041     * @version $Id: JavaStubCompilationUnit.java 112 2010-08-06 19:47:04Z user57 $
042     * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
043     *
044     * @since 1.1
045     */
046    public class JavaStubCompilationUnit
047        extends CompilationUnit
048    {
049        private static final String DOT_GROOVY = ".groovy";
050        
051        private final JavaStubGenerator stubGenerator;
052    
053        private int stubCount;
054    
055        public JavaStubCompilationUnit(final CompilerConfiguration config, final GroovyClassLoader gcl, File destDir) {
056            super(config,null,gcl);
057            assert config != null;
058    
059            Map options = config.getJointCompilationOptions();
060            if (destDir == null) {
061                destDir = (File) options.get("stubDir");
062            }
063            boolean useJava5 = config.getTargetBytecode().equals(CompilerConfiguration.POST_JDK5);
064            stubGenerator = new JavaStubGenerator(destDir, false, useJava5);
065    
066            addPhaseOperation(new PrimaryClassNodeOperation()
067            {
068                public void call(final SourceUnit source, final GeneratorContext context, final ClassNode node) throws CompilationFailedException {
069                    new JavaAwareResolveVisitor(JavaStubCompilationUnit.this).startResolving(node, source);
070                }
071            },Phases.CONVERSION);
072    
073            addPhaseOperation(new PrimaryClassNodeOperation()
074            {
075                @Override
076                public void call(final SourceUnit source, final GeneratorContext context, final ClassNode node) throws CompilationFailedException {
077                    try {
078                        stubGenerator.generateClass(node);
079                        stubCount++;
080                    }
081                    catch (FileNotFoundException e) {
082                        source.addException(e);
083                    }
084                }
085            },Phases.CONVERSION);
086        }
087    
088        public JavaStubCompilationUnit(final CompilerConfiguration config, final GroovyClassLoader gcl) {
089            this(config, gcl, null);
090        }
091    
092        public void gotoPhase(final int phase) throws CompilationFailedException {
093            super.gotoPhase(phase);
094    
095            if (phase==Phases.SEMANTIC_ANALYSIS) {
096                // This appears to be needed to avoid missing imports
097                Iterator modules = getAST().getModules().iterator();
098                while (modules.hasNext()) {
099                    ModuleNode module = (ModuleNode) modules.next();
100                    module.setImportsResolved(false);
101                }
102            }
103        }
104    
105        public int getStubCount() {
106            return stubCount;
107        }
108    
109        @Override
110        public void compile() throws CompilationFailedException {
111            stubCount = 0;
112            super.compile(Phases.CONVERSION);
113        }
114    
115        @Override
116        public void configure(final CompilerConfiguration config) {
117            super.configure(config);
118            // GroovyClassLoader should be able to find classes compiled from java sources
119            File targetDir = config.getTargetDirectory();
120            if (targetDir != null) {
121                final String classOutput = targetDir.getAbsolutePath();
122                getClassLoader().addClasspath(classOutput);
123            }
124        }
125    
126        @Override
127        public SourceUnit addSource(final File file) {
128            if (file.getName().toLowerCase().endsWith(DOT_GROOVY)) {
129                return super.addSource(file);
130            }
131            return null;
132        }
133    
134        @Override
135        public SourceUnit addSource(URL url) {
136            if (url.getPath().toLowerCase().endsWith(DOT_GROOVY)) {
137                return super.addSource(url);
138            }
139            return null;
140        }
141    }