001package org.apache.commons.jcs3.auxiliary.remote.http.client;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.IOException;
023import java.io.Serializable;
024import java.util.Collections;
025import java.util.Map;
026import java.util.Set;
027
028import org.apache.commons.jcs3.auxiliary.remote.behavior.IRemoteCacheDispatcher;
029import org.apache.commons.jcs3.auxiliary.remote.http.client.behavior.IRemoteHttpCacheClient;
030import org.apache.commons.jcs3.auxiliary.remote.util.RemoteCacheRequestFactory;
031import org.apache.commons.jcs3.auxiliary.remote.value.RemoteCacheRequest;
032import org.apache.commons.jcs3.auxiliary.remote.value.RemoteCacheResponse;
033import org.apache.commons.jcs3.engine.behavior.ICacheElement;
034import org.apache.commons.jcs3.log.Log;
035import org.apache.commons.jcs3.log.LogManager;
036
037/** This is the service used by the remote http auxiliary cache. */
038public class RemoteHttpCacheClient<K, V>
039    implements IRemoteHttpCacheClient<K, V>
040{
041    /** The Logger. */
042    private static final Log log = LogManager.getLog( RemoteHttpCacheClient.class );
043
044    /** The internal client. */
045    private IRemoteCacheDispatcher remoteDispatcher;
046
047    /** The remote attributes */
048    private RemoteHttpCacheAttributes remoteHttpCacheAttributes;
049
050    /** Set to true when initialize is called */
051    private boolean initialized;
052
053    /** For factory construction. */
054    public RemoteHttpCacheClient()
055    {
056        // does nothing
057    }
058
059    /**
060     * Constructs a client.
061     * <p>
062     * @param attributes
063     */
064    public RemoteHttpCacheClient( final RemoteHttpCacheAttributes attributes )
065    {
066        setRemoteHttpCacheAttributes( attributes );
067        initialize( attributes );
068    }
069
070    /**
071     * The provides an extension point. If you want to extend this and use a special dispatcher,
072     * here is the place to do it.
073     * <p>
074     * @param attributes
075     */
076    @Override
077    public void initialize( final RemoteHttpCacheAttributes attributes )
078    {
079        setRemoteDispatcher( new RemoteHttpCacheDispatcher( attributes ) );
080
081        log.info( "Created remote Dispatcher. {0}", this::getRemoteDispatcher);
082        setInitialized( true );
083    }
084
085    /**
086     * Create a request, process, extract the payload.
087     * <p>
088     * @param cacheName
089     * @param key
090     * @return ICacheElement
091     * @throws IOException
092     */
093    @Override
094    public ICacheElement<K, V> get( final String cacheName, final K key )
095        throws IOException
096    {
097        return get( cacheName, key, 0 );
098    }
099
100    /**
101     * Create a request, process, extract the payload.
102     * <p>
103     * @param cacheName
104     * @param key
105     * @param requesterId
106     * @return ICacheElement
107     * @throws IOException
108     */
109    @Override
110    public ICacheElement<K, V> get( final String cacheName, final K key, final long requesterId )
111        throws IOException
112    {
113        if ( !isInitialized() )
114        {
115            final String message = "The Remote Http Client is not initialized. Cannot process request.";
116            log.warn( message );
117            throw new IOException( message );
118        }
119        final RemoteCacheRequest<K, Serializable> remoteHttpCacheRequest =
120            RemoteCacheRequestFactory.createGetRequest( cacheName, key, requesterId );
121
122        final RemoteCacheResponse<ICacheElement<K, V>> remoteHttpCacheResponse =
123            getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
124
125        log.debug( "Get [{0}] = {1}", key, remoteHttpCacheResponse );
126
127        if ( remoteHttpCacheResponse != null)
128        {
129            return remoteHttpCacheResponse.getPayload();
130        }
131
132        return null;
133    }
134
135    /**
136     * Gets multiple items from the cache matching the pattern.
137     * <p>
138     * @param cacheName
139     * @param pattern
140     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
141     *         data in cache matching the pattern.
142     * @throws IOException
143     */
144    @Override
145    public Map<K, ICacheElement<K, V>> getMatching( final String cacheName, final String pattern )
146        throws IOException
147    {
148        return getMatching( cacheName, pattern, 0 );
149    }
150
151    /**
152     * Gets multiple items from the cache matching the pattern.
153     * <p>
154     * @param cacheName
155     * @param pattern
156     * @param requesterId
157     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
158     *         data in cache matching the pattern.
159     * @throws IOException
160     */
161    @Override
162    public Map<K, ICacheElement<K, V>> getMatching( final String cacheName, final String pattern, final long requesterId )
163        throws IOException
164    {
165        if ( !isInitialized() )
166        {
167            final String message = "The Remote Http Client is not initialized. Cannot process request.";
168            log.warn( message );
169            throw new IOException( message );
170        }
171
172        final RemoteCacheRequest<K, V> remoteHttpCacheRequest =
173            RemoteCacheRequestFactory.createGetMatchingRequest( cacheName, pattern, requesterId );
174
175        final RemoteCacheResponse<Map<K, ICacheElement<K, V>>> remoteHttpCacheResponse =
176            getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
177
178        log.debug( "GetMatching [{0}] = {1}", pattern, remoteHttpCacheResponse );
179
180        return remoteHttpCacheResponse.getPayload();
181    }
182
183    /**
184     * Gets multiple items from the cache based on the given set of keys.
185     * <p>
186     * @param cacheName
187     * @param keys
188     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
189     *         data in cache for any of these keys
190     * @throws IOException
191     */
192    @Override
193    public Map<K, ICacheElement<K, V>> getMultiple( final String cacheName, final Set<K> keys )
194        throws IOException
195    {
196        return getMultiple( cacheName, keys, 0 );
197    }
198
199    /**
200     * Gets multiple items from the cache based on the given set of keys.
201     * <p>
202     * @param cacheName
203     * @param keys
204     * @param requesterId
205     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
206     *         data in cache for any of these keys
207     * @throws IOException
208     */
209    @Override
210    public Map<K, ICacheElement<K, V>> getMultiple( final String cacheName, final Set<K> keys, final long requesterId )
211        throws IOException
212    {
213        if ( !isInitialized() )
214        {
215            final String message = "The Remote Http Client is not initialized.  Cannot process request.";
216            log.warn( message );
217            throw new IOException( message );
218        }
219
220        final RemoteCacheRequest<K, V> remoteHttpCacheRequest =
221            RemoteCacheRequestFactory.createGetMultipleRequest( cacheName, keys, requesterId );
222
223        final RemoteCacheResponse<Map<K, ICacheElement<K, V>>> remoteHttpCacheResponse =
224            getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
225
226        log.debug( "GetMultiple [{0}] = {1}", keys, remoteHttpCacheResponse );
227
228        return remoteHttpCacheResponse.getPayload();
229    }
230
231    /**
232     * Removes the given key from the specified cache.
233     * <p>
234     * @param cacheName
235     * @param key
236     * @throws IOException
237     */
238    @Override
239    public void remove( final String cacheName, final K key )
240        throws IOException
241    {
242        remove( cacheName, key, 0 );
243    }
244
245    /**
246     * Removes the given key from the specified cache.
247     * <p>
248     * @param cacheName
249     * @param key
250     * @param requesterId
251     * @throws IOException
252     */
253    @Override
254    public void remove( final String cacheName, final K key, final long requesterId )
255        throws IOException
256    {
257        if ( !isInitialized() )
258        {
259            final String message = "The Remote Http Client is not initialized.  Cannot process request.";
260            log.warn( message );
261            throw new IOException( message );
262        }
263
264        final RemoteCacheRequest<K, V> remoteHttpCacheRequest =
265            RemoteCacheRequestFactory.createRemoveRequest( cacheName, key, requesterId );
266
267        getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
268    }
269
270    /**
271     * Remove all keys from the specified cache.
272     * <p>
273     * @param cacheName
274     * @throws IOException
275     */
276    @Override
277    public void removeAll( final String cacheName )
278        throws IOException
279    {
280        removeAll( cacheName, 0 );
281    }
282
283    /**
284     * Remove all keys from the specified cache.
285     * <p>
286     * @param cacheName
287     * @param requesterId
288     * @throws IOException
289     */
290    @Override
291    public void removeAll( final String cacheName, final long requesterId )
292        throws IOException
293    {
294        if ( !isInitialized() )
295        {
296            final String message = "The Remote Http Client is not initialized.  Cannot process request.";
297            log.warn( message );
298            throw new IOException( message );
299        }
300
301        final RemoteCacheRequest<K, V> remoteHttpCacheRequest =
302            RemoteCacheRequestFactory.createRemoveAllRequest( cacheName, requesterId );
303
304        getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
305    }
306
307    /**
308     * Puts a cache item to the cache.
309     * <p>
310     * @param item
311     * @throws IOException
312     */
313    @Override
314    public void update( final ICacheElement<K, V> item )
315        throws IOException
316    {
317        update( item, 0 );
318    }
319
320    /**
321     * Puts a cache item to the cache.
322     * <p>
323     * @param cacheElement
324     * @param requesterId
325     * @throws IOException
326     */
327    @Override
328    public void update( final ICacheElement<K, V> cacheElement, final long requesterId )
329        throws IOException
330    {
331        if ( !isInitialized() )
332        {
333            final String message = "The Remote Http Client is not initialized.  Cannot process request.";
334            log.warn( message );
335            throw new IOException( message );
336        }
337
338        final RemoteCacheRequest<K, V> remoteHttpCacheRequest =
339            RemoteCacheRequestFactory.createUpdateRequest( cacheElement, requesterId );
340
341        getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
342    }
343
344    /**
345     * Frees the specified cache.
346     * <p>
347     * @param cacheName
348     * @throws IOException
349     */
350    @Override
351    public void dispose( final String cacheName )
352        throws IOException
353    {
354        if ( !isInitialized() )
355        {
356            final String message = "The Remote Http Client is not initialized.  Cannot process request.";
357            log.warn( message );
358            throw new IOException( message );
359        }
360
361        final RemoteCacheRequest<K, V> remoteHttpCacheRequest =
362            RemoteCacheRequestFactory.createDisposeRequest( cacheName, 0 );
363
364        getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
365    }
366
367    /**
368     * Frees the specified cache.
369     * <p>
370     * @throws IOException
371     */
372    @Override
373    public void release()
374        throws IOException
375    {
376        // noop
377    }
378
379    /**
380     * Return the keys in this cache.
381     * <p>
382     * @param cacheName the name of the cache
383     * @see org.apache.commons.jcs3.auxiliary.AuxiliaryCache#getKeySet()
384     */
385    @Override
386    public Set<K> getKeySet( final String cacheName ) throws IOException
387    {
388        if ( !isInitialized() )
389        {
390            final String message = "The Remote Http Client is not initialized.  Cannot process request.";
391            log.warn( message );
392            throw new IOException( message );
393        }
394
395        final RemoteCacheRequest<String, String> remoteHttpCacheRequest =
396            RemoteCacheRequestFactory.createGetKeySetRequest(cacheName, 0 );
397
398        final RemoteCacheResponse<Set<K>> remoteHttpCacheResponse = getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
399
400        if ( remoteHttpCacheResponse != null && remoteHttpCacheResponse.getPayload() != null )
401        {
402            return remoteHttpCacheResponse.getPayload();
403        }
404
405        return Collections.emptySet();
406    }
407
408    /**
409     * Make and alive request.
410     * <p>
411     * @return true if we make a successful alive request.
412     * @throws IOException
413     */
414    @Override
415    public boolean isAlive()
416        throws IOException
417    {
418        if ( !isInitialized() )
419        {
420            final String message = "The Remote Http Client is not initialized.  Cannot process request.";
421            log.warn( message );
422            throw new IOException( message );
423        }
424
425        final RemoteCacheRequest<K, V> remoteHttpCacheRequest = RemoteCacheRequestFactory.createAliveCheckRequest( 0 );
426        final RemoteCacheResponse<String> remoteHttpCacheResponse =
427            getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
428
429        if ( remoteHttpCacheResponse != null )
430        {
431            return remoteHttpCacheResponse.isSuccess();
432        }
433
434        return false;
435    }
436
437    /**
438     * @param remoteDispatcher the remoteDispatcher to set
439     */
440    public void setRemoteDispatcher( final IRemoteCacheDispatcher remoteDispatcher )
441    {
442        this.remoteDispatcher = remoteDispatcher;
443    }
444
445    /**
446     * @return the remoteDispatcher
447     */
448    public IRemoteCacheDispatcher getRemoteDispatcher()
449    {
450        return remoteDispatcher;
451    }
452
453    /**
454     * @param remoteHttpCacheAttributes the remoteHttpCacheAttributes to set
455     */
456    public void setRemoteHttpCacheAttributes( final RemoteHttpCacheAttributes remoteHttpCacheAttributes )
457    {
458        this.remoteHttpCacheAttributes = remoteHttpCacheAttributes;
459    }
460
461    /**
462     * @return the remoteHttpCacheAttributes
463     */
464    public RemoteHttpCacheAttributes getRemoteHttpCacheAttributes()
465    {
466        return remoteHttpCacheAttributes;
467    }
468
469    /**
470     * @param initialized the initialized to set
471     */
472    protected void setInitialized( final boolean initialized )
473    {
474        this.initialized = initialized;
475    }
476
477    /**
478     * @return the initialized
479     */
480    protected boolean isInitialized()
481    {
482        return initialized;
483    }
484}