Repository: ambari Updated Branches: refs/heads/trunk 9f296a25c -> 0edce3c4f
AMBARI-8605 Query predicate .matches doesn't work for stacks endpoint with passed logical OR(URL-encoding) (dsen) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/0edce3c4 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/0edce3c4 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/0edce3c4 Branch: refs/heads/trunk Commit: 0edce3c4f275b2ebca042e1fd8fb877acb7c5336 Parents: f77be4c Author: Dmytro Sen <d...@apache.org> Authored: Thu Jan 22 18:24:19 2015 +0200 Committer: Dmytro Sen <d...@apache.org> Committed: Thu Jan 22 19:23:35 2015 +0200 ---------------------------------------------------------------------- .../api/services/ResultPostProcessorImpl.java | 13 +++++- .../server/api/services/StacksService.java | 47 ++++++++++++++------ .../server/api/services/StacksServiceTest.java | 19 +++++++- 3 files changed, 63 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/0edce3c4/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java index 8d17846..61afee2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ResultPostProcessorImpl.java @@ -61,7 +61,18 @@ public class ResultPostProcessorImpl implements ResultPostProcessor { @Override public void process(Result result) { - processNode(result.getResultTree(), m_request.getURI()); + // Decode query string only + // Path should not be decoded here (username can contain '?') + String href = m_request.getURI(); + int pos = href.indexOf('?'); + if (pos != -1) { + try { + href = href.substring(0, pos + 1) + URLDecoder.decode(href.substring(pos + 1), "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("Unable to decode URI: " + e, e); + } + } + processNode(result.getResultTree(), href); } /** http://git-wip-us.apache.org/repos/asf/ambari/blob/0edce3c4/ambari-server/src/main/java/org/apache/ambari/server/api/services/StacksService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/StacksService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/StacksService.java index 366accf..74c7b57 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/StacksService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/StacksService.java @@ -22,6 +22,7 @@ import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -42,6 +43,9 @@ import javax.ws.rs.core.UriInfo; import org.apache.ambari.server.api.predicate.QueryLexer; import org.apache.ambari.server.api.resources.ResourceInstance; import org.apache.ambari.server.controller.spi.Resource; +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.message.BasicNameValuePair; /** * Service for stacks management. @@ -426,23 +430,38 @@ public class StacksService extends BaseService { return m_delegate.getPathSegments(b); } + /** + * Converts the new corrected property names to the old names for the backend. + * Because both the /stacks and /stacks2 api use the same underlying classes, we + * need to convert the new corrected property names to the old names for the backend. + * This should be removed when /stacks2 is removed and we can change the property names + * in the resource definitions to the new form. + */ + private String normalizeComponentNames(String value) { + if (value == null) { + return null; + } + value = value.replaceAll("services/", "stackServices/"); + value = value.replaceAll("components/", "serviceComponents/"); + value = value.replaceAll("operating_systems/", "operatingSystems/"); + return value; + } + @Override public URI getRequestUri() { - String uri; - try { - uri = URLDecoder.decode(m_delegate.getRequestUri().toASCIIString(), "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("Unable to decode URI: " + e, e); - } - uri = uri.replaceAll("services/", "stackServices/"); - uri = uri.replaceAll("components/", "serviceComponents/"); - uri = uri.replaceAll("operating_systems/", "operatingSystems/"); - - try { - return new URI(uri); - } catch (URISyntaxException e) { - throw new RuntimeException("Unable to create modified stacks URI: " + e, e); + String uriPath = m_delegate.getRequestUri().getPath(); + UriBuilder uriBuilder = UriBuilder.fromUri(m_delegate.getRequestUri()); + List<NameValuePair> parametersList = URLEncodedUtils.parse(m_delegate.getRequestUri(), "UTF-8"); + List<NameValuePair> newQuery = new ArrayList<NameValuePair>(); + for (NameValuePair nameValuePair : parametersList) { + newQuery.add(new BasicNameValuePair(normalizeComponentNames(nameValuePair.getName()), + normalizeComponentNames(nameValuePair.getValue()))); } + + uriBuilder.replacePath(normalizeComponentNames(uriPath)); + uriBuilder.replaceQuery(URLEncodedUtils.format(newQuery, "UTF-8")); + + return uriBuilder.build(); } @Override http://git-wip-us.apache.org/repos/asf/ambari/blob/0edce3c4/ambari-server/src/test/java/org/apache/ambari/server/api/services/StacksServiceTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/StacksServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/StacksServiceTest.java index e5be477..c36c6d9 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/StacksServiceTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/StacksServiceTest.java @@ -21,17 +21,22 @@ package org.apache.ambari.server.api.services; import org.apache.ambari.server.api.resources.ResourceInstance; import org.apache.ambari.server.api.services.parsers.RequestBodyParser; import org.apache.ambari.server.api.services.serializers.ResultSerializer; +import org.easymock.EasyMock; +import org.junit.Test; + import javax.ws.rs.PathParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; - import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; + import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.notNull; import static org.easymock.EasyMock.same; @@ -215,4 +220,16 @@ public class StacksServiceTest extends BaseServiceTest { expect(requestFactory.createRequest(same(httpHeaders), same(requestBody), (UriInfo) notNull(), same(testMethod.getRequestType()), same(resourceInstance))).andReturn(request); } + + @Test + public void testStackUriInfo() throws URISyntaxException { + + UriInfo delegate = new LocalUriInfo("http://host/services/?fields=*"); + StacksService.StackUriInfo sui = new StacksService.StackUriInfo(delegate); + assertEquals(new URI("http://host/stackServices/?fields=*"), sui.getRequestUri()); + + delegate = new LocalUriInfo("http://host/?condition1=true&condition2=true&services/service.matches(A%7CB)"); + sui = new StacksService.StackUriInfo(delegate); + assertEquals(new URI("http://host/?condition1=true&condition2=true&stackServices%2Fservice.matches%28A%7CB%29"), sui.getRequestUri()); + } }