Bug 505601: Adopt samples support that was removed from pde.ui
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/.classpath b/plugins/org.eclipse.objectteams.otdt.samples/.classpath
index 4f51512..3bc2475 100644
--- a/plugins/org.eclipse.objectteams.otdt.samples/.classpath
+++ b/plugins/org.eclipse.objectteams.otdt.samples/.classpath
@@ -3,6 +3,5 @@
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-	<classpathentry kind="con" path="OTRE"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/.project b/plugins/org.eclipse.objectteams.otdt.samples/.project
index 305af71..10f9d30 100644
--- a/plugins/org.eclipse.objectteams.otdt.samples/.project
+++ b/plugins/org.eclipse.objectteams.otdt.samples/.project
@@ -6,7 +6,7 @@
 	</projects>
 	<buildSpec>
 		<buildCommand>
-			<name>org.eclipse.objectteams.otdt.builder.OTJBuilder</name>
+			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
 			</arguments>
 		</buildCommand>
@@ -24,6 +24,5 @@
 	<natures>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 		<nature>org.eclipse.pde.PluginNature</nature>
-		<nature>org.eclipse.objectteams.otdt.OTJavaNature</nature>
 	</natures>
 </projectDescription>
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.samples/META-INF/MANIFEST.MF
index fc48b70..e84a54a 100644
--- a/plugins/org.eclipse.objectteams.otdt.samples/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt.samples/META-INF/MANIFEST.MF
@@ -11,17 +11,11 @@
  org.eclipse.ui.intro;bundle-version="[3.4.100,4.0.0)",
  org.eclipse.ui.intro.universal;bundle-version="[3.2.500,4.0.0)",
  org.eclipse.pde.ui;bundle-version="[3.6.100,4.0.0)",
- org.eclipse.core.resources;bundle-version="[3.7.0,4.0.0)",
  org.eclipse.ui.ide;bundle-version="[3.7.0,4.0.0)",
  org.eclipse.ui.forms;bundle-version="[3.5.100,4.0.0)",
  org.eclipse.debug.ui;bundle-version="[3.7.0,4.0.0)",
- org.eclipse.debug.core;bundle-version="[3.7.0,4.0.0)",
- org.eclipse.jdt.debug.ui;bundle-version="[3.6.0,4.0.0)",
  org.eclipse.jdt.core;bundle-version="[3.10.0.v_OTDT_r230,4.0.0)",
- org.eclipse.objectteams.otdt;bundle-version="[2.5.0,3.0.0)",
- org.eclipse.objectteams.otdt.ui;bundle-version="[2.5.0,3.0.0)",
- org.eclipse.objectteams.otdt.ui.help;bundle-version="[2.5.0,3.0.0)",
- org.eclipse.objectteams.otequinox;bundle-version="[2.5.0,3.0.0)"
+ org.eclipse.objectteams.otdt.ui.help;bundle-version="[2.5.0,3.0.0)"
 Export-Package: org.eclipse.objectteams.otdt.internal.samples;x-internal:="true"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.7
 Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/icons/obj16/build_exec.png b/plugins/org.eclipse.objectteams.otdt.samples/icons/obj16/build_exec.png
new file mode 100644
index 0000000..e6b8c80
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/icons/obj16/build_exec.png
Binary files differ
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/icons/obj16/build_exec@2x.png b/plugins/org.eclipse.objectteams.otdt.samples/icons/obj16/build_exec@2x.png
new file mode 100644
index 0000000..87e738f
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/icons/obj16/build_exec@2x.png
Binary files differ
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/intro/samplesExtensionContentOT.xml b/plugins/org.eclipse.objectteams.otdt.samples/intro/samplesExtensionContentOT.xml
index 2d7eb84..59d6a1c 100644
--- a/plugins/org.eclipse.objectteams.otdt.samples/intro/samplesExtensionContentOT.xml
+++ b/plugins/org.eclipse.objectteams.otdt.samples/intro/samplesExtensionContentOT.xml
@@ -19,7 +19,7 @@
 		  </link>	
 -->
         <link label="OTSample-StopWatch" 
-        	  url="http://org.eclipse.ui.intro/runAction?pluginId=org.eclipse.objectteams.otdt.samples&amp;class=org.eclipse.pde.internal.ui.samples.ShowSampleAction&amp;id=org.eclipse.objectteams.otdt.samples.stopwatch" 
+        	  url="http://org.eclipse.ui.intro/runAction?pluginId=org.eclipse.objectteams.otdt.samples&amp;class=org.eclipse.objectteams.otdt.internal.samples.ShowSampleAction&amp;id=org.eclipse.objectteams.otdt.samples.stopwatch" 
         	  id="stopwatchsample" 
         	  style-id="content-link">
 		  <text>This implementation of a simple stop watch demonstrates how the Model-View-Controller pattern can be applied in Object Teams. 
@@ -30,11 +30,11 @@
 			   (3) lifting a base object to its role.
 		  </text>
 		</link>
-        <link label="OTSample-Observer" url="http://org.eclipse.ui.intro/runAction?pluginId=org.eclipse.objectteams.otdt.samples&amp;class=org.eclipse.pde.internal.ui.samples.ShowSampleAction&amp;id=org.eclipse.objectteams.otdt.samples.observer" id="observersample" style-id="content-link">
+        <link label="OTSample-Observer" url="http://org.eclipse.ui.intro/runAction?pluginId=org.eclipse.objectteams.otdt.samples&amp;class=org.eclipse.objectteams.otdt.internal.samples.ShowSampleAction&amp;id=org.eclipse.objectteams.otdt.samples.observer" id="observersample" style-id="content-link">
 		  <text>A reusable implementation of the standard Observer pattern with two applications.
 					  
 			A fine point in this example is the temporary deactivation of a team to avoid the "jumping aspects" problem.</text></link>		  
-		<link label="OTSample-Flightbonus" url="http://org.eclipse.ui.intro/runAction?pluginId=org.eclipse.objectteams.otdt.samples&amp;class=org.eclipse.pde.internal.ui.samples.ShowSampleAction&amp;id=org.eclipse.objectteams.otdt.samples.flightbooking" id="flightbonussample" style-id="content-link">
+		<link label="OTSample-Flightbonus" url="http://org.eclipse.ui.intro/runAction?pluginId=org.eclipse.objectteams.otdt.samples&amp;class=org.eclipse.objectteams.otdt.internal.samples.ShowSampleAction&amp;id=org.eclipse.objectteams.otdt.samples.flightbooking" id="flightbonussample" style-id="content-link">
           <text>This examples demonstrates, how a reusable collaboration for collecting bonus points 
 			can be integrated into an existing application for flight booking.
 			
@@ -42,11 +42,11 @@
 			   (1) a core application, 
 			   (2) an abstract collaboration, and
 			   (3) a connector which combines the other two modules.</text></link>	
-        <link label="OTSample-Ordersystem" url="http://org.eclipse.ui.intro/runAction?pluginId=org.eclipse.objectteams.otdt.samples&amp;class=org.eclipse.pde.internal.ui.samples.ShowSampleAction&amp;id=org.eclipse.objectteams.otdt.samples.ordersystem" id="ordersystemsample" style-id="content-link">        
+        <link label="OTSample-Ordersystem" url="http://org.eclipse.ui.intro/runAction?pluginId=org.eclipse.objectteams.otdt.samples&amp;class=org.eclipse.objectteams.otdt.internal.samples.ShowSampleAction&amp;id=org.eclipse.objectteams.otdt.samples.ordersystem" id="ordersystemsample" style-id="content-link">        
         	<text>A comprehensive example showing different patterns of applying Object Teams.
 			It implements three components: a storage, reservation of items, and orders.
 			Also a GUI is provided which is cleanly separated into Model/View/Controller</text></link>
-        <link label="OTSample-ATM" url="http://org.eclipse.ui.intro/runAction?pluginId=org.eclipse.objectteams.otdt.samples&amp;class=org.eclipse.pde.internal.ui.samples.ShowSampleAction&amp;id=org.eclipse.objectteams.otdt.samples.atm" id="atmsample" style-id="content-link">        
+        <link label="OTSample-ATM" url="http://org.eclipse.ui.intro/runAction?pluginId=org.eclipse.objectteams.otdt.samples&amp;class=org.eclipse.objectteams.otdt.internal.samples.ShowSampleAction&amp;id=org.eclipse.objectteams.otdt.samples.atm" id="atmsample" style-id="content-link">        
     	    <text>An example showing the use of guard predicates in Object Teams. 
     	    
         	It implements a simple ATM that adds specific behaviour to specific groups of accounts:
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/plugin.properties b/plugins/org.eclipse.objectteams.otdt.samples/plugin.properties
index 04c80fa..73e4f21 100644
--- a/plugins/org.eclipse.objectteams.otdt.samples/plugin.properties
+++ b/plugins/org.eclipse.objectteams.otdt.samples/plugin.properties
@@ -13,3 +13,5 @@
 sample.ordersystem.desc = A comprehensive example showing different patterns of applying Object Teams. It implements three components: a storage, reservations of items, and orders plus a MVC GUI. 
 sample.atm.name = ATM Example
 sample.atm.desc = An example showing the use of guard predicates in Object Teams. It implements a simple ATM that adds specific behaviour to specific groups of accounts.
+
+editors.sample.name = Code Sample Editor
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/plugin.xml b/plugins/org.eclipse.objectteams.otdt.samples/plugin.xml
index 808e4ea..44e6ac4 100644
--- a/plugins/org.eclipse.objectteams.otdt.samples/plugin.xml
+++ b/plugins/org.eclipse.objectteams.otdt.samples/plugin.xml
@@ -99,7 +99,7 @@
       </category>
       <wizard
             category="org.eclipse.ui.Examples/org.eclipse.objectteams.otdt.samples"
-            class="org.eclipse.pde.internal.ui.samples.SampleWizard:org.eclipse.objectteams.otdt.samples.flightbooking"
+            class="org.eclipse.objectteams.otdt.internal.samples.SampleWizard:org.eclipse.objectteams.otdt.samples.flightbooking"
             icon="graphics/icons/newprj_wiz.gif"
             id="org.eclipse.objectteams.otdt.samples.samples.flightbooking"
             name="%sample.flightbooking.name"
@@ -109,7 +109,7 @@
       </wizard>      
       <wizard
             category="org.eclipse.ui.Examples/org.eclipse.objectteams.otdt.samples"
-            class="org.eclipse.pde.internal.ui.samples.SampleWizard:org.eclipse.objectteams.otdt.samples.observer"
+            class="org.eclipse.objectteams.otdt.internal.samples.SampleWizard:org.eclipse.objectteams.otdt.samples.observer"
             icon="graphics/icons/newprj_wiz.gif"
             id="org.eclipse.objectteams.otdt.samples.samples.observer"
             name="%sample.observer.name"
@@ -119,7 +119,7 @@
       </wizard>      
       <wizard
             category="org.eclipse.ui.Examples/org.eclipse.objectteams.otdt.samples"
