/*******************************************************************************
* Copyright (c) 2012 Pivotal Software, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal Software, Inc. - initial API and implementation
*******************************************************************************/
package org.springsource.ide.eclipse.dashboard.internal.ui.editors;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.mylyn.internal.tasks.core.sync.GetTaskHistoryJob;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;
import com.sun.syndication.feed.synd.SyndCategory;
import com.sun.syndication.feed.synd.SyndEntry;
/**
* Represents a notification based on an RSS feed entry.
*
* @author Steffen Pingel
*/
public class UpdateNotification {
public static class Artifact {
final String bundleId;
// currently not supported
final VersionRange versionRange;
public Artifact(String bundleId, VersionRange bundleVersion) {
Assert.isNotNull(bundleId);
this.bundleId = bundleId;
this.versionRange = bundleVersion;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Artifact other = (Artifact) obj;
if (bundleId == null) {
if (other.bundleId != null) {
return false;
}
}
else if (!bundleId.equals(other.bundleId)) {
return false;
}
if (versionRange == null) {
if (other.versionRange != null) {
return false;
}
}
else if (!versionRange.equals(other.versionRange)) {
return false;
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((bundleId == null) ? 0 : bundleId.hashCode());
result = prime * result + ((versionRange == null) ? 0 : versionRange.hashCode());
return result;
}
@Override
public String toString() {
return "Artifact [bundleId=" + bundleId + ", versionRange=" + versionRange + "]";
}
}
private final Set<Artifact> conflictingBundles = new HashSet<Artifact>();
private final SyndEntry entry;
private String platformFilter;
private final Set<Artifact> requiredBundles = new HashSet<Artifact>();
private String severity;
private String versionRange;
public UpdateNotification(List<String> properties) {
this.entry = null;
for (String property : properties) {
parseProperty(property);
}
}
public UpdateNotification(SyndEntry entry) {
this.entry = entry;
List<?> categories = entry.getCategories();
for (int i = 0; i < categories.size(); i++) {
Object obj = categories.get(i);
if (obj instanceof SyndCategory) {
SyndCategory category = (SyndCategory) obj;
String text = category.getName();
parseProperty(text);
}
}
}
public Set<Artifact> getConflictingBundles() {
return Collections.unmodifiableSet(conflictingBundles);
}
public SyndEntry getEntry() {
return entry;
}
public String getPlatformFilter() {
return platformFilter;
}
public Set<Artifact> getRequiredBundles() {
return Collections.unmodifiableSet(requiredBundles);
}
public String getSeverity() {
return severity;
}
public String getVersionRange() {
return versionRange;
}
/**
* Return true, if the notification is valid for the passed parameters.
*
* @param ideVersion the version of STS to check against
* @param environment
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public boolean matches(Version ideVersion, Set<String> installedFeatureIds, Dictionary<?, ?> environment) {
if (versionRange != null) {
VersionRange range = new VersionRange(versionRange);
if (!range.isIncluded(ideVersion)) {
return false;
}
}
if (installedFeatureIds != null && !requiredBundles.isEmpty()) {
for (Artifact artifact : requiredBundles) {
if (!installedFeatureIds.contains(artifact.bundleId)) {
return false;
}
}
}
if (installedFeatureIds != null && !conflictingBundles.isEmpty()) {
for (Artifact artifact : conflictingBundles) {
if (installedFeatureIds.contains(artifact.bundleId)) {
return false;
}
}
}
if (platformFilter != null) {
try {
Filter filter = FrameworkUtil.createFilter(platformFilter);
// TODO e3.7 remove cast and use expected typesObject
if (!filter.match((Dictionary) environment)) {
return false;
}
}
catch (InvalidSyntaxException e) {
// ignore
}
}
return true;
}
private Artifact parseArtifact(String substring) {
String bundleId = null;
VersionRange bundleVersion = null;
String[] tokens = substring.split(";");
for (String token : tokens) {
if (token.contains("=")) {
if (token.startsWith("version=")) {
try {
bundleVersion = new VersionRange(token.replaceFirst("version=", ""));
}
catch (IllegalArgumentException e) {
// ignore
return null;
}
}
}
else {
bundleId = token;
}
}
if (bundleId == null) {
// invalid specification
return null;
}
return new Artifact(bundleId, bundleVersion);
}
private void parseProperty(String text) {
if (text.startsWith("severity=")) {
severity = text.replaceFirst("severity=", "");
}
else if (text.startsWith("version=")) {
versionRange = text.replaceFirst("version=", "");
}
else if (text.startsWith("platform.filter=")) {
platformFilter = text.replaceFirst("platform.filter=", "");
}
else if (text.startsWith("bundle=")) {
String bundle = text.replaceFirst("bundle=", "");
if (bundle.startsWith("!")) {
Artifact artifact = parseArtifact(bundle.substring(1));
if (artifact != null) {
conflictingBundles.add(artifact);
}
}
else {
Artifact artifact = parseArtifact(bundle);
if (artifact != null) {
requiredBundles.add(artifact);
}
}
}
}
@Override
public int hashCode() {
if (entry.getTitle() != null) {
return entry.getTitle().hashCode();
}
else {
return -1;
}
}
@Override
public boolean equals(Object other) {
return other instanceof UpdateNotification && ((UpdateNotification) other).getEntry() != null && ((UpdateNotification) other).getEntry().getTitle().equals(entry.getTitle());
}
}