-
Notifications
You must be signed in to change notification settings - Fork 351
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: jansupol <[email protected]>
- Loading branch information
Showing
14 changed files
with
784 additions
and
181 deletions.
There are no files selected for viewing
208 changes: 208 additions & 0 deletions
208
...n/java/org/glassfish/jersey/internal/util/collection/GuardianStringKeyMultivaluedMap.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
/* | ||
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License v. 2.0, which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* This Source Code may also be made available under the following Secondary | ||
* Licenses when the conditions for such availability set forth in the | ||
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | ||
* version 2 with the GNU Classpath Exception, which is available at | ||
* https://www.gnu.org/software/classpath/license.html. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | ||
*/ | ||
|
||
package org.glassfish.jersey.internal.util.collection; | ||
|
||
import javax.ws.rs.core.MultivaluedMap; | ||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
|
||
/** | ||
* The {@link MultivaluedMap} wrapper that is able to set guards observing changes of values represented by a key. | ||
* @param <V> The value type of the wrapped {@code MultivaluedMap}. | ||
* | ||
* @since 2.38 | ||
*/ | ||
public class GuardianStringKeyMultivaluedMap<V> implements MultivaluedMap<String, V> { | ||
|
||
private final MultivaluedMap<String, V> inner; | ||
private final Map<String, Boolean> guards = new HashMap<>(); | ||
|
||
public GuardianStringKeyMultivaluedMap(MultivaluedMap<String, V> inner) { | ||
this.inner = inner; | ||
} | ||
|
||
@Override | ||
public void putSingle(String key, V value) { | ||
observe(key); | ||
inner.putSingle(key, value); | ||
} | ||
|
||
@Override | ||
public void add(String key, V value) { | ||
observe(key); | ||
inner.add(key, value); | ||
} | ||
|
||
@Override | ||
public V getFirst(String key) { | ||
return inner.getFirst(key); | ||
} | ||
|
||
@Override | ||
public void addAll(String key, V... newValues) { | ||
observe(key); | ||
inner.addAll(key, newValues); | ||
} | ||
|
||
@Override | ||
public void addAll(String key, List<V> valueList) { | ||
observe(key); | ||
inner.addAll(key, valueList); | ||
} | ||
|
||
@Override | ||
public void addFirst(String key, V value) { | ||
observe(key); | ||
inner.addFirst(key, value); | ||
} | ||
|
||
@Override | ||
public boolean equalsIgnoreValueOrder(MultivaluedMap<String, V> otherMap) { | ||
return inner.equalsIgnoreValueOrder(otherMap); | ||
} | ||
|
||
@Override | ||
public int size() { | ||
return inner.size(); | ||
} | ||
|
||
@Override | ||
public boolean isEmpty() { | ||
return inner.isEmpty(); | ||
} | ||
|
||
@Override | ||
public boolean containsKey(Object key) { | ||
return inner.containsKey(key); | ||
} | ||
|
||
@Override | ||
public boolean containsValue(Object value) { | ||
return inner.containsValue(value); | ||
} | ||
|
||
@Override | ||
public List<V> get(Object key) { | ||
return inner.get(key); | ||
} | ||
|
||
@Override | ||
public List<V> put(String key, List<V> value) { | ||
observe(key); | ||
return inner.put(key, value); | ||
} | ||
|
||
@Override | ||
public List<V> remove(Object key) { | ||
if (key != null) { | ||
observe(key.toString()); | ||
} | ||
return inner.remove(key); | ||
} | ||
|
||
@Override | ||
public void putAll(Map<? extends String, ? extends List<V>> m) { | ||
for (String key : m.keySet()) { | ||
observe(key); | ||
} | ||
inner.putAll(m); | ||
} | ||
|
||
@Override | ||
public void clear() { | ||
observeAll(); | ||
inner.clear(); | ||
} | ||
|
||
@Override | ||
public Set<String> keySet() { | ||
return inner.keySet(); | ||
} | ||
|
||
@Override | ||
public Collection<List<V>> values() { | ||
return inner.values(); | ||
} | ||
|
||
@Override | ||
public Set<Entry<String, List<V>>> entrySet() { | ||
return inner.entrySet(); | ||
} | ||
|
||
/** | ||
* Observe changes of a value represented by the key. | ||
* @param key the key values to observe | ||
*/ | ||
public void setGuard(String key) { | ||
guards.put(key, false); | ||
} | ||
|
||
/** | ||
* Get all the guarded keys | ||
* @return a {@link Set} of keys guarded. | ||
*/ | ||
public Set<String> getGuards() { | ||
return guards.keySet(); | ||
} | ||
|
||
/** | ||
* Return true when the value represented by the key has changed. Resets any observation - the operation is not idempotent. | ||
* @param key the Key observed. | ||
* @return whether the value represented by the key has changed. | ||
*/ | ||
public boolean isObservedAndReset(String key) { | ||
Boolean observed = guards.get(key); | ||
guards.put(key, false); | ||
return observed != null && observed; | ||
} | ||
|
||
private void observe(String key) { | ||
for (Map.Entry<String, Boolean> guard : guards.entrySet()) { | ||
if (guard.getKey().equals(key)) { | ||
guard.setValue(true); | ||
} | ||
} | ||
} | ||
|
||
private void observeAll() { | ||
for (Map.Entry<String, Boolean> guard : guards.entrySet()) { | ||
guard.setValue(true); | ||
} | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return inner.toString(); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
GuardianStringKeyMultivaluedMap<?> that = (GuardianStringKeyMultivaluedMap<?>) o; | ||
return inner.equals(that.inner) && guards.equals(that.guards); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(inner, guards); | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
core-common/src/main/java/org/glassfish/jersey/internal/util/collection/LRU.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License v. 2.0, which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* This Source Code may also be made available under the following Secondary | ||
* Licenses when the conditions for such availability set forth in the | ||
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | ||
* version 2 with the GNU Classpath Exception, which is available at | ||
* https://www.gnu.org/software/classpath/license.html. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | ||
*/ | ||
|
||
package org.glassfish.jersey.internal.util.collection; | ||
|
||
import org.glassfish.jersey.internal.guava.Cache; | ||
import org.glassfish.jersey.internal.guava.CacheBuilder; | ||
|
||
import java.util.concurrent.TimeUnit; | ||
|
||
/** | ||
* An abstract LRU interface wrapping an actual LRU implementation. | ||
* @param <K> Key type | ||
* @param <V> Value type | ||
* @Since 2.38 | ||
*/ | ||
public abstract class LRU<K, V> { | ||
|
||
/** | ||
* Returns the value associated with {@code key} in this cache, or {@code null} if there is no | ||
* cached value for {@code key}. | ||
*/ | ||
public abstract V getIfPresent(Object key); | ||
|
||
/** | ||
* Associates {@code value} with {@code key} in this cache. If the cache previously contained a | ||
* value associated with {@code key}, the old value is replaced by {@code value}. | ||
*/ | ||
public abstract void put(K key, V value); | ||
|
||
/** | ||
* Create new LRU | ||
* @return new LRU | ||
*/ | ||
public static <K, V> LRU<K, V> create() { | ||
return LRUFactory.createLRU(); | ||
} | ||
|
||
private static class LRUFactory { | ||
// TODO configure via the Configuration | ||
public static final int LRU_CACHE_SIZE = 128; | ||
public static final long TIMEOUT = 5000L; | ||
private static <K, V> LRU<K, V> createLRU() { | ||
final Cache<K, V> CACHE = CacheBuilder.newBuilder() | ||
.maximumSize(LRU_CACHE_SIZE) | ||
.expireAfterAccess(TIMEOUT, TimeUnit.MILLISECONDS) | ||
.build(); | ||
return new LRU<K, V>() { | ||
@Override | ||
public V getIfPresent(Object key) { | ||
return CACHE.getIfPresent(key); | ||
} | ||
|
||
@Override | ||
public void put(K key, V value) { | ||
CACHE.put(key, value); | ||
} | ||
}; | ||
} | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.