ContentListener.java
package gov.usgs.earthquake.distribution;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Logger;
import gov.usgs.earthquake.product.Content;
import gov.usgs.earthquake.product.Product;
import gov.usgs.earthquake.product.ProductId;
import gov.usgs.util.Config;
import gov.usgs.util.StreamUtils;
/**
* A listener that listens for a specific content path.
*
* This is intended for users who wish to output specific pieces of product
* content, such as "quakeml.xml", for products that otherwise meet their
* configured NotificationListener criteria.
*/
public class ContentListener extends DefaultNotificationListener {
private static final Logger LOGGER = Logger.getLogger(ContentListener.class
.getName());
/** configuration property for includePaths - output directory. */
public static final String OUTPUT_DIRECTORY_PROPERTY = "outputDirectory";
/** property for temporary directory */
public static final String TEMP_DIRECTORY_PROPERTY = "tempDirectory";
/** property for output format */
public static final String OUTPUT_FORMAT_PROPERTY = "outputFormat";
/** property for default output format */
public static final String DEFAULT_OUTPUT_FORMAT = "SOURCE_TYPE_CODE_UPDATETIME_PATH";
/** Directory where content is output. */
private File outputDirectory = null;
/**
* Temporary directory where content is written before moving to
* outputDirectory, defaults to system temp directory when null.
*/
private File tempDirectory = null;
/** Output format for files inside outputDirectory. */
private String outputFormat = DEFAULT_OUTPUT_FORMAT;
/** empty constructor for ContentListener */
public ContentListener() {
}
@Override
public void configure(final Config config) throws Exception {
super.configure(config);
if (getIncludePaths().size() == 0) {
throw new ConfigurationException("[" + getName()
+ "] ContentListener requires 'includePaths' be non-empty");
}
outputDirectory = new File(
config.getProperty(OUTPUT_DIRECTORY_PROPERTY));
LOGGER.config("[" + getName() + "] output directory = "
+ outputDirectory);
String tempDirectoryString = config
.getProperty(TEMP_DIRECTORY_PROPERTY);
if (tempDirectoryString != null) {
tempDirectory = new File(tempDirectoryString);
}
LOGGER.config("[" + getName() + "] temp directory = " + tempDirectory);
outputFormat = config.getProperty(OUTPUT_FORMAT_PROPERTY,
DEFAULT_OUTPUT_FORMAT);
LOGGER.config("[" + getName() + "] output format = " + outputFormat);
}
@Override
public void onProduct(final Product product) throws Exception {
Map<String, Content> contents = product.getContents();
Iterator<String> iter = getIncludePaths().iterator();
while (iter.hasNext()) {
String path = iter.next();
Content content = contents.get(path);
if (content != null) {
// product has content at this path
writeContent(product.getId(), path, content);
}
}
}
/**
* Generate an output path based on product id and content path.
*
* @param id
* the product id.
* @param path
* the content path.
* @return relative path to write content within output directory.
*/
protected String getOutputPath(final ProductId id, final String path) {
return outputFormat
.replace("SOURCE", id.getSource())
.replace("TYPE", id.getType())
.replace("CODE", id.getCode())
.replace("UPDATETIME",
Long.toString(id.getUpdateTime().getTime()))
.replace("PATH", path);
}
/**
* Output a product content that was in includePaths.
*
* @param id
* the product id.
* @param path
* the content path.
* @param content
* the content.
* @throws Exception
* when unable to output the content.
*/
protected void writeContent(final ProductId id, final String path,
final Content content) throws Exception {
String outputPath = getOutputPath(id, path);
if (tempDirectory != null && !tempDirectory.exists()) {
// make sure parent directories exist
tempDirectory.mkdirs();
}
File tempFile = File.createTempFile(outputPath, null, tempDirectory);
File outputFile = new File(outputDirectory, outputPath);
File outputFileParent = outputFile.getParentFile();
if (!outputFileParent.exists()) {
// make sure parent directories exist
outputFileParent.mkdirs();
}
// write, then move into place
InputStream in = null;
OutputStream out = null;
try {
if (!tempFile.getParentFile().exists()) {
tempFile.getParentFile().mkdirs();
}
if (!outputFile.getParentFile().exists()) {
outputFile.getParentFile().mkdirs();
}
in = content.getInputStream();
out = StreamUtils.getOutputStream(tempFile);
// write to temp file
StreamUtils.transferStream(in, out);
// move to output file
tempFile.renameTo(outputFile);
} finally {
StreamUtils.closeStream(in);
StreamUtils.closeStream(out);
// clean up temp file if it wasn't renamed
if (tempFile.exists()) {
tempFile.delete();
}
}
}
/**
* @return the outputDirectory
*/
public File getOutputDirectory() {
return outputDirectory;
}
/**
* @param outputDirectory
* the outputDirectory to set
*/
public void setOutputDirectory(File outputDirectory) {
this.outputDirectory = outputDirectory;
}
/**
* @return the tempDirectory
*/
public File getTempDirectory() {
return tempDirectory;
}
/**
* @param tempDirectory
* the tempDirectory to set
*/
public void setTempDirectory(File tempDirectory) {
this.tempDirectory = tempDirectory;
}
/**
* @return the outputFormat
*/
public String getOutputFormat() {
return outputFormat;
}
/**
* @param outputFormat
* the outputFormat to set
*/
public void setOutputFormat(String outputFormat) {
this.outputFormat = outputFormat;
}
}