/* * Copyright 2015 JBoss Inc * * Licensed 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 io.apiman.gateway.engine.ispn; import io.apiman.gateway.engine.DependsOnComponents; import io.apiman.gateway.engine.async.AsyncResultImpl; import io.apiman.gateway.engine.async.IAsyncHandler; import io.apiman.gateway.engine.async.IAsyncResultHandler; import io.apiman.gateway.engine.components.IBufferFactoryComponent; import io.apiman.gateway.engine.components.ICacheStoreComponent; import io.apiman.gateway.engine.io.IApimanBuffer; import io.apiman.gateway.engine.io.ISignalReadStream; import io.apiman.gateway.engine.io.ISignalWriteStream; import java.io.IOException; import java.util.Collections; import java.util.Map; /** * An infinispan implementation of a cache store. * * @author eric.wittmann@redhat.com */ @DependsOnComponents({ IBufferFactoryComponent.class }) public class InfinispanCacheStoreComponent extends AbstractInfinispanComponent implements ICacheStoreComponent { private static final String DEFAULT_CACHE_CONTAINER = "java:jboss/infinispan/apiman"; //$NON-NLS-1$ private static final String DEFAULT_CACHE = "cachestore"; //$NON-NLS-1$ private Object mutex = new Object(); private IBufferFactoryComponent bufferFactory; /** * Constructor. */ public InfinispanCacheStoreComponent() { this(Collections.EMPTY_MAP); } /** * Constructor. * @param config the config */ public InfinispanCacheStoreComponent(Map<String, String> config) { super(config, DEFAULT_CACHE_CONTAINER, DEFAULT_CACHE); } /** * @see io.apiman.gateway.engine.components.ICacheStoreComponent#put(java.lang.String, java.lang.Object, long) */ @Override public <T> void put(String cacheKey, T jsonObject, long timeToLive) throws IOException { synchronized (mutex) { InfinispanCacheEntry entry = (InfinispanCacheEntry) getCache().get(cacheKey); if (entry == null) { entry = new InfinispanCacheEntry(); } entry.setHead(jsonObject); entry.setExpiresOn(System.currentTimeMillis() + (timeToLive * 1000)); getCache().put(cacheKey, entry); } } /** * @see io.apiman.gateway.engine.components.ICacheStoreComponent#putBinary(java.lang.String, java.lang.Object, long) */ @Override public <T> ISignalWriteStream putBinary(final String cacheKey, final T jsonObject, final long timeToLive) throws IOException { final IApimanBuffer dataBuffer = bufferFactory.createBuffer(0); return new ISignalWriteStream() { private boolean finished = false; private boolean aborted = false; @Override public void abort(Throwable t) { aborted = true; finished = false; } @Override public boolean isFinished() { return finished; } @Override public void write(IApimanBuffer chunk) { dataBuffer.append(chunk); } @Override public void end() { if (!aborted) { synchronized (mutex) { InfinispanCacheEntry entry = (InfinispanCacheEntry) getCache().get(cacheKey); if (entry == null) { entry = new InfinispanCacheEntry(); } entry.setHead(jsonObject); entry.setExpiresOn(System.currentTimeMillis() + (timeToLive * 1000)); entry.setData(dataBuffer.getBytes()); getCache().put(cacheKey, entry); } } } }; } /** * @see io.apiman.gateway.engine.components.ICacheStoreComponent#get(java.lang.String, java.lang.Class, io.apiman.gateway.engine.async.IAsyncResultHandler) */ @SuppressWarnings("unchecked") @Override public <T> void get(String cacheKey, Class<T> type, IAsyncResultHandler<T> handler) { T rval; synchronized (mutex) { InfinispanCacheEntry entry = (InfinispanCacheEntry) getCache().get(cacheKey); if (entry != null) { if (System.currentTimeMillis() >= entry.getExpiresOn()) { getCache().remove(cacheKey); rval = null; } else { rval = (T) entry.getHead(); } } else { rval = null; } } handler.handle(AsyncResultImpl.create(rval)); } /** * @see io.apiman.gateway.engine.components.ICacheStoreComponent#getBinary(java.lang.String, java.lang.Class, io.apiman.gateway.engine.async.IAsyncResultHandler) */ @SuppressWarnings("unchecked") @Override public <T> void getBinary(String cacheKey, Class<T> type, IAsyncResultHandler<ISignalReadStream<T>> handler) { ISignalReadStream<T> rval; synchronized (mutex) { InfinispanCacheEntry entry = (InfinispanCacheEntry) getCache().get(cacheKey); if (entry != null) { if (entry.getExpiresOn() <= System.currentTimeMillis()) { getCache().remove(cacheKey); rval = null; } else { final T head = (T) entry.getHead(); final IApimanBuffer dataBuffer = bufferFactory.createBuffer(entry.getData()); rval = new ISignalReadStream<T>() { boolean finished = false; IAsyncHandler<IApimanBuffer> bodyHandler; IAsyncHandler<Void> endHandler; @Override public void bodyHandler(IAsyncHandler<IApimanBuffer> bodyHandler) { this.bodyHandler = bodyHandler; } @Override public void endHandler(IAsyncHandler<Void> endHandler) { this.endHandler = endHandler; } @Override public T getHead() { return head; } @Override public boolean isFinished() { return finished; } @Override public void abort(Throwable t) { finished = true; } @Override public void transmit() { bodyHandler.handle(dataBuffer); endHandler.handle(null); } }; } } else { rval = null; } } handler.handle(AsyncResultImpl.create(rval)); } /** * @param bufferFactory the bufferFactory to set */ public void setBufferFactory(IBufferFactoryComponent bufferFactory) { this.bufferFactory = bufferFactory; } }