### Eclipse Workspace Patch 1.0
#P org.jboss.tools.project.examples
Index: src/org/jboss/tools/project/examples/configurators/IJBossCentralConfigurator.java
===================================================================
--- src/org/jboss/tools/project/examples/configurators/IJBossCentralConfigurator.java	(revision 39172)
+++ src/org/jboss/tools/project/examples/configurators/IJBossCentralConfigurator.java	(working copy)
@@ -26,6 +26,7 @@
 	String getTwitterLink();
 	String getBlogsUrl();
 	String getNewsUrl();
+	String getDownloadRuntimesURL();
 	List<String> getWizardIds();
 	Image getHeaderImage();
 
Index: src/org/jboss/tools/project/examples/configurators/DefaultJBossCentralConfigurator.java
===================================================================
--- src/org/jboss/tools/project/examples/configurators/DefaultJBossCentralConfigurator.java	(revision 39172)
+++ src/org/jboss/tools/project/examples/configurators/DefaultJBossCentralConfigurator.java	(working copy)
@@ -64,6 +64,7 @@
 
 	private static final String NEWS_URL = "http://planet.jboss.org/feeds/news"; //$NON-NLS-1$
 
+	private static final String DOWNLOAD_RUNTIMES_URL = "http://download.jboss.org/examples/download_runtimes.xml"; //$NON-NLS-1$
 	private Image headerImage;
 
 	@Override
@@ -111,4 +112,9 @@
 		}
 		return headerImage;
 	}
+
+	@Override
+	public String getDownloadRuntimesURL() {
+		return DOWNLOAD_RUNTIMES_URL;
+	}
 }
Index: src/org/jboss/tools/project/examples/dialog/DownloadRuntimeDialog.java
===================================================================
--- src/org/jboss/tools/project/examples/dialog/DownloadRuntimeDialog.java	(revision 39808)
+++ src/org/jboss/tools/project/examples/dialog/DownloadRuntimeDialog.java	(working copy)
@@ -24,6 +24,7 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
@@ -391,20 +392,36 @@
 			destination.mkdirs();
 			file = new File (destination, name);
 			int i = 1;
