20020214_12
diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/core/IConfigurationSite.java b/update/org.eclipse.update.core/src/org/eclipse/update/core/IConfigurationSite.java
index 778079e..e7cea68 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/core/IConfigurationSite.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/core/IConfigurationSite.java
@@ -33,6 +33,13 @@
 	boolean isInstallSite();

 

 	/**

+	 * returns true if the Site is not accessible at this time.

+	 * @return Returns a boolean

+	 * @since 2.0

+	 */

+	boolean isBroken();

+

+	/**

 	 * sets if the site is an installable site

 	 * @since 2.0 

 	 */

diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/core/IFeatureReference.java b/update/org.eclipse.update.core/src/org/eclipse/update/core/IFeatureReference.java
index 2920b39..25bbdca 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/core/IFeatureReference.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/core/IFeatureReference.java
@@ -9,6 +9,7 @@
 import java.net.URL;

 

 import org.eclipse.core.runtime.CoreException;

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

  

  /**

   *

@@ -84,6 +85,20 @@
 

 	void addCategory(ICategory category);

 	

+	/**

+	 * returns true if the Feature is not accessible at this time.

+	 * @return Returns a boolean

+	 * @since 2.0

+	 */

+	boolean isBroken();

+

+	/**

+	 * Gets the updateURL. This is the update URL for the Feature.

+	 * This is used when the feature cannot be accessed.

+	 * @return Returns a URLEntryModel

+	 * @since 2.0

+	 */

+	 URLEntryModel getUpdateURL();

 	

 }

 

diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/core/VersionedIdentifier.java b/update/org.eclipse.update.core/src/org/eclipse/update/core/VersionedIdentifier.java
index f83c9b7..0c9b8b6 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/core/VersionedIdentifier.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/core/VersionedIdentifier.java
Binary files differ
diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/ConfigurationSiteModel.java b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/ConfigurationSiteModel.java
index 21d242d..7e8b725 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/ConfigurationSiteModel.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/ConfigurationSiteModel.java
@@ -19,6 +19,7 @@
  */

 public class ConfigurationSiteModel extends ModelObject {

 

+	private boolean broken=false;

 	private SiteMapModel site;

 	private String platformURLString;

 	private ConfigurationPolicyModel policy;

@@ -116,4 +117,20 @@
 		this.platformURLString = platformURLString;

 	}

 

+	/**

+	 * returns true if the Site is not accessible at this time.

+	 * @return Returns a boolean

+	 */

+	public boolean isBroken() {

+		return broken;

+	}

+

+	/**

+	 * Sets the broken.

+	 * @param broken The broken to set

+	 */

+	public void setBroken(boolean broken) {

+		this.broken = broken;

+	}

+

 }
\ No newline at end of file
diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/DefaultPluginParser.java b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/DefaultPluginParser.java
index 364f34c..6c9ceb1 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/DefaultPluginParser.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/DefaultPluginParser.java
@@ -9,7 +9,10 @@
 import java.io.InputStream;

 

 import org.apache.xerces.parsers.SAXParser;

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

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

 import org.eclipse.update.core.VersionedIdentifier;

+import org.eclipse.update.internal.core.PluginEntryContentConsumer;

 import org.xml.sax.Attributes;

 import org.xml.sax.InputSource;

 import org.xml.sax.SAXException;