-            class="org.eclipse.pde.internal.ui.samples.SampleWizard:org.eclipse.objectteams.otdt.samples.stopwatch"
+            class="org.eclipse.objectteams.otdt.internal.samples.SampleWizard:org.eclipse.objectteams.otdt.samples.stopwatch"
             icon="graphics/icons/newprj_wiz.gif"
             id="org.eclipse.objectteams.otdt.samples.samples.stopwatch"
             name="%sample.stopwatch.name"
@@ -129,7 +129,7 @@
       </wizard>      
       <wizard
             category="org.eclipse.ui.Examples/org.eclipse.objectteams.otdt.samples"
-            class="org.eclipse.pde.internal.ui.samples.SampleWizard:org.eclipse.objectteams.otdt.samples.ordersystem"
+            class="org.eclipse.objectteams.otdt.internal.samples.SampleWizard:org.eclipse.objectteams.otdt.samples.ordersystem"
             icon="graphics/icons/newprj_wiz.gif"
             id="org.eclipse.objectteams.otdt.samples.samples.ordersystem"
             name="%sample.ordersystem.name"
@@ -139,7 +139,7 @@
       </wizard>
       <wizard
             category="org.eclipse.ui.Examples/org.eclipse.objectteams.otdt.samples"
-            class="org.eclipse.pde.internal.ui.samples.SampleWizard:org.eclipse.objectteams.otdt.samples.atm"
+            class="org.eclipse.objectteams.otdt.internal.samples.SampleWizard:org.eclipse.objectteams.otdt.samples.atm"
             icon="graphics/icons/newprj_wiz.gif"
             id="org.eclipse.objectteams.otdt.samples.samples.atm"
             name="%sample.atm.name"
@@ -148,6 +148,18 @@
          </description>
       </wizard>
    </extension>
+   
+   <extension
+         point="org.eclipse.ui.editors">
+      <editor
+            name="%editors.sample.name"
+            default="true"
+            icon="$nl$/icons/obj16/build_exec.png"
+            filenames="sample.properties"
+            class="org.eclipse.objectteams.otdt.internal.samples.SampleEditor"
+            id="org.eclipse.objectteams.otdt.sampleEditor">
+      </editor>
+   </extension>
 
    <extension
          point="org.eclipse.ui.intro.configExtension">
@@ -157,20 +169,5 @@
    </extension>
 
 <!--  -->
-   <extension
-         point="org.eclipse.objectteams.otequinox.aspectBindings">
-      <aspectBinding
-            icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/calloutbinding_obj.gif">
-         <basePlugin 
-               icon="platform:/plugin/org.eclipse.pde.ui/icons/obj16/plugin_obj.png"
-               id="org.eclipse.pde.ui"/>
-         <team class="org.eclipse.objectteams.otdt.internal.samples.SamplesAdapter"
-               icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif"
-               activation="ALL_THREADS"/>
-         <team class="org.eclipse.objectteams.otdt.internal.samples.SamplesAdapter$SampleWizardAdapter"
-               icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif"
-               activation="NONE"/>
-      </aspectBinding>
-   </extension>
 <!-- -->
 </plugin>
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/Messages.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/Messages.java
new file mode 100644
index 0000000..a2958dc
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/Messages.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.objectteams.otdt.internal.samples;
+
+import org.eclipse.osgi.util.NLS;;
+
+public class Messages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.objectteams.otdt.internal.samples.messages";//$NON-NLS-1$
+
+	public static String SampleWizard_title;
+	public static String SampleWizard_overwrite;
+
+	public static String ShowSampleAction_title;
+
+	public static String SelectionPage_title;
+	public static String SelectionPage_desc;
+
+	public static String ProjectNamesPage_projectName;
+	public static String ProjectNamesPage_multiProjectName;
+	public static String ProjectNamesPage_title;
+	public static String ProjectNamesPage_desc;
+
+	public static String ProjectNamesPage_noSampleFound;
+	public static String ProjectNamesPage_emptyName;
+	public static String ProjectNamesPage_duplicateNames;
+
+	public static String ReviewPage_title;
+	public static String ReviewPage_desc;
+	public static String ReviewPage_descContent;
+	public static String ReviewPage_content;
+
+	public static String ReviewPage_noSampleFound;
+
+	
+	public static String SampleEditor_desc;
+	public static Object SampleEditor_content;
+
+	
+	public static String SampleOperation_creating;
+
+	
+	public static String SampleStandbyContent_content;
+	public static String SampleStandbyContent_desc;
+
+
+
+
+	
+
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/OTSamplesPlugin.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/OTSamplesPlugin.java
index 9d92fee..60a4490 100644
--- a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/OTSamplesPlugin.java
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/OTSamplesPlugin.java
@@ -1,7 +1,7 @@
 /**********************************************************************
  * This file is part of "Object Teams Development Tooling"-Software
  * 
- * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * Copyright 2004, 2016 Fraunhofer Gesellschaft, Munich, Germany,
  * for its Fraunhofer Institute for Computer Architecture and Software
  * Technology (FIRST), Berlin, Germany and Technical University Berlin,
  * Germany.
@@ -10,7 +10,6 @@
  * 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
- * $Id: OTSamplesPlugin.java 23482 2010-02-05 20:16:19Z stephan $
  * 
  * Please visit http://www.eclipse.org/objectteams for updates and contact.
  * 
@@ -20,8 +19,17 @@
  **********************************************************************/
 package org.eclipse.objectteams.otdt.internal.samples;
 
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
 import org.osgi.framework.BundleContext;
 
@@ -53,4 +61,41 @@
 	{
 		return new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, message, ex);
 	}
