You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2014/10/07 13:47:00 UTC

git commit: [CXF-6015] Optionally URL encoding all or specific client parameter characters

Repository: cxf
Updated Branches:
  refs/heads/2.7.x-fixes 0a1f41447 -> 4c509a532


[CXF-6015] Optionally URL encoding all or specific client parameter characters


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/4c509a53
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/4c509a53
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/4c509a53

Branch: refs/heads/2.7.x-fixes
Commit: 4c509a53208f69dd81c0c25990277a2e65be68f4
Parents: 0a1f414
Author: Sergey Beryozkin <sb...@talend.com>
Authored: Wed Sep 24 14:53:04 2014 +0100
Committer: Sergey Beryozkin <sb...@talend.com>
Committed: Tue Oct 7 12:46:34 2014 +0100

----------------------------------------------------------------------
 .../org/apache/cxf/common/util/UrlUtils.java    | 17 +++++
 .../jaxrs/client/JAXRSClientFactoryBean.java    | 29 +++++++-
 .../jaxrs/client/UrlEncodingParamConverter.java | 70 ++++++++++++++++++++
 .../org/apache/cxf/jaxrs/utils/HttpUtils.java   |  9 +--
 .../jaxrs/client/UrlEncodingParamConverter.java | 70 ++++++++++++++++++++
 .../org/apache/cxf/systest/jaxrs/BookStore.java | 15 +++++
 .../jaxrs/JAXRSClientServerBookTest.java        | 42 +++++++++++-
 7 files changed, 240 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/4c509a53/api/src/main/java/org/apache/cxf/common/util/UrlUtils.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/cxf/common/util/UrlUtils.java b/api/src/main/java/org/apache/cxf/common/util/UrlUtils.java
index 1e16677..e33fe8f 100644
--- a/api/src/main/java/org/apache/cxf/common/util/UrlUtils.java
+++ b/api/src/main/java/org/apache/cxf/common/util/UrlUtils.java
@@ -21,6 +21,7 @@ package org.apache.cxf.common.util;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
+import java.net.URLEncoder;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.StringTokenizer;
@@ -43,6 +44,22 @@ public final class UrlUtils {
         
     }
 
+    public static String urlEncode(String value) {
+        
+        return urlEncode(value, "UTF-8");
+    }
+    
+    public static String urlEncode(String value, String enc) {
+        
+        try {
+            value = URLEncoder.encode(value, enc);
+        } catch (UnsupportedEncodingException ex) {
+            throw new RuntimeException(ex);
+        }
+        
+        return value;
+    }
+    
     /**
      * Decodes using URLDecoder - use when queries or form post values are decoded
      * @param value value to decode

http://git-wip-us.apache.org/repos/asf/cxf/blob/4c509a53/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
----------------------------------------------------------------------
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
index 70f51c5..c6b8e14 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
@@ -18,14 +18,19 @@
  */
 package org.apache.cxf.jaxrs.client;
 
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
 import java.net.URI;
 import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
 
 import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.ParamConverter;
+import javax.ws.rs.ext.ParamConverterProvider;
 
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.PropertyUtils;
 import org.apache.cxf.common.util.ProxyHelper;
 import org.apache.cxf.configuration.security.AuthorizationPolicy;
 import org.apache.cxf.endpoint.ClientLifeCycleManager;
@@ -38,6 +43,7 @@ import org.apache.cxf.jaxrs.JAXRSServiceFactoryBean;
 import org.apache.cxf.jaxrs.JAXRSServiceImpl;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.provider.ProviderFactory;
 import org.apache.cxf.service.Service;
 import org.apache.cxf.service.factory.FactoryBeanListener;
 
@@ -365,7 +371,28 @@ public class JAXRSClientFactoryBean extends AbstractJAXRSFactoryBean {
             client.headers(headers);
         }
         
