[540499] Provide ability to hide generic "Validate" menu entry contributed in org.eclipse.wst.validation.ui
diff --git a/features/org.eclipse.wst.common_core.feature/feature.xml b/features/org.eclipse.wst.common_core.feature/feature.xml
index c8dfaf6..19fb5a1 100644
--- a/features/org.eclipse.wst.common_core.feature/feature.xml
+++ b/features/org.eclipse.wst.common_core.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature

       id="org.eclipse.wst.common_core.feature"

       label="%featureName"

-      version="3.9.1.qualifier"

+      version="3.10.0.qualifier"
       provider-name="%providerName"

       license-feature="org.eclipse.license"

       license-feature-version="1.0.1.qualifier">

diff --git a/features/org.eclipse.wst.common_core.feature/pom.xml b/features/org.eclipse.wst.common_core.feature/pom.xml
index 799c542..2672e62 100644
--- a/features/org.eclipse.wst.common_core.feature/pom.xml
+++ b/features/org.eclipse.wst.common_core.feature/pom.xml
@@ -21,7 +21,7 @@
 

   <groupId>org.eclipse.webtools.common</groupId>

   <artifactId>org.eclipse.wst.common_core.feature</artifactId>

-  <version>3.9.1-SNAPSHOT</version>

+  <version>3.10.0-SNAPSHOT</version>
   <packaging>eclipse-feature</packaging>

 

   <build>

diff --git a/features/org.eclipse.wst.common_ui.feature/feature.xml b/features/org.eclipse.wst.common_ui.feature/feature.xml
index ffe7d0d..5c44aad 100644
--- a/features/org.eclipse.wst.common_ui.feature/feature.xml
+++ b/features/org.eclipse.wst.common_ui.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature

       id="org.eclipse.wst.common_ui.feature"

       label="%featureName"

-      version="3.9.2.qualifier"

+      version="3.10.0.qualifier"
       provider-name="%providerName"

       license-feature="org.eclipse.license"

       license-feature-version="1.0.1.qualifier">

diff --git a/features/org.eclipse.wst.common_ui.feature/pom.xml b/features/org.eclipse.wst.common_ui.feature/pom.xml
index 498d423..da22dff 100644
--- a/features/org.eclipse.wst.common_ui.feature/pom.xml
+++ b/features/org.eclipse.wst.common_ui.feature/pom.xml
@@ -21,7 +21,7 @@
 
   <groupId>org.eclipse.webtools.common</groupId>
   <artifactId>org.eclipse.wst.common_ui.feature</artifactId>
-  <version>3.9.2-SNAPSHOT</version>
+  <version>3.10.0-SNAPSHOT</version>
   <packaging>eclipse-feature</packaging>
 
   <build>
diff --git a/plugins/org.eclipse.wst.common.core/.classpath b/plugins/org.eclipse.wst.common.core/.classpath
index 21f2a57..184d4e5 100644
--- a/plugins/org.eclipse.wst.common.core/.classpath
+++ b/plugins/org.eclipse.wst.common.core/.classpath
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src-search"/>
+	<classpathentry kind="src" path="src-properties"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/plugins/org.eclipse.wst.common.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.common.core/META-INF/MANIFEST.MF
index a1e6e2f..836e65e 100644
--- a/plugins/org.eclipse.wst.common.core/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.wst.common.core/META-INF/MANIFEST.MF
@@ -2,7 +2,8 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.wst.common.core; singleton:=true
-Bundle-Version: 1.2.0.qualifier
+Automatic-Module-Name: org.eclipse.wst.common.core
+Bundle-Version: 1.3.0.qualifier
 Bundle-Activator: org.eclipse.wst.common.core.search.SearchPlugin
 Bundle-Localization: plugin
 Export-Package: org.eclipse.wst.common.core.search,
@@ -11,10 +12,11 @@
  org.eclipse.wst.common.core.search.pattern,
  org.eclipse.wst.common.core.search.scope,
  org.eclipse.wst.common.core.search.util,
