Skip to content

Commit

Permalink
fix igniterealtime#43: Prevent ClassCastExceptions after plugin gets …
Browse files Browse the repository at this point in the history
…reloaded in a cluster

This plugin caches instances of classes that are defined in the code of the plugin. This causes ClassCastExceptions, when the plugin gets unloaded (removing the class definitions) and updated/reloaded (replacing the class definitions). The cached values at that time will refer to classes that no longer exist, causing the exceptions.

https://igniterealtime.atlassian.net/browse/OF-2239 introduces a new type of Cache to work around this problem, the org.jivesoftware.util.cache.SerializingCache which is available since Openfire 4.7.0. This implementation does not cache the instance directly, but caches a serialized version instead. This way, there no longer is a reference to the class, which means that any (compatible) future class definition can be used to instantiate the cache entry again.
  • Loading branch information
guusdk committed Jan 21, 2024
1 parent 9cd0371 commit 2dc101a
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 7 deletions.
1 change: 1 addition & 0 deletions changelog.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ <h1>HTTP File Upload Plugin Changelog</h1>
<p><b>1.4.1</b> -- (tbd)</p>
<ul>
<li>Updated Ukrainian (uk_UA) translation, by Vladislav Savchuk (Bruhmozavr)</li>
<li><a href="https://github.com/igniterealtime/openfire-httpFileUpload-plugin/issues/43">Issue #43:</a> ClassCastExceptions after reloading plugin in a cluster.</li>
</ul>

<p><b>1.4.0</b> -- (January 19, 2024)</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2022 Ignite Realtime Foundation. All rights reserved.
* Copyright (c) 2017-2024 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 @@ -29,10 +29,11 @@

public class OpenfireSlotProvider implements SlotProvider
{
private final Cache<SecureUniqueId, Slot> slotsCache;
// Use string-representation of SecureUniqueId as cache key, as the interface cannot be processed by JAXB.
private final Cache<String, Slot> slotsCache;

public OpenfireSlotProvider() {
slotsCache = CacheFactory.createCache("HTTP File Upload Slots");
slotsCache = CacheFactory.createSerializingCache("HTTP File Upload Slots", String.class, Slot.class);

// Unless there is specific configuration for this cache, default the max lifetime of entries in this cache to something that's fairly short.
if (null == JiveGlobals.getProperty("cache." + slotsCache.getName().replaceAll(" ", "") + ".maxLifetime")) {
Expand All @@ -43,10 +44,10 @@ public OpenfireSlotProvider() {
@Override
public void create(@Nonnull final Slot slot)
{
final Lock lock = slotsCache.getLock(slot.getUuid());
final Lock lock = slotsCache.getLock(slot.getUuid().toString());
lock.lock();
try {
slotsCache.put( slot.getUuid(), slot );
slotsCache.put( slot.getUuid().toString(), slot );
} finally {
lock.unlock();
}
Expand All @@ -56,10 +57,10 @@ public void create(@Nonnull final Slot slot)
@Override
public Slot consume(@Nonnull final SecureUniqueId slotId)
{
final Lock lock = slotsCache.getLock(slotId);
final Lock lock = slotsCache.getLock(slotId.toString());
lock.lock();
try {
return slotsCache.remove(slotId);
return slotsCache.remove(slotId.toString());
} finally {
lock.unlock();
}
Expand Down

0 comments on commit 2dc101a

Please sign in to comment.