Repository: knox Updated Branches: refs/heads/master 10de69b67 -> 4ca54c5a1
KNOX-395 POC for Jersey Topology Service from Knox Project: http://git-wip-us.apache.org/repos/asf/knox/repo Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/4ca54c5a Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/4ca54c5a Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/4ca54c5a Branch: refs/heads/master Commit: 4ca54c5a13e7bbf600a483cdebd653e8adcbc2a9 Parents: 10de69b Author: Larry McCay <[email protected]> Authored: Thu Jun 19 10:44:01 2014 -0400 Committer: Larry McCay <[email protected]> Committed: Thu Jun 19 10:44:01 2014 -0400 ---------------------------------------------------------------------- .../JerseyServiceDeploymentContributorBase.java | 6 +- gateway-service-vault/pom.xml | 59 ++ .../service/vault/CredentialResource.java | 128 +++ .../VaultServiceDeploymentContributor.java | 60 ++ ....gateway.deploy.ServiceDeploymentContributor | 19 + gateway-test/pom.xml | 5 + .../util/urltemplate/MatcherTest.java.orig | 839 +++++++++++++++++++ pom.xml | 10 +- 8 files changed, 1123 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/4ca54c5a/gateway-provider-jersey/src/main/java/org/apache/hadoop/gateway/jersey/JerseyServiceDeploymentContributorBase.java ---------------------------------------------------------------------- diff --git a/gateway-provider-jersey/src/main/java/org/apache/hadoop/gateway/jersey/JerseyServiceDeploymentContributorBase.java b/gateway-provider-jersey/src/main/java/org/apache/hadoop/gateway/jersey/JerseyServiceDeploymentContributorBase.java index fb7ac39..dc8a340 100644 --- a/gateway-provider-jersey/src/main/java/org/apache/hadoop/gateway/jersey/JerseyServiceDeploymentContributorBase.java +++ b/gateway-provider-jersey/src/main/java/org/apache/hadoop/gateway/jersey/JerseyServiceDeploymentContributorBase.java @@ -30,6 +30,7 @@ import java.util.List; public abstract class JerseyServiceDeploymentContributorBase extends ServiceDeploymentContributorBase { private static final String PACKAGES_PARAM = "jersey.config.server.provider.packages"; + private static final String TRACE_LOGGING_PARAM = "jersey.config.server.tracing"; protected abstract String[] getPackages(); @@ -50,8 +51,11 @@ public abstract class JerseyServiceDeploymentContributorBase extends ServiceDepl param.name( PACKAGES_PARAM ); param.value( packages ); params.add( param ); +// FilterParamDescriptor trace = resource.createFilterParam(); +// param.name( TRACE_LOGGING_PARAM ); +// param.value( "ALL" ); +// params.add( trace ); context.contributeFilter( service, resource, "pivot", "jersey", params ); } } - } http://git-wip-us.apache.org/repos/asf/knox/blob/4ca54c5a/gateway-service-vault/pom.xml ---------------------------------------------------------------------- diff --git a/gateway-service-vault/pom.xml b/gateway-service-vault/pom.xml new file mode 100644 index 0000000..9dab0dd --- /dev/null +++ b/gateway-service-vault/pom.xml @@ -0,0 +1,59 @@ +<?xml version="1.0"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.hadoop</groupId> + <artifactId>gateway</artifactId> + <version>0.5.0-SNAPSHOT</version> + </parent> + <groupId>org.apache.hadoop</groupId> + <artifactId>gateway-service-vault</artifactId> + <version>0.5.0-SNAPSHOT</version> + <name>gateway-service-vault</name> + <url>http://maven.apache.org</url> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <dependencies> + <dependency> + <groupId>${gateway-group}</groupId> + <artifactId>gateway-spi</artifactId> + </dependency> + <dependency> + <groupId>${gateway-group}</groupId> + <artifactId>gateway-provider-rewrite</artifactId> + </dependency> + <dependency> + <groupId>${gateway-group}</groupId> + <artifactId>gateway-provider-jersey</artifactId> + </dependency> + <dependency> + <groupId>com.owlike</groupId> + <artifactId>genson</artifactId> + <version>0.99</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/knox/blob/4ca54c5a/gateway-service-vault/src/main/java/org/apache/hadoop/gateway/service/vault/CredentialResource.java ---------------------------------------------------------------------- diff --git a/gateway-service-vault/src/main/java/org/apache/hadoop/gateway/service/vault/CredentialResource.java b/gateway-service-vault/src/main/java/org/apache/hadoop/gateway/service/vault/CredentialResource.java new file mode 100644 index 0000000..9f60624 --- /dev/null +++ b/gateway-service-vault/src/main/java/org/apache/hadoop/gateway/service/vault/CredentialResource.java @@ -0,0 +1,128 @@ +/** + * 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.hadoop.gateway.service.vault; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; + +import org.apache.hadoop.gateway.services.GatewayServices; +import org.apache.hadoop.gateway.services.security.AliasService; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static javax.ws.rs.core.MediaType.APPLICATION_XML; +import static javax.ws.rs.core.MediaType.TEXT_PLAIN_TYPE; +import static javax.ws.rs.core.Response.created; +import static javax.ws.rs.core.Response.ok; +import static javax.ws.rs.core.Response.serverError; +import static javax.ws.rs.core.Response.status; +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; + +@Path( "/vault/credentials" ) +public class CredentialResource { + @Context + private HttpServletRequest request; + + @GET + @Path("{alias}") + @Produces({APPLICATION_JSON, APPLICATION_XML}) + public Response getCredential(@PathParam("alias") String alias) { + if (alias != null && !alias.isEmpty()) { + CredentialValue value = getCredentialValueForAlias(alias); + if (value != null) { + return ok(value).build(); + } else { + return status(NOT_FOUND).build(); + } + } else { + return status(BAD_REQUEST). + entity("Please provide a credential alias in the path"). + type(TEXT_PLAIN_TYPE).build(); + } + } + + @GET + @Produces({APPLICATION_JSON, APPLICATION_XML}) + public Response getCredentials() { + List<String> aliases = getCredentialsList(); + if (aliases != null) { + return ok(aliases).build(); + } else { + return status(NOT_FOUND).build(); + } + } + + /** + * @return + */ + private List<String> getCredentialsList() { + GatewayServices services = (GatewayServices)request.getServletContext(). + getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE); + String clusterName = (String) request.getServletContext().getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE); + AliasService as = services.getService(GatewayServices.ALIAS_SERVICE); + List<String> aliases = as.getAliasesForCluster(clusterName); + return aliases; + } + + /** + * @param alias + * @return + */ + private CredentialValue getCredentialValueForAlias(String alias) { + GatewayServices services = (GatewayServices)request.getServletContext(). + getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE); + String clusterName = (String) request.getServletContext().getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE); + AliasService as = services.getService(GatewayServices.ALIAS_SERVICE); + char[] credential = as.getPasswordFromAliasForCluster(clusterName, alias); + if (credential != null) { + return new CredentialValue(alias, new String(credential)); + } + return null; + } + + public static class CredentialValue { + private String alias; + private String credential; + + public CredentialValue(String alias, String credential) { + super(); + this.alias = alias; + this.credential = credential; + } + + public String getAlias() { + return alias; + } + public void setAlias(String alias) { + this.alias = alias; + } + public String getCredential() { + return credential; + } + public void setCredential(String credential) { + this.credential = credential; + } + } +} http://git-wip-us.apache.org/repos/asf/knox/blob/4ca54c5a/gateway-service-vault/src/main/java/org/apache/hadoop/gateway/service/vault/deploy/VaultServiceDeploymentContributor.java ---------------------------------------------------------------------- diff --git a/gateway-service-vault/src/main/java/org/apache/hadoop/gateway/service/vault/deploy/VaultServiceDeploymentContributor.java b/gateway-service-vault/src/main/java/org/apache/hadoop/gateway/service/vault/deploy/VaultServiceDeploymentContributor.java new file mode 100644 index 0000000..b834cb4 --- /dev/null +++ b/gateway-service-vault/src/main/java/org/apache/hadoop/gateway/service/vault/deploy/VaultServiceDeploymentContributor.java @@ -0,0 +1,60 @@ +/** + * 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.hadoop.gateway.service.vault.deploy; + +import org.apache.hadoop.gateway.jersey.JerseyServiceDeploymentContributorBase; + +/** + * + */ +public class VaultServiceDeploymentContributor extends JerseyServiceDeploymentContributorBase { + + /* (non-Javadoc) + * @see org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor#getRole() + */ + @Override + public String getRole() { + // TODO Auto-generated method stub + return "VAULT"; + } + + /* (non-Javadoc) + * @see org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor#getName() + */ + @Override + public String getName() { + return "KnoxVaultService"; + } + + /* (non-Javadoc) + * @see org.apache.hadoop.gateway.jersey.JerseyServiceDeploymentContributorBase#getPackages() + */ + @Override + protected String[] getPackages() { + return new String[]{ "org.apache.hadoop.gateway.service.vault" }; + } + + /* (non-Javadoc) + * @see org.apache.hadoop.gateway.jersey.JerseyServiceDeploymentContributorBase#getPatterns() + */ + @Override + protected String[] getPatterns() { + return new String[]{ "vault/**?**" }; + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/4ca54c5a/gateway-service-vault/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor ---------------------------------------------------------------------- diff --git a/gateway-service-vault/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor b/gateway-service-vault/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor new file mode 100644 index 0000000..fc73269 --- /dev/null +++ b/gateway-service-vault/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor @@ -0,0 +1,19 @@ +########################################################################## +# 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. +########################################################################## + +org.apache.hadoop.gateway.service.vault.deploy.VaultServiceDeploymentContributor \ No newline at end of file http://git-wip-us.apache.org/repos/asf/knox/blob/4ca54c5a/gateway-test/pom.xml ---------------------------------------------------------------------- diff --git a/gateway-test/pom.xml b/gateway-test/pom.xml index 736b66d..ba7d86d 100644 --- a/gateway-test/pom.xml +++ b/gateway-test/pom.xml @@ -40,6 +40,11 @@ <artifactId>gateway-provider-jersey</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>${gateway-group}</groupId> + <artifactId>gateway-service-vault</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>${gateway-group}</groupId> http://git-wip-us.apache.org/repos/asf/knox/blob/4ca54c5a/gateway-util-urltemplate/src/test/java/org/apache/hadoop/gateway/util/urltemplate/MatcherTest.java.orig ---------------------------------------------------------------------- diff --git a/gateway-util-urltemplate/src/test/java/org/apache/hadoop/gateway/util/urltemplate/MatcherTest.java.orig b/gateway-util-urltemplate/src/test/java/org/apache/hadoop/gateway/util/urltemplate/MatcherTest.java.orig new file mode 100644 index 0000000..6b6012b --- /dev/null +++ b/gateway-util-urltemplate/src/test/java/org/apache/hadoop/gateway/util/urltemplate/MatcherTest.java.orig @@ -0,0 +1,839 @@ +/** + * 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.hadoop.gateway.util.urltemplate; + + +import org.apache.hadoop.test.category.FastTests; +import org.apache.hadoop.test.category.UnitTests; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import java.net.URISyntaxException; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.CoreMatchers.sameInstance; +import static org.hamcrest.core.IsCollectionContaining.hasItem; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.junit.Assert.assertThat; + +//TODO: Test to make sure that extra unmatched query parameters prevent a match. +@Category( { UnitTests.class, FastTests.class } ) +public class MatcherTest { + + private void addTemplate( Matcher<String> matcher, String template ) throws URISyntaxException { + matcher.add( Parser.parse( template ), template ); + } + + private void assertValidMatch( Matcher<String> matcher, String uri, String template ) throws URISyntaxException { + if( template == null ) { + assertThat( matcher.match( Parser.parse( uri ) ), nullValue() ); + } else { + Template uriTemplate = Parser.parse( uri ); + Matcher<String>.Match match = matcher.match( uriTemplate ); + assertThat( "Expected to find a match.", match, notNullValue() ); + assertThat( match.getValue(), equalTo( template ) ); + } + } + + @Test + public void testWildcardCharacterInInputTemplate() throws URISyntaxException { + Matcher<String> matcher; + Template patternTemplate, inputTemplate; + Matcher<String>.Match match; + + // First verify that if .../test_table/test_row/family1... works. + matcher = new Matcher<String>(); + inputTemplate = Parser.parse( "https://localhost:8443/gateway/sandbox/hbase/test_table/test_row/family1:row2_col1,family2/0,9223372036854775807?v=1" ); + patternTemplate = Parser.parse( "*://*:*/**/webhdfs/{version}/{path=**}?{**}" ); + matcher.add( patternTemplate, "webhdfs" ); + match = matcher.match( inputTemplate ); + assertThat( match, nullValue() ); + + // Then reproduce the issue with .../test_table/*/family1.. + matcher = new Matcher<String>(); + inputTemplate = Parser.parse( "https://localhost:8443/gateway/sandbox/hbase/test_table/*/family1:row2_col1,family2/0,9223372036854775807?v=1" ); + patternTemplate = Parser.parse( "*://*:*/**/webhdfs/{version}/{path=**}?{**}" ); + matcher.add( patternTemplate, "webhdfs" ); + match = matcher.match( inputTemplate ); + assertThat( match, nullValue() ); + + // Reproduce the issue where the wrong match was picked when there was a "*" in the input URL template. + matcher = new Matcher<String>(); + inputTemplate = Parser.parse( "https://localhost:8443/gateway/sandbox/hbase/test_table/*/family1:row2_col1,family2/0,9223372036854775807?v=1" ); + patternTemplate = Parser.parse( "*://*:*/**/webhdfs/{version}/{path=**}?{**}" ); + matcher.add( patternTemplate, "webhdfs" ); + patternTemplate = Parser.parse( "*://*:*/**/hbase/{path=**}?{**}" ); + matcher.add( patternTemplate, "hbase" ); + match = matcher.match( inputTemplate ); + assertThat( match.getValue(), is( "hbase" ) ); + } + + @Test + public void testDefaultAppDeployment() throws Exception { + Matcher<String> matcher; + Template patternTemplate, inputTemplate; + Matcher<String>.Match match; + + matcher = new Matcher<String>(); + inputTemplate = Parser.parse( "https://localhost:8443/webhdfs/v1/tmp?op=LISTSTATUS" ); + patternTemplate = Parser.parse( "*://*:*/webhdfs/{version}/{path=**}?{**}" ); + matcher.add( patternTemplate, "webhdfs" ); + match = matcher.match( inputTemplate ); + assertThat( match, notNullValue() ); + } + + @Test + public void testRootPathMatching() throws Exception { + Matcher<String> matcher; + Template patternTemplate, inputTemplate; + Matcher<String>.Match match; + + /////// + patternTemplate = Parser.parse( "*://*:*" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "test-match" ); + + inputTemplate = Parser.parse( "test-scheme://test-host:42" ); + match = matcher.match( inputTemplate ); + assertThat( match, notNullValue() ); + inputTemplate = Parser.parse( "test-scheme://test-host:42/" ); + match = matcher.match( inputTemplate ); + assertThat( match, notNullValue() ); + inputTemplate = Parser.parse( "test-scheme://test-host:42/test-path" ); + match = matcher.match( inputTemplate ); + assertThat( match, nullValue() ); + + /////// + patternTemplate = Parser.parse( "*://*:*/" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "test-match" ); + + inputTemplate = Parser.parse( "test-scheme://test-host:42" ); + match = matcher.match( inputTemplate ); + assertThat( match, notNullValue() ); + inputTemplate = Parser.parse( "test-scheme://test-host:42/" ); + match = matcher.match( inputTemplate ); + assertThat( match, notNullValue() ); + inputTemplate = Parser.parse( "test-scheme://test-host:42/test-path" ); + match = matcher.match( inputTemplate ); + assertThat( match, nullValue() ); + + /////// + patternTemplate = Parser.parse( "*://*:*/*" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "test-match" ); + + inputTemplate = Parser.parse( "test-scheme://test-host:42" ); + match = matcher.match( inputTemplate ); + assertThat( match, nullValue() ); + inputTemplate = Parser.parse( "test-scheme://test-host:42/" ); + match = matcher.match( inputTemplate ); + assertThat( match, nullValue() ); + inputTemplate = Parser.parse( "test-scheme://test-host:42/test-path" ); + match = matcher.match( inputTemplate ); + assertThat( match, notNullValue() ); + + /////// + patternTemplate = Parser.parse( "*://*:*/**" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "test-match" ); + +//KM: I'm not sure what the correct behavior is here. +// inputTemplate = Parser.parse( "test-scheme://test-host:42" ); +// match = matcher.match( inputTemplate ); +// assertThat( match, ? ); +// inputTemplate = Parser.parse( "test-scheme://test-host:42/" ); +// match = matcher.match( inputTemplate ); +// assertThat( match, ? ); + inputTemplate = Parser.parse( "test-scheme://test-host:42/test-path" ); + match = matcher.match( inputTemplate ); + assertThat( match, notNullValue() ); + + /////// + patternTemplate = Parser.parse( "*://*:*/{path=*}" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "test-match" ); + + inputTemplate = Parser.parse( "test-scheme://test-host:42" ); + match = matcher.match( inputTemplate ); + assertThat( match, nullValue() ); + inputTemplate = Parser.parse( "test-scheme://test-host:42/" ); + match = matcher.match( inputTemplate ); + assertThat( match, nullValue() ); + inputTemplate = Parser.parse( "test-scheme://test-host:42/test-path" ); + match = matcher.match( inputTemplate ); + assertThat( match, notNullValue() ); + + /////// + patternTemplate = Parser.parse( "*://*:*/{path=**}" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "test-match" ); + +//KM: I'm not sure what the correct behavior is here. +// inputTemplate = Parser.parse( "test-scheme://test-host:42" ); +// match = matcher.match( inputTemplate ); +// assertThat( match, ? ); +// inputTemplate = Parser.parse( "test-scheme://test-host:42/" ); +// match = matcher.match( inputTemplate ); +// assertThat( match, ? ); + inputTemplate = Parser.parse( "test-scheme://test-host:42/test-path" ); + match = matcher.match( inputTemplate ); + assertThat( match, notNullValue() ); + } + + @Test + public void testTopLevelPathGlobMatch() throws Exception { + Matcher<String> matcher; + Template patternTemplate, inputTemplate; + Matcher<String>.Match match; + + patternTemplate = Parser.parse( "{*}://{host}:{*}/{**=**}?{**}" ); + inputTemplate = Parser.parse( "test-scheme://test-input-host:42/test-path/test-file?test-name=test-value" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "test-math" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because the path ** should include both test-path and test-file", match, notNullValue() ); + + patternTemplate = Parser.parse( "{*}://{host}:{*}/{**}?{**}" ); + inputTemplate = Parser.parse( "test-scheme://test-input-host:42/test-path/test-file?test-name=test-value" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "test-math" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because the path ** should include both test-path and test-file", match, notNullValue() ); + } + + @Test + public void testQueryHandling() throws Exception { + Matcher<String> matcher; + Template patternTemplate, inputTemplate; + Matcher<String>.Match match; + + patternTemplate = Parser.parse( "/path?{query}" ); + inputTemplate = Parser.parse( "/path" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should not match because input does not contain the required query.", match, nullValue() ); + + matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/path?{query}" ), "T1" ); + matcher.add( Parser.parse( "/path" ), "T2" ); + inputTemplate = Parser.parse( "/path" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because there is an entry in the matcher without a query.", match, notNullValue() ); + assertThat( match.getValue(), equalTo( "T2") ); + + patternTemplate = Parser.parse( "/path?{query}" ); + inputTemplate = Parser.parse( "/path?query=value" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because input does contain the required query.", match, notNullValue() ); + assertThat( match.getParams().resolve( "query" ), hasItem( "value" ) ); + assertThat( match.getParams().resolve( "query" ).size(), equalTo( 1 ) ); + + patternTemplate = Parser.parse( "/path?{*}" ); + inputTemplate = Parser.parse( "/path" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should not match because input does not contain the required query.", match, nullValue() ); + + patternTemplate = Parser.parse( "/path?*" ); + inputTemplate = Parser.parse( "/path" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should not match because input does not contain the required query.", match, nullValue() ); + + patternTemplate = Parser.parse( "/path?*" ); + inputTemplate = Parser.parse( "/path?query=value" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( + "Should match because the template has an extra query and the input has a query.", + match, notNullValue() ); + assertThat( + "Should not have extracts any parameters since pattern template didn't contain {}", + match.getParams().resolve( "query" ), nullValue() ); + + patternTemplate = Parser.parse( "/path?{*}" ); + inputTemplate = Parser.parse( "/path?query=value" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because input does contain the required query.", match, notNullValue() ); + assertThat( match.getParams().resolve( "query" ), hasItem( "value" ) ); + + patternTemplate = Parser.parse( "/path?{**}" ); + inputTemplate = Parser.parse( "/path" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because the template has an optional query.", match, notNullValue() ); + + patternTemplate = Parser.parse( "/path?**" ); + inputTemplate = Parser.parse( "/path" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because the template has an optional extra query.", match, notNullValue() ); + + patternTemplate = Parser.parse( "/path?**" ); + inputTemplate = Parser.parse( "/path?query=value" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because the template has an optional extra query.", match, notNullValue() ); + assertThat( match.getParams().resolve( "query" ), nullValue() ); + + patternTemplate = Parser.parse( "/path?{**}" ); + inputTemplate = Parser.parse( "/path?query=value" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because the template has an optional extra query.", match, notNullValue() ); + assertThat( match.getParams().resolve( "query" ), hasItem( "value" ) ); + assertThat( match.getParams().resolve( "query" ).size(), equalTo( 1 ) ); + + patternTemplate = Parser.parse( "/path?{query}&{*}" ); + inputTemplate = Parser.parse( "/path?query=value" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should not match because input does not contain the required extra query.", match, nullValue() ); + + patternTemplate = Parser.parse( "/path?{query}&{*}" ); + inputTemplate = Parser.parse( "/path?query=value&extra=extra-value" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because input does contain the required query.", match, notNullValue() ); + assertThat( match.getParams().resolve( "query" ), hasItem( "value" ) ); + assertThat( match.getParams().resolve( "query" ).size(), equalTo( 1 ) ); + + patternTemplate = Parser.parse( "/path?{query=**}" ); + inputTemplate = Parser.parse( "/path?query=value1&query=value2" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because input does contain the required query.", match, notNullValue() ); + assertThat( match.getParams().resolve( "query" ), hasItem( "value1" ) ); + assertThat( match.getParams().resolve( "query" ), hasItem( "value2" ) ); + assertThat( match.getParams().resolve( "query" ).size(), equalTo( 2 ) ); + + patternTemplate = Parser.parse( "/path?{query}" ); + inputTemplate = Parser.parse( "/path?query=value1&query=value2" ); + matcher = new Matcher<String>(); + matcher.add( patternTemplate, "T" ); + match = matcher.match( inputTemplate ); + assertThat( "Should match because input does contain the required query.", match, notNullValue() ); + assertThat( match.getParams().resolve( "query" ), hasItem( "value1" ) ); + assertThat( match.getParams().resolve( "query" ), hasItem( "value2" ) ); + assertThat( match.getParams().resolve( "query" ).size(), equalTo( 2 ) ); + } + + @Test + public void testMatchCompleteUrl() throws Exception { + Matcher<String> matcher; + String pattern, input; + Template patternTemplate, inputTemplate; + Matcher<String>.Match match; + + matcher = new Matcher<String>(); + pattern = "foo://username:[email protected]:8042/over/there/index.dtb?type=animal&name=narwhal#nose"; + patternTemplate = Parser.parse( pattern ); + matcher.add( patternTemplate, pattern ); + input = "foo://username:[email protected]:8042/over/there/index.dtb?type=animal&name=narwhal#nose"; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match.getTemplate(), sameInstance( patternTemplate ) ); + assertThat( match.getValue(), equalTo( pattern ) ); + + matcher = new Matcher<String>(); + pattern = "foo://username:[email protected]:8042/over/there/index.dtb?type=animal&name=narwhal#nose"; + patternTemplate = Parser.parse( pattern ); + matcher.add( patternTemplate, pattern ); + + input = pattern; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match, notNullValue() ); + + input = "not://username:[email protected]:8042/over/there/index.dtb?type=animal&name=narwhal#nose"; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match, nullValue() ); + } + + @Test + public void testMatch() throws Exception { + Matcher<String> matcher; + String pattern, input; + Template patternTemplate, inputTemplate; + Matcher<String>.Match match; + + matcher = new Matcher<String>(); + pattern = "path"; + patternTemplate = Parser.parse( pattern ); + matcher.add( patternTemplate, pattern ); + assertThat( matcher.get( patternTemplate ), is( pattern ) ); + input = "path"; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match.getTemplate(), sameInstance( patternTemplate ) ); + assertThat( match.getValue(), equalTo( pattern ) ); + + + matcher = new Matcher<String>(); + pattern = "/path"; + patternTemplate = Parser.parse( pattern ); + matcher.add( patternTemplate, pattern ); + input = "/path"; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match.getTemplate(), sameInstance( patternTemplate ) ); + assertThat( match.getValue(), equalTo( pattern ) ); + + matcher = new Matcher<String>(); + pattern = "path/path"; + patternTemplate = Parser.parse( pattern ); + matcher.add( patternTemplate, pattern ); + input = "path/path"; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match.getTemplate(), sameInstance( patternTemplate ) ); + assertThat( match.getValue(), equalTo( pattern ) ); + + matcher = new Matcher<String>(); + pattern = "*/path"; + patternTemplate = Parser.parse( pattern ); + matcher.add( patternTemplate, pattern ); + input = "pathA/path"; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match.getTemplate(), sameInstance( patternTemplate ) ); + assertThat( match.getValue(), equalTo( pattern ) ); + + matcher = new Matcher<String>(); + pattern = "**/path"; + patternTemplate = Parser.parse( pattern ); + matcher.add( patternTemplate, pattern ); + input = "pathA/pathB/path"; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match.getTemplate(), sameInstance( patternTemplate ) ); + assertThat( match.getValue(), equalTo( pattern ) ); + + matcher = new Matcher<String>(); + pattern = "path-1/{path=**}/path-4"; + patternTemplate = Parser.parse( pattern ); + matcher.add( patternTemplate, pattern ); + input = "path-1/path-2/path-3/path-4"; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match.getTemplate(), sameInstance( patternTemplate ) ); + assertThat( match.getValue(), equalTo( pattern ) ); + assertThat( match.getParams().resolve( "path" ).get( 0 ), equalTo( "path-2" ) ); + assertThat( match.getParams().resolve( "path" ).get( 1 ), equalTo( "path-3" ) ); + + matcher = new Matcher<String>(); + pattern = "/"; + patternTemplate = Parser.parse( pattern ); + matcher.add( patternTemplate, pattern ); + input = "/"; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match.getTemplate(), sameInstance( patternTemplate ) ); + assertThat( match.getValue(), equalTo( pattern ) ); + + matcher = new Matcher<String>(); + pattern = ""; + patternTemplate = Parser.parse( pattern ); + matcher.add( patternTemplate, pattern ); + input = ""; + inputTemplate = Parser.parse( input ); + match = matcher.match( inputTemplate ); + assertThat( match.getTemplate(), sameInstance( patternTemplate ) ); + assertThat( match.getValue(), equalTo( pattern ) ); + } + + @Test + public void testVariousPatterns() throws URISyntaxException { + Matcher<String> matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/webhdfs" ), "/webhdfs" ); + matcher.add( Parser.parse( "/webhdfs/dfshealth.jsp" ), "/webhdfs/dfshealth.jsp" ); + matcher.add( Parser.parse( "/webhdfs/*.jsp" ), "/webhdfs/*.jsp" ); + matcher.add( Parser.parse( "/webhdfs/other.jsp" ), "/webhdfs/other.jsp" ); + matcher.add( Parser.parse( "/webhdfs/*" ), "/webhdfs/*" ); + matcher.add( Parser.parse( "/webhdfs/**" ), "/webhdfs/**" ); + matcher.add( Parser.parse( "/webhdfs/v1/**" ), "/webhdfs/v1/**" ); + matcher.add( Parser.parse( "/webhdfs/**/middle/*.xml" ), "/webhdfs/**/middle/*.xml" ); + + assertValidMatch( matcher, "/webhdfs", "/webhdfs" ); + assertValidMatch( matcher, "/webhdfs/dfshealth.jsp", "/webhdfs/dfshealth.jsp" ); + assertValidMatch( matcher, "/webhdfs/v1", "/webhdfs/*" ); // The star should be picked in preference to the glob. + assertValidMatch( matcher, "/webhdfs/some.jsp", "/webhdfs/*.jsp" ); + assertValidMatch( matcher, "/webhdfs/other.jsp", "/webhdfs/other.jsp" ); + assertValidMatch( matcher, "/webhdfs/path/some.jsp", "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/path/middle/some.jsp", "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/path/middle/some.xml", "/webhdfs/**/middle/*.xml" ); + assertValidMatch( matcher, "/webhdfs/path/to/file", "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/v1/path/to/file", "/webhdfs/v1/**" ); + } + + @Test + public void testStar() throws URISyntaxException { + Matcher<String> matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/webhdfs/*" ), "/webhdfs/*" ); + assertValidMatch( matcher, "/webhdfs/*", "/webhdfs/*" ); + assertValidMatch( matcher, "/webhdfs/file", "/webhdfs/*" ); + assertValidMatch( matcher, "/webhdfs/path/", "/webhdfs/*" ); + assertValidMatch( matcher, "/webhdfs/path/file", null ); + assertValidMatch( matcher, "/webhdfs/path/path/", null ); + } + + @Test + public void testGlob() throws URISyntaxException { + Matcher<String> matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/webhdfs/**" ), "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/file", "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/path/", "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/path/file", "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/path/path/", "/webhdfs/**" ); + } + + @Test + public void testMatrixParam() throws URISyntaxException { + Matcher<String> matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/webhdfs/**" ), "/webhdfs/**" ); + matcher.add( Parser.parse( "/webhdfs/browseDirectory.jsp;dn=*" ), "/webhdfs/browseDirectory.jsp;dn=*" ); + assertValidMatch( matcher, "/webhdfs/browseDirectory.jsp;dn=X", "/webhdfs/browseDirectory.jsp;dn=*" ); + } + + @Test + public void testTwoGlobsAtDifferentDepths() throws URISyntaxException { + Matcher<String> matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/webhdfs/**" ), "/webhdfs/**" ); + matcher.add( Parser.parse( "/webhdfs/v1/**" ), "/webhdfs/v1/**" ); + assertValidMatch( matcher, "/webhdfs/file", "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/v1/file", "/webhdfs/v1/**" ); + + // Reverse the put order. + matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/webhdfs/v1/**" ), "/webhdfs/v1/**" ); + matcher.add( Parser.parse( "/webhdfs/**" ), "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/file", "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/v1/file", "/webhdfs/v1/**" ); + } + + @Test + public void testGlobsVsStarsAtSameDepth() throws URISyntaxException { + Matcher<String> matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/webhdfs/*" ), "/webhdfs/*" ); + matcher.add( Parser.parse( "/webhdfs/**" ), "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/file", "/webhdfs/*" ); // The star should be picked in preference to the glob. + assertValidMatch( matcher, "/webhdfs/path/file", "/webhdfs/**" ); + + // Reverse the put order. + matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/webhdfs/**" ), "/webhdfs/**" ); + matcher.add( Parser.parse( "/webhdfs/*" ), "/webhdfs/*" ); + assertValidMatch( matcher, "/webhdfs/path/file", "/webhdfs/**" ); + assertValidMatch( matcher, "/webhdfs/file", "/webhdfs/*" ); + } + + @Test + public void testMatchingPatternsWithinPathSegments() throws URISyntaxException { + Matcher<String> matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/path/{file}" ), "default" ); + assertValidMatch( matcher, "/path/file-name", "default" ); + + matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/path/{file=*}" ), "*" ); + assertValidMatch( matcher, "/path/some-name", "*" ); + + matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/path/{more=**}" ), "**" ); + assertValidMatch( matcher, "/path/some-path/some-name", "**" ); + + matcher = new Matcher<String>(); + matcher.add( Parser.parse( "/path/{regex=prefix*suffix}" ), "regex" ); + assertValidMatch( matcher, "/path/prefix-middle-suffix", "regex" ); + assertValidMatch( matcher, "/path/not-prefix-middle-suffix", null ); + } + + @Test + public void testMatchingPatternsWithinQuerySegments() throws URISyntaxException { + Matcher<String> matcher = new Matcher<String>(); + matcher.add( Parser.parse( "?query={queryParam}" ), "default" ); + assertValidMatch( matcher, "?query=value", "default" ); + + matcher = new Matcher<String>(); + matcher.add( Parser.parse( "?query={queryParam=*}" ), "*" ); + assertValidMatch( matcher, "?query=some-value", "*" ); + + matcher = new Matcher<String>(); + matcher.add( Parser.parse( "?query={queryParam=**}" ), "**" ); + assertValidMatch( matcher, "?query=some-value", "**" ); + + matcher = new Matcher<String>(); + matcher.add( Parser.parse( "?query={queryParam=prefix*suffix}" ), "regex" ); + assertValidMatch( matcher, "?query=prefix-middle-suffix", "regex" ); + assertValidMatch( matcher, "?query=not-prefix-middle-suffix", null ); + } + + @Test + public void testMatchingForTemplatesThatVaryOnlyByQueryParams() throws URISyntaxException { + Matcher<String> matcher = new Matcher<String>(); + addTemplate( matcher, "?one={queryParam}" ); + addTemplate( matcher, "?two={queryParam}" ); + + assertValidMatch( matcher, "?one=value", "?one={queryParam}" ); + assertValidMatch( matcher, "?two=value", "?two={queryParam}" ); + assertValidMatch( matcher, "?three=value", null ); + assertValidMatch( matcher, "?", null ); + } + + @Test + public void testFullUrlExtraction() throws URISyntaxException { + Template template; + Template input; + Matcher<?> matcher; + Matcher<?>.Match match; + Params params; + + template = Parser.parse( "{scheme}://{username}:{password}@{host}:{port}/{root}/{path}/{file}?queryA={paramA}&queryB={paramB}#{fragment}" ); + input = Parser.parse( "http://horton:[email protected]:80/top/middle/end?queryA=valueA&queryB=valueB#section" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + + assertThat( params.getNames(), hasItem( "scheme" ) ); + assertThat( params.resolve( "scheme" ), hasItem( "http" ) ); + assertThat( params.getNames(), hasItem( "username" ) ); + assertThat( params.resolve( "username" ), hasItem( "horton" ) ); + assertThat( params.getNames(), hasItem( "password" ) ); + assertThat( params.resolve( "password" ), hasItem( "hadoop" ) ); + assertThat( params.getNames(), hasItem( "host" ) ); + assertThat( params.resolve( "host" ), hasItem( "hortonworks.com" ) ); + assertThat( params.getNames(), hasItem( "port" ) ); + assertThat( params.resolve( "port" ), hasItem( "80" ) ); + assertThat( params.getNames(), hasItem( "root" ) ); + assertThat( params.resolve( "root" ), hasItem( "top" ) ); + assertThat( params.getNames(), hasItem( "path" ) ); + assertThat( params.resolve( "path" ), hasItem( "middle" ) ); + assertThat( params.getNames(), hasItem( "file" ) ); + assertThat( params.resolve( "file" ), hasItem( "end" ) ); + assertThat( params.getNames(), hasItem( "paramA" ) ); + assertThat( params.resolve( "paramA" ), hasItem( "valueA" ) ); + assertThat( params.getNames(), hasItem( "paramB" ) ); + assertThat( params.resolve( "paramB" ), hasItem( "valueB" ) ); + assertThat( params.getNames(), hasItem( "fragment" ) ); + assertThat( params.resolve( "fragment" ), hasItem( "section" ) ); + assertThat( params.getNames().size(), equalTo( 11 ) ); + } + + @Test + public void testMultipleDoubleStarPathMatching() throws URISyntaxException { + Template template; + Template input; + Matcher<?> matcher; + Matcher<String> stringMatcher; + Matcher<?>.Match match; + +// template = Parser.parse( "*://*:*/**/webhdfs/v1/**?**" ); +// input = Parser.parse( "http://localhost:53221/gateway/cluster/webhdfs/v1/tmp/GatewayWebHdfsFuncTest/testBasicHdfsUseCase/dir?user.name=hdfs&op=MKDIRS" ); +// matcher = new Matcher<String>( template, "test-value" ); +// match = matcher.match( input ); +// assertThat( (String)match.getValue(), is( "test-value" ) ); +// +// template = Parser.parse( "*://*:*/**/webhdfs/v1/{path=**}?{**=*}" ); +// input = Parser.parse( "http://localhost:53221/gateway/cluster/webhdfs/v1/tmp/GatewayWebHdfsFuncTest/testBasicHdfsUseCase/dir?user.name=hdfs&op=MKDIRS" ); +// matcher = new Matcher<String>( template, "test-value-2" ); +// match = matcher.match( input ); +// assertThat( (String)match.getValue(), is( "test-value-2" ) ); +// +// stringMatcher = new Matcher<String>(); +// template = Parser.parse( "*://*:*/**/webhdfs/data/v1/{path=**}?host={host=*}&port={port=*}&{**=*}" ); +// stringMatcher.add( template, "test-value-C" ); +// template = Parser.parse( "*://*:*/**/webhdfs/v1/{path=**}?{**=*}" ); +// stringMatcher.add( template, "test-value-B" ); +// input = Parser.parse( "http://localhost:53221/gateway/cluster/webhdfs/v1/tmp/GatewayWebHdfsFuncTest/testBasicHdfsUseCase/dir?user.name=hdfs&op=MKDIRS" ); +// match = stringMatcher.match( input ); +// assertThat( match.getValue(), notNullValue() ); +// assertThat( (String)match.getValue(), is( "test-value-B" ) ); + + // This is just a reverse of the above. The order caused a bug. + stringMatcher = new Matcher<String>(); + template = Parser.parse( "*://*:*/**/webhdfs/v1/{path=**}?{**=*}" ); + stringMatcher.add( template, "test-value-B" ); + template = Parser.parse( "*://*:*/**/webhdfs/data/v1/{path=**}?host={host=*}&port={port=*}&{**=*}" ); + stringMatcher.add( template, "test-value-C" ); + input = Parser.parse( "http://localhost:53221/gateway/cluster/webhdfs/v1/tmp/GatewayWebHdfsFuncTest/testBasicHdfsUseCase/dir?user.name=hdfs&op=MKDIRS" ); + match = stringMatcher.match( input ); + assertThat( match.getValue(), notNullValue() ); + assertThat( (String)match.getValue(), is( "test-value-B" ) ); + + } + + @Test + public void testPathExtraction() throws Exception { + Template template; + Template input; + Matcher<?> matcher; + Matcher<?>.Match match; + Params params; + + template = Parser.parse( "{path-queryParam}" ); + input = Parser.parse( "path-value" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params, notNullValue() ); + assertThat( params.getNames().size(), equalTo( 1 ) ); + assertThat( params.getNames(), hasItem( "path-queryParam" ) ); + assertThat( params.resolve( "path-queryParam" ).size(), equalTo( 1 ) ); + assertThat( params.resolve( "path-queryParam" ), hasItem( "path-value" ) ); + + template = Parser.parse( "/some-path/{path-queryParam}" ); + input = Parser.parse( "/some-path/path-value" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params, notNullValue() ); + assertThat( params.getNames().size(), equalTo( 1 ) ); + assertThat( params.getNames(), hasItem( "path-queryParam" ) ); + assertThat( params.resolve( "path-queryParam" ).size(), equalTo( 1 ) ); + assertThat( params.resolve( "path-queryParam" ), hasItem( "path-value" ) ); + + template = Parser.parse( "/some-path/{path-queryParam}/some-other-path" ); + input = Parser.parse( "/some-path/path-value/some-other-path" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params, notNullValue() ); + assertThat( params.getNames().size(), equalTo( 1 ) ); + assertThat( params.getNames(), hasItem( "path-queryParam" ) ); + assertThat( params.resolve( "path-queryParam" ).size(), equalTo( 1 ) ); + assertThat( params.resolve( "path-queryParam" ), hasItem( "path-value" ) ); + + template = Parser.parse( "{path=**}" ); + input = Parser.parse( "A/B" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params, notNullValue() ); + assertThat( params.getNames().size(), equalTo( 1 ) ); + assertThat( params.getNames(), hasItem( "path" ) ); + assertThat( params.resolve( "path" ).size(), equalTo( 2 ) ); + assertThat( params.resolve( "path" ), hasItem( "A" ) ); + assertThat( params.resolve( "path" ), hasItem( "B" ) ); + + template = Parser.parse( "/top/{mid=**}/end" ); + input = Parser.parse( "/top/A/B/end" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params, notNullValue() ); + assertThat( params.getNames().size(), equalTo( 1 ) ); + assertThat( params.getNames(), hasItem( "mid" ) ); + assertThat( params.resolve( "mid" ).size(), equalTo( 2 ) ); + assertThat( params.resolve( "mid" ), hasItem( "A" ) ); + assertThat( params.resolve( "mid" ), hasItem( "B" ) ); + + template = Parser.parse( "*://*:*/{path=**}?{**}" ); + input = Parser.parse( "http://host:port/pathA/pathB" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params.resolve( "path" ), hasItem( "pathA" ) ); + assertThat( params.resolve( "path" ), hasItem( "pathB" ) ); + assertThat( params.resolve( "path" ).size(), is( 2 ) ); + + template = Parser.parse( "*://*:*/{path=**}?{**}" ); + input = Parser.parse( "http://host:port/pathA/pathB" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params.resolve( "path" ), hasItem( "pathA" ) ); + assertThat( params.resolve( "path" ), hasItem( "pathB" ) ); + assertThat( params.resolve( "path" ).size(), is( 2 ) ); + + template = Parser.parse( "*://*:*/{path=**}?{**}" ); + input = Parser.parse( "http://host:port/pathA/pathB" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params.resolve( "path" ), hasItem( "pathA" ) ); + assertThat( params.resolve( "path" ), hasItem( "pathB" ) ); + assertThat( params.resolve( "path" ).size(), is( 2 ) ); + } + + @Test + public void testQueryExtraction() throws Exception { + Template template; + Template input; + Matcher<?> matcher; + Matcher<?>.Match match; + Params params; + + template = Parser.parse( "?query-queryParam={queryParam-name}" ); + input = Parser.parse( "?query-queryParam=queryParam-value" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params, notNullValue() ); + assertThat( params.getNames().size(), equalTo( 1 ) ); + assertThat( params.getNames(), hasItem( "queryParam-name" ) ); + assertThat( params.resolve( "queryParam-name" ).size(), equalTo( 1 ) ); + assertThat( params.resolve( "queryParam-name" ), hasItem( "queryParam-value" ) ); + + template = Parser.parse( "?query-queryParam={queryParam-name}" ); + input = Parser.parse( "?query-queryParam=queryParam-value" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params, notNullValue() ); + assertThat( params.getNames().size(), equalTo( 1 ) ); + assertThat( params.getNames(), hasItem( "queryParam-name" ) ); + assertThat( params.resolve( "queryParam-name" ).size(), equalTo( 1 ) ); + assertThat( params.resolve( "queryParam-name" ), hasItem( "queryParam-value" ) ); + } + + @Test + public void testEdgeCaseExtraction() throws Exception { + Template template; + Template input; + Matcher<?> matcher; + Matcher<?>.Match match; + Params params; + + template = Parser.parse( "" ); + input = Parser.parse( "" ); + matcher = new Matcher<Void>( template, null ); + match = matcher.match( input ); + params = match.getParams(); + assertThat( params, notNullValue() ); + assertThat( params.getNames().size(), equalTo( 0 ) ); + } + +} http://git-wip-us.apache.org/repos/asf/knox/blob/4ca54c5a/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index d99c952..d7281ff 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,7 @@ <module>gateway-release</module> <module>gateway-test</module> <module>hsso-release</module> + <module>gateway-service-vault</module> </modules> <properties> @@ -425,6 +426,11 @@ </dependency> <dependency> <groupId>${gateway-group}</groupId> + <artifactId>gateway-service-vault</artifactId> + <version>${gateway-version}</version> + </dependency> + <dependency> + <groupId>${gateway-group}</groupId> <artifactId>gateway-service-as</artifactId> <version>${gateway-version}</version> </dependency> @@ -497,12 +503,12 @@ <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> - <version>2.4.1</version> + <version>2.6</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> - <version>2.4</version> + <version>2.6</version> </dependency> <dependency>