-			while (file.exists()) {
-				file = new File(destination, name + "(" + i++ + ")");
+			boolean download = true;
+			long urlModified = 0;
+			if (deleteOnExit) {
+				while (file.exists()) {
+					file = new File(destination, name + "(" + i++ + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			} else {
+				long cacheModified = file.lastModified();
+				try {
+					urlModified = ECFExamplesTransport.getInstance()
+							.getLastModified(url);
+					download = cacheModified <= 0 || cacheModified != urlModified;
+				} catch (CoreException e) {
+					// ignore
+				}
 			}
-			
 			if (deleteOnExit) {
 				file.deleteOnExit();
 			}
-			out = new BufferedOutputStream(
-					new FileOutputStream(file));
-			
-			IStatus result = ECFExamplesTransport.getInstance().download(file.getName(),
-					url.toExternalForm(), out, monitor);
-			out.flush();
-			out.close();
+			IStatus result = null;
+			if (download) {
+				out = new BufferedOutputStream(new FileOutputStream(file));
+				result = ECFExamplesTransport.getInstance().download(
+						file.getName(), url.toExternalForm(), out, monitor);
+				out.flush();
+				out.close();
+				if (urlModified > 0) {
+					file.setLastModified(urlModified);
+				}
+			}
 			if (monitor.isCanceled()) {
 				file.deleteOnExit();
 				file.delete();
@@ -413,14 +430,19 @@
 			File directory = new File(selectedDirectory);
 			directory.mkdirs();
 			if (!directory.isDirectory()) {
-				ProjectExamplesActivator.getDefault().getLog().log(result);
-				MessageDialog.openError(getActiveShell(), "Error", "The '" + directory + "' is not a directory.");
+				String message = "The '" + directory + "' is not a directory.";
+				if (result != null) {
+					ProjectExamplesActivator.getDefault().getLog().log(result);
+				} else {
+					ProjectExamplesActivator.getDefault().getLog().log(result);
+				}
+				MessageDialog.openError(getActiveShell(), "Error", message);
 				file.deleteOnExit();
 				file.delete();
 				return Status.CANCEL_STATUS;
 			}
 			ProjectExamplesActivator.extractZipFile(file, directory, monitor);
-			if (!result.isOK()) {
+			if (result != null && !result.isOK()) {
 				ProjectExamplesActivator.getDefault().getLog().log(result);
 				String message;
 				if (result.getException() != null) {
Index: src/org/jboss/tools/project/examples/ProjectExamplesActivator.java
===================================================================
--- src/org/jboss/tools/project/examples/ProjectExamplesActivator.java	(revision 40479)
+++ src/org/jboss/tools/project/examples/ProjectExamplesActivator.java	(working copy)
@@ -34,6 +34,10 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.apache.commons.lang.StringEscapeUtils;
 import org.eclipse.core.filesystem.EFS;
 import org.eclipse.core.filesystem.IFileStore;
@@ -51,6 +55,7 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Platform;
@@ -127,13 +132,18 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Version;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
 
 /**
  * The activator class controls the plug-in life cycle
  */
 public class ProjectExamplesActivator extends AbstractUIPlugin {
 
-	private static final String SEPARATOR = "/";
+	private static final String SEPARATOR = "/"; //$NON-NLS-1$
 
 	private static final int DESCRIPTION_LENGTH = 100;
 	
@@ -226,6 +236,8 @@
 	private static final String URL = "url"; //$NON-NLS-1$
 
 	private static final String DISCLAIMER = "disclaimer"; //$NON-NLS-1$
+
+	private static final String DOWNLOAD_RUNTIMES_FILE = "download_runtime.xml"; //$NON-NLS-1$
 	
 	private Map<String, DownloadRuntime> downloadRuntimes;
 	
@@ -1178,10 +1190,86 @@
 					downloadRuntimes.put(id, downloadRuntime);
 				}
 			}
+			addExternalRuntimes();
 		}
 		return downloadRuntimes;
 	}
 	
+	private void addExternalRuntimes() {
+		if (downloadRuntimes == null) {
+			return;
+		}
+		String urlString = getConfigurator().getDownloadRuntimesURL();
+		File cacheFile = null;
+		try {
+			long cacheModified = 0;
+			IPath location = ProjectExamplesActivator.getDefault()
+					.getStateLocation();
+			cacheFile = new File(location.toFile(), DOWNLOAD_RUNTIMES_FILE);
+			if (cacheFile.isFile()) {
+				cacheModified = cacheFile.lastModified();
+			}
+			URL url = new URL(urlString);
+			long urlModified;
+			try {
+				urlModified = ECFExamplesTransport.getInstance()
+						.getLastModified(url);
+			} catch (Exception e) {
+				urlModified = -1;
+			}
+			if (cacheModified == 0 || urlModified != cacheModified) {
+				File tempFile = File
+						.createTempFile("download_runtimes", ".xml");  //$NON-NLS-1$//$NON-NLS-2$
+				tempFile.deleteOnExit();
+				OutputStream destination = new FileOutputStream(tempFile);
+				IStatus status = ECFExamplesTransport.getInstance().download(
+						DOWNLOAD_RUNTIMES_FILE, urlString, destination,
+						new NullProgressMonitor());
+				if (status.isOK() && url != null) {
+					cacheModified = ECFExamplesTransport.getInstance()
+							.getLastModified(url);
+					ProjectExamplesActivator.copyFile(tempFile, cacheFile);
+					tempFile.delete();
+					cacheFile.setLastModified(cacheModified);
+				}
+			}
+		} catch (Exception e) {
+			log(e);
+		}
+		if (cacheFile != null && cacheFile.isFile()) {
+			try {
+				DocumentBuilderFactory dbf = DocumentBuilderFactory
+						.newInstance();
+				DocumentBuilder db = dbf.newDocumentBuilder();
+				Document doc = db.parse(cacheFile);
+				NodeList runtimes = doc.getElementsByTagName("runtime"); //$NON-NLS-1$
+				int len = runtimes.getLength();
+				for (int i = 0; i < len; i++) {
+					Node node = runtimes.item(i);
+					if (node.getNodeType() == Node.ELEMENT_NODE) {
+						Element element = (Element) node;
+						String id = element.getAttribute("id"); //$NON-NLS-1$
+						String name = element.getAttribute("name"); //$NON-NLS-1$
+						String version = element.getAttribute("version"); //$NON-NLS-1$
+						String url = element.getAttribute("url"); //$NON-NLS-1$
+						String disclaimer = element.getAttribute("disclaimer"); //$NON-NLS-1$
+						if (id == null || name == null || version == null || url == null) {
+							ProjectExamplesActivator.log("Invalid runtime: id=" + id + ",name=" + 
+									name + ",version=" + version + ",url=" + url);
+						} else {
+							DownloadRuntime runtime = new DownloadRuntime(id, name, version, url);
+							runtime.setDisclaimer("true".equals(disclaimer)); //$NON-NLS-1$
+							downloadRuntimes.put(id, runtime);
+						}
+					}
+				}
+			} catch (Exception e) {
+				ProjectExamplesActivator.log(e);
+			} 
+		}
+	}
+
+	
 	public IJBossCentralConfigurator getConfigurator() {
 		if (configurator == null) {
 			IExtensionRegistry registry = Platform.getExtensionRegistry();
