blob: a5bf207e87f726602283ba5383029fc5abe2fb03 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
******************************************************************************/
package uk.org.taverna.configuration.app.impl;
import java.io.File;
import org.apache.log4j.Logger;
/**
* Find and create an application's user directory according to operating system
* standards.
* <p>
* For example for the application "MyApp" this class will be able to find
* <code>$HOME/.myapp</code> on Linux or
* <code>C:\Document and settings\MyUsername\Application Data\MyApplication</code>
* on Windows XP.
*
* @author Stian Soiland-Reyes
* @author Stuart Owen
*
*/
public class ApplicationUserHome {
private final String defaultApplicationHome;
private final String applicationName;
private File homeDir;
private static Logger logger = Logger.getLogger(ApplicationUserHome.class);
/**
* Initialise with the name of the application.
*
* @param applicationName
* This name will be used as a template for creating the
* application home directory (but might be transcribed, for
* instance to lowercase). It is generally recommended, but not
* required - that this name does not contain spaces or any
* special international/Unicode characters.
*/
public ApplicationUserHome(String applicationName) {
this(applicationName, null);
}
/**
* Initialise with the name of the application and a default application
* home.
*
* @param applicationName
* This name will be used as a template for creating the
* application home directory (but might be transcribed, for
* instance to lowercase). It is generally recommended, but not
* required - that this name does not contain spaces or any
* special international/Unicode characters.
* @param defaultApplicationHome
* The full path to the default home directory. If this string is
* not <code>null</code>, then a {@link File} based on this
* directory will always be returned by
* {@link #getDefaultApplicationHome()} - otherwise the normal
* operating system logic is used to determine the application's
* home directory.
*/
public ApplicationUserHome(String applicationName,
String defaultApplicationHome) {
this.applicationName = applicationName;
this.defaultApplicationHome = defaultApplicationHome;
}
/**
* Find (and if necessary create) the user's application directory,
* according to operating system standards. The resolved directory is then
* returned as a {@link File} object.
* <p>
* The application's name as defined by {@link #getApplicationName()} is
* used as a basis for naming the directory of the application's user
* directory, but the directory name might for instance be transformed to
* lowercase.
* <p>
* If {@link #getDefaultApplicationHome()} returns a non-null value, the
* directory specified by that path will be used instead of the operation
* system specific directory. The directory will be created if needed.
* <p>
* If any exception occurs (such as out of diskspace), <code>null</code>
* will be returned.
*
* <p>
* On Windows XP, this will typically be something like:
*
* <pre>
* C:\Document and settings\MyUsername\Application Data\MyApplication
* </pre>
*
* and on Windows Vista it would be something like:
*
* <pre>
* C:\Users\MyUsername\Application Data\MyApplication
* </pre>
*
* while on Mac OS X it will be something like:
*
* <pre>
* /Users/MyUsername/Library/Application Support/MyApplication
* </pre>
*
* All other OS'es are assumed to be UNIX-alike, returning something like:
*
* <pre>
* /user/myusername/.myapplication
* </pre>
*
* <p>
* If the directory does not already exist, it will be created.
* </p>
*
* @return An {@link File} referring to an existing directory for
* user-specific configuration etc. for the given application.
*/
public synchronized File getAppUserHome() {
if (homeDir != null) {
return homeDir;
}
File appHome;
String applicationHome = getDefaultApplicationHome();
if (applicationHome != null) {
appHome = new File(applicationHome);
} else {
if (getApplicationName() == null) {
logger.warn("Unknown application name");
return null;
}
File home = new File(System.getProperty("user.home"));
if (!home.isDirectory()) {
logger.error("User home not a valid directory: " + home);
return null;
}
String os = System.getProperty("os.name");
// logger.debug("OS is " + os);
if (os.equals("Mac OS X")) {
File libDir = new File(home, "Library/Application Support");
libDir.mkdirs();
appHome = new File(libDir, getApplicationName());
} else if (os.startsWith("Windows")) {
String APPDATA = System.getenv("APPDATA");
File appData = null;
if (APPDATA != null) {
appData = new File(APPDATA);
}
if (appData != null && appData.isDirectory()) {
appHome = new File(appData, getApplicationName());
} else {
logger.warn("Could not find %APPDATA%: " + APPDATA);
appHome = new File(home, getApplicationName());
}
} else {
// We'll assume UNIX style is OK
appHome = new File(home, "."
+ getApplicationName().toLowerCase().replace(' ', '-'));
}
}
if (!appHome.exists()) {
if (appHome.mkdir()) {
logger.info("Created " + appHome);
} else {
logger.error("Could not create " + appHome);
return null;
}
}
if (!appHome.isDirectory()) {
logger.error("User home not a valid directory: " + appHome);
return null;
}
this.homeDir = appHome.getAbsoluteFile();
return this.homeDir;
}
/**
* The application's name. This name will be used as a template for creating
* the application home directory (but might be transcribed, for instance to
* lowercase). It is generally recommended, but not required - that this
* name does not contain spaces or any special international/Unicode
* characters.
*
* @return The application's name.
*
*/
public String getApplicationName() {
return applicationName;
}
/**
* The full path to the default home directory. If this string is not
* <code>null</code>, then a {@link File} based on this directory will
* always be returned by {@link #getDefaultApplicationHome()} - otherwise
* the normal operating system logic is used to determine the application's
* home directory.
*
* @return The full path to the application's home directory, or
* <code>null</code> if the operation system specific logic is to
* be used.
*/
public String getDefaultApplicationHome() {
return defaultApplicationHome;
}
}