1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.ui;
\r
14 import java.util.HashMap;
\r
15 import java.util.HashSet;
\r
16 import java.util.Map;
\r
17 import java.util.Set;
\r
18 import java.util.concurrent.atomic.AtomicBoolean;
\r
20 import org.eclipse.ui.IWindowListener;
\r
21 import org.eclipse.ui.IWorkbench;
\r
22 import org.eclipse.ui.IWorkbenchWindow;
\r
23 import org.simantics.db.management.ISessionContext;
\r
24 import org.simantics.db.management.ISessionContextProvider;
\r
25 import org.simantics.db.management.ISessionContextProviderSource;
\r
26 import org.simantics.db.management.SessionContextProvider;
\r
27 import org.simantics.ui.internal.SessionUtils;
\r
32 public class WorkbenchWindowSessionContextProviderSource implements ISessionContextProviderSource, IWindowListener {
\r
34 private static final boolean DEBUG = false;
\r
36 ISessionContextProvider[] ZERO = new ISessionContextProvider[0];
\r
38 Object temporaryContext = new Object() {
\r
40 public String toString() {
\r
41 return "Temporary Context Object";
\r
46 * The set of providers associated through
\r
47 * {@link #put(Object, ISessionContextProvider)} for knowing which
\r
48 * associations can be removed with {@link #remove(Object)}.
\r
50 Set<Object> manualProviders = new HashSet<Object>();
\r
52 Map<Object, ISessionContextProvider> providers = new HashMap<Object, ISessionContextProvider>();
\r
54 ISessionContextProvider[] allProviders = ZERO;
\r
56 IWorkbenchWindow activeWindow = null;
\r
58 ISessionContextProvider activeProvider = null;
\r
60 AtomicBoolean isFirstWindow = new AtomicBoolean(true);
\r
62 public WorkbenchWindowSessionContextProviderSource(IWorkbench workbench) {
\r
63 workbench.addWindowListener(this);
\r
65 // Bind the initial context provider to a temporary object.
\r
66 // This binding will be replaced later on when a workbench
\r
67 // window is opened.
\r
68 activeProvider = new SessionContextProvider(temporaryContext);
\r
70 System.out.println("Initial active session context provider: " + activeProvider);
\r
71 addProvider(temporaryContext, activeProvider);
\r
75 public ISessionContextProvider get(Object context) {
\r
76 synchronized (providers) {
\r
77 return providers.get(context);
\r
82 public ISessionContextProvider getActive() {
\r
83 // activeWindow may be null at this time.
\r
84 return activeProvider;
\r
88 public ISessionContextProvider[] getAll() {
\r
89 return allProviders;
\r
93 public void put(Object context, ISessionContextProvider provider) {
\r
94 synchronized (providers) {
\r
95 ISessionContextProvider prev = providers.get(context);
\r
97 throw new IllegalArgumentException("invalid context (" + context
\r
98 + "), a session context provider is already associated with this context: " + prev
\r
99 + ". Attempted to associate the context with this provider: " + provider);
\r
100 providers.put(context, provider);
\r
101 manualProviders.add(context);
\r
106 public ISessionContextProvider remove(Object context) {
\r
107 synchronized (providers) {
\r
108 if (!manualProviders.remove(context)) {
\r
109 throw new IllegalArgumentException("specified context not found: " + context);
\r
111 return providers.remove(context);
\r
116 public void windowActivated(IWorkbenchWindow window) {
\r
118 System.out.println("window activated: " + window);
\r
120 boolean firstActiveWindow = (activeWindow == null);
\r
121 activeWindow = window;
\r
122 if (firstActiveWindow) {
\r
123 // activeProvider should already be set.
\r
124 assert activeProvider != null;
\r
126 System.out.println(" first window activation!");
\r
128 synchronized (providers) {
\r
129 activeProvider = providers.get(window);
\r
130 if (activeProvider == null) {
\r
131 // This may be an issue, the context provider
\r
132 // should already have been created through
\r
133 // createContextForWindow(IWorkbenchWindow).
\r
134 activeProvider = new SessionContextProvider(window);
\r
135 addProvider(window, activeProvider);
\r
142 public void windowClosed(IWorkbenchWindow window) {
\r
144 System.out.println("window closed: " + window);
\r
145 removeProvider(window);
\r
149 public void windowDeactivated(IWorkbenchWindow window) {
\r
151 System.out.println("window deactivated: " + window);
\r
155 public void windowOpened(IWorkbenchWindow window) {
\r
157 System.out.println("window opened: " + window + ", active window = " + activeWindow);
\r
160 private void addProvider(Object context, ISessionContextProvider p) {
\r
161 synchronized (providers) {
\r
162 if (providers.put(context, p) != null) {
\r
163 // This is a bug, should never happen.
\r
164 throw new Error("Bug encountered, contact application support with stack trace.");
\r
166 allProviders = providers.values().toArray(ZERO);
\r
170 private void removeProvider(Object context) {
\r
171 synchronized (providers) {
\r
172 ISessionContextProvider provider = providers.remove(context);
\r
173 if (provider == null) {
\r
174 // This is a bug, should never happen.
\r
175 throw new Error("Bug encountered, contact application support with stack trace.");
\r
177 allProviders = providers.values().toArray(ZERO);
\r
179 // Make sure that any session remaining in the removed context will
\r
180 // be disposed of eventually.
\r
181 ISessionContext ctx = provider.getSessionContext();
\r
183 if (!SimanticsUI.isInUse(ctx)) {
\r
184 SessionUtils.releaseUnusedSessionAfterHoldTime(ctx);
\r
191 * This is a purely internal mechanism to allow proper creation of context
\r
192 * providers for workbench windows as early as possible during the workbench
\r
193 * window construction process, i.e. in the
\r
194 * <code>WorkbenchWindowAdvisor.preWindowOpen()</code> instantiated
\r
195 * by <code>WorkbenchAdvisor</code>.
\r
199 public void createProviderForWindow(IWorkbenchWindow context) {
\r
200 synchronized (providers) {
\r
201 if (isFirstWindow.compareAndSet(true, false)) {
\r
202 assert activeProvider != null;
\r
204 System.out.println("[Create Context] first window: " + context);
\r
206 SessionContextProvider v = (SessionContextProvider) providers.remove(temporaryContext);
\r
208 v.setHandle(context);
\r
209 providers.put(context, v);
\r
211 System.out.println(" rebound: '" + v + "' to '" + context + "'");
\r
215 System.out.println("[Create Context] new window: " + context);
\r
216 // Create new session context provider
\r
217 SessionContextProvider v = new SessionContextProvider(context);
\r
218 ISessionContextProvider active = getActive();
\r
219 if (active != null)
\r
220 v.setSessionContext(active.getSessionContext());
\r
221 addProvider(context, v);
\r