From 1e8ad44a00ad68a63b2996582096621c887b3f19 Mon Sep 17 00:00:00 2001 From: challenh Date: Tue, 17 Jun 2014 10:32:44 +0800 Subject: [PATCH] [OLINGO-326] URIbuilder issue on android, and uri format issue of addressing derived types --- .../olingo/ext/proxy/commons/FilterImpl.java | 10 +++-- .../client/api/CommonConfiguration.java | 25 ++++++++++++ .../client/core/AbstractConfiguration.java | 12 ++++++ .../client/core/uri/AbstractURIBuilder.java | 39 +++++++++++++------ 4 files changed, 70 insertions(+), 16 deletions(-) diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/FilterImpl.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/FilterImpl.java index 42ce64611..f328ac718 100644 --- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/FilterImpl.java +++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/FilterImpl.java @@ -150,10 +150,12 @@ public class FilterImpl uriBuilder = client.newURIBuilder(this.baseURI.toASCIIString()). - appendDerivedEntityTypeSegment(new FullQualifiedName( - ClassUtils.getNamespace(typeRef), ClassUtils.getEntityTypeName(typeRef)).toString()); - + CommonURIBuilder uriBuilder = client.newURIBuilder(this.baseURI.toASCIIString()); + + if(this.client.getConfiguration().isAddressingDerivedTypes()){ + uriBuilder = uriBuilder.appendDerivedEntityTypeSegment(new FullQualifiedName( + ClassUtils.getNamespace(typeRef), ClassUtils.getEntityTypeName(typeRef)).toString()); + } if (StringUtils.isNotBlank(filter)) { uriBuilder.filter(filter); } diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/CommonConfiguration.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/CommonConfiguration.java index 2e3a0d8c8..46f12b33f 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/CommonConfiguration.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/CommonConfiguration.java @@ -202,6 +202,31 @@ public interface CommonConfiguration extends Serializable { */ void setKeyAsSegment(boolean value); + /** + * Gets whether query URIs in request should contain fully qualified type name. + * - OData Intermediate Conformance Level: + * MUST support casting to a derived type according to [OData-URL] if derived types are present in the model. + *
+ * Example: http://host/service/Customers/Model.VipCustomer(102) or + * http://host/service/Customers/Model.VipCustomer + * + * @return whether query URIs in request should contain fully qualified type name. + * segment. + */ + boolean isAddressingDerivedTypes() ; + + /** + * Sets whether query URIs in request should contain fully qualified type name. + * - OData Intermediate Conformance Level: + * MUST support casting to a derived type according to [OData-URL] if derived types are present in the model. + *
+ * Example: http://host/service/Customers/Model.VipCustomer(102) or + * http://host/service/Customers/Model.VipCustomer + * + * @param value 'TRUE' to use this feature. + */ + void setAddressingDerivedTypes(final boolean value); + /** * Retrieves request executor service. * diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/AbstractConfiguration.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/AbstractConfiguration.java index dc9ee6c63..888452a69 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/AbstractConfiguration.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/AbstractConfiguration.java @@ -51,6 +51,8 @@ public abstract class AbstractConfiguration implements CommonConfiguration { private static final String USE_XHTTP_METHOD = "useHTTPMethod"; private static final String KEY_AS_SEGMENT = "keyAsSegment"; + + private static final String ADDRESS_DERIVED_TYPE = "addressDerivedType"; private static final String GZIP_COMPRESSION = "gzipCompression"; @@ -212,6 +214,16 @@ public abstract class AbstractConfiguration implements CommonConfiguration { setProperty(KEY_AS_SEGMENT, value); } + @Override + public boolean isAddressingDerivedTypes() { + return (Boolean) getProperty(ADDRESS_DERIVED_TYPE, true); + } + + @Override + public void setAddressingDerivedTypes(final boolean value) { + setProperty(ADDRESS_DERIVED_TYPE, value); + } + @Override public ExecutorService getExecutor() { return executor; diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java index 5b0b53310..7a7c63018 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java @@ -24,9 +24,14 @@ import java.net.URISyntaxException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; + import org.apache.commons.lang3.StringUtils; +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.message.BasicNameValuePair; import org.apache.olingo.client.api.CommonConfiguration; import org.apache.olingo.client.api.uri.CommonURIBuilder; import org.apache.olingo.client.api.uri.QueryOption; @@ -269,7 +274,9 @@ public abstract class AbstractURIBuilder> impleme break; default: - segmentsBuilder.append('/'); + if(segmentsBuilder.length() > 0 && segmentsBuilder.charAt(segmentsBuilder.length()-1) != '/') { + segmentsBuilder.append('/'); + } } } @@ -284,19 +291,27 @@ public abstract class AbstractURIBuilder> impleme } try { - final org.apache.http.client.utils.URIBuilder builder = - new org.apache.http.client.utils.URIBuilder(segmentsBuilder.toString()); + StringBuilder sb = segmentsBuilder; + if((queryOptions.size() + parameters.size()) > 0){ + sb.append("?"); + List list1 = new LinkedList(); + for (Map.Entry option : queryOptions.entrySet()) { + list1.add(new BasicNameValuePair("$" + option.getKey(), option.getValue())); + } + for (Map.Entry parameter : parameters.entrySet()) { + list1.add(new BasicNameValuePair("@" + parameter.getKey(), parameter.getValue())); + } - for (Map.Entry option : queryOptions.entrySet()) { - builder.addParameter("$" + option.getKey(), option.getValue()); + // don't use UriBuilder.build(): + // it will try to call URLEncodedUtils.format(Iterable<>,Charset) method, + // which works in desktop java application, however, throws NoSuchMethodError in android OS, + // so here manually construct the URL by its overload URLEncodedUtils.format(List<>,String). + String queryStr = URLEncodedUtils.format(list1, "UTF-8"); + sb.append(queryStr); } - - for (Map.Entry parameter : parameters.entrySet()) { - builder.addParameter("@" + parameter.getKey(), parameter.getValue()); - } - - return builder.build().normalize(); - } catch (URISyntaxException e) { + + return URI.create(sb.toString()); + } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Could not build valid URI", e); } }