*** empty log message ***
diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/DefaultSiteParser.java b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/DefaultSiteParser.java
index 6947d33..6ea9ef8 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/DefaultSiteParser.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/DefaultSiteParser.java
@@ -33,7 +33,9 @@
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.osgi.util.NLS;
+import org.eclipse.update.core.IURLEntry;
 import org.eclipse.update.core.SiteFeatureReferenceModel;
+import org.eclipse.update.core.URLEntry;
 import org.eclipse.update.internal.core.Digest;
 import org.eclipse.update.internal.core.ExtendedSite;
 import org.eclipse.update.internal.core.LiteFeature;
@@ -96,6 +98,8 @@
 	private static final String CATEGORY = "category"; //$NON-NLS-1$
 	private static final String DESCRIPTION = "description"; //$NON-NLS-1$
 	private static final String MIRROR = "mirror"; //$NON-NLS-1$
+	private static final String ASSOCIATE_SITES = "associateSites"; //$NON-NLS-1$
+	private static final String ASSOCIATE_SITE = "associateSite"; //$NON-NLS-1$
 
 	private static final String DEFAULT_INFO_URL = "index.html"; //$NON-NLS-1$
 	private static final String FEATURES = "features/"; //$NON-NLS-1$
@@ -544,6 +548,14 @@
 			}
 		}
 		
+		if ( (site instanceof ExtendedSite) && (attributes.getValue("associateSitesURL") != null)) { //$NON-NLS-1$
+			IURLEntry[] associateSites = getAssociateSites(attributes.getValue("associateSitesURL"), factory); //$NON-NLS-1$
+			if (associateSites != null)
+				((ExtendedSite)site).setAssociateSites(associateSites);
+			else 
+				site.setMirrorsURLString(mirrorsURL);
+		}
+		
 		objectStack.push(site);
 
 		if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING)
@@ -854,6 +866,43 @@
 		}
 	}
 	
+	private static IURLEntry[] getAssociateSites(String associateSitesURL, SiteModelFactory factory) {
+	    
+		try {
+		    DocumentBuilderFactory domFactory = 
+		    DocumentBuilderFactory.newInstance();
+		    DocumentBuilder builder = domFactory.newDocumentBuilder();
+		    Document document = builder.parse(associateSitesURL);
+		    if (document == null)
+		    	return null;
+		    NodeList mirrorNodes = document.getElementsByTagName(ASSOCIATE_SITE); 
+		    URLEntry[] mirrors = new URLEntry[mirrorNodes.getLength()];
+		    for (int i=0; i<mirrorNodes.getLength(); i++) {
+		    	Element mirrorNode = (Element)mirrorNodes.item(i);
+				mirrors[i] = new URLEntry();
+				String infoURL = mirrorNode.getAttribute("url"); //$NON-NLS-1$
+				String label = mirrorNode.getAttribute("label"); //$NON-NLS-1$
+				mirrors[i].setURLString(infoURL);
+				mirrors[i].setAnnotation(label);
+
+				if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING)
+					debug("Processed mirror: url:" + infoURL + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$
+		    }
+		    return mirrors;
+		}
+		catch (Exception e) {
+		    // log if absolute url
+		    if (associateSitesURL != null &&
+		    		(associateSitesURL.startsWith("http://") //$NON-NLS-1$
+					|| associateSitesURL.startsWith("https://") //$NON-NLS-1$
+					|| associateSitesURL.startsWith("file://") //$NON-NLS-1$
+					|| associateSitesURL.startsWith("ftp://") //$NON-NLS-1$
+					|| associateSitesURL.startsWith("jar://"))) //$NON-NLS-1$
+		    	UpdateCore.log(Messages.DefaultSiteParser_mirrors, e);
+			return null;
+		}
+	}
+	
 	private LiteFeature[] getLightFeatures(ExtendedSite site) {
 		
 		URL fullDigestURL;
diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/ExtendedSite.java b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/ExtendedSite.java
index 88630b6..1412abe 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/ExtendedSite.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/ExtendedSite.java
@@ -13,6 +13,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.update.core.IURLEntry;
 import org.eclipse.update.internal.model.SiteWithTimestamp;
 
 public class ExtendedSite extends SiteWithTimestamp /*Site*/ {
@@ -22,8 +23,10 @@
 	private String[] availableLocals;
 	private String digestURL;
 	private LiteFeature[] liteFeatures;
+	private IURLEntry[] associateSites;
 	private boolean pack200 = false;
 	
+	
 	public String getDigestURL() {
 		return digestURL;
 	}
@@ -113,5 +116,11 @@
 		
 		return result;	
 	}
+	public IURLEntry[] getAssociateSites() {
+		return associateSites;
+	}
+	public void setAssociateSites(IURLEntry[] associateSites) {
+		this.associateSites = associateSites;
+	}
 
 }
diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/search/UpdateSearchRequest.java b/update/org.eclipse.update.core/src/org/eclipse/update/search/UpdateSearchRequest.java
index 0079758..143a323 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/search/UpdateSearchRequest.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/search/UpdateSearchRequest.java
@@ -12,6 +12,10 @@
 
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
 
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -25,6 +29,7 @@
 import org.eclipse.update.core.ISiteWithMirrors;
 import org.eclipse.update.core.IURLEntry;
 import org.eclipse.update.core.SiteManager;
+import org.eclipse.update.internal.core.ExtendedSite;
 import org.eclipse.update.internal.core.Messages;
 import org.eclipse.update.internal.operations.UpdateUtils;
 import org.eclipse.update.internal.search.SiteSearchCategory;
@@ -59,6 +64,23 @@
 	private UpdateSearchScope scope;
 	private boolean searchInProgress = false;
 	private AggregateFilter aggregateFilter = new AggregateFilter();
+	
+	private static class UpdateSearchSite
+	extends UpdateSiteAdapter
+	implements IUpdateSearchSite {
+	private String[] categoriesToSkip;
+
+	public UpdateSearchSite(
+		String label,
+		URL siteURL,
+		String[] categoriesToSkip) {
+		super(label, siteURL);
+		this.categoriesToSkip = categoriesToSkip;
+	}
+	public String[] getCategoriesToSkip() {
+		return categoriesToSkip;
+	}
+}
 
 	class MirroredUpdateSiteAdapter extends UpdateSiteAdapter {
 		public MirroredUpdateSiteAdapter(IURLEntry mirror) {
@@ -215,6 +237,12 @@
 		searchInProgress = true;
 		IUpdateSearchQuery[] queries = category.getQueries();
 		IUpdateSearchSite[] candidates = scope.getSearchSites();
+		Set visitedSitesURL = new HashSet();
+		Set visitedSites = new HashSet();
+		for(int i = 0; i < candidates.length; i++) {
+			visitedSitesURL.add(candidates[i].getURL());
+			//visitedSites.add(candidates[i]);
+		}
 		URL updateMapURL = scope.getUpdateMapURL();
 		boolean searchFeatureProvidedSites = scope.isFeatureProvidedSitesEnabled();
 
@@ -245,6 +273,7 @@
 						statusList.add(status);
 				}
 				
+				List combinedAssociateSites = new ArrayList();
 				for (int i = 0; i < queries.length; i++) {
 					IUpdateSearchQuery query = queries[i];
 					IQueryUpdateSiteAdapter qsite = query.getQuerySearchSite();
@@ -258,19 +287,23 @@
 							continue;
 						SubProgressMonitor subMonitor =
 							new SubProgressMonitor(monitor, 1);
+						List associateSites = new ArrayList();
 						IStatus status =
 							searchOneSite(
 								mappedSite,
 								null,
 								query,
 								collector,
+								associateSites,
 								subMonitor,
 								true);
 						if (status != null)
 							statusList.add(status);
 						if (monitor.isCanceled())
 							break;
+						combinedAssociateSites = combineAssociateSites( combinedAssociateSites, associateSites, visitedSitesURL, visitedSites);
 					}
+					
 					for (int j = 0; j < candidates.length; j++) {
 						if (monitor.isCanceled()) {
 							break;
@@ -278,16 +311,48 @@
 						IUpdateSearchSite source = candidates[j];
 						SubProgressMonitor subMonitor =
 							new SubProgressMonitor(monitor, 1);
+						List associateSites = new ArrayList();
 						IStatus status =
 							searchOneSite(
 								source,
 								source.getCategoriesToSkip(),
 								query,
 								collector,
+								associateSites,
 								subMonitor,
 								true);
 						if (status != null)
 							statusList.add(status);
+						combinedAssociateSites = combineAssociateSites( combinedAssociateSites, associateSites, visitedSitesURL, visitedSites);
+					}
+					if (monitor.isCanceled())
+						break;
+					
+					
+					for(int associateSitesDepth = 0; associateSitesDepth < 5; associateSitesDepth++) {
+						List tempCombinedSites = new ArrayList();
+						Iterator combinedAssociateSitesIterator = combinedAssociateSites.iterator();
+						while(combinedAssociateSitesIterator.hasNext()) {
+							
+							IUpdateSearchSite source = (IUpdateSearchSite)combinedAssociateSitesIterator.next();
+							
+							List associateSites = new ArrayList();
+							SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 1);
+							IStatus status =
+								searchOneSite(
+									source,
+									source.getCategoriesToSkip(),
+									query,
+									collector,
+									associateSites,
+									subMonitor,
+									true);
+							combinedAssociateSites = combineAssociateSites( tempCombinedSites, associateSites, visitedSitesURL, visitedSites);
+							if (status != null)
+								statusList.add(status);
+						}	
+						combinedAssociateSites = tempCombinedSites;
+						
 					}
 					if (monitor.isCanceled())
 						break;
@@ -300,7 +365,13 @@
 		}
 		searchInProgress = false;
 		monitor.done();
