Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MSHARED-1216] Use caching output stream #73

Merged
merged 1 commit into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,6 @@ public void copyFile(MavenFileFilterRequest mavenFileFilterRequest) throws Maven
@Override
public void copyFile(File from, File to, boolean filtering, List<FilterWrapper> filterWrappers, String encoding)
throws MavenFilteringException {
// overwrite forced to false to preserve backward comp
copyFile(from, to, filtering, filterWrappers, encoding, false);
}

@Override
public void copyFile(
File from,
File to,
boolean filtering,
List<FilterWrapper> filterWrappers,
String encoding,
boolean overwrite)
throws MavenFilteringException {
try {
if (filtering) {
if (getLogger().isDebugEnabled()) {
Expand All @@ -106,7 +93,7 @@ public void copyFile(
if (getLogger().isDebugEnabled()) {
getLogger().debug("copy " + from.getPath() + " to " + to.getPath());
}
FilteringUtils.copyFile(from, to, encoding, new FilterWrapper[0], overwrite);
FilteringUtils.copyFile(from, to, encoding, new FilterWrapper[0], false);
}

buildContext.refresh(to);
Expand All @@ -117,4 +104,18 @@ public void copyFile(
e);
}
}

@Override
@Deprecated
public void copyFile(
File from,
File to,
boolean filtering,
List<FilterWrapper> filterWrappers,
String encoding,
boolean overwrite)
throws MavenFilteringException {
// overwrite forced to false to preserve backward comp
copyFile(from, to, filtering, filterWrappers, encoding);
}
}
109 changes: 31 additions & 78 deletions src/main/java/org/apache/maven/shared/filtering/FilteringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,18 @@

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.StandardCopyOption;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.SystemUtils;
import org.codehaus.plexus.util.io.CachingOutputStream;
import org.codehaus.plexus.util.io.CachingWriter;

/**
* @author Olivier Lamy
Expand All @@ -62,6 +56,7 @@ public final class FilteringUtils {
private static final String WINDOWS_PATH_PATTERN = "^(.*)[a-zA-Z]:\\\\(.*)";

private static final Pattern PATTERN = Pattern.compile(WINDOWS_PATH_PATTERN);
public static final int COPY_BUFFER_LENGTH = 8192;

/**
*
Expand Down Expand Up @@ -301,91 +296,31 @@ static boolean isEmpty(final String string) {

/**
* <b>If wrappers is null or empty, the file will be copy only if to.lastModified() &lt; from.lastModified() or if
* overwrite is true</b>
* overwrite is true</b>.
*
* @param from the file to copy
* @param to the destination file
* @param encoding the file output encoding (only if wrappers is not empty)
* @param wrappers array of {@link FilterWrapper}
* @param overwrite if true and wrappers is null or empty, the file will be copied even if
* to.lastModified() &lt; from.lastModified()
* @throws IOException if an IO error occurs during copying or filtering
*/
public static void copyFile(File from, File to, String encoding, FilterWrapper[] wrappers, boolean overwrite)
throws IOException {
public static void copyFile(File from, File to, String encoding, FilterWrapper[] wrappers) throws IOException {
if (wrappers == null || wrappers.length == 0) {
if (overwrite || to.lastModified() < from.lastModified()) {
Files.copy(from.toPath(), to.toPath(), LinkOption.NOFOLLOW_LINKS, StandardCopyOption.REPLACE_EXISTING);
try (OutputStream os = new CachingOutputStream(to.toPath())) {
Files.copy(from.toPath(), os);
}
} else {
Charset charset = charset(encoding);

// buffer so it isn't reading a byte at a time!
try (Reader fileReader = Files.newBufferedReader(from.toPath(), charset)) {
Reader wrapped = fileReader;
for (FilterWrapper wrapper : wrappers) {
wrapped = wrapper.getReader(wrapped);
}

if (overwrite || !to.exists()) {
try (Writer fileWriter = Files.newBufferedWriter(to.toPath(), charset)) {
IOUtils.copy(wrapped, fileWriter);
}
} else {
CharsetEncoder encoder = charset.newEncoder();

int charBufferSize = (int) Math.floor(FILE_COPY_BUFFER_SIZE / (2 + 2 * encoder.maxBytesPerChar()));
int byteBufferSize = (int) Math.ceil(charBufferSize * encoder.maxBytesPerChar());

CharBuffer newChars = CharBuffer.allocate(charBufferSize);
ByteBuffer newBytes = ByteBuffer.allocate(byteBufferSize);
ByteBuffer existingBytes = ByteBuffer.allocate(byteBufferSize);

CoderResult coderResult;
int existingRead;
boolean writing = false;

try (RandomAccessFile existing = new RandomAccessFile(to, "rw")) {
int n;
while (-1 != (n = wrapped.read(newChars))) {
((Buffer) newChars).flip();

coderResult = encoder.encode(newChars, newBytes, n != 0);
if (coderResult.isError()) {
coderResult.throwException();
}

((Buffer) newBytes).flip();

if (!writing) {
existingRead = existing.read(existingBytes.array(), 0, newBytes.remaining());
if (existingRead == -1) {
writing = true; // EOF
} else {
((Buffer) existingBytes).position(existingRead);
((Buffer) existingBytes).flip();

if (newBytes.compareTo(existingBytes) != 0) {
writing = true;
if (existingRead > 0) {
existing.seek(existing.getFilePointer() - existingRead);
}
}
}
}

if (writing) {
existing.write(newBytes.array(), 0, newBytes.remaining());
}

((Buffer) newChars).clear();
((Buffer) newBytes).clear();
((Buffer) existingBytes).clear();
}

if (existing.length() > existing.getFilePointer()) {
existing.setLength(existing.getFilePointer());
}
try (Writer writer = new CachingWriter(to.toPath(), charset)) {
char[] buffer = new char[COPY_BUFFER_LENGTH];
int nRead;
while ((nRead = wrapped.read(buffer, 0, COPY_BUFFER_LENGTH)) >= 0) {
writer.write(buffer, 0, nRead);
}
}
}
Expand All @@ -394,6 +329,24 @@ public static void copyFile(File from, File to, String encoding, FilterWrapper[]
copyFilePermissions(from, to);
}

/**
* <b>If wrappers is null or empty, the file will be copy only if to.lastModified() &lt; from.lastModified() or if
* overwrite is true</b>.
*
* @param from the file to copy
* @param to the destination file
* @param encoding the file output encoding (only if wrappers is not empty)
* @param wrappers array of {@link FilterWrapper}
* @param overwrite unused
* @throws IOException if an IO error occurs during copying or filtering
* @deprecated use {@link #copyFile(File, File, String, FilterWrapper[])} instead
*/
@Deprecated
public static void copyFile(File from, File to, String encoding, FilterWrapper[] wrappers, boolean overwrite)
throws IOException {
copyFile(from, to, encoding, wrappers);
}

/**
* Attempts to copy file permissions from the source to the destination file.
* Initially attempts to copy posix file permissions, assuming that the files are both on posix filesystems.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ void copyFile(File from, File to, boolean filtering, List<FilterWrapper> filterW
* @param filtering true to apply filtering
* @param filterWrappers The filters to be applied.
* @param encoding The encoding to use
* @param overwrite Overwrite to file ?
* @param overwrite unused
* @throws MavenFilteringException In case of an error.
* @since 1.0-beta-2
* @deprecated use {@link #copyFile(File, File, boolean, List, String)} instead
*/
@Deprecated
void copyFile(
File from,
File to,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,6 @@ protected void setUp() throws Exception {
Files.deleteIfExists(to.toPath());
}

public void testNotOverwriteFile() throws Exception {
MavenFileFilter mavenFileFilter = lookup(MavenFileFilter.class);

File from = new File(getBasedir(), "src/test/units-files/reflection-test.properties");

mavenFileFilter.copyFile(from, to, false, null, null);

from = new File(getBasedir(), "src/test/units-files/reflection-test-older.properties");

// very old file :-)
from.setLastModified(1);

to.setLastModified(System.currentTimeMillis());

mavenFileFilter.copyFile(from, to, false, null, null);

Properties properties = PropertyUtils.loadPropertyFile(to, null);
assertEquals("${pom.version}", properties.getProperty("version"));
}

public void testOverwriteFile() throws Exception {
MavenFileFilter mavenFileFilter = lookup(MavenFileFilter.class);

Expand All @@ -83,7 +63,7 @@ public void testOverwriteFile() throws Exception {

to.setLastModified(System.currentTimeMillis());

mavenFileFilter.copyFile(from, to, false, null, null, true);
mavenFileFilter.copyFile(from, to, false, null, null);

Properties properties = PropertyUtils.loadPropertyFile(to, null);
assertEquals("older file", properties.getProperty("version"));
Expand Down