diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox')
12 files changed, 2840 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/Activator.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/Activator.java new file mode 100644 index 000000000..10b7c7910 --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/Activator.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox; + +import java.util.Dictionary; +import java.util.Hashtable; +import org.eclipse.equinox.internal.provisional.frameworkadmin.FrameworkAdmin; +import org.eclipse.equinox.internal.provisional.frameworkadmin.Manipulator; +import org.osgi.framework.*; + +/** + * This bundle provides the {@link FrameworkAdmin} implementation for Felix. + * + * This bundle registers {@link Manipulator} object with these service property values. + * + * FW_NAME = "Equinox"; + * FW_VERSION = "3.3"; + * LAUCNHER_NAME = "Eclipse.exe"; + * LAUNCHER_VERSION = "3.2"; + * + * The launching by the eclipse launcher is supported. + * + * Handling plugins in non Jar format is not supported. + * + * FwBundleState supports retrieving fw persistent data + * and resolving bundles if running on equinox. + * FwBundleState Does NOT support retrieving start Levels from fw persistent data location/ + * + */ +public class Activator implements BundleActivator { + private static BundleContext context; + private ServiceRegistration registrationFA; + EquinoxFwAdminImpl fwAdmin = null; + + private void registerFwAdmin() { + Dictionary props = new Hashtable(); + props.put(Constants.SERVICE_VENDOR, "Eclipse.org"); + + props.put(FrameworkAdmin.SERVICE_PROP_KEY_FW_NAME, EquinoxConstants.FW_NAME); + props.put(FrameworkAdmin.SERVICE_PROP_KEY_FW_VERSION, EquinoxConstants.FW_VERSION); + props.put(FrameworkAdmin.SERVICE_PROP_KEY_LAUNCHER_NAME, EquinoxConstants.LAUNCHER_NAME); + props.put(FrameworkAdmin.SERVICE_PROP_KEY_LAUNCHER_VERSION, EquinoxConstants.LAUNCHER_VERSION); + + if (EquinoxFwAdminImpl.isRunningFw(context)) { + props.put(FrameworkAdmin.SERVICE_PROP_KEY_RUNNING_SYSTEM_FLAG, "true"); + fwAdmin = new EquinoxFwAdminImpl(context, true); + } else + fwAdmin = new EquinoxFwAdminImpl(context); + + registrationFA = context.registerService(FrameworkAdmin.class.getName(), fwAdmin, props); + } + + /** + * TODO: These services are never disposed. + */ + public static Object acquireService(String serviceName) { + //be tolerant of concurrent shutdown + BundleContext theContext = context; + if (theContext == null) + return null; + ServiceReference reference = theContext.getServiceReference(serviceName); + if (reference == null) + return null; + return theContext.getService(reference); + } + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext bundleContext) throws Exception { + Activator.context = bundleContext; + Log.init(bundleContext); + registerFwAdmin(); + } + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception { + Activator.context = null; + if (registrationFA != null) + registrationFA.unregister(); + if (fwAdmin != null) + fwAdmin.deactivate(); + Log.dispose(); + } +} diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EclipseLauncherImpl.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EclipseLauncherImpl.java new file mode 100644 index 000000000..d62ac6632 --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EclipseLauncherImpl.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox; + +import java.io.File; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import org.eclipse.equinox.internal.frameworkadmin.utils.SimpleBundlesState; +import org.eclipse.equinox.internal.frameworkadmin.utils.Utils; +import org.eclipse.equinox.internal.provisional.frameworkadmin.*; +import org.osgi.service.log.LogService; + +public class EclipseLauncherImpl { + static String getStringOfCmd(String[] cmdarray) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < cmdarray.length; i++) { + sb.append(cmdarray[i]); + sb.append(" "); + } + return sb.toString(); + } + + // BundleContext context = null; + + EquinoxFwAdminImpl fwAdmin = null; + + EclipseLauncherImpl(EquinoxFwAdminImpl fwAdmin) { + //EclipseLauncherImpl(BundleContext context, EquinoxFwAdminImpl fwAdmin) { + // this.context = context; + this.fwAdmin = fwAdmin; + } + + public Process launch(Manipulator manipulator, File cwd) throws IllegalArgumentException, IOException, FrameworkAdminRuntimeException { + SimpleBundlesState.checkAvailability(fwAdmin); + Log.log(LogService.LOG_DEBUG, this, "launch(Manipulator , File )", ""); + LauncherData launcherData = manipulator.getLauncherData(); + if (launcherData.getLauncher() == null) + return launchInMemory(manipulator, cwd); + return launchByLauncher(manipulator, cwd); + } + + private Process launchByLauncher(Manipulator manipulator, File cwd) throws IOException { + LauncherData launcherData = manipulator.getLauncherData(); + + if (launcherData.getLauncher() == null) + throw new IllegalStateException("launcherData.getLauncher() must be set."); + String[] cmdarray = new String[] {launcherData.getLauncher().getAbsolutePath()}; + // try { + if (cwd == null) + cwd = launcherData.getLauncher().getParentFile(); + Process process = Runtime.getRuntime().exec(cmdarray, null, cwd); + Log.log(LogService.LOG_DEBUG, "\t" + getStringOfCmd(cmdarray)); + return process; + } + + private Process launchInMemory(Manipulator manipulator, File cwd) throws IOException { + LauncherData launcherData = manipulator.getLauncherData(); + Utils.checkAbsoluteFile(launcherData.getFwJar(), "fwJar"); + // this.launcherCInfo.fwJar = fwJar; + // if (cwd == null) + // cwd = fwJar.; + Utils.checkAbsoluteDir(cwd, "cwd"); + + List cmdList = new LinkedList(); + if (launcherData.getJvm() != null) + cmdList.add(launcherData.getJvm().getAbsolutePath()); + else + cmdList.add("java"); + + if (launcherData.getJvmArgs() != null) + for (int i = 0; i < launcherData.getJvmArgs().length; i++) + cmdList.add(launcherData.getJvmArgs()[i]); + + cmdList.add("-jar"); + cmdList.add(Utils.getRelativePath(launcherData.getFwJar(), cwd)); + + EquinoxManipulatorImpl.checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(launcherData);//checkConsistency(this.launcherCInfo.fwConfigFile, this.launcherCInfo.fwInstancePrivateArea); + cmdList.add(EquinoxConstants.OPTION_CONFIGURATION); + cmdList.add(Utils.getRelativePath(launcherData.getFwPersistentDataLocation(), cwd)); + + if (launcherData.isClean()) + cmdList.add(EquinoxConstants.OPTION_CLEAN); + + String[] cmdarray = new String[cmdList.size()]; + cmdList.toArray(cmdarray); + Log.log(LogService.LOG_DEBUG, "In CWD = " + cwd + "\n\t" + getStringOfCmd(cmdarray)); + Process process = Runtime.getRuntime().exec(cmdarray, null, cwd); + return process; + } +} diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EclipseLauncherParser.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EclipseLauncherParser.java new file mode 100644 index 000000000..3b5c7e92c --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EclipseLauncherParser.java @@ -0,0 +1,283 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox; + +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.equinox.internal.frameworkadmin.equinox.utils.FileUtils; +import org.eclipse.equinox.internal.frameworkadmin.utils.Utils; +import org.eclipse.equinox.internal.provisional.frameworkadmin.LauncherData; +import org.osgi.service.log.LogService; + +public class EclipseLauncherParser { + + private String[] getConfigFileLines(LauncherData launcherData, File outputFile, boolean relative) { + List lines = new LinkedList(); + + boolean startUpFlag = false; + final String[] programArgs = launcherData.getProgramArgs(); + if (programArgs != null && programArgs.length != 0) + for (int i = 0; i < programArgs.length; i++) { + if (programArgs[i].equals(EquinoxConstants.OPTION_STARTUP) && (programArgs[i + 1] != null || programArgs[i + 1].length() != 0)) { + lines.add(programArgs[i]); + lines.add(programArgs[++i]); + startUpFlag = true; + } else + lines.add(programArgs[i]); + } + if (launcherData.isClean()) + lines.add(EquinoxConstants.OPTION_CLEAN); + File fwPersistentDataLocation = launcherData.getFwPersistentDataLocation(); + File fwConfigLocation = launcherData.getFwConfigLocation(); + if (fwPersistentDataLocation != null) { + if (fwConfigLocation != null) { + if (!fwPersistentDataLocation.equals(fwConfigLocation)) + throw new IllegalStateException(); + } + launcherData.setFwConfigLocation(fwPersistentDataLocation); + } else if (fwConfigLocation != null) + launcherData.setFwPersistentDataLocation(fwConfigLocation, launcherData.isClean()); + + if (launcherData.getFwConfigLocation() != null) { + lines.add(EquinoxConstants.OPTION_CONFIGURATION); + lines.add(launcherData.getFwConfigLocation().getAbsolutePath()); + } + + if (!startUpFlag) + if (launcherData.getFwJar() != null) { + lines.add(EquinoxConstants.OPTION_FW); + String path = ""; + //if (relative) + // path = Utils.getRelativePath(launcherData.getFwJar(), outputFile.getParentFile()); + //else + path = launcherData.getFwJar().getAbsolutePath(); + lines.add(path); + } + + if (launcherData.getJvm() != null) { + lines.add(EquinoxConstants.OPTION_VM); + lines.add(launcherData.getJvm().getAbsolutePath()); + } + final String[] jvmArgs = launcherData.getJvmArgs(); + if (jvmArgs != null && jvmArgs.length != 0) { + lines.add(EquinoxConstants.OPTION_VMARGS); + for (int i = 0; i < jvmArgs.length; i++) + lines.add(jvmArgs[i]); + } + String[] ret = new String[lines.size()]; + lines.toArray(ret); + return ret; + } + + private void parseCmdLine(LauncherData launcherData, String[] lines) { + //Log.log(LogService.LOG_DEBUG, "inputFile=" + inputFile.getAbsolutePath()); + // final File launcherFile = launcherData.getLauncher(); + final File launcherConfigFile = EquinoxManipulatorImpl.getLauncherConfigLocation(launcherData); + + boolean clean = launcherData.isClean(); + boolean needToUpdate = false; + File fwPersistentDataLoc = launcherData.getFwPersistentDataLocation(); + File fwConfigLocation = launcherData.getFwConfigLocation(); + if (fwPersistentDataLoc == null) { + if (fwConfigLocation == null) { + fwPersistentDataLoc = new File(launcherConfigFile.getParent(), EquinoxConstants.DEFAULT_CONFIGURATION); + fwConfigLocation = fwPersistentDataLoc; + needToUpdate = true; + } else { + fwPersistentDataLoc = fwConfigLocation; + needToUpdate = true; + } + } else { + if (fwConfigLocation == null) { + fwConfigLocation = fwPersistentDataLoc; + needToUpdate = true; + } + } + + File fwJar = launcherData.getFwJar(); + if (fwJar == null) { + String location = FileUtils.getEclipsePluginFullLocation(EquinoxConstants.FW_SYMBOLIC_NAME, new File(launcherConfigFile.getParent(), EquinoxConstants.PLUGINS_DIR)); + if (location != null) + try { + fwJar = new File(new URL(location).getFile()); + launcherData.setFwJar(fwJar); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + // launcherData.initialize(); // reset except launcherFile. + + // launcherData.setLauncher(launcherFile); + boolean vmArgsFlag = false; + + for (int i = 0; i < lines.length; i++) { + final String line = lines[i].trim(); + StringTokenizer tokenizer = new StringTokenizer(line, " "); + if (line.startsWith("#")) + continue; + if (line.length() == 0) + continue; + if (tokenizer.countTokens() != 1) { + Log.log(LogService.LOG_WARNING, this, "parseCmdLine(String[] lines, File inputFile)", "Illegal Format:line=" + line + "tokenizer.countTokens()=" + tokenizer.countTokens()); + //throw new IOException("Illegal Format:line=" + line + "tokenizer.countTokens()=" + tokenizer.countTokens()); + } + if (vmArgsFlag) { + launcherData.addJvmArg(line); + continue; + } + if (line.startsWith("-vmargs")) { + vmArgsFlag = true; + continue; + } + if (line.startsWith(EquinoxConstants.OPTION_CONFIGURATION)) { + final String nextLine = lines[++i].trim(); + File file = new File(nextLine); + if (!file.isAbsolute()) + file = new File(launcherConfigFile.getParent() + File.separator + nextLine); + fwPersistentDataLoc = file; + needToUpdate = true; + continue; + } else if (line.startsWith(EquinoxConstants.OPTION_CLEAN)) { + clean = true; + needToUpdate = true; + continue; + } else if (line.startsWith(EquinoxConstants.OPTION_VM)) { + final String nextLine = lines[++i].trim(); + File file = new File(nextLine); + if (!file.isAbsolute()) { + file = new File(launcherConfigFile.getAbsolutePath() + File.separator + nextLine); + } + launcherData.setJvm(file); + continue; + } else if (line.startsWith(EquinoxConstants.OPTION_FW)) { + final String nextLine = lines[++i].trim(); + File file = new File(nextLine); + if (!file.isAbsolute()) { + file = new File(launcherConfigFile.getAbsolutePath() + File.separator + nextLine); + } + launcherData.setFwJar(file); + continue; + } else { + launcherData.addProgramArg(lines[i]); + // Log.log(LogService.LOG_WARNING, this, "parseCmdLine(String[] lines, File inputFile)", "Unsupported by current impl:line=" + line); + } + } + if (needToUpdate) { + launcherData.setFwPersistentDataLocation(fwPersistentDataLoc, clean); + launcherData.setFwConfigLocation(fwPersistentDataLoc); + } + } + + public void read(LauncherData launcherData) throws IOException { + final File launcherConfigFile = EquinoxManipulatorImpl.getLauncherConfigLocation(launcherData); + if (launcherConfigFile == null) + throw new IllegalStateException("launcherData.getLauncherConfigFile() should be set in advance."); + if (!launcherConfigFile.exists()) + return; + + BufferedReader br = null; + try { + br = new BufferedReader(new FileReader(launcherConfigFile)); + + String line; + List list = new LinkedList(); + while ((line = br.readLine()) != null) { + list.add(line); + } + String[] lines = (String[]) list.toArray(new String[list.size()]); + String osgiInstallArea = getLauncher(lines) != null ? EquinoxManipulatorImpl.makeAbsolute(getLauncher(lines).getPath(), launcherData.getLauncher().getParentFile().getAbsolutePath()) : null; + + String resolveNextLine = null; + for (int i = 0; i < lines.length; i++) { + if (resolveNextLine != null) { + lines[i] = EquinoxManipulatorImpl.makeAbsolute(lines[i], resolveNextLine); + resolveNextLine = null; + } else { + resolveNextLine = needsPathResolution(lines[i], osgiInstallArea, launcherData.getLauncher().getParentFile().getAbsolutePath() + File.separator); + } + } + this.parseCmdLine(launcherData, lines); + } finally { + if (br != null) + br.close(); + } + Log.log(LogService.LOG_INFO, "Launcher Config file(" + launcherConfigFile.getAbsolutePath() + ") is read successfully."); + } + + private File getLauncher(String[] args) { + for (int i = 0; i < args.length; i++) { + if (args[i].equals(EquinoxConstants.OPTION_STARTUP) && i + 1 < args.length && args[i + 1].charAt(1) != '-') { + IPath parentFolder = new Path(args[i + 1]).removeLastSegments(1); + if (parentFolder.lastSegment().equals("plugins")) + return parentFolder.removeLastSegments(1).toFile(); + return parentFolder.toFile(); + } + } + return null; + } + + private String needsPathResolution(String entry, String osgiInstallArea, String launcherFolder) { + if (EquinoxConstants.OPTION_CONFIGURATION.equalsIgnoreCase(entry)) + return launcherFolder; + if ("--launcher.library".equalsIgnoreCase(entry)) + return launcherFolder; + if (EquinoxConstants.OPTION_STARTUP.equalsIgnoreCase(entry)) + return launcherFolder; + if (EquinoxConstants.OPTION_FW.equalsIgnoreCase(entry)) + return osgiInstallArea != null ? osgiInstallArea : launcherFolder; + if (EquinoxConstants.OPTION_SHOWSPLASH.equalsIgnoreCase(entry)) + return launcherFolder; + return null; + } + + public void save(LauncherData launcherData, boolean relative, boolean backup) throws IOException { + File launcherConfigFile = EquinoxManipulatorImpl.getLauncherConfigLocation(launcherData); + + if (launcherConfigFile == null) + throw new IllegalStateException("launcherConfigFile cannot be set. launcher file should be set in advance."); + Utils.createParentDir(launcherConfigFile); + // backup file if exists. + if (backup) + if (launcherConfigFile.exists()) { + File dest = Utils.getSimpleDataFormattedFile(launcherConfigFile); + if (!launcherConfigFile.renameTo(dest)) + throw new IOException("Fail to rename from (" + launcherConfigFile + ") to (" + dest + ")"); + Log.log(LogService.LOG_INFO, this, "saveConfigs()", "Succeed to rename from (" + launcherConfigFile + ") to (" + dest + ")"); + } + + BufferedWriter bw = null; + try { + bw = new BufferedWriter(new FileWriter(launcherConfigFile)); + + String[] lines = this.getConfigFileLines(launcherData, launcherConfigFile, relative); + String osgiInstallArea = getLauncher(lines) != null ? EquinoxManipulatorImpl.makeAbsolute(getLauncher(lines).getPath(), launcherData.getLauncher().getParentFile().getAbsolutePath()) : launcherData.getLauncher().getParentFile().getAbsolutePath(); + String resolveNextLine = null; + for (int i = 0; i < lines.length; i++) { + if (resolveNextLine != null) { + lines[i] = EquinoxManipulatorImpl.makeRelative(lines[i], resolveNextLine); + resolveNextLine = null; + } else { + resolveNextLine = needsPathResolution(lines[i], osgiInstallArea, launcherData.getLauncher().getParentFile().getAbsolutePath() + File.separator); + } + bw.write(lines[i]); + bw.newLine(); + } + bw.flush(); + Log.log(LogService.LOG_INFO, "Launcher Config file is saved successfully into:" + launcherConfigFile); + } finally { + if (bw != null) + bw.close(); + } + } +} diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxBundlesState.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxBundlesState.java new file mode 100644 index 000000000..6a43fb59f --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxBundlesState.java @@ -0,0 +1,755 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox; + +import java.io.File; +import java.net.MalformedURLException; +import java.util.*; +import org.eclipse.core.runtime.internal.adaptor.EclipseEnvironmentInfo; +import org.eclipse.equinox.internal.frameworkadmin.equinox.utils.FileUtils; +import org.eclipse.equinox.internal.frameworkadmin.utils.SimpleBundlesState; +import org.eclipse.equinox.internal.frameworkadmin.utils.Utils; +import org.eclipse.equinox.internal.provisional.frameworkadmin.*; +import org.eclipse.osgi.framework.internal.core.FrameworkProperties; +import org.eclipse.osgi.service.resolver.*; +import org.osgi.framework.*; +import org.osgi.service.log.LogService; + +public class EquinoxBundlesState implements BundlesState { + static final long DEFAULT_TIMESTAMP = 0L; + private static final boolean DEBUG = false; + // While we recognize the amd64 architecture, we change + // this internally to be x86_64. + private static final String INTERNAL_AMD64 = "amd64"; //$NON-NLS-1$ + private static final String INTERNAL_ARCH_I386 = "i386"; //$NON-NLS-1$ + public static final String[] PROPS = {"osgi.os", "osgi.ws", "osgi.nl", "osgi.arch", Constants.FRAMEWORK_SYSTEMPACKAGES, "osgi.resolverMode", Constants.FRAMEWORK_EXECUTIONENVIRONMENT, "osgi.resolveOptional", "osgi.genericAliases"}; + + static boolean checkFullySupported() { + //TODO - This was previously doing a bogus check by attempting to instantiate a particular class - it's not clear what this is trying to do + return true; + } + + /** + * eclipse.exe will launch a fw where plugins/org.eclipse.osgi_*.*.*.*.jar + * is an implementation of fw. + * + * @param launcherData + * @param configData + * @return File of fwJar to be used. + */ + static File getFwJar(LauncherData launcherData, ConfigData configData) { + return getFwJar(launcherData, configData, true); + // + // // EclipseLauncherParser launcherParser = new + // EclipseLauncherParser(launcherData); + // // launcherParser.read(); + // if (launcherData.getFwJar() != null) + // return launcherData.getFwJar(); + // + // // check -D arguments of jvmArgs ? + // String[] jvmArgs = launcherData.getJvmArgs(); + // String location = null; + // for (int i = 0; i < jvmArgs.length; i++) { + // if (jvmArgs[i].endsWith("-D" + "osgi.framework=")) { + // location = jvmArgs[i].substring(("-D" + "osgi.framework=").length()); + // } + // } + // if (location != null) + // return new File(location); + // + // File ret = getSystemBundleFromBundleInfos(launcherData, configData); + // if (ret != null) + // return ret; + // return getSystemBundleBySearching(launcherData); + } + + private static File getFwJar(LauncherData launcherData, ConfigData configData, boolean checkBundleInfos) { + // EclipseLauncherParser launcherParser = new + // EclipseLauncherParser(launcherData); + // launcherParser.read(); + if (launcherData.getFwJar() != null) { + return launcherData.getFwJar(); + } + + // check -D arguments of jvmArgs ? + String[] jvmArgs = launcherData.getJvmArgs(); + String location = null; + for (int i = 0; i < jvmArgs.length; i++) { + if (jvmArgs[i].endsWith("-D" + "osgi.framework=")) { + location = jvmArgs[i].substring(("-D" + "osgi.framework=").length()); + } + } + if (location != null) { + return new File(location); + } + + if (checkBundleInfos) { + File ret = getSystemBundleFromBundleInfos(configData); + if (ret != null) { + return ret; + } + } + return null; + // return getSystemBundleBySearching(launcherData); + } + + private static long getMaxId(State state) { + BundleDescription[] bundleDescriptions = state.getBundles(); + long maxId = DEFAULT_TIMESTAMP; + for (int i = 0; i < bundleDescriptions.length; i++) + if (maxId < bundleDescriptions[i].getBundleId()) { + maxId = bundleDescriptions[i].getBundleId(); + } + return maxId; + } + + // private static File getSystemBundleBySearching(LauncherData launcherData) { + // File pluginsDir; + // if (launcherData.getLauncher() == null) { + // if (launcherData.getHome() == null) + // return null; + // pluginsDir = new File(launcherData.getHome(), "plugins"); + // } else { + // pluginsDir = new File(launcherData.getLauncher().getParentFile(), "plugins"); + // } + // + // String fullLocation = FileUtils.getEclipsePluginFullLocation(EquinoxConstants.FW_SYMBOLIC_NAME, pluginsDir); + // if (fullLocation == null) + // return null; + // URL url = null; + // try { + // url = new URL(fullLocation); + // } catch (MalformedURLException e) { + // // TODO Auto-generated catch block + // Log.log(LogService.LOG_WARNING, "fullLocation is not in proper format:" + fullLocation); + // } + // return url == null ? null : new File(url.getFile()); + // } + + private static File getSystemBundleFromBundleInfos(BundleInfo[] bundleInfos) { + for (int i = 0; i < bundleInfos.length; i++) { + File match = isSystemBundle(bundleInfos[i]); + if (match != null) + return match; + } + return null; + } + + private static File getSystemBundleFromBundleInfos(ConfigData configData) { + BundleInfo[] bundleInfos = configData.getBundles(); + return getSystemBundleFromBundleInfos(bundleInfos); + } + + static long getTimeStamp(File fwPersistentDataLocation) { + if (fwPersistentDataLocation == null) + return DEFAULT_TIMESTAMP; + + File file = new File(fwPersistentDataLocation, EquinoxConstants.PERSISTENT_DIR_NAME); + if (!file.exists() || !file.isDirectory()) + return DEFAULT_TIMESTAMP; + long ret = file.lastModified(); + File[] lists = file.listFiles(); + if (lists == null) + return ret; + for (int i = 0; i < lists.length; i++) + if (ret < lists[i].lastModified()) + ret = lists[i].lastModified(); + return ret; + } + + public static File isSystemBundle(BundleInfo bundleInfo) { + if (bundleInfo == null || bundleInfo.getLocation() == null) + return null; + String bundleLocation = bundleInfo.getLocation(); + if (bundleLocation.startsWith(EquinoxConstants.REFERENCE)) + bundleLocation = bundleLocation.substring(EquinoxConstants.REFERENCE.length()); + if (bundleLocation.startsWith("file:")) { + try { + String[] clauses = Utils.getClausesManifestMainAttributes(bundleLocation, Constants.BUNDLE_SYMBOLICNAME); + if (bundleLocation.indexOf(EquinoxConstants.FW_SYMBOLIC_NAME) > 0) + if (EquinoxConstants.PERSISTENT_DIR_NAME.equals(Utils.getPathFromClause(clauses[0]))) + return new File(bundleLocation.substring("file:".length())); + } catch (RuntimeException e) { + e.printStackTrace(); + } + } + + return null; + } + + // "osgi.os", "osgi.ws", "osgi.nl", "osgi.arch", + // Constants.FRAMEWORK_SYSTEMPACKAGES, "osgi.resolverMode", + // Constants.FRAMEWORK_EXECUTIONENVIRONMENT, "osgi.resolveOptional" + static Properties setDefaultPlatformProperties() { + Properties platformProperties = new Properties(); + // set default value + + String nl = Locale.getDefault().toString(); + platformProperties.setProperty("osgi.nl", nl); //$NON-NLS-1$ + + // TODO remove EclipseEnvironmentInof + String os = EclipseEnvironmentInfo.guessOS(System.getProperty("os.name"));//$NON-NLS-1$); + platformProperties.setProperty("osgi.os", os); //$NON-NLS-1$ + + String ws = EclipseEnvironmentInfo.guessWS(os); + platformProperties.setProperty("osgi.ws", ws); + + // if the user didn't set the system architecture with a command line + // argument then use the default. + String arch = null; + String name = FrameworkProperties.getProperty("os.arch");//$NON-NLS-1$ + // Map i386 architecture to x86 + if (name.equalsIgnoreCase(INTERNAL_ARCH_I386)) + arch = org.eclipse.osgi.service.environment.Constants.ARCH_X86; + // Map amd64 architecture to x86_64 + else if (name.equalsIgnoreCase(INTERNAL_AMD64)) + arch = org.eclipse.osgi.service.environment.Constants.ARCH_X86_64; + else + arch = name; + platformProperties.setProperty("osgi.arch", arch); //$NON-NLS-1$ + + platformProperties.setProperty(Constants.FRAMEWORK_SYSTEMPACKAGES, FrameworkProperties.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES)); + platformProperties.setProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, FrameworkProperties.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT)); + platformProperties.setProperty("osgi.resolveOptional", "" + "true".equals(FrameworkProperties.getProperty("osgi.resolveOptional"))); + return platformProperties; + } + + EquinoxFwAdminImpl fwAdmin = null; + + BundleContext context; + + Manipulator manipulator = null; + Properties platfromProperties = new Properties(); + + long maxId = DEFAULT_TIMESTAMP; + + StateObjectFactory soFactory = null; + + State state = null; + + /** + * If useFwPersistentData flag equals false, this constructor will not take + * a framework persistent data into account. Otherwise, it will. + * + * @param context + * @param fwAdmin + * @param manipulator + * @param useFwPersistentData + */ + EquinoxBundlesState(BundleContext context, EquinoxFwAdminImpl fwAdmin, Manipulator manipulator, boolean useFwPersistentData) { + this.context = context; + this.fwAdmin = fwAdmin; + // copy manipulator object for avoiding modifying the parameters of the + // manipulator. + this.manipulator = fwAdmin.getManipulator(); + this.manipulator.setConfigData(manipulator.getConfigData()); + this.manipulator.setLauncherData(manipulator.getLauncherData()); + initialize(useFwPersistentData); + } + + /** + * This constructor does NOT take a framework persistent data into account. + * It will create State object based on the specified platformProperties. + * + * @param context + * @param fwAdmin + * @param manipulator + * @param platformProperties + */ + EquinoxBundlesState(BundleContext context, EquinoxFwAdminImpl fwAdmin, Manipulator manipulator, Properties platformProperties) { + super(); + this.context = context; + this.fwAdmin = fwAdmin; + // copy manipulator object for avoiding modifying the parameters of the + // manipulator. + this.manipulator = fwAdmin.getManipulator(); + this.manipulator.setConfigData(manipulator.getConfigData()); + this.manipulator.setLauncherData(manipulator.getLauncherData()); + LauncherData launcherData = manipulator.getLauncherData(); + ConfigData configData = manipulator.getConfigData(); + BundleInfo[] bInfos = configData.getBundles(); + this.composeNewState(launcherData, configData, platformProperties, bInfos); + } + + /** + * compose new state without reading framework persistent data. The + * configData.getFwDependentProps() is used for the composition. + * + * @param launcherData + * @param configData + * @param bInfos + */ + private void composeNewState(LauncherData launcherData, ConfigData configData, BundleInfo[] bInfos) { + this.composeNewState(launcherData, configData, configData.getFwDependentProps(), bInfos); + } + + /** + * compose new state without reading framework persistent data. The given + * properties is used for the composition. If system bundle is not included + * in the given bInfos, the fw jar launcherData contains will be used. + * + * @param launcherData + * @param configData + * @param properties + * @param bInfos + */ + private void composeNewState(LauncherData launcherData, ConfigData configData, Properties properties, BundleInfo[] bInfos) { + //Note, there use to be a lot more code in this method + File fwJar = getSystemBundleFromBundleInfos(configData); + launcherData.setFwJar(fwJar); + this.setFwJar(fwJar); + composeState(configData.getBundles(), properties, null); + resolve(true); + } + + /** + * compose state. If it cannot compose it by somehow, false is returned. + * + * @param bInfos + * @param props + * @param fwPersistentDataLocation + * @return if it cannot compose it by somehow, false is returned. + * @throws IllegalArgumentException + * @throws FrameworkAdminRuntimeException + */ + private boolean composeState(BundleInfo[] bInfos, Dictionary props, File fwPersistentDataLocation) throws IllegalArgumentException, FrameworkAdminRuntimeException { + BundleInfo[] infos = manipulator.getConfigData().getBundles(); + this.manipulator.getConfigData().setBundles(null); + SimpleBundlesState.checkAvailability(fwAdmin); + this.setStateObjectFactory(); + BundleDescription[] cachedInstalledBundles = null; + state = null; + boolean flagNewState = false; + if (fwPersistentDataLocation != null) { + //NOTE Here there was a big chunk of code reading the framework state persisted on disk + // and I removed it because it was causing various problems. See in previous revision + this.manipulator.getConfigData().setBundles(infos); + return false; + } + state = soFactory.createState(true); + flagNewState = true; + cachedInstalledBundles = new BundleDescription[0]; + if (props == null) { + this.manipulator.getConfigData().setBundles(infos); + return false; + } + setPlatformPropertiesToState(props); + setPlatformProperties(state); + + // remove initial bundle which were installed but not listed in + // fwConfigFileBInfos. + // bundleList.addAll(Arrays.asList(cachedInstalledBundles)); + for (int i = 0; i < cachedInstalledBundles.length; i++) { + if (cachedInstalledBundles[i].getLocation().startsWith("initial@")) { + String location = FileUtils.getRealLocation(manipulator, cachedInstalledBundles[i].getLocation(), true); + boolean found = false; + for (int j = 0; j < bInfos.length; j++) { + if (bInfos[j].getLocation().equals(location)) { + found = true; + break; + } + } + if (!found) + state.removeBundle(cachedInstalledBundles[i].getBundleId()); + } + } + + try { + maxId = state.getHighestBundleId(); + } catch (NoSuchMethodError e) { + maxId = getMaxId(state); + } + if (DEBUG) { + System.out.println(""); + Log.log(LogService.LOG_DEBUG, this, "composeExpectedState()", "installBundle():"); + } + if (flagNewState) { + int indexSystemBundle = -1; + for (int j = 0; j < bInfos.length; j++) + if (isSystemBundle(bInfos[j]) != null) { + indexSystemBundle = j; + break; + } + + if (indexSystemBundle > 0) { + BundleInfo[] newBundleInfos = new BundleInfo[bInfos.length]; + newBundleInfos[0] = bInfos[indexSystemBundle]; + System.arraycopy(bInfos, 0, newBundleInfos, 1, indexSystemBundle); + if (indexSystemBundle < bInfos.length - 1) + System.arraycopy(bInfos, indexSystemBundle + 1, newBundleInfos, indexSystemBundle + 1, bInfos.length - indexSystemBundle - 1); + bInfos = newBundleInfos; + } + } + for (int j = 0; j < bInfos.length; j++) { + if (DEBUG) + Log.log(LogService.LOG_DEBUG, this, "composeExpectedState()", "bInfos[" + j + "]=" + bInfos[j]); + try { + this.installBundle(bInfos[j]); + // System.out.println("install bInfos[" + j + "]=" + bInfos[j]); + } catch (RuntimeException e) { + //catch the exception and continue + Log.log(LogService.LOG_ERROR, this, "composeExpectedState()", "BundleInfo:" + bInfos[j], e); + } + } + return true; + } + + public BundleInfo convert(BundleDescription toConvert) { + boolean markedAsStarted = false; + int sl = BundleInfo.NO_LEVEL; + + String location = null; + // This algorithm is not sophisticated. + if (toConvert.getBundleId() == 0 && EquinoxConstants.FW_SYMBOLIC_NAME.equals(toConvert.getSymbolicName())) { + // Converting the System Bundle + String symbolicNameTarget = toConvert.getSymbolicName(); + Version versionTarget = toConvert.getVersion(); + try { + File fwJar = manipulator.getLauncherData().getFwJar(); + if (fwJar != null) { + String fwJarLocation = fwJar.toURL().toExternalForm(); + String[] clauses = Utils.getClausesManifestMainAttributes(fwJarLocation, Constants.BUNDLE_SYMBOLICNAME); + String fwJarSymbolicName = Utils.getPathFromClause(clauses[0]); + String fwJarVersionSt = Utils.getManifestMainAttributes(fwJarLocation, Constants.BUNDLE_VERSION); + if (fwJarSymbolicName.equals(symbolicNameTarget) && fwJarVersionSt.equals(versionTarget.toString())) { + location = fwJarLocation; + markedAsStarted = true; + } + } + } catch (MalformedURLException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (FrameworkAdminRuntimeException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } else { + location = FileUtils.getEclipseRealLocation(manipulator, toConvert.getLocation()); + BundleInfo[] originalBInfos = manipulator.getConfigData().getBundles(); + // if (DEBUG) + // System.out.println("toConvert=" + location); + boolean found = false; + for (int i = 0; i < originalBInfos.length; i++) { + // if (DEBUG) + // System.out.println("originalBInfos[" + i + "]=" + + // originalBInfos[i].getLocation()); + if (originalBInfos[i].getLocation().equals(location)) { + markedAsStarted = originalBInfos[i].isMarkedAsStarted(); + sl = getStartLevel(originalBInfos[i].getStartLevel()); + found = true; + break; + } + } + if (!found) { + // TODO current equinox impl has no way to get the start level + // info persistently stored. + markedAsStarted = false; + sl = BundleInfo.NO_LEVEL; + } + } + BundleInfo result = new BundleInfo(); + result.setSymbolicName(toConvert.getSymbolicName()); + result.setVersion(toConvert.getVersion().toString()); + result.setLocation(location); + result.setResolved(toConvert.isResolved()); + result.setMarkedAsStarted(markedAsStarted); + result.setStartLevel(sl); + result.setBundleId(toConvert.getBundleId()); + return result; + } + + public BundleInfo[] convertState(BundleDescription[] bundles) { + BundleInfo[] result = new BundleInfo[bundles.length]; + for (int i = 0; i < bundles.length; i++) { + result[i] = convert(bundles[i]); + } + return result; + } + + public BundleInfo[] getExpectedState() throws FrameworkAdminRuntimeException { + SimpleBundlesState.checkAvailability(fwAdmin); + return convertState(state.getBundles()); + } + + Properties getPlatformProperties() { + return platfromProperties; + } + + public BundleInfo[] getPrerequisteBundles(BundleInfo bInfo) { + Set set = new HashSet(); + BundleDescription bundle = state.getBundleByLocation(bInfo.getLocation()); + ImportPackageSpecification[] imports = bundle.getImportPackages(); + for (int i = 0; i < imports.length; i++) { + BaseDescription supplier = imports[i].getSupplier(); + set.add(supplier.getSupplier()); + // System.out.println(supplier.getSupplier()); + } + BundleDescription[] requires = bundle.getResolvedRequires(); + for (int i = 0; i < requires.length; i++) { + set.add(requires[i]); + } + BundleDescription[] bundles = new BundleDescription[set.size()]; + set.toArray(bundles); + return convertState(bundles); + } + + private int getStartLevel(int startLevel) { + return (startLevel == BundleInfo.NO_LEVEL ? manipulator.getConfigData().getInitialBundleStartLevel() : startLevel); + } + + public BundleInfo getSystemBundle() { + BundleDescription bundle = this.getSystemBundleDescription(); + return (bundle != null ? convert(bundle) : null); + } + + private BundleDescription getSystemBundleDescription() { + BundleDescription bundle = state.getBundle(0); + if (bundle == null || bundle.getHost() != null) { // null or a + // fragment bundle. + return null; + } + // if (DEBUG) { + // System.out.println("EquinoxConstants.FW_SYMBOLIC_NAME=" + + // EquinoxConstants.FW_SYMBOLIC_NAME); + // System.out.println("bundle.getSymbolicName()=" + + // bundle.getSymbolicName()); + // } + return (EquinoxConstants.FW_SYMBOLIC_NAME.equals(bundle.getSymbolicName()) ? bundle : null); + } + + public BundleInfo[] getSystemFragmentedBundles() { + BundleDescription bundle = this.getSystemBundleDescription(); + if (bundle == null) + return null; + return convertState(bundle.getFragments()); + } + + public String[] getUnsatisfiedConstraints(BundleInfo bInfo) { + BundleDescription description = state.getBundleByLocation(bInfo.getLocation()); + PlatformAdmin platformAdmin = (PlatformAdmin) Activator.acquireService(PlatformAdmin.class.getName()); + StateHelper helper = platformAdmin.getStateHelper(); + VersionConstraint[] constraints = helper.getUnsatisfiedConstraints(description); + String[] ret = new String[constraints.length]; + for (int i = 0; i < constraints.length; i++) + ret[i] = constraints[i].toString(); + return ret; + } + + private void initialize(boolean useFwPersistentData) { + LauncherData launcherData = manipulator.getLauncherData(); + ConfigData configData = manipulator.getConfigData(); + BundleInfo[] bInfos = configData.getBundles(); + + if (!useFwPersistentData) { + composeNewState(launcherData, configData, bInfos); + return; + } + + EquinoxManipulatorImpl.checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(launcherData); + if (launcherData.isClean()) { + composeNewState(launcherData, configData, bInfos); + } else { + if (manipulator.getLauncherData().getFwPersistentDataLocation() == null) { + // TODO default value should be set more precisely. + File installArea = null; + String installAreaSt = configData.getFwDependentProp(EquinoxConstants.PROP_INSTALL); + if (installAreaSt == null) { + if (manipulator.getLauncherData().getLauncher() == null) { + // TODO implement + } else { + installArea = manipulator.getLauncherData().getLauncher().getParentFile(); + } + } else { + if (installAreaSt.startsWith("file:")) + installArea = new File(installAreaSt.substring("file:".length())); + else + throw new IllegalStateException("Current implementation assume that property value keyed by " + EquinoxConstants.PROP_INSTALL + " must start with \"file:\". But it was not:" + installAreaSt); + } + if (DEBUG) + Log.log(LogService.LOG_DEBUG, this, "initialize(useFwPersistentDat)", "installArea=" + installArea); + File fwPersistentDataLocation = new File(installArea, "configuration"); + manipulator.getLauncherData().setFwPersistentDataLocation(fwPersistentDataLocation, false); + } + if (!composeState(bInfos, null, manipulator.getLauncherData().getFwPersistentDataLocation())) + composeNewState(launcherData, configData, bInfos); + resolve(true); + // if(this.getSystemBundle()==null) + } + } + + public void installBundle(BundleInfo bInfo) throws FrameworkAdminRuntimeException { + SimpleBundlesState.checkAvailability(fwAdmin); + boolean found = false; + + BundleDescription[] currentInstalledBundles = state.getBundles(); + String newLocation = FileUtils.getRealLocation(manipulator, bInfo.getLocation(), true); + Dictionary manifest = Utils.getOSGiManifest(newLocation); + if (manifest != null) { + String newSymbolicName = (String) manifest.get(Constants.BUNDLE_SYMBOLICNAME); + int position = newSymbolicName.indexOf(";"); + if (position >= 0) + newSymbolicName = newSymbolicName.substring(0, position).trim(); + String newVersion = (String) manifest.get(Constants.BUNDLE_VERSION); + for (int i = 0; i < currentInstalledBundles.length; i++) { + String location = FileUtils.getRealLocation(manipulator, currentInstalledBundles[i].getLocation(), true); + if (newLocation.equals(location)) { + found = true; + break; + } + String symbolicName = currentInstalledBundles[i].getSymbolicName(); + String version = currentInstalledBundles[i].getVersion().toString(); + if (newSymbolicName.equals(symbolicName) && newVersion.equals(version)) { + found = true; + break; + } + } + } + if (!found) { + BundleDescription newBundleDescription = null; + try { + bInfo.setBundleId(++maxId); + newBundleDescription = soFactory.createBundleDescription(state, Utils.getOSGiManifest(newLocation), newLocation, bInfo.getBundleId()); + state.addBundle(newBundleDescription); + manipulator.getConfigData().addBundle(bInfo); + } catch (BundleException e) { + Log.log(LogService.LOG_WARNING, this, "installBundle(BundleInfo)", e); + } + } + } + + public boolean isFullySupported() { + return true; + } + + public boolean isResolved() { + return state.isResolved(); + } + + public boolean isResolved(BundleInfo bInfo) { + BundleDescription description = state.getBundleByLocation(bInfo.getLocation()); + if (description == null) + return false; + return description.isResolved(); + } + + public void resolve(boolean increment) { + state.resolve(increment); + } + + void setFwJar(File fwJar) { + manipulator.getLauncherData().setFwJar(fwJar); + } + + /** + * get platforme properties from the given state. + * + * @param state + */ + private void setPlatformProperties(State state) { + Dictionary platformProperties = state.getPlatformProperties()[0]; + platfromProperties.clear(); + if (platformProperties != null) { + for (Enumeration enumeration = platformProperties.keys(); enumeration.hasMoreElements();) { + String key = (String) enumeration.nextElement(); + Object value = platformProperties.get(key); + platfromProperties.setProperty(key, (String) value); + } + } + if (DEBUG) + Utils.printoutProperties(System.out, "PlatformProperties[0]", platfromProperties); + } + + /** + * set platfromProperties required to compose state object into + * platformProperties of this state. + * + * @param props + */ + private void setPlatformPropertiesToState(Dictionary props) { + Properties platformProperties = setDefaultPlatformProperties(); + + for (Enumeration enumeration = props.keys(); enumeration.hasMoreElements();) { + String key = (String) enumeration.nextElement(); + for (int i = 0; i < PROPS.length; i++) { + if (key.equals(PROPS[i])) { + platformProperties.put(key, props.get(key)); + break; + } + } + } + state.setPlatformProperties(platformProperties); + } + + private void setStateObjectFactory() { + if (soFactory != null) + return; + PlatformAdmin platformAdmin = (PlatformAdmin) Activator.acquireService(PlatformAdmin.class.getName()); + // PlatformAdmin platformAdmin = (PlatformAdmin) + // heBundleHelper.getDefault().acquireService(PlatformAdmin.class.getName()); + soFactory = platformAdmin.getFactory(); + } + + public String toString() { + if (state == null) + return null; + StringBuffer sb = new StringBuffer(); + BundleDescription[] bundleDescriptions = state.getBundles(); + for (int i = 0; i < bundleDescriptions.length; i++) { + sb.append(bundleDescriptions[i].getBundleId() + ":"); + sb.append(bundleDescriptions[i].toString() + "("); + sb.append(bundleDescriptions[i].isResolved() + ")"); + String[] ees = bundleDescriptions[i].getExecutionEnvironments(); + for (int j = 0; j < ees.length; j++) + sb.append(ees[j] + " "); + sb.append("\n"); + } + sb.append("PlatformProperties:\n"); + Dictionary[] dics = state.getPlatformProperties(); + for (int i = 0; i < dics.length; i++) { + for (Enumeration enumeration = dics[i].keys(); enumeration.hasMoreElements();) { + String key = (String) enumeration.nextElement(); + String value = (String) dics[i].get(key); + sb.append(" (" + key + "," + value + ")\n"); + } + } + sb.append("\n"); + return sb.toString(); + } + + public void uninstallBundle(BundleInfo bInfo) throws FrameworkAdminRuntimeException { + SimpleBundlesState.checkAvailability(fwAdmin); + long id = DEFAULT_TIMESTAMP; + String targetLocation = bInfo.getLocation(); + BundleDescription[] currentInstalledBundles = state.getBundles(); + for (int i = 0; i < currentInstalledBundles.length; i++) { + String location = currentInstalledBundles[i].getLocation(); + // TODO Is handling "reference:" needed ? + // if(location.startsWith("reference:")) + // location = location.substring("reference:".length()); + if (targetLocation.equals(location)) { + id = currentInstalledBundles[i].getBundleId(); + break; + } + } + if (id != DEFAULT_TIMESTAMP) { + + try { + BundleDescription bundleDescription = soFactory.createBundleDescription(state, Utils.getOSGiManifest(bInfo.getLocation()), bInfo.getLocation(), id); + state.removeBundle(bundleDescription); + manipulator.getConfigData().removeBundle(bInfo); + } catch (BundleException e) { + Log.log(LogService.LOG_WARNING, this, "uninstallBundle(BundleInfo)", e); + // throw new ManipulatorException("Fail to + // createBundleDescription of bInfo:" + bInfo.toString(), e, + // ManipulatorException.OTHERS); + } + } + } + +} diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxConstants.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxConstants.java new file mode 100644 index 000000000..f9de5dbe1 --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxConstants.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox; + +public class EquinoxConstants { + + /** + * If BundleContext#getProperty(PROP_KEY_USE_REFERENCE) does not equal "false", + * Manipulator#save() will add "reference:" to any bundle location specified osgi.bundles in order to avoid + * caching its bundle jar. Otherwise, it will add nothing to any bundle location. + */ + public static final String PROP_KEY_USE_REFERENCE = "org.eclipse.equinox.frameworkadmin.equinox.useReference"; //$NON-NLS-1$ + + public static final String PLUGINS_DIR = "plugins"; //$NON-NLS-1$ + public final static String FW_SYMBOLIC_NAME = "org.eclipse.osgi"; //$NON-NLS-1$ + public static final String DEFAULT_CONFIGURATION = "configuration"; //$NON-NLS-1$ + public static final String CONFIG_INI = "config.ini"; //$NON-NLS-1$ + + public final static String FW_VERSION = "3.3"; //$NON-NLS-1$ + public final static String FW_NAME = "Equinox"; //$NON-NLS-1$ + public final static String LAUNCHER_VERSION = "3.2"; //$NON-NLS-1$ + public final static String LAUNCHER_NAME = "Eclipse.exe"; //$NON-NLS-1$ + + public static final String OPTION_CONFIGURATION = "-configuration"; //$NON-NLS-1$ + public static final String OPTION_FW = "-framework"; //$NON-NLS-1$ + public static final String OPTION_VM = "-vm"; //$NON-NLS-1$ + public static final String OPTION_VMARGS = "-vmargs"; //$NON-NLS-1$ + public static final String OPTION_CLEAN = "-clean"; //$NON-NLS-1$ + public static final String OPTION_STARTUP = "-startup"; //$NON-NLS-1$ + public static final String OPTION_SHOWSPLASH = "-showsplash"; //$NON-NLS-1$ + + // System properties + public static final String PROP_BUNDLES = "osgi.bundles"; //$NON-NLS-1$ + public static final String PROP_BUNDLES_STARTLEVEL = "osgi.bundles.defaultStartLevel"; //$NON-NLS-1$ //The start level used to install the bundles + public static final String PROP_INITIAL_STARTLEVEL = "osgi.startLevel"; //$NON-NLS-1$ //The start level when the fwl start + public static final String PROP_INSTALL = "osgi.install"; //$NON-NLS-1$ + public static final String PROP_ECLIPSE_COMMANDS = "eclipse.commands"; //$NON-NLS-1$ + public static final String PROP_OSGI_FW = "osgi.framework"; //$NON-NLS-1$ + public static final String PROP_LAUNCHER_PATH = "osgi.launcherPath"; //$NON-NLS-1$ + public static final String PROP_LAUNCHER_NAME = "osgi.launcherIni"; //$NON-NLS-1$ + + public static final String INI_EXTENSION = ".ini"; //$NON-NLS-1$ + public static final String EXE_EXTENSION = ".exe"; //$NON-NLS-1$ + + public static final String PROP_EQUINOX_DEPENDENT_PREFIX = "osgi."; //$NON-NLS-1$ + static final String REFERENCE = "reference:"; //$NON-NLS-1$ + public static final String PERSISTENT_DIR_NAME = "org.eclipse.osgi"; //$NON-NLS-1$ + +} diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxFrameworkAdminFactoryImpl.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxFrameworkAdminFactoryImpl.java new file mode 100644 index 000000000..82a230664 --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxFrameworkAdminFactoryImpl.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox; + +import org.eclipse.equinox.internal.provisional.configuratormanipulator.ConfiguratorManipulatorFactory; +import org.eclipse.equinox.internal.provisional.frameworkadmin.FrameworkAdmin; +import org.eclipse.equinox.internal.provisional.frameworkadmin.FrameworkAdminFactory; + +public class EquinoxFrameworkAdminFactoryImpl extends FrameworkAdminFactory { + public FrameworkAdmin createFrameworkAdmin() throws InstantiationException, IllegalAccessException, ClassNotFoundException { + String className = System.getProperty(ConfiguratorManipulatorFactory.SYSTEM_PROPERTY_KEY); + if (className == null) + return new EquinoxFwAdminImpl(); + return new EquinoxFwAdminImpl(className); + } +} diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxFwAdminImpl.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxFwAdminImpl.java new file mode 100644 index 000000000..18a741e71 --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxFwAdminImpl.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox; + +import java.io.File; +import java.io.IOException; +import java.util.Dictionary; +import org.eclipse.equinox.internal.frameworkadmin.equinox.utils.EclipseVersion; +import org.eclipse.equinox.internal.provisional.configuratormanipulator.ConfiguratorManipulator; +import org.eclipse.equinox.internal.provisional.configuratormanipulator.ConfiguratorManipulatorFactory; +import org.eclipse.equinox.internal.provisional.frameworkadmin.*; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; + +public class EquinoxFwAdminImpl implements FrameworkAdmin { + + /** + * If both the vendor and the Bundle-Version in the manifest match, + * return true. Otherwise false. + * + * @return flag true if the ManipulatorAdmin object can handle currently running fw launch. + */ + static boolean isRunningFw(BundleContext context) { + //TODO implementation for Eclipse.exe and for Equinox + String fwVendor = context.getProperty(Constants.FRAMEWORK_VENDOR); + if (!"Eclipse".equals(fwVendor)) + return false; + //TODO decide if this version can be supported by this bundle. + Dictionary header = context.getBundle(0).getHeaders(); + String versionSt = (String) header.get("Bundle-Version"); + EclipseVersion version = new EclipseVersion(versionSt); + int value = version.compareTo(new EclipseVersion(EquinoxConstants.FW_VERSION)); + if (value > 0) { + return true; + } + // TODO need to identify the version of eclipse.exe used for this launch, if used. + + // String eclipseCommandsSt = context.getProperty(EquinoxConstants.PROP_ECLIPSE_COMMANDS); + // StringTokenizer tokenizer = new StringTokenizer(eclipseCommandsSt,"\n"); + return false; + } + + BundleContext context = null; + + boolean active = false; + + private boolean runningFw = false; + private ConfiguratorManipulator configuratorManipulator = null; + + // private String configuratorManipulatorFactoryName = null; + + EquinoxFwAdminImpl() { + this(null, false); + } + + EquinoxFwAdminImpl(BundleContext context) { + this(context, false); + } + + EquinoxFwAdminImpl(String configuratorManipulatorFactoryName) throws InstantiationException, IllegalAccessException, ClassNotFoundException { + this.context = null; + this.active = true; + this.runningFw = false; + // this.configuratorManipulatorFactoryName = configuratorManipulatorFactoryName; + loadConfiguratorManipulator(configuratorManipulatorFactoryName); + } + + private void loadConfiguratorManipulator(String configuratorManipulatorFactoryName) throws InstantiationException, IllegalAccessException, ClassNotFoundException { + if (configuratorManipulatorFactoryName == null) + this.configuratorManipulator = null; + else + this.configuratorManipulator = ConfiguratorManipulatorFactory.getInstance(configuratorManipulatorFactoryName); + return; + } + + EquinoxFwAdminImpl(BundleContext context, boolean runningFw) { + this.context = context; + this.active = true; + this.runningFw = runningFw; + } + + void deactivate() { + active = false; + } + + public Manipulator getManipulator() { + return new EquinoxManipulatorImpl(context, this); + } + + public Manipulator getRunningManipulator() { + if (this.runningFw) + return new EquinoxManipulatorImpl(context, this, true); + return null; + } + + public boolean isActive() { + return active; + } + + public Process launch(Manipulator manipulator, File cwd) throws IllegalArgumentException, FrameworkAdminRuntimeException, IOException { + //return new EclipseLauncherImpl(context, this).launch(manipulator, cwd); + return new EclipseLauncherImpl(this).launch(manipulator, cwd); + } + + public ConfiguratorManipulator getConfiguratorManipulator() { + return configuratorManipulator; + } + +} diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxFwConfigFileParser.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxFwConfigFileParser.java new file mode 100644 index 000000000..70695adcf --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxFwConfigFileParser.java @@ -0,0 +1,439 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox; + +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.Properties; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.equinox.internal.frameworkadmin.equinox.utils.FileUtils; +import org.eclipse.equinox.internal.frameworkadmin.utils.Utils; +import org.eclipse.equinox.internal.provisional.frameworkadmin.*; +import org.osgi.framework.BundleContext; +import org.osgi.service.log.LogService; + +public class EquinoxFwConfigFileParser { + private static final String KEY_ECLIPSE_PROV_CACHE = "eclipse.p2.cache"; //$NON-NLS-1$ + private static final String KEY_ECLIPSE_PROV_DATA_AREA = "eclipse.p2.data.area"; //$NON-NLS-1$ + private static final String KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL = "org.eclipse.equinox.simpleconfigurator.configUrl"; //$NON-NLS-1$ + private static final String KEY_OSGI_BUNDLES = "osgi.bundles"; //$NON-NLS-1$ + private static final String KEY_OSGI_FRAMEWORK = "osgi.framework"; //$NON-NLS-1$ + private static final String KEY_OSGI_LAUNCHER_PATH = "osgi.launcherPath"; //$NON-NLS-1$ + private static final String[] PATHS = new String[] {KEY_OSGI_LAUNCHER_PATH, KEY_ECLIPSE_PROV_CACHE}; + private static final String[] URLS = new String[] {KEY_ECLIPSE_PROV_DATA_AREA}; + + private static boolean DEBUG = false; + private static String USE_REFERENCE_STRING = null; + + public EquinoxFwConfigFileParser(BundleContext context) { + if (context != null) + USE_REFERENCE_STRING = context.getProperty(EquinoxConstants.PROP_KEY_USE_REFERENCE); + + } + + private static String getCommandLine(BundleInfo bundleInfo, final URL baseUrl) { + String location = bundleInfo.getLocation(); + if (location == null) + return null; + boolean useReference = true; + if (location.startsWith("file:")) { + if (USE_REFERENCE_STRING != null && USE_REFERENCE_STRING.equals("false")) + useReference = false; + } + + try { + new URL(location); + } catch (MalformedURLException e) { + Log.log(LogService.LOG_ERROR, "EquinoxFwConfigFileParser.getCommandLine():bundleInfo=" + bundleInfo, e); + // Never happen. ignore. + } + if (useReference) + if (!location.startsWith("reference:")) + location = "reference:" + location; + + int startLevel = bundleInfo.getStartLevel(); + boolean toBeStarted = bundleInfo.isMarkedAsStarted(); + + StringBuffer sb = new StringBuffer(); + // if (baseUrl != null && bundleUrl.getProtocol().equals("file")) { + // String bundlePath = bundleUrl.toString(); + // bundlePath = Utils.getRelativePath(bundleUrl, baseUrl); + // sb.append(bundlePath); + // } else + sb.append(location); + if (startLevel == BundleInfo.NO_LEVEL && !toBeStarted) + return sb.toString(); + sb.append("@"); + if (startLevel != BundleInfo.NO_LEVEL) + sb.append(startLevel); + if (toBeStarted) + sb.append(":start"); + return sb.toString(); + } + + private static Properties getConfigProps(BundleInfo[] bInfos, ConfigData configData, LauncherData launcherData, boolean relative, File fwJar) { + Properties props = new Properties(); + + if (configData.getInitialBundleStartLevel() != BundleInfo.NO_LEVEL) + props.setProperty(EquinoxConstants.PROP_BUNDLES_STARTLEVEL, Integer.toString(configData.getInitialBundleStartLevel())); + if (configData.getBeginingFwStartLevel() != BundleInfo.NO_LEVEL) + props.setProperty(EquinoxConstants.PROP_INITIAL_STARTLEVEL, Integer.toString(configData.getBeginingFwStartLevel())); + + final File launcher = launcherData.getLauncher(); + if (launcher != null) { + String launcherName = launcher.getName(); + if (launcherName.endsWith(EquinoxConstants.EXE_EXTENSION)) { + props.setProperty(EquinoxConstants.PROP_LAUNCHER_NAME, launcherName.substring(0, launcherName.lastIndexOf(EquinoxConstants.EXE_EXTENSION))); + props.setProperty(EquinoxConstants.PROP_LAUNCHER_PATH, launcher.getParentFile().getAbsolutePath()); + } + } + + if (bInfos != null) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < bInfos.length; i++) { + normalizeLocation(bInfos[i]); + sb.append(getCommandLine(bInfos[i], null)); + if (i + 1 < bInfos.length) + sb.append(","); + } + props.setProperty(EquinoxConstants.PROP_BUNDLES, sb.toString()); + + } + //TODO The following merging operations are suspicious. + props = Utils.appendProperties(props, configData.getFwIndependentProps()); + + props = Utils.appendProperties(props, configData.getFwDependentProps()); + + //Deal with the fw jar and ensure it is not set. + //TODO This can't be done before because of the previous calls to appendProperties + String fwJarSt = null; + try { + if (fwJar != null) { + fwJarSt = fwJar.toURL().toExternalForm(); + } + } catch (MalformedURLException e) { + // Never happens + e.printStackTrace(); + } + if (fwJarSt != null) + props.setProperty(EquinoxConstants.PROP_OSGI_FW, fwJarSt /* fwJar.getAbsolutePath() */); + else + props.remove(EquinoxConstants.PROP_OSGI_FW); + + return props; + } + + private static boolean getMarkedAsStartedFormat(String msg, String original) { + if (msg == null) + return false; + msg = msg.trim(); + if (msg.equals("start")) { + return true; + } + if (!msg.equals("")) + new IllegalArgumentException("Invalid Format =" + original); + return false; + } + + static boolean isFwDependent(String key) { + // TODO This algorithm is temporal. + if (key.startsWith(EquinoxConstants.PROP_EQUINOX_DEPENDENT_PREFIX)) + return true; + return false; + } + + private static void normalizeLocation(BundleInfo bInfo) { + String location = bInfo.getLocation(); + try { + if (location.startsWith("file:")) { + bInfo.setLocation(new URL(location).toExternalForm()); + } else { + bInfo.setLocation(new File(location).toURL().toExternalForm()); + } + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + // location = location.substring("file:".length()); + // if (!location.startsWith("/")) + // location = "/" + location; + // // if (fwJarSt != null) + // // if (fwJarSt.equals(location)) + // // continue; + // location = Utils.replaceAll(location, File.separator, "/"); + // //String jarName = location.substring(location.lastIndexOf("/") + 1); + // // if (jarName.startsWith(EquinoxConstants.FW_JAR_PLUGIN_NAME)) + // // continue; + // bInfo.setLocation("file:" + location); + // } + } + + /** + * @param value + */ + private static void setInstallingBundles(Manipulator manipulator, String value) throws NumberFormatException { + ConfigData configData = manipulator.getConfigData(); + if (value != null) { + String[] bInfoStrings = Utils.getTokens(value, ","); + for (int i = 0; i < bInfoStrings.length; i++) { + String token = bInfoStrings[i].trim(); + token = FileUtils.getRealLocation(manipulator, token, false); + int index = 0; + while (true) { + if (token.charAt(index) == ' ') + index++; + else + break; + } + if (index != 0) + token = token.substring(index); + + int indexI = token.indexOf("@"); + if (indexI == -1) { + String location = FileUtils.getEclipseRealLocation(manipulator, token); + configData.addBundle(new BundleInfo(location)); + // configData.installingBundlesList.add(new BundleInfo(this.convertUrl(bInfoStrings[i]))); + continue; + } + String location = token.substring(0, indexI); + location = FileUtils.getEclipseRealLocation(manipulator, location); + // URL url = this.convertUrl(bInfoStrings[i].substring(0, indexI)); + String slAndFlag = token.substring(indexI + "@".length()); + boolean markedAsStarted = false; + int startLevel = -1; + int indexJ = slAndFlag.indexOf(":"); + if (indexJ == -1) { + markedAsStarted = getMarkedAsStartedFormat(slAndFlag, token); + configData.addBundle(new BundleInfo(location, markedAsStarted)); + continue; + } else if (indexJ == 0) { + markedAsStarted = getMarkedAsStartedFormat(slAndFlag.substring(indexJ + ":".length()), token); + configData.addBundle(new BundleInfo(location, startLevel, markedAsStarted)); + continue; + } + startLevel = Integer.parseInt(slAndFlag.substring(0, indexJ)); + markedAsStarted = getMarkedAsStartedFormat(slAndFlag.substring(indexJ + ":".length()), bInfoStrings[i]); + configData.addBundle(new BundleInfo(location, startLevel, markedAsStarted)); + } + } + } + + /** + * inputFile must be not a directory but a file. + * + * @param manipulator + * @param inputFile + * @throws IOException + */ + public void readFwConfig(Manipulator manipulator, File inputFile) throws IOException { + if (inputFile.isDirectory()) + throw new IllegalArgumentException("inputFile:" + inputFile + " must not be a directory."); + + //Initialize data structures + ConfigData configData = manipulator.getConfigData(); + LauncherData launcherData = manipulator.getLauncherData(); + configData.initialize(); + + //Load properties + Properties props = new Properties(); + InputStream is = null; + try { + is = new FileInputStream(inputFile); + props.load(is); + } finally { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + is = null; + } + + //Start figuring out stuffs + URL rootURL = launcherData.getLauncher() != null ? launcherData.getLauncher().getParentFile().toURL() : null; + + //Extracting fwkJar location needs to be done first + String launcherName = null; + String launcherPath = null; + configData.setBundles(null); + + File fwJar = null; + if (props.getProperty(EquinoxConstants.PROP_OSGI_FW) != null) { + props.setProperty(KEY_OSGI_FRAMEWORK, EquinoxManipulatorImpl.makeAbsolute(props.getProperty(EquinoxConstants.PROP_OSGI_FW), getOSGiInstallArea(launcherData).toURL())); + String fwJarString = props.getProperty(KEY_OSGI_FRAMEWORK); + if (fwJarString != null) { + fwJar = new File(new URL(fwJarString).getFile()); + launcherData.setFwJar(fwJar); + configData.addBundle(new BundleInfo(fwJarString)); + } + } + + props = makeAbsolute(props, rootURL, fwJar, inputFile.getParentFile(), getOSGiInstallArea(manipulator.getLauncherData())); + for (Enumeration enumeration = props.keys(); enumeration.hasMoreElements();) { + String key = (String) enumeration.nextElement(); + String value = props.getProperty(key); + if (key.equals(EquinoxConstants.PROP_BUNDLES_STARTLEVEL)) + configData.setInitialBundleStartLevel(Integer.parseInt(value)); + else if (key.equals(EquinoxConstants.PROP_INITIAL_STARTLEVEL)) { + configData.setBeginningFwStartLevel(Integer.parseInt(value)); + } else if (key.equals(EquinoxConstants.PROP_BUNDLES)) { + setInstallingBundles(manipulator, value); + } else { + if (isFwDependent(key)) { + configData.setFwDependentProp(key, value); + } else + configData.setFwIndependentProp(key, value); + if (key.equals(EquinoxConstants.PROP_LAUNCHER_NAME)) + if (launcherData.getLauncher() == null) + launcherName = value; + if (key.equals(EquinoxConstants.PROP_LAUNCHER_PATH)) + if (launcherData.getLauncher() == null) + launcherPath = value; + } + } + if (launcherName != null && launcherPath != null) { + launcherData.setLauncher(new File(launcherPath, launcherName + EquinoxConstants.EXE_EXTENSION)); + } + + Log.log(LogService.LOG_INFO, "Config file(" + inputFile.getAbsolutePath() + ") is read successfully."); + } + + private static Properties makeRelative(Properties props, URL rootURL, File fwJar, File configArea, File osgiInstallArea) throws IOException { + for (int i = 0; i < PATHS.length; i++) { + String path = props.getProperty(PATHS[i]); + if (path != null) + props.put(PATHS[i], EquinoxManipulatorImpl.makeRelative(path, rootURL.getFile())); + } + + if (props.getProperty(KEY_OSGI_FRAMEWORK) != null && osgiInstallArea != null) { + props.put(KEY_OSGI_FRAMEWORK, EquinoxManipulatorImpl.makeRelative(props.getProperty(KEY_OSGI_FRAMEWORK), osgiInstallArea.toURL())); + } + + if (props.getProperty(KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL) != null) { + props.put(KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL, EquinoxManipulatorImpl.makeRelative(props.getProperty(KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL), configArea.toURL())); + } + + for (int i = 0; i < URLS.length; i++) { + String url = props.getProperty(URLS[i]); + if (url != null) + props.put(URLS[i], EquinoxManipulatorImpl.makeRelative(url, rootURL)); + } + + String value = props.getProperty(KEY_OSGI_BUNDLES); + if (value != null && fwJar != null) { + File parent = fwJar.getParentFile(); + if (parent != null) + props.setProperty(KEY_OSGI_BUNDLES, EquinoxManipulatorImpl.makeArrayRelative(value, parent.toURL())); + } + return props; + } + + private static Properties makeAbsolute(Properties props, URL rootURL, File fwJar, File configArea, File osgiInstallArea) throws IOException { + for (int i = 0; i < PATHS.length; i++) { + String path = props.getProperty(PATHS[i]); + if (path != null) + props.setProperty(PATHS[i], EquinoxManipulatorImpl.makeAbsolute(path, rootURL.getFile())); + } + + if (props.getProperty(KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL) != null) { + props.put(KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL, EquinoxManipulatorImpl.makeAbsolute(props.getProperty(KEY_ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_CONFIGURL), configArea.toURL())); + } + + for (int i = 0; i < URLS.length; i++) { + String url = props.getProperty(URLS[i]); + if (url != null) + props.put(URLS[i], EquinoxManipulatorImpl.makeAbsolute(url, rootURL)); + } + + String value = props.getProperty(KEY_OSGI_BUNDLES); + if (value != null && fwJar != null) { + File parent = fwJar.getParentFile(); + if (parent != null) + props.setProperty(KEY_OSGI_BUNDLES, EquinoxManipulatorImpl.makeArrayAbsolute(value, parent.toURL())); + } + return props; + } + + public static File getOSGiInstallArea(LauncherData launcherData) { + if (launcherData == null) + return null; + String[] args = launcherData.getProgramArgs(); + if (args == null) + return null; + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-startup") && i + 1 < args.length && args[i + 1].charAt(1) != '-') { + IPath parentFolder = new Path(args[i + 1]).removeLastSegments(1); + if (parentFolder.lastSegment().equals("plugins")) + return parentFolder.removeLastSegments(1).toFile(); + return parentFolder.toFile(); + } + } + return launcherData.getLauncher().getParentFile(); + } + + public void saveFwConfig(BundleInfo[] bInfos, Manipulator manipulator, boolean backup, boolean relative) throws IOException {//{ + ConfigData configData = manipulator.getConfigData(); + LauncherData launcherData = manipulator.getLauncherData(); + File fwJar = EquinoxBundlesState.getFwJar(launcherData, configData); + launcherData.setFwJar(fwJar); + File outputFile = launcherData.getFwConfigLocation(); + if (outputFile.exists()) { + if (outputFile.isFile()) { + if (!outputFile.getName().equals(EquinoxConstants.CONFIG_INI)) + throw new IllegalStateException("launcherData.getFwConfigLocation() is a File but its name doesn't equal " + EquinoxConstants.CONFIG_INI); + } else { // Directory + outputFile = new File(outputFile, EquinoxConstants.CONFIG_INI); + } + } else { + if (!outputFile.getName().equals(EquinoxConstants.CONFIG_INI)) { + if (!outputFile.mkdir()) + throw new IOException("Fail to mkdir (" + outputFile + ")"); + outputFile = new File(outputFile, EquinoxConstants.CONFIG_INI); + } + } + String header = "This properties were written by " + this.getClass().getName(); + + Properties configProps = getConfigProps(bInfos, configData, launcherData, relative, fwJar); + if (configProps == null || configProps.size() == 0) { + Log.log(LogService.LOG_WARNING, this, "saveFwConfig() ", "configProps is empty"); + return; + } + Utils.createParentDir(outputFile); + + if (DEBUG) + Utils.printoutProperties(System.out, "configProps", configProps); + + if (backup) + if (outputFile.exists()) { + File dest = Utils.getSimpleDataFormattedFile(outputFile); + if (!outputFile.renameTo(dest)) + throw new IOException("Fail to rename from (" + outputFile + ") to (" + dest + ")"); + Log.log(LogService.LOG_INFO, this, "saveFwConfig()", "Succeed to rename from (" + outputFile + ") to (" + dest + ")"); + } + + FileOutputStream out = null; + try { + out = new FileOutputStream(outputFile); + configProps = makeRelative(configProps, launcherData.getLauncher().getParentFile().toURL(), fwJar, outputFile.getParentFile(), getOSGiInstallArea(manipulator.getLauncherData())); + configProps.store(out, header); + Log.log(LogService.LOG_INFO, "FwConfig is saved successfully into:" + outputFile); + } finally { + try { + out.flush(); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + out = null; + } + } +} diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxManipulatorImpl.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxManipulatorImpl.java new file mode 100644 index 000000000..22852d0bc --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/EquinoxManipulatorImpl.java @@ -0,0 +1,685 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.*; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.frameworkadmin.equinox.utils.FileUtils; +import org.eclipse.equinox.internal.frameworkadmin.utils.SimpleBundlesState; +import org.eclipse.equinox.internal.frameworkadmin.utils.Utils; +import org.eclipse.equinox.internal.provisional.configuratormanipulator.ConfiguratorManipulator; +import org.eclipse.equinox.internal.provisional.frameworkadmin.*; +import org.eclipse.osgi.service.datalocation.Location; +import org.osgi.framework.*; +import org.osgi.service.log.LogService; +import org.osgi.service.startlevel.StartLevel; +import org.osgi.util.tracker.ServiceTracker; + +public class EquinoxManipulatorImpl implements Manipulator { + private static final long DEFAULT_LASTMODIFIED = 0L; + private static final boolean LOG_ILLEGALSTATEEXCEPTION = false; + private static final String COMMA = ","; //$NON-NLS-1$ + private static final String FILE_PROTOCOL = "file:"; //$NON-NLS-1$ + + /** + * If the fwConfigLocation is a file and its name does not equal "config.ini", + * throw an IllegaStateException. + * If the fwConfigLocation is a file and its name equals "config.ini", + * fwConfigLocation will be updated by its parent directory. + * + * Then, reset fwConfigLocation and fwPersistentDataLocation to be matched. + * + * @param launcherData + */ + static void checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(LauncherData launcherData) { + File fwConfigLocation = launcherData.getFwConfigLocation(); + File fwPersistentDataLocation = launcherData.getFwPersistentDataLocation(); + + if (fwConfigLocation != null) { + if (fwConfigLocation.isFile()) { + if (fwConfigLocation.getName().equals(EquinoxConstants.CONFIG_INI)) + fwConfigLocation = fwConfigLocation.getParentFile(); + else + throw new IllegalStateException("fwConfigLocation is not a directory but its name does NOT equal \"" + EquinoxConstants.CONFIG_INI + "\"!\n" + "\tfwConfigLocation=" + fwConfigLocation.getAbsolutePath() + "\n\t,fwPersistentDataLocation=" + fwPersistentDataLocation.getAbsolutePath()); + launcherData.setFwConfigLocation(fwConfigLocation); + } + if (fwPersistentDataLocation != null) { + // Log.log(LogService.LOG_DEBUG, "fwConfigLocation=" + fwConfigLocation.getAbsolutePath() + ",\n\tfwInstancePrivateArea=" + fwPersistentDataLocation.getAbsolutePath()); + //if (!fwConfigLocation.getParentFile().equals(fwPersistentDataLocation)) + //throw new IllegalStateException("!configFile.getParentFile().equals(fwInstancePrivateArea)\n" + "\tconfigFile=" + fwConfigLocation.getAbsolutePath() + "\n\t,fwInstancePrivateArea=" + fwPersistentDataLocation.getAbsolutePath()); + if (!fwConfigLocation.equals(fwPersistentDataLocation)) + throw new IllegalStateException("!fwConfigLocation.equals(fwPersistentDataLocation)\n" + "\t!fwConfigLocation=" + fwConfigLocation.getAbsolutePath() + "\n\t,fwPersistentDataLocation=" + fwPersistentDataLocation.getAbsolutePath()); + } else + launcherData.setFwPersistentDataLocation(fwConfigLocation, launcherData.isClean()); + //launcherData.setFwPersistentDataLocation(fwConfigLocation.getParentFile(), launcherData.isClean()); + } else { + if (fwPersistentDataLocation != null) { + launcherData.setFwConfigLocation(fwPersistentDataLocation); + //launcherData.setFwConfigLocation(new File(fwPersistentDataLocation, EquinoxConstants.CONFIG_INI)); + } else { + File home = launcherData.getHome(); + if (home == null) + throw new IllegalStateException("All of fwConfigLocation, fwPersistentDataLocation, and home are not set"); + fwConfigLocation = new File(home, "configuration"); + launcherData.setFwPersistentDataLocation(fwConfigLocation, launcherData.isClean()); + launcherData.setFwConfigLocation(fwConfigLocation); + } + } + } + + static File getLauncherConfigLocation(LauncherData launcherData) { + File launcherConfigLocation = launcherData.getLauncherConfigLocation(); + if (launcherConfigLocation != null) + return launcherConfigLocation; + + File launcher = launcherData.getLauncher(); + if (launcher == null) + return null; + String launcherName = launcher.getName(); + int dotLocation = launcherName.lastIndexOf("."); + if (dotLocation != -1) + launcherName = launcherName.substring(0, dotLocation); + File result = new File(launcher.getParent() + File.separator + launcherName + EquinoxConstants.INI_EXTENSION); + // launcherData.setLauncherConfigLocation(result); + return result; + } + + ConfigData configData = new ConfigData(EquinoxConstants.FW_NAME, EquinoxConstants.FW_VERSION, EquinoxConstants.LAUNCHER_NAME, EquinoxConstants.LAUNCHER_VERSION); + LauncherData launcherData = new LauncherData(EquinoxConstants.FW_NAME, EquinoxConstants.FW_VERSION, EquinoxConstants.LAUNCHER_NAME, EquinoxConstants.LAUNCHER_VERSION); + + BundleContext context = null; + private Properties platformProperties = new Properties(); + + ServiceTracker cmTracker; + int trackingCount = -1; + + // private final boolean runtime; + + ConfiguratorManipulator configuratorManipulator; + + EquinoxFwAdminImpl fwAdmin = null; + + EquinoxManipulatorImpl(BundleContext context, EquinoxFwAdminImpl fwAdmin) { + this(context, fwAdmin, false); + } + + EquinoxManipulatorImpl(BundleContext context, EquinoxFwAdminImpl fwAdmin, boolean runtime) { + this.context = context; + this.fwAdmin = fwAdmin; + if (context != null) { + cmTracker = new ServiceTracker(context, ConfiguratorManipulator.class.getName(), null); + cmTracker.open(); + } + // this.runtime = runtime; + if (runtime) + initializeRuntime(); + // XXX For Equinox, default value of Initial Bundle Start Level is 4. + // Precisely speaking, it's not correct. + // Equinox doesn't support setting initial bundle start level as an OSGi terminology. + // Only bundles installed by config.ini and updateconfigurator will have that start level(4). + // Others has a start level of 1. + configData.setInitialBundleStartLevel(4); + } + + public BundlesState getBundlesState() throws FrameworkAdminRuntimeException { + if (context == null) + return new SimpleBundlesState(fwAdmin, this, EquinoxConstants.FW_SYMBOLIC_NAME); + + if (!EquinoxBundlesState.checkFullySupported()) + return new SimpleBundlesState(fwAdmin, this, EquinoxConstants.FW_SYMBOLIC_NAME); + + if (platformProperties.isEmpty()) + return new EquinoxBundlesState(context, fwAdmin, this, false); + // XXX checking if fwDependent or fwIndependent platformProperties are updated after the platformProperties was created might be required for better implementation. + return new EquinoxBundlesState(context, fwAdmin, this, platformProperties); + } + + public ConfigData getConfigData() throws FrameworkAdminRuntimeException { + return configData; + } + + public BundleInfo[] getExpectedState() throws IllegalArgumentException, FrameworkAdminRuntimeException { + //Log.log(LogService.LOG_DEBUG, this, "getExpectedState()", "BEGIN"); + SimpleBundlesState.checkAvailability(fwAdmin); + + BundlesState bundleState = this.getBundlesState(); + if (bundleState instanceof SimpleBundlesState) + return new BundleInfo[0]; + bundleState.resolve(true); + + return bundleState.getExpectedState(); + } + + public LauncherData getLauncherData() throws FrameworkAdminRuntimeException { + return launcherData; + } + + /** + * Return the configuration location. + * + * @see Location + */ + private File getRunningConfigurationLocation() { + ServiceTracker tracker = null; + Filter filter = null; + try { + filter = context.createFilter(Location.CONFIGURATION_FILTER); + } catch (InvalidSyntaxException e) { + // ignore this. It should never happen as we have tested the above format. + } + tracker = new ServiceTracker(context, filter, null); + tracker.open(); + Location location = (Location) tracker.getService(); + URL url = location.getURL(); + if (!url.getProtocol().equals("file")) + return null; + return new File(url.getFile()); + } + + private File getRunningLauncherFile() { + File launcherFile = null; + String eclipseCommandsSt = context.getProperty(EquinoxConstants.PROP_ECLIPSE_COMMANDS); + if (eclipseCommandsSt == null) + return null; + + StringTokenizer tokenizer = new StringTokenizer(eclipseCommandsSt, "\n"); + boolean found = false; + String launcherSt = null; + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (found) { + launcherSt = token; + break; + } + if (token.equals("-launcher")) + found = true; + } + if (launcherSt != null) + launcherFile = new File(launcherSt); + return launcherFile; + } + + private Properties getRunningPlatformProperties() { + Properties props = new Properties(); + for (int i = 0; i < EquinoxBundlesState.PROPS.length; i++) { + String value = context.getProperty(EquinoxBundlesState.PROPS[i]); + if (value != null) + props.setProperty(EquinoxBundlesState.PROPS[i], value); + } + return props; + } + + public long getTimeStamp() { + long ret = this.getTimeStampWithoutFwPersistentData(); + if (this.launcherData.isClean()) + return ret; + long lastModifiedFwPersistent = EquinoxBundlesState.getTimeStamp(launcherData.getFwPersistentDataLocation()); + return Math.max(ret, lastModifiedFwPersistent); + } + + private long getTimeStampWithoutFwPersistentData() { + SimpleBundlesState.checkAvailability(fwAdmin); + File launcherConfigFile = getLauncherConfigLocation(launcherData); + long lastModifiedLauncherConfigFile = DEFAULT_LASTMODIFIED; + long lastModifiedFwConfigFile = DEFAULT_LASTMODIFIED; + if (launcherConfigFile != null) { + // use launcher. -- > load from LaucnherConfig file. + lastModifiedLauncherConfigFile = launcherConfigFile.lastModified(); + } + checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(launcherData); + + if (launcherData.getFwConfigLocation() != null) { + File fwConfigFile = new File(launcherData.getFwConfigLocation(), EquinoxConstants.CONFIG_INI); + lastModifiedFwConfigFile = fwConfigFile.lastModified(); + } + long ret = Math.max(lastModifiedLauncherConfigFile, lastModifiedFwConfigFile); + return ret; + } + + // // + // public void load() throws IllegalStateException, IOException, FrameworkAdminRuntimeException { + // this.load(true); + // } + + public void initialize() { + Log.log(LogService.LOG_DEBUG, this, "initialize()", "BEGIN"); + configData.initialize(); + launcherData.initialize(); + } + + private void initializeRuntime() { + //TODO refine the implementation. using some MAGIC dependent on Eclipse.exe and Equinox implementation, + // set parameters according to the current running fw. + + // 1. retrieve location data from Location services registered by equinox fw. + String fwJarLocation = context.getProperty(EquinoxConstants.PROP_OSGI_FW); + if (!fwJarLocation.startsWith("file:")) + throw new IllegalStateException("Current implementation assume that property value keyed by " + EquinoxConstants.PROP_OSGI_FW + " must start with \"file:\". But it was not:" + fwJarLocation); + File fwJar = new File(fwJarLocation.substring("file:".length())); + //System.out.println("fwJar=" + fwJar); + File fwConfigLocation = getRunningConfigurationLocation(); + File launcherFile = getRunningLauncherFile(); + launcherData.setFwJar(fwJar); + launcherData.setFwPersistentDataLocation(fwConfigLocation, false); + launcherData.setLauncher(launcherFile); + try { + this.loadWithoutFwPersistentData(); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + // 2. Create a Manipulator object fully initialized to the current running fw. + + ServiceReference reference = context.getServiceReference(StartLevel.class.getName()); + StartLevel startLevel = (StartLevel) context.getService(reference); + Bundle[] bundles = context.getBundles(); + BundleInfo[] bInfos = new BundleInfo[bundles.length]; + for (int i = 0; i < bundles.length; i++) { + // System.out.println("bundles[" + i + "]=" + bundles[i]); + try { + if (bundles[i].getBundleId() == 0) // SystemBundle + bInfos[i] = new BundleInfo(bundles[i].getSymbolicName(), (String) bundles[i].getHeaders().get(Constants.BUNDLE_VERSION), FileLocator.getBundleFile(bundles[i]).getAbsolutePath(), -1, true); + else { + bInfos[i] = new BundleInfo(bundles[i].getSymbolicName(), (String) bundles[i].getHeaders().get(Constants.BUNDLE_VERSION), FileLocator.getBundleFile(bundles[i]).getAbsolutePath(), startLevel.getBundleStartLevel(bundles[i]), startLevel.isBundlePersistentlyStarted(bundles[i])); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + configData.setBundles(bInfos); + platformProperties = this.getRunningPlatformProperties(); + + // copy system properties to ConfigData + Properties props = System.getProperties(); + for (Enumeration enumeration = props.keys(); enumeration.hasMoreElements();) { + String key = (String) enumeration.nextElement(); + String value = props.getProperty(key); + if (toBeEliminated(key)) + continue; + if (EquinoxFwConfigFileParser.isFwDependent(key)) + configData.setFwDependentProp(key, value); + else + configData.setFwIndependentProp(key, value); + } + + // update initialBundleStartLevel + StartLevel slAdmin = (StartLevel) Activator.acquireService(StartLevel.class.getName()); + int initialBSL = configData.getInitialBundleStartLevel(); + if (initialBSL != slAdmin.getInitialBundleStartLevel()) + configData.setInitialBundleStartLevel(slAdmin.getInitialBundleStartLevel()); + + // for (int j = 0; j < bInfos.length; j++) + // configData.addBundle(bInfos[j]); + } + + /* (non-Javadoc) + * @see org.eclipse.equinox.internal.provisional.frameworkadmin.Manipulator#load() + */ + public void load() throws IllegalStateException, IOException, FrameworkAdminRuntimeException { + Log.log(LogService.LOG_DEBUG, this, "load()", "BEGIN"); + loadWithoutFwPersistentData(); + + BundlesState bundlesState = null; + if (EquinoxBundlesState.checkFullySupported()) { + // bundlesState = new EquinoxBundlesState(context, fwAdmin, this, true, runtime); + bundlesState = new EquinoxBundlesState(context, fwAdmin, this, !launcherData.isClean()); + platformProperties = ((EquinoxBundlesState) bundlesState).getPlatformProperties(); + + } else { + bundlesState = new SimpleBundlesState(fwAdmin, this, EquinoxConstants.FW_SYMBOLIC_NAME); + platformProperties.clear(); + } + updateAccordingToExpectedState(bundlesState); + // if (!useConfigurator) + // return; + setConfiguratorManipulator(); + if (this.configuratorManipulator == null) + return; + configuratorManipulator.updateBundles(this); + return; + } + + private void loadWithoutFwPersistentData() throws IOException { + SimpleBundlesState.checkAvailability(fwAdmin); + File launcherConfigFile = getLauncherConfigLocation(launcherData); + if (launcherConfigFile != null) { + // use launcher. -- > load from LaucnherConfig file. + // the parameters in memory will be updated. + EclipseLauncherParser parser = new EclipseLauncherParser(); + parser.read(launcherData); + } + checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(launcherData); + + File fwConfigFile = new File(launcherData.getFwConfigLocation(), EquinoxConstants.CONFIG_INI); + EquinoxFwConfigFileParser parser = new EquinoxFwConfigFileParser(context); + if (fwConfigFile.exists()) + parser.readFwConfig(this, fwConfigFile); + + } + + // Save all parameter in memory into proper config files. + public void save(boolean backup) throws IOException, FrameworkAdminRuntimeException { + Log.log(LogService.LOG_DEBUG, this, "save()", "BEGIN"); + SimpleBundlesState.checkAvailability(fwAdmin); + + try { + updateAccordingToExpectedState(this.getBundlesState()); + } catch (IllegalStateException e) { + // ignore. + } + // File fwJar = EquinoxBundlesState.getFwJar(launcherData, configData); + // if (fwJar != null) + // launcherData.setFwJar(fwJar); + + //if (context != null) + setConfiguratorManipulator(); + + BundleInfo[] newBInfos = null; + if (configuratorManipulator != null) { // Optimize BundleInfo[] + try { + newBInfos = configuratorManipulator.save(this, backup); + } catch (IllegalStateException e) { + // TODO Auto-generated catch block + if (LOG_ILLEGALSTATEEXCEPTION) + Log.log(LogService.LOG_WARNING, this, "save()", e); + newBInfos = configData.getBundles(); + } + } else { + newBInfos = configData.getBundles(); + } + + boolean stateIsEmpty = configData.getBundles().length == 0; + + File launcherConfigFile = getLauncherConfigLocation(launcherData); + if (launcherConfigFile != null) { + if (!stateIsEmpty) { + // Use launcher. -- > save LauncherConfig file. + EclipseLauncherParser launcherParser = new EclipseLauncherParser(); + launcherParser.save(launcherData, true, backup); + } else { + // No bundles in configuration, so delete the launcher config file + launcherConfigFile.delete(); + } + } + + checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(launcherData); + + // //if (context != null) + // setConfiguratorManipulator(); + // + // BundleInfo[] newBInfos = null; + // if (configuratorManipulator != null) { // Optimize BundleInfo[] + // try { + // newBInfos = configuratorManipulator.save(this, backup); + // } catch (IllegalStateException e) { + // // TODO Auto-generated catch block + // if (LOG_ILLEGALSTATEEXCEPTION) + // Log.log(LogService.LOG_WARNING, this, "save()", e); + // newBInfos = configData.getBundles(); + // } + // } else { + // newBInfos = configData.getBundles(); + // } + + if (!stateIsEmpty) { + // Save FwConfigFile + EquinoxFwConfigFileParser parser = new EquinoxFwConfigFileParser(context); + parser.saveFwConfig(newBInfos.length != 0 ? newBInfos : getConfigData().getBundles(), this, backup, false); + } else { + File configDir = launcherData.getFwConfigLocation(); + File outputFile = new File(configDir, EquinoxConstants.CONFIG_INI); + if (outputFile != null && outputFile.exists()) { + outputFile.delete(); + } + if (configDir != null && configDir.exists()) { + configDir.delete(); + } + } + } + + public void setConfigData(ConfigData configData) { + this.configData.initialize(); + this.configData.setInitialBundleStartLevel(configData.getInitialBundleStartLevel()); + this.configData.setBeginningFwStartLevel(configData.getBeginingFwStartLevel()); + BundleInfo[] bInfos = configData.getBundles(); + for (int i = 0; i < bInfos.length; i++) + this.configData.addBundle(bInfos[i]); + this.configData.setFwIndependentProps(configData.getFwIndependentProps()); + if (this.configData.getFwName().equals(configData.getFwName())) + if (this.configData.getFwVersion().equals(configData.getFwVersion())) { + // TODO refine the algorithm to copying fw dependent props. + // configData.getFwName()/getFwVersion()/ + // getLauncherName()/getLauncherVersion() might be taken into consideration. + this.configData.setFwDependentProps(configData.getFwDependentProps()); + } + } + + /** + * 1. get all ServiceReferences of ConfiguratorManipulator. + * 2. Check if there any ConfiguratorBundle in the Bundles list that can be manipulated by + * the available ConfiguratorManipulators. + * 3. Choose the one that will be firstly started among them. + * 4. set the object that corresponds to the chosen ConfiguratorBundle. + * + */ + private void setConfiguratorManipulator() { + if (context == null) { + this.configuratorManipulator = this.fwAdmin.getConfiguratorManipulator(); + return; + } + ServiceReference[] references = cmTracker.getServiceReferences(); + + int count = cmTracker.getTrackingCount(); + if (count == this.trackingCount && configuratorManipulator != null) + return; + this.trackingCount = count; + + BundleInfo[] bInfos = configData.getBundles(); + int initialBSL = configData.getInitialBundleStartLevel(); + bInfos = Utils.sortBundleInfos(bInfos, initialBSL); + //int index = -1; + configuratorManipulator = null; + if (references == null) + return; + for (int i = 0; i < bInfos.length; i++) { + String location = bInfos[i].getLocation(); + location = FileUtils.getRealLocation(this, location, true); + if (!bInfos[i].isMarkedAsStarted()) + continue; + for (int j = 0; j < references.length; j++) + if (references[j].getProperty(ConfiguratorManipulator.SERVICE_PROP_KEY_CONFIGURATOR_BUNDLESYMBOLICNAME).equals(Utils.getPathFromClause(Utils.getManifestMainAttributes(location, Constants.BUNDLE_SYMBOLICNAME)))) { + configuratorManipulator = (ConfiguratorManipulator) cmTracker.getService(references[j]); + break; + } + if (configuratorManipulator != null) + break; + } + } + + public void setLauncherData(LauncherData value) { + launcherData.initialize(); + launcherData.setFwConfigLocation(value.getFwConfigLocation()); + launcherData.setFwPersistentDataLocation(value.getFwPersistentDataLocation(), value.isClean()); + launcherData.setJvm(value.getJvm()); + launcherData.setJvmArgs(value.getJvmArgs()); + if (launcherData.getFwName().equals(value.getFwName())) + if (launcherData.getFwVersion().equals(value.getFwVersion())) { + // TODO launcherData.getFwName()/getFwVersion()/ + // getLauncherName()/getLauncherVersion() might be taken into consideration + // for copying . + launcherData.setFwJar(value.getFwJar()); + launcherData.setHome(value.getHome()); + launcherData.setLauncher(value.getLauncher()); + launcherData.setLauncherConfigLocation(value.getLauncherConfigLocation()); + } + } + + /** + * Temporal implementation. + * + * If a property of the given key should be eliminated + * from FwDependentProperties and FwIndependentProperties, + * return true. Otherwise false. + * + * @param key + * @return true if it should be elimineted from FwDependentProperties and FwIndependentProperties, + */ + private boolean toBeEliminated(String key) { + if (key.startsWith("java.")) + return true; + return false; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("++++++++++++++++++++++++++++++++++++++++++\n" + "Class:" + this.getClass().getName() + "\n"); + sb.append("------------- LauncherData -----------\n"); + sb.append(launcherData.toString()); + sb.append("------------- ConfigData -----------\n"); + sb.append(configData.toString()); + sb.append("\n" + Utils.toStringProperties("platformProperties", this.platformProperties)); + sb.append("++++++++++++++++++++++++++++++++++++++++++\n"); + return sb.toString(); + } + + private void updateAccordingToExpectedState(BundlesState bundlesState) { + // File newFwJar = EquinoxBundlesState.getFwJar(launcherData, configData); + // if (bundlesState instanceof EquinoxBundlesState) + // ((EquinoxBundlesState) bundlesState).setFwJar(newFwJar); + // + // if (launcherData.getFwJar() == null && newFwJar != null) + // launcherData.setFwJar(newFwJar); + BundleInfo[] newBundleInfos = bundlesState.getExpectedState(); + configData.setBundles(newBundleInfos); + } + + /* + * Make the given path relative to the specified root, if applicable. If not, then + * return the path as-is. + * + * Method similar to one from SimpleConfigurationManipulatorImpl. + */ + public static String makeRelative(String original, String rootPath) { + IPath path = new Path(original); + // ensure we have an absolute path to start with + if (!path.isAbsolute()) + return original; + + return makeRelative(path, new Path(rootPath)); + } + + private static String makeRelative(IPath toRel, IPath base) { + int i = base.matchingFirstSegments(toRel); + if (i == 0) { + return toRel.toOSString(); + } + String result = ""; + for (int j = 0; j < (base.segmentCount() - i); j++) { + result += ".." + Path.SEPARATOR; + } + if (i == toRel.segmentCount()) + return "."; + result += toRel.setDevice(null).removeFirstSegments(i).toOSString(); + return result; + } + + public static String makeRelative(String urlString, URL rootURL) { + // we only traffic in file: URLs + int index = urlString.indexOf(FILE_PROTOCOL); + if (index == -1) + return urlString; + index = index + 5; + + // ensure we have an absolute path to start with + boolean done = false; + URL url = null; + String file = urlString; + while (!done) { + try { + url = new URL(file); + file = url.getFile(); + } catch (java.net.MalformedURLException e) { + done = true; + } + } + if (url == null || !new File(url.getFile()).isAbsolute()) + return urlString; + + String rootString = rootURL.toExternalForm(); + return urlString.substring(0, index) + makeRelative(urlString.substring(index), rootString.substring(rootString.indexOf(FILE_PROTOCOL) + 5)); + } + + public static String makeArrayRelative(String array, URL rootURL) { + StringBuffer buffer = new StringBuffer(); + for (StringTokenizer tokenizer = new StringTokenizer(array, COMMA); tokenizer.hasMoreTokens();) { + String token = tokenizer.nextToken(); + String absolute = makeRelative(token, rootURL); + buffer.append(absolute); + if (tokenizer.hasMoreTokens()) + buffer.append(','); + } + return buffer.toString(); + } + + public static String makeArrayAbsolute(String array, URL rootURL) { + StringBuffer buffer = new StringBuffer(); + for (StringTokenizer tokenizer = new StringTokenizer(array, COMMA); tokenizer.hasMoreTokens();) { + String token = tokenizer.nextToken(); + String absolute = makeAbsolute(token, rootURL); + buffer.append(absolute); + if (tokenizer.hasMoreTokens()) + buffer.append(','); + } + return buffer.toString(); + } + + /* + * Make the given path absolute to the specified root, if applicable. If not, then + * return the path as-is. + * + * Method similar to one from SimpleConfigurationManipulatorImpl. + */ + public static String makeAbsolute(String original, String rootPath) { + IPath path = new Path(original); + // ensure we have a relative path to start with + if (path.isAbsolute()) + return original; + IPath root = new Path(rootPath); + return root.addTrailingSeparator().append(original.replace(':', '}')).toOSString().replace('}', ':'); + } + + public static String makeAbsolute(String urlString, URL rootURL) { + // we only traffic in file: URLs + int index = urlString.indexOf(FILE_PROTOCOL); + if (index == -1) + return urlString; + index = index + 5; + + // ensure we have a relative path to start with + boolean done = false; + URL url = null; + String file = urlString; + while (!done) { + try { + url = new URL(file); + file = url.getFile(); + } catch (java.net.MalformedURLException e) { + done = true; + } + } + if (url == null || new File(url.getFile()).isAbsolute()) + return urlString; + + return urlString.substring(0, index - 5) + makeAbsolute(urlString.substring(index), rootURL.toExternalForm()); + } +} diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/Log.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/Log.java new file mode 100644 index 000000000..6809674fa --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/Log.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.equinox.internal.frameworkadmin.equinox; + +import org.osgi.framework.BundleContext; +import org.osgi.service.log.LogService; +import org.osgi.util.tracker.ServiceTracker; + +/** + * Utility class with static methods for logging to LogService, if available + */ +public class Log { + static private ServiceTracker logTracker; + static private boolean useLog = false; + + public static void dispose() { + if (logTracker != null) { + logTracker.close(); + } + logTracker = null; + } + + public static void init(BundleContext bc) { + logTracker = new ServiceTracker(bc, LogService.class.getName(), null); + logTracker.open(); + } + + public static void log(int level, Object obj, String method, String message) { + log(level, obj, method, message, null); + } + + public static void log(int level, Object obj, String method, String message, Throwable e) { + LogService logService = null; + String msg = ""; + if (method == null) { + if (obj != null) + msg = "(" + obj.getClass().getName() + ")"; + } else if (obj == null) + msg = "[" + method + "]" + message; + else + msg = "[" + method + "](" + obj.getClass().getName() + ")"; + msg += message; + if (logTracker != null) + logService = (LogService) logTracker.getService(); + + if (logService != null) { + logService.log(level, msg, e); + } else { + String levelSt = null; + if (level == LogService.LOG_DEBUG) + levelSt = "DEBUG"; + else if (level == LogService.LOG_INFO) + levelSt = "INFO"; + else if (level == LogService.LOG_WARNING) + levelSt = "WARNING"; + else if (level == LogService.LOG_ERROR) { + levelSt = "ERROR"; + useLog = true; + } + if (useLog) { + System.err.println("[" + levelSt + "]" + msg); + if (e != null) + e.printStackTrace(); + } + } + } + + public static void log(int level, Object obj, String method, Throwable e) { + log(level, obj, method, null, e); + } + + public static void log(int level, String message) { + log(level, null, null, message, null); + } + + public static void log(int level, String message, Throwable e) { + log(level, null, null, message, e); + } + + private Log() { + } + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/utils/EclipseVersion.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/utils/EclipseVersion.java new file mode 100644 index 000000000..2b517545c --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/utils/EclipseVersion.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox.utils; + +import java.util.StringTokenizer; + +public class EclipseVersion implements Comparable { + int major = 0; + int minor = 0; + int service = 0; + String qualifier = null; + + public EclipseVersion(String version) { + StringTokenizer tok = new StringTokenizer(version, "."); + if (!tok.hasMoreTokens()) + return; + this.major = Integer.parseInt(tok.nextToken()); + if (!tok.hasMoreTokens()) + return; + this.minor = Integer.parseInt(tok.nextToken()); + if (!tok.hasMoreTokens()) + return; + this.service = Integer.parseInt(tok.nextToken()); + if (!tok.hasMoreTokens()) + return; + this.qualifier = tok.nextToken(); + } + + public int compareTo(Object obj) { + EclipseVersion target = (EclipseVersion) obj; + if (target.major > this.major) + return -1; + if (target.major < this.major) + return 1; + if (target.minor > this.minor) + return -1; + if (target.minor < this.minor) + return 1; + if (target.service > this.service) + return -1; + if (target.service < this.service) + return 1; + return 0; + } + +} diff --git a/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/utils/FileUtils.java b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/utils/FileUtils.java new file mode 100644 index 000000000..d438bf1de --- /dev/null +++ b/bundles/org.eclipse.equinox.frameworkadmin.equinox/src/org/eclipse/equinox/internal/frameworkadmin/equinox/utils/FileUtils.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.internal.frameworkadmin.equinox.utils; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import org.eclipse.equinox.internal.frameworkadmin.equinox.EquinoxConstants; +import org.eclipse.equinox.internal.provisional.frameworkadmin.LauncherData; +import org.eclipse.equinox.internal.provisional.frameworkadmin.Manipulator; + +public class FileUtils { + + public static String getEclipseRealLocation(final Manipulator manipulator, final String location) { + try { + new URL(location); + return location; + } catch (MalformedURLException e) { + // just ignore. + } + if (location.indexOf(":") >= 0) + return location; + + LauncherData launcherData = manipulator.getLauncherData(); + File home = launcherData.getHome(); + File pluginsDir = null; + if (home != null) + pluginsDir = new File(home, EquinoxConstants.PLUGINS_DIR); + else if (launcherData.getLauncher() != null) + pluginsDir = new File(launcherData.getLauncher().getParentFile(), EquinoxConstants.PLUGINS_DIR); + else if (launcherData.getFwJar() != null) + pluginsDir = launcherData.getFwJar().getParentFile(); + String pluginName = getPluginName(location); + String ret = getEclipsePluginFullLocation(pluginName, pluginsDir); + return ret; + } + + private static String getPluginName(final String location) { + int position = location.indexOf("_"); + String pluginName = location; + if (position >= 0) + pluginName = location.substring(0, position); + return pluginName; + } + + public static String getRealLocation(Manipulator manipulator, final String location, boolean useEclipse) { + if (location == null) + return null; + String ret = location; + if (location.startsWith("reference:")) { + ret = location.substring("reference:".length()); + if (ret.endsWith(".jar/")) { + ret = ret.substring(0, ret.length() - "/".length()); + if (ret.startsWith("file:")) + ret = ret.substring("file:".length()); + } + } + if (location.startsWith("initial@")) + ret = location.substring("initial@".length()); + + if (ret == location) + return useEclipse ? FileUtils.getEclipseRealLocation(manipulator, location) : location; + return getRealLocation(manipulator, ret, useEclipse); + } + + private static String replaceAll(String st, String oldSt, String newSt) { + if (oldSt.equals(newSt)) + return st; + int index = -1; + while ((index = st.indexOf(oldSt)) != -1) { + st = st.substring(0, index) + newSt + st.substring(index + oldSt.length()); + } + return st; + } + + /** + * If a bundle of the specified location is in the Eclipse plugin format (either plugin-name_version.jar + * or as a folder named plugin-name_version ), return version string.Otherwise, return null; + * + * @param url + * @param pluginName + * @return version string. If invalid format, return null. + */ + private static String getEclipseNamingVersion(URL url, final String pluginName, boolean isFile) { + String location = url.getFile(); + location = replaceAll(location, File.separator, "/"); + String filename = null; + if (location.indexOf(":") == -1) + filename = location; + else + filename = location.substring(location.lastIndexOf(":") + 1); + + // filename must be "jarName"_"version".jar + if (isFile) { + if (!filename.endsWith(".jar")) + return null; + filename = filename.substring(0, filename.lastIndexOf(".jar")); + } else { + // directory - remove trailing slash + filename = filename.substring(0, filename.length() - 1); + } + + if (filename.indexOf("/") != -1) + filename = filename.substring(filename.lastIndexOf("/") + 1); + + if (!filename.startsWith(pluginName)) + return null; + + int pluginnameLength = pluginName.length(); + if (filename.length() <= pluginnameLength || filename.charAt(pluginName.length()) != '_') + return null; + + return filename.substring(pluginnameLength + 1); + } + + public static String getEclipsePluginFullLocation(String pluginName, File bundlesDir) { + File[] lists = bundlesDir.listFiles(); + URL ret = null; + EclipseVersion maxVersion = null; + if (lists == null) + return null; + + for (int i = 0; i < lists.length; i++) { + try { + URL url = lists[i].toURL(); + String version = getEclipseNamingVersion(url, pluginName, lists[i].isFile()); + if (version != null) { + EclipseVersion eclipseVersion = new EclipseVersion(version); + if (maxVersion == null || eclipseVersion.compareTo(maxVersion) > 0) { + ret = url; + maxVersion = eclipseVersion; + } + } + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } + return (ret == null ? null : ret.toExternalForm()); + } +} |