blob: e29dcdc8397e9e86a2ffd5c3e5193ade0ade13da [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 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.core.model;
import java.net.*;
import java.util.*;
import org.eclipse.update.core.*;
import org.eclipse.update.internal.core.*;
/**
* Feature model object.
* <p>
* This class may be instantiated or subclassed by clients. However, in most
* cases clients should instead instantiate or subclass the provided
* concrete implementation of this model.
* </p>
* <p>
* <b>Note:</b> This class/interface is part of an interim API that is still under development and expected to
* change significantly before reaching stability. It is being made available at this early stage to solicit feedback
* from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
* (repeatedly) as the API evolves.
* </p>
* @see org.eclipse.update.core.Feature
* @since 2.0
*/
public class FeatureModel extends ModelObject {
private String featureId;
private String featureVersion;
private String label;
private String localizedLabel;
private String provider;
private String localizedProvider;
private String imageURLString;
private URL imageURL;
private String os;
private String ws;
private String nl;
private String arch;
private boolean primary = false;
private boolean exclusive=false;
private String primaryPluginID;
private String application;
private String affinity;
private InstallHandlerEntryModel installHandler;
private URLEntryModel description;
private URLEntryModel copyright;
private URLEntryModel license;
private URLEntryModel updateSiteInfo;
private List /*of InfoModel*/ discoverySiteInfo;
private List /*of ImportModel*/ imports;
private List /*of PluginEntryModel*/ pluginEntries;
private List /*of IncludedFeatureReferenceModel */ featureIncludes;
private List /*of NonPluginEntryModel*/ nonPluginEntries;
// performance
private URL bundleURL;
private URL base;
private boolean resolved = false;
/**
* Creates an uninitialized feature object.
*
* @since 2.0
*/
public FeatureModel() {
super();
}
/**
* Compares 2 feature models for equality
*
* @param obj feature model to compare with
* @return <code>true</code> if the two models are equal,
* <code>false</code> otherwise
* @since 2.0
*/
public boolean equals(Object obj) {
if (!(obj instanceof FeatureModel))
return false;
FeatureModel model = (FeatureModel) obj;
return (featureId.toLowerCase().equals(model.getFeatureIdentifier()) && featureVersion.toLowerCase().equals(model.getFeatureVersion()));
}
/**
* Returns the feature identifier as a string
*
* @see org.eclipse.update.core.IFeature#getVersionedIdentifier()
* @return feature identifier
* @since 2.0
*/
public String getFeatureIdentifier() {
//delayedResolve(); no delay
return featureId;
}
/**
* Returns the feature version as a string
*
* @see org.eclipse.update.core.IFeature#getVersionedIdentifier()
* @return feature version
* @since 2.0
*/
public String getFeatureVersion() {
//delayedResolve(); no delay
return featureVersion;
}
/**
* Retrieve the displayable label for the feature. If the model
* object has been resolved, the label is localized.
*
* @return displayable label, or <code>null</code>.
* @since 2.0
*/
public String getLabel() {
delayedResolve();
if (localizedLabel != null)
return localizedLabel;
else
return label;
}
/**
* Retrieve the non-localized displayable label for the feature.
*
* @return non-localized displayable label, or <code>null</code>.
* @since 2.0
*/
public String getLabelNonLocalized() {
return label;
}
/**
* Retrieve the displayable label for the feature provider. If the model
* object has been resolved, the label is localized.
*
* @return displayable label, or <code>null</code>.
* @since 2.0
*/
public String getProvider() {
delayedResolve();
if (localizedProvider != null)
return localizedProvider;
else
return provider;
}
/**
* Retrieve the non-localized displayable label for the feature provider.
*
* @return non-localized displayable label, or <code>null</code>.
* @since 2.0
*/
public String getProviderNonLocalized() {
return provider;
}
/**
* Returns the unresolved URL string for the feature image.
*
* @return url string, or <code>null</code>
* @since 2.0
*/
public String getImageURLString() {
delayedResolve();
return imageURLString;
}
/**
* Returns the resolved URL for the image.
*
* @return url, or <code>null</code>
* @since 2.0
*/
public URL getImageURL() {
delayedResolve();
return imageURL;
}
/**
* Get optional operating system specification as a comma-separated string.
*
* @return the operating system specification string, or <code>null</code>.
* @since 2.0
*/
public String getOS() {
return os;
}
/**
* Get optional windowing system specification as a comma-separated string.
* @return the windowing system specification string, or <code>null</code>.
* @since 2.0
*/
public String getWS() {
return ws;
}
/**
* Get optional system architecture specification as a comma-separated string.
*
* @return the system architecture specification string, or <code>null</code>.
* @since 2.0
*/
public String getOSArch() {
return arch;
}
/**
* Get optional locale specification as a comma-separated string.
*
* @return the locale specification string, or <code>null</code>.
* @since 2.0
*/
public String getNL() {
return nl;
}
/**
* Indicates whether the feature can be used as a primary feature.
*
* @return <code>true</code> if this is a primary feature,
* otherwise <code>false</code>
* @since 2.0
*/
public boolean isPrimary() {
return primary;
}
/**
* Indicates whether the feature must be processed alone
* during installation and configuration. Features that
* are not exclusive can be installed in a batch.
*
* @return <code>true</code> if feature requires
* exclusive processing, <code>false</code> otherwise.
* @since 2.1
*/
public boolean isExclusive() {
return exclusive;
}
/**
* Returns an optional identifier for the feature application
*
* @return application identifier, or <code>null</code>.
* @since 2.0
*/
public String getApplication() {
return application;
}
/**
* Returns an optional identifier for the colocation affinity feature
*
* @return feature identifier, or <code>null</code>.
* @since 2.0
*/
public String getAffinityFeature() {
return affinity;
}
/**
* Returns and optional custom install handler entry.
*
* @return install handler entry, or <code>null</code> if
* none was specified
* @since 2.0
*/
public InstallHandlerEntryModel getInstallHandlerModel() {
//delayedResolve(); no delay
return installHandler;
}
/**
* Returns the feature description.
*
* @return feature rescription, or <code>null</code>.
* @since 2.0
*/
public URLEntryModel getDescriptionModel() {
//delayedResolve(); no delay
return description;
}
/**
* Returns the copyright information for the feature.
*
* @return copyright information, or <code>null</code>.
* @since 2.0
*/
public URLEntryModel getCopyrightModel() {
//delayedResolve(); no delay
return copyright;
}
/**
* Returns the license information for the feature.
*
* @return feature license, or <code>null</code>.
* @since 2.0
*/
public URLEntryModel getLicenseModel() {
//delayedResolve(); no delay;
return license;
}
/**
* Returns an information entry referencing the location of the
* feature update site.
*
* @return update site entry, or <code>null</code>.
* @since 2.0
*/
public URLEntryModel getUpdateSiteEntryModel() {
//delayedResolve(); no delay;
return updateSiteInfo;
}
/**
* Return an array of information entries referencing locations of other
* update sites.
*
* @return an array of site entries, or an empty array.
* @since 2.0
* @since 2.0
*/
public URLEntryModel[] getDiscoverySiteEntryModels() {
//delayedResolve(); no delay;
if (discoverySiteInfo == null || discoverySiteInfo.size() == 0)
return new URLEntryModel[0];
return (URLEntryModel[]) discoverySiteInfo.toArray(arrayTypeFor(discoverySiteInfo));
}
/**
* Return a list of plug-in dependencies for this feature.
*
* @return the list of required plug-in dependencies, or an empty array.
* @since 2.0
*/
public ImportModel[] getImportModels() {
//delayedResolve(); no delay;
if (imports == null || imports.size() == 0)
return new ImportModel[0];
return (ImportModel[]) imports.toArray(arrayTypeFor(imports));
}
/**
* Returns an array of plug-in entries referenced by this feature
*
* @return an erray of plug-in entries, or an empty array.
* @since 2.0
*/
public PluginEntryModel[] getPluginEntryModels() {
if (pluginEntries == null || pluginEntries.size() == 0)
return new PluginEntryModel[0];
return (PluginEntryModel[]) pluginEntries.toArray(arrayTypeFor(pluginEntries));
}
/**
* Returns an array of versioned identifier referenced by this feature
*
* @return an array of versioned identifier, or an empty array.
* @deprecated use getFeatureIncludeIdentifier instead.
* @since 2.0
*/
public VersionedIdentifier[] getFeatureIncludeVersionedIdentifier() {
//delayedResolve(); no delay
if (featureIncludes == null)
return new VersionedIdentifier[0];
//
Iterator iter = featureIncludes.iterator();
VersionedIdentifier[] versionIncluded = new VersionedIdentifier[featureIncludes.size()];
int index = 0;
while (iter.hasNext()) {
IncludedFeatureReferenceModel model = (IncludedFeatureReferenceModel) iter.next();
versionIncluded[index] = model.getVersionedIdentifier();
index++;
}
return versionIncluded;
}
/**
* Returns an array of included feature reference model referenced by this feature.
*
* @return an array of included feature reference model, or an empty array.
* @since 2.0
*/
public IIncludedFeatureReference[] getFeatureIncluded() {
//delayedResolve(); no delay
if (featureIncludes == null || featureIncludes.size() == 0)
return new IIncludedFeatureReference[0];
return (IIncludedFeatureReference[]) featureIncludes.toArray(arrayTypeFor(featureIncludes));
}
/**
* Returns an array of non-plug-in entries referenced by this feature
*
* @return an erray of non-plug-in entries, or an empty array.
* @since 2.0
*/
public NonPluginEntryModel[] getNonPluginEntryModels() {
if (nonPluginEntries == null || nonPluginEntries.size() == 0)
return new NonPluginEntryModel[0];
return (NonPluginEntryModel[]) nonPluginEntries.toArray(arrayTypeFor(nonPluginEntries));
}
/**
* Sets the feature identifier.
* Throws a runtime exception if this object is marked read-only.
*
* @param featureId feature identifier
* @since 2.0
*/
public void setFeatureIdentifier(String featureId) {
assertIsWriteable();
this.featureId = featureId;
}
/**
* Sets the feature version.
* Throws a runtime exception if this object is marked read-only.
*
* @param featureVersion feature version
* @since 2.0
*/
public void setFeatureVersion(String featureVersion) {
assertIsWriteable();
this.featureVersion = featureVersion;
}
/**
* Sets the feature displayable label.
* Throws a runtime exception if this object is marked read-only.
*
* @param label displayable label
* @since 2.0
*/
public void setLabel(String label) {
assertIsWriteable();
this.label = label;
this.localizedLabel = null;
}
/**
* Sets the feature provider displayable label.
* Throws a runtime exception if this object is marked read-only.
*
* @param provider provider displayable label
* @since 2.0
*/
public void setProvider(String provider) {
assertIsWriteable();
this.provider = provider;
this.localizedProvider = null;
}
/**
* Sets the unresolved URL for the feature image.
* Throws a runtime exception if this object is marked read-only.
*
* @param imageURLString unresolved URL string
* @since 2.0
*/
public void setImageURLString(String imageURLString) {
assertIsWriteable();
this.imageURLString = imageURLString;
this.imageURL = null;
}
/**
* Sets the operating system specification.
* Throws a runtime exception if this object is marked read-only.
*
* @param os operating system specification as a comma-separated list
* @since 2.0
*/
public void setOS(String os) {
assertIsWriteable();
this.os = os;
}
/**
* Sets the windowing system specification.
* Throws a runtime exception if this object is marked read-only.
*
* @param ws windowing system specification as a comma-separated list
* @since 2.0
*/
public void setWS(String ws) {
assertIsWriteable();
this.ws = ws;
}
/**
* Sets the locale specification.
* Throws a runtime exception if this object is marked read-only.
*
* @param nl locale specification as a comma-separated list
* @since 2.0
*/
public void setNL(String nl) {
assertIsWriteable();
this.nl = nl;
}
/**
* Sets the system architecture specification.
* Throws a runtime exception if this object is marked read-only.
*
* @param arch system architecture specification as a comma-separated list
* @since 2.0
*/
public void setArch(String arch) {
assertIsWriteable();
this.arch = arch;
}
/**
* Indicates whether this feature can act as a primary feature.
* Throws a runtime exception if this object is marked read-only.
*
* @param primary <code>true</code> if this feature can act as primary,
* <code>false</code> otherwise
*
* @since 2.0
*/
public void setPrimary(boolean primary) {
assertIsWriteable();
this.primary = primary;
}
/**
* Indicates whether this feature can act as a primary feature.
* Throws a runtime exception if this object is marked read-only.
*
* @param exclusive <code>true</code> if this feature must be
* processed independently from other features, <code>false</code>
* if feature can be processed in a batch with other features.
*
* @since 2.1
*/
public void setExclusive(boolean exclusive) {
assertIsWriteable();
this.exclusive = exclusive;
}
/**
* Sets the feature application identifier.
* Throws a runtime exception if this object is marked read-only.
*
* @param application feature application identifier
* @since 2.0
*/
public void setApplication(String application) {
assertIsWriteable();
this.application = application;
}
/**
* Sets the identifier of the Feature this feature should be
* installed with.
* Throws a runtime exception if this object is marked read-only.
*
* @param affinity the identifier of the Feature
* @since 2.0
*/
public void setAffinityFeature(String affinity) {
assertIsWriteable();
this.affinity = affinity;
}
/**
* Sets the custom install handler for the feature.
* Throws a runtime exception if this object is marked read-only.
*
* @param installHandler install handler entry
* @since 2.0
*/
public void setInstallHandlerModel(InstallHandlerEntryModel installHandler) {
assertIsWriteable();
this.installHandler = installHandler;
}
/**
* Sets the feature description information.
* Throws a runtime exception if this object is marked read-only.
*
* @param description feature description information
* @since 2.0
*/
public void setDescriptionModel(URLEntryModel description) {
assertIsWriteable();
this.description = description;
}
/**
* Sets the feature copyright information.
* Throws a runtime exception if this object is marked read-only.
*
* @param copyright feature copyright information
* @since 2.0
*/
public void setCopyrightModel(URLEntryModel copyright) {
assertIsWriteable();
this.copyright = copyright;
}
/**
* Sets the feature license information.
* Throws a runtime exception if this object is marked read-only.
*
* @param license feature license information
* @since 2.0
*/
public void setLicenseModel(URLEntryModel license) {
assertIsWriteable();
this.license = license;
}
/**
* Sets the feature update site reference.
* Throws a runtime exception if this object is marked read-only.
*
* @param updateSiteInfo feature update site reference
* @since 2.0
*/
public void setUpdateSiteEntryModel(URLEntryModel updateSiteInfo) {
assertIsWriteable();
this.updateSiteInfo = updateSiteInfo;
}
/**
* Sets additional update site references.
* Throws a runtime exception if this object is marked read-only.
*
* @param discoverySiteInfo additional update site references
* @since 2.0
*/
public void setDiscoverySiteEntryModels(URLEntryModel[] discoverySiteInfo) {
assertIsWriteable();
if (discoverySiteInfo == null)
this.discoverySiteInfo = null;
else
this.discoverySiteInfo = new ArrayList(Arrays.asList(discoverySiteInfo));
}
/**
* Sets the feature plug-in dependency information.
* Throws a runtime exception if this object is marked read-only.
*
* @param imports feature plug-in dependency information
* @since 2.0
*/
public void setImportModels(ImportModel[] imports) {
assertIsWriteable();
if (imports == null)
this.imports = null;
else
this.imports = new ArrayList(Arrays.asList(imports));
}
/**
* Sets the feature plug-in references.
* Throws a runtime exception if this object is marked read-only.
*
* @param pluginEntries feature plug-in references
* @since 2.0
*/
public void setPluginEntryModels(PluginEntryModel[] pluginEntries) {
assertIsWriteable();
if (pluginEntries == null)
this.pluginEntries = null;
else
this.pluginEntries = new ArrayList(Arrays.asList(pluginEntries));
}
/**
* Sets the feature non-plug-in data references.
* Throws a runtime exception if this object is marked read-only.
*
* @param nonPluginEntries feature non-plug-in data references
* @since 2.0
*/
public void setNonPluginEntryModels(NonPluginEntryModel[] nonPluginEntries) {
assertIsWriteable();
if (nonPluginEntries == null)
this.nonPluginEntries = null;
else
this.nonPluginEntries = new ArrayList(Arrays.asList(nonPluginEntries));
}
/**
* Adds an additional update site reference.
* Throws a runtime exception if this object is marked read-only.
*
* @param discoverySiteInfo update site reference
* @since 2.0
*/
public void addDiscoverySiteEntryModel(URLEntryModel discoverySiteInfo) {
assertIsWriteable();
if (this.discoverySiteInfo == null)
this.discoverySiteInfo = new ArrayList();
if (!this.discoverySiteInfo.contains(discoverySiteInfo))
this.discoverySiteInfo.add(discoverySiteInfo);
}
/**
* Adds a plug-in dependency entry.
* Throws a runtime exception if this object is marked read-only.
*
* @param importEntry plug-in dependency entry
* @since 2.0
*/
public void addImportModel(ImportModel importEntry) {
assertIsWriteable();
if (this.imports == null)
this.imports = new ArrayList();
if (!this.imports.contains(importEntry))
this.imports.add(importEntry);
}
/**
* Adds a plug-in reference.
* Throws a runtime exception if this object is marked read-only.
*
* @param pluginEntry plug-in reference
* @since 2.0
*/
public void addPluginEntryModel(PluginEntryModel pluginEntry) {
assertIsWriteable();
if (this.pluginEntries == null)
this.pluginEntries = new ArrayList();
//PERF: no ListContains()
//if (!this.pluginEntries.contains(pluginEntry))
this.pluginEntries.add(pluginEntry);
}
/**
* Adds a feature identifier.
* Throws a runtime exception if this object is marked read-only.
* @param include the included feature
* @since 2.1
*/
public void addIncludedFeatureReferenceModel(IncludedFeatureReferenceModel include) {
assertIsWriteable();
if (this.featureIncludes == null)
this.featureIncludes = new ArrayList();
//PERF: no ListContains()
//if (!this.featureIncludes.contains(include))
this.featureIncludes.add(include);
}
/**
* Adds a non-plug-in data reference.
* Throws a runtime exception if this object is marked read-only.
*
* @param nonPluginEntry non-plug-in data reference
* @since 2.0
*/
public void addNonPluginEntryModel(NonPluginEntryModel nonPluginEntry) {
assertIsWriteable();
if (this.nonPluginEntries == null)
this.nonPluginEntries = new ArrayList();
//PERF: no ListContains()
//if (!this.nonPluginEntries.contains(nonPluginEntry))
this.nonPluginEntries.add(nonPluginEntry);
}
/**
* Removes an update site reference.
* Throws a runtime exception if this object is marked read-only.
*
* @param discoverySiteInfo update site reference
* @since 2.0
*/
public void removeDiscoverySiteEntryModel(URLEntryModel discoverySiteInfo) {
assertIsWriteable();
if (this.discoverySiteInfo != null)
this.discoverySiteInfo.remove(discoverySiteInfo);
}
/**
* Removes a plug-in dependency entry.
* Throws a runtime exception if this object is marked read-only.
*
* @param importEntry plug-in dependency entry
* @since 2.0
*/
public void removeImportModel(ImportModel importEntry) {
assertIsWriteable();
if (this.imports != null)
this.imports.remove(importEntry);
}
/**
* Removes a plug-in reference.
* Throws a runtime exception if this object is marked read-only.
*
* @param pluginEntry plug-in reference
* @since 2.0
*/
public void removePluginEntryModel(PluginEntryModel pluginEntry) {
assertIsWriteable();
if (this.pluginEntries != null)
this.pluginEntries.remove(pluginEntry);
}
/**
* Removes a non-plug-in data reference.
* Throws a runtime exception if this object is marked read-only.
*
* @param nonPluginEntry non-plug-in data reference
* @since 2.0
*/
public void removeNonPluginEntryModel(NonPluginEntryModel nonPluginEntry) {
assertIsWriteable();
if (this.nonPluginEntries != null)
this.nonPluginEntries.remove(nonPluginEntry);
}
/**
* Marks the model object as read-only.
*
* @since 2.0
*/
public void markReadOnly() {
super.markReadOnly();
markReferenceReadOnly(getDescriptionModel());
markReferenceReadOnly(getCopyrightModel());
markReferenceReadOnly(getLicenseModel());
markReferenceReadOnly(getUpdateSiteEntryModel());
markListReferenceReadOnly(getDiscoverySiteEntryModels());
markListReferenceReadOnly(getImportModels());
markListReferenceReadOnly(getPluginEntryModels());
markListReferenceReadOnly(getNonPluginEntryModels());
}
/**
* Resolve the model object.
* Any URL strings in the model are resolved relative to the
* base URL argument. Any translatable strings in the model that are
* specified as translation keys are localized using the supplied
* resource bundle.
*
* @param base URL
* @param bundleURL resource bundle url
* @exception MalformedURLException
* @since 2.0
*/
public void resolve(URL base,URL bundleURL) throws MalformedURLException {
this.bundleURL = bundleURL;
this.base = base;
// plugin entry and nonpluginentry are optimized too
resolveListReference(getPluginEntryModels(), base, bundleURL);
resolveListReference(getNonPluginEntryModels(), base, bundleURL);
//URLSiteModel are optimized
resolveReference(getDescriptionModel(),base, bundleURL);
resolveReference(getCopyrightModel(),base, bundleURL);
resolveReference(getLicenseModel(),base, bundleURL);
resolveReference(getUpdateSiteEntryModel(),base, bundleURL);
resolveListReference(getDiscoverySiteEntryModels(),base, bundleURL);
// Import Models are optimized
resolveListReference(getImportModels(),base, bundleURL);
}
private void delayedResolve() {
// PERF: delay resolution
if (resolved)
return;
resolved = true;
// resolve local elements
localizedLabel = resolveNLString(bundleURL, label);
localizedProvider = resolveNLString(bundleURL, provider);
try {
imageURL = resolveURL(base,bundleURL, imageURLString);
} catch (MalformedURLException e){
UpdateCore.warn("",e); //$NON-NLS-1$
}
}
/**
* Method setPrimaryPlugin.
* @param plugin
*/
public void setPrimaryPluginID(String plugin) {
if (primary && primaryPluginID == null) {
primaryPluginID = featureId;
}
primaryPluginID = plugin;
}
/**
* Returns the primaryPluginID.
* @return String
*/
public String getPrimaryPluginID() {
return primaryPluginID;
}
/**
* Returns <code>true</code> if this feature is patching another feature,
* <code>false</code> otherwise
* @return boolean
*/
public boolean isPatch() {
ImportModel[] imports = getImportModels();
for (int i = 0; i < imports.length; i++) {
if (imports[i].isPatch())
return true;
}
return false;
}
}