blob: fd9975c70c94d6fd975f71027e954caa78f5ce50 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2010 Sonatype, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Sonatype, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.m2e.core.internal.builder.plexusbuildapi;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.sonatype.plexus.build.incremental.BuildContext;
/**
* Writes to the file only if content of the file is different. TODO. Current implementation defers actual writing to
* the output file until invocation of {@link #close()} method. This results in missed/ignored IOExceptions in some
* cases. First, {@link #flush()} method does not actually flush buffer to the disk. Second, any problems writing to the
* file will be reported as IOException thrown by {@link #close()}, which are generally ignored.
*/
public class ChangedFileOutputStream extends OutputStream {
private final File file;
private final BuildContext buildContext;
private final OutputStream os;
private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
public ChangedFileOutputStream(File file) throws FileNotFoundException {
this(file, null);
}
public ChangedFileOutputStream(File file, BuildContext buildContext) throws FileNotFoundException {
this.file = file;
this.buildContext = buildContext;
this.os = new BufferedOutputStream(new FileOutputStream(file));
}
public void write(int b) {
buffer.write(b);
}
public void write(byte[] b, int off, int len) {
buffer.write(b, off, len);
}
public void close() throws IOException {
try {
writeIfNewOrChanged();
} finally {
os.close();
}
}
protected void writeIfNewOrChanged() throws IOException {
byte[] bytes = buffer.toByteArray();
boolean needToWrite = false;
// XXX harden
if(file.exists()) {
BufferedInputStream is = new BufferedInputStream(new FileInputStream(file));
try {
for(int i = 0; i < bytes.length; i++ ) {
if(bytes[i] != is.read()) {
needToWrite = true;
break;
}
}
} finally {
try {
is.close();
} catch(IOException e) {
}
}
} else {
// file does not exist
needToWrite = true;
}
if(needToWrite) {
if(buildContext != null) {
buildContext.refresh(file);
}
os.write(bytes);
}
}
}