@@ -22,8 +25,9 @@
 public class DefaultPluginParser extends DefaultHandler {

 

 	private SAXParser parser;

-	private String version;

-	private String id;

+	private String id = null;

+	private String version = null;

+	private PluginEntry pluginEntry;

 	

 	private static final String PLUGIN = "plugin";

 	private static final String FRAGMENT = "fragment";

@@ -48,14 +52,14 @@
 	/**

 	 * @since 2.0

 	 */

-	public synchronized VersionedIdentifier parse(InputStream in) throws SAXException, IOException {

+	public synchronized PluginEntry parse(InputStream in) throws SAXException, IOException {

 		try {

-			version = null;

-			id=null;

+			pluginEntry = new PluginEntry();			

 			parser.parse(new InputSource(in));

+			pluginEntry.setIdentifier(new VersionedIdentifier(id,version));			

 		} catch(ParseCompleteException e) {

 		}

-		return new VersionedIdentifier(id,version);

+		return pluginEntry;

 	}

 	

 	/**

@@ -67,11 +71,13 @@
 	

 		if (tag.equalsIgnoreCase(PLUGIN)) {

 			processPlugin(attributes);

+			pluginEntry.isFragment(false);

 			return;

 		}

 	

 		if (tag.equalsIgnoreCase(FRAGMENT)) {

 			processPlugin(attributes);

+			pluginEntry.isFragment(true);

 			return;

 		}

 	}

diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/FeatureReferenceModel.java b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/FeatureReferenceModel.java
index f484ade..b5bfe66 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/FeatureReferenceModel.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/FeatureReferenceModel.java
@@ -22,9 +22,11 @@
 

 public class FeatureReferenceModel extends ModelObject {

 	

+	private boolean broken= false;

 	private String type;

 	private String urlString;

 	private URL url;

+	private URLEntryModel updateURL;

 	private SiteMapModel site;

 	private List /* of String*/ categoryNames;

 	

@@ -157,4 +159,38 @@
 		// resolve local elements

 		url = resolveURL(base, bundle,urlString);

 	}

+	

+	/**

+	 * returns true if the Feature is not accessible at this time.

+	 * @return Returns a boolean

+	 */

+	public boolean isBroken() {

+		return broken;

+	}

+

+	/**

+	 * Sets the broken.

+	 * @param broken The broken to set

+	 */

+	public void setBroken(boolean broken) {

+		this.broken = broken;

+	}

+

+	/**

+	 * Gets the updateURL. This is the update URL for the Feature.

+	 * This is used when the feature cannot be accessed.

+	 * @return Returns a URLEntryModel

+	 */

+	public URLEntryModel getUpdateURL() {

+		return updateURL;

+	}

+

+	/**

+	 * Sets the updateURL.

+	 * @param updateURL The updateURL to set

+	 */

+	public void setUpdateURL(URLEntryModel updateURL) {

+		this.updateURL = updateURL;

+	}

+

 }

diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/ParsingException.java b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/ParsingException.java
index 22233f8..1154236 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/ParsingException.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/ParsingException.java
@@ -29,7 +29,7 @@
 	 */

 	public String toString() {

 		

-		return "org.eclipse.update.core.ParsingException: "+exception.getMessage();

+		return "org.eclipse.update.core.ParsingException: "+exception.toString();

 	}

 

 }

diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/PluginEntryModel.java b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/PluginEntryModel.java
index b3c1050..4d06eba 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/core/model/PluginEntryModel.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/core/model/PluginEntryModel.java
@@ -95,4 +95,16 @@
 		assertIsWriteable();

 		this.isFragment = isFragment;

 	}

+	/*

+	 * @see Object#equals(Object)

+	 */

+	public boolean equals(Object obj) {

+		if (!(obj instanceof PluginEntryModel))

+			return false;

+		PluginEntryModel model = (PluginEntryModel)obj;

+		return ( (getPluginIdentifier().equals(model.getPluginIdentifier())) &&

+					(getPluginVersion().equals(model.getPluginVersion())) &&

+					(isFragment()==model.isFragment()));

+	}

+

 }

diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/ConfigurationPolicy.java b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/ConfigurationPolicy.java
index ef5bb83..0aca72b 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/ConfigurationPolicy.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/ConfigurationPolicy.java
@@ -88,7 +88,7 @@
 			}

 		}

 

