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());
}