| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * James D Miles (IBM Corp.) - bug 191783, NullPointerException in FeatureDownloader |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.updatesite; |
| |
| import java.io.File; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.*; |
| |
| /** |
| * A reference to a feature in an update site.xml file. |
| * |
| * Based on org.eclipse.update.core.model.FeatureReferenceModel. |
| */ |
| public class SiteFeature { |
| |
| private String arch; |
| // performance |
| private URL base; |
| private List<String> categoryNames; |
| private String featureId; |
| private String featureVersion; |
| private String label; |
| private String nl; |
| |
| private String os; |
| private String patch; |
| private final boolean resolved = false; |
| private SiteModel site; |
| private String type; |
| private URL url; |
| private String urlString; |
| private String ws; |
| |
| /* |
| * Compares two URL for equality |
| */ |
| public static boolean sameURL(URL url1, URL url2) { |
| if (url1 == url2) |
| return true; |
| if (url1 == null ^ url2 == null) |
| return false; |
| |
| // check if URL are file: URL as we may |
| // have 2 URL pointing to the same featureReference |
| // but with different representation |
| // (i.e. file:/C;/ and file:C:/) |
| final boolean isFile1 = "file".equalsIgnoreCase(url1.getProtocol());//$NON-NLS-1$ |
| final boolean isFile2 = "file".equalsIgnoreCase(url2.getProtocol());//$NON-NLS-1$ |
| if (isFile1 && isFile2) { |
| File file1 = new File(url1.getFile()); |
| File file2 = new File(url2.getFile()); |
| return file1.equals(file2); |
| } |
| // URL1 xor URL2 is a file, return false. (They either both need to be files, or |
| // neither) |
| if (isFile1 ^ isFile2) |
| return false; |
| return getExternalForm(url1).equals(getExternalForm(url2)); |
| } |
| |
| /** |
| * Gets the external form of this URL. In particular, it trims any white space, |
| * removes a trailing slash and creates a lower case string. |
| */ |
| private static String getExternalForm(URL url) { |
| String externalForm = url.toExternalForm(); |
| if (externalForm == null) |
| return ""; //$NON-NLS-1$ |
| externalForm = externalForm.trim(); |
| if (externalForm.endsWith("/")) { //$NON-NLS-1$ |
| // Remove the trailing slash |
| externalForm = externalForm.substring(0, externalForm.length() - 1); |
| } |
| return externalForm.toLowerCase(); |
| |
| } |
| |
| /** |
| * Creates an uninitialized feature reference model object. |
| */ |
| public SiteFeature() { |
| super(); |
| } |
| |
| /** |
| * Adds the name of a category this feature belongs to. Throws a runtime |
| * exception if this object is marked read-only. |
| * |
| * @param categoryName category name |
| */ |
| public void addCategoryName(String categoryName) { |
| if (this.categoryNames == null) |
| this.categoryNames = new ArrayList<>(); |
| if (!this.categoryNames.contains(categoryName)) |
| this.categoryNames.add(categoryName); |
| } |
| |
| private void delayedResolve() { |
| |
| // PERF: delay resolution |
| if (resolved) |
| return; |
| |
| // resolve local elements |
| try { |
| url = new URL(base, urlString); |
| } catch (MalformedURLException e) { |
| // UpdateCore.warn("", e); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Compares 2 feature reference models for equality |
| * |
| * @param object feature reference model to compare with |
| * @return <code>true</code> if the two models are equal, <code>false</code> |
| * otherwise |
| */ |
| @Override |
| public boolean equals(Object object) { |
| if (object == null) |
| return false; |
| if (!(object instanceof SiteFeature)) |
| return false; |
| SiteFeature that = (SiteFeature) object; |
| if (this.featureId == null) { |
| if (that.featureId != null) |
| return false; |
| } else if (!this.featureId.equals(that.featureId)) |
| return false; |
| if (this.featureVersion == null) { |
| if (that.featureVersion != null) |
| return false; |
| } else if (!this.featureVersion.equals(that.featureVersion)) |
| return false; |
| if (this.label == null) { |
| if (that.label != null) |
| return false; |
| } else if (!this.label.equals(that.label)) |
| return false; |
| return sameURL(this.getURL(), that.getURL()); |
| } |
| |
| @Override |
| public int hashCode() { |
| final int prime = 31; |
| int result = 1; |
| result = prime * result + (featureId == null ? 0 : featureId.hashCode()); |
| result = prime * result + (featureVersion == null ? 0 : featureVersion.hashCode()); |
| if (this.getURL() == null) |
| return result; |
| |
| if ("file".equalsIgnoreCase(getURL().getProtocol())) {//$NON-NLS-1$ |
| // If the URL is a file, then create the HashCode from the file |
| File f = new File(getURL().getFile()); |
| if (f != null) |
| result = prime * result + f.hashCode(); |
| } else |
| // Otherwise create it from the External form of the URL (in lower case) |
| result = prime * result + getExternalForm(this.getURL()).hashCode(); |
| return result; |
| } |
| |
| /** |
| * Returns the names of categories the referenced feature belongs to. |
| * |
| * @return an array of names, or an empty array. |
| */ |
| public String[] getCategoryNames() { |
| if (categoryNames == null) |
| return new String[0]; |
| |
| return categoryNames.toArray(new String[0]); |
| } |
| |
| /** |
| * Returns the feature identifier as a string |
| * |
| * @return feature identifier |
| */ |
| public String getFeatureIdentifier() { |
| return featureId; |
| } |
| |
| /** |
| * Returns the feature version as a string |
| * |
| * @return feature version |
| */ |
| public String getFeatureVersion() { |
| return featureVersion; |
| } |
| |
| /** |
| * Retrieve the displayable label for the feature reference. If the model object |
| * has been resolved, the label is localized. |
| * |
| * @return displayable label, or <code>null</code>. |
| */ |
| public String getLabel() { |
| return label; |
| } |
| |
| /** |
| * Retrieve the non-localized displayable label for the feature reference. |
| * |
| * @return non-localized displayable label, or <code>null</code>. |
| */ |
| public String getLabelNonLocalized() { |
| return label; |
| } |
| |
| /** |
| * Get optional locale specification as a comma-separated string. |
| * |
| * @return the locale specification string, or <code>null</code>. |
| */ |
| public String getNL() { |
| return nl; |
| } |
| |
| /** |
| * Get optional operating system specification as a comma-separated string. |
| * |
| * @return the operating system specification string, or <code>null</code>. |
| */ |
| public String getOS() { |
| return os; |
| } |
| |
| /** |
| * Get optional system architecture specification as a comma-separated string. |
| * |
| * @return the system architecture specification string, or <code>null</code>. |
| */ |
| public String getOSArch() { |
| return arch; |
| } |
| |
| /** |
| * Returns the patch mode. |
| */ |
| public String getPatch() { |
| return patch; |
| } |
| |
| /** |
| * Returns the site model for the reference. |
| * |
| * @return site model |
| * @since 2.0 |
| */ |
| public SiteModel getSiteModel() { |
| return site; |
| } |
| |
| /** |
| * Returns the referenced feature type. |
| * |
| * @return feature type, or <code>null</code> representing the default feature |
| * type for the site |
| */ |
| public String getType() { |
| return type; |
| } |
| |
| /** |
| * Returns the resolved URL for the feature reference. |
| * |
| * @return url string |
| */ |
| public URL getURL() { |
| delayedResolve(); |
| return url; |
| } |
| |
| /** |
| * Returns the unresolved URL string for the reference. |
| * |
| * @return url string |
| */ |
| public String getURLString() { |
| return urlString; |
| } |
| |
| /** |
| * Get optional windowing system specification as a comma-separated string. |
| * |
| * @return the windowing system specification string, or <code>null</code>. |
| */ |
| public String getWS() { |
| return ws; |
| } |
| |
| /** |
| * 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 resolveBase URL |
| * @param bundleURL resource bundle URL |
| * @exception MalformedURLException |
| */ |
| public void resolve(URL resolveBase, URL bundleURL) throws MalformedURLException { |
| this.base = resolveBase; |
| } |
| |
| /** |
| * 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 |
| */ |
| public void setArch(String arch) { |
| this.arch = arch; |
| } |
| |
| /** |
| * Sets the names of categories this feature belongs to. Throws a runtime |
| * exception if this object is marked read-only. |
| * |
| * @param categoryNames an array of category names |
| */ |
| public void setCategoryNames(String[] categoryNames) { |
| if (categoryNames == null) |
| this.categoryNames = null; |
| else |
| this.categoryNames = new ArrayList<>(Arrays.asList(categoryNames)); |
| } |
| |
| /** |
| * Sets the feature identifier. Throws a runtime exception if this object is |
| * marked read-only. |
| * |
| * @param featureId feature identifier |
| */ |
| public void setFeatureIdentifier(String featureId) { |
| this.featureId = featureId; |
| } |
| |
| /** |
| * Sets the feature version. Throws a runtime exception if this object is marked |
| * read-only. |
| * |
| * @param featureVersion feature version |
| */ |
| public void setFeatureVersion(String featureVersion) { |
| this.featureVersion = featureVersion; |
| } |
| |
| /** |
| * Sets the label. |
| * |
| * @param label The label to set |
| */ |
| public void setLabel(String label) { |
| this.label = label; |
| } |
| |
| /** |
| * Sets the locale specification. Throws a runtime exception if this object is |
| * marked read-only. |
| * |
| * @param nl locale specification as a comma-separated list |
| */ |
| public void setNL(String nl) { |
| this.nl = nl; |
| } |
| |
| /** |
| * 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 |
| */ |
| public void setOS(String os) { |
| this.os = os; |
| } |
| |
| /** |
| * Sets the patch mode. |
| */ |
| public void setPatch(String patch) { |
| this.patch = patch; |
| } |
| |
| /** |
| * Sets the site for the referenced. Throws a runtime exception if this object |
| * is marked read-only. |
| * |
| * @param site site for the reference |
| */ |
| public void setSiteModel(SiteModel site) { |
| this.site = site; |
| } |
| |
| /** |
| * Sets the referenced feature type. Throws a runtime exception if this object |
| * is marked read-only. |
| * |
| * @param type referenced feature type |
| */ |
| public void setType(String type) { |
| this.type = type; |
| } |
| |
| /** |
| * Sets the unresolved URL for the feature reference. Throws a runtime exception |
| * if this object is marked read-only. |
| * |
| * @param urlString unresolved URL string |
| */ |
| public void setURLString(String urlString) { |
| this.urlString = urlString; |
| this.url = null; |
| } |
| |
| /** |
| * 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 |
| */ |
| public void setWS(String ws) { |
| this.ws = ws; |
| } |
| |
| /** |
| * @see Object#toString() |
| */ |
| @Override |
| public String toString() { |
| StringBuilder buffer = new StringBuilder(); |
| if (featureId != null) |
| buffer.append(featureId).append(' '); |
| if (featureVersion != null) |
| buffer.append(featureVersion).append(' '); |
| if (url != null) { |
| buffer.append(" at "); //$NON-NLS-1$ |
| buffer.append(url.toExternalForm()); |
| } |
| return buffer.toString(); |
| } |
| |
| } |