84386 Site Caching Performance Issues
diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/InternalSiteManager.java b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/InternalSiteManager.java
index 674a330..2f7f6d5 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/InternalSiteManager.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/InternalSiteManager.java
@@ -10,16 +10,28 @@
  *******************************************************************************/

 package org.eclipse.update.internal.core;

 

+import java.io.File;

+import java.io.IOException;

+import java.net.MalformedURLException;

+import java.net.URL;

+import java.util.HashMap;

+import java.util.Map;

 

-import java.io.*;

-import java.net.*;

-import java.util.*;

-

-import org.eclipse.core.runtime.*;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.core.runtime.MultiStatus;

+import org.eclipse.core.runtime.NullProgressMonitor;

 import org.eclipse.osgi.util.NLS;

-import org.eclipse.update.configuration.*;

-import org.eclipse.update.core.*;

-import org.eclipse.update.core.model.*;

+import org.eclipse.update.configuration.ILocalSite;

+import org.eclipse.update.core.ISite;

+import org.eclipse.update.core.ISiteFactory;

+import org.eclipse.update.core.ISiteFactoryExtension;

+import org.eclipse.update.core.JarContentReference;

+import org.eclipse.update.core.Site;

+import org.eclipse.update.core.Utilities;

+import org.eclipse.update.core.model.InvalidSiteTypeException;