-        setupFactory(ep);
+        ProviderFactory factory = setupFactory(ep);
+
+        final Map<String, Object> theProperties = super.getProperties();
+        final boolean encodeClientParameters = PropertyUtils.isTrue(theProperties, "url.encode.client.parameters");
+        if (encodeClientParameters) {
+            final String encodeClientParametersList = theProperties == null ? null 
+                : (String)getProperties().get("url.encode.client.parameters.list");
+            factory.registerUserProvider(new ParamConverterProvider() {
+
+                @SuppressWarnings("unchecked")
+                @Override
+                public <T> ParamConverter<T> getConverter(Class<T> cls,
+                    Type t, Annotation[] anns) {
+                    if (cls == String.class) {
+                        return (ParamConverter<T>)new UrlEncodingParamConverter(encodeClientParametersList);
+                    } else {
+                        return null;
+                    }
+                }
+            
+            });
+        }
     }
     
     protected void applyFeatures(AbstractClient client) {

http://git-wip-us.apache.org/repos/asf/cxf/blob/4c509a53/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/UrlEncodingParamConverter.java
----------------------------------------------------------------------
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/UrlEncodingParamConverter.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/UrlEncodingParamConverter.java
new file mode 100644
index 0000000..5b5bbd5
--- /dev/null
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/UrlEncodingParamConverter.java
@@ -0,0 +1,70 @@
+/**
+ * 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;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ext.ParamConverter;
+
+import org.apache.cxf.jaxrs.utils.HttpUtils;
+
+public class UrlEncodingParamConverter implements ParamConverter<String> {
+
+    private Set<Character> encodeClientParametersList;
+    
+    public UrlEncodingParamConverter() {
+        this(null);    
+    }
+    public UrlEncodingParamConverter(String encodeClientParametersListStr) {
+        if (encodeClientParametersListStr != null) {
+            String[] chars = encodeClientParametersListStr.trim().split(" ");
+            encodeClientParametersList = new HashSet<Character>();
+            for (String ch : chars) {
+                // this may need to be tuned though this should cover URI reserved chars
+                encodeClientParametersList.add(Character.valueOf(ch.charAt(0)));
+            }
+        }
+    }
+    
+    @Override
+    public String fromString(String s) {
+        return HttpUtils.urlDecode(s);
+    }
+
+    @Override
+    public String toString(String s) {
+        if (encodeClientParametersList == null || encodeClientParametersList.isEmpty()) {
+            return HttpUtils.urlEncode(s);    
+        } else {
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < s.length(); i++) {
+                Character ch = s.charAt(i);
+                if (encodeClientParametersList.contains(ch)) {
+                    sb.append(HttpUtils.urlEncode(ch.toString()));
+                } else {
+                    sb.append(ch);
+                }
+            }
+            return sb.toString();
+        }
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4c509a53/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
----------------------------------------------------------------------
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
index 710ce89..1a7520f 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
@@ -22,7 +22,6 @@ package org.apache.cxf.jaxrs.utils;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.net.URLEncoder;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -127,13 +126,7 @@ public final class HttpUtils {
     
     public static String urlEncode(String value, String enc) {
         
-        try {
-            value = URLEncoder.encode(value, enc);
-        } catch (UnsupportedEncodingException ex) {
-            throw new RuntimeException(ex);
-        }
-        
-        return value;
+        return UrlUtils.urlEncode(value, enc);
     }
     
     public static String pathEncode(String value) {

http://git-wip-us.apache.org/repos/asf/cxf/blob/4c509a53/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/UrlEncodingParamConverter.java
----------------------------------------------------------------------
diff --git a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/UrlEncodingParamConverter.java b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/UrlEncodingParamConverter.java
new file mode 100644
index 0000000..5b5bbd5
--- /dev/null
+++ b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/UrlEncodingParamConverter.java
@@ -0,0 +1,70 @@
+/**
+ * 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;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.ext.ParamConverter;
+
+import org.apache.cxf.jaxrs.utils.HttpUtils;
+
+public class UrlEncodingParamConverter implements ParamConverter<String> {
+
+    private Set<Character> encodeClientParametersList;
+    
+    public UrlEncodingParamConverter() {
+        this(null);    
+    }
+    public UrlEncodingParamConverter(String encodeClientParametersListStr) {
+        if (encodeClientParametersListStr != null) {
+            String[] chars = encodeClientParametersListStr.trim().split(" ");
+            encodeClientParametersList = new HashSet<Character>();
+            for (String ch : chars) {
+                // this may need to be tuned though this should cover URI reserved chars
+                encodeClientParametersList.add(Character.valueOf(ch.charAt(0)));
+            }
+        }
+    }
+    
+    @Override
+    public String fromString(String s) {
+        return HttpUtils.urlDecode(s);
+    }
+
+    @Override
+    public String toString(String s) {
+        if (encodeClientParametersList == null || encodeClientParametersList.isEmpty()) {
+            return HttpUtils.urlEncode(s);    
+        } else {
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < s.length(); i++) {
+                Character ch = s.charAt(i);
+                if (encodeClientParametersList.contains(ch)) {
+                    sb.append(HttpUtils.urlEncode(ch.toString()));
+                } else {
+                    sb.append(ch);
+                }
+            }
+            return sb.toString();
+        }
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/4c509a53/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
----------------------------------------------------------------------
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
index 14ae361..78a1e51 100644
--- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
@@ -46,6 +46,7 @@ import javax.ws.rs.Consumes;
 import javax.ws.rs.CookieParam;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
+import javax.ws.rs.Encoded;
 import javax.ws.rs.GET;
 import javax.ws.rs.HEAD;
 import javax.ws.rs.HeaderParam;
@@ -869,6 +870,20 @@ public class BookStore {
     }
     
     @GET
+    @Path("/thebooks/{bookId}/")
+    @Produces("application/xml")
+    public Book getBookWithSemicolon(@Encoded @PathParam("bookId") String id) {
+        Book b = new Book();
+        b.setId(Long.valueOf(id.substring(0, 3)));
+        b.setName("CXF in Action" + id.substring(3));
+        String absPath = ui.getAbsolutePath().toString();
+        if (absPath.contains("123;")) {
+            b.setName(b.getName() + ";");
+        }
+        return b;
+    }
+    
+    @GET
     @Path("/books/search")
     @Produces("application/xml")
     public Book getBook(@Context SearchContext searchContext) 

http://git-wip-us.apache.org/repos/asf/cxf/blob/4c509a53/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
----------------------------------------------------------------------
diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
index f9c5188..9d3adf6 100644
--- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
+++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
@@ -678,6 +678,41 @@ public class JAXRSClientServerBookTest extends AbstractBusClientServerTestBase {
         BookStore store = JAXRSClientFactory.create("http://localhost:" + PORT, BookStore.class);
         Book book = store.getBookWithSpace("123");
         assertEquals(123L, book.getId());
+        assertEquals("CXF in Action", book.getName());
+    }
+    
+    @Test
+    public void testBookWithSpaceProxyPathUrlEncoded() throws Exception {
+        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+        bean.setServiceClass(BookStore.class);
+        bean.setAddress("http://localhost:" + PORT);
+        bean.setProperties(Collections.<String, Object>singletonMap("url.encode.client.parameters", Boolean.TRUE));
+        BookStore store = bean.create(BookStore.class);
+        Book book = store.getBookWithSemicolon("123;:");
+        assertEquals(123L, book.getId());
+        assertEquals("CXF in Action%3B%3A", book.getName());
+    }
+    
+    @Test
+    public void testBookWithSpaceProxyPathUrlEncodedSemicolonOnly() throws Exception {
+        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+        bean.setServiceClass(BookStore.class);
+        bean.setAddress("http://localhost:" + PORT);
+        bean.getProperties(true).put("url.encode.client.parameters", "true");
+        bean.getProperties(true).put("url.encode.client.parameters.list", ";");
+        BookStore store = bean.create(BookStore.class);
+        Book book = store.getBookWithSemicolon("123;:");
+        assertEquals(123L, book.getId());
+        assertEquals("CXF in Action%3B:", book.getName());
+    }
+    
+    @Test
+    public void testBookWithSpaceProxyNonEncodedSemicolon() throws Exception {
+        BookStore store = JAXRSClientFactory.create("http://localhost:" + PORT,
+                                                    BookStore.class);
+        Book book = store.getBookWithSemicolon("123;");
+        assertEquals(123L, book.getId());
+        assertEquals("CXF in Action;", book.getName());
     }
     
     @Test
@@ -2051,14 +2086,15 @@ public class JAXRSClientServerBookTest extends AbstractBusClientServerTestBase {
     
     @Test
     public void testAddBookEmptyContent() throws Exception {
-        Response r = WebClient.create("http://localhost:" + PORT + "/bookstore/books").post(null);
+        Response r = WebClient.create("http://localhost:" + PORT + "/bookstore/books")
+            .type("*/*").post(null);
         assertEquals(400, r.getStatus());
     }
     
     @Test
     public void testAddBookEmptyContentWithNullable() throws Exception {
-        Book defaultBook = 
-            WebClient.create("http://localhost:" + PORT + "/bookstore/books/null").post(null, Book.class);
+        Book defaultBook = WebClient.create("http://localhost:" + PORT + "/bookstore/books/null")
+            .type("*/*").post(null, Book.class);
         assertEquals("Default Book", defaultBook.getName());
     }