Index: DefaultSwingInstallerManager.java
===================================================================
--- DefaultSwingInstallerManager.java	(revision 40580)
+++ DefaultSwingInstallerManager.java	(revision 40581)
@@ -38,7 +38,10 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
+import java.util.ListIterator;
 
 import org.gvsig.i18n.Messages;
 import org.gvsig.installer.lib.api.Dependencies;
@@ -71,6 +74,229 @@
  */
 public class DefaultSwingInstallerManager implements SwingInstallerManager {
 
+	public class DefaultUrlAndLabel implements UrlAndLabel {
+
+		private URL url;
+		private String label;
+
+		public DefaultUrlAndLabel(URL url, String label) {
+			this.url = url;
+			this.label = label;
+		}
+		public URL getURL() {
+			return this.url;
+		}
+
+		public String getLabel() {
+			return this.label;
+		}
+		
+		public void setLabel(String label) {
+			this.label = label;
+		}
+		@Override
+		public String toString() {
+			if( label == null ) {
+				return this.url.toString();
+			}
+			return this.label + " - " + this.url.toString();
+		}
+	}
+
+	/**
+	 * 
+	 * This class is for compatibility with deprecated method 
+	 * List<URL> getDefaultDownloadURLs()
+	 *  
+	 * @author jjdelcerro
+	 *
+	 */
+	public class DefaultDownloadURLsIterator<URL> implements ListIterator<URL> {
+		private List<UrlAndLabel> urlAndLabels;
+		private ListIterator<UrlAndLabel> it;
+		
+		DefaultDownloadURLsIterator(List<UrlAndLabel> urlAndLabels, int index) {
+			this.urlAndLabels = urlAndLabels;
+			this.it = this.urlAndLabels.listIterator(index);
+		}
+
+		DefaultDownloadURLsIterator(List<UrlAndLabel> urlAndLabels) {
+			this.urlAndLabels = urlAndLabels;
+			this.it = this.urlAndLabels.listIterator();
+		}
+
+		public boolean hasNext() {
+			return this.it.hasNext();
+		}
+
+		public URL next() {
+			UrlAndLabel value = this.it.next();
+			if( value == null ) {
+				return null;
+			}
+			return (URL) value.getURL();
+		}
+
+		public boolean hasPrevious() {
+			return it.hasPrevious();
+		}
+
+		public int nextIndex() {
+			return it.nextIndex();
+		}
+
+		public URL previous() {
+			UrlAndLabel value = this.it.previous();
+			if( value == null ) {
+				return null;
+			}
+			return (URL) value.getURL();
+		}
+
+		public int previousIndex() {
+			return it.previousIndex();
+		}
+
+		public void remove() {
+			throw new UnsupportedOperationException("This is read-only");
+		}
+
+		public void add(Object arg0) {
+			throw new UnsupportedOperationException("This is read-only");
+		}
+
+		public void set(Object arg0) {
+			throw new UnsupportedOperationException("This is read-only");
+		}
+	}
+	
+	/**
+	 * 
+	 * This class is for compatibility with deprecated method 
+	 * List<URL> getDefaultDownloadURLs()
+	 *  
+	 * @author jjdelcerro
+	 *
+	 */
+	public class DefaultDownloadURLs<URL> implements List<URL> {
+
+		private List<UrlAndLabel> urlAndLabels;
+
+		DefaultDownloadURLs(List<UrlAndLabel> urlAndLabels) {
+			this.urlAndLabels = urlAndLabels;
+		}
+		
+		public boolean add(Object url) {
+			throw new UnsupportedOperationException("This is a read-only list");
+		}
+
+		public void add(int arg0, Object url) {
+			throw new UnsupportedOperationException("This is a read-only list");
+		}
+
+		public boolean addAll(Collection arg0) {
+			throw new UnsupportedOperationException("This is a read-only list");
+		}
+
+		public boolean addAll(int arg0, Collection arg1) {
+			throw new UnsupportedOperationException("This is a read-only list");
+		}
+
+		public void clear() {
+			throw new UnsupportedOperationException("This is a read-only list");
+		}
+
+		public boolean contains(Object arg0) {
+			Iterator<UrlAndLabel> it = this.urlAndLabels.iterator();
+			while( it.hasNext() ) {
+				UrlAndLabel x = it.next();
+				if( x.getURL().equals(arg0) ) {
+					return true;
+				}
+			}
+			return false;
+		}
+
+		public boolean containsAll(Collection arg0) {
+			throw new UnsupportedOperationException("This method is not supported");
+		}
+
+		public URL get(int arg0) {
+			return (URL) this.urlAndLabels.get(arg0).getURL();
+		}
+
+		public int indexOf(Object arg0) {
+			for( int i=0; i<this.urlAndLabels.size(); i++) {
+				if( this.urlAndLabels.get(i).getURL().equals(arg0) ) {
+					return i;
+				}
+			}
+			return -1;
+		}
+
+		public boolean isEmpty() {
+			return this.urlAndLabels.isEmpty();
+		}
+
+		public Iterator iterator() {
+			return new DefaultDownloadURLsIterator(this.urlAndLabels);
+		}
+
+		public int lastIndexOf(Object arg0) {
+			for( int i=this.urlAndLabels.size()-1; i>=0; i--) {
+				if( this.urlAndLabels.get(i).getURL().equals(arg0) ) {
+					return i;
+				}
+			}
+			return -1;
+		}
+
+		public ListIterator listIterator() {
+			return new DefaultDownloadURLsIterator(this.urlAndLabels);
+		}
+
+		public ListIterator listIterator(int arg0) {
+			return new DefaultDownloadURLsIterator(this.urlAndLabels, arg0);
+		}
+
+		public boolean remove(Object arg0) {
+			throw new UnsupportedOperationException("This is a read-only list");
+		}
+
+		public URL remove(int arg0) {
+			throw new UnsupportedOperationException("This is a read-only list");
+		}
+
+		public boolean removeAll(Collection arg0) {
+			throw new UnsupportedOperationException("This is a read-only list");
+		}
+
+		public boolean retainAll(Collection arg0) {
+			throw new UnsupportedOperationException("This is a read-only list");
+		}
+
+		public Object set(int arg0, Object arg1) {
+			throw new UnsupportedOperationException("This is a read-only list");
+		}
+
+		public int size() {
+			return this.urlAndLabels.size();
+		}
+
+		public List subList(int arg0, int arg1) {
+			throw new UnsupportedOperationException("This method is not supported");
+		}
+
+		public Object[] toArray() {
+			throw new UnsupportedOperationException("This method is not supported");
+		}
+
+		public Object[] toArray(Object[] arg0) {
+			throw new UnsupportedOperationException("This method is not supported");
+		}
+		
+	}
+	
 	private static Logger logger = LoggerFactory
 			.getLogger(DefaultSwingInstallerManager.class);
 
@@ -81,7 +307,7 @@
 			.getExtensionPointManager();
 
 	private String applicationVersion = "1.0.0";
-	private List<URL> defaultDownloadURLs = new ArrayList<URL>();
+	private List<UrlAndLabel> defaultDownloadURLs = new ArrayList<UrlAndLabel>();
 
 	public String getText(String key) {
 		return Messages.getText(key);
@@ -113,9 +339,17 @@
 		if (defaultDownloadURLs.size() < 1) {
 			return null;
 		}
-		return defaultDownloadURLs.get(0);
+		return defaultDownloadURLs.get(0).getURL();
 	}
 
+	public List<URL> getDefaultDownloadURLs() {
+		return new DefaultDownloadURLs(this.defaultDownloadURLs);
+	}
+
+    public List<UrlAndLabel> getDefaultDownloadUrlAndLabels() {
+    	return this.defaultDownloadURLs;
+    }
+    
 	public void setDefaultDownloadURL(String defaultDownloadURLs) {
 		String[] urls = defaultDownloadURLs.split(";");
 		for (int i = 0; i < urls.length; i++) {
@@ -160,26 +394,45 @@
 	}
 
 	public void addDefaultDownloadURL(URL url) {
-		if( !this.defaultDownloadURLs.contains(url)) {
-			this.defaultDownloadURLs.add(url);
+		addDefaultDownloadURL(url,null);
+	}
+	
+	public void addDefaultDownloadURL(URL url, String label) {
+		Iterator<UrlAndLabel> it = this.defaultDownloadURLs.iterator();
+		while( it.hasNext() ) {
+			DefaultUrlAndLabel value = (DefaultUrlAndLabel) it.next();
+			if( value.getURL().equals(url) ) {
+				if( value.getLabel() == null ) {
+					value.setLabel(label);
+				}
+				// Already exists the url, don't duplicate.
+				return;
+			}
 		}
+		this.defaultDownloadURLs.add( new DefaultUrlAndLabel(url, label));
 	}
 	
 	public void addDefaultDownloadURL(String url) throws MalformedURLException {
+		String label = null;
+		
+		if( url.startsWith("#") ) {
+			return;
+		}
 		Version version = getInstallerManager().createVersion();
 		String versionFormat = version.getMajor() + "." + version.getMinor()
 				+ "." + version.getRevision();
+		int n = url.indexOf("##");
+		if( n>0 ) {
+			label = url.substring(n+2);
+			url = url.substring(0, n-1);
+		}
 		url = url.replace("$version", versionFormat);
 		url = url.replace("<%Version%>", versionFormat);
 		url = url.replace("$build", Integer.toString(version.getBuild()));
 		url = url.replace("<%Build%>", Integer.toString(version.getBuild()));
-		addDefaultDownloadURL(new URL(url));
+		addDefaultDownloadURL(new URL(url), label);
 	}
 
-	public List<URL> getDefaultDownloadURLs() {
-		return this.defaultDownloadURLs;
-	}
-
 	public InstallerManager getInstallerManager() {
 		return InstallerLocator.getInstallerManager();
 	}