- org.eclipse.wst.common.core.util
-Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)"
-Eclipse-LazyStart: true
+ org.eclipse.wst.common.core.util,
+ org.eclipse.wst.common.core.internal;x-internal:=true
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.15.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.12.0,4.0.0)",
+ org.eclipse.core.expressions;bundle-version="[3.6.0,4.0.0)"
+Bundle-ActivationPolicy: lazy
 Bundle-Vendor: %pluginProvider
 Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/plugins/org.eclipse.wst.common.core/build.properties b/plugins/org.eclipse.wst.common.core/build.properties
index 1f5bbdd..317adcd 100644
--- a/plugins/org.eclipse.wst.common.core/build.properties
+++ b/plugins/org.eclipse.wst.common.core/build.properties
@@ -1,4 +1,5 @@
-source.. = src-search/
+source.. = src-search/,\
+           src-properties/
 output.. = bin/
 bin.includes = META-INF/,\
                .,\
diff --git a/plugins/org.eclipse.wst.common.core/plugin.xml b/plugins/org.eclipse.wst.common.core/plugin.xml
index 5d2a621..c9185ea 100644
--- a/plugins/org.eclipse.wst.common.core/plugin.xml
+++ b/plugins/org.eclipse.wst.common.core/plugin.xml
@@ -4,6 +4,17 @@
    <extension-point id="searchParticipants" name="%searchParticipants" />
    <extension-point id="uiTester" name="UI Tester" schema="schema/uiTester.exsd"/>
    <extension-point id="uiContextSensitiveClass" name="UI Context Sensitive Class" schema="schema/uiContextSensitiveClass.exsd"/>
+
+   <!-- product property value tester -->
+   <extension point="org.eclipse.core.expressions.propertyTesters">
+      <propertyTester
+            class="org.eclipse.wst.common.core.internal.ProductPropertyTester"
+            id="org.eclipse.wst.common.core.productPropertyTest"
+            namespace="org.eclipse.wst.common.core"
+            properties="productProperty"
+            type="java.lang.Object">
+      </propertyTester>
+   </extension>
 </plugin>
 
 
diff --git a/plugins/org.eclipse.wst.common.core/pom.xml b/plugins/org.eclipse.wst.common.core/pom.xml
index 9cc96be..6a59a01 100644
--- a/plugins/org.eclipse.wst.common.core/pom.xml
+++ b/plugins/org.eclipse.wst.common.core/pom.xml
@@ -21,6 +21,6 @@
 

   <groupId>org.eclipse.webtools.common</groupId>

   <artifactId>org.eclipse.wst.common.core</artifactId>

-  <version>1.2.0-SNAPSHOT</version>

+  <version>1.3.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>

 </project>

diff --git a/plugins/org.eclipse.wst.common.core/src-properties/org/eclipse/wst/common/core/internal/ProductPropertyTester.java b/plugins/org.eclipse.wst.common.core/src-properties/org/eclipse/wst/common/core/internal/ProductPropertyTester.java
new file mode 100644
index 0000000..7c98c96
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.core/src-properties/org/eclipse/wst/common/core/internal/ProductPropertyTester.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2018 IBM Corporation and others.
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.common.core.internal;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.core.runtime.IProduct;
+import org.eclipse.core.runtime.Platform;
+
+public class ProductPropertyTester extends PropertyTester {
+
+	public ProductPropertyTester() {
+	}
+
+	public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+		IProduct product = Platform.getProduct();
+		if (product != null && args.length > 0) {
+			if (expectedValue != null)
+				return expectedValue.equals(product.getProperty(args[0].toString()));
+			else
+				return product.getProperty(args[0].toString()) == null;
+		}
+		return false;
+	}
+
+}
diff --git a/plugins/org.eclipse.wst.validation.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.validation.ui/META-INF/MANIFEST.MF
index 0efa586..b41cd88 100644
--- a/plugins/org.eclipse.wst.validation.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.wst.validation.ui/META-INF/MANIFEST.MF
@@ -2,21 +2,25 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name.0
 Bundle-SymbolicName: org.eclipse.wst.validation.ui; singleton:=true
