blob: 4ed49b8ef410b45f78634bbfd61cbb5aa3c2e184 [file] [log] [blame]
package org.eclipse.update.internal.core;
/*
* (c) Copyright IBM Corp. 2000, 2002.
* All Rights Reserved.
*/
import java.io.File;
import java.lang.reflect.Array;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.update.configuration.*;
import org.eclipse.update.core.*;
import org.eclipse.update.core.model.InvalidSiteTypeException;
import org.eclipse.update.internal.model.InstallChangeParser;
/**
*
*/
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 final String SIMPLE_EXTENSION_ID = "deltaHandler";
//$NON-NLS-1$
// cache found sites
private static Map sites = 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(false);
}
/*
* Internal call if optimistic reconciliation needed
*/
private static ILocalSite internalGetLocalSite(boolean isOptimistic) throws CoreException {
// if an exception occured while retrieving the Site
// rethrow it
if (exceptionOccured != null)
throw exceptionOccured;
if (localSite == null) {
try {
localSite = SiteLocal.internalGetLocalSite(isOptimistic);
} catch (CoreException e) {
exceptionOccured = e;
throw e;
}
}
return localSite;
}
/*
* @see ILocalSite#getSite(URL)
*/
public static ISite getSite(URL siteURL, boolean useCache) throws CoreException {
ISite site = null;
if (siteURL == null)
return null;
// use cache if set up globally (globalUseCache=true)
// and passed as parameter (useCache=true)
if ((useCache && globalUseCache) && sites.containsKey(siteURL)) {
site = (ISite) sites.get(siteURL);
return site;
}
try {
site = attemptCreateSite(DEFAULT_SITE_TYPE, siteURL);
} catch (CoreException preservedException) {
// attempt a retry is the protocol is file, with executbale type
if (!"file".equalsIgnoreCase(siteURL.getProtocol()))
throw preservedException;
try {
site = attemptCreateSite(DEFAULT_EXECUTABLE_SITE_TYPE, siteURL);
} 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, site);
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) throws CoreException {
ISite site = null;
try {
site = createSite(guessedTypeSite, siteURL);
} catch (InvalidSiteTypeException e) {
// the type in the site.xml is not the one expected
// attempt to use this type instead
//DEBUG:
if (UpdateManagerPlugin.DEBUG && UpdateManagerPlugin.DEBUG_SHOW_TYPE) {
UpdateManagerPlugin.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$
}
InvalidSiteTypeException exception = (InvalidSiteTypeException) e;
try {
if (exception.getNewType() == null)
throw e;
site = createSite(exception.getNewType(), siteURL);
} catch (InvalidSiteTypeException e1) {
throw Utilities.newCoreException(Policy.bind("InternalSiteManager.UnableToCreateSiteWithType", e.getNewType(), siteURL.toExternalForm()), e1);
//$NON-NLS-1$ //$NON-NLS-2$
}
}
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) throws CoreException, InvalidSiteTypeException {
ISite site = null;
ISiteFactory factory = SiteTypeFactory.getInstance().getFactory(siteType);
try {
site = factory.createSite(url);
} catch (CoreException e) {
// 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 {
site = factory.createSite(urlRetry);
} 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 {
site = factory.createSite(urlRetry);
} catch (CoreException e1) {
throw Utilities.newCoreException(Policy.bind("InternalSiteManager.UnableToAccessURL", url.toExternalForm()), url.toExternalForm(), urlRetry.toExternalForm(), e, e1);
//$NON-NLS-1$
}
}
}
return site;
}
/*
* 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);
} catch (MalformedURLException e) {
throw Utilities.newCoreException(Policy.bind("InternalSiteManager.UnableToCreateURL", siteLocation.getAbsolutePath()), e);
//$NON-NLS-1$
}
}
return site;
}
/*
* Prompt the user to configure or unconfigure
* newly discoverd features.
* @throws CoreException if an error occurs.
* @since 2.0
*/
public static void handleNewChanges() throws CoreException {
// find extension point
IInstallDeltaHandler handler = null;
String pluginID = UpdateManagerPlugin.getPlugin().getDescriptor().getUniqueIdentifier();
IPluginRegistry pluginRegistry = Platform.getPluginRegistry();
IConfigurationElement[] elements = pluginRegistry.getConfigurationElementsFor(pluginID, SIMPLE_EXTENSION_ID);
if (elements == null || elements.length == 0) {
throw Utilities.newCoreException(Policy.bind("SiteReconciler.UnableToFindInstallDeltaFactory", pluginID + "." + SIMPLE_EXTENSION_ID), null);
//$NON-NLS-1$
} else {
IConfigurationElement element = elements[0];
handler = (IInstallDeltaHandler) element.createExecutableExtension("class");
//$NON-NLS-1$
}
// instanciate and open
if (handler != null) {
ISessionDelta[] deltas = getSessionDeltas();
handler.init(deltas);
handler.open();
}
}
/*
* Returns the list of sessions deltas found on the file system
*
* Do not cache, calculate everytime
* because we delete the file in SessionDelta when the session
* has been seen by the user
*
* So the shared state is the file system itself
*/
private static ISessionDelta[] getSessionDeltas() {
List sessionDeltas = new ArrayList();
IPath path = UpdateManagerPlugin.getPlugin().getStateLocation();
InstallChangeParser parser;
File file = path.toFile();
if (file.isDirectory()) {
File[] allFiles = file.listFiles();
for (int i = 0; i < allFiles.length; i++) {
try {
// TRACE
if (UpdateManagerPlugin.DEBUG && UpdateManagerPlugin.DEBUG_SHOW_RECONCILER) {
UpdateManagerPlugin.debug("Found delta change:" + allFiles[i]);
}
parser = new InstallChangeParser(allFiles[i]);
ISessionDelta change = parser.getInstallChange();
if (change != null) {
sessionDeltas.add(change);
}
} catch (Exception e) {
if (UpdateManagerPlugin.DEBUG && UpdateManagerPlugin.DEBUG_SHOW_RECONCILER) {
UpdateManagerPlugin.log("Unable to parse install change:" + allFiles[i], e);
}
}
}
}
if (sessionDeltas.size() == 0)
return new ISessionDelta[0];
return (ISessionDelta[]) sessionDeltas.toArray(arrayTypeFor(sessionDeltas));
}
/*
* Returns a concrete array type for the elements of the specified
* list. The method assumes all the elements of the list are the same
* concrete type as the first element in the list.
*
* @param l list
* @return concrete array type, or <code>null</code> if the array type
* could not be determined (the list is <code>null</code> or empty)
* @since 2.0
*/
private static Object[] arrayTypeFor(List l) {
if (l == null || l.size() == 0)
return null;
return (Object[]) Array.newInstance(l.get(0).getClass(), 0);
}
/*
* Reconcile the local site following a specific reconciliation strategy
* The parameter is true if we need to follow an optimistic reconciliation
* returns true if there are delta to process
*
* Called internally by UpdateManagerReconciler aplication
*/
public static boolean reconcile(boolean optimisticReconciliation) throws CoreException {
// reconcile
internalGetLocalSite(optimisticReconciliation);
// check if new features have been found
if (localSite instanceof SiteLocal) {
return ((SiteLocal) localSite).newFeaturesFound;
}
return false;
}
}