+import org.eclipse.update.internal.model.ITimestamp;

 

 /**

  * 

@@ -35,6 +47,8 @@
 

 	// cache found sites

 	private static Map sites = new HashMap();

+	// cache http updated url

+	private static Map httpSitesUpdatedUrls = new HashMap();

 	// cache timestamps

 	private static Map siteTimestamps = new HashMap();

 	public static boolean globalUseCache = true;

@@ -95,6 +109,9 @@
 

 		// use cache if set up globally (globalUseCache=true)

 		// and passed as parameter (useCache=true)

+		if (httpSitesUpdatedUrls.containsKey(siteURL.toExternalForm())) {

+			siteURL = (URL)httpSitesUpdatedUrls.get(siteURL.toExternalForm());

+		}

 		String siteURLString = siteURL.toExternalForm();

 		if ((useCache && globalUseCache) && isValidCachedSite(siteURL)) {

 			site = (ISite) sites.get(siteURLString);

@@ -160,12 +177,16 @@
 		}

 

 		if (site != null) {

-			sites.put(siteURL.toExternalForm(), site);

-			try {

-				Response response = UpdateCore.getPlugin().get(URLEncoder.encode(siteURL));

-				siteTimestamps.put(siteURL, new Long(response.getLastModified()));

-			} catch (MalformedURLException e) {

-			} catch (IOException e) {

+			sites.put(site.getURL().toExternalForm(), site);

+			if (site instanceof ITimestamp) {

+				siteTimestamps.put(site.getURL(), new Long(((ITimestamp)site).getTimestamp().getTime()));

+			} else {

+				try {

+					Response response = UpdateCore.getPlugin().get(URLEncoder.encode(siteURL));

+					siteTimestamps.put(siteURL, new Long(response.getLastModified()));

+				} catch (MalformedURLException e) {

+				} catch (IOException e) {

+				}

 			}

 		}

 

@@ -241,56 +262,45 @@
 	 * 4 open the stream	

 	 */

 	private static ISite createSite(String siteType, URL url, IProgressMonitor monitor) throws CoreException, InvalidSiteTypeException {

+		

 		if (monitor == null) monitor = new NullProgressMonitor();

-		ISite site = null;

 		ISiteFactory factory = SiteTypeFactory.getInstance().getFactory(siteType);

-

+		URL fixedUrl;

+		

+		// see if we need to (and can) fix url by adding site.xml to it

 		try {

-			monitor.worked(1);

-			site = createSite(factory, url, monitor);

-		} catch (CoreException e) {

-			if (monitor.isCanceled()) return null;

-

-			// if the URL is pointing to either a file 

-			// or a directory, without reference			

-			if (url.getRef() != null) {

-				// 4 nothing we can do

-				throw Utilities.newCoreException(NLS.bind(Messages.InternalSiteManager_UnableToAccessURL, (new String[] { url.toExternalForm() })), e);

+			if ( (url.getRef() != null) || (url.getFile().endsWith(Site.SITE_XML))) {

+			 	fixedUrl = url;

 			} else if (url.getFile().endsWith("/")) { //$NON-NLS-1$

-				// 1 try to add site.xml

-				URL urlRetry;

-				try {

-					urlRetry = new URL(url, Site.SITE_XML);

-				} catch (MalformedURLException e1) {

-					throw Utilities.newCoreException(NLS.bind(Messages.InternalSiteManager_UnableToCreateURL, (new String[] { url.toExternalForm() + "+" + Site.SITE_XML })), e1);	//$NON-NLS-1$

-				}

-				try {

-					monitor.worked(1);

-					site = createSite(factory, urlRetry, monitor);

-				} catch (CoreException e1) {

-					throw Utilities.newCoreException(NLS.bind(Messages.InternalSiteManager_UnableToAccessURL, (new String[] { url.toExternalForm() })), url.toExternalForm(), urlRetry.toExternalForm(), e, e1);

-				}

-			} else if (url.getFile().endsWith(Site.SITE_XML)) {

-				// 3 nothing we can do

-				throw Utilities.newCoreException(NLS.bind(Messages.InternalSiteManager_UnableToAccessURL, (new String[] { url.toExternalForm() })), e);

+				fixedUrl = new URL(url, Site.SITE_XML);

 			} else {

-				// 2 try to add /site.xml 

-				URL urlRetry;

-				try {

-					urlRetry = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile() + "/" + Site.SITE_XML);	//$NON-NLS-1$

-				} catch (MalformedURLException e1) {

-					throw Utilities.newCoreException(NLS.bind(Messages.InternalSiteManager_UnableToCreateURL, (new String[] { url.toExternalForm() + "+" + Site.SITE_XML })), e1);	//$NON-NLS-1$

-				}

-

-				try {

-					monitor.worked(1);

-					site = createSite(factory, urlRetry, monitor);

-				} catch (CoreException e1) {

-					throw Utilities.newCoreException(NLS.bind(Messages.InternalSiteManager_UnableToAccessURL, (new String[] { url.toExternalForm() })), url.toExternalForm(), urlRetry.toExternalForm(), e, e1);

+				fixedUrl = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile() + "/" + Site.SITE_XML);	//$NON-NLS-1$

+			}

+		} catch (MalformedURLException mue) {

+			fixedUrl = url;

+		}

+		

+		try {

+			ISite site = null;

+			try {

+				monitor.worked(1);

+				site = createSite(factory, fixedUrl, monitor);

+				httpSitesUpdatedUrls.put(url.toExternalForm(), fixedUrl);

+			} catch (CoreException ce) {

+				if (monitor.isCanceled())

+					return null;

+				if (!fixedUrl.equals(url)) {

+					// try with original url

+					site = createSite(factory, url, monitor);

+					httpSitesUpdatedUrls.put(url.toExternalForm(), url);

+				} else {

+					throw ce;

 				}

 			}

+			return site;

+		} catch(CoreException ce) {

+			throw Utilities.newCoreException(NLS.bind(Messages.InternalSiteManager_UnableToAccessURL, (new String[] { url.toExternalForm() })), ce);

 		}

-		return site;

 	}

 	

 	private static ISite createSite(ISiteFactory factory, URL url, IProgressMonitor monitor) throws CoreException, InvalidSiteTypeException {

diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteURLFactory.java b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteURLFactory.java
index f491beb..8202a1f 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteURLFactory.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteURLFactory.java
@@ -9,13 +9,25 @@
  *     IBM Corporation - initial API and implementation

  *******************************************************************************/

 package org.eclipse.update.internal.core;

-import java.io.*;

-import java.net.*;

 

-import org.eclipse.core.runtime.*;

+import java.io.IOException;

+import java.io.InputStream;

+import java.net.MalformedURLException;

+import java.net.URL;

+import java.util.Date;

+

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IProgressMonitor;

 import org.eclipse.osgi.util.NLS;

-import org.eclipse.update.core.*;

-import org.eclipse.update.core.model.*;

+import org.eclipse.update.core.BaseSiteFactory;

+import org.eclipse.update.core.ISite;

+import org.eclipse.update.core.ISiteFactoryExtension;

+import org.eclipse.update.core.Site;

+import org.eclipse.update.core.SiteFeatureReferenceModel;

+import org.eclipse.update.core.Utilities;

+import org.eclipse.update.core.model.InvalidSiteTypeException;

+import org.eclipse.update.core.model.SiteModelFactory;

+import org.eclipse.update.internal.model.SiteWithTimestamp;

 

 /**

  * An update site factory.

@@ -69,6 +81,9 @@
 			contentProvider.setSite(site);

 			site.resolve(url, url);

 			site.markReadOnly();

+			SiteWithTimestamp siteWithTimestamp = new SiteWithTimestamp(site);

+			siteWithTimestamp.setTimestamp( new Date(response.getLastModified()));

+			site = siteWithTimestamp;

 		} catch (MalformedURLException e) {

 			throw Utilities.newCoreException(NLS.bind(Messages.SiteURLFactory_UnableToCreateURL, (new String[] { url == null ? "" : url.toExternalForm() })), e); //$NON-NLS-1$

 		} catch (IOException e) {

diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/internal/model/ITimestamp.java b/update/org.eclipse.update.core/src/org/eclipse/update/internal/model/ITimestamp.java
new file mode 100644
index 0000000..246287b
--- /dev/null
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/internal/model/ITimestamp.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.update.internal.model;
+
+import java.util.Date;
+
+public interface ITimestamp {
+
+	public Date getTimestamp();
+	
+	public void setTimestamp( Date timestamp);
+}
diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/internal/model/SiteWithTimestamp.java b/update/org.eclipse.update.core/src/org/eclipse/update/internal/model/SiteWithTimestamp.java
new file mode 100644
index 0000000..aed4658
--- /dev/null
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/internal/model/SiteWithTimestamp.java
@@ -0,0 +1,286 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.update.internal.model;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Date;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.update.configuration.IConfiguredSite;
+import org.eclipse.update.core.IArchiveReference;
+import org.eclipse.update.core.ICategory;
+import org.eclipse.update.core.IFeature;
+import org.eclipse.update.core.IFeatureContentConsumer;
+import org.eclipse.update.core.IFeatureReference;
+import org.eclipse.update.core.IPluginEntry;
+import org.eclipse.update.core.ISiteContentProvider;
+import org.eclipse.update.core.ISiteFeatureReference;
+import org.eclipse.update.core.IURLEntry;
+import org.eclipse.update.core.IVerificationListener;
+import org.eclipse.update.core.IVerifier;
+import org.eclipse.update.core.Site;
+import org.eclipse.update.core.SiteFeatureReferenceModel;
+import org.eclipse.update.core.model.ArchiveReferenceModel;
+import org.eclipse.update.core.model.CategoryModel;
+import org.eclipse.update.core.model.FeatureReferenceModel;
+import org.eclipse.update.core.model.InstallAbortedException;
+import org.eclipse.update.core.model.URLEntryModel;
+
+/**
+ * This is a wrapper class for Site class that adds timestamp
+ * 
+ *
+ */
+public class SiteWithTimestamp extends Site implements ITimestamp {
+
+	private Date timestamp;
+	
+	private Site site;
+	
+	public SiteWithTimestamp( Site site) {
+		this.site = site;
+	}
+	
+	public Date getTimestamp() {
+		return timestamp;
+	}
+
+	public void setTimestamp(Date timestamp) {
+		this.timestamp = timestamp;
+		
+	}
+
+	public boolean isReadOnly() {
+		return site.isReadOnly();
+	}
+
+	public Object getAdapter(Class adapter) {		
+		return site.getAdapter(adapter);
+	}
+
+	public void addPluginEntry(IPluginEntry pluginEntry) {		
+		site.addPluginEntry(pluginEntry);
+	}
+
+	public IFeature createFeature(String type, URL url) throws CoreException {	
+		return site.createFeature(type, url);
+	}
+
+	public IFeature createFeature(String type, URL url, IProgressMonitor monitor) throws CoreException {		
+		return site.createFeature(type, url, monitor);
+	}
+
+	public IArchiveReference[] getArchives() {		
+		return site.getArchives();
+	}
+
+	public ICategory[] getCategories() {		
+		return site.getCategories();
+	}
+
+	public ICategory getCategory(String key) {		
+		return site.getCategory(key);
+	}
+
+	public IConfiguredSite getCurrentConfiguredSite() {	
+		return site.getCurrentConfiguredSite();
+	}
+
+	public String getDefaultPackagedFeatureType() {	
+		return site.getDefaultPackagedFeatureType();
+	}
+
+	public IURLEntry getDescription() {	
+		return site.getDescription();
+	}
+
+	public long getDownloadSizeFor(IFeature feature) {	
+		return site.getDownloadSizeFor(feature);
+	}
+
+	public ISiteFeatureReference getFeatureReference(IFeature feature) {	
+		return site.getFeatureReference(feature);
+	}
+
+	public ISiteFeatureReference[] getFeatureReferences() {	
+		return site.getFeatureReferences();
+	}
+
+	public long getInstallSizeFor(IFeature feature) {	
+		return site.getInstallSizeFor(feature);
+	}
+
+	public IURLEntry[] getMirrorSiteEntries() {	
+		return site.getMirrorSiteEntries();
+	}
+
+	public IPluginEntry[] getPluginEntries() {	
+		return site.getPluginEntries();
+	}
+
+	public IPluginEntry[] getPluginEntriesOnlyReferencedBy(IFeature feature) throws CoreException {	
+		return site.getPluginEntriesOnlyReferencedBy(feature);
+	}
+
+	public int getPluginEntryCount() {		
+		return site.getPluginEntryCount();
+	}
+
+	public ISiteFeatureReference[] getRawFeatureReferences() {	
+		return site.getRawFeatureReferences();
+	}
+
+	public ISiteContentProvider getSiteContentProvider() throws CoreException {	
+		return site.getSiteContentProvider();
+	}
+
+	public URL getURL() {	
+		return site.getURL();
+	}
+
+	public IFeatureReference install(IFeature sourceFeature, IFeatureReference[] optionalFeatures, IFeatureContentConsumer parentContentConsumer, IVerifier parentVerifier, IVerificationListener verificationListener, IProgressMonitor progress) throws CoreException {	
+		return site.install(sourceFeature, optionalFeatures, parentContentConsumer,
+				parentVerifier, verificationListener, progress);
+	}
+
+	public IFeatureReference install(IFeature sourceFeature, IFeatureReference[] optionalFeatures, IVerificationListener verificationListener, IProgressMonitor progress) throws InstallAbortedException, CoreException {		
+		return site.install(sourceFeature, optionalFeatures, verificationListener,
+				progress);
+	}
+
+	public IFeatureReference install(IFeature sourceFeature, IVerificationListener verificationListener, IProgressMonitor progress) throws InstallAbortedException, CoreException {		
+		return site.install(sourceFeature, verificationListener, progress);
+	}
+
+	public void remove(IFeature feature, IProgressMonitor progress) throws CoreException {		
+		site.remove(feature, progress);
+	}
+
+	public void setSiteContentProvider(ISiteContentProvider siteContentProvider) {		
+		site.setSiteContentProvider(siteContentProvider);
+	}
+
+	public void addArchiveReferenceModel(ArchiveReferenceModel archiveReference) {		
+		site.addArchiveReferenceModel(archiveReference);
+	}
+
+	public void addCategoryModel(CategoryModel category) {		
+		site.addCategoryModel(category);
+	}
+
+	public void addFeatureReferenceModel(SiteFeatureReferenceModel featureReference) {		
+		site.addFeatureReferenceModel(featureReference);
+	}
+
+	public void addMirrorModel(URLEntryModel mirror) {		
+		site.addMirrorModel(mirror);
+	}
+
+	public ArchiveReferenceModel[] getArchiveReferenceModels() {		
+		return site.getArchiveReferenceModels();
+	}
+
+	public CategoryModel[] getCategoryModels() {	
+		return site.getCategoryModels();
+	}
+
+	public ConfiguredSiteModel getConfiguredSiteModel() {	
+		return site.getConfiguredSiteModel();
+	}
+
+	public URLEntryModel getDescriptionModel() {	
+		return site.getDescriptionModel();
+	}
+
+	public SiteFeatureReferenceModel[] getFeatureReferenceModels() {		
+		return site.getFeatureReferenceModels();
+	}
+
+	public URL getLocationURL() {		
+		return site.getLocationURL();
+	}
+
+	public String getLocationURLString() {		
+		return site.getLocationURLString();
+	}
+
+	public URLEntryModel[] getMirrorSiteEntryModels() {	
+		return site.getMirrorSiteEntryModels();
+	}
+
+	public String getType() {	
+		return site.getType();
+	}
+
+	public void markReadOnly() {	
+		site.markReadOnly();
+	}
+
+	public void removeArchiveReferenceModel(ArchiveReferenceModel archiveReference) {	
+		site.removeArchiveReferenceModel(archiveReference);
+	}
+
+	public void removeCategoryModel(CategoryModel category) {	
+		site.removeCategoryModel(category);
+	}
+
+	public void removeFeatureReferenceModel(FeatureReferenceModel featureReference) {	
+		site.removeFeatureReferenceModel(featureReference);
+	}
+
+	public void removeMirror(URLEntryModel mirror) {		
+		site.removeMirror(mirror);
+	}
+
+	public void resolve(URL base, URL bundleURL) throws MalformedURLException {		
+		site.resolve(base, bundleURL);
+	}
+
+	public void setArchiveReferenceModels(ArchiveReferenceModel[] archiveReferences) {		
+		site.setArchiveReferenceModels(archiveReferences);
+	}
+
+	public void setCategoryModels(CategoryModel[] categories) {		
+		site.setCategoryModels(categories);
+	}
+
+	public void setConfiguredSiteModel(ConfiguredSiteModel configuredSiteModel) {		
+		site.setConfiguredSiteModel(configuredSiteModel);
+	}
+
+	public void setDescriptionModel(URLEntryModel description) {		
+		site.setDescriptionModel(description);
+	}
+
+	public void setFeatureReferenceModels(FeatureReferenceModel[] featureReferences) {		
+		site.setFeatureReferenceModels(featureReferences);
+	}
+
+	public void setLocationURLString(String locationURLString) {		
+		site.setLocationURLString(locationURLString);
+	}
+
+	public void setMirrorSiteEntryModels(URLEntryModel[] mirrors) {		
+		site.setMirrorSiteEntryModels(mirrors);
+	}
+
+	public void setMirrorsURLString(String mirrorsURL) {		
+		site.setMirrorsURLString(mirrorsURL);
+	}
+
+	public void setType(String type) {		
+		site.setType(type);
+	}
+
+}