[Bug 396928] Destinations preference page
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/META-INF/MANIFEST.MF b/bundles/org.eclipse.platform.discovery.destprefs/META-INF/MANIFEST.MF
index b10dc2f..942c52b 100644
--- a/bundles/org.eclipse.platform.discovery.destprefs/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.platform.discovery.destprefs/META-INF/MANIFEST.MF
@@ -9,7 +9,9 @@
 Bundle-ActivationPolicy: lazy
 Export-Package: org.eclipse.platform.discovery.destprefs.api,
  org.eclipse.platform.discovery.destprefs.internal,
+ org.eclipse.platform.discovery.destprefs.internal.i18n,
  org.eclipse.platform.discovery.destprefs.internal.prefpage.ui,
+ org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.nodes,
  org.eclipse.platform.discovery.destprefs.internal.xpparser
 Require-Bundle: org.eclipse.ui,
  org.eclipse.core.runtime,
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/plugin.xml b/bundles/org.eclipse.platform.discovery.destprefs/plugin.xml
index f4ba31b..6b423a7 100644
--- a/bundles/org.eclipse.platform.discovery.destprefs/plugin.xml
+++ b/bundles/org.eclipse.platform.discovery.destprefs/plugin.xml
Binary files differ
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/i18n/DestPrefsMessages.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/i18n/DestPrefsMessages.java
new file mode 100644
index 0000000..50099ae
--- /dev/null
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/i18n/DestPrefsMessages.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG and others.
+ * 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.destprefs.internal.i18n;
+
+import org.eclipse.osgi.util.NLS;
+
+public class DestPrefsMessages extends NLS {
+    private static final String BUNDLE_NAME = "org.eclipse.platform.discovery.destprefs.internal.i18n.DestPrefsMessages";
+    static {
+        NLS.initializeMessages(BUNDLE_NAME, DestPrefsMessages.class);
+    }
+    
+    public static String DestinationsPrefPage_AddButton;
+    public static String DestinationsPrefPage_EditButton;
+    public static String DestinationsPrefPage_DeleteButton;
+    public static String DestinationsPrefPage_TestButton;
+}
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/i18n/DestPrefsMessages.properties b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/i18n/DestPrefsMessages.properties
new file mode 100644
index 0000000..1e9c408
--- /dev/null
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/i18n/DestPrefsMessages.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2012 SAP AG and others.
+# 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
+###############################################################################
+DestinationsPrefPage_AddButton = Add
+DestinationsPrefPage_EditButton = Edit
+DestinationsPrefPage_DeleteButton = Delete
+DestinationsPrefPage_TestButton = Test
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/CategoryDestinationProviderPair.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/CategoryDestinationProviderPair.java
index 2afbee2..c094386 100644
--- a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/CategoryDestinationProviderPair.java
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/CategoryDestinationProviderPair.java
@@ -1,3 +1,13 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG and others.
+ * 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.destprefs.internal.prefpage.ui;
 
 import org.eclipse.platform.discovery.runtime.internal.model.descriptions.IDestinationCategoryDescription;
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/CategoryDestinationsContentProvider.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/CategoryDestinationsContentProvider.java
new file mode 100644
index 0000000..b92c5b6
--- /dev/null
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/CategoryDestinationsContentProvider.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG and others.
+ * 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.destprefs.internal.prefpage.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.nodes.CategoryNode;
+
+public class CategoryDestinationsContentProvider implements ITreeContentProvider {
+
+    private final List<CategoryDestinationProviderPair> categoryDestinationPairs;
+
+    public CategoryDestinationsContentProvider() {
+        this.categoryDestinationPairs = new ArrayList<CategoryDestinationProviderPair>();
+    }
+
+    @Override
+    public void dispose() {
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+        categoryDestinationPairs.clear();
+
+        if (newInput != null) {
+            assert (newInput instanceof List);
+            categoryDestinationPairs.addAll((List<CategoryDestinationProviderPair>) newInput);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object[] getElements(Object inputElement) {
+        final List<CategoryNode> categoryNodes = new ArrayList<CategoryNode>();
+        
+        final List<CategoryDestinationProviderPair> pairs = (List<CategoryDestinationProviderPair>) inputElement;
+        for (CategoryDestinationProviderPair categDescPair : pairs) {
+            CategoryNode node = new CategoryNode(categDescPair.category.getDisplayName(), categDescPair.destinationProvider);
+            categoryNodes.add(node);
+        }
+        
+        return categoryNodes.toArray();
+    }
+
+    @Override
+    public Object[] getChildren(Object parentElement) {
+        final CategoryNode categoryNode  = (CategoryNode) parentElement;
+        return categoryNode.getDestinations().toArray();
+    }
+
+    @Override
+    public Object getParent(Object element) {
+        return null;
+    }
+
+    @Override
+    public boolean hasChildren(Object element) {
+        if(element instanceof CategoryNode) {
+            return ((CategoryNode)element).getDestinationsCount() > 0;
+        }
+        return false;
+    }
+
+}
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationConfiguratorSelection.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationConfiguratorSelection.java
index 1124b72..7b6c191 100644
--- a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationConfiguratorSelection.java
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationConfiguratorSelection.java
@@ -1,3 +1,13 @@
+/*******************************************************************************

+ * Copyright (c) 2012 SAP AG and others.

+ * 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.destprefs.internal.prefpage.ui;

 

 import org.eclipse.platform.discovery.runtime.api.ISearchDestination;

diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationConfiguratorsPresenter.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationConfiguratorsPresenter.java
index 545ead7..32dc6b2 100644
--- a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationConfiguratorsPresenter.java
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationConfiguratorsPresenter.java
@@ -1,3 +1,13 @@
+/*******************************************************************************

+ * Copyright (c) 2012 SAP AG and others.

+ * 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.destprefs.internal.prefpage.ui;

 

 import java.util.ArrayList;

diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationsLabelProvider.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationsLabelProvider.java
new file mode 100644
index 0000000..17c5aa4
--- /dev/null
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationsLabelProvider.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 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.destprefs.internal.prefpage.ui;
+
+import org.eclipse.jface.viewers.StyledCellLabelProvider;
+import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.nodes.CategoryNode;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.nodes.DestinationNode;
+
+public class DestinationsLabelProvider extends StyledCellLabelProvider {
+    @Override
+    public void update(ViewerCell cell) {
+        Object object = cell.getElement();
+        StyledString styledString = (object instanceof CategoryNode ? getCategoryNodeText((CategoryNode)object) : getDestinationNodeText((DestinationNode)object));
+        cell.setText(styledString.toString());
+        cell.setStyleRanges(styledString.getStyleRanges());
+        super.update(cell);
+    }
+
+    private StyledString getDestinationNodeText(DestinationNode destination) {
+        return new StyledString(destination.getDestination().getDisplayName());
+    }
+
+    private StyledString getCategoryNodeText(CategoryNode category) {
+        StyledString styledString = new StyledString(category.getDisplayName());
+        styledString.append(" (" + category.getDestinationsCount() + ")", StyledString.COUNTER_STYLER);
+        return styledString;
+    }
+}
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationsPreferencePage.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationsPreferencePage.java
new file mode 100644
index 0000000..5bc1e43
--- /dev/null
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/DestinationsPreferencePage.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG and others.
+ * 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.destprefs.internal.prefpage.ui;
+
+import java.util.Collection;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.platform.discovery.destprefs.internal.i18n.DestPrefsMessages;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.nodes.CategoryNode;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.nodes.DestinationNode;
+import org.eclipse.platform.discovery.destprefs.internal.xpparser.SearchDestinationsConfiguratorXPParser;
+import org.eclipse.platform.discovery.runtime.internal.SearchProviderConfigurationFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+public class DestinationsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, IDestinationConfiguratorsView {
+    private final IDestinationConfiguratorsPresenter presenter;
+    private TreeViewer destinationsTreeViewer;
+    private Button addDestinationButton;
+    private Button removeDestinationButton;
+    private Button deleteDestinationButton;
+    private Button testDestinationButton;
+
+    public DestinationsPreferencePage(final IDestinationConfiguratorsPresenter presenter) {
+        this.presenter = presenter;
+    }
+
+    public DestinationsPreferencePage() {
+        this(new DestinationConfiguratorsPresenter(new SearchDestinationsConfiguratorXPParser(Platform.getExtensionRegistry()), SearchProviderConfigurationFactory.getDefault()));
+    }
+
+    @Override
+    public void init(IWorkbench workbench) {
+        noDefaultAndApplyButton();
+        this.presenter.setView(this);
+    }
+
+    @Override
+    protected Control createContents(final Composite parent) {
+        final Composite parentComposite = new Composite(parent, SWT.NONE);
+        parentComposite.setLayout(new GridLayout(2, false));
+        final Composite treeViewerComposite = new Composite(parentComposite, SWT.NONE);
+        treeViewerComposite.setLayout(new FillLayout(SWT.VERTICAL));
+        GridDataFactory.defaultsFor(treeViewerComposite).align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(treeViewerComposite);
+        destinationsTreeViewer = createDestinationsTreeViewer(treeViewerComposite);
+
+        final Composite buttonsComposite = new Composite(parentComposite, SWT.NONE);
+        buttonsComposite.setLayout(new GridLayout(1, true));
+        GridDataFactory.defaultsFor(buttonsComposite).align(SWT.END, SWT.FILL).grab(false, true).applyTo(buttonsComposite);
+        addDestinationButton = createAddDestinationButton(buttonsComposite);
+        removeDestinationButton = createEditDestinationButton(buttonsComposite);
+        deleteDestinationButton = createDeleteDestinationButton(buttonsComposite);
+        testDestinationButton = createTestDestinationButton(buttonsComposite);
+
+        return parentComposite;
+    }
+
+    private TreeViewer createDestinationsTreeViewer(final Composite parent) {
+        final TreeViewer viewer = new TreeViewer(parent, SWT.SINGLE | SWT.BORDER);
+        viewer.addSelectionChangedListener(destinationsSelectionChangeListener());
+        viewer.setLabelProvider(new DestinationsLabelProvider());
+        viewer.setContentProvider(new CategoryDestinationsContentProvider());
+        return viewer;
+    }
+
+    private ISelectionChangedListener destinationsSelectionChangeListener() {
+        return new ISelectionChangedListener() {
+            @Override
+            public void selectionChanged(final SelectionChangedEvent event) {
+                if (event.getSelection().isEmpty()) {
+                    return;
+                }
+
+                final Object selectedElement = ((StructuredSelection) event.getSelection()).getFirstElement();
+                if (selectedElement instanceof CategoryNode) {
+                    presenter.selectionChanged(new DestinationConfiguratorSelection(((CategoryNode) selectedElement).getDestinationProviderId(), null));
+                }
+                if (selectedElement instanceof DestinationNode) {
+                    final DestinationNode destNode = (DestinationNode)selectedElement;
+                    presenter.selectionChanged(new DestinationConfiguratorSelection(destNode.getParentNode().getDestinationProviderId(), destNode.getDestination()));
+                }
+                throw new IllegalArgumentException("Unsupported element: " + selectedElement);
+            }
+        };
+    }
+
+    private Button createAddDestinationButton(final Composite parent) {
+        final Button button = createDisabledButton(parent, DestPrefsMessages.DestinationsPrefPage_AddButton);
+        button.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                presenter.addDestination();
+            }
+        });
+        return button;
+    }
+
+    private Button createEditDestinationButton(final Composite parent) {
+        final Button button = createDisabledButton(parent, DestPrefsMessages.DestinationsPrefPage_EditButton);
+        button.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                presenter.editDestination();
+            }
+        });
+        return button;
+    }
+
+    private Button createDeleteDestinationButton(final Composite parent) {
+        final Button button = createDisabledButton(parent, DestPrefsMessages.DestinationsPrefPage_DeleteButton);
+        button.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                presenter.removeDestination();
+            }
+        });
+        return button;
+    }
+
+    private Button createTestDestinationButton(final Composite parent) {
+        final Button button = createDisabledButton(parent, DestPrefsMessages.DestinationsPrefPage_TestButton);
+        button.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                presenter.testDestination();
+            }
+        });
+        return button;
+    }
+
+    private Button createDisabledButton(final Composite parent, final String label) {
+        final Button button = new Button(parent, SWT.PUSH);
+        button.setText(label);
+        GridDataFactory.defaultsFor(button).applyTo(button);
+        button.setEnabled(false);
+        return button;
+    }
+
+    @Override
+    public void setInput(Collection<CategoryDestinationProviderPair> input) {
+        destinationsTreeViewer.setInput(input);
+    }
+
+    @Override
+    public void setStatus(IStatus status) {
+        this.setMessage(status.getMessage(), StatusSeverityToMessageTypeAdapter.messageTypeFor(status));
+    }
+
+    @Override
+    public void setAddEnabled(boolean enabled) {
+        this.addDestinationButton.setEnabled(enabled);
+    }
+
+    @Override
+    public void setEditEnabled(boolean enabled) {
+        this.removeDestinationButton.setEnabled(enabled);
+    }
+
+    @Override
+    public void setRemoveEnabled(boolean enabled) {
+        this.deleteDestinationButton.setEnabled(enabled);
+    }
+
+    @Override
+    public void setTestEnabled(boolean enabled) {
+        this.testDestinationButton.setEnabled(enabled);
+    }
+
+    private static class StatusSeverityToMessageTypeAdapter {
+        static int messageTypeFor(final IStatus status) {
+            switch (status.getSeverity()) {
+            case IStatus.ERROR:
+                return IMessageProvider.ERROR;
+
+            case IStatus.WARNING:
+                return IMessageProvider.WARNING;
+            default:
+                return IMessageProvider.INFORMATION;
+            }
+        }
+    }
+}
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/IDestinationConfiguratorsPresenter.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/IDestinationConfiguratorsPresenter.java
index 6a1cfc0..8853523 100644
--- a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/IDestinationConfiguratorsPresenter.java
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/IDestinationConfiguratorsPresenter.java
@@ -1,3 +1,13 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG and others.
+ * 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.destprefs.internal.prefpage.ui;
 
 import org.eclipse.platform.discovery.runtime.api.ISearchDestination;
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/IDestinationConfiguratorsView.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/IDestinationConfiguratorsView.java
index ee74c57..8be1926 100644
--- a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/IDestinationConfiguratorsView.java
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/IDestinationConfiguratorsView.java
@@ -1,3 +1,13 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG and others.
+ * 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.destprefs.internal.prefpage.ui;
 
 import java.util.Collection;
diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/nodes/CategoryNode.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/nodes/CategoryNode.java
new file mode 100644
index 0000000..dba429f
--- /dev/null
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/nodes/CategoryNode.java
@@ -0,0 +1,54 @@
+/*******************************************************************************

+ * Copyright (c) 2012 SAP AG and others.

+ * 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.destprefs.internal.prefpage.ui.nodes;

+

+import java.util.ArrayList;

+import java.util.List;

+import java.util.Set;

+

+import org.eclipse.platform.discovery.runtime.api.ISearchDestination;

+import org.eclipse.platform.discovery.runtime.internal.model.descriptions.IDestinationsProviderDescription;

+

+public class CategoryNode {

+

+	private final String displayName;

+	private final Set<ISearchDestination> destinations;

+	private final IDestinationsProviderDescription destinationProvider;

+

+	public CategoryNode(String displayName, IDestinationsProviderDescription destinationProvider) {

+		this.displayName = displayName;

+		this.destinations = destinationProvider.createProvider().getSearchDestinations();

+		this.destinationProvider = destinationProvider;

+	}

+

+	public List<DestinationNode> getDestinations() {

+		final List<DestinationNode> result = new ArrayList<DestinationNode>();

+		

+		for (ISearchDestination destination : destinations) {

+			DestinationNode destinationNode = new DestinationNode(this, destination);

+			result.add(destinationNode);

+		}

+		

+		return result;

+	}

+	

+	public int getDestinationsCount() {

+		return this.destinations.size();

+	}

+	

+	public String getDisplayName() {

+		return this.displayName;

+	}

+

+    public String getDestinationProviderId() {

+        return destinationProvider.getId();

+    }

+}

diff --git a/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/nodes/DestinationNode.java b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/nodes/DestinationNode.java
new file mode 100644
index 0000000..5565d48
--- /dev/null
+++ b/bundles/org.eclipse.platform.discovery.destprefs/src/org/eclipse/platform/discovery/destprefs/internal/prefpage/ui/nodes/DestinationNode.java
@@ -0,0 +1,33 @@
+/*******************************************************************************

+ * Copyright (c) 2012 SAP AG and others.

+ * 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.destprefs.internal.prefpage.ui.nodes;

+

+import org.eclipse.platform.discovery.runtime.api.ISearchDestination;

+

+public class DestinationNode {

+

+	private final CategoryNode parentNode;

+	private final ISearchDestination destination;

+	

+	public DestinationNode(CategoryNode parentNode, ISearchDestination destination) {

+		this.parentNode = parentNode;

+		this.destination = destination;

+	}

+	

+	public ISearchDestination getDestination() {

+		return this.destination;

+	}

+	

+	public CategoryNode getParentNode() {

+		return this.parentNode;

+	}

+	

+}

diff --git a/bundles/org.eclipse.platform.discovery.ui/src/org/eclipse/platform/discovery/ui/internal/view/SearchConsoleView.java b/bundles/org.eclipse.platform.discovery.ui/src/org/eclipse/platform/discovery/ui/internal/view/SearchConsoleView.java
index de70f8c..b79a83f 100644
--- a/bundles/org.eclipse.platform.discovery.ui/src/org/eclipse/platform/discovery/ui/internal/view/SearchConsoleView.java
+++ b/bundles/org.eclipse.platform.discovery.ui/src/org/eclipse/platform/discovery/ui/internal/view/SearchConsoleView.java
@@ -280,10 +280,12 @@
 		manageConfigurationHyperlink.setCursor(hyperlinkCursor);

 		

 		final List<String> prefPageIDs = new LinkedList<String>(); 

-

-		for (IDestinationsProviderDescription provider : this.getSearchProviderConfiguration().getAvailableDestinationProviders())

-			if (provider.getPreferencePageId()!=null)

-				prefPageIDs.add(provider.getPreferencePageId());

+		prefPageIDs.add("org.eclipse.platform.discovery.destprefs.preferencepage");

+		for (IDestinationsProviderDescription provider : this.getSearchProviderConfiguration().getAvailableDestinationProviders()) {

+			if (provider.getPreferencePageId()!=null) {

+				prefPageIDs.add(provider.getPreferencePageId());
+			}
+		}

 		

 		manageConfigurationHyperlink.addHyperlinkListener(new IHyperlinkListener()

 		{

diff --git a/tests/org.eclipse.platform.discovery.destprefs.test.unit/META-INF/MANIFEST.MF b/tests/org.eclipse.platform.discovery.destprefs.test.unit/META-INF/MANIFEST.MF
index 71666c9..901003b 100644
--- a/tests/org.eclipse.platform.discovery.destprefs.test.unit/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.platform.discovery.destprefs.test.unit/META-INF/MANIFEST.MF
@@ -6,6 +6,8 @@
 Bundle-Vendor: %Bundle-Vendor
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Export-Package: org.eclipse.platform.discovery.destprefs.test.unit,
+ org.eclipse.platform.discovery.destprefs.test.unit.prefpage,
+ org.eclipse.platform.discovery.destprefs.test.unit.prefpage.ui,
  org.eclipse.platform.discovery.destprefs.test.unit.xpparser
 Require-Bundle: org.junit,
  org.eclipse.platform.discovery.destprefs,
@@ -15,5 +17,6 @@
  org.eclipse.platform.discovery.runtime,
  org.eclipse.core.runtime,
  org.eclipse.platform.discovery.util,
- org.eclipse.ui
- 
+ org.eclipse.ui,
+ org.eclipse.ui.forms,
+ org.eclipse.swtbot.eclipse.finder
diff --git a/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/SearchConfiguratorsFixture.java b/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/SearchConfiguratorsFixture.java
index ce62534..70e49af 100644
--- a/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/SearchConfiguratorsFixture.java
+++ b/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/SearchConfiguratorsFixture.java
@@ -1,3 +1,13 @@
+/*******************************************************************************

+ * Copyright (c) 2012 SAP AG and others.

+ * 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.destprefs.test.unit;

 

 import java.util.ArrayList;

diff --git a/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/DestinationConfiguratorsPresenterTest.java b/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/DestinationConfiguratorsPresenterTest.java
index afb56ea..3c487a9 100644
--- a/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/DestinationConfiguratorsPresenterTest.java
+++ b/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/DestinationConfiguratorsPresenterTest.java
@@ -1,3 +1,13 @@
+/*******************************************************************************

+ * Copyright (c) 2012 SAP AG and others.

+ * 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.destprefs.test.unit.prefpage;

 

 import java.util.ArrayList;

diff --git a/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/ui/CategoryDestinationsContentProviderTest.java b/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/ui/CategoryDestinationsContentProviderTest.java
new file mode 100644
index 0000000..ca14b1f
--- /dev/null
+++ b/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/ui/CategoryDestinationsContentProviderTest.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG and others.
+ * 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.destprefs.test.unit.prefpage.ui;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.CategoryDestinationProviderPair;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.CategoryDestinationsContentProvider;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.nodes.CategoryNode;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.nodes.DestinationNode;
+import org.eclipse.platform.discovery.runtime.api.IDestinationsProvider;
+import org.eclipse.platform.discovery.runtime.api.ISearchDestination;
+import org.eclipse.platform.discovery.runtime.internal.model.descriptions.IDestinationCategoryDescription;
+import org.eclipse.platform.discovery.runtime.internal.model.descriptions.IDestinationsProviderDescription;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+public class CategoryDestinationsContentProviderTest {
+
+    private CategoryDestinationsContentProvider contentProvider;
+
+    @Mock private ISearchDestination DESTINATION_1;
+    @Mock private ISearchDestination DESTINATION_2;
+    @Mock private ISearchDestination DESTINATION_3;
+    private final static String DESTINATION_NAME_1 = "First destination";
+    private final static String DESTINATION_NAME_2 = "Second destination";
+    private final static String DESTINATION_NAME_3 = "Third destination";
+
+    @Mock private IDestinationCategoryDescription CATEGORY_1;
+    @Mock private IDestinationCategoryDescription CATEGORY_2;
+    private final static String CATEGORY_NAME_1 = "First category";
+    private final static String CATEGORY_NAME_2 = "Second category";
+
+    @Mock private IDestinationsProviderDescription DESTINATION_PROVIDER_1;
+    @Mock private IDestinationsProviderDescription DESTINATION_PROVIDER_2;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        setupSearchDestinations();
+        setupDestinationProviders();
+        setupCategories();
+
+        contentProvider = new CategoryDestinationsContentProvider();
+    }
+
+    private void setupSearchDestinations() {
+        Mockito.when(DESTINATION_1.getDisplayName()).thenReturn(DESTINATION_NAME_1);
+        Mockito.when(DESTINATION_2.getDisplayName()).thenReturn(DESTINATION_NAME_2);
+        Mockito.when(DESTINATION_3.getDisplayName()).thenReturn(DESTINATION_NAME_3);
+    }
+
+    private void setupCategories() {
+        Mockito.when(CATEGORY_1.getDisplayName()).thenReturn(CATEGORY_NAME_1);
+        Mockito.when(CATEGORY_2.getDisplayName()).thenReturn(CATEGORY_NAME_2);
+    }
+    
+    private void setupDestinationProviders() {
+        final Set<ISearchDestination> destinations1 = new HashSet<ISearchDestination>();
+        destinations1.add(DESTINATION_1);
+        destinations1.add(DESTINATION_2);
+
+        final Set<ISearchDestination> destinations2 = new HashSet<ISearchDestination>();
+        destinations2.add(DESTINATION_3);
+        
+        final IDestinationsProvider provider1 = Mockito.mock(IDestinationsProvider.class);
+        Mockito.when(provider1.getSearchDestinations()).thenReturn(destinations1);
+        final IDestinationsProvider provider2 = Mockito.mock(IDestinationsProvider.class);
+        Mockito.when(provider2.getSearchDestinations()).thenReturn(destinations2);
+        
+        Mockito.when(DESTINATION_PROVIDER_1.createProvider()).thenReturn(provider1);
+        Mockito.when(DESTINATION_PROVIDER_2.createProvider()).thenReturn(provider2);
+    }
+
+    @Test
+    public void testGetElements() {
+        final CategoryDestinationProviderPair categDescPair_1 = new CategoryDestinationProviderPair(CATEGORY_1, DESTINATION_PROVIDER_1);
+        final CategoryDestinationProviderPair categDescPair_2 = new CategoryDestinationProviderPair(CATEGORY_2, DESTINATION_PROVIDER_2);
+        
+        final List<CategoryDestinationProviderPair> pairs = Arrays.asList(new CategoryDestinationProviderPair[] { categDescPair_1,
+                categDescPair_2 });
+        final Object[] elements = contentProvider.getElements(pairs);
+        assertEquals("Two elements expected", 2, elements.length);
+        final List<String> elementDisplayNames = new ArrayList<String>();
+        for (Object object : elements) {
+            elementDisplayNames.add(((CategoryNode) object).getDisplayName());
+        }
+
+        assertTrue("Category 1 expected to be contained in the result", elementDisplayNames.contains(CATEGORY_NAME_1));
+        assertTrue("Category 2 expected to be contained in the result", elementDisplayNames.contains(CATEGORY_NAME_2));
+    }
+    
+    @Test
+    public void testHasChildren() {
+        final CategoryNode categoryNode = new CategoryNode(CATEGORY_NAME_1, DESTINATION_PROVIDER_1);
+        final DestinationNode destinationNode = new DestinationNode(categoryNode, DESTINATION_1);
+        
+        assertTrue("Children expected for category node", contentProvider.hasChildren(categoryNode));
+        assertFalse("No children expected for destination node", contentProvider.hasChildren(destinationNode));
+    }
+    
+    @Test
+    public void testGetChildren() {
+        final CategoryNode categoryNode1 = new CategoryNode(CATEGORY_NAME_1, DESTINATION_PROVIDER_1);
+        final CategoryNode categoryNode2 = new CategoryNode(CATEGORY_NAME_2, DESTINATION_PROVIDER_2);
+
+        assertFalse("Array should not be empty", contentProvider.getChildren(categoryNode1).length == 0);
+        assertTrue("Array should have 2 children", contentProvider.getChildren(categoryNode1).length == 2);
+        assertTrue("Array should have 1 child", contentProvider.getChildren(categoryNode2).length == 1);
+        
+        final List<String> destinationDisplayNames = new ArrayList<String>();
+        final Object[] elements = contentProvider.getChildren(categoryNode1);
+        for (Object object : elements) {
+            destinationDisplayNames.add(((DestinationNode) object).getDestination().getDisplayName());
+        }
+        
+        assertTrue("Destination 1 expected to be contained in the result", destinationDisplayNames.contains(DESTINATION_NAME_1));
+        assertTrue("Destination 2 expected to be contained in the result", destinationDisplayNames.contains(DESTINATION_NAME_2));
+        assertFalse("Destination 3 not expected to be contained in the result", destinationDisplayNames.contains(DESTINATION_NAME_3));
+    }
+    
+}
diff --git a/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/ui/DestinationsPreferencePagePageObject.java b/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/ui/DestinationsPreferencePagePageObject.java
new file mode 100644
index 0000000..8505eaf
--- /dev/null
+++ b/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/ui/DestinationsPreferencePagePageObject.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG and others.
+ * 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.destprefs.test.unit.prefpage.ui;
+
+import static org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable.syncExec;
+
+import java.text.MessageFormat;
+import java.util.Collection;
+
+import org.eclipse.platform.discovery.destprefs.internal.i18n.DestPrefsMessages;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.CategoryDestinationProviderPair;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.DestinationsPreferencePage;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.IDestinationConfiguratorsPresenter;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.IDestinationConfiguratorsView;
+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swtbot.swt.finder.results.VoidResult;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+public class DestinationsPreferencePagePageObject extends InShellPageObject {
+    private final IDestinationConfiguratorsPresenter presenter;
+    private DestinationsPreferencePage page;
+
+    public DestinationsPreferencePagePageObject(final IDestinationConfiguratorsPresenter presenter) {
+        this.presenter = presenter;
+    }
+
+    @Override
+    protected void createContent(Shell parent, FormToolkit formToolkit) {
+        page = new DestinationsPreferencePage(this.presenter);
+        page.createControl(parent);
+    }
+
+    public IDestinationConfiguratorsView getView() {
+        return page;
+    }
+
+    public boolean canAddDestination() {
+        return addDestinationButton().isEnabled();
+    }
+
+    public void addDestination() {
+        addDestinationButton().click();
+    }
+
+    public boolean canEditDestination() {
+        return editDestinationButton().isEnabled();
+    }
+
+    public void editDestination() {
+        editDestinationButton().click();
+    }
+
+    public boolean canRemoveDestination() {
+        return removeDestinationButton().isEnabled();
+    }
+
+    public void removeDestination() {
+        removeDestinationButton().click();
+    }
+
+    public boolean canTestDestination() {
+        return testDestinationButton().isEnabled();
+    }
+
+    public void testDestination() {
+        testDestinationButton().click();
+    }
+
+    public void selectCategory(final String category) {
+        destinationsTree().select(categoryTreeItem(category));
+    }
+
+    private SWTBotTreeItem categoryTreeItem(String category) {
+        for (SWTBotTreeItem item : destinationsTree().getAllItems()) {
+            if (item.getText().startsWith(category)) {
+                return item;
+            }
+        }
+        throw new RuntimeException("Could not find category " + category);
+    }
+
+    public void selectDestination(final String category, final String destination) {
+        final SWTBotTreeItem categoryNode = categoryTreeItem(category);
+        categoryNode.expand();
+        final SWTBotTreeItem destNode = categoryNode.getNode(destination);
+        if (destNode != null) {
+            destNode.select();
+            return;
+        }
+        throw new RuntimeException(MessageFormat.format("Could not find destination {0} for category {1}", destination, category));
+    }
+
+    public int getMessageType() {
+        return page.getMessageType();
+    }
+
+    public String getMessage() {
+        return page.getMessage();
+    }
+
+    public void setInput(final Collection<CategoryDestinationProviderPair> input) {
+        syncExec(new VoidResult() {
+            @Override
+            public void run() {
+                page.setInput(input);
+            }
+        });
+    }
+
+    public void setAddEnabled(final boolean enabled) {
+        syncExec(new VoidResult() {
+            @Override
+            public void run() {
+                page.setAddEnabled(enabled);
+            }
+        });
+    }
+
+    public void setEditEnabled(final boolean enabled) {
+        syncExec(new VoidResult() {
+            @Override
+            public void run() {
+                page.setEditEnabled(enabled);
+            }
+        });
+    }
+
+    public void setRemoveEnabled(final boolean enabled) {
+        syncExec(new VoidResult() {
+            @Override
+            public void run() {
+                page.setRemoveEnabled(enabled);
+            }
+        });
+    }
+
+    public void setTestEnabled(final boolean enabled) {
+        syncExec(new VoidResult() {
+            @Override
+            public void run() {
+                page.setTestEnabled(enabled);
+            }
+        });
+    }
+
+    private SWTBotTree destinationsTree() {
+        return bot().tree();
+    }
+
+    private SWTBotButton addDestinationButton() {
+        return bot().button(DestPrefsMessages.DestinationsPrefPage_AddButton);
+    }
+
+    private SWTBotButton removeDestinationButton() {
+        return bot().button(DestPrefsMessages.DestinationsPrefPage_DeleteButton);
+    }
+
+    private SWTBotButton editDestinationButton() {
+        return bot().button(DestPrefsMessages.DestinationsPrefPage_EditButton);
+    }
+
+    private SWTBotButton testDestinationButton() {
+        return bot().button(DestPrefsMessages.DestinationsPrefPage_TestButton);
+    }
+}
diff --git a/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/ui/DestinationsPreferencePageTest.java b/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/ui/DestinationsPreferencePageTest.java
new file mode 100644
index 0000000..13cced9
--- /dev/null
+++ b/tests/org.eclipse.platform.discovery.destprefs.test.unit/src/org/eclipse/platform/discovery/destprefs/test/unit/prefpage/ui/DestinationsPreferencePageTest.java
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 2012 SAP AG and others.
+ * 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.destprefs.test.unit.prefpage.ui;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.CategoryDestinationProviderPair;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.DestinationConfiguratorSelection;
+import org.eclipse.platform.discovery.destprefs.internal.prefpage.ui.IDestinationConfiguratorsPresenter;
+import org.eclipse.platform.discovery.runtime.api.IDestinationsProvider;
+import org.eclipse.platform.discovery.runtime.api.ISearchDestination;
+import org.eclipse.platform.discovery.runtime.internal.model.descriptions.IDestinationCategoryDescription;
+import org.eclipse.platform.discovery.runtime.internal.model.descriptions.IDestinationsProviderDescription;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class DestinationsPreferencePageTest {
+    private static final String CATEGORY_ID = "my.category.id";
+    private static final String CATEGORY_NAME = "My Category";
+    private static final String DESTINATION_PROVIDER_ID = "my.dest.provider.id";
+    private static final String DESTINATION_NAME = "My Destination";
+    
+    private DestinationsPreferencePagePageObject pageObject;
+    @Mock
+    private IDestinationConfiguratorsPresenter presenter;
+    @Mock
+    private IDestinationCategoryDescription category;
+    @Mock
+    private IDestinationsProviderDescription destinationProviderDescr;
+    @Mock
+    private IDestinationsProvider destinationProvider;
+    @Mock
+    private ISearchDestination destination;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        stubDestinations();
+        pageObject = new DestinationsPreferencePagePageObject(presenter);
+        
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                pageObject.getView().setAddEnabled(true);
+                pageObject.getView().setRemoveEnabled(true);
+                pageObject.getView().setEditEnabled(true);
+                pageObject.getView().setTestEnabled(true);
+                return null;
+            }
+        }).when(presenter).selectionChanged(Mockito.any(DestinationConfiguratorSelection.class));
+        
+        pageObject.open();
+        pageObject.setInput(createPageInput());
+    }
+
+    private void stubDestinations() {
+        Mockito.stub(destination.getDisplayName()).toReturn(DESTINATION_NAME);
+        Mockito.stub(destinationProvider.getSearchDestinations()).toReturn(new HashSet<ISearchDestination>(Arrays.asList(new ISearchDestination[]{destination})));
+        Mockito.stub(destinationProviderDescr.createProvider()).toReturn(destinationProvider);
+        Mockito.stub(destinationProviderDescr.getId()).toReturn(DESTINATION_PROVIDER_ID);
+        Mockito.stub(category.getId()).toReturn(CATEGORY_ID);
+        Mockito.stub(category.getDisplayName()).toReturn(CATEGORY_NAME);
+    }
+
+    private Collection<CategoryDestinationProviderPair> createPageInput() {
+        final Collection<CategoryDestinationProviderPair> result = new ArrayList<CategoryDestinationProviderPair>();
+        result.add(new CategoryDestinationProviderPair(category, destinationProviderDescr));
+        return result;
+    }
+
+    @After
+    public void tearDown() {
+        pageObject.close();
+    }
+
+    @Test
+    public void testNoDestinationsSelected() {
+        assertFalse("Adding destination is unexpectedly enabled", pageObject.canAddDestination());
+        assertFalse("Removing destination is unexpectedly enabled", pageObject.canRemoveDestination());
+        assertFalse("Editing destination is unexpectedly enabled", pageObject.canEditDestination());
+        assertFalse("Testing destination is unexpectedly enabled", pageObject.canTestDestination());
+    }
+
+    @Test
+    public void testEnableAdd() {
+        pageObject.setAddEnabled(true);
+        assertTrue("Adding destination is unexpectedly disabled", pageObject.canAddDestination());
+    }
+
+    @Test
+    public void testEnableEdit() {
+        pageObject.setEditEnabled(true);
+        assertTrue("Editing destination is unexpectedly disabled", pageObject.canEditDestination());
+    }
+
+    @Test
+    public void testEnableRemove() {
+        pageObject.setRemoveEnabled(true);
+        assertTrue("Removing destination is unexpectedly disabled", pageObject.canRemoveDestination());
+    }
+
+    @Test
+    public void testEnableTest() {
+        pageObject.setTestEnabled(true);
+        assertTrue("Testingdestination is unexpectedly disabled", pageObject.canTestDestination());
+    }
+
+    @Test
+    public void testSetErrorStatus() throws InterruptedException {
+        setStatusTest(createStatus(IStatus.ERROR, "Some error"), IMessageProvider.ERROR);
+    }
+
+    @Test
+    public void testSetWarningStatus() throws InterruptedException {
+        setStatusTest(createStatus(IStatus.WARNING, "Some warning"), IMessageProvider.WARNING);
+    }
+
+    @Test
+    public void testSetCancelStatus() throws InterruptedException {
+        setStatusTest(createStatus(IStatus.CANCEL, "Cancelled"), IMessageProvider.INFORMATION);
+    }
+
+    @Test
+    public void testSetOkStatus() throws InterruptedException {
+        setStatusTest(createStatus(IStatus.OK, "Success"), IMessageProvider.INFORMATION);
+    }
+    
+    @Test
+    public void testSelectCategory() {
+        pageObject.selectCategory(CATEGORY_NAME);
+        Mockito.verify(presenter, Mockito.atLeastOnce()).selectionChanged(Mockito.argThat(selectionMatcher(DESTINATION_PROVIDER_ID, null)));
+    }
+
+    @Test
+    public void testSelectDestination() {
+        pageObject.selectDestination(CATEGORY_NAME, DESTINATION_NAME);
+        Mockito.verify(presenter, Mockito.atLeastOnce()).selectionChanged(Mockito.argThat(selectionMatcher(DESTINATION_PROVIDER_ID, destination)));
+    }
+    
+    @Test
+    public void testAddDestination() {
+        pageObject.selectDestination(CATEGORY_NAME, DESTINATION_NAME);
+        pageObject.addDestination();
+        Mockito.verify(presenter).addDestination();
+    }
+    
+    @Test
+    public void testEditDestination() {
+        pageObject.selectDestination(CATEGORY_NAME, DESTINATION_NAME);
+        pageObject.editDestination();
+        Mockito.verify(presenter).editDestination();
+    }
+    
+    @Test
+    public void testRemoveDestination() {
+        pageObject.selectDestination(CATEGORY_NAME, DESTINATION_NAME);
+        pageObject.removeDestination();
+        Mockito.verify(presenter).removeDestination();
+    }
+    
+    @Test
+    public void testTestDestination() {
+        pageObject.selectDestination(CATEGORY_NAME, DESTINATION_NAME);
+        pageObject.testDestination();
+        Mockito.verify(presenter).testDestination();
+    }
+    
+    private Matcher<DestinationConfiguratorSelection> selectionMatcher(String destinationProviderId, final ISearchDestination destination) {
+        return new BaseMatcher<DestinationConfiguratorSelection>() {
+            @Override
+            public boolean matches(Object item) {
+                final DestinationConfiguratorSelection selection = (DestinationConfiguratorSelection)item;
+                return selection.destProviderId.equals(DESTINATION_PROVIDER_ID) && (selection.destination == destination);
+            }
+
+            @Override
+            public void describeTo(Description description) {
+            }
+        };
+    }
+
+    private void setStatusTest(final IStatus status, int expectedMessageType) {
+        pageObject.getView().setStatus(status);
+        assertEquals("Unexpected message type", expectedMessageType, pageObject.getMessageType());
+        assertEquals("Unexpected message ", status.getMessage(), pageObject.getMessage());
+    }
+
+    private IStatus createStatus(int severity, String message) {
+        final IStatus status = Mockito.mock(IStatus.class);
+        Mockito.stub(status.getSeverity()).toReturn(severity);
+        Mockito.stub(status.getMessage()).toReturn(message);
+        return status;
+    }
+}
diff --git a/tests/org.eclipse.platform.discovery.test.testutils/META-INF/MANIFEST.MF b/tests/org.eclipse.platform.discovery.test.testutils/META-INF/MANIFEST.MF
index 2a127ad..78f2dfb 100644
--- a/tests/org.eclipse.platform.discovery.test.testutils/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.platform.discovery.test.testutils/META-INF/MANIFEST.MF
@@ -17,7 +17,9 @@
  org.eclipse.platform.discovery.runtime,

  org.mockito,

  org.eclipse.platform.discovery.ui,

- org.eclipse.platform.discovery.destprefs

+ org.eclipse.platform.discovery.destprefs,

+ org.eclipse.swtbot.eclipse.finder,

+ org.apache.log4j

 Bundle-ActivationPolicy: lazy

 Bundle-RequiredExecutionEnvironment: JavaSE-1.6

 Bundle-Activator: org.eclipse.platform.discovery.testutils.internal.plugin.TestPlugin

@@ -26,6 +28,7 @@
  org.eclipse.platform.discovery.testutils.utils.junit.util.assertions,

  org.eclipse.platform.discovery.testutils.utils.junit.util.threading,

  org.eclipse.platform.discovery.testutils.utils.model,

+ org.eclipse.platform.discovery.testutils.utils.pageobjects,

  org.eclipse.platform.discovery.testutils.utils.reflection,

  org.eclipse.platform.discovery.testutils.utils.registry,

  org.eclipse.platform.discovery.testutils.utils.testcases

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/InShellPageObject.java b/tests/org.eclipse.platform.discovery.test.testutils/src/org/eclipse/platform/discovery/testutils/utils/pageobjects/InShellPageObject.java
similarity index 94%
rename from tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/InShellPageObject.java
rename to tests/org.eclipse.platform.discovery.test.testutils/src/org/eclipse/platform/discovery/testutils/utils/pageobjects/InShellPageObject.java
index 8309fc3..e435747 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/InShellPageObject.java
+++ b/tests/org.eclipse.platform.discovery.test.testutils/src/org/eclipse/platform/discovery/testutils/utils/pageobjects/InShellPageObject.java
@@ -8,7 +8,7 @@
  * Contributors:

  *     SAP AG - initial API and implementation

  *******************************************************************************/

-package org.eclipse.platform.discovery.ui.test.comp.internal.pageobjects;

+package org.eclipse.platform.discovery.testutils.utils.pageobjects;

 

 import org.eclipse.swt.SWT;

 import org.eclipse.swt.events.DisposeEvent;

@@ -27,7 +27,7 @@
  * @author Danail Branekov

  * 

  */

-abstract class InShellPageObject

+public abstract class InShellPageObject

 {

 	private SWTBotShell botShell;

 	private static final String TEST_SHELL_LABEL = "Testing Shell";

@@ -109,4 +109,8 @@
 	{

 		return botShell;

 	}

+	

+	public Shell getShell() {

+	    return botShell.widget;

+	}

 }

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/AdvancedSearchParamsPageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/AdvancedSearchParamsPageObject.java
index 3599f50..609e82a 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/AdvancedSearchParamsPageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/AdvancedSearchParamsPageObject.java
@@ -6,6 +6,7 @@
 import org.eclipse.platform.discovery.runtime.api.ISearchParameters;

 import org.eclipse.platform.discovery.runtime.internal.ISearchProviderConfiguration;

 import org.eclipse.platform.discovery.runtime.internal.model.descriptions.IObjectTypeDescription;

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.api.IAdvancedSearchParamsUiContributor;

 import org.eclipse.platform.discovery.ui.api.IViewUiContext;

 import org.eclipse.platform.discovery.ui.internal.search.advancedparams.AdvancedSearchParamsDisplayer;

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/ComboSelectorPageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/ComboSelectorPageObject.java
index 4d00f79..f83234b 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/ComboSelectorPageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/ComboSelectorPageObject.java
@@ -17,6 +17,7 @@
 

 import org.eclipse.jface.viewers.ISelectionChangedListener;

 import org.eclipse.platform.discovery.runtime.api.IDisplayableObject;

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.internal.selector.ComboSelector;

 import org.eclipse.swt.widgets.Shell;

 import org.eclipse.swtbot.swt.finder.results.VoidResult;

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/DiscoveredItemsInShellPageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/DiscoveredItemsInShellPageObject.java
index f8dfb78..15d1310 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/DiscoveredItemsInShellPageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/DiscoveredItemsInShellPageObject.java
@@ -14,6 +14,7 @@
 import java.util.HashSet;

 

 import org.eclipse.platform.discovery.core.api.IContributedAction;

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.api.IGenericViewCustomization;

 import org.eclipse.platform.discovery.ui.api.IResultsViewAccessor;

 import org.eclipse.platform.discovery.ui.internal.view.result.impl.DiscoveryTreeViewerFactory;

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/InteractiveComboSelectorPageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/InteractiveComboSelectorPageObject.java
index e510c60..5ec7ad8 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/InteractiveComboSelectorPageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/InteractiveComboSelectorPageObject.java
@@ -15,6 +15,7 @@
 import java.util.List;

 

 import org.eclipse.platform.discovery.runtime.api.IDisplayableObject;

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.internal.selector.InteractiveComboSelector;

 import org.eclipse.swt.widgets.Shell;

 import org.eclipse.swtbot.swt.finder.results.VoidResult;

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchConsolePageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchConsolePageObject.java
index 54ec0fa..7640289 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchConsolePageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchConsolePageObject.java
@@ -1,6 +1,7 @@
 package org.eclipse.platform.discovery.ui.test.comp.internal.pageobjects;

 

 import static org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable.syncExec;

+import static org.junit.Assert.assertNotNull;

 

 import java.text.MessageFormat;

 import java.util.Collection;

@@ -17,6 +18,7 @@
 import org.eclipse.platform.discovery.runtime.api.SearchFailedException;

 import org.eclipse.platform.discovery.runtime.internal.ISearchProviderConfiguration;

 import org.eclipse.platform.discovery.runtime.internal.ProviderNotFoundException;

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.api.IGenericViewCustomization;

 import org.eclipse.platform.discovery.ui.api.IViewUiContext;

 import org.eclipse.platform.discovery.ui.api.impl.DefaultSessionIds;

@@ -162,10 +164,11 @@
 

 		final SWTBotShell preferencePageShell = findPreferencePageShell();

 		verifyDestinationPreferenceDisplayed(preferencePageShell);

+		verifyGenericDestinationPreferencesDisplayed(preferencePageShell);

 		preferencePageShell.close();

 	}

 

-	public void verifySearchPerformed(final String objectTypeId, final String destinationName, final String keyword)

+    public void verifySearchPerformed(final String objectTypeId, final String destinationName, final String keyword)

 	{

 		Assert.assertNotNull("Search was not invoked", viewController.lastSearchEvent);

 		Assert.assertEquals("Unexpected object id", objectTypeId, viewController.lastSearchEvent.getSearchParameters().getObjectTypeId());

@@ -421,6 +424,12 @@
 		{

 		}

 	}

+	

+    private void verifyGenericDestinationPreferencesDisplayed(SWTBotShell preferencePageShell) {

+        assertNotNull(preferencePageShell.bot().tree().getTreeItem("Search Destinations"));

+    }

+

+	

 

 	private class PageObjectConsoleView extends SearchConsoleView

 	{

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchDestinationsSelectorPageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchDestinationsSelectorPageObject.java
index 24fa740..eea258c 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchDestinationsSelectorPageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchDestinationsSelectorPageObject.java
@@ -22,6 +22,7 @@
 import org.eclipse.platform.discovery.runtime.api.IDestinationsProvider;

 import org.eclipse.platform.discovery.runtime.api.ISearchDestination;

 import org.eclipse.platform.discovery.runtime.internal.model.descriptions.IDestinationCategoryDescription;

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.internal.selector.SearchDestinationsSelector;

 import org.eclipse.swt.widgets.Shell;

 import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchFavoritesPageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchFavoritesPageObject.java
index 4757dbb..859c5ec 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchFavoritesPageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SearchFavoritesPageObject.java
@@ -19,6 +19,7 @@
 import org.eclipse.platform.discovery.core.internal.IContextStructuredSelection;

 import org.eclipse.platform.discovery.runtime.api.ISearchDestination;

 import org.eclipse.platform.discovery.runtime.api.ISearchParameters;

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.api.ISearchFavoritesViewCustomization;

 import org.eclipse.platform.discovery.ui.internal.dnd.LocalContextSelectionTransfer;

 import org.eclipse.platform.discovery.ui.internal.view.SearchFavoritesView;

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SlidingCompositePageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SlidingCompositePageObject.java
index 0be59b2..bc6d893 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SlidingCompositePageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SlidingCompositePageObject.java
@@ -1,5 +1,6 @@
 package org.eclipse.platform.discovery.ui.test.comp.internal.pageobjects;

 

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.internal.SlidingComposite;

 import org.eclipse.platform.discovery.ui.test.comp.internal.pageobjects.swtbot.SWTBotSash;

 import org.eclipse.platform.discovery.ui.test.comp.internal.pageobjects.swtbot.SwtBotCanvas;

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SubdestinationsSelectorPageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SubdestinationsSelectorPageObject.java
index 11a1867..f8368c8 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SubdestinationsSelectorPageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/SubdestinationsSelectorPageObject.java
@@ -10,6 +10,7 @@
  *******************************************************************************/

 package org.eclipse.platform.discovery.ui.test.comp.internal.pageobjects;

 

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.api.ISearchParametersUI.IConsoleContext;

 import org.eclipse.platform.discovery.ui.test.comp.internal.pageobjects.swtbot.SWTBotSubdSelector;

 import org.eclipse.swt.widgets.Shell;

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/TabbedSessionDisplayerPageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/TabbedSessionDisplayerPageObject.java
index d427119..c73da4a 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/TabbedSessionDisplayerPageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/TabbedSessionDisplayerPageObject.java
@@ -6,6 +6,7 @@
 import java.util.HashMap;

 import java.util.Map;

 

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.internal.plugin.DiscoveryUIMessages;

 import org.eclipse.platform.discovery.ui.internal.view.result.impl.TabbedSessionDisplayer;

 import org.eclipse.platform.discovery.ui.internal.view.result.impl.TabbedSessionDisplayer.UI;

@@ -168,7 +169,7 @@
 	}

 	

 	private SWTBot shellBot() {

-		return new MyBot(inShellPageObject.shell().widget);

+		return new MyBot(inShellPageObject.getShell());

 	}

 

 	public void closeSession(String sessionId) {

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/TextControlPageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/TextControlPageObject.java
index c3c0b35..92fc64c 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/TextControlPageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/TextControlPageObject.java
@@ -12,6 +12,7 @@
 

 import static org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable.syncExec;

 

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.internal.view.impl.TextControl;

 import org.eclipse.swt.SWT;

 import org.eclipse.swt.widgets.Label;

diff --git a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/ViewProgressMonitorPageObject.java b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/ViewProgressMonitorPageObject.java
index 3aef8e0..11b194f 100644
--- a/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/ViewProgressMonitorPageObject.java
+++ b/tests/org.eclipse.platform.discovery.ui.test.comp/src/org/eclipse/platform/discovery/ui/test/comp/internal/pageobjects/ViewProgressMonitorPageObject.java
@@ -14,6 +14,7 @@
 

 import java.util.Arrays;

 

+import org.eclipse.platform.discovery.testutils.utils.pageobjects.InShellPageObject;

 import org.eclipse.platform.discovery.ui.internal.view.ViewProgressMonitor;

 import org.eclipse.swt.SWT;

 import org.eclipse.swt.layout.FillLayout;