package org.eclipse.osgi.internal.location;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration.ConfigValues;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.storage.StorageUtil;
import org.osgi.framework.Constants;
public class EquinoxLocations {
public static final String READ_ONLY_AREA_SUFFIX = ".readOnly";
public static final String PROP_INSTALL_AREA = "osgi.install.area";
public static final String PROP_CONFIG_AREA = "osgi.configuration.area";
public static final String PROP_CONFIG_AREA_DEFAULT = "osgi.configuration.area.default";
public static final String PROP_SHARED_CONFIG_AREA = "osgi.sharedConfiguration.area";
public static final String PROP_INSTANCE_AREA = "osgi.instance.area";
public static final String PROP_INSTANCE_AREA_DEFAULT = "osgi.instance.area.default";
public static final String PROP_USER_AREA = "osgi.user.area";
public static final String PROP_USER_AREA_DEFAULT = "osgi.user.area.default";
public static final String PROP_USER_HOME = "user.home";
public static final String PROP_USER_DIR = "user.dir";
public static final String PROP_HOME_LOCATION_AREA = "eclipse.home.location";
public static final String PROP_LAUNCHER = "eclipse.launcher";
private static final String ECLIPSE = "eclipse";
private static final String PRODUCT_SITE_MARKER = ".eclipseproduct";
private static final String PRODUCT_SITE_ID = "id";
private static final String PRODUCT_SITE_VERSION = "version";
private static final String CONFIG_DIR = "configuration";
private static final String NONE = "@none";
private static final String NO_DEFAULT = "@noDefault";
private static final String USER_HOME = "@user.home";
private static final String USER_DIR = "@user.dir";
private static final String INSTALL_HASH_PLACEHOLDER = "@install.hash";
private static final String INSTANCE_DATA_AREA_PREFIX = ".metadata/.plugins/";
private final ConfigValues equinoxConfig;
private final EquinoxContainer container;
private final AtomicBoolean debugLocations;
private final Location installLocation;
private final Location configurationLocation;
private final Location userLocation;
private final Location instanceLocation;
private final Location eclipseHomeLocation;
public EquinoxLocations(ConfigValues equinoxConfig, EquinoxContainer container, AtomicBoolean debugLocations, Map<Throwable, Integer> exceptions) {
this.equinoxConfig = equinoxConfig;
this.container = container;
this.debugLocations = debugLocations;
String osgiStorage = equinoxConfig.getConfiguration(Constants.FRAMEWORK_STORAGE);
if (osgiStorage != null) {
if (equinoxConfig.getConfiguration(PROP_CONFIG_AREA) != null) {
exceptions.put(new IllegalArgumentException(String.format(
"The property '%s' with the value '%s' is being overriden by the OSGi standard configuration property '%s' with the value '%s'.",
PROP_CONFIG_AREA, equinoxConfig.getConfiguration(PROP_CONFIG_AREA), Constants.FRAMEWORK_STORAGE, osgiStorage)), FrameworkLogEntry.WARNING);
}
equinoxConfig.setConfiguration(PROP_CONFIG_AREA, osgiStorage);
}
installLocation = buildLocation(PROP_INSTALL_AREA, null, "", true, false, null);
Location temp = buildLocation(PROP_USER_AREA_DEFAULT, null, "", false, false, null);
URL defaultLocation = temp == null ? null : temp.getURL();
if (defaultLocation == null)
defaultLocation = buildURL(new File(System.getProperty(PROP_USER_HOME), "user").getAbsolutePath(), true);
userLocation = buildLocation(PROP_USER_AREA, defaultLocation, "", false, false, null);
temp = buildLocation(PROP_INSTANCE_AREA_DEFAULT, null, "", false, false, INSTANCE_DATA_AREA_PREFIX);
defaultLocation = temp == null ? null : temp.getURL();
if (defaultLocation == null)
defaultLocation = buildURL(new File(System.getProperty(PROP_USER_DIR), "workspace").getAbsolutePath(), true);
instanceLocation = buildLocation(PROP_INSTANCE_AREA, defaultLocation, "", false, false, INSTANCE_DATA_AREA_PREFIX);
mungeConfigurationLocation();
temp = buildLocation(PROP_CONFIG_AREA_DEFAULT, null, "", false, false, null);
defaultLocation = temp == null ? null : temp.getURL();
if (defaultLocation == null && equinoxConfig.getConfiguration(PROP_CONFIG_AREA) == null)
defaultLocation = buildURL(computeDefaultConfigurationLocation(), true);
configurationLocation = buildLocation(PROP_CONFIG_AREA, defaultLocation, "", false, false, null);
URL parentLocation = computeSharedConfigurationLocation();
if (parentLocation != null && !parentLocation.equals(configurationLocation.getURL())) {
Location parent = new BasicLocation(null, parentLocation, true, null, equinoxConfig, container, debugLocations);
((BasicLocation) configurationLocation).setParent(parent);
}
if (equinoxConfig.getConfiguration(PROP_HOME_LOCATION_AREA) == null) {
String eclipseLauncher = equinoxConfig.getConfiguration(PROP_LAUNCHER);
String eclipseHomeLocationPath = getEclipseHomeLocation(eclipseLauncher, equinoxConfig);
if (eclipseHomeLocationPath != null)
equinoxConfig.setConfiguration(PROP_HOME_LOCATION_AREA, eclipseHomeLocationPath);
}
if (equinoxConfig.getConfiguration(PROP_HOME_LOCATION_AREA) == null && equinoxConfig.getConfiguration(PROP_INSTALL_AREA) != null)
equinoxConfig.setConfiguration(PROP_HOME_LOCATION_AREA, equinoxConfig.getConfiguration(PROP_INSTALL_AREA));
eclipseHomeLocation = buildLocation(PROP_HOME_LOCATION_AREA, null, "", true, true, null);
}
public static URL buildURL(String spec, boolean trailingSlash) {
return LocationHelper.buildURL(spec, trailingSlash);
}
private void mungeConfigurationLocation() {
String location = equinoxConfig.getConfiguration(PROP_CONFIG_AREA);
if (location != null) {
if (location.endsWith(".cfg")) {
int index = location.lastIndexOf('/');
if (index < 0)
index = location.lastIndexOf('\\');
location = location.substring(0, index + 1);
equinoxConfig.setConfiguration(PROP_CONFIG_AREA, location);
}
}
}
private static String getEclipseHomeLocation(String launcher, ConfigValues configValues) {
if (launcher == null)
return null;
File launcherFile = new File(launcher);
if (launcherFile.getParent() == null)
return null;
File launcherDir = new File(launcherFile.getParent());
String macosx = org.eclipse.osgi.service.environment.Constants.OS_MACOSX;
if (macosx.equals(configValues.getConfiguration(EquinoxConfiguration.PROP_OSGI_OS)))
launcherDir = getMacOSEclipseHomeLocation(launcherDir);
return (launcherDir.exists() && launcherDir.isDirectory()) ? launcherDir.getAbsolutePath() : null;
}
private static File getMacOSEclipseHomeLocation(File launcherDir) {
if (!launcherDir.getName().equalsIgnoreCase("macos"))
return launcherDir;
return new File(launcherDir.getParent(), "Eclipse");
}
@SuppressWarnings("deprecation")
private Location buildLocation(String property, URL defaultLocation, String userDefaultAppendage, boolean readOnlyDefault, boolean computeReadOnly, String dataAreaPrefix) {
String location = equinoxConfig.clearConfiguration(property);
String userReadOnlySetting = equinoxConfig.getConfiguration(property + READ_ONLY_AREA_SUFFIX);
boolean readOnly = (userReadOnlySetting == null ? readOnlyDefault : Boolean.valueOf(userReadOnlySetting).booleanValue());
if (location == null)
return new BasicLocation(property, defaultLocation, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(defaultLocation), dataAreaPrefix, equinoxConfig, container, debugLocations);
String trimmedLocation = location.trim();
if (trimmedLocation.equalsIgnoreCase(NONE))
return null;
if (trimmedLocation.equalsIgnoreCase(NO_DEFAULT))
return new BasicLocation(property, null, readOnly, dataAreaPrefix, equinoxConfig, container, debugLocations);
if (trimmedLocation.startsWith(USER_HOME)) {
String base = substituteVar(location, USER_HOME, PROP_USER_HOME);
location = new File(base, userDefaultAppendage).getAbsolutePath();
} else if (trimmedLocation.startsWith(USER_DIR)) {
String base = substituteVar(location, USER_DIR, PROP_USER_DIR);
location = new File(base, userDefaultAppendage).getAbsolutePath();
}
int idx = location.indexOf(INSTALL_HASH_PLACEHOLDER);
if (idx == 0) {
throw new RuntimeException("The location cannot start with '" + INSTALL_HASH_PLACEHOLDER + "': " + location);
} else if (idx > 0) {
location = location.substring(0, idx) + getInstallDirHash() + location.substring(idx + INSTALL_HASH_PLACEHOLDER.length());
}
URL url = buildURL(location, true);
BasicLocation result = null;
if (url != null) {
result = new BasicLocation(property, null, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(url), dataAreaPrefix, equinoxConfig, container, debugLocations);
result.setURL(url, false);
}
return result;
}
private String substituteVar(String source, String var, String prop) {
String value = equinoxConfig.getConfiguration(prop, "");
return value + source.substring(var.length());
}
private URL computeInstallConfigurationLocation() {
String property = equinoxConfig.getConfiguration(PROP_INSTALL_AREA);
if (property != null)
return LocationHelper.buildURL(property, true);
return null;
}
private URL computeSharedConfigurationLocation() {
String property = equinoxConfig.getConfiguration(PROP_SHARED_CONFIG_AREA);
if (property == null)
return null;
try {
URL sharedConfigurationURL = LocationHelper.buildURL(property, true);
if (sharedConfigurationURL == null)
return null;
if (sharedConfigurationURL.getPath().startsWith("/"))
return sharedConfigurationURL;
URL installURL = installLocation.getURL();
if (!sharedConfigurationURL.getProtocol().equals(installURL.getProtocol()))
return sharedConfigurationURL;
sharedConfigurationURL = new URL(installURL, sharedConfigurationURL.getPath());
equinoxConfig.setConfiguration(PROP_SHARED_CONFIG_AREA, sharedConfigurationURL.toExternalForm());
} catch (MalformedURLException e) {
}
return null;
}
private String computeDefaultConfigurationLocation() {
URL installURL = computeInstallConfigurationLocation();
if (installURL != null && "file".equals(installURL.getProtocol())) {
File installDir = new File(installURL.getPath());
File defaultConfigDir = new File(installDir, CONFIG_DIR);
if (!defaultConfigDir.exists())
defaultConfigDir.mkdirs();
if (defaultConfigDir.exists() && StorageUtil.canWrite(defaultConfigDir))
return defaultConfigDir.getAbsolutePath();
}
return computeDefaultUserAreaLocation(CONFIG_DIR);
}
private static boolean canWrite(URL location) {
if (location != null && "file".equals(location.getProtocol())) {
File locationDir = new File(location.getPath());
if (!locationDir.exists())
locationDir.mkdirs();
if (locationDir.exists() && StorageUtil.canWrite(locationDir))
return true;
}
return false;
}
private String computeDefaultUserAreaLocation(String pathAppendage) {
String installProperty = equinoxConfig.getConfiguration(PROP_INSTALL_AREA);
URL installURL = buildURL(installProperty, true);
if (installURL == null)
return null;
File installDir = new File(installURL.getPath());
String installDirHash = getInstallDirHash();
String appName = "." + ECLIPSE;
File eclipseProduct = new File(installDir, PRODUCT_SITE_MARKER);
if (eclipseProduct.exists()) {
Properties props = new Properties();
try {
props.load(new FileInputStream(eclipseProduct));
String appId = props.getProperty(PRODUCT_SITE_ID);
if (appId == null || appId.trim().length() == 0)
appId = ECLIPSE;
String appVersion = props.getProperty(PRODUCT_SITE_VERSION);
if (appVersion == null || appVersion.trim().length() == 0)
appVersion = "";
appName += File.separator + appId + "_" + appVersion + "_" + installDirHash;
} catch (IOException e) {
appName += File.separator + installDirHash;
}
} else {
appName += File.separator + installDirHash;
}
String userHome = System.getProperty(PROP_USER_HOME);
return new File(userHome, appName + "/" + pathAppendage).getAbsolutePath();
}
private String getInstallDirHash() {
String installProperty = equinoxConfig.getConfiguration(PROP_INSTALL_AREA);
URL installURL = buildURL(installProperty, true);
if (installURL == null)
return "";
File installDir = new File(installURL.getPath());
int hashCode;
try {
hashCode = installDir.getCanonicalPath().hashCode();
} catch (IOException ioe) {
hashCode = installDir.getAbsolutePath().hashCode();
}
if (hashCode < 0)
hashCode = -(hashCode);
String installDirHash = String.valueOf(hashCode);
return installDirHash;
}
public Location getUserLocation() {
return userLocation;
}
public Location getConfigurationLocation() {
return configurationLocation;
}
public Location getInstallLocation() {
return installLocation;
}
public Location getInstanceLocation() {
return instanceLocation;
}
public Location getEclipseHomeLocation() {
return eclipseHomeLocation;
}
}