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_5; 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 protected Component doCreate() throws Exception { 047 return new ClassCompilerImpl(); 048 } 049 050 // 051 // ClassCompilerImpl 052 // 053 054 private class ClassCompilerImpl 055 extends CompilerSupport 056 implements ClassCompiler, ClassCompiler.Keys 057 { 058 private final CompilerConfiguration cc = new CompilerConfiguration(); 059 060 private URL[] classPath; 061 062 private ClassCompilerImpl() throws Exception { 063 super(ClassCompilerFeature.this); 064 } 065 066 private void configure() { 067 cc.setVerbose(config.get(VERBOSE, false)); 068 069 cc.setDebug(config.get(DEBUG, false)); 070 071 if (config.contains(TOLERANCE)) { 072 cc.setTolerance(config.get(TOLERANCE, 0)); 073 } 074 075 if (config.contains(TARGET_BYTECODE)) { 076 cc.setTargetBytecode(config.get(TARGET_BYTECODE, (String)null)); 077 } 078 079 if (config.contains(SCRIPT_BASE_CLASSNAME)) { 080 cc.setScriptBaseClass(config.get(SCRIPT_BASE_CLASSNAME, (String)null)); 081 } 082 083 if (config.contains(DEFAULT_SCRIPT_EXTENSION)) { 084 cc.setDefaultScriptExtension(config.get(DEFAULT_SCRIPT_EXTENSION, (String)null)); 085 } 086 087 if (config.contains(WARNING_LEVEL)) { 088 cc.setTolerance(config.get(WARNING_LEVEL, 0)); 089 } 090 091 if (config.contains(SOURCE_ENCODING)) { 092 cc.setSourceEncoding(config.get(SOURCE_ENCODING, (String)null)); 093 } 094 } 095 096 public void setClassPath(final URL[] urls) { 097 assert urls != null && urls.length > 0; 098 099 this.classPath = urls; 100 } 101 102 public URL[] getClassPath() { 103 if (classPath == null || classPath.length == 0) { 104 throw new IllegalStateException("Classpath not bound, or is empty"); 105 } 106 107 return classPath; 108 } 109 110 public int compile() throws Exception { 111 if (sources.isEmpty()) { 112 log.debug("No sources added to compile; skipping"); 113 114 return 0; 115 } 116 117 configure(); 118 cc.setTargetDirectory(getTargetDirectory().getCanonicalPath()); 119 120 // 121 // NOTE: Do not use the CL from this class or it will mess up resolution 122 // when using classes from groovy* which depend on other artifacts, 123 // also don't really want to pollute the classpath with our dependencies. 124 // 125 126 ClassLoader parent = ClassLoader.getSystemClassLoader(); 127 128 GroovyClassLoader gcl = new GroovyClassLoader(parent, cc); 129 130 log.debug("Classpath:"); 131 132 // Append each URL to the GCL 133 URL[] classpath = getClassPath(); 134 135 for (int i=0; i<classpath.length; i++) { 136 gcl.addURL(classpath[i]); 137 138 log.debug(" {}", classpath[i]); 139 } 140 141 // 142 // TODO: See if we should set the CodeSource to something? 143 // 144 145 CodeSource security = null; 146 147 CompilationUnit cu = new CompilationUnit(cc, security, gcl); 148 149 log.debug("Compiling {} sources", String.valueOf(sources.size())); 150 151 for (Iterator iter = sources.iterator(); iter.hasNext();) { 152 URL url = (URL) iter.next(); 153 log.debug(" {}", url); 154 155 cu.addSource(url); 156 } 157 158 cu.compile(); 159 160 List classes = cu.getClasses(); 161 162 if (log.isDebugEnabled()) { 163 log.debug("Compiled {} classes:", String.valueOf(classes.size())); 164 165 for (Iterator iter = classes.iterator(); iter.hasNext();) { 166 log.debug(" {}", ((GroovyClass)iter.next()).getName()); 167 } 168 } 169 170 return classes.size(); 171 } 172 } 173 }