All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jace.ant.GenerateCppProxiesTask Maven / Gradle / Ivy

There is a newer version: 1.2.22
Show newest version
package org.jace.ant;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jace.proxy.AutoProxy;
import org.jace.metaclass.TypeName;
import org.jace.metaclass.TypeNameFactory;
import org.jace.proxy.ClassPath;
import org.jace.proxy.ProxyGenerator.AccessibilityType;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Set;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.DirSet;
import org.apache.tools.ant.types.Path;

/**
 * Generates C++ proxies for Java classes.
 *
 * Example:
 * <GenerateCppProxies inputHeaders="input/include" inputSources="input/source"
 * outputHeaders="output/include" outputSources="output/source" exportSymbols="false"
 * classpath="rt.jar" accessibility="PUBLIC">
 *   <classpath>
 *     <pathelement location="classes"/>
 *   </classpath>
 *   <dependency name="java.lang.String"/>
 *   <inputHeaders dir="input">
 *     <include name="include1">
 *     <include name="include2">
 *   </inputHeaders>
 *   <inputSources dir="input">
 *     <include name="source1">
 *     <include name="source2">
 *   </inputSources>
 * </GenerateCppProxies>
 *
 * @author Gili Tzbari
 */
public class GenerateCppProxiesTask extends Task
{
	private final Collection inputHeaders = Lists.newArrayList();
	private boolean inputHeadersSpecified = false;
	private final Collection inputSources = Lists.newArrayList();
	private boolean inputSourcesSpecified = false;
	private File outputHeaders;
	private File outputSources;
	private Path classpath = new Path(getProject());
	private AccessibilityType accessibility = AccessibilityType.PUBLIC;
	/**
	 * A list of fully-qualified class names that must be exported.
	 *
	 * When generating C++ proxies for a Java library, there is no way of
	 * knowing which classes will be referenced by 3rd-party code. This feature
	 * enables developers to export C++ proxies for Java classes even if they are
	 * not referenced at the time the generator is run.
	 */
	private Set dependencies = Sets.newHashSet();
	/**
	 * True if proxies should export their symbols (for DLLs/SOs).
	 */
	private boolean exportSymbols;

	/**
	 * Sets the directory containing the input header files.
	 *
	 * @param inputHeaders the directory containing the input header files
	 */
	public void setInputHeaders(String inputHeaders)
	{
		inputHeadersSpecified = true;
		this.inputHeaders.clear();
		for (String path: inputHeaders.split(File.pathSeparator))
			this.inputHeaders.add(new File(path));
	}

	/**
	 * Sets the directory containing the input source files.
	 *
	 * @param inputSources the directory containing the input source files
	 */
	public void setInputSources(String inputSources)
	{
		inputSourcesSpecified = true;
		this.inputSources.clear();
		for (String path: inputSources.split(File.pathSeparator))
			this.inputSources.add(new File(path));
	}

	/**
	 * Sets the directory containing the output header files.
	 *
	 * @param outputHeaders the directory containing the output header files
	 */
	public void setOutputHeaders(File outputHeaders)
	{
		this.outputHeaders = outputHeaders;
	}

	/**
	 * Sets the directory containing the output source files.
	 *
	 * @param outputSources the directory containing the output source files
	 */
	public void setOutputSources(File outputSources)
	{
		this.outputSources = outputSources;
	}

	/**
	 * Indicates the method accessibility to expose.
	 *
	 * For example, a value of PROTECTED indicates that public or protected
	 * methods should be generated.
	 * 
	 * @param accessibility PUBLIC, PROTECTED, PACKAGE or PRIVATE
	 * @throws IllegalArgumentException if an unknown accessibility type is specified
	 */
	public void setAccessibility(String accessibility) throws IllegalArgumentException
	{
		this.accessibility = AccessibilityType.valueOf(accessibility.toUpperCase());
	}

	/**
	 * Indicates if the proxy symbols should be exported (for generating DLLs/SOs).
	 *
	 * @param exportSymbols true if the proxy symbols should be exported
	 */
	public void setExportSymbols(boolean exportSymbols)
	{
		this.exportSymbols = exportSymbols;
	}

	/**
	 * Sets the Java classpath.
	 *
	 * @param classpath the Java classpath
	 */
	public void setClasspath(Path classpath)
	{
		this.classpath = classpath;
	}

	@Override
	public void execute() throws BuildException
	{
		if (!inputHeadersSpecified && !inputSourcesSpecified)
			throw new BuildException("Must specify at least one inputHeaders or inputSources directory",
				getLocation());
		if (inputHeadersSpecified && inputHeaders.isEmpty())
			throw new BuildException("inputHeaders refers to non-existant directories", getLocation());
		if (inputSourcesSpecified && inputSources.isEmpty())
			throw new BuildException("inputSources refers to non-existant directories", getLocation());
		if (outputHeaders == null)
			throw new BuildException("outputHeaders must be set", getLocation());
		if (outputSources == null)
			throw new BuildException("outputSources must be set", getLocation());
		log(toString(), Project.MSG_DEBUG);
		Set extraDependencies = Sets.newHashSetWithExpectedSize(dependencies.size());
		for (Dependency dependency: dependencies)
			extraDependencies.add(TypeNameFactory.fromIdentifier(dependency.getName()));
		AutoProxy.Builder autoProxy = new AutoProxy.Builder(inputHeaders, inputSources, outputHeaders,
			outputSources, new ClassPath(classpath.toString())).accessibility(accessibility).
			minimizeDependencies(true).exportSymbols(exportSymbols);
		for (TypeName dependency: extraDependencies)
			autoProxy.extraDependency(dependency);
		try
		{
			autoProxy.generateProxies();
		}
		catch (IOException e)
		{
			throw new BuildException(e);
		}
		catch (ClassNotFoundException e)
		{
			throw new BuildException(e);
		}
	}

	/**
	 * Adds a class that must have a C++ proxy generated.
	 *
	 * @param dependency a class that must have a C++ proxy generated
	 */
	public void addConfiguredDependency(Dependency dependency)
	{
		if (dependency.getName() == null)
			throw new BuildException("name must be set", getLocation());
		dependencies.add(dependency);
	}

	/**
	 * Adds to the Java classpath.
	 *
	 * @param classpath the Java classpath
	 */
	public void addConfiguredClasspath(Path classpath)
	{
		this.classpath.add(classpath);
	}

	/**
	 * Adds input header directories.
	 *
	 * @param headers the input header directories
	 */
	public void addConfiguredInputHeaders(DirSet headers)
	{
		inputHeadersSpecified = true;
		DirectoryScanner scanner = headers.getDirectoryScanner(getProject());
		scanner.scan();
		for (String directory: scanner.getIncludedDirectories())
			this.inputHeaders.add(new File(scanner.getBasedir(), directory));
	}

	/**
	 * Adds input source directories.
	 *
	 * @param sources the input source directories
	 */
	public void addConfiguredInputSources(DirSet sources)
	{
		inputSourcesSpecified = true;
		DirectoryScanner scanner = sources.getDirectoryScanner(getProject());
		scanner.scan();
		for (String directory: scanner.getIncludedDirectories())
			this.inputSources.add(new File(scanner.getBasedir(), directory));
	}

	@Override
	public String toString()
	{
		return getClass().getSimpleName() + "[inputHeaders=" + inputHeaders + ", inputSources="
					 + inputSources
					 + ", outputHeader=" + outputHeaders + ", outputSources=" + outputSources
					 + ", exportSymbols=" + exportSymbols
					 + "]";
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy