blob: da7b429b00144b3fee3bccc41fe2b20a535570a2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 SAP AG, Walldorf.
* 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:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.platform.discovery.integration.internal.plugin;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.platform.discovery.core.api.IContributedAction;
import org.eclipse.platform.discovery.core.api.ISearchConsoleMasterController;
import org.eclipse.platform.discovery.core.api.ISearchConsoleSlaveController;
import org.eclipse.platform.discovery.core.api.ISearchFavoritesMasterController;
import org.eclipse.platform.discovery.core.api.ISearchFavoritesSlaveController;
import org.eclipse.platform.discovery.core.api.ISlaveController;
import org.eclipse.platform.discovery.core.internal.IDiscoveryView;
import org.eclipse.platform.discovery.core.internal.ISearchConsoleView;
import org.eclipse.platform.discovery.core.internal.ISearchSession;
import org.eclipse.platform.discovery.core.internal.SearchConsoleController;
import org.eclipse.platform.discovery.core.internal.console.ISearchConsoleController;
import org.eclipse.platform.discovery.core.internal.console.ISearchConsoleControllerOutputView;
import org.eclipse.platform.discovery.core.internal.favorites.IPersistenceUtil;
import org.eclipse.platform.discovery.core.internal.favorites.ISearchFavoritesControllerOutputView;
import org.eclipse.platform.discovery.core.internal.favorites.SearchFavoritesContentManager;
import org.eclipse.platform.discovery.core.internal.favorites.SearchFavoritesController;
import org.eclipse.platform.discovery.core.internal.favorites.SearchFavoritesPersistenceUtil;
import org.eclipse.platform.discovery.core.internal.favorites.SearchFavoritesPersistenceUtil.IPersistenceContext;
import org.eclipse.platform.discovery.destprefs.internal.DestinationsManager;
import org.eclipse.platform.discovery.destprefs.internal.PreferenceDialogCreator;
import org.eclipse.platform.discovery.destprefs.internal.xpparser.SearchDestinationsConfiguratorXPParser;
import org.eclipse.platform.discovery.integration.internal.slavecontrollers.SlaveControllersConfiguration;
import org.eclipse.platform.discovery.integration.internal.viewcustomization.ViewCustomizationConfiguration;
import org.eclipse.platform.discovery.runtime.api.persistence.DestinationItemPair;
import org.eclipse.platform.discovery.runtime.internal.ISearchProviderConfiguration;
import org.eclipse.platform.discovery.runtime.internal.SearchProviderConfigurationFactory;
import org.eclipse.platform.discovery.runtime.internal.persistence.IMementoContentManager;
import org.eclipse.platform.discovery.runtime.internal.persistence.MementoContentManagerException;
import org.eclipse.platform.discovery.runtime.internal.persistence.util.IPersistenceProviderRegistry;
import org.eclipse.platform.discovery.ui.api.IGenericViewCustomization;
import org.eclipse.platform.discovery.ui.api.IMasterDiscoveryView;
import org.eclipse.platform.discovery.ui.api.IViewUiContext;
import org.eclipse.platform.discovery.ui.api.impl.DefaultSessionIds;
import org.eclipse.platform.discovery.ui.api.impl.ErrorHandler;
import org.eclipse.platform.discovery.ui.internal.view.ICustomizableView;
import org.eclipse.platform.discovery.ui.internal.view.SearchConsoleView;
import org.eclipse.platform.discovery.util.api.env.IDiscoveryEnvironment;
import org.eclipse.platform.discovery.util.api.env.IErrorHandler;
import org.eclipse.platform.discovery.util.api.longop.ILongOperationRunner;
import org.eclipse.platform.discovery.util.internal.logging.Logger;
import org.eclipse.platform.discovery.util.internal.longop.ModalContextLongOpRunner;
import org.eclipse.platform.discovery.util.internal.session.ISessionManager;
import org.eclipse.platform.discovery.util.internal.session.SessionManager;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.IStartup;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
/**
* The activator class controls the plug-in life cycle
*/
public class DiscoveryIntegrationPlugin extends AbstractUIPlugin implements IStartup
{
// The plug-in ID
public static final String PLUGIN_ID = "org.eclipse.platform.discovery.integration"; //$NON-NLS-1$
static final String SEARCH_CONSOLE_VIEW_ID = "org.eclipse.platform.discovery.ui.internal.view.SearchConsoleView"; //$NON-NLS-1$
static final String SEARCH_FAVORITES_VIEW_ID = "org.eclipse.platform.discovery.ui.internal.view.SearchFavoritesView"; //$NON-NLS-1$
private final static String SEARCH_FAVORITES_STORAGE_FILENAME = "searchFavoritesViewState.memento"; //$NON-NLS-1$
private volatile ISearchConsoleController consoleController;
private volatile ISearchFavoritesMasterController searchFavoritesController;
private volatile ISessionManager<ISearchSession> sessionManager = new SessionManager<ISearchSession>(new SearchSessionFactory());
private PluginPartListener openViewPartListener;
// The shared instance
private static DiscoveryIntegrationPlugin plugin;
private ISchedulingRule searchRule = new SearchScheudlingRule();
private final Set<Thread> threadTracker = new HashSet<Thread>();
/**
* The constructor
*/
public DiscoveryIntegrationPlugin()
{
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception
{
super.start(context);
plugin = this;
final Job job = new Job(DiscoveryIntegrationMessages.CONSOLE_INIT_JOB_NAME){
@Override
protected IStatus run(IProgressMonitor monitor)
{
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable()
{
public void run()
{
createControllerIfViewOpened();
createControllerOnViewOpen();
}
});
return Status.OK_STATUS;
}
};
job.schedule();
}
private void createControllerIfViewOpened()
{
final IViewReference[] viewReferences = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences();
for(IViewReference vref : viewReferences)
{
partOpenedInternal(vref);
}
}
private void createControllerOnViewOpen()
{
openViewPartListener = new PluginPartListener();
getPartService().addPartListener(openViewPartListener);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception
{
plugin = null;
super.stop(context);
final Display display = PlatformUI.getWorkbench().getDisplay();
if(display.isDisposed())
{
return;
}
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable()
{
public void run()
{
disposeController();
}
});
}
private void disposeController()
{
getPartService().removePartListener(openViewPartListener);
}
/**
* Gets the part service. It is assumed that the method is called from the UI thread.
*
* @return
*/
private IPartService getPartService()
{
return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService();
}
/**
* Returns the shared instance
*
* @return the shared instance
*/
public static DiscoveryIntegrationPlugin getDefault()
{
return plugin;
}
/**
* Returns an image descriptor for the image file at the given plug-in relative path
*
* @param path
* the path
* @return the image descriptor
*/
public static ImageDescriptor getImageDescriptor(String path)
{
return imageDescriptorFromPlugin(PLUGIN_ID, path);
}
protected synchronized ISearchConsoleController createSearchConsoleController(final ISearchConsoleControllerOutputView controllerView, final ISearchProviderConfiguration searchProviderConfig, final IDiscoveryEnvironment environment)
{
return new SearchConsoleController(searchProviderConfig, controllerView, environment, sessionManager, DefaultSessionIds.mainSearchSessionId);
}
protected ILongOperationRunner longOperationRunner(final IProgressMonitor monitor)
{
//Make sure that the thread tracker is one and the same for
//the search favorites and the search console. Otherwise what happens
//is that objects loaded by the search concole keep reference
//to the search console environment. Later on when manipulated
//by the favorites view they might get accessed from objects living
//inside the favorites environment. For example if one puts
//a an item that is not yet resolved in the favorites
//then uppon dragging and dropping from the favorites, convertion
//to xml would be triggered. This conversion would run in the
//favorites environment. However the object would start to resolve
//and it would resolve in the console environment. The resolving
//would run inside the thread triggered by the xml conversion. As
//the two activities are run by different runners, the second runner
//would know that it's already executed inside a long op activity and
//thus not in the UI thread. It would try to access the progress monitor
//which in turn would lead to Illegal thread access.
return new ModalContextLongOpRunner(monitor, searchRule)
{
@Override
protected Set<Thread> newThreadTracker() {
return threadTracker;
}
};
}
private class PluginPartListener implements IPartListener2
{
public void partActivated(IWorkbenchPartReference partRef)
{
}
public void partBroughtToTop(IWorkbenchPartReference partRef)
{
}
public void partClosed(IWorkbenchPartReference partRef)
{
if (partRef.getId().equals(SEARCH_CONSOLE_VIEW_ID))
{
consoleController = null;
}
else if(partRef.getId().equals(SEARCH_FAVORITES_VIEW_ID))
{
searchFavoritesController = null;
}
}
public void partDeactivated(IWorkbenchPartReference partRef)
{
}
public void partHidden(IWorkbenchPartReference partRef)
{
}
public void partInputChanged(IWorkbenchPartReference partRef)
{
}
public void partOpened(IWorkbenchPartReference partRef)
{
partOpenedInternal(partRef);
}
public void partVisible(IWorkbenchPartReference partRef)
{
}
}
public void earlyStartup()
{
}
protected void partOpenedInternal(final IWorkbenchPartReference partRef)
{
if(partRef.getId().equals(SEARCH_CONSOLE_VIEW_ID))
{
handleSearchConsoleViewOpened(partRef);
}
else if(partRef.getId().equals(SEARCH_FAVORITES_VIEW_ID))
{
handleSearchFavoritesViewOpened(partRef);
}
}
private void handleSearchConsoleViewOpened(final IWorkbenchPartReference partRef)
{
if(consoleController != null)
{
return;
}
final IWorkbenchPart wbPart = partRef.getPart(false);
if(wbPart != null)
{
final ISearchConsoleView consoleView = getBusinessViewFromPart(wbPart);
final ICustomizableView customizableView = getCustomizableViewFromPart(wbPart);
final IMasterDiscoveryView masterView = getMasterViewFromPart(wbPart);
final ILongOperationRunner runner = longOperationRunner(consoleView.getProgressMonitor());
final IDiscoveryEnvironment environment = createConsoleEnvironment(errorHandler(), runner, consoleView);
consoleView.setEnvironment(environment);
consoleView.setDefaultSessionId(DefaultSessionIds.mainSearchSessionId);
consoleController = createSearchConsoleController(consoleView.getControllerView(), searchProviderConfiguration(), environment);
final List<ISearchConsoleSlaveController> slaveControllers = slaveControllersConfig().availableSearchConsoleSlaveControllers();
configureSlaveControllers(consoleController, slaveControllers);
final Set<IGenericViewCustomization> viewCust = new HashSet<IGenericViewCustomization>(viewCustomizationsConfig().availableSearchConsoleCustomizations());
customizeView(customizableView, masterView, new HashSet<ISlaveController>(slaveControllers), viewCust);
consoleView.registerController(consoleController);
consoleView.setDestinationsManager(new DestinationsManager(new SearchDestinationsConfiguratorXPParser(extensionRegistry()), new PreferenceDialogCreator(), searchProviderConfiguration()));
consoleView.initializationCompleted();
}
else
{
Logger.instance().logWarn("Search console view could not be created"); //$NON-NLS-1$
}
}
private void handleSearchFavoritesViewOpened(final IWorkbenchPartReference partRef)
{
if(searchFavoritesController != null)
{
return;
}
final IWorkbenchPart wbPart = partRef.getPart(false);
if(wbPart != null)
{
final IDiscoveryView<ISearchFavoritesControllerOutputView, ISearchFavoritesMasterController> favoritesView = getSearchFavoritesViewFromPart(wbPart);
final ILongOperationRunner runner = longOperationRunner(favoritesView.getProgressMonitor());
final IDiscoveryEnvironment env = new IDiscoveryEnvironment()
{
public IErrorHandler errorHandler()
{
return DiscoveryIntegrationPlugin.this.errorHandler();
}
public ILongOperationRunner operationRunner()
{
return runner;
}
public IProgressMonitor progressMonitor()
{
return favoritesView.getProgressMonitor();
}
};
favoritesView.setEnvironment(env);
final ICustomizableView customizableView = getCustomizableViewFromPart(wbPart);
final IMasterDiscoveryView masterView = getMasterViewFromPart(wbPart);
final List<ISearchFavoritesSlaveController> slaveControllers = slaveControllersConfig().availableSearchFavoritesSlaveControllers();
final Set<IGenericViewCustomization> viewCust = new HashSet<IGenericViewCustomization>(viewCustomizationsConfig().availableSearchFavoritesCustomizations());
searchFavoritesController = createSearchFavoritesController(favoritesView.getControllerView(), env);
favoritesView.registerController(searchFavoritesController);
for(ISearchFavoritesSlaveController sc : slaveControllers)
{
sc.setMasterController(searchFavoritesController);
}
customizeView(customizableView, masterView, new HashSet<ISlaveController>(slaveControllers), viewCust);
favoritesView.initializationCompleted();
}
else
{
Logger.instance().logWarn("Search favorites view could not be created"); //$NON-NLS-1$
}
}
private void customizeView(final ICustomizableView customizableView, final IMasterDiscoveryView masterView, final Set<ISlaveController> slaveControllers, final Set<IGenericViewCustomization> viewCustomizations)
{
customizableView.setUiContext(createViewUiContext());
registerActionsInView(customizableView, slaveControllers);
configureViewCustomizations(masterView, viewCustomizations);
for(IGenericViewCustomization viewCust : viewCustomizations)
{
customizableView.registerViewCustomization(viewCust);
}
}
protected synchronized ISearchFavoritesMasterController createSearchFavoritesController(final ISearchFavoritesControllerOutputView favoritesView, final IDiscoveryEnvironment env)
{
return new SearchFavoritesController(favoritesView, env, new SearchFavoritesPersistenceUtil(createSearchFavoritesPersistenceContext()));
}
/**
* Creates a new persistence context instance which can persist objects in the search favorites view storage
*/
private IPersistenceContext<DestinationItemPair> createSearchFavoritesPersistenceContext()
{
return new IPersistenceContext<DestinationItemPair>()
{
private IMementoContentManager<DestinationItemPair> cm = null;
public IMementoContentManager<DestinationItemPair> getContentManager() throws MementoContentManagerException
{
if (cm == null)
{
cm = new SearchFavoritesContentManager(IPersistenceProviderRegistry.INSTANCE);
}
return cm;
}
public File getFile()
{
return new File(DiscoveryIntegrationPlugin.getDefault().getStateLocation().toFile(), SEARCH_FAVORITES_STORAGE_FILENAME);
}
};
}
/**
* Creates a favorites persistence util. In case the favorites view is opened, the returned util instance will delegate invocations to the view controller. Otherwise, a new util instance is created. As the favorites view can be closed or opened in the meanwhile, users are not advised to cache this instance
*
* @return
*/
public IPersistenceUtil createFavoritesPersistenceUtil()
{
final IPersistenceUtil util = new SearchFavoritesPersistenceUtil(createSearchFavoritesPersistenceContext());
if (this.searchFavoritesController != null)
{
return new IPersistenceUtil()
{
@Override
public void addItems(final Set<DestinationItemPair> itemsToAdd, final ILongOperationRunner opRunner) throws WorkbenchException, IOException, MementoContentManagerException
{
searchFavoritesController.importData(itemsToAdd.toArray(new DestinationItemPair[itemsToAdd.size()]));
}
@Override
public void deleteItems(final Set<Object> itemsToDelete, final ILongOperationRunner opRunner) throws WorkbenchException, IOException, MementoContentManagerException
{
searchFavoritesController.deleteItems(itemsToDelete);
}
@Override
public Set<DestinationItemPair> loadItems(final ILongOperationRunner opRunner) throws WorkbenchException, IOException, MementoContentManagerException
{
return util.loadItems(opRunner);
}
};
}
return util;
}
private void configureViewCustomizations(final IMasterDiscoveryView masterView, final Set<IGenericViewCustomization> viewCustomizations)
{
for(IGenericViewCustomization cust : viewCustomizations)
{
cust.setMasterView(masterView);
}
}
private void configureSlaveControllers(final ISearchConsoleMasterController masterController, final List<ISearchConsoleSlaveController> slaveControllers)
{
for(ISearchConsoleSlaveController slave : slaveControllers)
{
slave.setMasterController(masterController);
}
}
protected ISearchConsoleView getBusinessViewFromPart(final IWorkbenchPart part)
{
return (ISearchConsoleView) part;
}
@SuppressWarnings("unchecked")
protected IDiscoveryView<ISearchFavoritesControllerOutputView, ISearchFavoritesMasterController> getSearchFavoritesViewFromPart(final IWorkbenchPart part)
{
return (IDiscoveryView<ISearchFavoritesControllerOutputView, ISearchFavoritesMasterController>) part;
}
protected ICustomizableView getCustomizableViewFromPart(final IWorkbenchPart part)
{
return (ICustomizableView) part;
}
protected IMasterDiscoveryView getMasterViewFromPart(final IWorkbenchPart wbPart)
{
return (IMasterDiscoveryView)wbPart;
}
private void registerActionsInView(final ICustomizableView customizableView, final Set<ISlaveController> slaveControllers)
{
for (ISlaveController slave : slaveControllers)
{
for (final IContributedAction singleAction : slave.createActions())
{
customizableView.registerAction(singleAction);
}
}
}
private ISearchProviderConfiguration searchProviderConfiguration()
{
return new SearchProviderConfigurationFactory().getSearchProviderConfiguration(extensionRegistry());
}
private IExtensionRegistry extensionRegistry() {
return Platform.getExtensionRegistry();
}
private IErrorHandler errorHandler()
{
return new ErrorHandler();
}
protected ISlaveControllersConfiguration slaveControllersConfig()
{
return new SlaveControllersConfiguration();
}
protected IViewCustomizationConfiguration viewCustomizationsConfig()
{
return new ViewCustomizationConfiguration();
}
private class SearchScheudlingRule implements ISchedulingRule
{
public boolean contains(ISchedulingRule rule) {
return rule == this;
}
public boolean isConflicting(ISchedulingRule rule) {
return rule == this;
}
}
private IDiscoveryEnvironment createConsoleEnvironment(final IErrorHandler errorHandler, final ILongOperationRunner opRunner, final ISearchConsoleView explView)
{
return new IDiscoveryEnvironment()
{
public IErrorHandler errorHandler()
{
return errorHandler;
}
public ILongOperationRunner operationRunner()
{
return opRunner;
}
public IProgressMonitor progressMonitor()
{
return explView.getProgressMonitor();
}
};
}
private IViewUiContext createViewUiContext()
{
return new IViewUiContext()
{
private int secondCPosition;
@Override
public int controlsSpacing()
{
return SearchConsoleView.UI_IN_CONTROL_SPACING;
}
@Override
public int getSecondColumnPosition()
{
return this.secondCPosition;
}
@Override
public void setSecondColumnPosition(final int position)
{
secondCPosition = position;
}
};
}
}