+		
 
+		Iterator visitedSitesIterator = visitedSites.iterator();
+		while (visitedSitesIterator.hasNext()) {
+			IUpdateSearchSite associateSite = (IUpdateSearchSite)visitedSitesIterator.next();
+			scope.addSearchSite(associateSite.getLabel(), associateSite.getURL(), null);
+		}
 		if (statusList.size() > 0) {
 			IStatus[] children =
 				(IStatus[]) statusList.toArray(new IStatus[statusList.size()]);
@@ -311,11 +382,28 @@
 					children,
 					Messages.Search_networkProblems, 
 					null);
+			System.out.println("U ERROR"); //$NON-NLS-1$
 			throw new CoreException(multiStatus);
 		}
 	}
 
 
+	private List combineAssociateSites(List combinedAssociateSites, List associateSites, Set visitedSitesURL, Set visitedSites) {
+		Iterator iterator = associateSites.iterator();
+
+		while(iterator.hasNext()) {
+			UpdateSearchSite associateSite = (UpdateSearchSite)iterator.next();
+			if ( !visitedSitesURL.contains(associateSite.getURL())) {
+				combinedAssociateSites.add(associateSite);
+				visitedSitesURL.add(associateSite.getURL());
+				visitedSites.add(associateSite);
+			}
+			
+		}
+		return combinedAssociateSites;
+	}
+
+
 /*
  * See if this query site adapter is mapped in the map file
  * to a different URL.
@@ -339,6 +427,7 @@
 		String[] categoriesToSkip,
 		IUpdateSearchQuery query,
 		IUpdateSearchResultCollector collector,
+		List associateSites,
 		SubProgressMonitor monitor,
 		boolean checkMirrors)
 		throws CoreException {
@@ -361,6 +450,7 @@
 				return null;
 			}
 			
+			
 			// prompt the user to pick up a site (do not recursively go into mirror sites on the mirror site)
 			if ((collector instanceof IUpdateSearchResultCollectorFromMirror) &&
 				(site instanceof ISiteWithMirrors) &&
@@ -369,7 +459,7 @@
 				IURLEntry mirror = ((IUpdateSearchResultCollectorFromMirror)collector).getMirror((ISiteWithMirrors)site, siteAdapter.getLabel());
 				
 				if (mirror != null) 
-					return searchOneSite(new MirroredUpdateSiteAdapter(mirror), categoriesToSkip, query, collector, new SubProgressMonitor(monitor,1), false);
+					return searchOneSite(new MirroredUpdateSiteAdapter(mirror), categoriesToSkip, query, collector, associateSites, new SubProgressMonitor(monitor,1), false);
 			}
 		} catch (CoreException e) {
 			// Test the exception. If the exception is
@@ -389,6 +479,15 @@
 		text = NLS.bind(Messages.UpdateSearchRequest_checking, siteAdapter.getLabel());
 		monitor.getWrappedProgressMonitor().subTask(text);
 
+		if (site instanceof ExtendedSite) {
+			//System.out.println("ExtendedSite is here"); //$NON-NLS-1$
+			IURLEntry[] associateSitesList = ((ExtendedSite)site).getAssociateSites(); 
+			if (associateSitesList != null) {
+				for(int i = 0; i < associateSitesList.length; i++) {
+					associateSites.add(new UpdateSearchSite(associateSitesList[i].getAnnotation(), associateSitesList[i].getURL(), null));
+				}
+			}
+		}
 		query.run(
 			site,
 			categoriesToSkip,