/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.component.infinispan;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import org.apache.camel.InvokeOnHeader;
import org.apache.camel.Message;
import org.apache.camel.component.infinispan.remote.InfinispanRemoteOperation;
import org.apache.camel.impl.HeaderSelectorProducer;
import org.apache.camel.util.ObjectHelper;
import org.infinispan.commons.api.BasicCache;
import org.infinispan.query.dsl.Query;
import org.jgroups.util.NotifyingFuture;
public class InfinispanProducer extends HeaderSelectorProducer {
private final String cacheName;
private final InfinispanConfiguration configuration;
private final InfinispanManager manager;
public InfinispanProducer(InfinispanEndpoint endpoint, String cacheName, InfinispanConfiguration configuration) {
super(endpoint, InfinispanConstants.OPERATION, () -> configuration.getOperationOrDefault().name(), false);
this.cacheName = cacheName;
this.configuration = configuration;
this.manager = new InfinispanManager(endpoint.getCamelContext(), configuration);
}
@Override
protected void doStart() throws Exception {
super.doStart();
manager.start();
}
@Override
protected void doStop() throws Exception {
manager.stop();
super.doStop();
}
// ************************************
// Operations
// ************************************
@InvokeOnHeader("PUT")
@InvokeOnHeader(InfinispanConstants.PUT)
void onPut(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object key = message.getHeader(InfinispanConstants.KEY);
final Object value = message.getHeader(InfinispanConstants.VALUE);
final Object result;
if (hasLifespan(message)) {
long lifespan = message.getHeader(InfinispanConstants.LIFESPAN_TIME, long.class);
TimeUnit timeUnit = message.getHeader(InfinispanConstants.LIFESPAN_TIME_UNIT, TimeUnit.class);
if (hasMaxIdleTime(message)) {
long maxIdle = message.getHeader(InfinispanConstants.MAX_IDLE_TIME, long.class);
TimeUnit maxIdleTimeUnit = message.getHeader(InfinispanConstants.MAX_IDLE_TIME_UNIT, TimeUnit.class);
result = cache.put(key, value, lifespan, timeUnit, maxIdle, maxIdleTimeUnit);
} else {
result = cache.put(key, value, lifespan, timeUnit);
}
} else {
result = cache.put(key, value);
}
setResult(message, result);
}
@InvokeOnHeader("PUTASYNC")
@InvokeOnHeader(InfinispanConstants.PUT_ASYNC)
void onPutAsync(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object key = message.getHeader(InfinispanConstants.KEY);
final Object value = message.getHeader(InfinispanConstants.VALUE);
final CompletableFuture<Object> result;
if (hasLifespan(message)) {
long lifespan = message.getHeader(InfinispanConstants.LIFESPAN_TIME, long.class);
TimeUnit timeUnit = message.getHeader(InfinispanConstants.LIFESPAN_TIME_UNIT, TimeUnit.class);
if (hasMaxIdleTime(message)) {
long maxIdle = message.getHeader(InfinispanConstants.MAX_IDLE_TIME, long.class);
TimeUnit maxIdleTimeUnit = message.getHeader(InfinispanConstants.MAX_IDLE_TIME_UNIT, TimeUnit.class);
result = cache.putAsync(key, value, lifespan, timeUnit, maxIdle, maxIdleTimeUnit);
} else {
result = cache.putAsync(key, value, lifespan, timeUnit);
}
} else {
result = cache.putAsync(key, value);
}
setResult(message, result);
}
@InvokeOnHeader("PUTALL")
@InvokeOnHeader(InfinispanConstants.PUT_ALL)
void onPutAll(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Map<Object, Object> map = message.getHeader(InfinispanConstants.MAP, Map.class);
if (hasLifespan(message)) {
long lifespan = message.getHeader(InfinispanConstants.LIFESPAN_TIME, long.class);
TimeUnit timeUnit = message.getHeader(InfinispanConstants.LIFESPAN_TIME_UNIT, TimeUnit.class);
if (hasMaxIdleTime(message)) {
long maxIdle = message.getHeader(InfinispanConstants.MAX_IDLE_TIME, long.class);
TimeUnit maxIdleTimeUnit = message.getHeader(InfinispanConstants.MAX_IDLE_TIME_UNIT, TimeUnit.class);
cache.putAll(map, lifespan, timeUnit, maxIdle, maxIdleTimeUnit);
} else {
cache.putAll(map, lifespan, timeUnit);
}
} else {
cache.putAll(map);
}
}
@InvokeOnHeader("PUTALLASYNC")
@InvokeOnHeader(InfinispanConstants.PUT_ALL_ASYNC)
void onPutAllAsync(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Map<Object, Object> map = message.getHeader(InfinispanConstants.MAP, Map.class);
final CompletableFuture<Void> result;
if (hasLifespan(message)) {
long lifespan = message.getHeader(InfinispanConstants.LIFESPAN_TIME, long.class);
TimeUnit timeUnit = message.getHeader(InfinispanConstants.LIFESPAN_TIME_UNIT, TimeUnit.class);
if (hasMaxIdleTime(message)) {
long maxIdle = message.getHeader(InfinispanConstants.MAX_IDLE_TIME, long.class);
TimeUnit maxIdleTimeUnit = message.getHeader(InfinispanConstants.MAX_IDLE_TIME_UNIT, TimeUnit.class);
result = cache.putAllAsync(map, lifespan, timeUnit, maxIdle, maxIdleTimeUnit);
} else {
result = cache.putAllAsync(map, lifespan, timeUnit);
}
} else {
result = cache.putAllAsync(map);
}
setResult(message, result);
}
@InvokeOnHeader("PUTIFABSENT")
@InvokeOnHeader(InfinispanConstants.PUT_IF_ABSENT)
void onPutIfAbsent(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object key = message.getHeader(InfinispanConstants.KEY);
final Object value = message.getHeader(InfinispanConstants.VALUE);
final Object result;
if (hasLifespan(message)) {
long lifespan = message.getHeader(InfinispanConstants.LIFESPAN_TIME, long.class);
TimeUnit timeUnit = message.getHeader(InfinispanConstants.LIFESPAN_TIME_UNIT, TimeUnit.class);
if (hasMaxIdleTime(message)) {
long maxIdle = message.getHeader(InfinispanConstants.MAX_IDLE_TIME, long.class);
TimeUnit maxIdleTimeUnit = message.getHeader(InfinispanConstants.MAX_IDLE_TIME_UNIT, TimeUnit.class);
result = cache.putIfAbsent(key, value, lifespan, timeUnit, maxIdle, maxIdleTimeUnit);
} else {
result = cache.putIfAbsent(key, value, lifespan, timeUnit);
}
} else {
result = cache.putIfAbsent(key, value);
}
setResult(message, result);
}
@InvokeOnHeader("PUTIFABSENTASYNC")
@InvokeOnHeader(InfinispanConstants.PUT_IF_ABSENT_ASYNC)
void onPutIfAbsentAsync(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object key = message.getHeader(InfinispanConstants.KEY);
final Object value = message.getHeader(InfinispanConstants.VALUE);
final CompletableFuture<Object> result;
if (hasLifespan(message)) {
long lifespan = message.getHeader(InfinispanConstants.LIFESPAN_TIME, long.class);
TimeUnit timeUnit = message.getHeader(InfinispanConstants.LIFESPAN_TIME_UNIT, TimeUnit.class);
if (hasMaxIdleTime(message)) {
long maxIdle = message.getHeader(InfinispanConstants.MAX_IDLE_TIME, long.class);
TimeUnit maxIdleTimeUnit = message.getHeader(InfinispanConstants.MAX_IDLE_TIME_UNIT, TimeUnit.class);
result = cache.putIfAbsentAsync(key, value, lifespan, timeUnit, maxIdle, maxIdleTimeUnit);
} else {
result = cache.putIfAbsentAsync(key, value, lifespan, timeUnit);
}
} else {
result = cache.putIfAbsentAsync(key, value);
}
setResult(message, result);
}
@InvokeOnHeader("GET")
@InvokeOnHeader(InfinispanConstants.GET)
void onGet(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object key = message.getHeader(InfinispanConstants.KEY);
final Object result = cache.get(key);
setResult(message, result);
}
@InvokeOnHeader("CONTAINSKEY")
@InvokeOnHeader(InfinispanConstants.CONTAINS_KEY)
void onContainsKey(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object key = message.getHeader(InfinispanConstants.KEY);
final Object result = cache.containsKey(key);
setResult(message, result);
}
@InvokeOnHeader("CONTAINSVALUE")
@InvokeOnHeader(InfinispanConstants.CONTAINS_VALUE)
void onContainsValue(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object value = message.getHeader(InfinispanConstants.VALUE);
final Object result = cache.containsValue(value);
setResult(message, result);
}
@InvokeOnHeader("REMOVE")
@InvokeOnHeader(InfinispanConstants.REMOVE)
void onRemove(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object key = message.getHeader(InfinispanConstants.KEY);
final Object value = message.getHeader(InfinispanConstants.VALUE);
final Object result;
if (ObjectHelper.isEmpty(value)) {
result = cache.remove(key);
} else {
result = cache.remove(key, value);
}
setResult(message, result);
}
@InvokeOnHeader("REMOVEASYNC")
@InvokeOnHeader(InfinispanConstants.REMOVE_ASYNC)
void onRemoveAsync(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object key = message.getHeader(InfinispanConstants.KEY);
final Object value = message.getHeader(InfinispanConstants.VALUE);
final CompletableFuture<Object> resultRemoveAsyncKey;
final CompletableFuture<Boolean> resultRemoveAsyncKeyValue;
if (ObjectHelper.isEmpty(value)) {
resultRemoveAsyncKey = cache.removeAsync(key);
setResult(message, resultRemoveAsyncKey);
} else {
resultRemoveAsyncKeyValue = cache.removeAsync(key, value);
setResult(message, resultRemoveAsyncKeyValue);
}
}
@InvokeOnHeader("REPLACE")
@InvokeOnHeader(InfinispanConstants.REPLACE)
void onReplace(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object key = message.getHeader(InfinispanConstants.KEY);
final Object value = message.getHeader(InfinispanConstants.VALUE);
final Object oldValue = message.getHeader(InfinispanConstants.OLD_VALUE);
final Object result;
if (hasLifespan(message)) {
long lifespan = message.getHeader(InfinispanConstants.LIFESPAN_TIME, long.class);
TimeUnit timeUnit = message.getHeader(InfinispanConstants.LIFESPAN_TIME_UNIT, TimeUnit.class);
if (hasMaxIdleTime(message)) {
long maxIdle = message.getHeader(InfinispanConstants.MAX_IDLE_TIME, long.class);
TimeUnit maxIdleTimeUnit = message.getHeader(InfinispanConstants.MAX_IDLE_TIME_UNIT, TimeUnit.class);
if (ObjectHelper.isEmpty(oldValue)) {
result = cache.replace(key, value, lifespan, timeUnit, maxIdle, maxIdleTimeUnit);
} else {
result = cache.replace(key, oldValue, value, lifespan, timeUnit, maxIdle, maxIdleTimeUnit);
}
} else {
if (ObjectHelper.isEmpty(oldValue)) {
result = cache.replace(key, value, lifespan, timeUnit);
} else {
result = cache.replace(key, oldValue, value, lifespan, timeUnit);
}
}
} else {
if (ObjectHelper.isEmpty(oldValue)) {
result = cache.replace(key, value);
} else {
result = cache.replace(key, oldValue, value);
}
}
setResult(message, result);
}
@InvokeOnHeader("REPLACEASYNC")
@InvokeOnHeader(InfinispanConstants.REPLACE_ASYNC)
void onReplaceAsync(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object key = message.getHeader(InfinispanConstants.KEY);
final Object value = message.getHeader(InfinispanConstants.VALUE);
final Object oldValue = message.getHeader(InfinispanConstants.OLD_VALUE);
final CompletableFuture<Object> resultWithNewValue;
final CompletableFuture<Boolean> resultWithNewAndOldValue;
if (hasLifespan(message)) {
long lifespan = message.getHeader(InfinispanConstants.LIFESPAN_TIME, long.class);
TimeUnit timeUnit = message.getHeader(InfinispanConstants.LIFESPAN_TIME_UNIT, TimeUnit.class);
if (hasMaxIdleTime(message)) {
long maxIdle = message.getHeader(InfinispanConstants.MAX_IDLE_TIME, long.class);
TimeUnit maxIdleTimeUnit = message.getHeader(InfinispanConstants.MAX_IDLE_TIME_UNIT, TimeUnit.class);
if (ObjectHelper.isEmpty(oldValue)) {
resultWithNewValue = cache.replaceAsync(key, value, lifespan, timeUnit, maxIdle, maxIdleTimeUnit);
setResult(message, resultWithNewValue);
} else {
resultWithNewAndOldValue = cache.replaceAsync(key, oldValue, value, lifespan, timeUnit, maxIdle, maxIdleTimeUnit);
setResult(message, resultWithNewAndOldValue);
}
} else {
if (ObjectHelper.isEmpty(oldValue)) {
resultWithNewValue = cache.replaceAsync(key, value, lifespan, timeUnit);
setResult(message, resultWithNewValue);
} else {
resultWithNewAndOldValue = cache.replaceAsync(key, oldValue, value, lifespan, timeUnit);
setResult(message, resultWithNewAndOldValue);
}
}
} else {
if (ObjectHelper.isEmpty(oldValue)) {
resultWithNewValue = cache.replaceAsync(key, value);
setResult(message, resultWithNewValue);
} else {
resultWithNewAndOldValue = cache.replaceAsync(key, oldValue, value);
setResult(message, resultWithNewAndOldValue);
}
}
}
@InvokeOnHeader("SIZE")
@InvokeOnHeader(InfinispanConstants.SIZE)
void onSize(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object result = cache.size();
setResult(message, result);
}
@InvokeOnHeader("CLEAR")
@InvokeOnHeader(InfinispanConstants.CLEAR)
void onClear(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
cache.clear();
}
@InvokeOnHeader("CLEARASYNC")
@InvokeOnHeader(InfinispanConstants.CLEAR_ASYNC)
void onCLearAsync(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final CompletableFuture<Void> result = cache.clearAsync();
setResult(message, result);
}
@InvokeOnHeader("QUERY")
@InvokeOnHeader(InfinispanConstants.QUERY)
void onQuery(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
if (InfinispanUtil.isRemote(cache)) {
final Query query = InfinispanRemoteOperation.buildQuery(configuration, cache, message);
if (query != null) {
setResult(message, query.list());
}
} else {
throw new UnsupportedOperationException("Query is supported on remote cache only");
}
}
@InvokeOnHeader("STATS")
@InvokeOnHeader(InfinispanConstants.STATS)
void onStats(Message message) {
final BasicCache<Object, Object> cache = manager.getCache(message, this.cacheName);
final Object result = InfinispanUtil.asAdvanced(cache).getStats();
setResult(message, result);
}
// ************************************
// Helpers
// ************************************
private boolean hasLifespan(Message message) {
return !InfinispanUtil.isHeaderEmpty(message, InfinispanConstants.LIFESPAN_TIME)
&& !InfinispanUtil.isHeaderEmpty(message, InfinispanConstants.LIFESPAN_TIME_UNIT);
}
private boolean hasMaxIdleTime(Message message) {
return !InfinispanUtil.isHeaderEmpty(message, InfinispanConstants.MAX_IDLE_TIME)
&& !InfinispanUtil.isHeaderEmpty(message, InfinispanConstants.MAX_IDLE_TIME_UNIT);
}
private void setResult(Message message, Object result) {
String resultHeader = message.getHeader(InfinispanConstants.RESULT_HEADER, configuration::getResultHeader, String.class);
if (resultHeader != null) {
message.setHeader(resultHeader, result);
} else {
message.setBody(result);
}
}
}