git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@713173 13f79535-47bb-0310-9956-ffa450edef68master
@@ -20,20 +20,18 @@ package org.apache.tools.ant.taskdefs; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.Writer; | |||
import java.io.BufferedWriter; | |||
import java.io.OutputStreamWriter; | |||
import java.io.FileOutputStream; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.Task; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.ResourceUtils; | |||
import org.apache.tools.ant.util.StringUtils; | |||
import org.apache.tools.ant.types.LogLevel; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.resources.FileProvider; | |||
import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.types.resources.LogOutputResource; | |||
import org.apache.tools.ant.types.resources.StringResource; | |||
/** | |||
* Writes a message to the Ant logging facilities. | |||
@@ -62,23 +60,14 @@ public class Echo extends Task { | |||
* @exception BuildException if something goes wrong with the build | |||
*/ | |||
public void execute() throws BuildException { | |||
if (output == null) { | |||
log(message, logLevel); | |||
} else { | |||
Writer out = null; | |||
try { | |||
OutputStream os = output instanceof FileProvider ? os = new FileOutputStream( | |||
((FileProvider) output).getFile(), append) : output.getOutputStream(); | |||
OutputStreamWriter osw = (encoding == null || "".equals(encoding)) ? new OutputStreamWriter( | |||
os) | |||
: new OutputStreamWriter(os, encoding); | |||
out = new BufferedWriter(osw); | |||
out.write(message, 0, message.length()); | |||
} catch (IOException ioe) { | |||
throw new BuildException(ioe, getLocation()); | |||
} finally { | |||
FileUtils.close(out); | |||
} | |||
final String msg = "".equals(message) ? StringUtils.LINE_SEP : message; | |||
try { | |||
ResourceUtils | |||
.copyResource(new StringResource(msg), output == null ? new LogOutputResource( | |||
this, logLevel) : output, null, null, false, false, append, null, "" | |||
.equals(encoding) ? null : encoding, getProject()); | |||
} catch (IOException ioe) { | |||
throw new BuildException(ioe, getLocation()); | |||
} | |||
} | |||
@@ -88,7 +77,7 @@ public class Echo extends Task { | |||
* @param msg Sets the value for the message variable. | |||
*/ | |||
public void setMessage(String msg) { | |||
this.message = msg; | |||
this.message = msg == null ? "" : msg; | |||
} | |||
/** | |||
@@ -97,7 +86,6 @@ public class Echo extends Task { | |||
* standard output | |||
*/ | |||
public void setFile(File file) { | |||
this.file = file; | |||
setOutput(new FileResource(getProject(), file)); | |||
} | |||
@@ -0,0 +1,35 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You 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 org.apache.tools.ant.types.resources; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
/** | |||
* Interface to be implemented by "appendable" resources. | |||
* @since Ant 1.8 | |||
*/ | |||
public interface Appendable { | |||
/** | |||
* Get an appending OutputStream. | |||
* @return OutputStream | |||
* @throws IOException if anything goes wrong | |||
*/ | |||
OutputStream getAppendOutputStream() throws IOException; | |||
} |
@@ -36,7 +36,7 @@ import org.apache.tools.ant.types.ResourceFactory; | |||
* @since Ant 1.7 | |||
*/ | |||
public class FileResource extends Resource implements Touchable, FileProvider, | |||
ResourceFactory { | |||
ResourceFactory, Appendable { | |||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
private static final int NULL_FILE | |||
@@ -209,11 +209,25 @@ public class FileResource extends Resource implements Touchable, FileProvider, | |||
*/ | |||
public OutputStream getOutputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getOutputStream(); | |||
return ((FileResource) getCheckedRef()).getOutputStream(); | |||
} | |||
return getOutputStream(false); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public OutputStream getAppendOutputStream() throws IOException { | |||
if (isReference()) { | |||
return ((FileResource) getCheckedRef()).getAppendOutputStream(); | |||
} | |||
return getOutputStream(true); | |||
} | |||
private OutputStream getOutputStream(boolean append) throws IOException { | |||
File f = getNotNullFile(); | |||
if (f.exists()) { | |||
if (f.isFile()) { | |||
if (f.isFile() && !append) { | |||
f.delete(); | |||
} | |||
} else { | |||
@@ -222,7 +236,7 @@ public class FileResource extends Resource implements Touchable, FileProvider, | |||
p.mkdirs(); | |||
} | |||
} | |||
return new FileOutputStream(f); | |||
return append ? new FileOutputStream(f.getAbsolutePath(), true) : new FileOutputStream(f); | |||
} | |||
/** | |||
@@ -0,0 +1,68 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You 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 org.apache.tools.ant.types.resources; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import org.apache.tools.ant.ProjectComponent; | |||
import org.apache.tools.ant.taskdefs.LogOutputStream; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Output-only Resource that always appends to Ant's log. | |||
* @since Ant 1.8 | |||
*/ | |||
public class LogOutputResource extends Resource implements Appendable { | |||
private static final String NAME = "[Ant log]"; | |||
private LogOutputStream outputStream; | |||
/** | |||
* Create a new LogOutputResource. | |||
* @param managingComponent | |||
*/ | |||
public LogOutputResource(ProjectComponent managingComponent) { | |||
super(NAME); | |||
outputStream = new LogOutputStream(managingComponent); | |||
} | |||
/** | |||
* Create a new LogOutputResource. | |||
* @param managingComponent owning log content | |||
* @param level log level | |||
*/ | |||
public LogOutputResource(ProjectComponent managingComponent, int level) { | |||
super(NAME); | |||
outputStream = new LogOutputStream(managingComponent, level); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public OutputStream getAppendOutputStream() throws IOException { | |||
return outputStream; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
*/ | |||
public OutputStream getOutputStream() throws IOException { | |||
return outputStream; | |||
} | |||
} |
@@ -469,15 +469,52 @@ public class FileUtils { | |||
* | |||
* @since Ant 1.6 | |||
*/ | |||
public void copyFile(File sourceFile, File destFile, | |||
FilterSetCollection filters, Vector filterChains, | |||
boolean overwrite, boolean preserveLastModified, | |||
String inputEncoding, String outputEncoding, | |||
Project project) throws IOException { | |||
copyFile(sourceFile, destFile, filters, filterChains, overwrite, preserveLastModified, | |||
false, inputEncoding, outputEncoding, project); | |||
} | |||
/** | |||
* Convenience method to copy a file from a source to a | |||
* destination specifying if token filtering must be used, if | |||
* filter chains must be used, if source files may overwrite | |||
* newer destination files and the last modified time of | |||
* <code>destFile</code> file should be made equal | |||
* to the last modified time of <code>sourceFile</code>. | |||
* | |||
* @param sourceFile the file to copy from. | |||
* Must not be <code>null</code>. | |||
* @param destFile the file to copy to. | |||
* Must not be <code>null</code>. | |||
* @param filters the collection of filters to apply to this copy. | |||
* @param filterChains filterChains to apply during the copy. | |||
* @param overwrite Whether or not the destination file should be | |||
* overwritten if it already exists. | |||
* @param preserveLastModified Whether or not the last modified time of | |||
* the resulting file should be set to that | |||
* of the source file. | |||
* @param append whether to append to the destination file. | |||
* @param inputEncoding the encoding used to read the files. | |||
* @param outputEncoding the encoding used to write the files. | |||
* @param project the project instance. | |||
* | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.8 | |||
*/ | |||
public void copyFile(File sourceFile, File destFile, | |||
FilterSetCollection filters, Vector filterChains, | |||
boolean overwrite, boolean preserveLastModified, | |||
boolean overwrite, boolean preserveLastModified, boolean append, | |||
String inputEncoding, String outputEncoding, | |||
Project project) throws IOException { | |||
ResourceUtils.copyResource( | |||
new FileResource(sourceFile), new FileResource(destFile), | |||
filters, filterChains, overwrite, preserveLastModified, | |||
inputEncoding, outputEncoding, project); | |||
ResourceUtils.copyResource(new FileResource(sourceFile), new FileResource(destFile), | |||
filters, filterChains, overwrite, preserveLastModified, append, inputEncoding, | |||
outputEncoding, project); | |||
} | |||
// CheckStyle:ParameterNumberCheck ON | |||
@@ -39,6 +39,7 @@ import org.apache.tools.ant.types.TimeComparison; | |||
import org.apache.tools.ant.types.ResourceFactory; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
import org.apache.tools.ant.types.FilterSetCollection; | |||
import org.apache.tools.ant.types.resources.Appendable; | |||
import org.apache.tools.ant.types.resources.FileProvider; | |||
import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.types.resources.Union; | |||
@@ -265,12 +266,46 @@ public class ResourceUtils { | |||
String inputEncoding, String outputEncoding, | |||
Project project) | |||
throws IOException { | |||
if (!overwrite) { | |||
long slm = source.getLastModified(); | |||
if (dest.isExists() && slm != 0 | |||
&& dest.getLastModified() > slm) { | |||
return; | |||
} | |||
copyResource(source, dest, filters, filterChains, overwrite, preserveLastModified, false, inputEncoding, outputEncoding, project); | |||
} | |||
// CheckStyle:ParameterNumberCheck OFF - bc | |||
/** | |||
* Convenience method to copy content from one Resource to another | |||
* specifying whether token filtering must be used, whether filter chains | |||
* must be used, whether newer destination files may be overwritten and | |||
* whether the last modified time of <code>dest</code> file should be made | |||
* equal to the last modified time of <code>source</code>. | |||
* | |||
* @param source the Resource to copy from. | |||
* Must not be <code>null</code>. | |||
* @param dest the Resource to copy to. | |||
* Must not be <code>null</code>. | |||
* @param filters the collection of filters to apply to this copy. | |||
* @param filterChains filterChains to apply during the copy. | |||
* @param overwrite Whether or not the destination Resource should be | |||
* overwritten if it already exists. | |||
* @param preserveLastModified Whether or not the last modified time of | |||
* the destination Resource should be set to that | |||
* of the source. | |||
* @param append Whether to append to an Appendable Resource. | |||
* @param inputEncoding the encoding used to read the files. | |||
* @param outputEncoding the encoding used to write the files. | |||
* @param project the project instance. | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.8 | |||
*/ | |||
public static void copyResource(Resource source, Resource dest, | |||
FilterSetCollection filters, Vector filterChains, | |||
boolean overwrite, boolean preserveLastModified, boolean append, | |||
String inputEncoding, String outputEncoding, | |||
Project project) | |||
throws IOException { | |||
if (!(overwrite || SelectorUtils.isOutOfDate(source, dest, FileUtils.getFileUtils() | |||
.getFileTimestampGranularity()))) { | |||
return; | |||
} | |||
final boolean filterSetsAvailable = (filters != null | |||
&& filters.hasFilters()); | |||
@@ -288,12 +323,12 @@ public class ResourceUtils { | |||
inputEncoding); | |||
} | |||
in = new BufferedReader(isr); | |||
OutputStreamWriter osw = null; | |||
OutputStream os = getOutputStream(dest, append, project); | |||
OutputStreamWriter osw; | |||
if (outputEncoding == null) { | |||
osw = new OutputStreamWriter(dest.getOutputStream()); | |||
osw = new OutputStreamWriter(os); | |||
} else { | |||
osw = new OutputStreamWriter(dest.getOutputStream(), | |||
outputEncoding); | |||
osw = new OutputStreamWriter(os, outputEncoding); | |||
} | |||
out = new BufferedWriter(osw); | |||
if (filterChainsAvailable) { | |||
@@ -339,12 +374,12 @@ public class ResourceUtils { | |||
inputEncoding); | |||
} | |||
in = new BufferedReader(isr); | |||
OutputStreamWriter osw = null; | |||
OutputStream os = getOutputStream(dest, append, project); | |||
OutputStreamWriter osw; | |||
if (outputEncoding == null) { | |||
osw = new OutputStreamWriter(dest.getOutputStream()); | |||
osw = new OutputStreamWriter(os); | |||
} else { | |||
osw = new OutputStreamWriter(dest.getOutputStream(), | |||
outputEncoding); | |||
osw = new OutputStreamWriter(os, outputEncoding); | |||
} | |||
out = new BufferedWriter(osw); | |||
if (filterChainsAvailable) { | |||
@@ -373,7 +408,7 @@ public class ResourceUtils { | |||
OutputStream out = null; | |||
try { | |||
in = source.getInputStream(); | |||
out = dest.getOutputStream(); | |||
out = getOutputStream(dest, append, project); | |||
byte[] buffer = new byte[FileUtils.BUF_SIZE]; | |||
int count = 0; | |||
@@ -587,4 +622,15 @@ public class ResourceUtils { | |||
} | |||
} | |||
private static OutputStream getOutputStream(Resource resource, boolean append, Project project) | |||
throws IOException { | |||
if (append) { | |||
if (resource instanceof Appendable) { | |||
return ((Appendable) resource).getAppendOutputStream(); | |||
} | |||
project.log("Appendable OutputStream not available for non-appendable resource " | |||
+ resource + "; using plain OutputStream", Project.MSG_VERBOSE); | |||
} | |||
return resource.getOutputStream(); | |||
} | |||
} |
@@ -86,6 +86,9 @@ | |||
<target name="testAppend"> | |||
<echo file="${output}/echo.txt">Simple text</echo> | |||
<echo file="${output}/echo.txt" append="true">Appended</echo> | |||
<concat> | |||
<file file="${output}/echo.txt" /> | |||
</concat> | |||
<au:assertTrue> | |||
<resourcecount count="1"> | |||
<restrict> | |||