blob: c5208b851f56c4c78f5d8e71b38c3f0b24021e13 [file] [log] [blame]
package org.eclipse.update.internal.core;
/*
* (c) Copyright IBM Corp. 2000, 2002.
* All Rights Reserved.
*/
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
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 cache = 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) throws CoreException {
ISite site = null;
if (siteURL == null)
return null;
if (cache && 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
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);
} 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();
InputStream in;
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;
}
}