-Bundle-Version: 1.2.501.qualifier
+Automatic-Module-Name: org.eclipse.wst.validation.ui
+Bundle-Version: 1.2.600.qualifier
 Bundle-Activator: org.eclipse.wst.validation.internal.ui.plugin.ValidationUIPlugin
 Bundle-Vendor: %Bundle-Vendor.0
 Bundle-Localization: plugin
 Export-Package: org.eclipse.wst.validation.internal.ui;x-internal:=true,
  org.eclipse.wst.validation.internal.ui.plugin;x-internal:=true
 Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.13.0,4.0.0)",
  org.eclipse.ui;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.swt;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.wst.common.core;bundle-version="[1.3.0,2.0.0)",
  org.eclipse.wst.common.frameworks.ui;bundle-version="[1.1.200,2.0.0)",
  org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
  org.eclipse.wst.common.frameworks;bundle-version="[1.1.200,2.0.0)",
  org.eclipse.wst.validation;bundle-version="[1.2.0,2.0.0)",
  org.eclipse.ui.forms;bundle-version="[3.3.100,4.0.0)",
- org.eclipse.wst.common.project.facet.core;bundle-version="[1.4.102,2.0.0)"
+ org.eclipse.ui.workbench;bundle-version="[3.108.0,4.0.0)",
+ org.eclipse.wst.common.project.facet.core;bundle-version="[1.4.102,2.0.0)",
+ org.eclipse.core.expressions;bundle-version="[3.6.200,4.0.0)",
+ org.eclipse.core.commands;bundle-version="[3.9.0,4.0.0)"
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.wst.validation.ui/plugin.properties b/plugins/org.eclipse.wst.validation.ui/plugin.properties
old mode 100644
new mode 100755
index 887dfc0..9c1aed1
--- a/plugins/org.eclipse.wst.validation.ui/plugin.properties
+++ b/plugins/org.eclipse.wst.validation.ui/plugin.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2001, 2009 IBM Corporation and others.
+# Copyright (c) 2001, 2018 IBM Corporation 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
@@ -13,6 +13,8 @@
 #
 VBF_TITLE_PROPERTIES=Validation
 VBF_UI_POPUP_RUNVALIDATION=&Validate
+VBF_UI_POPUP_RUNVALIDATION_NOMNEMONIC=Validate
+VBF_UI_POPUP_RUNVALIDATIONDESC=Invoke registered Validators
 VBF_TITLE_PREFERENCE=Validation
 
 Bundle-Name.0 = Validation Framework UI
diff --git a/plugins/org.eclipse.wst.validation.ui/plugin.xml b/plugins/org.eclipse.wst.validation.ui/plugin.xml
old mode 100644
new mode 100755
index 20502a4..d808a18
--- a/plugins/org.eclipse.wst.validation.ui/plugin.xml
+++ b/plugins/org.eclipse.wst.validation.ui/plugin.xml
@@ -1,27 +1,69 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?eclipse version="3.0"?>
 <plugin>
+	<extension point="org.eclipse.ui.commands">
+		<command
+			description="%VBF_UI_POPUP_RUNVALIDATIONDESC"
+			id="org.eclipse.wst.validation.ValidationCommand"
+			name="%VBF_UI_POPUP_RUNVALIDATION_NOMNEMONIC" />
+	</extension>
 
