|
|
@@ -1,610 +0,0 @@ |
|
|
|
/* |
|
|
|
* The Apache Software License, Version 1.1 |
|
|
|
* |
|
|
|
* Copyright (c) 2000-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 |
|
|
|
* <http://www.apache.org/>. |
|
|
|
*/ |
|
|
|
|
|
|
|
package org.apache.tools.ant; |
|
|
|
|
|
|
|
import java.io.File; |
|
|
|
import java.io.FileInputStream; |
|
|
|
import java.io.PrintStream; |
|
|
|
import java.io.FileOutputStream; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.util.Vector; |
|
|
|
import java.util.Properties; |
|
|
|
import java.util.Enumeration; |
|
|
|
|
|
|
|
/** |
|
|
|
* A bean to use to embed ant in a project. |
|
|
|
* |
|
|
|
* Based on Main.java. |
|
|
|
* |
|
|
|
* Note: this is the result of refactoring Main. Some methods are not |
|
|
|
* usefull for embeded use or may have better names ( I used the |
|
|
|
* option name from Main, for consistency ). I marked them with @experimental. |
|
|
|
* |
|
|
|
* @experimental: the current API is not yet stable. |
|
|
|
* |
|
|
|
* @author duncan@x180.com |
|
|
|
* @author Costin Manolache |
|
|
|
* @since ant1.5 |
|
|
|
*/ |
|
|
|
public class AntBean extends Task { |
|
|
|
|
|
|
|
/** The default build file name */ |
|
|
|
public final static String DEFAULT_BUILD_FILENAME = "build.xml"; |
|
|
|
|
|
|
|
/** Our current message output status. Follows Project.MSG_XXX */ |
|
|
|
private int msgOutputLevel = Project.MSG_INFO; |
|
|
|
|
|
|
|
/** File that we are using for configuration */ |
|
|
|
private File buildFile; /** null */ |
|
|
|
private String searchForThis=null; |
|
|
|
|
|
|
|
/** Stream that we are using for logging */ |
|
|
|
private PrintStream out = System.out; |
|
|
|
|
|
|
|
/** Stream that we are using for logging error messages */ |
|
|
|
private PrintStream err = System.err; |
|
|
|
|
|
|
|
/** The build targets */ |
|
|
|
private Vector targets = new Vector(5); |
|
|
|
|
|
|
|
/** Set of properties that can be used by tasks */ |
|
|
|
private Properties definedProps = new Properties(); |
|
|
|
|
|
|
|
/** Names of classes to add as listeners to project */ |
|
|
|
private Vector listeners = new Vector(5); |
|
|
|
|
|
|
|
/** File names of property files to load on startup */ |
|
|
|
private Vector propertyFiles = new Vector(5); |
|
|
|
|
|
|
|
/** |
|
|
|
* The Ant logger class. There may be only one logger. It will have the |
|
|
|
* right to use the 'out' PrintStream. The class must implements the BuildLogger |
|
|
|
* interface |
|
|
|
*/ |
|
|
|
private String loggerClassname = null; |
|
|
|
|
|
|
|
/** |
|
|
|
* Indicates whether output to the log is to be unadorned. |
|
|
|
*/ |
|
|
|
private boolean emacsMode = false; |
|
|
|
|
|
|
|
private ClassLoader coreLoader; |
|
|
|
|
|
|
|
private ProjectHelper helper=null; |
|
|
|
|
|
|
|
private Project newProject=null; |
|
|
|
|
|
|
|
private boolean redirectOutput=true; |
|
|
|
|
|
|
|
|
|
|
|
public AntBean() { |
|
|
|
} |
|
|
|
|
|
|
|
// -------------------- Bean properties -------------------- |
|
|
|
// extracted from Main's command line processing code |
|
|
|
|
|
|
|
/** Global verbosity level |
|
|
|
*/ |
|
|
|
public void setOutputLevel( int level ) { |
|
|
|
msgOutputLevel=level; |
|
|
|
} |
|
|
|
|
|
|
|
public void setBuildfile( String name ) { |
|
|
|
buildFile = new File(name); |
|
|
|
} |
|
|
|
|
|
|
|
/** Add a listener class name |
|
|
|
*/ |
|
|
|
public void addListener( String s ) { |
|
|
|
listeners.addElement(s); |
|
|
|
} |
|
|
|
|
|
|
|
/** Set the logger class name ( -logger option in command |
|
|
|
* line ). |
|
|
|
* |
|
|
|
* @experimental LoggerClassName would be a better name |
|
|
|
*/ |
|
|
|
public void setLogger( String s ) { |
|
|
|
if (loggerClassname != null) { |
|
|
|
System.out.println("Only one logger class may be specified."); |
|
|
|
return; |
|
|
|
} |
|
|
|
loggerClassname = s; |
|
|
|
} |
|
|
|
|
|
|
|
/** Emacs mode for the output |
|
|
|
*/ |
|
|
|
public void setEmacs( boolean b ) { |
|
|
|
emacsMode = b; |
|
|
|
} |
|
|
|
|
|
|
|
/** The name of the build file to execute, by |
|
|
|
* searching in the filesystem. |
|
|
|
*/ |
|
|
|
public void setFind( String s ) { |
|
|
|
if (s==null) { |
|
|
|
searchForThis = s; |
|
|
|
} else { |
|
|
|
searchForThis = DEFAULT_BUILD_FILENAME; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** Same as -propertyfile |
|
|
|
*/ |
|
|
|
public void addPropertyfile( String s ) { |
|
|
|
propertyFiles.addElement(s); |
|
|
|
} |
|
|
|
|
|
|
|
/** Set the core loader, to be used to execute. |
|
|
|
*/ |
|
|
|
public void setCoreLoader( ClassLoader coreLoader ) { |
|
|
|
coreLoader=coreLoader; |
|
|
|
} |
|
|
|
|
|
|
|
/** Add a user-defined property |
|
|
|
*/ |
|
|
|
public void setUserProperty( String name, String value ) { |
|
|
|
definedProps.put( name, value ); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Add a target to be executed |
|
|
|
*/ |
|
|
|
public void addTarget(String arg ) { |
|
|
|
targets.addElement(arg); |
|
|
|
} |
|
|
|
|
|
|
|
/** Log file. It'll redirect the System output and logs to this |
|
|
|
* file. Supported by -logfile argument in ant - probably |
|
|
|
* a bad idea if you embed ant in an application. |
|
|
|
* |
|
|
|
* @experimental - I don't think it's a good idea. |
|
|
|
*/ |
|
|
|
public void setLogfile( String name ) { |
|
|
|
try { |
|
|
|
File logFile = new File(name); |
|
|
|
out = new PrintStream(new FileOutputStream(logFile)); |
|
|
|
err = out; |
|
|
|
System.setOut(out); |
|
|
|
System.setErr(out); |
|
|
|
} catch (IOException ioe) { |
|
|
|
String msg = "Cannot write on the specified log file. " + |
|
|
|
"Make sure the path exists and you have write permissions."; |
|
|
|
System.out.println(msg); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** Redirect the output and set a security manager before |
|
|
|
* executing ant. Defaults to true for backward comptibility, |
|
|
|
* you should set it to false if you embed ant. |
|
|
|
*/ |
|
|
|
public void setRedirectOutput( boolean b ) { |
|
|
|
redirectOutput=b; |
|
|
|
} |
|
|
|
|
|
|
|
// -------------------- Property getters -------------------- |
|
|
|
|
|
|
|
|
|
|
|
/** Return the build file. If it was not explicitely specified, search |
|
|
|
* for it in the parent directories |
|
|
|
* |
|
|
|
* <P>Takes the "find" property as a suffix to append to each |
|
|
|
* parent directory in seach of a build file. Once the |
|
|
|
* root of the file-system has been reached an exception |
|
|
|
* is thrown. |
|
|
|
*/ |
|
|
|
public File getBuildFile() |
|
|
|
throws BuildException |
|
|
|
{ |
|
|
|
// if buildFile was not specified on the command line, |
|
|
|
if (buildFile == null) { |
|
|
|
// but -find then search for it |
|
|
|
if (searchForThis != null) { |
|
|
|
buildFile = findBuildFile(System.getProperty("user.dir"), |
|
|
|
searchForThis); |
|
|
|
} else { |
|
|
|
buildFile = new File(DEFAULT_BUILD_FILENAME); |
|
|
|
} |
|
|
|
} |
|
|
|
getProject().setUserProperty("ant.file" , buildFile.getAbsolutePath() ); |
|
|
|
return buildFile; |
|
|
|
} |
|
|
|
|
|
|
|
/** Return an (initialized) project constructed using the current |
|
|
|
* settings. |
|
|
|
* This will not load the build.xml file - you can 'load' the |
|
|
|
* project object with tasks manually or execute 'standalone' |
|
|
|
* tasks in the context of the project. |
|
|
|
*/ |
|
|
|
public Project getProject() { |
|
|
|
if( newProject!=null ) |
|
|
|
return newProject; |
|
|
|
loadProperties(); |
|
|
|
|
|
|
|
helper=ProjectHelper.getProjectHelper(); |
|
|
|
newProject = helper.createProject(coreLoader); |
|
|
|
newProject.setCoreLoader(coreLoader); |
|
|
|
|
|
|
|
addBuildListeners(newProject); |
|
|
|
|
|
|
|
newProject.fireBuildStarted(); |
|
|
|
|
|
|
|
newProject.init(); |
|
|
|
newProject.setUserProperty("ant.version", getAntVersion()); |
|
|
|
|
|
|
|
// set user-define properties |
|
|
|
Enumeration e = definedProps.keys(); |
|
|
|
while (e.hasMoreElements()) { |
|
|
|
String arg = (String)e.nextElement(); |
|
|
|
String value = (String)definedProps.get(arg); |
|
|
|
newProject.setUserProperty(arg, value); |
|
|
|
} |
|
|
|
|
|
|
|
return newProject; |
|
|
|
} |
|
|
|
|
|
|
|
private static String antVersion = null; |
|
|
|
|
|
|
|
/** @experimental |
|
|
|
* Ant version should be combined with the ProjectHelper version and type, |
|
|
|
* since it'll determine the set of features supported by ant ( at the xml |
|
|
|
* level ). |
|
|
|
*/ |
|
|
|
public static synchronized String getAntVersion() throws BuildException { |
|
|
|
if (antVersion == null) { |
|
|
|
try { |
|
|
|
Properties props = new Properties(); |
|
|
|
InputStream in = |
|
|
|
Main.class.getResourceAsStream("/org/apache/tools/ant/version.txt"); |
|
|
|
props.load(in); |
|
|
|
in.close(); |
|
|
|
|
|
|
|
String lSep = System.getProperty("line.separator"); |
|
|
|
StringBuffer msg = new StringBuffer(); |
|
|
|
msg.append("Apache Ant version "); |
|
|
|
msg.append(props.getProperty("VERSION")); |
|
|
|
msg.append(" compiled on "); |
|
|
|
msg.append(props.getProperty("DATE")); |
|
|
|
antVersion = msg.toString(); |
|
|
|
} catch (IOException ioe) { |
|
|
|
throw new BuildException("Could not load the version information:" |
|
|
|
+ ioe.getMessage()); |
|
|
|
} catch (NullPointerException npe) { |
|
|
|
throw new BuildException("Could not load the version information."); |
|
|
|
} |
|
|
|
} |
|
|
|
return antVersion; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------- Bean methods -------------------- |
|
|
|
Throwable error = null; |
|
|
|
|
|
|
|
|
|
|
|
/** Clean up allocated resources and finish the processing of the |
|
|
|
* current Project. |
|
|
|
*/ |
|
|
|
public void done() { |
|
|
|
newProject.fireBuildFinished(error); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Process an XML file and execute the targets. |
|
|
|
* |
|
|
|
* This method can be called multiple times, eventually after setting different |
|
|
|
* build file and different targets - all executions will happen in the |
|
|
|
* same execution context ( project ). |
|
|
|
*/ |
|
|
|
public void processBuildXml() throws BuildException { |
|
|
|
checkBuildFile(); |
|
|
|
File buildFile=getBuildFile(); |
|
|
|
Project newProject=getProject(); |
|
|
|
|
|
|
|
// first use the ProjectHelper to create the project object |
|
|
|
// from the given build file. |
|
|
|
String noParserMessage = |
|
|
|
"No JAXP compliant XML parser found. Please visit http://xml.apache.org for a suitable parser"; |
|
|
|
try { |
|
|
|
Class.forName("javax.xml.parsers.SAXParserFactory"); |
|
|
|
helper.parse(newProject, buildFile); |
|
|
|
} catch (NoClassDefFoundError ncdfe) { |
|
|
|
throw new BuildException(noParserMessage, ncdfe); |
|
|
|
} catch (ClassNotFoundException cnfe) { |
|
|
|
throw new BuildException(noParserMessage, cnfe); |
|
|
|
} catch (NullPointerException npe) { |
|
|
|
throw new BuildException(noParserMessage, npe); |
|
|
|
} |
|
|
|
|
|
|
|
// make sure that we have a target to execute |
|
|
|
if (targets.size() == 0) { |
|
|
|
targets.addElement(newProject.getDefaultTarget()); |
|
|
|
} |
|
|
|
|
|
|
|
newProject.executeTargets(targets); |
|
|
|
} |
|
|
|
|
|
|
|
public void execute() throws BuildException { |
|
|
|
|
|
|
|
try { |
|
|
|
if( redirectOutput ) { |
|
|
|
pushSystemOut(); |
|
|
|
} |
|
|
|
|
|
|
|
processBuildXml(); |
|
|
|
} catch(RuntimeException exc) { |
|
|
|
error = exc; |
|
|
|
throw exc; |
|
|
|
} catch(Error err) { |
|
|
|
error = err; |
|
|
|
throw err; |
|
|
|
} finally { |
|
|
|
done(); |
|
|
|
if( redirectOutput ) |
|
|
|
popSystemOut(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// -------------------- Private methods -------------------- |
|
|
|
|
|
|
|
private void checkBuildFile() throws BuildException { |
|
|
|
File buildFile=getBuildFile(); |
|
|
|
|
|
|
|
// make sure buildfile exists |
|
|
|
if (!buildFile.exists()) { |
|
|
|
System.out.println("Buildfile: " + buildFile + " does not exist!"); |
|
|
|
throw new BuildException("Build failed"); |
|
|
|
} |
|
|
|
|
|
|
|
// make sure it's not a directory (this falls into the ultra |
|
|
|
// paranoid lets check everything catagory |
|
|
|
if (buildFile.isDirectory()) { |
|
|
|
System.out.println("What? Buildfile: " + buildFile + " is a dir!"); |
|
|
|
throw new BuildException("Build failed"); |
|
|
|
} |
|
|
|
|
|
|
|
// track when we started |
|
|
|
if (msgOutputLevel >= Project.MSG_INFO) { |
|
|
|
System.out.println("Buildfile: " + buildFile); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private PrintStream oldErr=null; |
|
|
|
private PrintStream oldOut=null; |
|
|
|
private SecurityManager oldsm = null; |
|
|
|
|
|
|
|
private void pushSystemOut() { |
|
|
|
oldErr = System.err; |
|
|
|
oldOut = System.out; |
|
|
|
|
|
|
|
// use a system manager that prevents from System.exit() |
|
|
|
// only in JDK > 1.1 |
|
|
|
if ( !Project.JAVA_1_0.equals(Project.getJavaVersion()) && |
|
|
|
!Project.JAVA_1_1.equals(Project.getJavaVersion()) ){ |
|
|
|
oldsm = System.getSecurityManager(); |
|
|
|
|
|
|
|
//SecurityManager can not be installed here for backwards |
|
|
|
//compatability reasons (PD). Needs to be loaded prior to |
|
|
|
//ant class if we are going to implement it. |
|
|
|
//System.setSecurityManager(new NoExitSecurityManager()); |
|
|
|
} |
|
|
|
System.setOut(new PrintStream(new DemuxOutputStream(getProject(), false))); |
|
|
|
System.setErr(new PrintStream(new DemuxOutputStream(getProject(), true))); |
|
|
|
} |
|
|
|
|
|
|
|
private void popSystemOut() { |
|
|
|
// put back the original security manager |
|
|
|
//The following will never eval to true. (PD) |
|
|
|
if (oldsm != null){ |
|
|
|
System.setSecurityManager(oldsm); |
|
|
|
} |
|
|
|
|
|
|
|
if( oldOut!=null && oldErr!=null ) { |
|
|
|
System.setOut(oldOut); |
|
|
|
System.setErr(oldErr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected void addBuildListeners(Project newProject) { |
|
|
|
|
|
|
|
// Add the default listener |
|
|
|
newProject.addBuildListener(createLogger()); |
|
|
|
|
|
|
|
for (int i = 0; i < listeners.size(); i++) { |
|
|
|
String className = (String) listeners.elementAt(i); |
|
|
|
try { |
|
|
|
BuildListener listener = |
|
|
|
(BuildListener) Class.forName(className).newInstance(); |
|
|
|
newProject.addBuildListener(listener); |
|
|
|
} |
|
|
|
catch(Throwable exc) { |
|
|
|
throw new BuildException("Unable to instantiate listener " + className, exc); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Creates the default build logger for sending build events to the ant log. |
|
|
|
*/ |
|
|
|
protected BuildLogger createLogger() { |
|
|
|
BuildLogger logger = null; |
|
|
|
if (loggerClassname != null) { |
|
|
|
try { |
|
|
|
logger = (BuildLogger)(Class.forName(loggerClassname).newInstance()); |
|
|
|
} catch (ClassCastException e) { |
|
|
|
System.err.println("The specified logger class " + loggerClassname + |
|
|
|
" does not implement the BuildLogger interface"); |
|
|
|
throw new RuntimeException(); |
|
|
|
} catch (Exception e) { |
|
|
|
System.err.println("Unable to instantiate specified logger class " + |
|
|
|
loggerClassname + " : " + e.getClass().getName()); |
|
|
|
throw new RuntimeException(); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
logger = new DefaultLogger(); |
|
|
|
} |
|
|
|
|
|
|
|
logger.setMessageOutputLevel(msgOutputLevel); |
|
|
|
logger.setOutputPrintStream(out); |
|
|
|
logger.setErrorPrintStream(err); |
|
|
|
logger.setEmacsMode(emacsMode); |
|
|
|
|
|
|
|
return logger; |
|
|
|
} |
|
|
|
|
|
|
|
/** Load all propertyFiles |
|
|
|
*/ |
|
|
|
private void loadProperties() |
|
|
|
{ |
|
|
|
// Load the property files specified by -propertyfile |
|
|
|
for (int propertyFileIndex=0; |
|
|
|
propertyFileIndex < propertyFiles.size(); |
|
|
|
propertyFileIndex++) { |
|
|
|
String filename = (String) propertyFiles.elementAt(propertyFileIndex); |
|
|
|
Properties props = new Properties(); |
|
|
|
FileInputStream fis = null; |
|
|
|
try { |
|
|
|
fis = new FileInputStream(filename); |
|
|
|
props.load(fis); |
|
|
|
} |
|
|
|
catch (IOException e) { |
|
|
|
System.out.println("Could not load property file " |
|
|
|
+ filename + ": " + e.getMessage()); |
|
|
|
} finally { |
|
|
|
if (fis != null){ |
|
|
|
try { |
|
|
|
fis.close(); |
|
|
|
} catch (IOException e){ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// ensure that -D properties take precedence |
|
|
|
Enumeration propertyNames = props.propertyNames(); |
|
|
|
while (propertyNames.hasMoreElements()) { |
|
|
|
String name = (String) propertyNames.nextElement(); |
|
|
|
if (definedProps.getProperty(name) == null) { |
|
|
|
definedProps.put(name, props.getProperty(name)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// -------------------- XXX Move to FileUtil -------------------- |
|
|
|
|
|
|
|
/** |
|
|
|
* Helper to get the parent file for a given file. |
|
|
|
* |
|
|
|
* <P>Added to simulate File.getParentFile() from JDK 1.2. |
|
|
|
* |
|
|
|
* @param file File |
|
|
|
* @return Parent file or null if none |
|
|
|
*/ |
|
|
|
private File getParentFile(File file) { |
|
|
|
String filename = file.getAbsolutePath(); |
|
|
|
file = new File(filename); |
|
|
|
filename = file.getParent(); |
|
|
|
|
|
|
|
if (filename != null && msgOutputLevel >= Project.MSG_VERBOSE) { |
|
|
|
System.out.println("Searching in "+filename); |
|
|
|
} |
|
|
|
|
|
|
|
return (filename == null) ? null : new File(filename); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Search parent directories for the build file. |
|
|
|
* |
|
|
|
* <P>Takes the given target as a suffix to append to each |
|
|
|
* parent directory in seach of a build file. Once the |
|
|
|
* root of the file-system has been reached an exception |
|
|
|
* is thrown. |
|
|
|
* |
|
|
|
* @param suffix Suffix filename to look for in parents. |
|
|
|
* @return A handle to the build file |
|
|
|
* |
|
|
|
* @exception BuildException Failed to locate a build file |
|
|
|
*/ |
|
|
|
private File findBuildFile(String start, String suffix) throws BuildException { |
|
|
|
if (msgOutputLevel >= Project.MSG_INFO) { |
|
|
|
System.out.println("Searching for " + suffix + " ..."); |
|
|
|
} |
|
|
|
|
|
|
|
File parent = new File(new File(start).getAbsolutePath()); |
|
|
|
File file = new File(parent, suffix); |
|
|
|
|
|
|
|
// check if the target file exists in the current directory |
|
|
|
while (!file.exists()) { |
|
|
|
// change to parent directory |
|
|
|
parent = getParentFile(parent); |
|
|
|
|
|
|
|
// if parent is null, then we are at the root of the fs, |
|
|
|
// complain that we can't find the build file. |
|
|
|
if (parent == null) { |
|
|
|
throw new BuildException("Could not locate a build file!"); |
|
|
|
} |
|
|
|
|
|
|
|
// refresh our file handle |
|
|
|
file = new File(parent, suffix); |
|
|
|
} |
|
|
|
|
|
|
|
return file; |
|
|
|
} |
|
|
|
|
|
|
|
} |