/* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Ant", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.apache.tools.ant.taskdefs.optional.python; import org.apache.tools.ant.taskdefs.MatchingTask; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.taskdefs.Java; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.DirectoryScanner; import java.io.File; /** * Jytonc is a Python compiler into Java Bytecode. So you can * call your python code from Java, and call you java code from * Python, create bean, servlet... * *

* * The task is a directory based task, so attributes like includes="*.py" and * excludes="broken.py" can be used to control the files pulled in. By default, * all *.py files from the project folder down are included in the command. * * @author Cyrille Morvan - cmorvan@ingenosya.com - Ingenosya France * @version 1.0 */ public class Jythonc extends MatchingTask { protected static final String JYTHONC_PY = "Tools/jythonc/jythonc.py"; protected static final String JYTHON_CLASS = "org.python.util.jython"; /** * The classpath for the virtual machine. */ protected Path classpath; /** * Put all compiled code into the named Java package. */ protected String packageName; /** * Specifies a .jar file to create and put the results of * the freeze into. Set the deep option to true. */ protected File jarFile; /** * the compiler. */ protected File jythoncpy; /** * Compile all Python dependencies of the module. This is * used for creating applets. */ protected boolean deep; /** * Include the core Jython libraries (about 130K). * Needed for applets since Netscape doesn't yet support * multiple archives. */ protected boolean core; /** * Include all of the Jython libraries (everything in core + compiler and * parser). */ protected boolean all; /** * Include Java dependencies from this list of packages. Default is * org.python.modules and org.apache.oro.text.regex. */ protected String addpackages; /** * Compile into jarfile, including the correct manifest for the bean. */ protected File jarFileBean; /** * Don't include any of these modules in compilation. This is a * comma-separated list of modules. */ protected String skipModule; /** * Compiler name. */ protected String compiler; /** * Use a different compiler than `standard' javac. If this is set to "NONE" * then compile ends with the generation of the Java source file. * Alternatively, you can set the property python.jythonc.compiler in the * registry. */ protected String compileropts; /** * Options passed directly to the Java compiler. Alternatively, you can set * the property python.jythonc.compileropts in the registry. */ protected String falsenames; /** * Path to jython directory. */ protected File jythonHome; /** * Destination, build directory. */ protected File destDir; /** * Source directory. */ protected File srcDir; /** * Specify the working directory where the generated Java source code is * placed. Default is "./jpywork" */ protected File workdir; /** * aditionnals args. */ protected String extraArgs; /** * constructor set up the search pattern */ public Jythonc() { setIncludes("**/*.py"); } /** * Add a classpath. Used to handle the nested classpath * element. * @return A Path object representing the classpath to be used. */ public Path createClasspath() { if(classpath == null) { classpath = new Path(this.getProject()); } return classpath.createPath(); } /** * Sets the classpath field. * @param classpath A Path object representing the "classpath" attribute. */ public void setClasspath(Path aClasspath) { classpath = aClasspath; } /** * Put all compiled code into the named Java package. * @param aString the packake name. */ public void setPackage(String aString) { packageName = aString; } /** * Specifies a .jar file to create and put the results of * the freeze into. Set the deep option to true. */ public void setJar(File aJarFile) { jarFile = aJarFile; deep = true; } /** * Include the core Jython libraries (about 130K). * Needed for applets since Netscape doesn't yet support * multiple archives. Set the deep option to true. */ public void setCore(boolean aValue) { core = aValue; deep = true; } /** * Include all of the Jython libraries (everything in core + compiler and * parser). Set the deep option to true. */ public void setAll(boolean aValue) { all = aValue; deep = true; } /** * Compile into jarfile, including the correct manifest for the bean. */ public void setBean(File aJarFileBean) { jarFileBean = aJarFileBean; } /** * Don't include any of these modules in compilation. This is a * comma-separated list of modules. */ public void setSkip(String aValue) { skipModule = aValue; } /** * Compile all Python dependencies of the module. This is * used for creating applets. */ public void setDeep(boolean aValue) { deep = aValue; } /** * Include Java dependencies from this list of packages. Default is * org.python.modules and org.apache.oro.text.regex. */ public void setAddpackages(String aValue) { addpackages = aValue; } /** * Specify the working directory where the generated Java source code is * placed. Default is "./jpywork" */ public void setWorkdir(File aValue) { if( aValue.exists() ) { if( ! aValue.isDirectory() ) { throw new BuildException( "Workdir ("+ aValue + ") is not a directory" ); } } else { aValue.mkdirs(); } workdir = aValue; } /** * Set the compiler. */ public void setCompiler(String aCompiler) { compiler = aCompiler; } /** * Options passed directly to the Java compiler. Alternatively, you can set * the property python.jythonc.compileropts in the registry. */ public void setCompileropts(String aValue) { compileropts = aValue; } /** * A comma-separated list of names that are always false. Can be used to * short-circuit if clauses. */ public void setFalsenames(String aValue) { falsenames = aValue; } /** * Jython home directory. */ public void setHome(File aFile) { jythonHome = aFile; } /** * Home for the source. */ public void setSrcdir(File aFile) { srcDir = aFile; } /** * Home for the destination (build). */ public void setDestdir(File aFile) { destDir = aFile; } /** * Change the default Python compiler. */ public void setJythoncpy(File aValue) { jythoncpy = aValue; } /** * sets some additional args to send to jythonc. */ public void setArgs(String aValue) { extraArgs = aValue; } /** * get the compiler option, null if none. */ public String getCompilerOptions() { StringBuffer aStringBuffer = new StringBuffer(); if( destDir != null ) { aStringBuffer.append("-d \""); aStringBuffer.append( destDir ); aStringBuffer.append("\""); createClasspath().setLocation(destDir); destDir.mkdirs(); } if( compileropts != null ) { aStringBuffer.append(compileropts); } if( aStringBuffer.length() == 0 ) { return null; } else { return aStringBuffer.toString(); } } /** * Get the path to the jython home (or python home) */ public File getPythonHome() { if(jythonHome == null ) { String aPythonHome = getProject().getProperty("python.home"); if(aPythonHome == null ) { throw new BuildException("No python.home or home specified"); } jythonHome = new File(aPythonHome); } return jythonHome; } /** * Get the path to the jython compiler file (in python). */ public File getJythoncPY() { if(jythoncpy == null ) { return new File(getPythonHome(),JYTHONC_PY); } return jythoncpy; } /** * Exectute the compiler. */ public void execute() { try { Java javaTask = null; javaTask = (Java)getProject().createTask("java"); javaTask.setTaskName("jythonc"); javaTask.setClassname( JYTHON_CLASS ); javaTask.createJvmarg().setValue( "-Dpython.home=" + getPythonHome() ); // classpath File aJythonJarFile = new File(getPythonHome(), "jython.jar" ); createClasspath().setLocation(aJythonJarFile); javaTask.setClasspath(classpath); // jythonc file javaTask.createArg().setFile( getJythoncPY() ); if( packageName != null ) { javaTask.createArg().setValue("--package"); javaTask.createArg().setValue(packageName); } if( jarFile != null ) { javaTask.createArg().setValue( "--jar" ); javaTask.createArg().setFile( jarFile ); } if(deep) { javaTask.createArg().setValue( "--deep" ); } if(core) { javaTask.createArg().setValue( "--core" ); } if(all) { javaTask.createArg().setValue( "--all" ); } if( jarFileBean != null ) { javaTask.createArg().setValue( "--bean" ); javaTask.createArg().setFile( jarFileBean ); } if( addpackages != null ) { javaTask.createArg().setValue( "--addpackages " ); javaTask.createArg().setValue( addpackages ); } if( workdir != null ) { javaTask.createArg().setValue( "--workdir " ); javaTask.createArg().setFile( workdir ); } if( skipModule != null ) { javaTask.createArg().setValue("--skip"); javaTask.createArg().setValue(skipModule); } // --compiler if( compiler == null ) { // try to use the compiler specified by build.compiler. Right now we are // just going to allow Jikes String buildCompiler = getProject().getProperty("build.compiler"); if (buildCompiler != null && buildCompiler.equals("jikes")) { javaTask.createArg().setValue("--compiler"); javaTask.createArg().setValue("jikes"); } } else { javaTask.createArg().setValue("--compiler"); javaTask.createArg().setValue(compiler); } String aCompilerOpts = getCompilerOptions(); if( aCompilerOpts != null ) { javaTask.createArg().setValue("--compileropts"); javaTask.createArg().setValue(aCompilerOpts); } if( falsenames != null ) { javaTask.createArg().setValue("--falsenames"); javaTask.createArg().setValue(falsenames); } if( extraArgs != null ) { javaTask.createArg().setLine(extraArgs); } //get dependencies list. if( srcDir == null ) { srcDir = project.resolveFile("."); } DirectoryScanner scanner = super.getDirectoryScanner(srcDir); String[] dependencies = scanner.getIncludedFiles(); log("compiling " + dependencies.length + " file" + ((dependencies.length == 1)?"":"s")); String baseDir = scanner.getBasedir().toString() + File.separator; //add to the command for (int i = 0; i < dependencies.length; i++) { String targetFile = dependencies[i]; javaTask.createArg().setValue(baseDir + targetFile); } // change the location directory javaTask.setDir(srcDir); javaTask.setFork(true); if (javaTask.executeJava() != 0) { throw new BuildException("jythonc reported an error"); } } catch (Exception e) { // Have to catch this because of the semantics of calling main() String msg = "Exception while calling " + JYTHON_CLASS + ". Details: " + e.toString(); throw new BuildException(msg, e); } } }