-package org.simantics.team.internal;\r
-\r
-import java.io.File;\r
-import java.io.FileWriter;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.PrintStream;\r
-import java.net.URLDecoder;\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.HashSet;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Properties;\r
-import java.util.Set;\r
-\r
-import org.eclipse.core.runtime.Platform;\r
-import org.eclipse.equinox.frameworkadmin.BundleInfo;\r
-import org.eclipse.equinox.internal.frameworkadmin.equinox.EquinoxConstants;\r
-import org.eclipse.equinox.internal.frameworkadmin.utils.Utils;\r
-import org.eclipse.equinox.internal.provisional.frameworkadmin.ConfigData;\r
-import org.eclipse.equinox.internal.provisional.frameworkadmin.FrameworkAdmin;\r
-import org.eclipse.equinox.internal.provisional.frameworkadmin.FrameworkAdminRuntimeException;\r
-import org.eclipse.equinox.internal.provisional.frameworkadmin.LauncherData;\r
-import org.eclipse.equinox.internal.provisional.frameworkadmin.Manipulator;\r
-import org.osgi.framework.Bundle;\r
-import org.osgi.framework.BundleContext;\r
-import org.osgi.framework.BundleException;\r
-import org.osgi.framework.FrameworkUtil;\r
-import org.osgi.framework.InvalidSyntaxException;\r
-import org.osgi.framework.ServiceReference;\r
-import org.simantics.application.db.SocketUtils;\r
-import org.simantics.databoard.binding.error.BindingConstructionException;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.utils.FileUtils;\r
-import org.simantics.utils.strings.EString;\r
-\r
-@SuppressWarnings("restriction")\r
-public final class StagingLauncher {\r
- private static final boolean DEBUG = true;\r
- private static final boolean DEBUG_EXEC = true;\r
- private static final boolean REMOTE_DEBUG_DISABLED = true;\r
- public static StagingResult launch(\r
- final Config stagingConfig,\r
- String serverAddress,\r
- String targetResourceId)\r
- throws InvalidSyntaxException, IllegalArgumentException,\r
- FrameworkAdminRuntimeException, IOException, BindingConstructionException, DatabaseException {\r
- Bundle dsBundle = Platform.getBundle("org.eclipse.equinox.ds");\r
- try {\r
- dsBundle.start(/*Bundle.START_TRANSIENT*/);\r
- if (DEBUG)\r
- System.out.println("state="+dsBundle.getState());\r
- } catch (BundleException ex) {\r
- throw new StagingException("Could not start org.eclipse.equinox.ds.", ex);\r
- }\r
- Bundle faBundle = FrameworkUtil.getBundle(FrameworkAdmin.class);\r
- if (null == faBundle)\r
- throw new StagingException("Bundle for FrameworkAdmin not available.");\r
- BundleContext faContext = faBundle.getBundleContext();\r
- if (null == faContext)\r
- throw new StagingException("Context for FrameworkAdmin not available.");\r
- ServiceReference<FrameworkAdmin> ref = faContext.getServiceReference(FrameworkAdmin.class);\r
- if (ref == null)\r
- throw new StagingException("Reference for FrameworkAdmin not available.");\r
- FrameworkAdmin admin = (FrameworkAdmin)faContext.getService(ref);\r
- if (null == admin)\r
- throw new StagingException("FrameworkAdmin not available.");\r
- try {\r
- Manipulator rmanip = admin.getRunningManipulator();\r
- if (rmanip == null)\r
- throw new StagingException("No FrameworkAdmin Manipulator available for the currently running environment.");\r
- if (DEBUG)\r
- System.out.println("FrameworkAdmin Manipulator of the running environment:\n" + rmanip);\r
- Properties system = System.getProperties();\r
- ConfigData rcd = rmanip.getConfigData();\r
- LauncherData rld = rmanip.getLauncherData();\r
- Manipulator manip = admin.getManipulator();\r
- manip.setConfigData(rcd);\r
- manip.setLauncherData(rld);\r
- ConfigData cd = manip.getConfigData();\r
- LauncherData ld = manip.getLauncherData();\r
- Properties config = new Properties();\r
- StringBuilder osgiBundles = new StringBuilder(1024);\r
- StringBuilder bundlesInfo = new StringBuilder(1024);\r
- bundlesInfo.append("#version=1\n");\r
- for (BundleInfo bi : cd.getBundles()) {\r
- boolean started = isMarkedAsStarted(bi);\r
- bundlesInfo\r
- .append(bi.getSymbolicName())\r
- .append(",")\r
- .append(bi.getVersion())\r
- .append(",")\r
- //.append(bi.getLocation().toString())\r
- .append(URLDecoder.decode(bi.getLocation().toString(), "UTF-8"))\r
- .append(",")\r
- .append(bi.getStartLevel())\r
- .append(",")\r
- .append(started)\r
- .append("\n");\r
- if (DEBUG) {\r
- System.out.println("bundle: " + bi.getSymbolicName() + "\n\t" + bi.getLocation().toString() + "\n\t" + started);\r
- if (started)\r
- System.out.println("IS STARTED: bundle: " + bi.getSymbolicName() + "\n\t" + bi.getLocation().toString());\r
- if (!started && bi.isMarkedAsStarted())\r
- System.out.println("NOT STARTED, BUT WAS MARKED AS STARTED: bundle: " + bi.getSymbolicName() + "\n\t" + bi.getLocation().toString());\r
- }\r
- if (isStartUpBundle(bi)) {\r
- if (osgiBundles.length() > 0) {\r
- osgiBundles.append(",");\r
- }\r
- osgiBundles\r
- .append("reference:")\r
- .append(URLDecoder.decode(bi.getLocation().toString(), "UTF-8"))\r
- .append("@")\r
- .append(bi.getStartLevel())\r
- .append(":start");\r
- }\r
- }\r
- //File cwd = new File(system.getProperty("user.dir"));\r
- File javaHome = new File(system.getProperty("java.home"));\r
- String installArea = system.getProperty("osgi.install.area");\r
- config.setProperty("eclipse.application", "org.simantics.workbench.application");\r
- config.setProperty("eclipse.product", "org.simantics.devs3.ui.product");\r
- //config.setProperty("eclipse.consoleLog", "");\r
- config.setProperty("org.eclipse.update.reconcile", "false");\r
- config.setProperty("osgi.bundles", osgiBundles.toString());\r
- config.setProperty("osgi.bundles.defaultStartLevel", "4");\r
- //config.setProperty("osgi.clean", "true");\r
- //config.setProperty("osgi.configuration.area", "@default");\r
- config.setProperty("osgi.configuration.cascaded", "false");\r
- //config.setProperty("osgi.console", "");\r
- //config.setProperty("osgi.debug", "");\r
- config.setProperty("osgi.framework", URLDecoder.decode(ld.getFwJar().toURI().toString(), "UTF-8"));\r
- //config.setProperty("osgi.noShutdown", "");\r
- config.setProperty("osgi.install.area", installArea);\r
- config.setProperty("osgi.instance.area", stagingConfig.workspaceRoot.getAbsolutePath());\r
-// cd.setProperty("osgi.instance.area", "@none");\r
- config.setProperty("osgi.user.area", "@none");\r
- // Eclipse 3.6, not sure what this is for but modern apps have it.\r
- config.setProperty("equinox.use.ds", "true");\r
- // Ignore INFO level log messages\r
- config.setProperty("eclipse.log.level", "WARNING");\r
- File configDir = new File(stagingConfig.workspaceRoot, "configuration");\r
- File simpleConfiguratorDir = new File(configDir, "org.eclipse.equinox.simpleconfigurator");\r
- simpleConfiguratorDir.mkdirs();\r
- File bundlesInfoFile = new File(simpleConfiguratorDir, "bundles.info");\r
- config.setProperty("org.eclipse.equinox.simpleconfigurator.configUrl", URLDecoder.decode(bundlesInfoFile.toURI().toString(), "UTF-8"));\r
- File logFile = new File(stagingConfig.workspaceRoot, "db-client.log");\r
- writeProperties(config, new File(configDir, "config.ini"), "This configuration file was written by: " + StagingLauncher.class.getCanonicalName());\r
- writeFile(bundlesInfo.toString(), bundlesInfoFile);\r
-\r
- ld.setJvm(new File(new File(javaHome, "bin"), "java"));\r
- ld.setFwConfigLocation(configDir);\r
- ld.setFwPersistentDataLocation(configDir, false);\r
- ld.setLauncher(null);\r
- int maxHeap = 768; /*prefs.getInt(Activator.PLUGIN_ID, ImportPreferences.PREF_IMPORT_PROCESS_MAX_HEAP,\r
- ImportPreferences.getDefaultImportProcessMaxHeap(), preferenceScopes);\r
- // Just a safety if preferences have not been properly initialized for some reason.\r
- if (maxHeap == 0)\r
- maxHeap = ImportPreferences.getDefaultImportProcessMaxHeap();*/\r
- ld.addJvmArg("-Xmx" + maxHeap + "m");\r
- ld.addJvmArg("-Xms" + maxHeap + "m");\r
- // Enable assertions to have faster failure in db client routines with improper input.\r
- ld.addJvmArg("-ea");\r
- // For supporting OSGi dev mode (launched from IDE)\r
- if (Platform.inDevelopmentMode()) {\r
- // TODO: %osgi.dev is not escaped, it can contain whitespace\r
- // but this doesn't seem to matter ?\r
- ld.addJvmArg("-Dosgi.dev=" + system.getProperty("osgi.dev"));\r
- }\r
- ld.addJvmArg("-Dosgi.arch=" + rcd.getProperty("osgi.arch"));\r
- ld.addJvmArg("-Dosgi.os=" + rcd.getProperty("osgi.os"));\r
- ld.addJvmArg("-Dosgi.ws=" + rcd.getProperty("osgi.ws"));\r
- ld.addJvmArg("-Dosgi.nl=" + rcd.getProperty("osgi.nl"));\r
-\r
- // WORKAROUND for a problem in org.eclipse.ecf fragment org.eclipse.ecf.ssl.\r
- // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=316500\r
- // Either one of these works, THESE:\r
- //ld.addJvmArg("-Dosgi.java.profile.bootdelegation=override");\r
- //ld.addJvmArg("-Dorg.osgi.framework.bootdelegation=sun.*, com.sun.*, javax.*");\r
- // OR:\r
- ld.addJvmArg("-Dosgi.compatibility.bootdelegation=true");\r
-\r
- // Enable remote debugging when in osgi dev mode.\r
- if (Platform.inDevelopmentMode())\r
- if (!REMOTE_DEBUG_DISABLED) {\r
- ld.addJvmArg("-Xdebug");\r
- ld.addJvmArg("-Xnoagent");\r
- int port = SocketUtils.getFreeEphemeralPort();\r
- ld.addJvmArg("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=" + port);\r
- }\r
-\r
- ld.addJvmArg("-D" + Constants.PROP_DUMP_PROPERTIES);\r
- ld.addJvmArg("-D" + Constants.PROP_LOGFILE + "=" + logFile.toURI().toString());\r
- String titleArgument = System.getProperty(Constants.PROP_WINDOW_TITLE);\r
- if (null != titleArgument && !titleArgument.equals(""))\r
- titleArgument = stagingConfig.titlePrefix + " " + titleArgument;\r
- else\r
- titleArgument = stagingConfig.titlePrefix;\r
- ld.addJvmArg("-D" + Constants.PROP_WINDOW_TITLE + "=" + titleArgument);\r
- if (null != stagingConfig.teamFolder)\r
- ld.addJvmArg("-D" + Constants.PROP_TEAM_FOLDER + "=" + stagingConfig.teamFolder.getAbsolutePath()); \r
- ld.addJvmArg("-D" + Constants.PROP_WORKSPACE_ROOT + "=" + stagingConfig.workspaceRoot.toURI().toString());\r
- if (DEBUG)\r
- System.out.println("JVM ARGS: " + Arrays.toString(ld.getJvmArgs()));\r
-\r
- // Using this means that\r
- // * config.ini must not be written self\r
- // * parent program bundles.info can be reused (this could be done in any case)\r
- // * running platform configuration must not be copied completely, only selected parts of\r
- //manip.save(false);\r
-\r
- // #5849 workaround\r
-// XSupport xs = stagingConfig.session.getService(XSupport.class);\r
-// xs.initClusterIdMap(stagingConfig.workspaceRoot.getAbsolutePath());\r
- if (null != stagingConfig.clusterMapFolder) {\r
- String file = "clusterIdMap.dat";\r
- File f = new File(stagingConfig.clusterMapFolder, file);\r
- File tFolder = new File(stagingConfig.workspaceRoot, ".metadata/.plugins/org.simantics.db.procore");\r
- tFolder.mkdirs();\r
- FileUtils.copyFile(f, new File(tFolder, file));\r
- String file2 = "nextId.dat";\r
- File f2 = new File(stagingConfig.clusterMapFolder, file2);\r
- File tFolder2 = new File(stagingConfig.workspaceRoot, "db");\r
- FileUtils.copyFile(f2, new File(tFolder2, file2));\r
- }\r
- if (DEBUG)\r
- System.out.println("LAUNCHING\n" + manip);\r
- Process process;\r
- {\r
- LauncherData launcherData = ld;\r
- if (DEBUG)\r
- System.out.println("Framework JAR: " + ld.getFwJar().toURI().toString());\r
- Utils.checkAbsoluteFile(launcherData.getFwJar(), "fwJar"); //$NON-NLS-1$\r
- File cwd = stagingConfig.workspaceRoot;\r
- Utils.checkAbsoluteDir(cwd, "cwd"); //$NON-NLS-1$\r
-\r
- List<String> cmdList = new LinkedList<String>();\r
- if (launcherData.getJvm() != null)\r
- cmdList.add(launcherData.getJvm().getAbsolutePath());\r
- else\r
- cmdList.add("java"); //$NON-NLS-1$\r
-\r
- if (launcherData.getJvmArgs() != null)\r
- for (int i = 0; i < launcherData.getJvmArgs().length; i++)\r
- cmdList.add(launcherData.getJvmArgs()[i]);\r
-\r
- cmdList.add("-jar"); //$NON-NLS-1$\r
- cmdList.add("\"" + launcherData.getFwJar().getAbsolutePath() + "\"");\r
-\r
- //EquinoxManipulatorImpl.checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(launcherData);\r
- cmdList.add(EquinoxConstants.OPTION_CONFIGURATION);\r
- cmdList.add("\"" + launcherData.getFwPersistentDataLocation().getAbsolutePath() + "\"");\r
-\r
- cmdList.add("-data");\r
- cmdList.add(stagingConfig.workspaceRoot.getAbsolutePath());\r
-\r
- if (launcherData.isClean())\r
- cmdList.add(EquinoxConstants.OPTION_CLEAN);\r
-\r
- String[] cmdarray = cmdList.toArray(new String[cmdList.size()]);\r
-\r
- if (DEBUG_EXEC)\r
- System.out.println("Launching import, CWD=" + cwd + "\n\t" + EString.implode(cmdarray, "\n\t"));\r
-\r
- process = Runtime.getRuntime().exec(cmdarray, null, cwd);\r
- }\r
-\r
- long startTime = System.nanoTime();\r
- int exitValue = Integer.MIN_VALUE;\r
- InputStream is = process.getInputStream();\r
- InputStream es = process.getErrorStream();\r
- while (true) {\r
- try {\r
- long endTime = System.nanoTime();\r
- //System.out.println("Checking for process exit value");\r
- exitValue = process.exitValue();\r
- System.out.println("finished in " + (endTime-startTime)*1e-6 + "ms");\r
- System.out.println("exit value: " + exitValue);\r
- } catch (IllegalThreadStateException e) {\r
- try {\r
- int n = is.available(); \r
- if (n > 0) {\r
- byte[] bytes = new byte[n];\r
- int nr = is.read(bytes);\r
- if (nr > 0)\r
- System.out.println("DEBUG: STDOUT:" + org.simantics.team.Utils.bytesToStringASCII(bytes, 0, nr));\r
- }\r
- n = es.available();\r
- if (n > 0) {\r
- byte[] bytes = new byte[n];\r
- int nr = es.read(bytes);\r
- if (nr > 0)\r
- System.out.println("DEBUG: STDERR:" + org.simantics.team.Utils.bytesToStringASCII(bytes, 0, nr));\r
- }\r
- Thread.sleep(100);\r
- } catch (InterruptedException e1) {\r
- e1.printStackTrace();\r
- }\r
- continue;\r
- }\r
- String ins = FileUtils.getContents(is);\r
- if (!ins.isEmpty())\r
- System.out.println("--- STDOUT ---\n" + ins);\r
- String errs = FileUtils.getContents(es);\r
- if (!errs.isEmpty())\r
- System.out.println("--- STDERR ---\n" + errs);\r
- break;\r
- }\r
-\r
- // #5849 workaround\r
-// xs.mergeClusterIdMap(stagingConfig.workspaceRoot.getAbsolutePath());\r
-\r
- return new StagingResult(exitValue, logFile, null);\r
- } finally {\r
- faContext.ungetService(ref);\r
- }\r
- }\r
-\r
- private static Set<String> startUpBundles = new HashSet<String>();\r
- static {\r
- //startUpBundles.add("org.eclipse.equinox.ds");\r
- startUpBundles.add("org.eclipse.equinox.simpleconfigurator");\r
- }\r
-\r
- private static Set<String> startedBundles = new HashSet<String>();\r
- static {\r
- startedBundles.add("org.eclipse.core.runtime");\r
- }\r
-\r
- private static boolean isStartUpBundle(BundleInfo bi) {\r
- return startUpBundles.contains(bi.getSymbolicName());\r
- }\r
-\r
- private static boolean isMarkedAsStarted(BundleInfo bi) {\r
- // Prevent unnecessary bundles from being\r
- // activated by only marking as started the plug-ins that\r
- // are vital to the environment, which always have lower\r
- // start level than the default 4.\r
- return bi.isMarkedAsStarted() && (bi.getStartLevel() < 4 || startedBundles.contains(bi.getSymbolicName()));\r
- }\r
-\r
- private static void writeProperties(Properties properties, File target, String comment) throws IOException {\r
- FileWriter writer = new FileWriter(target);\r
- try {\r
- properties.store(writer, comment);\r
- } finally {\r
- writer.close();\r
- }\r
- }\r
-\r
- private static void writeFile(String string, File target) throws IOException {\r
- FileWriter writer = new FileWriter(target);\r
- try {\r
- writer.write(string);\r
- } finally {\r
- writer.close();\r
- }\r
- }\r
- static public final class StagingResult {\r
-\r
- private final int exitValue;\r
-\r
- private final File logFile;\r
- \r
- private final String messageLog;\r
-\r
- public StagingResult(String message) {\r
- this.exitValue = Integer.MIN_VALUE;\r
- this.logFile = null;\r
- this.messageLog = message;\r
- }\r
- public StagingResult(int exitValue, File logFile, String messageLog) {\r
- this.exitValue = exitValue;\r
- this.logFile = logFile;\r
- this.messageLog = messageLog;\r
- }\r
-\r
- public int getExitValue() {\r
- return exitValue;\r
- }\r
-\r
- public File getLogFile() {\r
- return logFile;\r
- }\r
- \r
- public String getMessageLog() {\r
- return messageLog;\r
- }\r
-\r
- }\r
- public static final class Config {\r
- public final Session session;\r
- public final Resource targetLibrary;\r
- public final File workspaceRoot;\r
- public final File clusterMapFolder;\r
- public final File teamFolder;\r
- public final PrintStream out;\r
- // Outputs\r
- public Resource createdModel;\r
- public Resource createdState;\r
- public List<String> messages = new ArrayList<String>();\r
- public String titlePrefix = "Staging";\r
-\r
- public Config(Session session, Resource library, File workspaceRoot, File clusterMapFolder)\r
- throws DatabaseException {\r
- this(session, library, workspaceRoot, clusterMapFolder, null);\r
- }\r
-\r
- public Config( Session session, Resource library, File workspaceRoot, File clusterMapFolder, PrintStream out)\r
- throws DatabaseException {\r
- this.session = session;\r
- this.targetLibrary = library;\r
- this.workspaceRoot = workspaceRoot;\r
- this.clusterMapFolder = clusterMapFolder;\r
- this.teamFolder = org.simantics.team.Utils.getTeamFolder();\r
- this.out = out;\r
- }\r
- }\r
- static final class Constants {\r
-\r
- /**\r
- * Tells the launched application to dump all its system properties into the\r
- * standard output / log.\r
- */\r
- public static final String PROP_DUMP_PROPERTIES = "dump.properties";\r
-\r
- /**\r
- * Controls where the launched application log is written. Specified as an URI.\r
- */\r
- public static final String PROP_LOGFILE = "staging.logfile";\r
-\r
- /**\r
- * Prefix for the window title.\r
- */\r
- public static final String PROP_WINDOW_TITLE = "staging.window.title";\r
-\r
- /**\r
- * Tells the launched application where its team data comes from.\r
- */\r
- public static final String PROP_TEAM_FOLDER = "staging.team.folder";\r
-\r
- /**\r
- * Workspace root directory of the workbench process that launched the\r
- * import process.\r
- */\r
- public static final String PROP_WORKSPACE_ROOT = "import.workspace.root";\r
- }\r
-}\r
+package org.simantics.team.internal;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.equinox.frameworkadmin.BundleInfo;
+import org.eclipse.equinox.internal.frameworkadmin.equinox.EquinoxConstants;
+import org.eclipse.equinox.internal.frameworkadmin.utils.Utils;
+import org.eclipse.equinox.internal.provisional.frameworkadmin.ConfigData;
+import org.eclipse.equinox.internal.provisional.frameworkadmin.FrameworkAdmin;
+import org.eclipse.equinox.internal.provisional.frameworkadmin.FrameworkAdminRuntimeException;
+import org.eclipse.equinox.internal.provisional.frameworkadmin.LauncherData;
+import org.eclipse.equinox.internal.provisional.frameworkadmin.Manipulator;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.simantics.application.db.SocketUtils;
+import org.simantics.databoard.binding.error.BindingConstructionException;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.utils.FileUtils;
+import org.simantics.utils.strings.EString;
+
+@SuppressWarnings("restriction")
+public final class StagingLauncher {
+ private static final boolean DEBUG = true;
+ private static final boolean DEBUG_EXEC = true;
+ private static final boolean REMOTE_DEBUG_DISABLED = true;
+ public static StagingResult launch(
+ final Config stagingConfig,
+ String serverAddress,
+ String targetResourceId)
+ throws InvalidSyntaxException, IllegalArgumentException,
+ FrameworkAdminRuntimeException, IOException, BindingConstructionException, DatabaseException {
+ Bundle dsBundle = Platform.getBundle("org.eclipse.equinox.ds");
+ try {
+ dsBundle.start(/*Bundle.START_TRANSIENT*/);
+ if (DEBUG)
+ System.out.println("state="+dsBundle.getState());
+ } catch (BundleException ex) {
+ throw new StagingException("Could not start org.eclipse.equinox.ds.", ex);
+ }
+ Bundle faBundle = FrameworkUtil.getBundle(FrameworkAdmin.class);
+ if (null == faBundle)
+ throw new StagingException("Bundle for FrameworkAdmin not available.");
+ BundleContext faContext = faBundle.getBundleContext();
+ if (null == faContext)
+ throw new StagingException("Context for FrameworkAdmin not available.");
+ ServiceReference<FrameworkAdmin> ref = faContext.getServiceReference(FrameworkAdmin.class);
+ if (ref == null)
+ throw new StagingException("Reference for FrameworkAdmin not available.");
+ FrameworkAdmin admin = (FrameworkAdmin)faContext.getService(ref);
+ if (null == admin)
+ throw new StagingException("FrameworkAdmin not available.");
+ try {
+ Manipulator rmanip = admin.getRunningManipulator();
+ if (rmanip == null)
+ throw new StagingException("No FrameworkAdmin Manipulator available for the currently running environment.");
+ if (DEBUG)
+ System.out.println("FrameworkAdmin Manipulator of the running environment:\n" + rmanip);
+ Properties system = System.getProperties();
+ ConfigData rcd = rmanip.getConfigData();
+ LauncherData rld = rmanip.getLauncherData();
+ Manipulator manip = admin.getManipulator();
+ manip.setConfigData(rcd);
+ manip.setLauncherData(rld);
+ ConfigData cd = manip.getConfigData();
+ LauncherData ld = manip.getLauncherData();
+ Properties config = new Properties();
+ StringBuilder osgiBundles = new StringBuilder(1024);
+ StringBuilder bundlesInfo = new StringBuilder(1024);
+ bundlesInfo.append("#version=1\n");
+ for (BundleInfo bi : cd.getBundles()) {
+ boolean started = isMarkedAsStarted(bi);
+ bundlesInfo
+ .append(bi.getSymbolicName())
+ .append(",")
+ .append(bi.getVersion())
+ .append(",")
+ //.append(bi.getLocation().toString())
+ .append(URLDecoder.decode(bi.getLocation().toString(), "UTF-8"))
+ .append(",")
+ .append(bi.getStartLevel())
+ .append(",")
+ .append(started)
+ .append("\n");
+ if (DEBUG) {
+ System.out.println("bundle: " + bi.getSymbolicName() + "\n\t" + bi.getLocation().toString() + "\n\t" + started);
+ if (started)
+ System.out.println("IS STARTED: bundle: " + bi.getSymbolicName() + "\n\t" + bi.getLocation().toString());
+ if (!started && bi.isMarkedAsStarted())
+ System.out.println("NOT STARTED, BUT WAS MARKED AS STARTED: bundle: " + bi.getSymbolicName() + "\n\t" + bi.getLocation().toString());
+ }
+ if (isStartUpBundle(bi)) {
+ if (osgiBundles.length() > 0) {
+ osgiBundles.append(",");
+ }
+ osgiBundles
+ .append("reference:")
+ .append(URLDecoder.decode(bi.getLocation().toString(), "UTF-8"))
+ .append("@")
+ .append(bi.getStartLevel())
+ .append(":start");
+ }
+ }
+ //File cwd = new File(system.getProperty("user.dir"));
+ File javaHome = new File(system.getProperty("java.home"));
+ String installArea = system.getProperty("osgi.install.area");
+ config.setProperty("eclipse.application", "org.simantics.workbench.application");
+ config.setProperty("eclipse.product", "org.simantics.devs3.ui.product");
+ //config.setProperty("eclipse.consoleLog", "");
+ config.setProperty("org.eclipse.update.reconcile", "false");
+ config.setProperty("osgi.bundles", osgiBundles.toString());
+ config.setProperty("osgi.bundles.defaultStartLevel", "4");
+ //config.setProperty("osgi.clean", "true");
+ //config.setProperty("osgi.configuration.area", "@default");
+ config.setProperty("osgi.configuration.cascaded", "false");
+ //config.setProperty("osgi.console", "");
+ //config.setProperty("osgi.debug", "");
+ config.setProperty("osgi.framework", URLDecoder.decode(ld.getFwJar().toURI().toString(), "UTF-8"));
+ //config.setProperty("osgi.noShutdown", "");
+ config.setProperty("osgi.install.area", installArea);
+ config.setProperty("osgi.instance.area", stagingConfig.workspaceRoot.getAbsolutePath());
+// cd.setProperty("osgi.instance.area", "@none");
+ config.setProperty("osgi.user.area", "@none");
+ // Eclipse 3.6, not sure what this is for but modern apps have it.
+ config.setProperty("equinox.use.ds", "true");
+ // Ignore INFO level log messages
+ config.setProperty("eclipse.log.level", "WARNING");
+ File configDir = new File(stagingConfig.workspaceRoot, "configuration");
+ File simpleConfiguratorDir = new File(configDir, "org.eclipse.equinox.simpleconfigurator");
+ simpleConfiguratorDir.mkdirs();
+ File bundlesInfoFile = new File(simpleConfiguratorDir, "bundles.info");
+ config.setProperty("org.eclipse.equinox.simpleconfigurator.configUrl", URLDecoder.decode(bundlesInfoFile.toURI().toString(), "UTF-8"));
+ File logFile = new File(stagingConfig.workspaceRoot, "db-client.log");
+ writeProperties(config, new File(configDir, "config.ini"), "This configuration file was written by: " + StagingLauncher.class.getCanonicalName());
+ writeFile(bundlesInfo.toString(), bundlesInfoFile);
+
+ ld.setJvm(new File(new File(javaHome, "bin"), "java"));
+ ld.setFwConfigLocation(configDir);
+ ld.setFwPersistentDataLocation(configDir, false);
+ ld.setLauncher(null);
+ int maxHeap = 768; /*prefs.getInt(Activator.PLUGIN_ID, ImportPreferences.PREF_IMPORT_PROCESS_MAX_HEAP,
+ ImportPreferences.getDefaultImportProcessMaxHeap(), preferenceScopes);
+ // Just a safety if preferences have not been properly initialized for some reason.
+ if (maxHeap == 0)
+ maxHeap = ImportPreferences.getDefaultImportProcessMaxHeap();*/
+ ld.addJvmArg("-Xmx" + maxHeap + "m");
+ ld.addJvmArg("-Xms" + maxHeap + "m");
+ // Enable assertions to have faster failure in db client routines with improper input.
+ ld.addJvmArg("-ea");
+ // For supporting OSGi dev mode (launched from IDE)
+ if (Platform.inDevelopmentMode()) {
+ // TODO: %osgi.dev is not escaped, it can contain whitespace
+ // but this doesn't seem to matter ?
+ ld.addJvmArg("-Dosgi.dev=" + system.getProperty("osgi.dev"));
+ }
+ ld.addJvmArg("-Dosgi.arch=" + rcd.getProperty("osgi.arch"));
+ ld.addJvmArg("-Dosgi.os=" + rcd.getProperty("osgi.os"));
+ ld.addJvmArg("-Dosgi.ws=" + rcd.getProperty("osgi.ws"));
+ ld.addJvmArg("-Dosgi.nl=" + rcd.getProperty("osgi.nl"));
+
+ // WORKAROUND for a problem in org.eclipse.ecf fragment org.eclipse.ecf.ssl.
+ // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=316500
+ // Either one of these works, THESE:
+ //ld.addJvmArg("-Dosgi.java.profile.bootdelegation=override");
+ //ld.addJvmArg("-Dorg.osgi.framework.bootdelegation=sun.*, com.sun.*, javax.*");
+ // OR:
+ ld.addJvmArg("-Dosgi.compatibility.bootdelegation=true");
+
+ // Enable remote debugging when in osgi dev mode.
+ if (Platform.inDevelopmentMode())
+ if (!REMOTE_DEBUG_DISABLED) {
+ ld.addJvmArg("-Xdebug");
+ ld.addJvmArg("-Xnoagent");
+ int port = SocketUtils.getFreeEphemeralPort();
+ ld.addJvmArg("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=" + port);
+ }
+
+ ld.addJvmArg("-D" + Constants.PROP_DUMP_PROPERTIES);
+ ld.addJvmArg("-D" + Constants.PROP_LOGFILE + "=" + logFile.toURI().toString());
+ String titleArgument = System.getProperty(Constants.PROP_WINDOW_TITLE);
+ if (null != titleArgument && !titleArgument.equals(""))
+ titleArgument = stagingConfig.titlePrefix + " " + titleArgument;
+ else
+ titleArgument = stagingConfig.titlePrefix;
+ ld.addJvmArg("-D" + Constants.PROP_WINDOW_TITLE + "=" + titleArgument);
+ if (null != stagingConfig.teamFolder)
+ ld.addJvmArg("-D" + Constants.PROP_TEAM_FOLDER + "=" + stagingConfig.teamFolder.getAbsolutePath());
+ ld.addJvmArg("-D" + Constants.PROP_WORKSPACE_ROOT + "=" + stagingConfig.workspaceRoot.toURI().toString());
+ if (DEBUG)
+ System.out.println("JVM ARGS: " + Arrays.toString(ld.getJvmArgs()));
+
+ // Using this means that
+ // * config.ini must not be written self
+ // * parent program bundles.info can be reused (this could be done in any case)
+ // * running platform configuration must not be copied completely, only selected parts of
+ //manip.save(false);
+
+ // #5849 workaround
+// XSupport xs = stagingConfig.session.getService(XSupport.class);
+// xs.initClusterIdMap(stagingConfig.workspaceRoot.getAbsolutePath());
+ if (null != stagingConfig.clusterMapFolder) {
+ String file = "clusterIdMap.dat";
+ File f = new File(stagingConfig.clusterMapFolder, file);
+ File tFolder = new File(stagingConfig.workspaceRoot, ".metadata/.plugins/org.simantics.db.procore");
+ tFolder.mkdirs();
+ FileUtils.copyFile(f, new File(tFolder, file));
+ String file2 = "nextId.dat";
+ File f2 = new File(stagingConfig.clusterMapFolder, file2);
+ File tFolder2 = new File(stagingConfig.workspaceRoot, "db");
+ FileUtils.copyFile(f2, new File(tFolder2, file2));
+ }
+ if (DEBUG)
+ System.out.println("LAUNCHING\n" + manip);
+ Process process;
+ {
+ LauncherData launcherData = ld;
+ if (DEBUG)
+ System.out.println("Framework JAR: " + ld.getFwJar().toURI().toString());
+ Utils.checkAbsoluteFile(launcherData.getFwJar(), "fwJar"); //$NON-NLS-1$
+ File cwd = stagingConfig.workspaceRoot;
+ Utils.checkAbsoluteDir(cwd, "cwd"); //$NON-NLS-1$
+
+ List<String> cmdList = new LinkedList<String>();
+ if (launcherData.getJvm() != null)
+ cmdList.add(launcherData.getJvm().getAbsolutePath());
+ else
+ cmdList.add("java"); //$NON-NLS-1$
+
+ if (launcherData.getJvmArgs() != null)
+ for (int i = 0; i < launcherData.getJvmArgs().length; i++)
+ cmdList.add(launcherData.getJvmArgs()[i]);
+
+ cmdList.add("-jar"); //$NON-NLS-1$
+ cmdList.add("\"" + launcherData.getFwJar().getAbsolutePath() + "\"");
+
+ //EquinoxManipulatorImpl.checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(launcherData);
+ cmdList.add(EquinoxConstants.OPTION_CONFIGURATION);
+ cmdList.add("\"" + launcherData.getFwPersistentDataLocation().getAbsolutePath() + "\"");
+
+ cmdList.add("-data");
+ cmdList.add(stagingConfig.workspaceRoot.getAbsolutePath());
+
+ if (launcherData.isClean())
+ cmdList.add(EquinoxConstants.OPTION_CLEAN);
+
+ String[] cmdarray = cmdList.toArray(new String[cmdList.size()]);
+
+ if (DEBUG_EXEC)
+ System.out.println("Launching import, CWD=" + cwd + "\n\t" + EString.implode(cmdarray, "\n\t"));
+
+ process = Runtime.getRuntime().exec(cmdarray, null, cwd);
+ }
+
+ long startTime = System.nanoTime();
+ int exitValue = Integer.MIN_VALUE;
+ InputStream is = process.getInputStream();
+ InputStream es = process.getErrorStream();
+ while (true) {
+ try {
+ long endTime = System.nanoTime();
+ //System.out.println("Checking for process exit value");
+ exitValue = process.exitValue();
+ System.out.println("finished in " + (endTime-startTime)*1e-6 + "ms");
+ System.out.println("exit value: " + exitValue);
+ } catch (IllegalThreadStateException e) {
+ try {
+ int n = is.available();
+ if (n > 0) {
+ byte[] bytes = new byte[n];
+ int nr = is.read(bytes);
+ if (nr > 0)
+ System.out.println("DEBUG: STDOUT:" + org.simantics.team.Utils.bytesToStringASCII(bytes, 0, nr));
+ }
+ n = es.available();
+ if (n > 0) {
+ byte[] bytes = new byte[n];
+ int nr = es.read(bytes);
+ if (nr > 0)
+ System.out.println("DEBUG: STDERR:" + org.simantics.team.Utils.bytesToStringASCII(bytes, 0, nr));
+ }
+ Thread.sleep(100);
+ } catch (InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ continue;
+ }
+ String ins = FileUtils.getContents(is);
+ if (!ins.isEmpty())
+ System.out.println("--- STDOUT ---\n" + ins);
+ String errs = FileUtils.getContents(es);
+ if (!errs.isEmpty())
+ System.out.println("--- STDERR ---\n" + errs);
+ break;
+ }
+
+ // #5849 workaround
+// xs.mergeClusterIdMap(stagingConfig.workspaceRoot.getAbsolutePath());
+
+ return new StagingResult(exitValue, logFile, null);
+ } finally {
+ faContext.ungetService(ref);
+ }
+ }
+
+ private static Set<String> startUpBundles = new HashSet<String>();
+ static {
+ //startUpBundles.add("org.eclipse.equinox.ds");
+ startUpBundles.add("org.eclipse.equinox.simpleconfigurator");
+ }
+
+ private static Set<String> startedBundles = new HashSet<String>();
+ static {
+ startedBundles.add("org.eclipse.core.runtime");
+ }
+
+ private static boolean isStartUpBundle(BundleInfo bi) {
+ return startUpBundles.contains(bi.getSymbolicName());
+ }
+
+ private static boolean isMarkedAsStarted(BundleInfo bi) {
+ // Prevent unnecessary bundles from being
+ // activated by only marking as started the plug-ins that
+ // are vital to the environment, which always have lower
+ // start level than the default 4.
+ return bi.isMarkedAsStarted() && (bi.getStartLevel() < 4 || startedBundles.contains(bi.getSymbolicName()));
+ }
+
+ private static void writeProperties(Properties properties, File target, String comment) throws IOException {
+ FileWriter writer = new FileWriter(target);
+ try {
+ properties.store(writer, comment);
+ } finally {
+ writer.close();
+ }
+ }
+
+ private static void writeFile(String string, File target) throws IOException {
+ FileWriter writer = new FileWriter(target);
+ try {
+ writer.write(string);
+ } finally {
+ writer.close();
+ }
+ }
+ static public final class StagingResult {
+
+ private final int exitValue;
+
+ private final File logFile;
+
+ private final String messageLog;
+
+ public StagingResult(String message) {
+ this.exitValue = Integer.MIN_VALUE;
+ this.logFile = null;
+ this.messageLog = message;
+ }
+ public StagingResult(int exitValue, File logFile, String messageLog) {
+ this.exitValue = exitValue;
+ this.logFile = logFile;
+ this.messageLog = messageLog;
+ }
+
+ public int getExitValue() {
+ return exitValue;
+ }
+
+ public File getLogFile() {
+ return logFile;
+ }
+
+ public String getMessageLog() {
+ return messageLog;
+ }
+
+ }
+ public static final class Config {
+ public final Session session;
+ public final Resource targetLibrary;
+ public final File workspaceRoot;
+ public final File clusterMapFolder;
+ public final File teamFolder;
+ public final PrintStream out;
+ // Outputs
+ public Resource createdModel;
+ public Resource createdState;
+ public List<String> messages = new ArrayList<String>();
+ public String titlePrefix = "Staging";
+
+ public Config(Session session, Resource library, File workspaceRoot, File clusterMapFolder)
+ throws DatabaseException {
+ this(session, library, workspaceRoot, clusterMapFolder, null);
+ }
+
+ public Config( Session session, Resource library, File workspaceRoot, File clusterMapFolder, PrintStream out)
+ throws DatabaseException {
+ this.session = session;
+ this.targetLibrary = library;
+ this.workspaceRoot = workspaceRoot;
+ this.clusterMapFolder = clusterMapFolder;
+ this.teamFolder = org.simantics.team.Utils.getTeamFolder();
+ this.out = out;
+ }
+ }
+ static final class Constants {
+
+ /**
+ * Tells the launched application to dump all its system properties into the
+ * standard output / log.
+ */
+ public static final String PROP_DUMP_PROPERTIES = "dump.properties";
+
+ /**
+ * Controls where the launched application log is written. Specified as an URI.
+ */
+ public static final String PROP_LOGFILE = "staging.logfile";
+
+ /**
+ * Prefix for the window title.
+ */
+ public static final String PROP_WINDOW_TITLE = "staging.window.title";
+
+ /**
+ * Tells the launched application where its team data comes from.
+ */
+ public static final String PROP_TEAM_FOLDER = "staging.team.folder";
+
+ /**
+ * Workspace root directory of the workbench process that launched the
+ * import process.
+ */
+ public static final String PROP_WORKSPACE_ROOT = "import.workspace.root";
+ }
+}