Skip to content

Commit

Permalink
OF-2941: Improve Version comparison that involve SNAPSHOTs
Browse files Browse the repository at this point in the history
For certain versions of plugins, Openfire incorrectly identifies that an update is available.

When Openfire has installed `10.1.7.3-SNAPSHOT` it incorrectly identifies that version `10.1.7.2` is an update.

This seems to be caused by Openfire’s abuse of the 4th numeric value in a version. It was originally intended to be a classifier for the status (eg: ‘the second beta release’). When that 4th value is used as part of a four-digit version, things do not quite compare as expected.

To illustrate, compare these two scenarios. The numbers 3 and 2 are all stored in the same field, which gets interpreted differently.

- `10.1.7 beta 3` is older than `10.1.7 release 2`

- `10.1.7.3-SNAPSHOT` is expected to be newer than `10.1.7.2` (release).

Prior to this commit, Openfire did not flag that `10.1.7.3-SNAPSHOT` is newer than `10.1.7.2`, which was causing confusion.

In this commit, _only_ the `SNAPSHOT` release status is now compared differently (as if the 4th value is part of the version string).

(cherry picked from commit 72b67cb)
  • Loading branch information
guusdk authored and github-actions[bot] committed Jan 4, 2025
1 parent 2214420 commit 38be2c0
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 Jive Software, 2017-2018 Ignite Realtime Foundation. All rights reserved.
* Copyright (C) 2005-2008 Jive Software, 2017-2025 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,8 @@

package org.jivesoftware.openfire.update;

import org.jivesoftware.util.Version;

/**
* An Update represents a component that needs to be updated. By component we can refer
* to the Openfire server itself or to any of the installed plugins.
Expand All @@ -28,27 +30,35 @@ public class Update {
* Name of the component that is outdated. The name could be of the server
* (i.e. "Openfire") or of installed plugins.
*/
private String componentName;
private final String componentName;
/**
* Latest version of the component that was found.
*/
private String latestVersion;
private final Version latestVersion;
/**
* URL from where the latest version of the component can be downloaded.
*/
private String url;
private final String url;
/**
* Changelog URL of the latest version of the component.
*/
private String changelog;
private final String changelog;

/**
* Flag that indicates if the plugin was downloaded. This flag only makes sense for
* plugins since we currently do not support download new openfire releases.
*/
private boolean downloaded;

@Deprecated(forRemoval = true) // Remove in or after Openfire 5.1.0
public Update(String componentName, String latestVersion, String changelog, String url) {
this.componentName = componentName;
this.latestVersion = new Version(latestVersion);
this.changelog = changelog;
this.url = url;
}

