package org.springframework.roo.process.manager.internal;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.roo.file.monitor.NotifiableFileMonitorService;
/**
* Ensures the {@link NotifiableFileMonitorService#notifyChanged(String)} method
* is invoked when {@link #close()} is called.
* <p>
* This is useful for ensuring the file monitoring system is notified of all
* changed files, even those which are changed very rapidly on disk and would
* not normally be detected using the file system's "last updated" timestamps.
*
* @author Ben Alex
* @since 1.0
*/
public class MonitoredOutputStream extends ByteArrayOutputStream {
private final File file;
private final NotifiableFileMonitorService fileMonitorService;
private final ManagedMessageRenderer managedMessageRenderer;
/**
* Constructs a {@link MonitoredOutputStream}.
*
* @param file the file to output to (required)
* @param managedMessageRenderer a rendered for outputting a message once
* the output stream is closed (required)
* @param fileMonitorService an optional monitoring service (null is
* acceptable)
* @throws FileNotFoundException if the file cannot be found
*/
public MonitoredOutputStream(final File file,
final ManagedMessageRenderer managedMessageRenderer,
final NotifiableFileMonitorService fileMonitorService) throws FileNotFoundException {
Validate.notNull(file, "File required");
Validate.notNull(managedMessageRenderer, "Message renderer required");
this.file = file;
this.fileMonitorService = fileMonitorService;
this.managedMessageRenderer = managedMessageRenderer;
}
@Override
public void close() throws IOException {
// Obtain the bytes the user is writing out
final byte[] bytes = toByteArray();
// Try to calculate the SHA hash code
managedMessageRenderer.setHashCode(DigestUtils.shaHex(bytes));
// Log that we're writing the file
managedMessageRenderer.logManagedMessage();
// Write the actual file out to disk
FileUtils.writeByteArrayToFile(file, bytes);
// Tell the FileMonitorService what happened
String fileCanonicalPath;
try {
fileCanonicalPath = file.getCanonicalPath();
} catch (final IOException ioe) {
throw new IllegalStateException(ioe);
}
if (fileMonitorService != null) {
fileMonitorService.notifyChanged(fileCanonicalPath);
}
}
}