![JAR search and dependency download from the Maven repository](/logo.png)
protoj.lang.CompileFeature Maven / Gradle / Ivy
Show all versions of protoj-jdk6 Show documentation
/**
* Copyright 2009 Ashley Williams
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package protoj.lang;
import java.io.File;
import java.util.List;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.DirSet;
import org.apache.tools.ant.types.FileSet;
import protoj.lang.internal.InformationException;
import protoj.util.AntTarget;
import protoj.util.ArgRunnable;
import protoj.util.AspectJCompileTask;
import protoj.util.JavacCompileTask;
/**
* Compiles the project source Java (.java) files. Compilation of AspectJ (.aj)
* files is also supported without any additional software. Note that the
* {@link #compile(String, String)} method is used to fully compile the project
* from a programmatic call or from the compile command. The
* {@link #compileAjc(List)} and {@link #compileJavac(List)} methods are used
* usually from the command line as an alternative to calling the initial javac
* in order to compile the core bootstrapping part of this project.
*
*
* @author Ashley Williams
*
*/
public final class CompileFeature {
/**
* See {@link #getParent()}.
*/
private final StandardProject parent;
/**
* The callback object used to provide extra configuration.
*/
private ArgRunnable config;
/**
* See {@link #getAjcCompileTask()}.
*/
private AspectJCompileTask ajcCompileTask;
/**
* See {@link #isAspectCompiler()}.
*/
private boolean aspectCompiler;
/**
* See {@link #getJavacCompileTask()}.
*/
private JavacCompileTask javacCompileTask;
/**
* See the getters corresponding to the parameters here.
*
* @param parent
*/
public CompileFeature(StandardProject parent) {
this.parent = parent;
this.aspectCompiler = false;
}
/**
* See {@link #isAspectCompiler()} and {@link #getConfig()}.
*
* @param aspectCompiler
* @param config
*/
public void initConfig(boolean aspectCompiler,
ArgRunnable config) {
this.aspectCompiler = aspectCompiler;
this.config = config;
}
/**
* Pass-thru method to
* {@link JavacCompileTask#initCrossCompile(String, String, String)}, that
* additionally will allow the following property overrides to apply if
* specified: {@link StandardProperties#getCompileTarget()},
* {@link StandardProperties#getCompileExtdirs()} and
* {@link StandardProperties#getCompileBootclasspath()}.
*
* @param target
* @param extdirs
* @param bootclasspath
*/
public void initJavacCrossCompile(String target, String extdirs,
String bootclasspath) {
getJavacCompileTask().initCrossCompile(target, extdirs, bootclasspath);
}
/**
* Pass-thru method to
* {@link AspectJCompileTask#initCrossCompile(String, String, String)}, that
* additionally will allow the following property overrides to apply if
* specified: {@link StandardProperties#getCompileTarget()},
* {@link StandardProperties#getCompileExtdirs()} and
* {@link StandardProperties#getCompileBootclasspath()}.
*
* @param target
* @param extdirs
* @param bootclasspath
*/
public void initAjcCrossCompile(String target, String extdirs,
String bootclasspath) {
getAjcCompileTask().initCrossCompile(target, extdirs, bootclasspath);
}
/**
* Delegates to the underlying ant task and additionally will allow an
* override from {@link StandardProperties#getCompileSource()} if specified.
*
* @param source
*/
public void initJavacSource(String source) {
getJavacCompileTask().getCompileTask().setSource(source);
}
/**
* Delegates to the underlying ant task and additionally will allow an
* override from {@link StandardProperties#getCompileSource()} if specified.
*
* @param source
*/
public void initAjcSource(String source) {
getAjcCompileTask().getCompileTask().setSource(source);
}
/**
* Delegates to the underlying ant task and additionally will allow an
* override from {@link StandardProperties#getCompileMemory()} if specified.
*
* @param memory
*/
public void initAjcMemory(String memory) {
getAjcCompileTask().getCompileTask().setMaxmem(memory);
}
/**
* Delegates to the underlying ant task and additionally will allow an
* override from {@link StandardProperties#getCompileMemory()} if specified.
*
* @param memory
*/
public void initJavacMemory(String memory) {
getJavacCompileTask().getCompileTask().setMemoryMaximumSize(memory);
}
/**
* The instance used to configure the api. This gets called back during the
* call to {@link #compile(String, String)}.
*
* @return
*/
public ArgRunnable getConfig() {
return config;
}
/**
* The ant wrapper used to carry out aspectj compilation.
*
* @return
*/
public AspectJCompileTask getAjcCompileTask() {
return ajcCompileTask;
}
/**
* The ant wrapper used to carry out javac compilation.
*
* @return
*/
public JavacCompileTask getJavacCompileTask() {
return javacCompileTask;
}
/**
* Compiles the source code based on the specified ant patterns. Resources
* are initially copied to the classes directory.
*
* @param includes
* can be null to include all
* @param excludes
* can be null to exclude nothing
*/
public void compile(String includes, String excludes) {
// use if statement, don't need polymorphism
if (aspectCompiler) {
compileAjc(includes, excludes);
} else {
compileJavac(includes, excludes);
}
}
/**
* Invokes the aspectj compiler.
*
* @param includes
* @param excludes
*/
public void compileAjc(String includes, String excludes) {
copyResources(null, null);
ajcCompileTask = createAjcTask();
DirSet dirSet = ajcCompileTask.getDirSet();
if (includes != null) {
dirSet.setIncludes(includes);
}
if (excludes != null) {
dirSet.setExcludes(excludes);
}
if (config != null) {
config.run(this);
}
ajcCompileTask.execute();
if (!ajcCompileTask.isSuccess()) {
throw new InformationException(
"there was a problem compiling the source code");
}
}
/**
* Invokes the javac compiler.
*
* @param includes
* @param excludes
*/
public void compileJavac(String includes, String excludes) {
copyResources(null, null);
javacCompileTask = createJavacTask();
DirSet dirSet = javacCompileTask.getDirSet();
if (includes != null) {
dirSet.setIncludes(includes);
}
if (excludes != null) {
dirSet.setExcludes(excludes);
}
if (config != null) {
config.run(this);
}
javacCompileTask.execute();
if (!javacCompileTask.isSuccess()) {
throw new InformationException(
"there was a problem compiling the source code");
}
}
/**
* Compiles a set of files in the source directory using the javac compiler.
* The options parameter contains name value pairs to be applied to the
* underlying ant task by beans introspection, so that the compiler can
* easily be configured from the command line.
*
* The bean being configured is the JavacCompileTask instance. For example a
* string with the content "compileTask.source=1.5" is equivalent to calling
* JavacCompileTask.getCompileTask().setSource("1.5")
.
*
* If the source directory doesn't exist then this method does nothing.
*
* Resources are initially copied but not including any aop.xml files. This
* is because they may point to aspects that don't even exist yet until a
* full compile has been carried out.
*
* @param options
*/
public void compileJavac(List options) {
File srcDir = parent.getLayout().getSrcDir();
if (srcDir.exists()) {
copyResources(null, "**/aop.xml");
parent.getLogger().info("applying javac options:");
JavacCompileTask task = createJavacTask();
assignProperties(options, task);
task.execute();
if (!task.isSuccess()) {
throw new InformationException(
"there was a problem compiling the source code");
}
}
}
/**
* Aspectj compiling equivalent of {@link #compileJavac(List)}.
*
* @param options
*/
public void compileAjc(List options) {
File srcDir = parent.getLayout().getSrcDir();
if (srcDir.exists()) {
copyResources(null, "**/aop.xml");
parent.getLogger().info("applying ajc options:");
AspectJCompileTask task = createAjcTask();
assignProperties(options, task);
task.execute();
if (!task.isSuccess()) {
throw new InformationException(
"there was a problem compiling the source code");
}
}
}
/**
* Assigns the name=value pairs in the opts list to the given task using
* beans utils.
*
* @param opts
* @param task
*/
private void assignProperties(List opts, Object task) {
for (String opt : opts) {
String[] property = opt.split("=");
String name = property[0];
String value = property[1];
parent.getLogger().info(String.format("%s=%s", name, value));
PropertyUtils.setProperty(task, name, value);
}
}
/**
* True if the ajc compiler is configured, false if the javac compiler is
* configured.
*
* @return
*/
public boolean isAspectCompiler() {
return aspectCompiler;
}
/**
* Creates the ajc compile implementation instance.
*
* @return
*/
public AspectJCompileTask createAjcTask() {
ProjectLayout layout = parent.getLayout();
AspectJCompileTask task = new AspectJCompileTask(layout.getJavaDir(),
layout.getClassesDir(), layout.getClasspathConfig());
task.initLogging();
task.getCompileTask().setFailonerror(true);
return task;
}
/**
* Creates the javac compile implementation instance.
*
* @return
*/
public JavacCompileTask createJavacTask() {
ProjectLayout layout = parent.getLayout();
JavacCompileTask task = new JavacCompileTask(layout.getJavaDir(),
layout.getClassesDir(), parent.getLayout().getClasspathConfig());
task.initLogging();
return task;
}
/**
* Copies the files in the resources directory into the classes directory.
*
* @param includes
* the ant pattern of files to be included, null means all
* @param excludes
* the ant pattern of files to be excluded, null means none
*/
public void copyResources(String includes, String excludes) {
AntTarget target = new AntTarget("compile-feature-copy");
ProjectLayout layout = parent.getLayout();
layout.getClassesDir().mkdirs();
Copy copy = new Copy();
target.addTask(copy);
copy.setTaskName("copy");
copy.setTodir(layout.getClassesDir());
FileSet resourceFiles = new FileSet();
resourceFiles.setDir(layout.getResourcesDir());
if (includes != null) {
resourceFiles.setIncludes(includes);
}
if (excludes != null) {
resourceFiles.setExcludes(excludes);
}
copy.addFileset(resourceFiles);
target.execute();
}
/**
* The owning instance.
*
* @return
*/
public StandardProject getParent() {
return parent;
}
}