--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.ui;\r
+\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.concurrent.atomic.AtomicBoolean;\r
+\r
+import org.eclipse.ui.IWindowListener;\r
+import org.eclipse.ui.IWorkbench;\r
+import org.eclipse.ui.IWorkbenchWindow;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.management.ISessionContextProvider;\r
+import org.simantics.db.management.ISessionContextProviderSource;\r
+import org.simantics.db.management.SessionContextProvider;\r
+import org.simantics.ui.internal.SessionUtils;\r
+\r
+/**\r
+ *\r
+ */\r
+public class WorkbenchWindowSessionContextProviderSource implements ISessionContextProviderSource, IWindowListener {\r
+\r
+ private static final boolean DEBUG = false;\r
+\r
+ ISessionContextProvider[] ZERO = new ISessionContextProvider[0];\r
+\r
+ Object temporaryContext = new Object() {\r
+ @Override\r
+ public String toString() {\r
+ return "Temporary Context Object";\r
+ }\r
+ };\r
+\r
+ /**\r
+ * The set of providers associated through\r
+ * {@link #put(Object, ISessionContextProvider)} for knowing which\r
+ * associations can be removed with {@link #remove(Object)}.\r
+ */\r
+ Set<Object> manualProviders = new HashSet<Object>();\r
+\r
+ Map<Object, ISessionContextProvider> providers = new HashMap<Object, ISessionContextProvider>();\r
+\r
+ ISessionContextProvider[] allProviders = ZERO;\r
+\r
+ IWorkbenchWindow activeWindow = null;\r
+\r
+ ISessionContextProvider activeProvider = null;\r
+\r
+ AtomicBoolean isFirstWindow = new AtomicBoolean(true);\r
+\r
+ public WorkbenchWindowSessionContextProviderSource(IWorkbench workbench) {\r
+ workbench.addWindowListener(this);\r
+\r
+ // Bind the initial context provider to a temporary object.\r
+ // This binding will be replaced later on when a workbench\r
+ // window is opened.\r
+ activeProvider = new SessionContextProvider(temporaryContext);\r
+ if (DEBUG)\r
+ System.out.println("Initial active session context provider: " + activeProvider);\r
+ addProvider(temporaryContext, activeProvider);\r
+ }\r
+\r
+ @Override\r
+ public ISessionContextProvider get(Object context) {\r
+ synchronized (providers) {\r
+ return providers.get(context);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public ISessionContextProvider getActive() {\r
+ // activeWindow may be null at this time.\r
+ return activeProvider;\r
+ }\r
+\r
+ @Override\r
+ public ISessionContextProvider[] getAll() {\r
+ return allProviders;\r
+ }\r
+\r
+ @Override\r
+ public void put(Object context, ISessionContextProvider provider) {\r
+ synchronized (providers) {\r
+ ISessionContextProvider prev = providers.get(context);\r
+ if (prev != null)\r
+ throw new IllegalArgumentException("invalid context (" + context\r
+ + "), a session context provider is already associated with this context: " + prev\r
+ + ". Attempted to associate the context with this provider: " + provider);\r
+ providers.put(context, provider);\r
+ manualProviders.add(context);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public ISessionContextProvider remove(Object context) {\r
+ synchronized (providers) {\r
+ if (!manualProviders.remove(context)) {\r
+ throw new IllegalArgumentException("specified context not found: " + context);\r
+ }\r
+ return providers.remove(context);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void windowActivated(IWorkbenchWindow window) {\r
+ if (DEBUG)\r
+ System.out.println("window activated: " + window);\r
+\r
+ boolean firstActiveWindow = (activeWindow == null);\r
+ activeWindow = window;\r
+ if (firstActiveWindow) {\r
+ // activeProvider should already be set.\r
+ assert activeProvider != null;\r
+ if (DEBUG)\r
+ System.out.println(" first window activation!");\r
+ } else {\r
+ synchronized (providers) {\r
+ activeProvider = providers.get(window);\r
+ if (activeProvider == null) {\r
+ // This may be an issue, the context provider\r
+ // should already have been created through\r
+ // createContextForWindow(IWorkbenchWindow).\r
+ activeProvider = new SessionContextProvider(window);\r
+ addProvider(window, activeProvider);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void windowClosed(IWorkbenchWindow window) {\r
+ if (DEBUG)\r
+ System.out.println("window closed: " + window);\r
+ removeProvider(window);\r
+ }\r
+\r
+ @Override\r
+ public void windowDeactivated(IWorkbenchWindow window) {\r
+ if (DEBUG)\r
+ System.out.println("window deactivated: " + window);\r
+ }\r
+\r
+ @Override\r
+ public void windowOpened(IWorkbenchWindow window) {\r
+ if (DEBUG)\r
+ System.out.println("window opened: " + window + ", active window = " + activeWindow);\r
+ }\r
+\r
+ private void addProvider(Object context, ISessionContextProvider p) {\r
+ synchronized (providers) {\r
+ if (providers.put(context, p) != null) {\r
+ // This is a bug, should never happen.\r
+ throw new Error("Bug encountered, contact application support with stack trace.");\r
+ }\r
+ allProviders = providers.values().toArray(ZERO);\r
+ }\r
+ }\r
+\r
+ private void removeProvider(Object context) {\r
+ synchronized (providers) {\r
+ ISessionContextProvider provider = providers.remove(context);\r
+ if (provider == null) {\r
+ // This is a bug, should never happen.\r
+ throw new Error("Bug encountered, contact application support with stack trace.");\r
+ }\r
+ allProviders = providers.values().toArray(ZERO);\r
+\r
+ // Make sure that any session remaining in the removed context will\r
+ // be disposed of eventually.\r
+ ISessionContext ctx = provider.getSessionContext();\r
+ if (ctx != null) {\r
+ if (!SimanticsUI.isInUse(ctx)) {\r
+ SessionUtils.releaseUnusedSessionAfterHoldTime(ctx);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * This is a purely internal mechanism to allow proper creation of context\r
+ * providers for workbench windows as early as possible during the workbench\r
+ * window construction process, i.e. in the\r
+ * <code>WorkbenchWindowAdvisor.preWindowOpen()</code> instantiated\r
+ * by <code>WorkbenchAdvisor</code>.\r
+ * \r
+ * @param context\r
+ */\r
+ public void createProviderForWindow(IWorkbenchWindow context) {\r
+ synchronized (providers) {\r
+ if (isFirstWindow.compareAndSet(true, false)) {\r
+ assert activeProvider != null;\r
+ if (DEBUG)\r
+ System.out.println("[Create Context] first window: " + context);\r
+\r
+ SessionContextProvider v = (SessionContextProvider) providers.remove(temporaryContext);\r
+ if (v != null) {\r
+ v.setHandle(context);\r
+ providers.put(context, v);\r
+ if (DEBUG)\r
+ System.out.println(" rebound: '" + v + "' to '" + context + "'");\r
+ }\r
+ } else {\r
+ if (DEBUG)\r
+ System.out.println("[Create Context] new window: " + context);\r
+ // Create new session context provider\r
+ SessionContextProvider v = new SessionContextProvider(context);\r
+ ISessionContextProvider active = getActive();\r
+ if (active != null)\r
+ v.setSessionContext(active.getSessionContext());\r
+ addProvider(context, v);\r
+ }\r
+ }\r
+ }\r
+\r
+}\r