+
+	public static void logException(Throwable e, final String title, String message) {
+		if (e instanceof InvocationTargetException) {
+			e = ((InvocationTargetException) e).getTargetException();
+		}
+		IStatus status = null;
+		if (e instanceof CoreException) {
+			status = ((CoreException) e).getStatus();
+		} else {
+			if (message == null)
+				message = e.getMessage();
+			if (message == null)
+				message = e.toString();
+			status = new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, message, e);
+		}
+		ResourcesPlugin.getPlugin().getLog().log(status);
+		Display display = getStandardDisplay();
+		final IStatus fstatus = status;
+		display.asyncExec(new Runnable() {
+			@Override
+			public void run() {
+				ErrorDialog.openError(null, title, null, fstatus);
+			}
+		});		
+	}
+	public static IWorkbenchPage getActivePage() {
+		IWorkbenchWindow workbenchWin = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+		return workbenchWin != null ? workbenchWin.getActivePage() : null;
+	}
+
+	public static Display getStandardDisplay() {
+		Display display;
+		display = Display.getCurrent();
+		if (display == null)
+			display = Display.getDefault();
+		return display;
+	}
 }
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/ProjectNamesPage.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/ProjectNamesPage.java
new file mode 100644
index 0000000..fecc3fb
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/ProjectNamesPage.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.objectteams.otdt.internal.samples;
+
+import java.util.HashSet;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.objectteams.otdt.internal.samples.Messages;
+
+public class ProjectNamesPage extends WizardPage {
+
+	private SampleWizard wizard;
+	private Composite container;
+	private boolean isInitialized;
+
+	public ProjectNamesPage(SampleWizard wizard) {
+		super("projects"); //$NON-NLS-1$
+		this.wizard = wizard;
+		setTitle(Messages.ProjectNamesPage_title);
+		setDescription(Messages.ProjectNamesPage_desc);
+	}
+
+	@Override
+	public void setVisible(boolean visible) {
+		setPageComplete(wizard.getSelection() != null);
+		if (container != null)
+			updateEntries();
+		super.setVisible(visible);
+	}
+
+	void updateEntries() {
+	    if (isInitialized)
+	        return;
+	    
+		IConfigurationElement selection = wizard.getSelection();
+		if (selection != null) {
+			isInitialized = true;
+			setMessage(null);
+			IConfigurationElement[] projects = selection.getChildren("project"); //$NON-NLS-1$
+			Control[] children = container.getChildren();
+			if (projects.length == 1 && children.length == 2) {
+				Text text = (Text) children[1];
+				text.setText(projects[0].getAttribute("name")); //$NON-NLS-1$
+				validateEntries();
+				return;
+			}
+			// dispose all
+			for (int i = 0; i < children.length; i++) {
+				children[i].dispose();
+			}
+			// create entries
+			if (projects.length == 1) {
+				createEntry(Messages.ProjectNamesPage_projectName, projects[0].getAttribute("name")); //$NON-NLS-1$
+			} else {
+				for (int i = 0; i < projects.length; i++) {
+					String label = NLS.bind(Messages.ProjectNamesPage_multiProjectName, "" + (i + 1)); //$NON-NLS-1$
+					createEntry(label, projects[i].getAttribute("name")); //$NON-NLS-1$
+				}
+			}
+			container.layout();
+			validateEntries();
+		} else {
+			setMessage(Messages.ProjectNamesPage_noSampleFound, IMessageProvider.WARNING);
+		}
+	}
+
+	public String[] getProjectNames() {
+		Control[] children = container.getChildren();
+		String[] names = new String[children.length / 2];
+
+		int index = 0;
+		for (int i = 0; i < children.length; i++) {
+			if (children[i] instanceof Text) {
+				String name = ((Text) children[i]).getText();
+				names[index++] = name;
+			}
+		}
+		return names;
+	}
+
+	private void createEntry(String labelName, String projectName) {
+		Label label = new Label(container, SWT.NULL);
+		label.setText(labelName);
+		label.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_CENTER));
+		final Text text = new Text(container, SWT.SINGLE | SWT.BORDER);
+		text.setText(projectName);
+		text.addModifyListener(new ModifyListener() {
+			@Override
+			public void modifyText(ModifyEvent e) {
+				validateEntries();
+			}
+		});
+		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+	}
+
+	private void validateEntries() {
+		Control[] children = container.getChildren();
+		boolean empty = false;
+
+		HashSet<String> set = new HashSet<>();
+		for (int i = 0; i < children.length; i++) {
+			if (children[i] instanceof Text) {
+				String name = ((Text) children[i]).getText();
+				if (name.length() == 0) {
+					empty = true;
+					break;
+				}
+				IStatus nameStatus = ResourcesPlugin.getWorkspace().validateName(name, IResource.PROJECT);
+				if (!nameStatus.isOK()) {
+					setErrorMessage(nameStatus.getMessage());
+					setPageComplete(false);
+					return;
+				}
+				set.add(name);
+			}
+		}
+		if (empty) {
+			setErrorMessage(Messages.ProjectNamesPage_emptyName);
+			setPageComplete(false);
+		} else {
+			int nnames = set.size();
+			int nfields = children.length / 2;
+			if (nfields > nnames) {
+				setErrorMessage(Messages.ProjectNamesPage_duplicateNames);
+				setPageComplete(false);
+			} else {
+				setPageComplete(true);
+				setErrorMessage(null);
+			}
+		}
+	}
+
+	@Override
+	public void createControl(Composite parent) {
+		container = new Composite(parent, SWT.NULL);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		container.setLayout(layout);
+		setControl(container);
+		updateEntries();
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(container, IHelpContextIds.PROJECT_NAMES);
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/ReviewPage.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/ReviewPage.java
new file mode 100644
index 0000000..0069f9c
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/ReviewPage.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.objectteams.otdt.internal.samples;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.pde.internal.ui.IHelpContextIds;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.HyperlinkSettings;
+import org.eclipse.ui.forms.widgets.ScrolledFormText;
+
+public class ReviewPage extends WizardPage {
+
+	private SampleWizard wizard;
+	private ScrolledFormText formText;
+
+	public ReviewPage(SampleWizard wizard) {
+		super("last"); //$NON-NLS-1$
+		this.wizard = wizard;
+		setTitle(Messages.ReviewPage_title);
+		setDescription(Messages.ReviewPage_desc);
+	}
+
+	@Override
+	public void setVisible(boolean visible) {
+		setPageComplete(wizard.getSelection() != null);
+		if (formText != null)
+			updateContent();
+		super.setVisible(visible);
+	}
+
+	private void updateContent() {
+		StringBuffer buf = new StringBuffer();
+		buf.append("<form>"); //$NON-NLS-1$
+		IConfigurationElement selection = wizard.getSelection();
+		if (selection != null) {
+			setMessage(null);
+			IConfigurationElement[] desc = selection.getChildren("description"); //$NON-NLS-1$
+			if (desc.length == 1)
+				buf.append(NLS.bind(Messages.ReviewPage_descContent, (new String[] {selection.getAttribute("name"), desc[0].getValue()}))); //$NON-NLS-1$
+			else
+				buf.append(NLS.bind(Messages.ReviewPage_content, selection.getAttribute("name"))); //$NON-NLS-1$
+		} else {
+			setMessage(Messages.ReviewPage_noSampleFound, IMessageProvider.WARNING);
+		}
+		buf.append("</form>"); //$NON-NLS-1$
+		formText.setText(buf.toString());
+	}
+
+	@Override
+	public void createControl(Composite parent) {
+		Composite container = new Composite(parent, SWT.NULL);
+		GridLayout layout = new GridLayout();
+		container.setLayout(layout);
+		container.setLayoutData(new GridData(GridData.FILL_BOTH));
+		formText = new ScrolledFormText(container, true);
+		formText.setBackground(parent.getBackground());
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.widthHint = 300;
+		gd.heightHint = 300;
+		formText.setLayoutData(gd);
+		HyperlinkSettings settings = new HyperlinkSettings(parent.getDisplay());
+		formText.getFormText().setHyperlinkSettings(settings);
+		setControl(container);
+		updateContent();
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(container, IHelpContextIds.REVIEW);
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleEditor.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleEditor.java
new file mode 100644
index 0000000..3127ca6
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleEditor.java
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.objectteams.otdt.internal.samples;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.*;
+import org.eclipse.ui.forms.events.HyperlinkAdapter;
+import org.eclipse.ui.forms.events.HyperlinkEvent;
+import org.eclipse.ui.forms.widgets.*;
+import org.eclipse.ui.part.EditorPart;
+
+public class SampleEditor extends EditorPart {
+
+	private FormToolkit toolkit;
+	private ScrolledForm form;
+	private FormText descText;
+	private FormText instText;
+	private InputFileListener inputFileListener;
+
+	class InputFileListener implements IResourceChangeListener, IResourceDeltaVisitor {
+		@Override
+		public void resourceChanged(IResourceChangeEvent event) {
+			if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
+				IResourceDelta delta = event.getDelta();
+				try {
+					delta.accept(this);
+				} catch (CoreException e) {
+					OTSamplesPlugin.logException(e, null, null);
+				}
+			}
+		}
+
+		@Override
+		public boolean visit(IResourceDelta delta) throws CoreException {
+			IResource resource = delta.getResource();
+			if (resource instanceof IFile) {
+				IFile file = (IFile) resource;
+				if (file.equals(((IFileEditorInput) getEditorInput()).getFile())) {
+					if (delta.getKind() == IResourceDelta.REMOVED || delta.getKind() == IResourceDelta.REPLACED)
+						close();
+					return false;
+				}
+			}
+			return true;
+		}
+	}
+
+	public SampleEditor() {
+		PDEPlugin.getDefault().getLabelProvider().connect(this);
+	}
+
+	/**
+	 * @see EditorPart#createPartControl
+	 */
+	@Override
+	public void createPartControl(Composite parent) {
+		toolkit = new FormToolkit(parent.getDisplay());
+		form = toolkit.createScrolledForm(parent);
+		Properties properties = loadContent();
+		form.setText(properties.getProperty("name")); //$NON-NLS-1$
+		TableWrapLayout layout = new TableWrapLayout();
+		layout.verticalSpacing = 10;
+		layout.topMargin = 10;
+		layout.bottomMargin = 10;
+		layout.leftMargin = 10;
+		layout.rightMargin = 10;
+		form.getBody().setLayout(layout);
+
+		final String launcher = properties.getProperty("launcher"); //$NON-NLS-1$
+		final String launchTarget = properties.getProperty("launchTarget"); //$NON-NLS-1$
+
+		descText = toolkit.createFormText(form.getBody(), true);
+		descText.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
+		String desc = properties.getProperty("description"); //$NON-NLS-1$
+		String content = NLS.bind(Messages.SampleEditor_desc, (desc != null ? desc : "")); //$NON-NLS-1$
+		descText.setText(content, true, false);
+		final String helpURL = properties.getProperty("helpHref"); //$NON-NLS-1$
+		if (helpURL != null) {
+			Hyperlink moreLink = toolkit.createHyperlink(form.getBody(), "Read More", SWT.NULL); //$NON-NLS-1$
+			moreLink.addHyperlinkListener(new HyperlinkAdapter() {
+				@Override
+				public void linkActivated(HyperlinkEvent e) {
+					PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(helpURL);
+				}
+			});
+		}
+		instText = toolkit.createFormText(form.getBody(), true);
+		instText.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
+		StringBuffer buf = new StringBuffer();
+		buf.append(Messages.SampleEditor_content);
+		instText.setText(buf.toString(), true, false);
+		final SampleRunner runner = new SampleRunner(properties.getProperty("id"));
+		instText.addHyperlinkListener(new HyperlinkAdapter() {
+			@Override
+			public void linkActivated(HyperlinkEvent e) {
+				Object href = e.getHref();
+				if (href.equals("help")) { //$NON-NLS-1$
+					PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(helpURL);
+				} else if (href.equals("run")) { //$NON-NLS-1$
+					runner.doRun(launcher, launchTarget, false);
+				} else if (href.equals("debug")) { //$NON-NLS-1$
+					runner.doRun(launcher, launchTarget, true);
+				}
+			}
+		});
+		instText.setImage("run", PDEPlugin.getDefault().getLabelProvider().get(PDEPluginImages.DESC_RUN_EXC)); //$NON-NLS-1$
+		instText.setImage("debug", PDEPlugin.getDefault().getLabelProvider().get(PDEPluginImages.DESC_DEBUG_EXC)); //$NON-NLS-1$
+		instText.setImage("help", PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_INFO_TSK)); //$NON-NLS-1$
+	}
+
+	private Properties loadContent() {
+		IStorageEditorInput input = (IStorageEditorInput) getEditorInput();
+		Properties properties = new Properties();
+		try {
+			IStorage storage = input.getStorage();
+			InputStream is = storage.getContents();
+			properties.load(is);
+			is.close();
+		} catch (IOException e) {
+			OTSamplesPlugin.logException(e, null, null);
+		} catch (CoreException e) {
+			OTSamplesPlugin.logException(e, null, null);
+		}
+		return properties;
+	}
+
+	@Override
+	public void dispose() {
+		if (inputFileListener != null) {
+			ResourcesPlugin.getWorkspace().removeResourceChangeListener(inputFileListener);
+			inputFileListener = null;
+		}
+		toolkit.dispose();
+		PDEPlugin.getDefault().getLabelProvider().disconnect(this);
+		super.dispose();
+	}
+
+	/**
+	 * @see EditorPart#setFocus
+	 */
+	@Override
+	public void setFocus() {
+		form.setFocus();
+	}
+
+	/**
+	 * @see EditorPart#doSave
+	 */
+	@Override
+	public void doSave(IProgressMonitor monitor) {
+	}
+
+	/**
+	 * @see EditorPart#doSaveAs
+	 */
+	@Override
+	public void doSaveAs() {
+	}
+
+	/**
+	 * @see EditorPart#isDirty
+	 */
+	@Override
+	public boolean isDirty() {
+		return false;
+	}
+
+	/**
+	 * @see EditorPart#isSaveAsAllowed
+	 */
+	@Override
+	public boolean isSaveAsAllowed() {
+		return false;
+	}
+
+	/**
+	 * @see EditorPart#init
+	 */
+	@Override
+	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+		setSite(site);
+		setInput(input);
+		inputFileListener = new InputFileListener();
+		PDEPlugin.getWorkspace().addResourceChangeListener(inputFileListener);
+	}
+
+	public void close() {
+		Display display = getSite().getShell().getDisplay();
+		display.asyncExec(new Runnable() {
+			@Override
+			public void run() {
+				if (toolkit != null) {
+					getSite().getPage().closeEditor(SampleEditor.this, false);
+				}
+			}
+		});
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleOperation.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleOperation.java
new file mode 100644
index 0000000..f3a82f0
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleOperation.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.objectteams.otdt.internal.samples;
+
+import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.util.Properties;
+import java.util.zip.ZipFile;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+import org.eclipse.ui.wizards.datatransfer.ImportOperation;
+import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
+import org.osgi.framework.Bundle;
+
+public class SampleOperation implements IRunnableWithProgress {
+
+	private static final String SAMPLE_PROPERTIES = "sample.properties"; //$NON-NLS-1$
+
+	private IConfigurationElement sample;
+
+	private String[] projectNames;
+
+	private IFile sampleManifest;
+
+	private IOverwriteQuery query;
+
+	private boolean yesToAll;
+
+	private boolean cancel;
+
+	private IProject[] createdProjects;
+
+	public SampleOperation(IConfigurationElement sample, String[] projectNames, IOverwriteQuery query) {
+		this.sample = sample;
+		this.query = query;
+		this.projectNames = projectNames;
+	}
+
+	public IFile getSampleManifest() {
+		return sampleManifest;
+	}
+
+	public IProject[] getCreatedProjects() {
+		return createdProjects;
+	}
+
+	@Override
+	public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+		try {
+			ICoreRunnable op = new ICoreRunnable() {
+				@Override
+				public void run(IProgressMonitor monitor) throws CoreException {
+					IConfigurationElement[] projects = sample.getChildren("project"); //$NON-NLS-1$
+					SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.SampleOperation_creating,
+							projects.length);
+					createdProjects = new IProject[projects.length];
+					try {
+						for (int i = 0; i < projects.length; i++) {
+							IFile file = importProject(projectNames[i], projects[i],
+									subMonitor.split(1));
+							if (file != null && sampleManifest == null)
+								sampleManifest = file;
+							if (file != null) {
+								createdProjects[i] = file.getProject();
+							}
+							if (cancel)
+								// if user has cancelled operation, exit.
+								break;
+						}
+					} catch (InterruptedException e) {
+						throw new OperationCanceledException();
+					} catch (InvocationTargetException e) {
+						throwCoreException(e);
+					}
+				}
+			};
+			ResourcesPlugin.getWorkspace().run(op, monitor);
+		} catch (CoreException e) {
+			throw new InvocationTargetException(e);
+		} catch (OperationCanceledException e) {
+			throw e;
+		}
+	}
+
+	private void throwCoreException(InvocationTargetException e) throws CoreException {
+		Throwable t = e.getCause();
+		Status status = new Status(IStatus.ERROR, OTSamplesPlugin.PLUGIN_ID, IStatus.OK, e.getMessage(), t);
+		throw new CoreException(status);
+	}
+
+	private IFile importProject(String name, IConfigurationElement config, IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException {
+		String path = config.getAttribute("archive"); //$NON-NLS-1$
+		if (name == null || path == null)
+			return null;
+		IWorkspace workspace = ResourcesPlugin.getWorkspace();
+		IWorkspaceRoot root = workspace.getRoot();
+		IProject project = root.getProject(name);
+		boolean skip = false;
+
+		SubMonitor subMonitor = SubMonitor.convert(monitor, name, 5);
+		if (project.exists()) {
+			if (!yesToAll) {
+				String returnId = query.queryOverwrite(project.getFullPath().toString());
+				if (returnId.equals(IOverwriteQuery.ALL)) {
+					yesToAll = true;
+					skip = false;
+				} else if (returnId.equals(IOverwriteQuery.YES)) {
+					skip = false;
+				} else if (returnId.equals(IOverwriteQuery.NO)) {
+					skip = true;
+				} else if (returnId.equals(IOverwriteQuery.CANCEL)) {
+					skip = true;
+					cancel = true;
+				}
+			}
+			if (!skip) {
+				project.delete(true, true, subMonitor.split(1));
+				project = root.getProject(name);
+			} else {
+				subMonitor.worked(1);
+			}
+		}
+		if (skip) {
+			subMonitor.worked(4);
+			IFile manifest = project.getFile(SAMPLE_PROPERTIES);
+			return manifest;
+		}
+
+		project.create(subMonitor.split(1));
+		project.open(subMonitor.split(1));
+		Bundle bundle = Platform.getBundle(sample.getNamespaceIdentifier());
+		ZipFile zipFile = getZipFileFromPluginDir(path, bundle);
+		importFilesFromZip(zipFile, project.getFullPath(), subMonitor.split(1));
+		return createSampleManifest(project, config, subMonitor.split(1));
+	}
+
+	private IFile createSampleManifest(IProject project, IConfigurationElement config, IProgressMonitor monitor) throws CoreException {
+		IFile file = project.getFile(SAMPLE_PROPERTIES);
+		if (!file.exists()) {
+			try {
+				ByteArrayOutputStream out = new ByteArrayOutputStream();
+				Properties properties = new Properties();
+				createSampleManifestContent(config.getAttribute("name"), properties); //$NON-NLS-1$
+				properties.store(out, ""); //$NON-NLS-1$
+				out.flush();
+				String contents = out.toString();
+				out.close();
+				ByteArrayInputStream stream = new ByteArrayInputStream(contents.getBytes("UTF8")); //$NON-NLS-1$
+				file.create(stream, true, monitor);
+				stream.close();
+			} catch (UnsupportedEncodingException e) {
+			} catch (IOException e) {
+			}
+		}
+		return file;
+	}
+
+	private void createSampleManifestContent(String projectName, Properties properties) {
+		writeProperty(properties, "id", sample.getAttribute("id")); //$NON-NLS-1$ //$NON-NLS-2$
+		writeProperty(properties, "name", sample.getAttribute("name")); //$NON-NLS-1$ //$NON-NLS-2$
+		writeProperty(properties, "projectName", projectName); //$NON-NLS-1$
+		writeProperty(properties, "launcher", sample.getAttribute("launcher")); //$NON-NLS-1$ //$NON-NLS-2$
+		writeProperty(properties, "launchTarget", sample.getAttribute("launchTarget"));//$NON-NLS-1$ //$NON-NLS-2$
+		IConfigurationElement desc[] = sample.getChildren("description"); //$NON-NLS-1$
+		if (desc.length == 1) {
+			writeProperty(properties, "helpHref", desc[0] //$NON-NLS-1$
+					.getAttribute("helpHref")); //$NON-NLS-1$
+			writeProperty(properties, "description", desc[0].getValue()); //$NON-NLS-1$
+		}
+	}
+
+	private void writeProperty(Properties properties, String name, String value) {
+		if (value == null)
+			return;
+		properties.setProperty(name, value);
+	}
+
+	private ZipFile getZipFileFromPluginDir(String pluginRelativePath, Bundle bundle) throws CoreException {
+		try {
+			URL starterURL = FileLocator.resolve(bundle.getEntry(pluginRelativePath));
+			return new ZipFile(FileLocator.toFileURL(starterURL).getFile());
+		} catch (IOException e) {
+			String message = pluginRelativePath + ": " + e.getMessage(); //$NON-NLS-1$
+			Status status = new Status(IStatus.ERROR, OTSamplesPlugin.PLUGIN_ID, IStatus.ERROR, message, e);
+			throw new CoreException(status);
+		}
+	}
+
+	private void importFilesFromZip(ZipFile srcZipFile, IPath destPath, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+		ZipFileStructureProvider structureProvider = new ZipFileStructureProvider(srcZipFile);
+		ImportOperation op = new ImportOperation(destPath, structureProvider.getRoot(), structureProvider, query);
+		op.run(monitor);
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleRunner.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleRunner.java
new file mode 100644
index 0000000..8fc7a78
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleRunner.java
@@ -0,0 +1,135 @@
+package org.eclipse.objectteams.otdt.internal.samples;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.ui.ILaunchShortcut;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+
+class SampleRunner {
+
+	private ILaunchShortcut launchShortcut;
+	final String sampleId;
+
+	public SampleRunner(String sampleId) {
+		this.sampleId = sampleId;
+	}
+
+	void doRun(String launcher, String target, final boolean debug) {
+		try {
+			final ILaunchShortcut fshortcut = getLaunchShortcut(launcher);
+
+			Object launchSelection = getLaunchSelection(target);
+			final ISelection selection = (launchSelection != null) ? new StructuredSelection(launchSelection) : new StructuredSelection();
+
+			BusyIndicator.showWhile(Display.getDefault(), new Runnable() {
+				public void run() {
+					fshortcut.launch(selection, debug ? ILaunchManager.DEBUG_MODE : ILaunchManager.RUN_MODE);
+				}
+			});
+		} catch (CoreException ex) {
+			ErrorDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), 
+					SampleMessages.SamplesAdapter_unable_to_run, SampleMessages.SamplesAdapter_cannot_run_selected,
+					ex.getStatus());
+			OTSamplesPlugin.getDefault().getLog().log(ex.getStatus());
+		}
+	}
+
+	private ILaunchShortcut getLaunchShortcut(String launcher) throws CoreException {
+		if (launchShortcut != null && launchShortcut.getClass().getName().equals(launcher))
+			return launchShortcut;
+		
+		try {
+			Class<?> launcherClass = Class.forName(launcher);
+			launchShortcut = (ILaunchShortcut) launcherClass.newInstance();
+			return launchShortcut;
+		} catch (Exception ex) {
+			IStatus status = OTSamplesPlugin.createErrorStatus("Unable to create launcher", ex); //$NON-NLS-1$
+			throw new CoreException(status);
+		} 
+	}
+
+	// NEW: target is the "launchTarget" property from the launchTarget attribute in the sample.properties
+	//      file or the <sample> configuration element.
+	//      Note: target may be null.
+	// falls back to search a main-class in the first src-folder available.
+	Object getLaunchSelection(String target) throws JavaModelException {
+		IProject project = getProject(sampleId);
+		if (project != null) {
+			IJavaProject javaProject = JavaCore.create(project);
+			if (javaProject.exists()) {
+				if (target != null) {
+					IType targetType = javaProject.findType(target);
+					if (targetType != null)
+						return targetType;
+				}
+				IPackageFragmentRoot[] packageFragmentRoots = javaProject.getPackageFragmentRoots();
+				for (int i = 0; i < packageFragmentRoots.length; i++) {
+					IPackageFragmentRoot root = packageFragmentRoots[i];
+					if (root.getKind() == IPackageFragmentRoot.K_SOURCE)
+						return root;
+				}
+			}
+		}
+		return null;
+	}
+
+	// OT_COPY_PASTE: STATE: 3.2: most parts copy&paste from SampleStandbyContent.doBrowse()
+	IProject getProject(String sid) {
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IProject[] projects = root.getProjects();
+		if (sid == null)
+			return null;
+		for (int i = 0; i < projects.length; i++) {
+			IProject project = projects[i];
+			if (!project.exists() || !project.isOpen())
+				continue;
+			IFile pfile = project.getFile("sample.properties"); //$NON-NLS-1$
+			if (pfile.exists()) {
+				try {
+					InputStream is = pfile.getContents();
+					Properties prop = new Properties();
+					prop.load(is);
+					is.close();
+					String id = prop.getProperty("id"); //$NON-NLS-1$
+					if (id != null && id.equals(sid)) {
+						return project;
+					}
+				} catch (IOException e) {
+					OTSamplesPlugin.logException(e, null, null);
+				} catch (CoreException e) {
+					OTSamplesPlugin.logException(e, null, null);
+				}
+			}
+		}
+		return null;
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleStandbyContent.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleStandbyContent.java
new file mode 100644
index 0000000..a4e4488
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleStandbyContent.java
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.objectteams.otdt.internal.samples;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Properties;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.*;
+import org.eclipse.ui.forms.events.HyperlinkAdapter;
+import org.eclipse.ui.forms.events.HyperlinkEvent;
+import org.eclipse.ui.forms.widgets.*;
+import org.eclipse.ui.intro.IIntroPart;
+import org.eclipse.ui.intro.config.IStandbyContentPart;
+import org.eclipse.ui.part.ISetSelectionTarget;
+
+public class SampleStandbyContent implements IStandbyContentPart {
+
+	private ScrolledForm form;
+	private Hyperlink moreLink;
+	private String helpURL;
+	private String launcher;
+	private String launchTarget;
+	private FormText descText;
+	private FormText instText;
+	private IConfigurationElement sample;
+	// cached input.
+	private String input;
+
+	private static String MEMENTO_SAMPLE_ID_ATT = "sampleId"; //$NON-NLS-1$
+
+	/**
+	 *
+	 */
+	public SampleStandbyContent() {
+		PDEPlugin.getDefault().getLabelProvider().connect(this);
+	}
+
+	@Override
+	public void createPartControl(Composite parent, FormToolkit toolkit) {
+		form = toolkit.createScrolledForm(parent);
+		//form.setBackgroundImage(PDEPlugin.getDefault().getLabelProvider().get(
+		//		PDEPluginImages.DESC_FORM_BANNER));
+		TableWrapLayout layout = new TableWrapLayout();
+		layout.verticalSpacing = 10;
+		layout.topMargin = 10;
+		layout.bottomMargin = 10;
+		layout.leftMargin = 10;
+		layout.rightMargin = 10;
+		form.getBody().setLayout(layout);
+		descText = toolkit.createFormText(form.getBody(), true);
+		descText.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
+		descText.setText("", false, false); //$NON-NLS-1$
+		moreLink = toolkit.createHyperlink(form.getBody(), "Read More", //$NON-NLS-1$
+				SWT.NULL);
+		moreLink.addHyperlinkListener(new HyperlinkAdapter() {
+			@Override
+			public void linkActivated(HyperlinkEvent e) {
+				if (helpURL != null)
+					PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(helpURL);
+			}
+		});
+		instText = toolkit.createFormText(form.getBody(), true);
+		instText.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
+		StringBuffer buf = new StringBuffer();
+		buf.append(Messages.SampleStandbyContent_content);
+		instText.setText(buf.toString(), true, false);
+		
+		final SampleRunner runner = new SampleRunner(sample.getAttribute("id"));
+		instText.addHyperlinkListener(new HyperlinkAdapter() {
+			@Override
+			public void linkActivated(HyperlinkEvent e) {
+				Object href = e.getHref();
+				if (href.equals("help")) { //$NON-NLS-1$
+					PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(helpURL);
+				} else if (href.equals("browse")) { //$NON-NLS-1$
+					doBrowse();
+				} else if (href.equals("run")) { //$NON-NLS-1$
+					runner.doRun(launcher, launchTarget, false);
+				} else if (href.equals("debug")) { //$NON-NLS-1$
+					runner.doRun(launcher, launchTarget, true);
+				}
+			}
+		});
+		instText.setImage("run", PDEPlugin.getDefault().getLabelProvider().get( //$NON-NLS-1$
+				PDEPluginImages.DESC_RUN_EXC));
+		instText.setImage("debug", PDEPlugin.getDefault().getLabelProvider() //$NON-NLS-1$
+				.get(PDEPluginImages.DESC_DEBUG_EXC));
+		instText.setImage("help", PlatformUI.getWorkbench().getSharedImages() //$NON-NLS-1$
+				.getImage(ISharedImages.IMG_OBJS_INFO_TSK));
+	}
+
+	private void doBrowse() {
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IProject[] projects = root.getProjects();
+		ISetSelectionTarget target = findTarget();
+		if (target == null)
+			return;
+		String sid = sample.getAttribute("id"); //$NON-NLS-1$
+		if (sid == null)
+			return;
+		ArrayList<IResource> items = new ArrayList<>();
+		for (int i = 0; i < projects.length; i++) {
+			IProject project = projects[i];
+			if (!project.exists() || !project.isOpen())
+				continue;
+			IFile pfile = project.getFile("sample.properties"); //$NON-NLS-1$
+			if (pfile.exists()) {
+				try {
+					InputStream is = pfile.getContents();
+					Properties prop = new Properties();
+					prop.load(is);
+					is.close();
+					String id = prop.getProperty("id"); //$NON-NLS-1$
+					if (id != null && id.equals(sid)) {
+						//match
+						IResource res = findSelectReveal(project, prop.getProperty("projectName")); //$NON-NLS-1$
+						if (res != null)
+							items.add(res);
+					}
+				} catch (IOException e) {
+					OTSamplesPlugin.logException(e, null, null);
+				} catch (CoreException e) {
+					OTSamplesPlugin.logException(e, null, null);
+				}
+			}
+		}
+		if (items.size() > 0)
+			target.selectReveal(new StructuredSelection(items));
+	}
+
+	private ISetSelectionTarget findTarget() {
+		String id = sample.getAttribute("targetViewId"); //$NON-NLS-1$
+		if (id == null)
+			return null;
+		IViewPart view = OTSamplesPlugin.getActivePage().findView(id);
+		if (view == null || !(view instanceof ISetSelectionTarget))
+			return null;
+		return (ISetSelectionTarget) view;
+	}
+	
+	private IResource findSelectReveal(IProject project, String originalName) {
+		IConfigurationElement[] projects = sample.getChildren("project"); //$NON-NLS-1$
+		for (int i = 0; i < projects.length; i++) {
+			if (originalName.equals(projects[i].getAttribute("name"))) { //$NON-NLS-1$
+				String path = projects[i].getAttribute("selectReveal"); //$NON-NLS-1$
+				if (path == null)
+					continue;
+				IResource res = project.findMember(path);
+				if (res != null && res.exists())
+					return res;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public Control getControl() {
+		return form;
+	}
+
+	public void init(IIntroPart introPart) {
+	}
+
+	@Override
+	public void setInput(Object input) {
+		// if the new input is null, use cached input from momento.
+		if (input != null)
+			this.input = (String) input;
+		String sampleId = this.input.toString();
+		IConfigurationElement[] samples = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.pde.ui.samples"); //$NON-NLS-1$
+		for (int i = 0; i < samples.length; i++) {
+			IConfigurationElement sample = samples[i];
+			String id = sample.getAttribute("id"); //$NON-NLS-1$
+			if (id != null && id.equals(sampleId)) {
+				update(sample);
+				return;
+			}
+		}
+		update(null);
+	}
+
+	private void update(IConfigurationElement sample) {
+		this.sample = sample;
+		if (form == null)
+			return;
+		String title = sample != null ? sample.getAttribute("name") : ""; //$NON-NLS-1$ //$NON-NLS-2$
+		form.setText(title);
+		if (sample != null) {
+			launcher = sample.getAttribute("launcher"); //$NON-NLS-1$
+			launchTarget = sample.getAttribute("launchTarget"); //$NON-NLS-1$
+		} else {
+			launcher = null;
+			launchTarget = null;
+		}
+		IConfigurationElement[] descConfig = sample != null ? sample.getChildren("description") : null; //$NON-NLS-1$
+		if (descConfig != null && descConfig.length == 1) {
+			String desc = descConfig[0].getValue();
+			String content = NLS.bind(Messages.SampleStandbyContent_desc, (desc != null ? desc : "")); //$NON-NLS-1$
+			helpURL = descConfig[0].getAttribute("helpHref"); //$NON-NLS-1$
+			moreLink.setVisible(helpURL != null);
+			descText.setText(content, true, false);
+		} else {
+			moreLink.setVisible(false);
+			descText.setText("", false, false); //$NON-NLS-1$
+		}
+		form.reflow(true);
+	}
+
+	@Override
+	public void setFocus() {
+		form.setFocus();
+	}
+
+	@Override
+	public void dispose() {
+		PDEPlugin.getDefault().getLabelProvider().disconnect(this);
+	}
+
+	@Override
+	public void init(IIntroPart introPart, IMemento memento) {
+		// try to restore last state.
+		input = getCachedInput(memento);
+
+	}
+
+	/**
+	* Tries to create the last content part viewed, based on sample id.
+	*
+	* @param memento
+	*/
+	private String getCachedInput(IMemento memento) {
+		if (memento == null)
+			return null;
+		return memento.getString(MEMENTO_SAMPLE_ID_ATT);
+
+	}
+
+	@Override
+	public void saveState(IMemento memento) {
+		String currentSampleId = input;
+		if (input != null)
+			memento.putString(MEMENTO_SAMPLE_ID_ATT, currentSampleId);
+
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleWizard.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleWizard.java
new file mode 100644
index 0000000..40900e1
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SampleWizard.java
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.objectteams.otdt.internal.samples;
+
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.objectteams.otdt.ui.help.OTHelpPlugin;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.*;
+import org.eclipse.ui.activities.IWorkbenchActivitySupport;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.ISetSelectionTarget;
+import org.osgi.framework.Bundle;
+
+public class SampleWizard extends Wizard implements INewWizard, IExecutableExtension {
+	private IConfigurationElement[] samples;
+	private IConfigurationElement selection;
+	private ProjectNamesPage namesPage;
+	private ReviewPage lastPage;
+
+	private boolean switchPerspective = true;
+	private boolean selectRevealEnabled = true;
+	private boolean activitiesEnabled = true;
+	private IProject[] createdProjects;
+
+	private class ImportOverwriteQuery implements IOverwriteQuery {
+		@Override
+		public String queryOverwrite(String file) {
+			String[] returnCodes = {YES, NO, ALL, CANCEL};
+			int returnVal = openDialog(file);
+			return returnVal < 0 ? CANCEL : returnCodes[returnVal];
+		}
+
+		private int openDialog(final String file) {
+			final int[] result = {IDialogConstants.CANCEL_ID};
+			getShell().getDisplay().syncExec(new Runnable() {
+				@Override
+				public void run() {
+					String title = Messages.SampleWizard_title;
+					String msg = NLS.bind(Messages.SampleWizard_overwrite, file);
+					String[] options = {IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.YES_TO_ALL_LABEL, IDialogConstants.CANCEL_LABEL};
+					MessageDialog dialog = new MessageDialog(getShell(), title, null, msg, MessageDialog.QUESTION, options, 0);
+					result[0] = dialog.open();
+				}
+			});
+			return result[0];
+		}
+	}
+
+	public SampleWizard() {
+		PDEPlugin.getDefault().getLabelProvider().connect(this);
+		setDefaultPageImageDescriptor(PDEPluginImages.DESC_NEWEXP_WIZ);
+		samples = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.pde.ui.samples"); //$NON-NLS-1$ //FIXME
+		namesPage = new ProjectNamesPage(this);
+		lastPage = new ReviewPage(this);
+		setNeedsProgressMonitor(true);
+		setWindowTitle(Messages.ShowSampleAction_title);
+	}
+
+	@Override
+	public void dispose() {
+		PDEPlugin.getDefault().getLabelProvider().disconnect(this);
+		super.dispose();
+	}
+
+	public IConfigurationElement[] getSamples() {
+		return samples;
+	}
+
+	@Override
+	public void addPages() {
+		if (selection == null) {
+			addPage(new SelectionPage(this));
+		}
+		addPage(namesPage);
+		addPage(lastPage);
+	}
+
+	@Override
+	public boolean performFinish() {
+		try {
+			String perspId = selection.getAttribute("perspectiveId"); //$NON-NLS-1$
+			IWorkbenchPage page = OTSamplesPlugin.getActivePage();
+			if (perspId != null && switchPerspective) {
+				PlatformUI.getWorkbench().showPerspective(perspId, page.getWorkbenchWindow());
+			}
+			SampleOperation op = new SampleOperation(selection, namesPage.getProjectNames(), new ImportOverwriteQuery());
+			getContainer().run(true, true, op);
+			createdProjects = op.getCreatedProjects();
+			if (selectRevealEnabled) {
+				selectReveal(getShell());
+			}
+			if (activitiesEnabled)
+				enableActivities();
+		} catch (InvocationTargetException e) {
+			OTSamplesPlugin.logException(e, null, null);
+			return false;
+		} catch (InterruptedException e) {
+			//PDEPlugin.logException(e);
+			return false;
+		} catch (CoreException e) {
+			OTSamplesPlugin.logException(e, null, null);
+			return false;
+		} catch (OperationCanceledException e) {
+			return false;
+		}
+		return true;
+	}
+
+	public void selectReveal(Shell shell) {
+		shell.getDisplay().asyncExec(new Runnable() {
+			public void run() {
+				doSelectReveal();
+			}
+		});
+	}
+
+	private void doSelectReveal() {
+		if (selection == null || createdProjects==null)
+			return;
+		String viewId = selection.getAttribute("targetViewId"); //$NON-NLS-1$
+		if (viewId == null)
+			return;
+		IWorkbenchWindow window = PlatformUI.getWorkbench()
+				.getActiveWorkbenchWindow();
+		if (window == null)
+			return;
+		IWorkbenchPage page = window.getActivePage();
+		if (page == null)
+			return;
+		IViewPart view = page.findView(viewId);
+		if (view == null || !(view instanceof ISetSelectionTarget))
+			return;
+		ISetSelectionTarget target = (ISetSelectionTarget) view;
+		IConfigurationElement[] projects = selection.getChildren("project"); //$NON-NLS-1$
+
+		ArrayList<IResource> items = new ArrayList<IResource>();
+		for (int i = 0; i < projects.length; i++) {
+			String path = projects[i].getAttribute("selectReveal"); //$NON-NLS-1$
+			if (path == null)
+				continue;
+			IResource resource = createdProjects[i].findMember(path);
+			if (resource != null && resource.exists()) {
+				if (resource.getName().equals("Intro0.html")) { //$NON-NLS-1$
+					resource = setBaseTag(createdProjects[i], resource);
+				}
+				items.add(resource);
+			}
+		}
+		if (items.size() > 0)
+			target.selectReveal(new StructuredSelection(items));
+		
+		revealInEditor(items, page);
+	}
+
+	/** Insert a HTML base-tag to enable relative navigation to resources in OTHelp. */
+	private IResource setBaseTag(IProject project, IResource resource) {
+		if (resource instanceof IFile) { 				
+			IFile file = (IFile)resource;
+			try {
+				NullProgressMonitor npm = new NullProgressMonitor();
+				
+				// fetch path to help plugin hosting images/ and guide/otjld/def/:
+				Bundle helpBundle = OTHelpPlugin.getDocPlugin();
+				String absPath = FileLocator.toFileURL(helpBundle.getEntry("/")).toString();  //$NON-NLS-1$
+				String baseTag = "<base href=\""+absPath+"\">\n"; //$NON-NLS-1$ //$NON-NLS-2$
+				
+				// assemble new new file with new content:
+				IFile newFile = project.getFile("Intro.html"); //$NON-NLS-1$
+				ByteArrayInputStream stream = new ByteArrayInputStream(baseTag.getBytes("UTF8")); //$NON-NLS-1$
+				newFile.create(stream, false, npm);
+				newFile.appendContents(file.getContents(), 0, npm);
+				stream.close();
+				resource.delete(false, npm);
+				return newFile;
+			} catch (Exception e) {
+				OTSamplesPlugin.getDefault().getLog().log(
+					OTSamplesPlugin.createErrorStatus("Failed to convert Intro.html", e)); //$NON-NLS-1$
+			}
+		}	
+		return resource;
+	}
+
+	void revealInEditor(List<IResource> items, IWorkbenchPage page) {
+		if (items.size() > 0) {
+			for (IResource resource : items) {
+	            if (resource instanceof IFile) {
+	                try {
+	                    IDE.openEditor(page, (IFile)resource);
+	                }
+	                catch (PartInitException ex)
+	                { /* ignore, user will try to open it manually, then */ } 
+	            }
+	        }
+		}
+	}
+
+	public void enableActivities() {
+		IConfigurationElement[] elements = selection.getChildren("activity"); //$NON-NLS-1$
+		HashSet<String> activitiesToEnable = new HashSet<>();
+		IWorkbenchActivitySupport workbenchActivitySupport = PlatformUI.getWorkbench().getActivitySupport();
+
+		for (int i = 0; i < elements.length; i++) {
+			IConfigurationElement element = elements[i];
+			String id = element.getAttribute("id"); //$NON-NLS-1$
+			if (id == null)
+				continue;
+			activitiesToEnable.add(id);
+		}
+		HashSet<String> set = new HashSet<>(workbenchActivitySupport.getActivityManager().getEnabledActivityIds());
+		set.addAll(activitiesToEnable);
+		workbenchActivitySupport.setEnabledActivityIds(set);
+	}
+
+	/**
+	 *
+	 */
+	@Override
+	public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+		String variable = data != null && data instanceof String ? data.toString() : null;
+		if (variable != null) {
+			for (int i = 0; i < samples.length; i++) {
+				IConfigurationElement element = samples[i];
+				String id = element.getAttribute("id"); //$NON-NLS-1$
+				if (id != null && id.equals(variable)) {
+					setSelection(element);
+					break;
+				}
+			}
+		}
+	}
+
+	@Override
+	public void init(IWorkbench workbench, IStructuredSelection selection) {
+	}
+
+	/**
+	 * @return Returns the selection.
+	 */
+	public IConfigurationElement getSelection() {
+		return selection;
+	}
+
+	/**
+	 * @param selection
+	 *            The selection to set.
+	 */
+	public void setSelection(IConfigurationElement selection) {
+		this.selection = selection;
+	}
+
+	/**
+	 * @param switchPerspective The switchPerspective to set.
+	 * @todo Generated comment
+	 */
+	public void setSwitchPerspective(boolean switchPerspective) {
+		this.switchPerspective = switchPerspective;
+	}
+
+	/**
+	 * @param selectRevealEnabled The selectRevealEnabled to set.
+	 * @todo Generated comment
+	 */
+	public void setSelectRevealEnabled(boolean selectRevealEnabled) {
+		this.selectRevealEnabled = selectRevealEnabled;
+	}
+
+	/**
+	 * @param activitiesEnabled The activitiesEnabled to set.
+	 * @todo Generated comment
+	 */
+	public void setActivitiesEnabled(boolean activitiesEnabled) {
+		this.activitiesEnabled = activitiesEnabled;
+	}
+
+	public void updateEntries() {
+		namesPage.updateEntries();
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SamplesAdapter.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SamplesAdapter.java
deleted file mode 100644
index 2f0a1ef..0000000
--- a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SamplesAdapter.java
+++ /dev/null
@@ -1,456 +0,0 @@
-/**********************************************************************
- * This file is part of "Object Teams Development Tooling"-Software
- * 
- * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
- * for its Fraunhofer Institute for Computer Architecture and Software
- * Technology (FIRST), Berlin, Germany and Technical University Berlin,
- * Germany.
- * 
- * 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
- * $Id: SamplesAdapter.java 23482 2010-02-05 20:16:19Z stephan $
- * 
- * Please visit http://www.eclipse.org/objectteams for updates and contact.
- * 
- * Contributors:
- * Fraunhofer FIRST - Initial API and implementation
- * Technical University Berlin - Initial API and implementation
- * IBM Corporation - copies of individual methods from bound base classes.
- **********************************************************************/
-package org.eclipse.objectteams.otdt.internal.samples;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Properties;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.FileLocator;
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.debug.core.ILaunchManager;
-import org.eclipse.debug.ui.ILaunchShortcut;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jface.dialogs.ErrorDialog;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.objectteams.otdt.ui.help.OTHelpPlugin;
-import org.eclipse.pde.internal.ui.PDEPlugin;
-import org.eclipse.swt.custom.BusyIndicator;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IViewPart;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.ide.IDE;
-import org.eclipse.ui.part.ISetSelectionTarget;
-import org.osgi.framework.Bundle;
-
-import base org.eclipse.pde.internal.ui.samples.ProjectNamesPage;
-import base org.eclipse.pde.internal.ui.samples.SampleEditor;
-import base org.eclipse.pde.internal.ui.samples.SampleOperation;
-import base org.eclipse.pde.internal.ui.samples.SampleStandbyContent;
-import base org.eclipse.pde.internal.ui.samples.SampleWizard;
-import base org.eclipse.pde.internal.ui.samples.ShowSampleAction;
-
-/**
- * @author gis
- */
-@SuppressWarnings("restriction")
-public team class SamplesAdapter
-{
-	boolean _needsAdaptation = false;
-	
-	public boolean isOTSample(String sampleId)
-	{
-		return sampleId != null && sampleId.startsWith("org.eclipse.objectteams.otdt.samples."); //$NON-NLS-1$
-	}
-	
-	public class ShowSampleActionAdapter playedBy ShowSampleAction
-	{
-
-		@SuppressWarnings("basecall")
-		callin boolean ensureSamplesPresent()
-		{
-			String id = getSampleId();
-			if (id != null) {
-				if (SamplesAdapter.this.isOTSample(id))
-					return true; //OT-samples are definitely present
-			}
-			
-			return base.ensureSamplesPresent();
-		}
-		@SuppressWarnings("decapsulation")
-		String getSampleId() -> get String sampleId;
-		@SuppressWarnings("decapsulation")
-		boolean ensureSamplesPresent() <- replace boolean ensureSampleFeaturePresent();
-	}
-	
-	public class ProjectNamesPageAdapter playedBy ProjectNamesPage
-//		base when (SamplesAdapter.this.needsAdaptation())
-	{
-		private boolean _isInitialized;
-
-		// bugfix: avoid executing updateEntries more than once!
-		@SuppressWarnings("basecall")
-		callin void updateEntries() {
-		    if (_isInitialized)
-		        return;
-		    
-		    _isInitialized = (getWizard().getSelection() != null);
-		    
-		    base.updateEntries();
-		}
-		
-		@SuppressWarnings("decapsulation")
-		SampleWizardAdapter getWizard() -> get SampleWizard wizard;
-		@SuppressWarnings("decapsulation")
-		void updateEntries() <- replace void updateEntries();
-	}
-	
-	protected team class SampleWizardAdapter playedBy SampleWizard
-		when (needsAdaptation())
-	{
-		IProject[] _createdProjects;
-		
-		void initializationHook()
-		{
-			// override default behavior
-			setSampleEditorNeeded(false);
-		}
-		
-		protected void setCreatedProjects(IProject[] projects)
-		{
-			_createdProjects = projects;
-		}
-		
-		callin boolean performFinish()
-		{
-			activate(ALL_THREADS); // base call forks, so a per-thread within() is not sufficient
-			try {
-				return base.performFinish();
-			} finally {
-				deactivate(ALL_THREADS);
-			}
-		}
-		
-		
-		@SuppressWarnings("basecall")
-		callin void selectReveal(Shell shell)
-		{
-			shell.getDisplay().asyncExec(new Runnable() {
-				public void run() {
-					SampleWizardAdapter.this.doSelectReveal();
-				}
-			});
-		}
-		
-		// provide commented out method of SampleWizard
-		void doSelectReveal() {
-//{ObjectTeams: added local variables for fields in base class
-			IConfigurationElement selection = getSelection();
-			IProject[] createdProjects = _createdProjects;
-//carp}
-			
-			if (selection == null || createdProjects==null)
-				return;
-			String viewId = selection.getAttribute("targetViewId"); //$NON-NLS-1$
-			if (viewId == null)
-				return;
-			IWorkbenchWindow window = PlatformUI.getWorkbench()
-					.getActiveWorkbenchWindow();
-			if (window == null)
-				return;
-			IWorkbenchPage page = window.getActivePage();
-			if (page == null)
-				return;
-			IViewPart view = page.findView(viewId);
-			if (view == null || !(view instanceof ISetSelectionTarget))
-				return;
-			ISetSelectionTarget target = (ISetSelectionTarget) view;
-			IConfigurationElement[] projects = selection.getChildren("project"); //$NON-NLS-1$
-	
-			ArrayList<IResource> items = new ArrayList<IResource>();
-			for (int i = 0; i < projects.length; i++) {
-				String path = projects[i].getAttribute("selectReveal"); //$NON-NLS-1$
-				if (path == null)
-					continue;
-				IResource resource = createdProjects[i].findMember(path);
-				if (resource != null && resource.exists()) {
-					if (resource.getName().equals("Intro0.html")) { //$NON-NLS-1$
-						resource = setBaseTag(createdProjects[i], resource);
-					}
-					items.add(resource);
-				}
-			}
-			if (items.size() > 0)
-				target.selectReveal(new StructuredSelection(items));
-			
-//{ObjectTeams: reveal in editor as well
-			revealInEditor(items, page);
-//carp}
-		}
-
-		/** Insert a HTML base-tag to enable relative navigation to resources in OTHelp. */
- 		private IResource setBaseTag(IProject project, IResource resource) {
- 			if (resource instanceof IFile) { 				
- 				IFile file = (IFile)resource;
- 				try {
- 					NullProgressMonitor npm = new NullProgressMonitor();
- 					
- 					// fetch path to help plugin hosting images/ and guide/otjld/def/:
- 					Bundle helpBundle = OTHelpPlugin.getDocPlugin();
- 					String absPath = FileLocator.toFileURL(helpBundle.getEntry("/")).toString();  //$NON-NLS-1$
- 					String baseTag = "<base href=\""+absPath+"\">\n"; //$NON-NLS-1$ //$NON-NLS-2$
- 					
- 					// assemble new new file with new content:
- 					IFile newFile = project.getFile("Intro.html"); //$NON-NLS-1$
- 					ByteArrayInputStream stream = new ByteArrayInputStream(baseTag.getBytes("UTF8")); //$NON-NLS-1$
-					newFile.create(stream, false, npm);
- 					newFile.appendContents(file.getContents(), 0, npm);
- 					stream.close();
- 					resource.delete(false, npm);
- 					return newFile;
- 				} catch (Exception e) {
- 					OTSamplesPlugin.getDefault().getLog().log(
- 						OTSamplesPlugin.createErrorStatus("Failed to convert Intro.html", e)); //$NON-NLS-1$
- 				}
- 			}	
- 			return resource;
- 		}
-
-		void revealInEditor(List<IResource> items, IWorkbenchPage page)
-		{
-			if (items.size() > 0)
-			{
-				for (Iterator<IResource> iter = items.iterator(); iter.hasNext();)
-		        {
-		            IResource resource = iter.next();
-		            if (resource instanceof IFile)
-		            {
-		                try {
-		                    IDE.openEditor(page, (IFile)resource);
-		                }
-		                catch (PartInitException ex)
-		                { /* ignore, user will try to open it manually, then */ } 
-		            }
-		        }
-			}
-		}
-		
-		boolean needsAdaptation()
-		{
-			IConfigurationElement selection = getSelection();
-			if (selection == null) return false; // no sample selected
-			String id = selection.getAttribute("id"); //$NON-NLS-1$
-			return SamplesAdapter.this.isOTSample(id);
-		}
-		
-		void initializationHook()      <- before void addPages();
-		boolean performFinish()        <- replace boolean performFinish();
-		void selectReveal(Shell shell) <- replace void selectReveal(Shell shell);
-
-		void setSampleEditorNeeded(boolean sampleEditorNeeded) 
-		                                     -> void setSampleEditorNeeded(boolean sampleEditorNeeded);
-		IConfigurationElement getSelection() -> IConfigurationElement getSelection();
-		
-		public class SampleOperationAdaptor playedBy SampleOperation
-		{
-			void fetchCreatedProjects()
-			{
-				IProject[] projects = getCreatedProjects();
-				if (projects != null)
-					SampleWizardAdapter.this.setCreatedProjects(projects);
-			}
-			
-			// Original implementation doesn't copy the "launchTarget" attribute from configuration element to manifest file
-			void fixCreatedSampleManifestContent(String projectName, Properties properties)
-			{
-				final String attr = "launchTarget"; //$NON-NLS-1$
-				writeProperty(properties, attr, getSample().getAttribute(attr));
-			}
-			
-			void fetchCreatedProjects() <- after void run(IProgressMonitor monitor);
-			
-			void fixCreatedSampleManifestContent(String projectName, Properties properties)
-										<- after void createSampleManifestContent(String projectName, Properties properties);
-
-
-			@SuppressWarnings("decapsulation")
-			void writeProperty(Properties properties, String name, String value)
-			-> void writeProperty(Properties properties, String name, String value);
-			
-			IProject[] getCreatedProjects()   -> IProject[] getCreatedProjects();
-			@SuppressWarnings("decapsulation")
-			IConfigurationElement getSample() -> get IConfigurationElement sample;
-		}
-	}
-	
-	/** This role generalizes over unrelated base classes SampleStandbyContent and SampleEditor. */
-	public abstract class SampleRunner
-	{
-		private ILaunchShortcut launchShortcut;
-
-		@SuppressWarnings("basecall")
-		callin void doRun(String launcher, String target, final boolean debug) 
-		{
-			if (target != null && target.startsWith("org.eclipse.objectteams.")) //$NON-NLS-1$
-			{
-				final ISelection selection;
-				try
-				{
-					Object launchSelection = getLaunchSelection(target);
-					if (launchSelection != null) {
-						selection = new StructuredSelection(launchSelection);
-					} else
-						selection = new StructuredSelection();
-
-					final ILaunchShortcut fshortcut = getLaunchShortcut(launcher);
-
-					BusyIndicator.showWhile(Display.getDefault(), new Runnable() {
-						public void run() {
-							fshortcut.launch(selection, debug
-									? ILaunchManager.DEBUG_MODE
-											: ILaunchManager.RUN_MODE);
-						}
-					});
-				} 
-				catch (CoreException ex)
-				{
-					ErrorDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), 
-							SampleMessages.SamplesAdapter_unable_to_run, SampleMessages.SamplesAdapter_cannot_run_selected,
-							ex.getStatus());
-					OTSamplesPlugin.getDefault().getLog().log(ex.getStatus());
-				}
-			}
-			else
-			{
-				base.doRun(launcher, target, debug);
-			}
-		}
-
-		// NEW: target is the "launchTarget" property from the launchTarget attribute in the sample.properties
-		//      file or the <sample> configuration element.
-		//      Note: target may be null.
-		// falls back to search a main-class in the first src-folder available.
-		private Object getLaunchSelection(String target) throws JavaModelException
-		{
-			IProject project = getProject();
-			if (project != null)
-			{
-				IJavaProject javaProject = JavaCore.create(project);
-				if (javaProject.exists())
-				{
-					if (target != null)
-					{
-						IType targetType = javaProject.findType(target);
-						if (targetType != null)
-							return targetType;
-					}
-					
-					IPackageFragmentRoot[] packageFragmentRoots = javaProject.getPackageFragmentRoots();
-					for (int i = 0; i < packageFragmentRoots.length; i++)
-					{
-						IPackageFragmentRoot root = packageFragmentRoots[i];
-						if (root.getKind() == IPackageFragmentRoot.K_SOURCE)
-							return root;
-					}
-				}
-			}
-			
-			return null;
-		}
-
-		private ILaunchShortcut getLaunchShortcut(String launcher) throws CoreException
-		{
-			if (launchShortcut != null && launchShortcut.getClass().getName().equals(launcher))
-				return launchShortcut;
-			
-			try {
-				Class<?> launcherClass = Class.forName(launcher);
-				launchShortcut = (ILaunchShortcut) launcherClass.newInstance();
-				return launchShortcut;
-			}
-			catch (Exception ex)
-			{
-				IStatus status = OTSamplesPlugin.createErrorStatus("Unable to create launcher", ex); //$NON-NLS-1$
-				throw new CoreException(status);
-			} 
-		}
-
-		// OT_COPY_PASTE: STATE: 3.2: most parts copy&paste from SampleStandbyContent.doBrowse()
-		private IProject getProject()
-		{
-			IWorkspaceRoot root = PDEPlugin.getWorkspace().getRoot();
-			IProject[] projects = root.getProjects();
-			String sid = getSampleID();
-			if (sid == null)
-				return null;
-			for (int i = 0; i < projects.length; i++) {
-				IProject project = projects[i];
-				if (!project.exists() || !project.isOpen())
-					continue;
-				IFile pfile = project.getFile("sample.properties"); //$NON-NLS-1$
-				if (pfile.exists()) {
-					try {
-						InputStream is = pfile.getContents();
-						Properties prop = new Properties();
-						prop.load(is);
-						is.close();
-						String id = prop.getProperty("id"); //$NON-NLS-1$
-						if (id != null && id.equals(sid)) {
-							return project;
-						}
-					} catch (IOException e) {
-						PDEPlugin.logException(e);
-					} catch (CoreException e) {
-						PDEPlugin.logException(e);
-					}
-				}
-			}
-			
-			return null;
-		}
-		
-		protected abstract String getSampleID();
-	}
-	
-	// stupid, stupid...
-	public class SampleStandbyContentAdaptor extends SampleRunner playedBy SampleStandbyContent
-	{
-		@SuppressWarnings("decapsulation")
-		void doRun(String launcher, String target, final boolean debug) <- replace void doRun(String launcher, String target, final boolean debug);
-		
-		@SuppressWarnings("decapsulation")
-		String getSampleID() -> get IConfigurationElement sample with {
-			result <- sample.getAttribute("id") //$NON-NLS-1$
-		}
-	}
-
-	public class SampleEditorAdaptor extends SampleRunner playedBy SampleEditor
-	{
-		@SuppressWarnings("decapsulation")
-		void doRun(String launcher, String target, final boolean debug) <- replace void doRun(String launcher, String target, final boolean debug);
-
-		@SuppressWarnings("decapsulation")
-		String getSampleID() -> Properties loadContent() with {
-			result <- result.getProperty("id") //$NON-NLS-1$
-		}
-	}
-}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SelectionPage.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SelectionPage.java
new file mode 100644
index 0000000..601f4fd
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/SelectionPage.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.objectteams.otdt.internal.samples;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.pde.internal.ui.parts.TablePart;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+public class SelectionPage extends WizardPage {
+
+	private SelectionPart part;
+	private Text desc;
+	private SampleWizard wizard;
+
+	@SuppressWarnings("restriction")
+	class SelectionPart extends TablePart {
+		public SelectionPart() {
+			super(new String[] {"More Info"}); //$NON-NLS-1$
+		}
+
+		@Override
+		protected void buttonSelected(Button button, int index) {
+			if (index == 0)
+				doMoreInfo();
+		}
+
+		@Override
+		protected void selectionChanged(IStructuredSelection selection) {
+			updateSelection(selection);
+		}
+
+		@Override
+		protected void handleDoubleClick(IStructuredSelection selection) {
+		}
+
+		// expose to avoid access warnings outside this class
+		@Override public void setMinimumSize(int width, int height) { super.setMinimumSize(width, height); }
+		@Override public void createControl(Composite parent, int style, int span, FormToolkit toolkit) { super.createControl(parent, style, span, toolkit); }
+		@Override public TableViewer getTableViewer() { return super.getTableViewer(); }
+		@Override public void setButtonEnabled(int index, boolean enabled) { super.setButtonEnabled(index, enabled); }
+	}
+
+	class SampleProvider implements IStructuredContentProvider {
+		@Override
+		public Object[] getElements(Object input) {
+			return wizard.getSamples();
+		}
+	}
+
+	class SampleLabelProvider extends LabelProvider {
+		private Image image;
+
+		public SampleLabelProvider() {
+			image = PDEPlugin.getDefault().getLabelProvider().get(PDEPluginImages.DESC_NEWEXP_TOOL);
+		}
+
+		@Override
+		public String getText(Object obj) {
+			IConfigurationElement sample = (IConfigurationElement) obj;
+			return sample.getAttribute("name"); //$NON-NLS-1$
+		}
+
+		@Override
+		public Image getImage(Object obj) {
+			return image;
+		}
+	}
+
+	/**
+	 * @param pageName
+	 */
+	public SelectionPage(SampleWizard wizard) {
+		super("selection"); //$NON-NLS-1$
+		this.wizard = wizard;
+		setTitle(Messages.SelectionPage_title);
+		setDescription(Messages.SelectionPage_desc);
+		part = new SelectionPart();
+	}
+
+	@Override
+	public void createControl(Composite parent) {
+		Composite container = new Composite(parent, SWT.NULL);
+		GridLayout layout = new GridLayout();
+		container.setLayout(layout);
+		layout.numColumns = 2;
+		part.setMinimumSize(300, 300);
+		part.createControl(container, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, 2, null);
+		part.getTableViewer().setContentProvider(new SampleProvider());
+		part.getTableViewer().setLabelProvider(new SampleLabelProvider());
+		desc = new Text(container, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL);
+		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+		gd.heightHint = 64;
+		desc.setLayoutData(gd);
+		part.getTableViewer().setInput(this);
+		updateSelection(null);
+		setControl(container);
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(container, IHelpContextIds.SELECTION);
+	}
+
+	private void doMoreInfo() {
+		if (wizard.getSelection() != null) {
+			IConfigurationElement desc[] = wizard.getSelection().getChildren("description"); //$NON-NLS-1$
+			String helpHref = desc[0].getAttribute("helpHref"); //$NON-NLS-1$
+			PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(helpHref);
+		}
+	}
+
+	private void updateSelection(IStructuredSelection selection) {
+		if (selection == null) {
+			desc.setText(""); //$NON-NLS-1$
+			part.setButtonEnabled(0, false);
+			setPageComplete(false);
+		} else {
+			IConfigurationElement sample = (IConfigurationElement) selection.getFirstElement();
+			String text = ""; //$NON-NLS-1$
+			String helpHref = null;
+			IConfigurationElement[] sampleDesc = sample.getChildren("description"); //$NON-NLS-1$
+			if (sampleDesc.length == 1) {
+				text = sampleDesc[0].getValue();
+				helpHref = sampleDesc[0].getAttribute("helpHref"); //$NON-NLS-1$
+			}
+			desc.setText(text);
+			part.setButtonEnabled(0, helpHref != null);
+			wizard.setSelection(sample);
+			wizard.updateEntries();
+			setPageComplete(true);
+		}
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/ShowSampleAction.java b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/ShowSampleAction.java
new file mode 100644
index 0000000..1a7d8bd
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/ShowSampleAction.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software 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:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.objectteams.otdt.internal.samples;
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.WorkbenchException;
+import org.eclipse.ui.intro.IIntroSite;
+import org.eclipse.ui.intro.config.*;
+
+public class ShowSampleAction extends Action implements IIntroAction {
+	
+	private String sampleId;
+
+	@Override
+	public void run(IIntroSite site, Properties params) {
+		sampleId = params.getProperty("id"); //$NON-NLS-1$
+		if (sampleId == null)
+			return;
+
+		Runnable r = new Runnable() {
+			@Override
+			public void run() {
+				SampleWizard wizard = new SampleWizard();
+				try {
+					wizard.setInitializationData(null, "class", sampleId); //$NON-NLS-1$
+					wizard.setSwitchPerspective(false);
+					wizard.setSelectRevealEnabled(false);
+					wizard.setActivitiesEnabled(false);
+					WizardDialog dialog = new WizardDialog(getActiveWorkbenchShell(), wizard);
+					dialog.create();
+					if (dialog.open() == Window.OK) {
+						switchToSampleStandby(wizard);
+					}
+				} catch (CoreException e) {
+					OTSamplesPlugin.logException(e, null, null);
+				}
+			}
+		};
+
+		Shell currentShell = getActiveWorkbenchWindow().getShell();
+		currentShell.getDisplay().asyncExec(r);
+	}
+	
+	Shell getActiveWorkbenchShell() {
+		IWorkbenchWindow window = getActiveWorkbenchWindow();
+		if (window != null) {
+			return window.getShell();
+		}
+		return null;
+	}
+
+	IWorkbenchWindow getActiveWorkbenchWindow() {
+		return PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+	}
+
+	private void switchToSampleStandby(SampleWizard wizard) {
+		StringBuffer url = new StringBuffer();
+		url.append("http://org.eclipse.ui.intro/showStandby?"); //$NON-NLS-1$
+		url.append("pluginId=org.eclipse.pde.ui"); //$NON-NLS-1$
+		url.append("&"); //$NON-NLS-1$
+		url.append("partId=org.eclipse.pde.ui.sampleStandbyPart"); //$NON-NLS-1$
+		url.append("&"); //$NON-NLS-1$
+		url.append("input="); //$NON-NLS-1$
+		url.append(sampleId);
+		IIntroURL introURL = IntroURLFactory.createIntroURL(url.toString());
+		if (introURL != null) {
+			introURL.execute();
+			ensureProperContext(wizard);
+		}
+	}
+
+	private void ensureProperContext(SampleWizard wizard) {
+		IConfigurationElement sample = wizard.getSelection();
+		String perspId = sample.getAttribute("perspectiveId"); //$NON-NLS-1$
+		if (perspId != null) {
+			try {
+				wizard.enableActivities();
+				PlatformUI.getWorkbench().showPerspective(perspId, getActiveWorkbenchWindow());
+				wizard.selectReveal(getActiveWorkbenchShell());
+			} catch (WorkbenchException e) {
+				OTSamplesPlugin.logException(e, null, null);
+			}
+		}
+		enableActivities(sample);
+	}
+
+	private void enableActivities(IConfigurationElement sample) {
+		// TODO: what was planned here (never was implemented in pde.ui)
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/messages.properties b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/messages.properties
new file mode 100644
index 0000000..0413e50
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otdt.samples/src/org/eclipse/objectteams/otdt/internal/samples/messages.properties
@@ -0,0 +1,62 @@
+#******************************************************************************
+# Copyright (c) 2016 GK Software 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:
+#     Stephan Herrmann - initial API and implementation
+#******************************************************************************
+SampleWizard_title=Sample Wizard
+SampleWizard_overwrite=Project "{0}" already exists. Do you want to replace it?
+
+ShowSampleAction_title=Object Teams Samples
+
+SelectionPage_title=Selection
+SelectionPage_desc=Select the sample to create from the provided list.
+
+ProjectNamesPage_projectName=Project name:
+ProjectNamesPage_multiProjectName=Project name #&{0}:
+ProjectNamesPage_title=Project names
+ProjectNamesPage_desc=Select project names or accept the defaults.
+
+ProjectNamesPage_noSampleFound=No sample has been selected.
+ProjectNamesPage_duplicateNames=Duplicate project names.
+ProjectNamesPage_emptyName=Project name cannot be empty.
+
+
+ReviewPage_title=Review
+ReviewPage_desc=Review the selected sample.
+ReviewPage_descContent = <p>You have selected the following sample:</p>\
+<p><b>{0}</b></p>\
+<p>{1}</p>\
+<p>If the selection is correct, press <b>Finish</b> to create the sample.</p>
+ReviewPage_content = <p>You have selected the following sample:</p>\
+<p><b>{0}</b></p>\
+<p>If the selection is correct, press <b>Finish</b> to create the sample.</p>
+
+ReviewPage_noSampleFound=No sample has been selected.
+
+SampleEditor_desc=<form>{0}</form>
+SampleEditor_content=<form>\
+<p><b>What you can do with the sample</b></p>\
+<li>Browse the source code in the workspace.</li>\
+<li>When ready, <a href="run">run the sample</a> and follow instructions in the <img href="help"/><a href="help">help document.</a></li>\
+<li>Later on, you can re-run the sample by pressing the <img href="run"/><b>Run</b> icon on the tool bar.</li>\
+<li>If you place breakpoints in the code, you can <a href="debug">debug it.</a></li>\
+<li>Later on, you can debug the sample by pressing the <img href="debug"/><b>Debug</b> icon on the tool bar.</li>\
+</form>
+
+SampleOperation_creating=Creating projects...
+SampleStandbyContent_content=<form>\
+<p><b>What you can do with the sample</b></p>\
+<li><a href="browse">Browse the source code</a> in the workspace.</li>\
+<li>When ready, <a href="run">run the sample</a> and follow instructions in the <img href="help"/><a href="help">help document.</a></li>\
+<li>Later on, you can re-run the sample by pressing the <img href="run"/><b>Run</b> icon on the tool bar.</li>\
+<li>If you place breakpoints in the code, you can <a href="debug">debug it.</a></li>\
+<li>Later on, you can debug the sample by pressing the <img href="debug"/><b>Debug</b> icon on the tool bar.</li>\
+</form>
+SampleStandbyContent_desc=<form>{0}</form>
+
+