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_6; 018 019 import groovy.lang.GroovyClassLoader; 020 import org.codehaus.gmaven.feature.Component; 021 import org.codehaus.gmaven.feature.support.FeatureSupport; 022 import org.codehaus.gmaven.runtime.ClassCompiler; 023 import org.codehaus.gmaven.runtime.support.CompilerSupport; 024 import org.codehaus.groovy.control.CompilationUnit; 025 import org.codehaus.groovy.control.CompilerConfiguration; 026 import org.codehaus.groovy.tools.GroovyClass; 027 028 import java.net.URL; 029 import java.security.CodeSource; 030 import java.util.Iterator; 031 import java.util.List; 032 033 /** 034 * Provides the class compilation feature. 035 * 036 * @version $Id: ClassCompilerFeature.java 91 2010-07-05 21:06:12Z user57 $ 037 * @author <a href="mailto:jason@planet57.com">Jason Dillon</a> 038 */ 039 public class ClassCompilerFeature 040 extends FeatureSupport 041 { 042 public ClassCompilerFeature() { 043 super(ClassCompiler.KEY); 044 } 045 046 @Override 047 protected Component doCreate() throws Exception { 048 return new ClassCompilerImpl(); 049 } 050 051 // 052 // ClassCompilerImpl 053 // 054 055 private class ClassCompilerImpl 056 extends CompilerSupport 057 implements ClassCompiler, ClassCompiler.Keys 058 { 059 private final CompilerConfiguration cc = new CompilerConfiguration(); 060 061 private URL[] classPath; 062 063 private ClassCompilerImpl() throws Exception { 064 super(ClassCompilerFeature.this); 065 066 } 067 068 private void configure() { 069 cc.setVerbose(config.get(VERBOSE, false)); 070 071 cc.setDebug(config.get(DEBUG, false)); 072 073 if (config.contains(TOLERANCE)) { 074 cc.setTolerance(config.get(TOLERANCE, 0)); 075 } 076 077 if (config.contains(TARGET_BYTECODE)) { 078 cc.setTargetBytecode(config.get(TARGET_BYTECODE, (String)null)); 079 } 080 081 if (config.contains(SCRIPT_BASE_CLASSNAME)) { 082 cc.setScriptBaseClass(config.get(SCRIPT_BASE_CLASSNAME, (String)null)); 083 } 084 085 if (config.contains(DEFAULT_SCRIPT_EXTENSION)) { 086 cc.setDefaultScriptExtension(config.get(DEFAULT_SCRIPT_EXTENSION, (String)null)); 087 } 088 089 if (config.contains(WARNING_LEVEL)) { 090 cc.setTolerance(config.get(WARNING_LEVEL, 0)); 091 } 092 093 if (config.contains(SOURCE_ENCODING)) { 094 cc.setSourceEncoding(config.get(SOURCE_ENCODING, (String)null)); 095 } 096 } 097 098 public void setClassPath(final URL[] urls) { 099 assert urls != null && urls.length > 0; 100 101 this.classPath = urls; 102 } 103 104 public URL[] getClassPath() { 105 if (classPath == null || classPath.length == 0) { 106 throw new IllegalStateException("Classpath not bound, or is empty"); 107 } 108 109 return classPath; 110 } 111 112 public int compile() throws Exception { 113 if (sources.isEmpty()) { 114 log.debug("No sources added to compile; skipping"); 115 116 return 0; 117 } 118 119 configure(); 120 cc.setTargetDirectory(getTargetDirectory().getCanonicalPath()); 121 122 // 123 // NOTE: Do not use the CL from this class or it will mess up resolution 124 // when using classes from groovy* which depend on other artifacts, 125 // also don't really want to pollute the classpath with our dependencies. 126 // 127 128 ClassLoader parent = ClassLoader.getSystemClassLoader(); 129 130 GroovyClassLoader gcl = new GroovyClassLoader(parent, cc); 131 132 log.debug("Classpath:"); 133 134 // Append each URL to the GCL 135 URL[] classpath = getClassPath(); 136 137 for (int i=0; i<classpath.length; i++) { 138 gcl.addURL(classpath[i]); 139 140 log.debug(" {}", classpath[i]); 141 } 142 143 // 144 // TODO: See if we should set the CodeSource to something? 145 // 146 147 CodeSource security = null; 148 GroovyClassLoader transformLoader = new GroovyClassLoader(getClass().getClassLoader()); 149 for (int i=0; i<classpath.length; i++) { 150 transformLoader.addURL(classpath[i]); 151 } 152 153 CompilationUnit cu = new CompilationUnit(cc, security, gcl, transformLoader); 154 log.debug("Compiling {} sources", String.valueOf(sources.size())); 155 156 for (Iterator iter = sources.iterator(); iter.hasNext();) { 157 URL url = (URL) iter.next(); 158 log.debug(" {}", url); 159 160 cu.addSource(url); 161 } 162 163 cu.compile(); 164 165 List classes = cu.getClasses(); 166 167 if (log.isDebugEnabled()) { 168 log.debug("Compiled {} classes:", String.valueOf(classes.size())); 169 170 for (Iterator iter = classes.iterator(); iter.hasNext();) { 171 log.debug(" {}", ((GroovyClass)iter.next()).getName()); 172 } 173 } 174 175 return classes.size(); 176 } 177 } 178 }