blob: 1dd81817bf6e94cac9e150c952b910aec5cfeb18 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Pascal Rapicault - Support for bundled macosx http://bugs.eclipse.org/57349
* Christian Georgi - Relativize VM path https://bugs.eclipse.org/bugs/437680
*******************************************************************************/
package org.eclipse.equinox.internal.frameworkadmin.equinox;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.equinox.internal.frameworkadmin.equinox.utils.FileUtils;
import org.eclipse.equinox.internal.frameworkadmin.utils.Utils;
import org.eclipse.equinox.internal.provisional.frameworkadmin.FrameworkAdminRuntimeException;
import org.eclipse.equinox.internal.provisional.frameworkadmin.LauncherData;
import org.eclipse.osgi.service.environment.Constants;
import org.eclipse.osgi.util.NLS;
import org.osgi.service.log.LogService;
public class EclipseLauncherParser {
private static final String CONFIGURATION_FOLDER = "configuration"; //$NON-NLS-1$
//this figures out the location of the data area on partial data read from the <eclipse>.ini
private URI getOSGiInstallArea(List<String> lines, URI base, LauncherData launcherData) {
//does the eclipse.ini say anything for osgi.install.area?
File osgiInstallArea = ParserUtils.getOSGiInstallArea(lines, null, base);
if (osgiInstallArea == null) {
//otherwise use the launcherData to figure it out
osgiInstallArea = ParserUtils.getOSGiInstallArea(lines, null, launcherData);
}
if (osgiInstallArea != null)
return URIUtil.makeAbsolute(osgiInstallArea.toURI(), base);
return null;
}
private void setInstall(List<String> lines, LauncherData launcherData, File launcherFolder) {
if (launcherData.getFwConfigLocation() == null || launcherData.getFwJar() == null) {
ParserUtils.removeArgument(EquinoxConstants.OPTION_INSTALL, lines);
return;
}
if (Constants.OS_MACOSX.equals(launcherData.getOS())) {
if (!new File(ParserUtils.fromOSGiJarToOSGiInstallArea(launcherData.getFwJar().getAbsolutePath()), "../MacOS").equals(launcherFolder)) {
ParserUtils.setValueForArgument(EquinoxConstants.OPTION_INSTALL, launcherFolder.getAbsolutePath().replace('\\', '/'), lines);
}
} else if (!ParserUtils.fromOSGiJarToOSGiInstallArea(launcherData.getFwJar().getAbsolutePath()).equals(launcherFolder)) {
ParserUtils.setValueForArgument(EquinoxConstants.OPTION_INSTALL, launcherFolder.getAbsolutePath().replace('\\', '/'), lines);
}
}
void read(File launcherConfigFile, LauncherData launcherData) throws IOException {
if (!launcherConfigFile.exists())
return;
List<String> lines = FileUtils.loadFile(launcherConfigFile);
URI launcherFolder = launcherData.getLauncher().getParentFile().toURI();
getStartup(lines, launcherFolder);
getFrameworkJar(lines, launcherFolder, launcherData);
URI osgiInstallArea = getOSGiInstallArea(lines, launcherFolder, launcherData);
if (osgiInstallArea == null) {
osgiInstallArea = launcherData.getFwJar() != null ? ParserUtils.fromOSGiJarToOSGiInstallArea(launcherData.getFwJar().getAbsolutePath()).toURI() : launcherFolder;
}
URI configArea = getConfigurationLocation(lines, osgiInstallArea, launcherData);
if (configArea == null)
throw new FrameworkAdminRuntimeException(Messages.exception_nullConfigArea, ""); //$NON-NLS-1$
getPersistentDataLocation(lines, osgiInstallArea, configArea, launcherData);
getLauncherLibrary(lines, launcherFolder);
getJVMArgs(lines, launcherData);
getProgramArgs(lines, launcherData);
getVM(lines, launcherFolder, launcherData);
Log.log(LogService.LOG_INFO, NLS.bind(Messages.log_configFile, launcherConfigFile.getAbsolutePath()));
}
private void getFrameworkJar(List<String> lines, URI launcherFolder, LauncherData launcherData) {
File fwJar = launcherData.getFwJar();
if (fwJar != null)
return;
URI location = ParserUtils.getFrameworkJar(lines, launcherFolder);
if (location != null)
launcherData.setFwJar(URIUtil.toFile(location));
}
private void getPersistentDataLocation(List<String> lines, URI osgiInstallArea, URI configArea, LauncherData launcherData) {
//TODO The setting of the -clean could only do properly once config.ini has been read
if (launcherData.getFwPersistentDataLocation() == null) {
launcherData.setFwPersistentDataLocation(URIUtil.toFile(configArea), ParserUtils.isArgumentSet(EquinoxConstants.OPTION_CLEAN, lines));
}
}
private void getVM(List<String> lines, URI launcherFolder, LauncherData launcherData) {
String vm = ParserUtils.getValueForArgument(EquinoxConstants.OPTION_VM, lines);
if (vm == null)
return;
URI VMFullPath;
try {
VMFullPath = URIUtil.makeAbsolute(FileUtils.fromPath(vm), launcherFolder);
launcherData.setJvm(URIUtil.toFile(VMFullPath));
ParserUtils.setValueForArgument(EquinoxConstants.OPTION_VM, VMFullPath.toString(), lines);
} catch (URISyntaxException e) {
Log.log(LogService.LOG_ERROR, NLS.bind(Messages.log_failed_make_absolute, vm));
return;
}
}
private void setVM(List<String> lines, File vm, URI launcherFolder, File installHome) {
if (vm == null) {
if (ParserUtils.getValueForArgument(EquinoxConstants.OPTION_VM, lines) != null)
return;
ParserUtils.removeArgument(EquinoxConstants.OPTION_VM, lines);
return;
}
URI vmRelativePath = null;
if (vm.isAbsolute()) {
// Bug 437680: Correctly relativize on MacOS
// Example: (traditional layout) (bundled layout)
// Install home: install/ Eclipse.app/
// Launcher: Eclipse.app/Contents/MacOS/ Contents/MacOS/
// VM: jre/ jre/
// Result: ../../../jre ../../jre
URI vmRelativePathToHome = installHome.toURI().relativize(vm.toURI());
if (vmRelativePathToHome.isAbsolute()) {
// VM is not below the install root -> use absolute path
vmRelativePath = vmRelativePathToHome;
} else {
// make VM path relative to launcher folder (which is different to the install root in MacOS installs)
vmRelativePath = URIUtil.makeRelative(vm.toURI(), launcherFolder);
}
} else {
//For relative files, File#toURI will create an absolute URI by resolving against the current working directory, we don't want that
String path = vm.getPath().replace('\\', '/');
try {
vmRelativePath = URIUtil.fromString(path);
} catch (URISyntaxException e) {
vmRelativePath = launcherFolder.relativize(vm.toURI());
}
}
ParserUtils.setValueForArgument(EquinoxConstants.OPTION_VM, FileUtils.toPath(vmRelativePath).replace('\\', '/'), lines);
}
private void getJVMArgs(List<String> lines, LauncherData launcherData) {
ArrayList<String> vmargs = new ArrayList<>(lines.size());
boolean foundVmArgs = false;
for (String line : lines) {
if (!foundVmArgs) {
if (EquinoxConstants.OPTION_VMARGS.equals(line))
foundVmArgs = true;
continue;
}
vmargs.add(line);
}
launcherData.setJvmArgs(null);
launcherData.setJvmArgs(vmargs.toArray(new String[vmargs.size()]));
}
private void setJVMArgs(List<String> lines, LauncherData launcherData) {
ParserUtils.removeArgument(EquinoxConstants.OPTION_VMARGS, lines);
if (launcherData.getJvmArgs() == null || launcherData.getJvmArgs().length == 0)
return;
String[] args = launcherData.getJvmArgs();
lines.add(EquinoxConstants.OPTION_VMARGS);
for (String arg : args) {
lines.add(arg);
}
}
private void getProgramArgs(List<String> lines, LauncherData launcherData) {
ArrayList<String> args = new ArrayList<>(lines.size());
for (String line : lines) {
if (EquinoxConstants.OPTION_VMARGS.equals(line))
break;
args.add(line);
}
launcherData.setProgramArgs(null);
launcherData.setProgramArgs(args.toArray(new String[args.size()]));
}
private URI getLauncherLibrary(List<String> lines, URI launcherFolder) {
String launcherLibrary = ParserUtils.getValueForArgument(EquinoxConstants.OPTION_LAUNCHER_LIBRARY, lines);
if (launcherLibrary == null)
return null;
URI result = null;
try {
result = URIUtil.makeAbsolute(FileUtils.fromPath(launcherLibrary), launcherFolder);
ParserUtils.setValueForArgument(EquinoxConstants.OPTION_LAUNCHER_LIBRARY, result.toString(), lines);
} catch (URISyntaxException e) {
Log.log(LogService.LOG_ERROR, NLS.bind(Messages.log_failed_make_absolute, launcherLibrary));
return null;
}
return result;
}
private void setLauncherLibrary(List<String> lines, URI launcherFolder) {
String launcherLibrary = ParserUtils.getValueForArgument(EquinoxConstants.OPTION_LAUNCHER_LIBRARY, lines);
if (launcherLibrary == null)
return;
try {
URI result = URIUtil.makeRelative(FileUtils.fromPath(launcherLibrary), launcherFolder);
ParserUtils.setValueForArgument(EquinoxConstants.OPTION_LAUNCHER_LIBRARY, FileUtils.toPath(result).replace('\\', '/'), lines);
} catch (URISyntaxException e) {
Log.log(LogService.LOG_ERROR, NLS.bind(Messages.log_failed_make_absolute, launcherLibrary));
return;
}
}
private URI getConfigurationLocation(List<String> lines, URI osgiInstallArea, LauncherData data) {
String configuration = ParserUtils.getValueForArgument(EquinoxConstants.OPTION_CONFIGURATION, lines);
if (configuration == null)
try {
return URIUtil.makeAbsolute(new URI(CONFIGURATION_FOLDER), osgiInstallArea);
} catch (URISyntaxException e1) {
//ignore
}
URI result = null;
try {
result = URIUtil.makeAbsolute(FileUtils.fromPath(configuration), osgiInstallArea);
ParserUtils.setValueForArgument(EquinoxConstants.OPTION_CONFIGURATION, result.toString(), lines);
data.setFwConfigLocation(URIUtil.toFile(result));
} catch (URISyntaxException e) {
Log.log(LogService.LOG_ERROR, NLS.bind(Messages.log_failed_make_absolute, configuration));
return null;
}
return result;
}
private void setConfigurationLocation(List<String> lines, URI osgiInstallArea, LauncherData data) {
String result = FileUtils.toPath(URIUtil.makeRelative(data.getFwConfigLocation().toURI(), osgiInstallArea));
//We don't write the default
if (CONFIGURATION_FOLDER.equals(result)) {
if (ParserUtils.getValueForArgument(EquinoxConstants.OPTION_CONFIGURATION, lines) != null)
ParserUtils.removeArgument(EquinoxConstants.OPTION_CONFIGURATION, lines);
return;
}
if (ParserUtils.getValueForArgument(EquinoxConstants.OPTION_CONFIGURATION, lines) == null) {
ParserUtils.setValueForArgument(EquinoxConstants.OPTION_CONFIGURATION, result.replace('\\', '/'), lines);
}
return;
}
private URI getStartup(List<String> lines, URI launcherFolder) {
String startup = ParserUtils.getValueForArgument(EquinoxConstants.OPTION_STARTUP, lines);
if (startup == null)
return null;
URI result = null;
try {
result = URIUtil.makeAbsolute(FileUtils.fromPath(startup), launcherFolder);
ParserUtils.setValueForArgument(EquinoxConstants.OPTION_STARTUP, result.toString(), lines);
} catch (URISyntaxException e) {
Log.log(LogService.LOG_ERROR, NLS.bind(Messages.log_failed_make_absolute, startup));
return null;
}
return result;
}
private void setStartup(List<String> lines, URI launcherFolder) {
String startup = ParserUtils.getValueForArgument(EquinoxConstants.OPTION_STARTUP, lines);
if (startup == null)
return;
try {
URI result = URIUtil.makeRelative(FileUtils.fromPath(startup), launcherFolder);
ParserUtils.setValueForArgument(EquinoxConstants.OPTION_STARTUP, FileUtils.toPath(result).replace('\\', '/'), lines);
} catch (URISyntaxException e) {
Log.log(LogService.LOG_ERROR, NLS.bind(Messages.log_failed_make_relative, startup));
return;
}
}
void save(EquinoxLauncherData launcherData, boolean backup) throws IOException {
File launcherConfigFile = EquinoxManipulatorImpl.getLauncherConfigLocation(launcherData);
if (launcherConfigFile == null)
throw new IllegalStateException(Messages.exception_launcherLocationNotSet);
if (!Utils.createParentDir(launcherConfigFile)) {
throw new IllegalStateException(Messages.exception_failedToCreateDir);
}
//Tweak all the values to make them relative
File launcherFolder = launcherData.getLauncher().getParentFile();
List<String> newlines = new ArrayList<>();
newlines.addAll(Arrays.asList(launcherData.getProgramArgs()));
setStartup(newlines, launcherFolder.toURI());
setInstall(newlines, launcherData, launcherFolder);
//Get the osgi install area
File osgiInstallArea = ParserUtils.getOSGiInstallArea(newlines, null, launcherData);
//setInstall(lines, osgiInstallArea, launcherFolder);
setConfigurationLocation(newlines, osgiInstallArea.toURI(), launcherData);
setLauncherLibrary(newlines, launcherFolder.toURI());
// setFrameworkJar(newlines, launcherData.getFwJar());
setVM(newlines, launcherData.getJvm(), launcherFolder.toURI(), launcherData.getHome());
//We are done, let's update the program args in the launcher data
launcherData.setProgramArgs(null);
launcherData.setProgramArgs(newlines.toArray(new String[newlines.size()]));
//append jvm args
setJVMArgs(newlines, launcherData);
// backup file if exists.
if (backup)
if (launcherConfigFile.exists()) {
File dest = Utils.getSimpleDataFormattedFile(launcherConfigFile);
if (!launcherConfigFile.renameTo(dest))
throw new IOException(NLS.bind(Messages.exception_failedToRename, launcherConfigFile, dest));
Log.log(LogService.LOG_INFO, this, "save()", NLS.bind(Messages.log_renameSuccessful, launcherConfigFile, dest)); //$NON-NLS-1$
}
//only write the file if we actually have content
if (newlines.size() > 0) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(launcherConfigFile));) {
for (String arg : newlines) {
if (arg == null)
continue;
bw.write(arg);
bw.newLine();
}
bw.flush();
Log.log(LogService.LOG_INFO, NLS.bind(Messages.log_launcherConfigSave, launcherConfigFile));
}
}
File previousLauncherIni = launcherData.getPreviousLauncherIni();
if (previousLauncherIni != null && !previousLauncherIni.equals(launcherConfigFile))
previousLauncherIni.delete();
launcherData.setLauncherConfigLocation(launcherConfigFile);
}
}