-    
-<!-- ============================================== -->
-<!-- Popup Contributions                            -->
-<!-- ============================================== -->
-<!-- By saying "adaptable=true", this item will appear on both IProject and IJavaProject -->
-   <extension
-         point="org.eclipse.ui.popupMenus">
-      <objectContribution
-            adaptable="true"
-            objectClass="org.eclipse.core.resources.IResource"
-            id="ValidationMenuAction">
-         <action
-               label="%VBF_UI_POPUP_RUNVALIDATION"
-               class="org.eclipse.wst.validation.internal.ui.ValidationMenuAction"
-               menubarPath="additions"
-               enablesFor="+"
-               id="ValidationAction">
-         </action>
-      </objectContribution>      
-   </extension>
+    <extension point="org.eclipse.ui.handlers">
+       <handler
+             class="org.eclipse.wst.validation.internal.ui.ValidationHandler"
+             commandId="org.eclipse.wst.validation.ValidationCommand">
+             <enabledWhen>
+	           <or>
+		        <with variable="activePart">
+					<test forcePluginActivation="true"
+						property="org.eclipse.ui.ide.editor.input"
+						value="ignored?"/>
+		        </with>
+				<with variable="selection">
+                    <iterate ifEmpty="false">
+	                    <adapt type="org.eclipse.core.resources.IResource">
+	                    </adapt>
+                    </iterate>
+                </with>
+               </or>
+             </enabledWhen>
+       </handler>
+	</extension>
+
+ 	<extension point="org.eclipse.ui.menus">
+     <menuContribution locationURI="popup:org.eclipse.ui.popup.any?endof=additions" allPopups="true">
+		<command commandId="org.eclipse.wst.validation.ValidationCommand" id="ValidationCommand" style="push" icon="icons/ok_tbl.gif" disabledIcon="icons/ok_tbl_disabled.gif">
+		   <visibleWhen checkEnabled="false">
+           <and>
+	           <not>
+		           <systemTest
+		                 property="org.eclipse.wst.validation.ui.disable.validation.context.menu" value="true">
+		           </systemTest>
+	           </not>
+	           <not>
+				<test forcePluginActivation="true"
+					property="org.eclipse.wst.common.core.productProperty"
+					args="org.eclipse.wst.validation.ui.disable.validation.context.menu"
+					value="true" />
+	           </not>
+	           <or>
+		        <with variable="activePart">
+					<test forcePluginActivation="true"
+						property="org.eclipse.ui.ide.editor.input"
+						value="ignored?"/>
+		        </with>
+				<with variable="selection">
+                    <iterate ifEmpty="false">
+	                    <adapt type="org.eclipse.core.resources.IResource">
+	                    </adapt>
+                    </iterate>
+                </with>
+               </or>
+              </and>
+			</visibleWhen>
+		</command>
+	</menuContribution>
+	</extension>
   
 
 <!-- ====================================================== -->
diff --git a/plugins/org.eclipse.wst.validation.ui/pom.xml b/plugins/org.eclipse.wst.validation.ui/pom.xml
index 36f98da..6a603b8 100644
--- a/plugins/org.eclipse.wst.validation.ui/pom.xml
+++ b/plugins/org.eclipse.wst.validation.ui/pom.xml
@@ -21,6 +21,6 @@
 

   <groupId>org.eclipse.webtools.common</groupId>

   <artifactId>org.eclipse.wst.validation.ui</artifactId>

-  <version>1.2.501-SNAPSHOT</version>

+  <version>1.2.600-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>

 </project>

