/* * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. * * Distributable under LGPL license. * See terms of license at gnu.org. */ package net.java.sip.communicator.impl.fileaccess; import java.io.*; import net.java.sip.communicator.service.configuration.*; import net.java.sip.communicator.service.fileaccess.*; import net.java.sip.communicator.util.*; /** * Default FileAccessService implementation. * * @author Alexander Pelov */ public class FileAccessServiceImpl implements FileAccessService { /** * The logger for this class. */ private static Logger logger = Logger .getLogger(FileAccessServiceImpl.class); /** * The file prefix for all temp files. */ public static final String TEMP_FILE_PREFIX = "SIPCOMM"; /** * The file suffix for all temp files. */ public static final String TEMP_FILE_SUFFIX = "TEMP"; /** * This method returns a created temporary file. After you close this file * it is not guaranteed that you will be able to open it again nor that it * will contain any information. * * Note: DO NOT store unencrypted sensitive information in this file * * @return The created temporary file * @throws IOException * If the file cannot be created */ public File getTemporaryFile() throws IOException { File retVal = null; try { logger.logEntry(); retVal = TempFileManager.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX); } finally { logger.logExit(); } return retVal; } public File getTemporaryDirectory() throws IOException { File file = getTemporaryFile(); if (!file.delete()) { throw new IOException("Could not create temporary directory, " + "because: could not delete temporary file."); } if (!file.mkdirs()) { throw new IOException("Could not create temporary directory"); } return file; } /** * This method returns a file specific to the current user. It may not * exist, but it is guaranteed that you will have the sufficient rights to * create it. * * This file should not be considered secure because the implementor may * return a file accesible to everyone. Generaly it will reside in current * user's homedir, but it may as well reside in a shared directory. * * Note: DO NOT store unencrypted sensitive information in this file * * @param fileName * The name of the private file you wish to access * @return The file * @throws Exception if we faile to create the file. */ public File getPrivatePersistentFile(String fileName) throws Exception { File file = null; try { logger.logEntry(); String fullPath = getFullPath(fileName); file = this.accessibleFile(fullPath, fileName); if (file == null) { throw new SecurityException("Insufficient rights to access " + "this file in current user's home directory: " + new File(fullPath, fileName).getPath()); } } finally { logger.logExit(); } return file; } /** * This method creates a directory specific to the current user. * * This directory should not be considered secure because the implementor * may return a directory accesible to everyone. Generaly it will reside in * current user's homedir, but it may as well reside in a shared directory. * * It is guaranteed that you will be able to create files in it. * * Note: DO NOT store unencrypted sensitive information in this file * * @param dirName * The name of the private directory you wish to access. * @return The created directory. * @throws Exception * Thrown if there is no suitable location for the persistent * directory. */ public File getPrivatePersistentDirectory(String dirName) throws Exception { String fullPath = getFullPath(dirName); File dir = new File(fullPath, dirName); if (dir.exists()) { if (!dir.isDirectory()) { throw new RuntimeException("Could not create directory " + "because: A file exists with this name:" + dir.getAbsolutePath()); } } else { if (!dir.mkdirs()) { throw new IOException("Could not create directory"); } } return dir; } /** * This method creates a directory specific to the current user. * * {@link #getPrivatePersistentDirectory(String)} * * @param dirNames * The name of the private directory you wish to access. * @return The created directory. * @throws Exception * Thrown if there is no suitable location for the persistent * directory. */ public File getPrivatePersistentDirectory(String[] dirNames) throws Exception { StringBuffer dirName = new StringBuffer(); for (int i = 0; i < dirNames.length; i++) { if (i > 0) { dirName.append(File.separatorChar); } dirName.append(dirNames[i]); } return getPrivatePersistentDirectory(dirName.toString()); } /** * Returns the full parth corresponding to a file located in the * sip-communicator config home and carrying the specified name. * @param fileName the name of the file whose location we're looking for. * @return the config home location of a a file withe the specified name. */ private String getFullPath(String fileName) { // bypass the configurationService here to remove the dependancy String userhome = getScHomeDirLocation(); String sipSubdir = getScHomeDirName(); if (!userhome.endsWith(File.separator)) { userhome += File.separator; } if (!sipSubdir.endsWith(File.separator)) { sipSubdir += File.separator; } return userhome + sipSubdir; } /** * Returns the name of the directory where SIP Communicator is to store user * specific data such as configuration files, message and call history * as well as is bundle repository. * * @return the name of the directory where SIP Communicator is to store * user specific data such as configuration files, message and call history * as well as is bundle repository. */ public String getScHomeDirName() { //check whether user has specified a custom name in the //system properties String scHomeDirName = getSystemProperty(ConfigurationService.PNAME_SC_HOME_DIR_NAME); if (scHomeDirName == null) { scHomeDirName = ".sip-communicator"; } return scHomeDirName; } /** * Returns the location of the directory where SIP Communicator is to store * user specific data such as configuration files, message and call history * as well as is bundle repository. * * @return the location of the directory where SIP Communicator is to store * user specific data such as configuration files, message and call history * as well as is bundle repository. */ public String getScHomeDirLocation() { //check whether user has specified a custom name in the //system properties String scHomeDirLocation = getSystemProperty(ConfigurationService .PNAME_SC_HOME_DIR_LOCATION); if (scHomeDirLocation == null) { scHomeDirLocation = getSystemProperty("user.home"); } return scHomeDirLocation; } /** * Returns the value of the specified java system property. In case the * value was a zero length String or one that only contained whitespaces, * null is returned. This method is for internal use only. Users of the * configuration service are to use the getProperty() or getString() methods * which would automatically determine whether a property is system or not. * @param propertyName the name of the property whose value we need. * @return the value of the property with name propertyName or null if * the value had length 0 or only contained spaces tabs or new lines. */ private static String getSystemProperty(String propertyName) { String retval = System.getProperty(propertyName); if (retval == null){ return retval; } if (retval.trim().length() == 0){ return null; } return retval; } /** * Checks if a file exists and if it is writable or readable. If not - * checks if the user has a write privileges to the containing directory. * * If those conditions are met it returns a File in the directory with a * fileName. If not - returns null. * * @param homedir the location of the sip-communicator home directory. * @param fileName the name of the file to create. * @return Returns null if the file does not exist and cannot be created. * Otherwise - an object to this file * @throws IOException * Thrown if the home directory cannot be created */ private File accessibleFile(String homedir, String fileName) throws IOException { File file = null; try { logger.logEntry(); homedir = homedir.trim(); if (!homedir.endsWith(File.separator)) { homedir += File.separator; } file = new File(homedir + fileName); if (file.canRead() || file.canWrite()) { return file; } File homedirFile = new File(homedir); if (!homedirFile.exists()) { logger.debug("Creating home directory : " + homedirFile.getAbsolutePath()); if (!homedirFile.mkdirs()) { String message = "Could not create the home directory : " + homedirFile.getAbsolutePath(); logger.debug(message); throw new IOException(message); } logger.debug("Home directory created : " + homedirFile.getAbsolutePath()); } else if (!homedirFile.canWrite()) { file = null; } } finally { logger.logExit(); } return file; } /** * Creates a failsafe transaction which can be used to safely store * informations into a file. * * @param file The file concerned by the transaction, null if file is null. * * @return A new failsafe transaction related to the given file. */ public FailSafeTransaction createFailSafeTransaction(File file) { if (file == null) { return null; } return new FailSafeTransactionImpl(file); } }