public Update(String componentName, Version latestVersion, String changelog, String url) {
this.componentName = componentName;
this.latestVersion = latestVersion;
this.changelog = changelog;
Expand All @@ -72,6 +82,15 @@ public String getComponentName() {
* @return the latest version of the component that was found.
*/
public String getLatestVersion() {
return latestVersion.getVersionString();
}

/**
* Returns the latest version of the component that was found.
*
* @return the latest version of the component that was found.
*/
public Version getLatest() {
return latestVersion;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 Jive Software, 2017-2023 Ignite Realtime Foundation. All rights reserved.
* Copyright (C) 2005-2008 Jive Software, 2017-2025 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -529,7 +529,7 @@ public Update getPluginUpdate(String pluginName, Version currentVersion) {
// Check if this is the requested plugin
if (update.getComponentName().equals(pluginName)) {
// Check if the plugin version is right
if (new Version(update.getLatestVersion()).isNewerThan( currentVersion ) ) {
if (update.getLatest().isNewerThan( currentVersion ) ) {
return update;
}
}
Expand Down Expand Up @@ -585,7 +585,7 @@ private void processServerUpdateResponse(String response, boolean notificationsE
Log.warn( "Unable to parse URL from openfire download url value '{}'.", openfire.attributeValue("url"), e );
}
// Keep information about the available server update
serverUpdate = new Update("Openfire", latestVersion.getVersionString(), String.valueOf(changelog), String.valueOf(url));
serverUpdate = new Update("Openfire", latestVersion, String.valueOf(changelog), String.valueOf(url));
}
}
// Check if we need to send notifications to admins
Expand Down Expand Up @@ -670,7 +670,7 @@ private void buildPluginsUpdateList() {
continue;
}

final Update update = new Update( plugin.getName(), latestPlugin.getVersion().getVersionString(), latestPlugin.getChangelog().toExternalForm(), latestPlugin.getDownloadURL().toExternalForm() );
final Update update = new Update( plugin.getName(), latestPlugin.getVersion(), latestPlugin.getChangelog().toExternalForm(), latestPlugin.getDownloadURL().toExternalForm() );
pluginUpdates.add(update);
}
}
Expand Down Expand Up @@ -832,7 +832,7 @@ private void loadLatestServerInfo() {
// Check if current server version is correct
Version currentServerVersion = XMPPServer.getInstance().getServerInfo().getVersion();
if (latestVersion.isNewerThan(currentServerVersion)) {
serverUpdate = new Update("Openfire", latestVersion.getVersionString(), String.valueOf(changelog), String.valueOf(url) );
serverUpdate = new Update("Openfire", latestVersion, String.valueOf(changelog), String.valueOf(url) );
}
}
}
Expand Down
14 changes: 11 additions & 3 deletions xmppserver/src/main/java/org/jivesoftware/util/Version.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2008 Jive Software, 2017-2019 Ignite Realtime Foundation. All rights reserved.
* Copyright (C) 2004-2008 Jive Software, 2017-2025 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -254,9 +254,17 @@ public int compareTo(Version that) {
if (result == 0) {
result = Integer.compare(getMicro(), that.getMicro());
if (result == 0) {
result = that.getStatus().compareTo(getStatus());
if (result == 0) {
// OF-2941: Hacky solution to allow for four-digit SNAPSHOT version comparison.
if (that.status == ReleaseStatus.Snapshot || status == ReleaseStatus.Snapshot) {
result = Integer.compare(getStatusVersion(), that.getStatusVersion());
if (result == 0) {
result = that.getStatus().compareTo(getStatus());
}
} else {
result = that.getStatus().compareTo(getStatus());
if (result == 0) {
result = Integer.compare(getStatusVersion(), that.getStatusVersion());
}
}
}
}
Expand Down
42 changes: 41 additions & 1 deletion xmppserver/src/test/java/org/jivesoftware/util/VersionTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2023 Ignite Realtime Foundation. All rights reserved.
* Copyright (C) 2017-2025 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -168,4 +168,44 @@ public void willVersionAFourDigitRelease() {
assertThat(test.getStatus(), is(ReleaseStatus.Release));
assertThat(test.getVersionString(),is("1.2.3 Release 4"));
}

@Test // OF-2941
public void testSnapshotCompareToRelease() {
final Version snapshotVersion = new Version(10,1,7, ReleaseStatus.Snapshot, 3);
final Version olderReleaseVersion = new Version(10,1,7, ReleaseStatus.Release, 2);

assertTrue(snapshotVersion.isNewerThan(olderReleaseVersion));
}

@Test // OF-2941
public void testAlphaCompareToRelease() {
final Version alphaVersion = new Version(10,1,7, ReleaseStatus.Alpha, 3);
final Version newerReleaseVersion = new Version(10,1,7, ReleaseStatus.Release, 2);

assertTrue(newerReleaseVersion.isNewerThan(alphaVersion));
}

@Test // OF-2941
public void testBetaCompareToRelease() {
final Version betaVersion = new Version(10,1,7, ReleaseStatus.Beta, 3);
final Version newerReleaseVersion = new Version(10,1,7, ReleaseStatus.Release, 2);

assertTrue(newerReleaseVersion.isNewerThan(betaVersion));
}

@Test // OF-2941
public void testReleaseCandidateCompareToRelease() {
final Version releaseCandidateVersion = new Version(10,1,7, ReleaseStatus.Release_Candidate, 3);
final Version newerReleaseVersion = new Version(10,1,7, ReleaseStatus.Release, 2);

assertTrue(newerReleaseVersion.isNewerThan(releaseCandidateVersion));
}

@Test // OF-2941
public void testReleaseCompareToRelease() {
final Version releaseVersion = new Version(10,1,7, ReleaseStatus.Release, 3);
final Version olderReleaseVersion = new Version(10,1,7, ReleaseStatus.Release, 2);

assertTrue(releaseVersion.isNewerThan(olderReleaseVersion));
}
}

0 comments on commit 38be2c0

Please sign in to comment.