diff --git a/plugins/org.eclipse.wst.validation.ui/validateui/org/eclipse/wst/validation/internal/ui/ValidationHandler.java b/plugins/org.eclipse.wst.validation.ui/validateui/org/eclipse/wst/validation/internal/ui/ValidationHandler.java
new file mode 100644
index 0000000..12fec81
--- /dev/null
+++ b/plugins/org.eclipse.wst.validation.ui/validateui/org/eclipse/wst/validation/internal/ui/ValidationHandler.java
@@ -0,0 +1,317 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2018 IBM Corporation and others.
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.validation.internal.ui;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.part.IContributedContentsView;
+import org.eclipse.wst.validation.internal.ConfigurationManager;
+import org.eclipse.wst.validation.internal.DisabledResourceManager;
+import org.eclipse.wst.validation.internal.ValManager;
+import org.eclipse.wst.validation.internal.ValType;
+import org.eclipse.wst.validation.internal.ValidationSelectionHandlerRegistryReader;
+import org.eclipse.wst.validation.internal.ui.plugin.ValidationUIPlugin;
+import org.eclipse.wst.validation.ui.internal.ManualValidationRunner;
+
+public class ValidationHandler extends AbstractHandler {
+	private IResourceVisitor _folderVisitor;
+	private IResourceVisitor _projectVisitor;
+	private Map<IProject, Set<IResource>> _selectedResources;
+
+	public ValidationHandler() {
+		_selectedResources = new HashMap<IProject, Set<IResource>>();
+	}
+
+	void addSelected(IResource selected) {
+		IProject project = selected.getProject();
+		boolean added = _selectedResources.containsKey(project);
+		Set<IResource> changedRes = null;
+		if (added) {
+			// If the value is null, the entire project needs to be validated anyway.
+			changedRes = _selectedResources.get(project);
+			if (changedRes == null)
+				return;
+
+		} else {
+			changedRes = new HashSet<IResource>();
+		}
+		if (changedRes.add(selected)) {
+			_selectedResources.put(project, changedRes);
+		}
+	}
+
+	private void addSelected(ValidateAction action, Object selected) {
+		if (selected instanceof IProject) {
+			addVisitor((IProject) selected);
+		} else if (selected instanceof IFile) {
+			addSelected((IFile) selected);
+		} else if (selected instanceof IFolder) {
+			addVisitor((IFolder) selected);
+		} else if (isValidType(getExtendedType(selected))) {
+			addSelected(action, getExtendedType(selected));
+		} else {
+			// Not a valid input type. Must be IProject, IJavaProject, or IResource.
+			// If this ValidationMenuAction is a delegate of ValidateAction, is
+			// the input type recognized by the ValidateAction?
+			boolean valid = false;
+			if (action != null) {
+				IResource[] resources = action.getResource(selected);
+				if (resources != null) {
+					valid = true;
+					for (int i = 0; i < resources.length; i++) {
+						addSelected(action, resources[i]);
+					}
+				}
+			}
+			if (!valid) {
+				IResource resource = Platform.getAdapterManager().getAdapter(selected, IResource.class);
+				if (resource != null) {
+					valid = true;
+					addSelected(action, resource);
+				}
+			}
+			if (!valid) {
+				// Stop processing. This allows the "Run Validation" menu item
+				// to gray out once an element that can not be validated is selected.
+				_selectedResources.clear();
+			}
+		}
+	}
+
+	private void addVisitor(IFolder selected) {
+		// add the folder and its children
+		try {
+			selected.accept(getFolderVisitor());
+		} catch (CoreException exc) {
+			ValidationUIPlugin.getPlugin().handleException(exc);
+			return;
+		}
+	}
+
+	private void addVisitor(IProject selected) {
+		// add the folder and its children
+		if (!selected.isAccessible())
+			return;
+		try {
+			selected.accept(getProjectVisitor());
+		} catch (CoreException exc) {
+			ValidationUIPlugin.getPlugin().handleException(exc);
+			return;
+		}
+	}
+
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		Shell activeShell = HandlerUtil.getActiveShell(event);
+		IWorkbenchPart interestedPart = HandlerUtil.getActivePart(event);
+
+		IStructuredSelection sel = HandlerUtil.getCurrentStructuredSelection(event);
+		Map<IProject, Set<IResource>> projects = loadSelected(sel);
+
+		if (projects == null || projects.isEmpty()) {
+			if (!(interestedPart instanceof IEditorPart)) {
+				IContributedContentsView contributedContentsView = interestedPart
+						.getAdapter(IContributedContentsView.class);
+				if (contributedContentsView != null) {
+					interestedPart = contributedContentsView.getContributingPart();
+				}
+			}
+			if (interestedPart instanceof IEditorPart) {
+				IEditorInput editorInput = HandlerUtil.getActiveEditorInput(event);
+				if (editorInput != null) {
+					IResource resource = editorInput.getAdapter(IResource.class);
+					if (resource != null) {
+						sel = new StructuredSelection(resource);
+					}
+				}
+			}
+			projects = loadSelected(sel);
+		}
+
+		if (projects == null || projects.isEmpty()) {
+			return null;
+		}
+		// If the files aren't saved do not run validation.
+		if (!handleFilesToSave(projects, activeShell))
+			return null;
+
+		boolean confirm = ValManager.getDefault().getGlobalPreferences()
+				.getConfirmDialog();
+		ManualValidationRunner.validate(projects, ValType.Manual, confirm);
+
+		return null;
+	}
+
+	private Object getExtendedType(Object selected) {
+		Object result = ValidationSelectionHandlerRegistryReader.getInstance().getExtendedType(selected);
+		return result == null ? selected : result;
+	}
+
+	private IResourceVisitor getFolderVisitor() {
+		if (_folderVisitor == null) {
+			_folderVisitor = new IResourceVisitor() {
+				public boolean visit(IResource res) {
+					if (res instanceof IFile) {
+						addSelected(res);
+					} else if (res instanceof IFolder) {
+						addSelected(res);
+					}
+					return true; // visit the resource's children
+				}
+			};
+		}
+		return _folderVisitor;
+	}
+
+	protected List<IFile> getIFiles(Map<IProject, Set<IResource>> projects) {
+		List<IFile> fileList = new LinkedList<IFile>();
+		for (IProject project : projects.keySet()) {
+			for (IResource resource : projects.get(project)) {
+				if (resource instanceof IFile)
+					fileList.add((IFile) resource);
+			}
+		}
+		return fileList;
+	}
+
+	private IResourceVisitor getProjectVisitor() {
+		if (_projectVisitor == null) {
+			_projectVisitor = new IResourceVisitor() {
+				public boolean visit(IResource res) {
+					if (DisabledResourceManager.getDefault().isDisabled(res))
+						return false;
+					if (res instanceof IFile)
+						addSelected(res);
+					else if (res instanceof IFolder)
+						addSelected(res);
+					else if (res instanceof IProject)
+						addSelected(res);
+
+					return true;
+				}
+			};
+		}
+		return _projectVisitor;
+	}
+
+	/**
+	 * Handle any files that must be saved prior to running validation.
+	 * 
+	 * @param projects The list of projects that will be validated.
+	 * @return True if all files have been saved, false otherwise.
+	 */
+	protected boolean handleFilesToSave(Map<IProject, Set<IResource>> projects, Shell shell) {
+		List fileList = getIFiles(projects);
+		final IEditorPart[] dirtyEditors = SaveFilesHelper.getDirtyEditors(fileList);
+		if (dirtyEditors == null || dirtyEditors.length == 0)
+			return true;
+		boolean saveAutomatically = false;
+		try {
+			saveAutomatically = ConfigurationManager.getManager().getGlobalConfiguration().getSaveAutomatically();
+		} catch (InvocationTargetException e) {
+			// In this case simply default to false.
+		}
+		SaveFilesDialog sfDialog = null;
+		if (!saveAutomatically) {
+			sfDialog = new SaveFilesDialog(
+					ValidationUIPlugin.getPlugin().getWorkbench().getActiveWorkbenchWindow().getShell());
+			sfDialog.setInput(Arrays.asList(dirtyEditors));
+		}
+
+		if (saveAutomatically || sfDialog.open() == Window.OK) {
+			ProgressMonitorDialog ctx = new ProgressMonitorDialog(shell);
+
+			IRunnableWithProgress runnable = new IRunnableWithProgress() {
+				public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+					try {
+						SubMonitor submonitor = SubMonitor.convert(monitor, ValidationUIMessages.SaveFilesDialog_saving, dirtyEditors.length);
+						for (int i = 0; i < dirtyEditors.length; i++) {
+							dirtyEditors[i].doSave(submonitor.newChild(1));
+						}
+					} finally {
+						monitor.done();
+					}
+				}
+			};
+
+			try {
+				ctx.run(false, true, runnable);
+				return true;
+			} catch (InvocationTargetException e) {
+				ValidationUIPlugin.getPlugin().handleException(e);
+			} catch (InterruptedException e) {
+				ValidationUIPlugin.getPlugin().handleException(e);
+			}
+		}
+		return false;
+	}
+
+	private boolean isValidType(Object object) {
+		return object instanceof IProject || object instanceof IFile || object instanceof IFolder;
+	}
+
+	/**
+	 * Return a map of the selected elements. Each key of the map is an IProject,
+	 * and the value is a Set of the selected resources in that project. If a
+	 * project is selected, and nothing else in the project is selected, a full
+	 * validation (null value) will be done on the project. If a project is
+	 * selected, and some files/folders in the project are also selected, only the
+	 * files/folders will be validated. If a folder is selected, all of its contents
+	 * are also validated.
+	 * 
+	 * @return null if there is no selection.
+	 */
+	private Map<IProject, Set<IResource>> loadSelected(IStructuredSelection selection) {
+		// GRK previously this did not do a clear, but I couldn't understand why that
+		// would be so I am forcing a clear
+		// GRK In my testing, not doing a clear caused duplicate validations
+		_selectedResources.clear();
+		if ((selection == null) || selection.isEmpty() )
+			return null;
+
+		Object[] elements = selection.toArray();
+		for (Object element : elements) {
+			if (element != null)
+				addSelected(null, element);
+		}
+		return _selectedResources;
+	}
+}