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