This is an automated email from the ASF dual-hosted git repository.

ffang pushed a commit to branch 3.3.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/3.3.x-fixes by this push:
     new 0bf9f01  [CXF-8570]a test to demonstrate how to configure 
JAXRSClientFactoryBean with org.apache.cxf.feature.Feature to enable Client 
Cache
0bf9f01 is described below

commit 0bf9f01c94cf9a73525f24545473419ac3a03c38
Author: Freeman Fang <[email protected]>
AuthorDate: Thu Jul 29 11:54:16 2021 -0400

    [CXF-8570]a test to demonstrate how to configure JAXRSClientFactoryBean 
with org.apache.cxf.feature.Feature to enable Client Cache
    
    (cherry picked from commit 15619e15e95a42164e146fad11a9fedf0d982a05)
    (cherry picked from commit 2ef7652ea9374c85e12fea7d8beca8d114694f1a)
---
 .../jaxrs/client/cache/CXFCacheControlFeature.java | 163 +++++++++++++++++++++
 .../cxf/jaxrs/client/cache/ClientCacheTest.java    |  38 +++++
 2 files changed, 201 insertions(+)

diff --git 
a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/CXFCacheControlFeature.java
 
b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/CXFCacheControlFeature.java
new file mode 100644
index 0000000..75cd17a
--- /dev/null
+++ 
b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/CXFCacheControlFeature.java
@@ -0,0 +1,163 @@
+/**
+ * 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.cxf.jaxrs.client.cache;
+
+import java.io.Closeable;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.annotation.PreDestroy;
+import javax.cache.Cache;
+import javax.cache.CacheManager;
+import javax.cache.Caching;
+import javax.cache.configuration.Factory;
+import javax.cache.configuration.MutableConfiguration;
+import javax.cache.expiry.ExpiryPolicy;
+import javax.cache.integration.CacheLoader;
+import javax.cache.integration.CacheWriter;
+import javax.cache.spi.CachingProvider;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.feature.AbstractFeature;
+import org.apache.cxf.interceptor.InterceptorProvider;
+
+
+public class CXFCacheControlFeature extends AbstractFeature {
+    
+    private static final String BUS_PROVIDERS = 
"org.apache.cxf.jaxrs.bus.providers";
+    private CachingProvider provider;
+    private CacheManager manager;
+    private Cache<Key, Entry> cache;
+    private boolean cacheResponseInputStream;
+    
+    public CXFCacheControlFeature(boolean cacheStream) {
+        this.cacheResponseInputStream = cacheStream;
+    }
+    
+    public CXFCacheControlFeature() {
+    }
+    
+    protected void initializeProvider(InterceptorProvider interceptorProvider, 
Bus bus) {
+        if (bus != null) {
+            List<Object> providerList = new ArrayList<Object>();
+            providerList.add(this.createCacheControlClientReaderInterceptor());
+            providerList.add(this.createCacheControlClientRequestFilter());
+            bus.setProperty(BUS_PROVIDERS, providerList);
+        }
+    }
+
+    
+    public CacheControlClientRequestFilter 
createCacheControlClientRequestFilter() {
+        if (cache == null) {
+            cache = createCache(new HashMap<String, Object>());
+        }
+        return new CacheControlClientRequestFilter(cache);
+    }
+    
+    public CacheControlClientReaderInterceptor 
createCacheControlClientReaderInterceptor() {
+        if (cache == null) {
+            cache = createCache(new HashMap<String, Object>());
+        }
+        CacheControlClientReaderInterceptor reader = new 
CacheControlClientReaderInterceptor(cache);
+        reader.setCacheResponseInputStream(cacheResponseInputStream);
+        return reader;
+    }
+
+    @PreDestroy // TODO: check it is called
+    public void close() {
+        for (final Closeable c : Arrays.asList(cache, manager, provider)) {
+            try {
+                if (c != null) {
+                    c.close();
+                }
+            } catch (final Exception e) {
+                // no-op
+            }
+        }
+        
+    }
+    
+    private Cache<Key, Entry> createCache(final Map<String, Object> 
properties) {
+        final Properties props = new Properties();
+        props.putAll(properties);
+
+        final String prefix = this.getClass().getName() + ".";
+        final String uri = props.getProperty(prefix + "config-uri");
+        final String name = props.getProperty(prefix + "name", 
this.getClass().getName());
+
+        final ClassLoader contextClassLoader = 
Thread.currentThread().getContextClassLoader();
+
+        provider = Caching.getCachingProvider();
+        try {
+            manager = provider.getCacheManager(
+                    uri == null ? provider.getDefaultURI() : new URI(uri),
+                    contextClassLoader,
+                    props);
+
+            final MutableConfiguration<Key, Entry> configuration = new 
MutableConfiguration<Key, Entry>()
+                
.setReadThrough("true".equalsIgnoreCase(props.getProperty(prefix + 
"readThrough", "false")))
+                
.setWriteThrough("true".equalsIgnoreCase(props.getProperty(prefix + 
"writeThrough", "false")))
+                .setManagementEnabled(
+                    "true".equalsIgnoreCase(props.getProperty(prefix + 
"managementEnabled", "false")))
+                .setStatisticsEnabled(
+                    "true".equalsIgnoreCase(props.getProperty(prefix + 
"statisticsEnabled", "false")))
+                
.setStoreByValue("true".equalsIgnoreCase(props.getProperty(prefix + 
"storeByValue", "false")));
+
+            final String loader = props.getProperty(prefix + "loaderFactory");
+            if (loader != null) {
+                @SuppressWarnings("unchecked")
+                Factory<? extends CacheLoader<Key, Entry>> f = 
newInstance(contextClassLoader, loader, Factory.class);
+                configuration.setCacheLoaderFactory(f);
+            }
+            final String writer = props.getProperty(prefix + "writerFactory");
+            if (writer != null) {
+                @SuppressWarnings("unchecked")
+                Factory<? extends CacheWriter<Key, Entry>> f = 
newInstance(contextClassLoader, writer, Factory.class);
+                configuration.setCacheWriterFactory(f);
+            }
+            final String expiry = props.getProperty(prefix + "expiryFactory");
+            if (expiry != null) {
+                @SuppressWarnings("unchecked")
+                Factory<? extends ExpiryPolicy> f = 
newInstance(contextClassLoader, expiry, Factory.class);
+                configuration.setExpiryPolicyFactory(f);
+            }
+
+            cache = manager.createCache(name, configuration);
+            return cache;
+        } catch (final URISyntaxException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> T newInstance(final ClassLoader contextClassLoader, 
final String clazz, final Class<T> cast) {
+        try {
+            return (T) contextClassLoader.loadClass(clazz).newInstance();
+        } catch (final Exception e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+}
diff --git 
a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/ClientCacheTest.java
 
b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/ClientCacheTest.java
index 6fe9f71..f784f5d 100644
--- 
a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/ClientCacheTest.java
+++ 
b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/cache/ClientCacheTest.java
@@ -21,6 +21,7 @@ package org.apache.cxf.jaxrs.client.cache;
 
 import java.io.InputStream;
 import java.io.Serializable;
+import java.util.Collections;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
@@ -33,9 +34,12 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.xml.bind.annotation.XmlRootElement;
 
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
 import org.apache.cxf.endpoint.Server;
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
 import org.apache.cxf.transport.local.LocalConduit;
@@ -141,6 +145,23 @@ public class ClientCacheTest {
             feature.close();
         }
     }
+    
+    @Test
+    public void 
testGetTimeStringAsStringAndInputStreamWithJAXRSClientFactoryBean() throws 
Exception {
+        CXFCacheControlFeature feature = new CXFCacheControlFeature(true);
+        try {
+            WebClient client = createClient(feature);
+            final Response r = client.get();
+            assertEquals(Response.Status.OK.getStatusCode(), r.getStatus());
+            final String r1 = r.readEntity(String.class);
+            waitABit();
+            InputStream is = client.get(InputStream.class);
+            final String r2 = IOUtils.readStringFromStream(is);
+            assertEquals(r1, r2);
+        } finally {
+            feature.close();
+        }
+    }
 
     @Test
     public void testGetJaxbBookCache() {
@@ -249,5 +270,22 @@ public class ClientCacheTest {
             return false;
         }
     }
+    
+    private WebClient createClient(CXFCacheControlFeature feature) {
+        Bus bus = BusFactory.newInstance().createBus();
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setBus(bus);
+        sf.setResourceClasses(TheServer.class);
+        sf.setResourceProvider(TheServer.class, new 
SingletonResourceProvider(new TheServer(), false));
+        sf.setTransportId(LocalTransportFactory.TRANSPORT_ID);
+        sf.setAddress(ADDRESS);
+        sf.create();
+        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+        bean.setBus(bus);
+        bean.setAddress(ADDRESS);
+        bean.setFeatures(Collections.singletonList(feature));
+        bean.setTransportId(LocalTransportFactory.TRANSPORT_ID);
+        return 
bean.createWebClient().accept("text/plain").header(HttpHeaders.CACHE_CONTROL, 
"public");
+    }
 
 }
\ No newline at end of file

Reply via email to