FileContent.java
- /*
- * FileContent
- */
- package gov.usgs.earthquake.product;
- import gov.usgs.util.StreamUtils;
- import java.io.File;
- import java.io.InputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.net.URISyntaxException;
- import java.util.Date;
- import java.util.Map;
- import java.util.HashMap;
- import java.util.regex.Pattern;
- import javax.activation.MimetypesFileTypeMap;
- /**
- * Content stored in a file.
- */
- public class FileContent extends AbstractContent {
- /** Used to look up file types. */
- private static MimetypesFileTypeMap SYSTEM_MIME_TYPES = new MimetypesFileTypeMap();
- /** Explicit list of file extensions with standard mime types. */
- private static Map<String, String> MIME_TYPES = new HashMap<String, String>();
- static {
- MIME_TYPES.put("atom", "application/atom+xml");
- MIME_TYPES.put("css", "text/css");
- MIME_TYPES.put("gif", "image/gif");
- MIME_TYPES.put("gz", "application/gzip");
- MIME_TYPES.put("html", "text/html");
- MIME_TYPES.put("jpg", "image/jpeg");
- MIME_TYPES.put("js", "text/javascript");
- MIME_TYPES.put("json", "application/json");
- MIME_TYPES.put("kml", "application/vnd.google-earth.kml+xml");
- MIME_TYPES.put("kmz", "application/vnd.google-earth.kmz");
- MIME_TYPES.put("pdf", "application/pdf");
- MIME_TYPES.put("png", "image/png");
- MIME_TYPES.put("ps", "application/postscript");
- MIME_TYPES.put("txt", "text/plain");
- MIME_TYPES.put("xml", "application/xml");
- MIME_TYPES.put("zip", "application/zip");
- }
- /** The actual content. */
- private File content;
- /**
- * Construct a new FileContent that does not use a nested path. same as new
- * FileContent(file, file.getParentFile());
- *
- * @param file
- * the source of content.
- */
- public FileContent(final File file) {
- this.content = file;
- this.setLastModified(new Date(file.lastModified()));
- this.setLength(file.length());
- this.setContentType(getMimeType(file));
- }
- /**
- * Construct a new FileContent from a URLContent for legacy products
- *
- * @param urlc
- * the source of content.
- * @throws URISyntaxException if error in URI
- */
- public FileContent(final URLContent urlc) throws URISyntaxException {
- super(urlc);
- this.content = new File(urlc.getURL().toURI());
- }
- /**
- * Convert a Content to a file backed content.
- *
- * The file written is new File(baseDirectory, content.getPath()).
- *
- * @param content
- * the content that will be converted to a file.
- * @param toWrite
- * the file where content is written.
- * @throws IOException
- * if IO error occurs
- */
- public FileContent(final Content content, final File toWrite)
- throws IOException {
- super(content);
- // this file content object will use the newly created file
- this.content = toWrite;
- // make sure the parent directory exists
- File parent = toWrite.getCanonicalFile().getParentFile();
- if (!parent.isDirectory()) {
- parent.mkdirs();
- }
- // save handle to stream to force it closed
- OutputStream out = null;
- InputStream in = null;
- try {
- in = content.getInputStream();
- out = StreamUtils.getOutputStream(toWrite);
- // write the file
- StreamUtils.transferStream(in, out);
- } finally {
- // force the stream closed
- StreamUtils.closeStream(in);
- StreamUtils.closeStream(out);
- }
- // update modification date in filesystem
- toWrite.setLastModified(content.getLastModified().getTime());
- // verify file length
- Long length = getLength();
- if (length > 0 && !length.equals(toWrite.length())) {
- throw new IOException("Written file length ("
- + toWrite.length()
- + ") does not match non-zero content length (" + length
- + ")");
- }
- // length may still be <= 0 if content was input stream.
- setLength(toWrite.length());
- }
- /**
- * @return an InputStream for the wrapped content.
- */
- public InputStream getInputStream() throws IOException {
- return StreamUtils.getInputStream(content);
- }
- /**
- * @return the wrapped file.
- */
- public File getFile() {
- return content;
- }
- /**
- * Search a directory for files. This is equivalent to
- * getDirectoryContents(directory, directory).
- *
- * @param directory
- * the directory to search.
- * @return a map of relative paths to FileContent objects.
- * @throws IOException if IO error occurs
- */
- public static Map<String, FileContent> getDirectoryContents(
- final File directory) throws IOException {
- File absDirectory = directory.getCanonicalFile();
- return getDirectoryContents(absDirectory, absDirectory);
- }
- /**
- * Search a directory for files. The path to files relative to baseDirectory
- * is used as a key in the returned map.
- *
- * @param directory
- * the directory to search.
- * @param baseDirectory
- * the directory used to compute relative paths.
- * @return a map of relative paths to FileContent objects.
- * @throws IOException if IO error occurs
- */
- public static Map<String, FileContent> getDirectoryContents(
- final File directory, final File baseDirectory) throws IOException {
- Map<String, FileContent> contents = new HashMap<String, FileContent>();
- // compute the base path once, and escape the pattern being matched
- String basePath = Pattern.quote(baseDirectory.getCanonicalPath()
- + File.separator);
- File[] files = directory.listFiles();
- for (File file : files) {
- if (file.isDirectory()) {
- // recurse into sub directory
- contents.putAll(getDirectoryContents(file.getCanonicalFile(),
- baseDirectory.getCanonicalFile()));
- } else {
- String path = file.getCanonicalPath().replaceAll(basePath, "");
- contents.put(path, new FileContent(file));
- }
- }
- return contents;
- }
- /**
- * This implementation calls defaultGetMimeType, and exists so subclasses
- * can override.
- *
- * @param file
- * file to check.
- * @return corresponding mime type.
- */
- public String getMimeType(final File file) {
- return defaultGetMimeType(file);
- }
- /**
- * Check a local list of mime types, and fall back to MimetypeFileTypesMap
- * if not specified.
- *
- * @param file
- * file to check.
- * @return corresponding mime type.
- */
- protected static String defaultGetMimeType(final File file) {
- String name = file.getName();
- int index = name.lastIndexOf('.');
- if (index != -1) {
- String extension = name.substring(index + 1);
- if (MIME_TYPES.containsKey(extension)) {
- return MIME_TYPES.get(extension);
- }
- }
- return SYSTEM_MIME_TYPES.getContentType(file);
- }
- /**
- * Free any resources associated with this content.
- */
- public void close() {
- // nothing to free
- }
- }