blob: d0d83971dca47c7aece06d07f8dec4bd64538aa5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.update.internal.core;
import java.io.*;
import java.net.*;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.update.configuration.*;
import org.eclipse.update.core.*;
import org.eclipse.update.core.model.*;
/**
*
*/
public class InternalSiteManager {
public static ILocalSite localSite;
public static final String DEFAULT_SITE_TYPE = SiteURLContentProvider.SITE_TYPE;
private static final String DEFAULT_EXECUTABLE_SITE_TYPE = SiteFileContentProvider.SITE_TYPE;
private static Map estimates;
// cache found sites
private static Map sites = new HashMap();
// cache timestamps
private static Map siteTimestamps = new HashMap();
public static boolean globalUseCache = true;
// true if an exception occured creating localSite
// so we cache it and don't attempt to create it again
private static CoreException exceptionOccured = null;
/*
* @see SiteManager#getLocalSite()
*/
public static ILocalSite getLocalSite() throws CoreException {
return internalGetLocalSite();
}
/*
* Internal call if optimistic reconciliation needed
*/
private static ILocalSite internalGetLocalSite() throws CoreException {
// if an exception occured while retrieving the Site
// rethrow it
if (exceptionOccured != null)
throw exceptionOccured;
if (localSite == null) {
try {
localSite = SiteLocal.internalGetLocalSite();
} catch (CoreException e) {
exceptionOccured = e;
throw e;
}
}
return localSite;
}
private static boolean isValidCachedSite(URL siteURL) {
if (!sites.containsKey(siteURL.toExternalForm()))
return false;
Long timestamp = (Long)siteTimestamps.get(siteURL);
if (timestamp == null)
return false;
long localLastModified = timestamp.longValue();
return UpdateManagerUtils.isSameTimestamp(siteURL, localLastModified);
}
/*
* @see ILocalSite#getSite(URL)
*/
public static ISite getSite(URL siteURL, boolean useCache, IProgressMonitor monitor) throws CoreException {
ISite site = null;
if (monitor==null) monitor = new NullProgressMonitor();
if (siteURL == null)
return null;
// use cache if set up globally (globalUseCache=true)
// and passed as parameter (useCache=true)
String siteURLString = siteURL.toExternalForm();
if ((useCache && globalUseCache) && isValidCachedSite(siteURL)) {
site = (ISite) sites.get(siteURLString);
return site;
}
// try adding "eclipse" to the site url, in case this is an extension site
if ("file".equals(siteURL.getProtocol()) ) { //$NON-NLS-1$
File f = new File(siteURL.getFile());
if (f.isDirectory() && !"eclipse".equals(f.getName())) { //$NON-NLS-1$
f = new File(f, "eclipse"); //$NON-NLS-1$
try {
if ((useCache && globalUseCache) && isValidCachedSite(f.toURL())) {
site = (ISite) sites.get(f.toURL().toExternalForm());
return site;
}
} catch (MalformedURLException e) {
}
}
}
// consider file protocol also if the URL points to a directory
// and no site.xml exist
// if the user points to a file, consider DEFAULT_SITE_TYPE
// site.xml will have to specify the type
boolean fileProtocol = "file".equalsIgnoreCase(siteURL.getProtocol()); //$NON-NLS-1$
boolean directoryExists = false;
if (fileProtocol) {
File dir;
dir = new File(siteURL.getFile());
if (dir != null && dir.isDirectory()) {
if (!(new File(dir, Site.SITE_XML).exists()))
directoryExists = true;
}
}
//PERF: if file: <path>/ and directory exists then consider executable
monitor.beginTask(Policy.bind("InternalSiteManager.ConnectingToSite"), 8); //$NON-NLS-1$
if (fileProtocol && directoryExists) {
site = attemptCreateSite(DEFAULT_EXECUTABLE_SITE_TYPE, siteURL, monitor);
monitor.worked(4); // only one attempt
} else {
try {
monitor.worked(3);
site = attemptCreateSite(DEFAULT_SITE_TYPE, siteURL, monitor);
monitor.worked(1);
} catch (CoreException preservedException) {
if (!monitor.isCanceled()) {
// attempt a retry is the protocol is file, with executbale type
if (!fileProtocol)
throw preservedException;
try {
site = attemptCreateSite(DEFAULT_EXECUTABLE_SITE_TYPE, siteURL, monitor);
} catch (CoreException retryException) {
IStatus firstStatus = preservedException.getStatus();
MultiStatus multi = new MultiStatus(firstStatus.getPlugin(), IStatus.OK, Policy.bind("InternalSiteManager.FailedRetryAccessingSite"), retryException); //$NON-NLS-1$
multi.addAll(firstStatus);
throw preservedException;
}
}
}
}
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) {
}
}
//flush the JarFile we may hold on to
// we keep the temp not to create them again
JarContentReference.shutdown(); // make sure we are not leaving jars open for this site
//flush mapping of downloaded JAR files
// FIXME : provide better cache flushing after 2.1
// FIXED: everything downloaded is cached and timestamped.
// Timestamps are compared to lastModifed on the server
// and we download only when there is a differenc
// Utilities.flushLocalFile();
return site;
}
/*
* Attempt to create a site
* if the site guessed is not the type found,
* attempt to create a type with the type found in the site.xml
*/
private static ISite attemptCreateSite(String guessedTypeSite, URL siteURL, IProgressMonitor monitor) throws CoreException {
if (monitor == null) monitor = new NullProgressMonitor();
ISite site = null;
try {
monitor.worked(1);
site = createSite(guessedTypeSite, siteURL, monitor);
monitor.worked(1); // if no error, occurs the retry branch doesn't need to be executed
} catch (InvalidSiteTypeException e) {
if (monitor.isCanceled()) return null;
// the type in the site.xml is not the one expected
// attempt to use this type instead
//DEBUG:
if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_TYPE) {
UpdateCore.debug("The Site :" + siteURL.toExternalForm() + " is a different type than the guessed type based on the protocol. new Type:" + e.getNewType()); //$NON-NLS-1$ //$NON-NLS-2$
}
try {
if (e.getNewType() == null)
throw e;
site = createSite(e.getNewType(), siteURL, monitor);
} catch (InvalidSiteTypeException e1) {
throw Utilities.newCoreException(Policy.bind("InternalSiteManager.UnableToCreateSiteWithType", e.getNewType(), siteURL.toExternalForm()), e1); //$NON-NLS-1$
}
}
return site;
}
/*
* create an instance of a class that implements ISite
*
* the URL can be of the following form
* 1 protocol://...../
* 2 protocol://.....
* 3 protocol://..../site.xml
* 4 protocol://...#...
*
* 1 If the file of the file of teh url ends with '/', attempt to open the stream.
* if it fails, add site.xml and attempt to open the stream
*
* 2 attempt to open the stream
* fail
* add '/site.xml' and attempt to open the stream
* sucess
* attempt to parse, if it fails, add '/site.xml' and attempt to open the stream
*
* 3 open the stream
*
* 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);
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(Policy.bind("InternalSiteManager.UnableToAccessURL", url.toExternalForm()), e); //$NON-NLS-1$
} 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(Policy.bind("InternalSiteManager.UnableToCreateURL", url.toExternalForm() + "+" + Site.SITE_XML), e1); //$NON-NLS-1$ //$NON-NLS-2$
}
try {
monitor.worked(1);
site = createSite(factory, urlRetry, monitor);
} catch (CoreException e1) {
throw Utilities.newCoreException(Policy.bind("InternalSiteManager.UnableToAccessURL", url.toExternalForm()), url.toExternalForm(), urlRetry.toExternalForm(), e, e1);//$NON-NLS-1$
}
} else if (url.getFile().endsWith(Site.SITE_XML)) {
// 3 nothing we can do
throw Utilities.newCoreException(Policy.bind("InternalSiteManager.UnableToAccessURL", url.toExternalForm()), e);//$NON-NLS-1$
} 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(Policy.bind("InternalSiteManager.UnableToCreateURL", url.toExternalForm() + "+" + Site.SITE_XML), e1); //$NON-NLS-1$ //$NON-NLS-2$
}
try {
monitor.worked(1);
site = createSite(factory, urlRetry, monitor);
} catch (CoreException e1) {
throw Utilities.newCoreException(Policy.bind("InternalSiteManager.UnableToAccessURL", url.toExternalForm()), url.toExternalForm(), urlRetry.toExternalForm(), e, e1);//$NON-NLS-1$
}
}
}
return site;
}
private static ISite createSite(ISiteFactory factory, URL url, IProgressMonitor monitor) throws CoreException, InvalidSiteTypeException {
if (factory instanceof ISiteFactoryExtension)
return ((ISiteFactoryExtension)factory).createSite(url, monitor);
else
return factory.createSite(url);
}
/*
* Creates a new site on the file system
* This is the only Site we can create.
*
* @param siteLocation
* @throws CoreException
*/
public static ISite createSite(File siteLocation) throws CoreException {
ISite site = null;
if (siteLocation != null) {
try {
URL siteURL = siteLocation.toURL();
site = getSite(siteURL, false, null);
} catch (MalformedURLException e) {
throw Utilities.newCoreException(Policy.bind("InternalSiteManager.UnableToCreateURL", siteLocation.getAbsolutePath()), e); //$NON-NLS-1$
}
}
return site;
}
/**
* Method downloaded.
* @param downloadSize size downloaded in bytes
* @param time time in seconds
* @param url
*/
public static void downloaded(long downloadSize, long time, URL url) {
if (downloadSize <= 0 || time < 0)
return;
String host = url.getHost();
long sizeByTime = (time == 0) ? 0 : downloadSize / time;
Long value = new Long(sizeByTime);
if (estimates == null) {
estimates = new HashMap();
} else {
Long previous = (Long) estimates.get(host);
if (previous != null) {
value = new Long((previous.longValue() + sizeByTime) / 2);
}
}
estimates.put(host, value);
}
/**
* Method getEstimatedTransferRate rate bytes/seconds.
* @param host
* @return long
*/
public static long getEstimatedTransferRate(String host) {
if (estimates == null)
return 0;
Long value = (Long) estimates.get(host);
if (value == null)
return 0;
return value.longValue();
}
}