/** * Copyright (C) 2010 Orbeon, Inc. * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * The full text of the license is available at http://www.gnu.org/copyleft/lesser.html */ package org.orbeon.oxf.resources; import org.apache.log4j.Logger; import org.orbeon.oxf.common.OXFException; import org.orbeon.oxf.util.LoggerFactory; import java.io.*; import java.net.URLDecoder; import java.util.Map; /** * The Filesystem resource manager is able to load resources from the filesystem with a direct * mapping, or, if the property is specified, within a sandbox. */ public class FilesystemResourceManagerImpl extends ResourceManagerBase { private static Logger logger = LoggerFactory.createLogger(FilesystemResourceManagerImpl.class); private boolean hasSandbox; protected File rootDirectory; public FilesystemResourceManagerImpl(Map props) throws OXFException { super(props); // Try to get sandbox directory final String sandbox = (String) props.get(FilesystemResourceManagerFactory.SANDBOX_DIRECTORY_PROPERTY); if (sandbox != null) { // A sandbox directory was found rootDirectory = new File(sandbox); if (! rootDirectory.isDirectory()) logger.warn("non-existing root directory for resource manager: " + rootDirectory.getAbsolutePath()); hasSandbox = true; } } /** * Returns a binary input stream for the specified key. The key could point * to any document type (text or binary). * @param key A Resource Manager key * @return a input stream */ public InputStream getContentAsStream(String key) { if (logger.isDebugEnabled()) logger.debug("getContentAsStream(" + key + ")"); try { File file = getFile(key); if (file.canRead()) { return new FileInputStream(file); } else throw new ResourceNotFoundException(key); } catch (FileNotFoundException e) { throw new ResourceNotFoundException(key); } } /** * Gets the last modified timestamp for the specified resource * @param key A Resource Manager key * @param doNotThrowResourceNotFound * @return a timestamp */ protected long lastModifiedImpl(String key, boolean doNotThrowResourceNotFound) { File file = getFile(key); if (file.canRead()) return file.lastModified(); else { if (doNotThrowResourceNotFound) return -1; else throw new ResourceNotFoundException(key); } } /** * Returns the length of the file denoted by this abstract pathname. * @return The length, in bytes, of the file denoted by this abstract pathname, or 0L if the file does not exist */ public int length(String key) { return new Long(getFile(key).length()).intValue(); } /** * Indicates if the resource manager implementation supports write operations * @return true if write operations are allowed */ public boolean canWrite(String key) { return getFile(key).getParentFile().canWrite(); } /** * Allows writing to the resource * @param key A Resource Manager key * @return an output stream */ public OutputStream getOutputStream(String key) { try { File file = getFile(key); // Delete file if it exists if (file.exists() && file.canWrite()) file.delete(); // Create file file.createNewFile(); if(file.canWrite()) return new FileOutputStream(file); else throw new OXFException("Can't write to file: "+file); } catch (IOException e) { throw new OXFException(e); } } /** * Allow writing to the resource * @param key A Resource Manager key * @return a writer */ public Writer getWriter(String key) { try { File file = getFile(key); // Delete file if it exists if (file.exists() && file.canWrite()) file.delete(); // Create file if (!file.createNewFile()) throw new OXFException("Can't create file: " + file); if(file.canWrite()) return new FileWriter(file); else throw new OXFException("Can't write to file: "+file); } catch (IOException e) { throw new OXFException(e); } } protected File getFile(String key) { try { // The key comes from a URL, and therefore needs to be decoded to be used as a file key = URLDecoder.decode(key, "utf-8"); } catch (UnsupportedEncodingException e) { throw new OXFException(e); } if (hasSandbox) { return new File(rootDirectory, key); } else { // Remove any starting / if there is a drive letter (kind of a hack!) // On Windows, we may receive keys of the form "/C:/myfile.xpl" // On Unix, we may receive keys of the form "/home/myfile.xpl" return new File(key.startsWith("/") && key.length() >= 3 && key.charAt(2) == ':' ? key.substring(1) : key); } } public String getRealPath(String key) { return getFile(key).getAbsolutePath(); // Need an option for this as some callers call this for non-existing files // final File file = getFile(key); // if (!file.canRead()) // throw new ResourceNotFoundException("Cannot read from file " + key); // else // return file.getAbsolutePath(); } }