001package org.apache.commons.jcs.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 org.apache.commons.jcs.auxiliary.remote.behavior.IRemoteCacheDispatcher;
023import org.apache.commons.jcs.auxiliary.remote.http.client.behavior.IRemoteHttpCacheClient;
024import org.apache.commons.jcs.auxiliary.remote.util.RemoteCacheRequestFactory;
025import org.apache.commons.jcs.auxiliary.remote.value.RemoteCacheRequest;
026import org.apache.commons.jcs.auxiliary.remote.value.RemoteCacheResponse;
027import org.apache.commons.jcs.engine.behavior.ICacheElement;
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030
031import java.io.IOException;
032import java.io.Serializable;
033import java.util.Collections;
034import java.util.Map;
035import java.util.Set;
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 = LogFactory.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 = false;
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( 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( RemoteHttpCacheAttributes attributes )
078    {
079        setRemoteDispatcher( new RemoteHttpCacheDispatcher( attributes ) );
080
081        if ( log.isInfoEnabled() )
082        {
083            log.info( "Created remote Dispatcher." + getRemoteDispatcher() );
084        }
085        setInitialized( true );
086    }
087
088    /**
089     * Create a request, process, extract the payload.
090     * <p>
091     * @param cacheName
092     * @param key
093     * @return ICacheElement
094     * @throws IOException
095     */
096    @Override
097    public ICacheElement<K, V> get( String cacheName, K key )
098        throws IOException
099    {
100        return get( cacheName, key, 0 );
101    }
102
103    /**
104     * Create a request, process, extract the payload.
105     * <p>
106     * @param cacheName
107     * @param key
108     * @param requesterId
109     * @return ICacheElement
110     * @throws IOException
111     */
112    @Override
113    public ICacheElement<K, V> get( String cacheName, K key, long requesterId )
114        throws IOException
115    {
116        if ( !isInitialized() )
117        {
118            String message = "The Remote Http Client is not initialized.  Cannot process request.";
119            log.warn( message );
120            throw new IOException( message );
121        }
122        RemoteCacheRequest<K, Serializable> remoteHttpCacheRequest =
123            RemoteCacheRequestFactory.createGetRequest( cacheName, key, requesterId );
124
125        RemoteCacheResponse<ICacheElement<K, V>> remoteHttpCacheResponse =
126            getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
127
128        if ( log.isDebugEnabled() )
129        {
130            log.debug( "Get [" + key + "] = " + remoteHttpCacheResponse );
131        }
132
133        if ( remoteHttpCacheResponse != null)
134        {
135            return remoteHttpCacheResponse.getPayload();
136        }
137
138        return null;
139    }
140
141    /**
142     * Gets multiple items from the cache matching the pattern.
143     * <p>
144     * @param cacheName
145     * @param pattern
146     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
147     *         data in cache matching the pattern.
148     * @throws IOException
149     */
150    @Override
151    public Map<K, ICacheElement<K, V>> getMatching( String cacheName, String pattern )
152        throws IOException
153    {
154        return getMatching( cacheName, pattern, 0 );
155    }
156
157    /**
158     * Gets multiple items from the cache matching the pattern.
159     * <p>
160     * @param cacheName
161     * @param pattern
162     * @param requesterId
163     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
164     *         data in cache matching the pattern.
165     * @throws IOException
166     */
167    @Override
168    public Map<K, ICacheElement<K, V>> getMatching( String cacheName, String pattern, long requesterId )
169        throws IOException
170    {
171        if ( !isInitialized() )
172        {
173            String message = "The Remote Http Client is not initialized.  Cannot process request.";
174            log.warn( message );
175            throw new IOException( message );
176        }
177
178        RemoteCacheRequest<K, V> remoteHttpCacheRequest =
179            RemoteCacheRequestFactory.createGetMatchingRequest( cacheName, pattern, requesterId );
180
181        RemoteCacheResponse<Map<K, ICacheElement<K, V>>> remoteHttpCacheResponse =
182            getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
183
184        if ( log.isDebugEnabled() )
185        {
186            log.debug( "GetMatching [" + pattern + "] = " + remoteHttpCacheResponse );
187        }
188
189        return remoteHttpCacheResponse.getPayload();
190    }
191
192    /**
193     * Gets multiple items from the cache based on the given set of keys.
194     * <p>
195     * @param cacheName
196     * @param keys
197     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
198     *         data in cache for any of these keys
199     * @throws IOException
200     */
201    @Override
202    public Map<K, ICacheElement<K, V>> getMultiple( String cacheName, Set<K> keys )
203        throws IOException
204    {
205        return getMultiple( cacheName, keys, 0 );
206    }
207
208    /**
209     * Gets multiple items from the cache based on the given set of keys.
210     * <p>
211     * @param cacheName
212     * @param keys
213     * @param requesterId
214     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
215     *         data in cache for any of these keys
216     * @throws IOException
217     */
218    @Override
219    public Map<K, ICacheElement<K, V>> getMultiple( String cacheName, Set<K> keys, long requesterId )
220        throws IOException
221    {
222        if ( !isInitialized() )
223        {
224            String message = "The Remote Http Client is not initialized.  Cannot process request.";
225            log.warn( message );
226            throw new IOException( message );
227        }
228
229        RemoteCacheRequest<K, V> remoteHttpCacheRequest =
230            RemoteCacheRequestFactory.createGetMultipleRequest( cacheName, keys, requesterId );
231
232        RemoteCacheResponse<Map<K, ICacheElement<K, V>>> remoteHttpCacheResponse =
233            getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
234
235        if ( log.isDebugEnabled() )
236        {
237            log.debug( "GetMultiple [" + keys + "] = " + remoteHttpCacheResponse );
238        }
239
240        return remoteHttpCacheResponse.getPayload();
241    }
242
243    /**
244     * Removes the given key from the specified cache.
245     * <p>
246     * @param cacheName
247     * @param key
248     * @throws IOException
249     */
250    @Override
251    public void remove( String cacheName, K key )
252        throws IOException
253    {
254        remove( cacheName, key, 0 );
255    }
256
257    /**
258     * Removes the given key from the specified cache.
259     * <p>
260     * @param cacheName
261     * @param key
262     * @param requesterId
263     * @throws IOException
264     */
265    @Override
266    public void remove( String cacheName, K key, long requesterId )
267        throws IOException
268    {
269        if ( !isInitialized() )
270        {
271            String message = "The Remote Http Client is not initialized.  Cannot process request.";
272            log.warn( message );
273            throw new IOException( message );
274        }
275
276        RemoteCacheRequest<K, V> remoteHttpCacheRequest =
277            RemoteCacheRequestFactory.createRemoveRequest( cacheName, key, requesterId );
278
279        getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
280    }
281
282    /**
283     * Remove all keys from the specified cache.
284     * <p>
285     * @param cacheName
286     * @throws IOException
287     */
288    @Override
289    public void removeAll( String cacheName )
290        throws IOException
291    {
292        removeAll( cacheName, 0 );
293    }
294
295    /**
296     * Remove all keys from the sepcified cache.
297     * <p>
298     * @param cacheName
299     * @param requesterId
300     * @throws IOException
301     */
302    @Override
303    public void removeAll( String cacheName, long requesterId )
304        throws IOException
305    {
306        if ( !isInitialized() )
307        {
308            String message = "The Remote Http Client is not initialized.  Cannot process request.";
309            log.warn( message );
310            throw new IOException( message );
311        }
312
313        RemoteCacheRequest<K, V> remoteHttpCacheRequest =
314            RemoteCacheRequestFactory.createRemoveAllRequest( cacheName, requesterId );
315
316        getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
317    }
318
319    /**
320     * Puts a cache item to the cache.
321     * <p>
322     * @param item
323     * @throws IOException
324     */
325    @Override
326    public void update( ICacheElement<K, V> item )
327        throws IOException
328    {
329        update( item, 0 );
330    }
331
332    /**
333     * Puts a cache item to the cache.
334     * <p>
335     * @param cacheElement
336     * @param requesterId
337     * @throws IOException
338     */
339    @Override
340    public void update( ICacheElement<K, V> cacheElement, long requesterId )
341        throws IOException
342    {
343        if ( !isInitialized() )
344        {
345            String message = "The Remote Http Client is not initialized.  Cannot process request.";
346            log.warn( message );
347            throw new IOException( message );
348        }
349
350        RemoteCacheRequest<K, V> remoteHttpCacheRequest =
351            RemoteCacheRequestFactory.createUpdateRequest( cacheElement, requesterId );
352
353        getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
354    }
355
356    /**
357     * Frees the specified cache.
358     * <p>
359     * @param cacheName
360     * @throws IOException
361     */
362    @Override
363    public void dispose( String cacheName )
364        throws IOException
365    {
366        if ( !isInitialized() )
367        {
368            String message = "The Remote Http Client is not initialized.  Cannot process request.";
369            log.warn( message );
370            throw new IOException( message );
371        }
372
373        RemoteCacheRequest<K, V> remoteHttpCacheRequest =
374            RemoteCacheRequestFactory.createDisposeRequest( cacheName, 0 );
375
376        getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
377    }
378
379    /**
380     * Frees the specified cache.
381     * <p>
382     * @throws IOException
383     */
384    @Override
385    public void release()
386        throws IOException
387    {
388        // noop
389    }
390
391    /**
392     * Return the keys in this cache.
393     * <p>
394     * @param cacheName the name of the cache
395     * @see org.apache.commons.jcs.auxiliary.AuxiliaryCache#getKeySet()
396     */
397    @Override
398    public Set<K> getKeySet( String cacheName ) throws IOException
399    {
400        if ( !isInitialized() )
401        {
402            String message = "The Remote Http Client is not initialized.  Cannot process request.";
403            log.warn( message );
404            throw new IOException( message );
405        }
406
407        RemoteCacheRequest<String, String> remoteHttpCacheRequest =
408            RemoteCacheRequestFactory.createGetKeySetRequest(cacheName, 0 );
409
410        RemoteCacheResponse<Set<K>> remoteHttpCacheResponse = getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
411
412        if ( remoteHttpCacheResponse != null && remoteHttpCacheResponse.getPayload() != null )
413        {
414            return remoteHttpCacheResponse.getPayload();
415        }
416
417        return Collections.emptySet();
418    }
419
420    /**
421     * Make and alive request.
422     * <p>
423     * @return true if we make a successful alive request.
424     * @throws IOException
425     */
426    @Override
427    public boolean isAlive()
428        throws IOException
429    {
430        if ( !isInitialized() )
431        {
432            String message = "The Remote Http Client is not initialized.  Cannot process request.";
433            log.warn( message );
434            throw new IOException( message );
435        }
436
437        RemoteCacheRequest<K, V> remoteHttpCacheRequest = RemoteCacheRequestFactory.createAliveCheckRequest( 0 );
438        RemoteCacheResponse<String> remoteHttpCacheResponse =
439            getRemoteDispatcher().dispatchRequest( remoteHttpCacheRequest );
440
441        if ( remoteHttpCacheResponse != null )
442        {
443            return remoteHttpCacheResponse.isSuccess();
444        }
445
446        return false;
447    }
448
449    /**
450     * @param remoteDispatcher the remoteDispatcher to set
451     */
452    public void setRemoteDispatcher( IRemoteCacheDispatcher remoteDispatcher )
453    {
454        this.remoteDispatcher = remoteDispatcher;
455    }
456
457    /**
458     * @return the remoteDispatcher
459     */
460    public IRemoteCacheDispatcher getRemoteDispatcher()
461    {
462        return remoteDispatcher;
463    }
464
465    /**
466     * @param remoteHttpCacheAttributes the remoteHttpCacheAttributes to set
467     */
468    public void setRemoteHttpCacheAttributes( RemoteHttpCacheAttributes remoteHttpCacheAttributes )
469    {
470        this.remoteHttpCacheAttributes = remoteHttpCacheAttributes;
471    }
472
473    /**
474     * @return the remoteHttpCacheAttributes
475     */
476    public RemoteHttpCacheAttributes getRemoteHttpCacheAttributes()
477    {
478        return remoteHttpCacheAttributes;
479    }
480
481    /**
482     * @param initialized the initialized to set
483     */
484    protected void setInitialized( boolean initialized )
485    {
486        this.initialized = initialized;
487    }
488
489    /**
490     * @return the initialized
491     */
492    protected boolean isInitialized()
493    {
494        return initialized;
495    }
496}