-		if (multiStatus.getChildren().length > 0) {

+		if (multiStatus.getChildren().length > 0 && handler!=null) {

 			unconfigure = handler.reportProblem("Are you certain to want to unconfigure this feature ?", multiStatus);

 		}

 

diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteFileFactory.java b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteFileFactory.java
index ed99b56..1b4b426 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteFileFactory.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteFileFactory.java
@@ -258,7 +258,8 @@
 						}

 

 						if (pluginFile != null && pluginFile.exists()) {

-							VersionedIdentifier identifier = new DefaultPluginParser().parse(new FileInputStream(pluginFile));

+							IPluginEntry entry = new DefaultPluginParser().parse(new FileInputStream(pluginFile));

+							VersionedIdentifier identifier = entry.getVersionIdentifier();

 							plugin = new PluginIdentifier(identifier, pluginFile);

 

 							addParsedPlugin(plugin);

@@ -335,7 +336,8 @@
 						jarReference.peek("fragment.xml", null, null);

 

 					if (ref != null) {

-						VersionedIdentifier identifier = new DefaultPluginParser().parse(ref.getInputStream());

+						IPluginEntry entry = new DefaultPluginParser().parse(ref.getInputStream());

+						VersionedIdentifier identifier = entry.getVersionIdentifier();

 						plugin = new PluginIdentifier(identifier, file);

 						addParsedPlugin(plugin);

 					} //ref!=null

diff --git a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteLocal.java b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteLocal.java
index 56b0ccf..6c015a5 100644
--- a/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteLocal.java
+++ b/update/org.eclipse.update.core/src/org/eclipse/update/internal/core/SiteLocal.java
@@ -25,6 +25,7 @@
 import org.eclipse.core.runtime.IStatus;

 import org.eclipse.core.runtime.Platform;

 import org.eclipse.core.runtime.Status;

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

 import org.eclipse.update.core.IActivity;

 import org.eclipse.update.core.IConfigurationSite;

 import org.eclipse.update.core.IFeature;

@@ -50,6 +51,7 @@
 

 public class SiteLocal extends SiteLocalModel implements ILocalSite, IWritable {

 

+	private IPluginEntry[] allRunningPluginEntry;

 	private ListenersList listeners = new ListenersList();

 

 	/**

@@ -115,7 +117,6 @@
 		return site;

 	}

 

-

 	private SiteLocal() {

 	}

 

@@ -526,7 +527,7 @@
 			// new site only exist in platformConfig

 			List modified = new ArrayList();

 			List toInstall = new ArrayList();

-			List toRemove = new ArrayList();

+			List brokenLink = new ArrayList();

 			IConfigurationSite[] configured = new IConfigurationSite[0];

 			if (getCurrentConfiguration() != null)

 				configured = getCurrentConfiguration().getConfigurationSites();

@@ -539,6 +540,7 @@
 					if (configured[index].getSite().getURL().equals(resolvedURL)) {

 						found = true;

 						modified.add(configured[index]);

+						configured[index] = null;

 					}

 				}

 				// new site not found, create it

@@ -546,7 +548,7 @@
 					ISite site = SiteManager.getSite(resolvedURL);

 					//site policy

 					IPlatformConfiguration.ISitePolicy sitePolicy = siteEntries[siteIndex].getSitePolicy();

-					ConfigurationSite configSite = (ConfigurationSite) new BaseSiteLocalFactory().createConfigurationSiteModel((SiteMapModel)site, sitePolicy.getType());

+					ConfigurationSite configSite = (ConfigurationSite) new BaseSiteLocalFactory().createConfigurationSiteModel((SiteMapModel) site, sitePolicy.getType());

 					configSite.setPlatformURLString(siteEntries[siteIndex].getURL().toExternalForm());

 

 					//the site may not be read-write

@@ -555,6 +557,12 @@
 				}

 			}

 

+			// get the broken sites.... teh one that are not setup and not modified

+			for (int g = 0; g < configured.length; g++) {

+				if (configured[g] != null)

+					brokenLink.add(configured[g]);

+			}

+

 			// we now have three lists

 

 			// create new InstallConfiguration

@@ -575,7 +583,16 @@
 				newDefaultConfiguration.addConfigurationSite(element);

 			}

 

+			// add the broken one as is

+			Iterator brokenIter = brokenLink.iterator();

+			while (brokenIter.hasNext()) {

+				IConfigurationSite element = (IConfigurationSite) addIter.next();

+				((ConfigurationSiteModel) element).setBroken(true);

+				newDefaultConfiguration.addConfigurationSite(element);

+			}

+

 			this.addConfiguration(newDefaultConfiguration);

+

 		} catch (IOException e) {

 			String id = UpdateManagerPlugin.getPlugin().getDescriptor().getUniqueIdentifier();

 			IStatus status = new Status(IStatus.ERROR, id, IStatus.OK, "Cannot create the Local Site: " + e.getMessage(), e);

@@ -585,25 +602,33 @@
 

 	private IConfigurationSite reconcile(IConfigurationSite toReconcile) throws CoreException {

 

-	int policy = toReconcile.getConfigurationPolicy().getPolicy();

-	SiteMapModel siteModel = (SiteMapModel)toReconcile.getSite();

-	ConfigurationSiteModel newSiteModel = new BaseSiteLocalFactory().createConfigurationSiteModel(siteModel,policy );

-	newSiteModel.setInstallSite(toReconcile.isInstallSite());

-	IConfigurationSite newSite = (IConfigurationSite)newSiteModel;

+		int policy = toReconcile.getConfigurationPolicy().getPolicy();

+		SiteMapModel siteModel = (SiteMapModel) toReconcile.getSite();

+		ConfigurationSiteModel newSiteModel = new BaseSiteLocalFactory().createConfigurationSiteModel(siteModel, policy);

+		newSiteModel.setInstallSite(toReconcile.isInstallSite());

+		IConfigurationSite newSite = (IConfigurationSite) newSiteModel;

 

 		// check the Features that are still here

 		List toCheck = new ArrayList();

-		IFeatureReference[ ] configured = toReconcile.getSite().getFeatureReferences();

+		List brokenfeature = new ArrayList();

+		IFeatureReference[] configured = toReconcile.getSite().getFeatureReferences();

 		IFeatureReference[] found = newSite.getSite().getFeatureReferences();

 

 		for (int i = 0; i < found.length; i++) {

 			for (int j = 0; j < configured.length; j++) {

 				if (configured[j].equals(found[i])) {

 					toCheck.add(configured[j]);

+					configured[j] = null;

 				}

 			}

 		}

 

+		// teh features that are still in the array are broken

+		for (int k = 0; k < configured.length; k++) {

+			if (configured[k] != null)

+				brokenfeature.add(configured[k]);

+		}

+

 		// check the Plugins of all the features

 		// every plugin of the feature must be on the site

 		ISite currentSite = null;

@@ -611,6 +636,7 @@
 		Iterator featureIter = toCheck.iterator();

 		while (featureIter.hasNext()) {

 			IFeatureReference element = (IFeatureReference) featureIter.next();

+

 			if (currentSite.equals(element.getSite())) {

 				currentSite = element.getSite();

 				siteEntries = currentSite.getPluginEntries();

@@ -618,8 +644,7 @@
 			IPluginEntry[] featuresEntries = element.getFeature().getPluginEntries();

 			IPluginEntry[] result = intersection(featuresEntries, siteEntries);

 			if (result == null || (result.length != featuresEntries.length)) {

-				//FIXME set feature as broken

-				//element.setValid(false);

+				((FeatureReferenceModel) element).setBroken(true);

 				IPluginEntry[] missing = intersection(featuresEntries, result);

 				String listOfMissingPlugins = "";

 				for (int k = 0; k < missing.length; k++) {

@@ -629,9 +654,20 @@
 				IStatus status = new Status(IStatus.ERROR, id, IStatus.OK, "The feature " + element.getURL().toExternalForm() + " requires some missing plugins from the site:" + currentSite.getURL().toExternalForm() + listOfMissingPlugins, null);

 				UpdateManagerPlugin.getPlugin().getLog().log(status);

 			}

+			checkConfigure(element, newSite);

 		}

 

-		return toReconcile;

+		//add broken features

+		Iterator brokenIter = brokenfeature.iterator();

+		while (brokenIter.hasNext()) {

+			IFeatureReference element = (IFeatureReference) featureIter.next();

+			((FeatureReferenceModel) element).setBroken(true);

+			// if it is broken (ie the feature does not exist, we 

+			//cannot check the plugins... consider as unconfigured)

+			newSite.unconfigure(element,null);

+		}

+

+		return newSite;

 	}

 

 	/**

@@ -666,4 +702,55 @@
 		return resultEntry;

 	}

 

+	/**

+	 * Check if all the plugins of the feature are configured in the runtime

+	 * depending on teh answer add it to the newSite as either configured or unconfigured

+	 * We have to check all the running plugin, even if they come from different site

+	 * A feature may be broken because all the plugins are not in the Site, but may be configured

+	 * because soem of the needed plugins come from other site

+	 */

+	private void checkConfigure(IFeatureReference ref, IConfigurationSite newSite) throws CoreException {

+		// check if all the needed plugins are part of all plugin

+		

+		IPluginEntry[] allPlugins = getAllRunningPlugin();

+		IPluginEntry[] featurePlugins = ref.getFeature().getPluginEntries();

+		IPluginEntry[] result = intersection(featurePlugins,allPlugins);

+		

+		// there are soem plugins the feature need that are not present

+		if (result.length!=0){

+			newSite.unconfigure(ref,null);

+		} else {

+			newSite.configure(ref);

+		}

+		

+	}

+

+	private IPluginEntry[] getAllRunningPlugin() throws CoreException {

+		if (allRunningPluginEntry == null) {

+			// get all the running plugins

+			URL[] pluginPathURL = BootLoader.getCurrentPlatformConfiguration().getPluginPath();

+

+			// we explicitly create instances of PlugiNEntry as we will just compare them

+			allRunningPluginEntry = new PluginEntry[pluginPathURL.length];

+			if (pluginPathURL.length > 0) {

+				DefaultPluginParser parser = new DefaultPluginParser();

+				for (int i = 0; i < pluginPathURL.length; i++) {

+					try {

+						IPluginEntry entry = parser.parse(pluginPathURL[i].openStream());

+						allRunningPluginEntry[i] = entry;						

+					} catch (Exception e){

+						throw newCoreException("Unable to parse file"+pluginPathURL[i]+".\r\n"+e.toString(),e);

+					}

+				}

+			}

+		}

+		return allRunningPluginEntry;

+	}

+	

+	/**

+	 * returns a Core Exception

+	 */

+	private static CoreException newCoreException(String s, Throwable e) throws CoreException {

+		return new CoreException(new Status(IStatus.ERROR, "org.eclipse.update.core", 0, s, e));

+	}	

 }
\ No newline at end of file