You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2017/09/01 13:17:22 UTC
[24/64] [partial] knox git commit: KNOX-998 - Refactoring save 1
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterGroupDescriptorBase.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterGroupDescriptorBase.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterGroupDescriptorBase.java
new file mode 100644
index 0000000..bc1dd91
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterGroupDescriptorBase.java
@@ -0,0 +1,52 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterApplyDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterGroupDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterPathDescriptor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class UrlRewriteFilterGroupDescriptorBase
+ extends UrlRewriteFilterSelectorDescriptorBase
+ implements UrlRewriteFilterGroupDescriptor {
+
+ private List<UrlRewriteFilterPathDescriptor> selectors = new ArrayList<UrlRewriteFilterPathDescriptor>();
+
+ @Override
+ public List<UrlRewriteFilterPathDescriptor> getSelectors() {
+ return selectors;
+ }
+
+ @Override
+ public void addSelector( UrlRewriteFilterPathDescriptor selector ) {
+ this.selectors.add( selector );
+ }
+
+ @Override
+ public UrlRewriteFilterApplyDescriptor addApply( String path, String rule ) {
+ UrlRewriteFilterApplyDescriptor apply = new UrlRewriteFilterApplyDescriptorImpl();
+ apply.path( path );
+ apply.rule( rule );
+ addSelector( apply );
+ return apply;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterReader.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterReader.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterReader.java
new file mode 100644
index 0000000..b512a8c
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterReader.java
@@ -0,0 +1,39 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import java.util.regex.Pattern;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterPathDescriptor;
+
+
+public interface UrlRewriteFilterReader {
+
+ public String filterValueString( String name, String value, String rule );
+
+ public static class RegexCompiler implements UrlRewriteFilterPathDescriptor.Compiler<Pattern> {
+ @Override
+ public Pattern compile( String expression, Pattern compiled ) {
+ if( compiled != null ) {
+ return compiled;
+ } else {
+ return Pattern.compile( expression );
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterScopeDescriptorImpl.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterScopeDescriptorImpl.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterScopeDescriptorImpl.java
new file mode 100644
index 0000000..bc64870
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterScopeDescriptorImpl.java
@@ -0,0 +1,25 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterScopeDescriptor;
+
+public class UrlRewriteFilterScopeDescriptorImpl
+ extends UrlRewriteFilterGroupDescriptorBase
+ implements UrlRewriteFilterScopeDescriptor {
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterSelectorDescriptorBase.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterSelectorDescriptorBase.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterSelectorDescriptorBase.java
new file mode 100644
index 0000000..3994128
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFilterSelectorDescriptorBase.java
@@ -0,0 +1,64 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterPathDescriptor;
+
+public class UrlRewriteFilterSelectorDescriptorBase<T> implements UrlRewriteFilterPathDescriptor<T> {
+
+ private String path;
+ private Object compiledPath;
+
+ @Override
+ public String path() {
+ return path;
+ }
+
+ @Override
+ public T path( String path ) {
+ this.path = path;
+ return (T)this;
+ }
+
+ public void setPath( String path ) {
+ this.path = path;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public <C> C compiledPath() {
+ return (C)compiledPath;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T compiledPath( Object compiledPath ) {
+ this.compiledPath = compiledPath;
+ return (T)this;
+ }
+
+ @Override
+ public <C> C compiledPath( Compiler<C> compiler ) {
+ compiledPath = compiler.compile( path, (C)compiledPath );
+ return (C)compiledPath;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFunctionProcessorFactory.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFunctionProcessorFactory.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFunctionProcessorFactory.java
new file mode 100644
index 0000000..def7a24
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteFunctionProcessorFactory.java
@@ -0,0 +1,113 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptorFactory;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+public abstract class UrlRewriteFunctionProcessorFactory {
+
+ private static final Map<Class<? extends UrlRewriteFunctionDescriptor>,Map<String,Class<? extends UrlRewriteFunctionProcessor>>> MAP
+ = loadProcessors();
+
+ private UrlRewriteFunctionProcessorFactory() {
+ }
+
+ public static UrlRewriteFunctionProcessor create( String name, UrlRewriteFunctionDescriptor descriptor )
+ throws IllegalAccessException, InstantiationException {
+ UrlRewriteFunctionProcessor processor;
+ if( descriptor == null ) {
+ descriptor = UrlRewriteFunctionDescriptorFactory.create( name );
+ }
+ Map<String,Class<? extends UrlRewriteFunctionProcessor>> typeMap;
+ typeMap = MAP.get( descriptor.getClass() );
+ if( typeMap == null ) {
+ Class<? extends UrlRewriteFunctionDescriptor> descriptorInterface = getDescriptorInterface( descriptor );
+ typeMap = MAP.get( descriptorInterface );
+ }
+ if( typeMap == null ) {
+ throw new IllegalArgumentException( descriptor.getClass().getName() );
+ } else {
+ Class<? extends UrlRewriteFunctionProcessor> processorClass = typeMap.get( name );
+ if( processorClass == null ) {
+ throw new IllegalArgumentException( name );
+ } else {
+ processor = processorClass.newInstance();
+ }
+ }
+ return processor;
+ }
+
+ private static Map<Class<? extends UrlRewriteFunctionDescriptor>,Map<String,Class<? extends UrlRewriteFunctionProcessor>>> loadProcessors() {
+ Map<Class<? extends UrlRewriteFunctionDescriptor>,Map<String,Class<? extends UrlRewriteFunctionProcessor>>> descriptorMap
+ = new HashMap<>();
+ ServiceLoader<UrlRewriteFunctionProcessor> processors = ServiceLoader.load( UrlRewriteFunctionProcessor.class );
+ for( UrlRewriteFunctionProcessor processor : processors ) {
+ Class<? extends UrlRewriteFunctionDescriptor> descriptorInterface = getDescriptorInterface( processor );
+ Map<String,Class<? extends UrlRewriteFunctionProcessor>> typeMap = descriptorMap.get( descriptorInterface );
+ if( typeMap == null ) {
+ typeMap = new HashMap<>();
+ descriptorMap.put( descriptorInterface, typeMap );
+ }
+ String functionName = processor.name();
+ typeMap.put( functionName, processor.getClass() );
+ }
+ return descriptorMap;
+ }
+
+ private static Class<? extends UrlRewriteFunctionDescriptor> getDescriptorInterface(
+ UrlRewriteFunctionDescriptor descriptor ) {
+ Class<? extends UrlRewriteFunctionDescriptor> descriptorClass = null;
+ for( Type interfaceType : descriptor.getClass().getGenericInterfaces() ) {
+ Class genericClass = (Class)interfaceType;
+ if( UrlRewriteFunctionDescriptor.class.isAssignableFrom( genericClass ) ) {
+ descriptorClass = uncheckedDescriptorClassCast( genericClass );
+ break;
+ }
+ }
+ return descriptorClass;
+ }
+
+ private static Class<? extends UrlRewriteFunctionDescriptor> getDescriptorInterface(
+ UrlRewriteFunctionProcessor processor ) {
+ Class<? extends UrlRewriteFunctionDescriptor> descriptorClass = null;
+ Class<? extends UrlRewriteFunctionProcessor> processorClass = processor.getClass();
+ for( Type interfaceType : processorClass.getGenericInterfaces() ) {
+ if( UrlRewriteFunctionProcessor.class.isAssignableFrom(
+ (Class)((ParameterizedType)interfaceType).getRawType() ) ) {
+ ParameterizedType interfaceClass = (ParameterizedType)interfaceType;
+ descriptorClass = uncheckedDescriptorClassCast( interfaceClass.getActualTypeArguments()[ 0 ] );
+ break;
+ }
+ }
+ return descriptorClass;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Class<? extends UrlRewriteFunctionDescriptor> uncheckedDescriptorClassCast( Type type ) {
+ return (Class<? extends UrlRewriteFunctionDescriptor>)type;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRequest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRequest.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRequest.java
new file mode 100644
index 0000000..f91035c
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRequest.java
@@ -0,0 +1,265 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.AbstractGatewayFilter;
+import org.apache.knox.gateway.filter.GatewayRequestWrapper;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterContentDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteRulesDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteServletContextListener;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteServletFilter;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteStreamFilterFactory;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriter;
+import org.apache.knox.gateway.filter.rewrite.i18n.UrlRewriteMessages;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.util.MimeTypes;
+import org.apache.knox.gateway.util.urltemplate.Parser;
+import org.apache.knox.gateway.util.urltemplate.Resolver;
+import org.apache.knox.gateway.util.urltemplate.Template;
+
+import javax.activation.MimeType;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+
+import static org.apache.knox.gateway.filter.rewrite.impl.UrlRewriteUtil.pickFirstRuleWithEqualsIgnoreCasePathMatch;
+
+public class UrlRewriteRequest extends GatewayRequestWrapper implements Resolver {
+
+ private static final UrlRewriteMessages LOG = MessagesFactory.get( UrlRewriteMessages.class );
+ private static final String[] EMPTY_STRING_ARRAY = new String[]{};
+
+ private FilterConfig config;
+ private UrlRewriter rewriter;
+ private String urlRuleName;
+ private String bodyFilterName;
+ private String headersFilterName;
+ private UrlRewriteFilterContentDescriptor headersFilterConfig;
+ private String cookiesFilterName;
+
+ /**
+ * Constructs a request object wrapping the given request.
+ *
+ * @throws IllegalArgumentException if the request is null
+ */
+ public UrlRewriteRequest( FilterConfig config, HttpServletRequest request ) throws IOException {
+ super( request );
+ this.config = config;
+ this.rewriter = UrlRewriteServletContextListener.getUrlRewriter( config.getServletContext() );
+ this.urlRuleName = config.getInitParameter( UrlRewriteServletFilter.REQUEST_URL_RULE_PARAM );
+ this.bodyFilterName = config.getInitParameter( UrlRewriteServletFilter.REQUEST_BODY_FILTER_PARAM );
+ this.headersFilterName = config.getInitParameter( UrlRewriteServletFilter.REQUEST_HEADERS_FILTER_PARAM );
+ this.headersFilterConfig = getRewriteFilterConfig( headersFilterName, UrlRewriteServletFilter.HEADERS_MIME_TYPE );
+ this.cookiesFilterName = config.getInitParameter( UrlRewriteServletFilter.REQUEST_COOKIES_FILTER_PARAM );
+ }
+
+ private Template getSourceUrl() {
+ Template urlTemplate;
+ //KNOX-439[
+ //StringBuffer urlString = super.getRequestURL();
+ StringBuffer urlString = new StringBuffer( 128 );
+ urlString.append( getScheme() );
+ urlString.append( "://" );
+ urlString.append( getServerName() );
+ urlString.append( ":" );
+ urlString.append( getServerPort() );
+ urlString.append( super.getRequestURI() );
+ //]
+ String queryString = super.getQueryString();
+ if( queryString != null ) {
+ urlString.append( '?' );
+ urlString.append( queryString );
+ }
+ try {
+ urlTemplate = Parser.parseLiteral( urlString.toString() );
+ } catch( URISyntaxException e ) {
+ LOG.failedToParseValueForUrlRewrite( urlString.toString() );
+ // Shouldn't be possible given that the URL is constructed from parts of an existing URL.
+ urlTemplate = null;
+ }
+ return urlTemplate;
+ }
+
+ // Note: Source url was added to the request attributes by the GatewayFilter doFilter method.
+ private Template getTargetUrl() {
+ boolean rewriteRequestUrl = true;
+ Template targetUrl;
+ if( rewriteRequestUrl ) {
+ targetUrl = (Template)getAttribute( AbstractGatewayFilter.TARGET_REQUEST_URL_ATTRIBUTE_NAME );
+ if( targetUrl == null ) {
+ Template sourceUrl = getSourceUrl();
+ targetUrl = rewriter.rewrite( this, sourceUrl, UrlRewriter.Direction.IN, urlRuleName );
+ setAttribute( AbstractGatewayFilter.TARGET_REQUEST_URL_ATTRIBUTE_NAME, targetUrl );
+ }
+ } else {
+ targetUrl = (Template)getAttribute( AbstractGatewayFilter.SOURCE_REQUEST_URL_ATTRIBUTE_NAME );
+ }
+ return targetUrl;
+ }
+
+ private String[] splitTargetUrl( Template url ) {
+ if( url == null ) {
+ return EMPTY_STRING_ARRAY;
+ } else {
+ String s = url.toString();
+ return s.split( "\\?" );
+ }
+ }
+
+ @Override
+ public StringBuffer getRequestURL() {
+ return new StringBuffer( getRequestURI() );
+ }
+
+ //TODO: I think this method is implemented wrong based on the HttpServletRequest.getRequestURI docs.
+ // It should not include the scheme or authority parts.
+ @Override
+ public String getRequestURI() {
+ String[] split = splitTargetUrl( getTargetUrl() );
+ if( split.length > 0 ) {
+ return split[0];
+ } else {
+ return "";
+ }
+ }
+
+ @Override
+ public String getQueryString() {
+ String[] split = splitTargetUrl( getTargetUrl() );
+ if( split.length > 1 ) {
+ try {
+ return URLDecoder.decode(split[1], "UTF-8");
+ } catch ( UnsupportedEncodingException e ) {
+ LOG.failedToDecodeQueryString(split[1], e);
+ return split[1];
+ }
+ } else {
+ return null;
+ }
+ }
+
+ private String rewriteValue( UrlRewriter rewriter, String value, String rule ) {
+ try {
+ Template input = Parser.parseLiteral( value );
+ Template output = rewriter.rewrite( this, input, UrlRewriter.Direction.IN, rule );
+ value = output.getPattern();
+ } catch( URISyntaxException e ) {
+ LOG.failedToParseValueForUrlRewrite( value );
+ }
+ return value;
+ }
+
+ @Override
+ public String getHeader( String name ) {
+ String value = super.getHeader( name );
+ if( value != null ) {
+ value = rewriteValue( rewriter, super.getHeader( name ), pickFirstRuleWithEqualsIgnoreCasePathMatch( headersFilterConfig, name ) );
+ }
+ return value;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Enumeration getHeaders( String name ) {
+ return new EnumerationRewriter( rewriter, super.getHeaders( name ), pickFirstRuleWithEqualsIgnoreCasePathMatch( headersFilterConfig, name ) );
+ }
+
+ @Override
+ public List<String> resolve( String name ) {
+ return Arrays.asList( config.getInitParameter( name ) );
+ }
+
+ private class EnumerationRewriter implements Enumeration<String> {
+
+ private UrlRewriter rewriter;
+ private Enumeration<String> delegate;
+ private String rule;
+
+ private EnumerationRewriter( UrlRewriter rewriter, Enumeration<String> delegate, String rule ) {
+ this.rewriter = rewriter;
+ this.delegate = delegate;
+ this.rule = rule;
+ }
+
+ @Override
+ public boolean hasMoreElements() {
+ return delegate.hasMoreElements();
+ }
+
+ @Override
+ public String nextElement() {
+ return rewriteValue( rewriter, delegate.nextElement(), rule );
+ }
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ ServletInputStream input = super.getInputStream();
+ if( getContentLength() != 0 ) {
+ MimeType mimeType = getMimeType();
+ UrlRewriteFilterContentDescriptor filterContentConfig = getRewriteFilterConfig( bodyFilterName, mimeType );
+ if (filterContentConfig != null) {
+ String asType = filterContentConfig.asType();
+ if ( asType != null && asType.trim().length() > 0 ) {
+ mimeType = MimeTypes.create(asType, getCharacterEncoding());
+ }
+ }
+ InputStream stream = UrlRewriteStreamFilterFactory.create( mimeType, null, input, rewriter, this, UrlRewriter.Direction.IN, filterContentConfig );
+ input = new UrlRewriteRequestStream( stream );
+ }
+ return input;
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ return new BufferedReader( new InputStreamReader( getInputStream(), getCharacterEncoding() ) );
+ }
+
+ @Override
+ public int getContentLength() {
+ // The rewrite might change the content length so return the default of -1 to indicate the length is unknown.
+ int contentLength = super.getContentLength();
+ if( contentLength > 0 ) {
+ contentLength = -1;
+ }
+ return contentLength;
+ }
+
+ private UrlRewriteFilterContentDescriptor getRewriteFilterConfig( String filterName, MimeType mimeType ) {
+ UrlRewriteFilterContentDescriptor filterContentConfig = null;
+ UrlRewriteRulesDescriptor rewriteConfig = rewriter.getConfig();
+ if( rewriteConfig != null ) {
+ UrlRewriteFilterDescriptor filterConfig = rewriteConfig.getFilter( filterName );
+ if( filterConfig != null ) {
+ filterContentConfig = filterConfig.getContent( mimeType );
+ }
+ }
+ return filterContentConfig;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRequestStream.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRequestStream.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRequestStream.java
new file mode 100644
index 0000000..5995317
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRequestStream.java
@@ -0,0 +1,40 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.knox.gateway.servlet.SynchronousServletInputStreamAdapter;
+
+//TODO: This needs to be coded much more efficiently!
+public class UrlRewriteRequestStream extends
+ SynchronousServletInputStreamAdapter {
+
+ private InputStream stream;
+
+ public UrlRewriteRequestStream( InputStream stream ) {
+ this.stream = stream;
+ }
+
+ @Override
+ public int read() throws IOException {
+ return stream.read();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteResponse.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteResponse.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteResponse.java
new file mode 100644
index 0000000..d451c26
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteResponse.java
@@ -0,0 +1,331 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.GatewayResponseWrapper;
+import org.apache.knox.gateway.filter.ResponseStreamer;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterContentDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteServletContextListener;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteServletFilter;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteStreamFilterFactory;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriter;
+import org.apache.knox.gateway.filter.rewrite.i18n.UrlRewriteMessages;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.util.MimeTypes;
+import org.apache.knox.gateway.util.Urls;
+import org.apache.knox.gateway.util.urltemplate.Params;
+import org.apache.knox.gateway.util.urltemplate.Parser;
+import org.apache.knox.gateway.util.urltemplate.Template;
+import org.apache.commons.io.IOUtils;
+
+import javax.activation.MimeType;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import java.util.zip.ZipException;
+
+import static org.apache.knox.gateway.filter.rewrite.impl.UrlRewriteUtil.getRewriteFilterConfig;
+import static org.apache.knox.gateway.filter.rewrite.impl.UrlRewriteUtil.pickFirstRuleWithEqualsIgnoreCasePathMatch;
+
+/**
+ *
+ */
+public class UrlRewriteResponse extends GatewayResponseWrapper implements Params,
+ ResponseStreamer {
+
+ private static final UrlRewriteMessages LOG = MessagesFactory.get( UrlRewriteMessages.class );
+
+ // An 8K buffer better matches the underlying buffer sizes.
+ // Testing with 16K made no appreciable difference.
+ private static final int STREAM_BUFFER_SIZE = 8 * 1024;
+
+ private static final Set<String> IGNORE_HEADER_NAMES = new HashSet<>();
+ static {
+ IGNORE_HEADER_NAMES.add( "Content-Length" );
+ }
+
+ private static final String REQUEST_PARAM_PREFIX = "request.";
+ private static final String CLUSTER_PARAM_PREFIX = "cluster.";
+ private static final String GATEWAY_PARAM_PREFIX = "gateway.";
+ public static final String INBOUND_QUERY_PARAM_PREFIX = "query.param.";
+
+ private UrlRewriter rewriter;
+ private FilterConfig config;
+ private HttpServletRequest request;
+ private HttpServletResponse response;
+ private ServletOutputStream output;
+ private String bodyFilterName;
+ private String headersFilterName;
+ private UrlRewriteFilterContentDescriptor headersFilterConfig;
+ private String cookiesFilterName;
+ private String xForwardedHostname;
+ private String xForwardedPort;
+ private String xForwardedScheme;
+
+ public UrlRewriteResponse( FilterConfig config, HttpServletRequest request, HttpServletResponse response )
+ throws IOException {
+ super( response );
+ this.rewriter = UrlRewriteServletContextListener.getUrlRewriter( config.getServletContext() );
+ this.config = config;
+ this.request = request;
+ this.response = response;
+ this.output = null;
+ getXForwardedHeaders();
+ this.bodyFilterName = config.getInitParameter( UrlRewriteServletFilter.RESPONSE_BODY_FILTER_PARAM );
+ this.headersFilterName = config.getInitParameter( UrlRewriteServletFilter.RESPONSE_HEADERS_FILTER_PARAM );
+ this.headersFilterConfig = getRewriteFilterConfig( rewriter.getConfig(), headersFilterName, UrlRewriteServletFilter.HEADERS_MIME_TYPE );
+ this.cookiesFilterName = config.getInitParameter( UrlRewriteServletFilter.RESPONSE_COOKIES_FILTER_PARAM );
+ }
+
+ protected boolean ignoreHeader( String name ) {
+ return IGNORE_HEADER_NAMES.contains( name );
+ }
+
+ private String rewriteValue( String value, String rule ) {
+ try {
+ Template input = Parser.parseLiteral( value );
+ Template output = rewriter.rewrite( this, input, UrlRewriter.Direction.OUT, rule );
+ if( output != null ) {
+ value = output.toString();
+ }
+ } catch( URISyntaxException e ) {
+ LOG.failedToParseValueForUrlRewrite( value );
+ }
+ return value;
+ }
+
+ // Ignore the Content-Length from the dispatch respond since the respond body may be rewritten.
+ @Override
+ public void setHeader( String name, String value ) {
+ if( !ignoreHeader( name) ) {
+ value = rewriteValue( value, pickFirstRuleWithEqualsIgnoreCasePathMatch( headersFilterConfig, name ) );
+ super.setHeader( name, value );
+ }
+ }
+
+ // Ignore the Content-Length from the dispatch respond since the respond body may be rewritten.
+ @Override
+ public void addHeader( String name, String value ) {
+ if( !ignoreHeader( name ) ) {
+ String rule = pickFirstRuleWithEqualsIgnoreCasePathMatch( headersFilterConfig, name );
+ value = rewriteValue( value, rule );
+ super.addHeader( name, value );
+ }
+ }
+
+ @Override
+ public OutputStream getRawOutputStream() throws IOException {
+ return response.getOutputStream();
+ }
+
+ @Override
+ public void streamResponse( InputStream input, OutputStream output ) throws IOException {
+ InputStream inStream;
+ OutputStream outStream;
+ boolean isGzip = false;
+ BufferedInputStream inBuffer = new BufferedInputStream(input);
+ try {
+ // Use this way to check whether the input stream is gzip compressed, in case
+ // the content encoding header is unknown, as it could be unset in inbound response
+ inBuffer.mark(STREAM_BUFFER_SIZE);
+ inStream = new GZIPInputStream(inBuffer);
+ isGzip = true;
+ } catch (ZipException e) {
+ inBuffer.reset();
+ inStream = inBuffer;
+ } catch (IOException e) {
+ inBuffer.reset();
+ inStream = inBuffer;
+ }
+
+ MimeType mimeType = getMimeType();
+ UrlRewriteFilterContentDescriptor filterContentConfig =
+ getRewriteFilterConfig( rewriter.getConfig(), bodyFilterName, mimeType );
+ if (filterContentConfig != null) {
+ String asType = filterContentConfig.asType();
+ if ( asType != null && asType.trim().length() > 0 ) {
+ mimeType = MimeTypes.create(asType, getCharacterEncoding());
+ }
+ }
+ InputStream filteredInput = UrlRewriteStreamFilterFactory.create(
+ mimeType, null, inStream, rewriter, this, UrlRewriter.Direction.OUT, filterContentConfig );
+ outStream = (isGzip) ? new GZIPOutputStream(output) : output;
+ IOUtils.copyLarge( filteredInput, outStream, new byte[STREAM_BUFFER_SIZE] );
+ //KNOX-685: outStream.flush();
+ outStream.close();
+ }
+
+ //TODO: Need to buffer the output here and when it is closed, rewrite it and then write the result to the stream.
+ // This should only happen if the caller isn't using the streaming model.
+ @Override
+ public ServletOutputStream getOutputStream() throws IOException {
+ if( output == null ) {
+ output = new UrlRewriteResponseStream( this );
+ }
+ return output;
+ }
+
+ @Override
+ public Set<String> getNames() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public List<String> resolve( String name ) {
+ if( name.startsWith( REQUEST_PARAM_PREFIX ) ) {
+ return Arrays.asList( getRequestParam( name.substring( REQUEST_PARAM_PREFIX.length() ) ) );
+ } else if ( name.startsWith( GATEWAY_PARAM_PREFIX ) ) {
+ return Arrays.asList( getGatewayParam( name.substring( GATEWAY_PARAM_PREFIX.length() ) ) );
+ } else if ( name.startsWith( CLUSTER_PARAM_PREFIX ) ) {
+ return Arrays.asList( getClusterParam( name.substring( GATEWAY_PARAM_PREFIX.length() ) ) );
+ } else if ( name.startsWith( INBOUND_QUERY_PARAM_PREFIX ) ) {
+ return getInboundQueryParam(name.substring(INBOUND_QUERY_PARAM_PREFIX.length()));
+ } else {
+ return Arrays.asList( config.getInitParameter( name ) );
+ }
+ }
+
+ // KNOX-464: Doing this because Jetty only returns the string version of the IP address for request.getLocalName().
+ // Hopefully the local hostname will be cached so this will not be a significant performance hit.
+ // Previously this was an inline request.getServerName() but this ended up mixing the hostname from the Host header
+ // and the local port which was making load balancer configuration difficult if not impossible.
+ private String getRequestLocalHostName() {
+ String hostName = request.getLocalName();
+ try {
+ hostName = InetAddress.getByName( hostName ).getHostName();
+ } catch( UnknownHostException e ) {
+ // Ignore it and use the original hostname.
+ }
+ return hostName;
+ }
+
+ private String getGatewayParam( String name ) {
+ if( "url".equals( name ) ) {
+ if( xForwardedPort == null ) {
+ return xForwardedScheme + "://" + xForwardedHostname + request.getContextPath();
+ } else {
+ return xForwardedScheme + "://" + xForwardedHostname + ":" + xForwardedPort + request.getContextPath();
+ }
+ } else if( "scheme".equals( name ) ) {
+ return xForwardedScheme;
+ } else if( "host".equals( name ) ) {
+ return xForwardedHostname;
+ } else if( "port".equals( name ) ) {
+ return xForwardedPort;
+ } else if( "addr".equals( name ) || "address".equals( name ) ) {
+ if( xForwardedPort == null ) {
+ return xForwardedHostname;
+ } else {
+ return xForwardedHostname + ":" + xForwardedPort;
+ }
+ } else if( "path".equals( name ) ) {
+ return request.getContextPath();
+ } else {
+ return null;
+ }
+ }
+
+ private String getClusterParam( String name ) {
+ if( "name".equals( name ) ) {
+ return config.getServletContext().getServletContextName();
+ } else {
+ return null;
+ }
+ }
+
+ private List <String> getInboundQueryParam(String name ){
+ List <String> inboundHosts = null;
+ if( this.request!=null )
+ inboundHosts =
+ Arrays.asList( this.request.getParameterValues(name));
+ return inboundHosts;
+ }
+
+ private String getRequestParam( String name ) {
+ if( "host".equals( name ) ) {
+ return request.getServerName();
+ } else if ( "port".equals( name ) ) {
+ return Integer.toString( request.getLocalPort() );
+ } else if ( "scheme".equals( name ) ) {
+ return request.getScheme();
+ } else if ( "context-path".equals( name ) ) {
+ return Urls.stripLeadingSlash( request.getContextPath() );
+ } else {
+ config.getServletContext().getServletContextName();
+ return null;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public String encodeUrl( String url ) {
+ return this.encodeURL( url );
+ }
+
+ //TODO: Route these through the rewriter.
+ public String encodeURL( String url ) {
+ throw new UnsupportedOperationException();
+ }
+
+ @SuppressWarnings("deprecation")
+ public String encodeRedirectUrl( String url ) {
+ return this.encodeRedirectURL( url );
+ }
+
+ //TODO: Route these through the rewriter.
+ public String encodeRedirectURL( String url ) {
+ throw new UnsupportedOperationException();
+ }
+
+ private void getXForwardedHeaders() {
+ xForwardedHostname = request.getHeader( "X-Forwarded-Host" );
+ xForwardedPort = request.getHeader( "X-Forwarded-Port" );
+ xForwardedScheme = request.getHeader( "X-Forwarded-Proto" );
+ if ( xForwardedScheme == null ) {
+ xForwardedScheme = request.getScheme();
+ }
+ if ( xForwardedHostname != null ) {
+ int separator = xForwardedHostname.indexOf( ":" );
+ if ( separator > 0 ) {
+ //a specific port in the forwarded host wins
+ xForwardedPort = xForwardedHostname.substring(separator + 1, xForwardedHostname.length());
+ xForwardedHostname = xForwardedHostname.substring( 0, separator );
+ }
+ } else {
+ xForwardedHostname = getRequestLocalHostName();
+ xForwardedPort = Integer.toString( request.getLocalPort() );
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteResponseStream.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteResponseStream.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteResponseStream.java
new file mode 100644
index 0000000..300a8b4
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteResponseStream.java
@@ -0,0 +1,54 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.GatewayResponse;
+import org.apache.knox.gateway.servlet.SynchronousServletOutputStreamAdapter;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+//TODO: This needs to be coded much more efficiently!
+public class UrlRewriteResponseStream extends
+ SynchronousServletOutputStreamAdapter {
+
+ private static final int DEFAULT_BUFFER_SIZE = 1024;
+
+ private GatewayResponse response;
+ private ByteArrayOutputStream buffer;
+
+ public UrlRewriteResponseStream( GatewayResponse response ) {
+ this.response = response;
+ this.buffer = new ByteArrayOutputStream( DEFAULT_BUFFER_SIZE );
+ }
+
+ @Override
+ public void write( int b ) throws IOException {
+ buffer.write( b );
+ }
+
+ @Override
+ public void close() throws IOException {
+ InputStream stream = new ByteArrayInputStream( buffer.toByteArray() );
+ response.streamResponse( stream ) ;
+ stream.close();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleDescriptorImpl.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleDescriptorImpl.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleDescriptorImpl.java
new file mode 100644
index 0000000..d86c670
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleDescriptorImpl.java
@@ -0,0 +1,195 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteRuleDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteStepDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriter;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteFlowDescriptorBase;
+import org.apache.knox.gateway.util.urltemplate.Parser;
+import org.apache.knox.gateway.util.urltemplate.Template;
+
+import java.net.URISyntaxException;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+public class UrlRewriteRuleDescriptorImpl extends UrlRewriteFlowDescriptorBase<UrlRewriteRuleDescriptor>
+ implements UrlRewriteRuleDescriptor {
+
+ private String name;
+ private String scope;
+ private String pattern;
+ private Template template;
+ private EnumSet<UrlRewriter.Direction> directions;
+
+ public UrlRewriteRuleDescriptorImpl() {
+ super( "rule" );
+ }
+
+ @Override
+ public String name() {
+ return this.name;
+ }
+
+ @Override
+ public UrlRewriteRuleDescriptor name( String name ) {
+ this.name = name;
+ return this;
+ }
+
+ public void setName( String name ) {
+ name( name );
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ public void setScope(String scope) {
+ scope( scope );
+ }
+
+ @Override
+ public String scope() {
+ return scope;
+ }
+
+ @Override
+ public UrlRewriteStepDescriptor scope( String scope ) {
+ this.scope = scope;
+ return this;
+ }
+
+ @Override
+ public EnumSet<UrlRewriter.Direction> directions() {
+ return directions;
+ }
+
+ @Override
+ public UrlRewriteRuleDescriptor directions( String directions ) {
+ this.directions = parseDirections( directions );
+ return this;
+ }
+
+ public void setDirections( String directions ) {
+ directions( directions );
+ }
+
+ public void setDirection( String directions ) {
+ directions( directions );
+ }
+
+ public void setDir( String directions ) {
+ directions( directions );
+ }
+
+ public String getDir() {
+ String s = null;
+ if( directions != null ) {
+ StringBuilder sb = new StringBuilder();
+ for( UrlRewriter.Direction direction: directions ) {
+ if( sb.length() > 0 ) {
+ sb.append( ',' );
+ }
+ sb.append( direction.toString() );
+ }
+ s = sb.toString();
+ }
+ return s;
+ }
+
+ @Override
+ public UrlRewriteRuleDescriptor directions( UrlRewriter.Direction... directions ) {
+ return this;
+ }
+
+ @Override
+ public String pattern() {
+ return pattern;
+ }
+
+ @Override
+ public UrlRewriteRuleDescriptor pattern( String pattern ) throws URISyntaxException {
+ this.pattern = pattern;
+ this.template = Parser.parseTemplate( pattern );
+ return this;
+ }
+
+ public void setPattern( String pattern ) throws URISyntaxException {
+ pattern( pattern );
+ }
+
+ public void setUrl( String pattern ) throws URISyntaxException {
+ pattern( pattern );
+ }
+
+ public String getPattern() {
+ return pattern();
+ }
+
+ @Override
+ public Template template() {
+ return template;
+ }
+
+ @Override
+ public UrlRewriteRuleDescriptor template( Template template ) {
+ this.template = template;
+ this.pattern = template.toString();
+ return this;
+ }
+
+ private static EnumSet<UrlRewriter.Direction> parseDirections( String directions ) {
+ EnumSet<UrlRewriter.Direction> set = EnumSet.noneOf( UrlRewriter.Direction.class );
+ StringTokenizer parser = new StringTokenizer( directions, " ,;:/|+" );
+ while( parser.hasMoreTokens() ) {
+ UrlRewriter.Direction direction = parseDirection( parser.nextToken() );
+ if( direction != null ) {
+ set.add( direction );
+ }
+ }
+ return set;
+ }
+
+ private static UrlRewriter.Direction parseDirection( String direction ) {
+ direction = direction.trim().toLowerCase();
+ return directionNameMap.get( direction );
+ }
+
+ private static Map<String,UrlRewriter.Direction> directionNameMap = new HashMap<>();
+ static {
+ directionNameMap.put( "inbound", UrlRewriter.Direction.IN );
+ directionNameMap.put( "in", UrlRewriter.Direction.IN );
+ directionNameMap.put( "i", UrlRewriter.Direction.IN );
+ directionNameMap.put( "request", UrlRewriter.Direction.IN );
+ directionNameMap.put( "req", UrlRewriter.Direction.IN );
+
+ directionNameMap.put( "outbound", UrlRewriter.Direction.OUT );
+ directionNameMap.put( "out", UrlRewriter.Direction.OUT );
+ directionNameMap.put( "o", UrlRewriter.Direction.OUT );
+ directionNameMap.put( "response", UrlRewriter.Direction.OUT );
+ directionNameMap.put( "res", UrlRewriter.Direction.OUT );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleProcessorHolder.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleProcessorHolder.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleProcessorHolder.java
new file mode 100644
index 0000000..1c3fb11
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleProcessorHolder.java
@@ -0,0 +1,65 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteRuleDescriptor;
+import org.apache.knox.gateway.filter.rewrite.ext.ScopedMatcher;
+
+import java.util.List;
+
+public class UrlRewriteRuleProcessorHolder extends UrlRewriteStepProcessorHolder {
+
+ private String ruleName;
+
+ private String scope;
+
+ public void initialize( UrlRewriteEnvironment environment, UrlRewriteRuleDescriptor descriptor ) throws Exception {
+ super.initialize( environment, descriptor );
+ ruleName = descriptor.name();
+ //if a scope is set in the rewrite file, use that
+ if (descriptor.scope() != null) {
+ scope = descriptor.scope();
+ } else {
+ //by convention the name of the rules start with ROLENAME/servicename/direction
+ //use the first part of the name to determine the scope, therefore setting the scope of a rule to
+ //be local to that service
+ int slashIndex = ruleName.indexOf('/');
+ if (slashIndex > 0) {
+ scope = ruleName.substring( 0, slashIndex );
+ }
+ //check config to see if the is an override configuration for a given service to have all its rules set to global
+ GatewayConfig gatewayConfig = environment.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+ if (gatewayConfig != null) {
+ List<String> globalRulesServices = gatewayConfig.getGlobalRulesServices();
+ if ( globalRulesServices.contains(scope) ) {
+ scope = ScopedMatcher.GLOBAL_SCOPE;
+ }
+ }
+ }
+ }
+
+ public String getRuleName() {
+ return ruleName;
+ }
+
+ public String getScope() {
+ return scope;
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleProcessorImpl.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleProcessorImpl.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleProcessorImpl.java
new file mode 100644
index 0000000..e02ad23
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRuleProcessorImpl.java
@@ -0,0 +1,59 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteRuleDescriptor;
+import org.apache.knox.gateway.filter.rewrite.ext.UrlRewriteMatchDescriptor;
+import org.apache.knox.gateway.filter.rewrite.ext.UrlRewriteMatchDescriptorExt;
+import org.apache.knox.gateway.filter.rewrite.ext.UrlRewriteMatchProcessorExt;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteContext;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepProcessor;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepStatus;
+
+public class UrlRewriteRuleProcessorImpl implements
+ UrlRewriteStepProcessor<UrlRewriteRuleDescriptor> {
+
+ private UrlRewriteMatchProcessorExt matchProcessor;
+
+ @Override
+ public String getType() {
+ return "rule";
+ }
+
+ @Override
+ public void initialize( UrlRewriteEnvironment environment, UrlRewriteRuleDescriptor descriptor ) throws Exception {
+ UrlRewriteMatchDescriptor matchDescriptor = new UrlRewriteMatchDescriptorExt();
+ matchDescriptor.operation( "matches" );
+ matchDescriptor.flow( descriptor.flow() );
+ matchDescriptor.template( descriptor.template() );
+ matchProcessor = new UrlRewriteMatchProcessorExt();
+ matchProcessor.initialize( environment, matchDescriptor );
+ }
+
+ @Override
+ public UrlRewriteStepStatus process( UrlRewriteContext context ) throws Exception {
+ return matchProcessor.process( context );
+ }
+
+ @Override
+ public void destroy() {
+ matchProcessor.destroy();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRulesDescriptorImpl.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRulesDescriptorImpl.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRulesDescriptorImpl.java
new file mode 100644
index 0000000..86dbc2a
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteRulesDescriptorImpl.java
@@ -0,0 +1,143 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptorFactory;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteRuleDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteRulesDescriptor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class UrlRewriteRulesDescriptorImpl implements UrlRewriteRulesDescriptor {
+
+ private Map<String,UrlRewriteFunctionDescriptor> funcMap = new HashMap<>();
+ private List<UrlRewriteFunctionDescriptor> funcList = new ArrayList<UrlRewriteFunctionDescriptor>();
+ private List<UrlRewriteRuleDescriptor> ruleList = new ArrayList<UrlRewriteRuleDescriptor>();
+ private Map<String,UrlRewriteRuleDescriptor> ruleMap = new HashMap<>();
+ private List<UrlRewriteFilterDescriptor> filterList = new ArrayList<UrlRewriteFilterDescriptor>();
+ private Map<String,UrlRewriteFilterDescriptor> filterMap = new HashMap<>();
+
+ @Override
+ public void addRules( UrlRewriteRulesDescriptor rules ) {
+ for( UrlRewriteRuleDescriptor rule : rules.getRules() ) {
+ addRule( rule );
+ }
+ for( UrlRewriteFilterDescriptor filter : rules.getFilters() ) {
+ addFilter( filter );
+ }
+ }
+
+ @Override
+ public UrlRewriteRuleDescriptor getRule( String name ) {
+ return ruleMap.get( name );
+ }
+
+ @Override
+ public List<UrlRewriteRuleDescriptor> getRules() {
+ return ruleList;
+ }
+
+ @Override
+ public UrlRewriteRuleDescriptor addRule( String name ) {
+ UrlRewriteRuleDescriptor rule = newRule();
+ rule.name( name );
+ addRule( rule );
+ return rule;
+ }
+
+ @Override
+ public UrlRewriteRuleDescriptor newRule() {
+ return new UrlRewriteRuleDescriptorImpl();
+ }
+
+ @Override
+ public void addRule( UrlRewriteRuleDescriptor rule ) {
+ ruleList.add( rule );
+ String name = rule.name();
+ if( name != null && name.length() > 0 ) {
+ ruleMap.put( rule.name(), rule );
+ }
+ }
+
+ @Override
+ public List<UrlRewriteFunctionDescriptor> getFunctions() {
+ return funcList;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T extends UrlRewriteFunctionDescriptor<?>> T getFunction( String name ) {
+ T descriptor = (T)funcMap.get( name );
+ return (T)descriptor;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T extends UrlRewriteFunctionDescriptor<?>> T addFunction( String name ) {
+ T descriptor = (T)newFunction( name );
+ addFunction( descriptor );
+ return (T)descriptor;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected <T extends UrlRewriteFunctionDescriptor<?>> T newFunction( String name ) {
+ T descriptor = (T)UrlRewriteFunctionDescriptorFactory.create( name );
+ return (T)descriptor;
+ }
+
+ protected void addFunction( UrlRewriteFunctionDescriptor descriptor ) {
+ funcList.add( descriptor );
+ funcMap.put( descriptor.name(), descriptor );
+ }
+
+
+ @Override
+ public List<UrlRewriteFilterDescriptor> getFilters() {
+ return filterList;
+ }
+
+ @Override
+ public UrlRewriteFilterDescriptor getFilter( String name ) {
+ return filterMap.get( name );
+ }
+
+ @Override
+ public UrlRewriteFilterDescriptor newFilter() {
+ return new UrlRewriteFilterDescriptorImpl();
+ }
+
+ @Override
+ public UrlRewriteFilterDescriptor addFilter( String name ) {
+ UrlRewriteFilterDescriptor filter = newFilter();
+ filter.name( name );
+ addFilter( filter );
+ return filter;
+ }
+
+ @Override
+ public void addFilter( UrlRewriteFilterDescriptor descriptor ) {
+ filterList.add( descriptor );
+ filterMap.put( descriptor.name(), descriptor );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorFactory.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorFactory.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorFactory.java
new file mode 100644
index 0000000..7d88f8b
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorFactory.java
@@ -0,0 +1,106 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteStepDescriptor;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepProcessor;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+public abstract class UrlRewriteStepProcessorFactory {
+
+ private static final Map<Class<? extends UrlRewriteStepDescriptor>,Map<String,Class<? extends UrlRewriteStepProcessor>>> MAP
+ = loadStepProcessors();
+
+ private UrlRewriteStepProcessorFactory() {
+ }
+
+ public static UrlRewriteStepProcessor create( UrlRewriteStepDescriptor descriptor ) throws IllegalAccessException, InstantiationException {
+ UrlRewriteStepProcessor processor;
+ Map<String,Class<? extends UrlRewriteStepProcessor>> typeMap;
+ typeMap = MAP.get( descriptor.getClass() );
+ if( typeMap == null ) {
+ Class<? extends UrlRewriteStepDescriptor> descriptorInterface = getDescriptorInterface( descriptor );
+ typeMap = MAP.get( descriptorInterface );
+ }
+ if( typeMap == null ) {
+ throw new IllegalArgumentException( descriptor.getClass().getName() );
+ } else {
+ String type = descriptor.type();
+ Class<? extends UrlRewriteStepProcessor> processorClass = typeMap.get( type );
+ if( processorClass == null ) {
+ throw new IllegalArgumentException( type );
+ } else {
+ processor = processorClass.newInstance();
+ }
+ }
+ return processor;
+ }
+
+ private static Map<Class<? extends UrlRewriteStepDescriptor>,Map<String,Class<? extends UrlRewriteStepProcessor>>> loadStepProcessors() {
+ Map<Class<? extends UrlRewriteStepDescriptor>,Map<String,Class<? extends UrlRewriteStepProcessor>>> descriptorMap
+ = new HashMap<>();
+ ServiceLoader<UrlRewriteStepProcessor> processors = ServiceLoader.load( UrlRewriteStepProcessor.class );
+ for( UrlRewriteStepProcessor processor : processors ) {
+ Class<? extends UrlRewriteStepDescriptor> descriptorInterface = getDescriptorInterface( processor );
+ Map<String,Class<? extends UrlRewriteStepProcessor>> typeMap = descriptorMap.get( descriptorInterface );
+ if( typeMap == null ) {
+ typeMap = new HashMap<>();
+ descriptorMap.put( descriptorInterface, typeMap );
+ }
+ String processorType = processor.getType();
+ typeMap.put( processorType, processor.getClass() );
+ }
+ return descriptorMap;
+ }
+
+ private static Class<? extends UrlRewriteStepDescriptor> getDescriptorInterface( UrlRewriteStepDescriptor descriptor ) {
+ Class<? extends UrlRewriteStepDescriptor> descriptorClass = null;
+ for( Type interfaceType : descriptor.getClass().getGenericInterfaces() ) {
+ Class genericClass = (Class)interfaceType;
+ if( UrlRewriteStepDescriptor.class.isAssignableFrom( genericClass ) ) {
+ descriptorClass = uncheckedStepDescriptorClassCast( genericClass );
+ break;
+ }
+ }
+ return descriptorClass;
+ }
+
+ private static Class<? extends UrlRewriteStepDescriptor> getDescriptorInterface( UrlRewriteStepProcessor processor ) {
+ Class<? extends UrlRewriteStepDescriptor> descriptorClass = null;
+ Class<? extends UrlRewriteStepProcessor> processorClass = processor.getClass();
+ for( Type interfaceType : processorClass.getGenericInterfaces() ) {
+ if( UrlRewriteStepProcessor.class.isAssignableFrom( (Class)((ParameterizedType)interfaceType).getRawType() ) ) {
+ ParameterizedType interfaceClass = (ParameterizedType)interfaceType;
+ descriptorClass = uncheckedStepDescriptorClassCast( interfaceClass.getActualTypeArguments()[ 0 ] );
+ break;
+ }
+ }
+ return descriptorClass;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Class<? extends UrlRewriteStepDescriptor> uncheckedStepDescriptorClassCast( Type type ) {
+ return (Class<? extends UrlRewriteStepDescriptor>)type;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorHolder.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorHolder.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorHolder.java
new file mode 100644
index 0000000..1d4811c
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorHolder.java
@@ -0,0 +1,233 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFlowDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteStepDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteStepFlow;
+import org.apache.knox.gateway.filter.rewrite.i18n.UrlRewriteMessages;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteContext;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepProcessor;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepStatus;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class UrlRewriteStepProcessorHolder implements UrlRewriteStepProcessor {
+
+ private static final UrlRewriteMessages LOG = MessagesFactory.get( UrlRewriteMessages.class );
+
+ private boolean isCondition;
+ private UrlRewriteStepDescriptor descriptor;
+ private UrlRewriteStepProcessor processor;
+ private List<UrlRewriteStepProcessorHolder> childProcessors;
+
+ @Override
+ public String getType() {
+ return "system";
+ }
+
+ public boolean isCondition() {
+ return isCondition;
+ }
+
+ public boolean isAction() {
+ return !isCondition;
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public void initialize( UrlRewriteEnvironment environment, UrlRewriteStepDescriptor descriptor ) throws Exception {
+ UrlRewriteStepProcessor processor = UrlRewriteStepProcessorFactory.create( descriptor );
+ processor.initialize( environment, descriptor );
+ initialize( environment, descriptor, processor );
+ }
+
+ // For unit testing.
+ @SuppressWarnings("unchecked")
+ void initialize( UrlRewriteEnvironment environment, UrlRewriteStepDescriptor descriptor, UrlRewriteStepProcessor processor ) throws Exception {
+ this.descriptor = descriptor;
+ this.processor = processor;
+ this.isCondition = descriptor instanceof UrlRewriteFlowDescriptor;
+ this.childProcessors = new ArrayList<UrlRewriteStepProcessorHolder>();
+ if( isCondition ) {
+ UrlRewriteFlowDescriptor flowDescriptor = (UrlRewriteFlowDescriptor)descriptor;
+ List<UrlRewriteStepDescriptor> stepList = flowDescriptor.steps();
+ if( stepList != null && !stepList.isEmpty() ) {
+ Iterator<UrlRewriteStepDescriptor> stepIterator = stepList.iterator();
+ while( stepIterator.hasNext() ) {
+ UrlRewriteStepDescriptor stepDescriptor = stepIterator.next();
+ UrlRewriteStepProcessorHolder stepProcessor = new UrlRewriteStepProcessorHolder();
+ stepProcessor.initialize( environment, stepDescriptor );
+ childProcessors.add( stepProcessor );
+ }
+ }
+ }
+ }
+
+ // For unit testing.
+ UrlRewriteStepDescriptor getDescriptor() {
+ return descriptor;
+ }
+
+ // For unit testing.
+ UrlRewriteStepProcessor getProcessor() {
+ return processor;
+ }
+
+ @Override
+ public UrlRewriteStepStatus process( UrlRewriteContext context ) throws Exception {
+ UrlRewriteStepStatus status = UrlRewriteStepStatus.SUCCESS;
+ // If initialization failed then fail processing
+ if( processor != null ) {
+ status = processor.process( context );
+ if( UrlRewriteStepStatus.SUCCESS == status &&
+ descriptor instanceof UrlRewriteFlowDescriptor &&
+ !childProcessors.isEmpty() ) {
+ UrlRewriteFlowDescriptor flowDescriptor = (UrlRewriteFlowDescriptor)descriptor;
+ UrlRewriteStepFlow flow = flowDescriptor.flow();
+ if( flow == null ) {
+ flow = UrlRewriteStepFlow.AND;
+ }
+ switch( flow ) {
+ case ALL:
+ return processAllFlow( context );
+ case AND:
+ return processAndFlow( context );
+ case OR:
+ return processOrFlow( context );
+ }
+ }
+ }
+ return status;
+ }
+
+ private UrlRewriteStepStatus processAllFlow( UrlRewriteContext context ) throws Exception {
+ UrlRewriteStepProcessorState state = new UrlRewriteStepProcessorState( childProcessors.iterator() );
+ UrlRewriteStepStatus stepStatus = UrlRewriteStepStatus.SUCCESS;
+ UrlRewriteStepProcessorHolder step;
+ while( state.hasNext() ) {
+ while( state.hasNextCondition() ) {
+ step = state.nextCondition( stepStatus );
+ stepStatus = step.process( context );
+ if( stepStatus == UrlRewriteStepStatus.FINISHED ) {
+ return stepStatus;
+ }
+ }
+ stepStatus = processActions( context, state );
+ if( stepStatus == UrlRewriteStepStatus.FINISHED ) {
+ return stepStatus;
+ }
+ }
+ return UrlRewriteStepStatus.SUCCESS;
+ }
+
+ // All conditions proceeding a set of one or more actions must succeed for the actions to be executed.
+ private UrlRewriteStepStatus processAndFlow( UrlRewriteContext context ) throws Exception {
+ UrlRewriteStepProcessorState state = new UrlRewriteStepProcessorState( childProcessors.iterator() );
+ UrlRewriteStepStatus stepStatus = UrlRewriteStepStatus.SUCCESS;
+ UrlRewriteStepProcessorHolder step;
+ while( state.hasNext() ) {
+ while( state.hasNextCondition() ) {
+ step = state.nextCondition( stepStatus );
+ stepStatus = step.process( context );
+ if( !( stepStatus == UrlRewriteStepStatus.SUCCESS ) ) {
+ return stepStatus;
+ }
+ }
+ stepStatus = processActions( context, state );
+ if( !( stepStatus == UrlRewriteStepStatus.SUCCESS ) ) {
+ return stepStatus;
+ }
+ }
+ return UrlRewriteStepStatus.SUCCESS;
+ }
+
+ // At least one condition proceeding a set of one or more actions must succedd for the actions to be executed.
+ private UrlRewriteStepStatus processOrFlow( UrlRewriteContext context ) throws Exception {
+ UrlRewriteStepProcessorState state = new UrlRewriteStepProcessorState( childProcessors.iterator() );
+ UrlRewriteStepStatus status = UrlRewriteStepStatus.SUCCESS;
+ UrlRewriteStepProcessorHolder step;
+ while( state.hasNext() ) {
+ UrlRewriteStepStatus flowStatus = UrlRewriteStepStatus.FAILURE;
+ while( state.hasNextCondition() ) {
+ step = state.nextCondition( status );
+ if( flowStatus == UrlRewriteStepStatus.FAILURE ) {
+ status = step.process( context );
+ switch( status ) {
+ case SUCCESS:
+ flowStatus = UrlRewriteStepStatus.SUCCESS;
+ continue;
+ case FINISHED:
+ return status;
+ }
+ }
+ }
+ status = processActions( context, state );
+ if( status != UrlRewriteStepStatus.SUCCESS ) {
+ return status;
+ }
+ }
+ return UrlRewriteStepStatus.SUCCESS;
+ }
+
+ private UrlRewriteStepStatus processActions( UrlRewriteContext context, UrlRewriteStepProcessorState state )
+ throws Exception {
+ UrlRewriteStepStatus flowStatus = UrlRewriteStepStatus.SUCCESS;
+ while( state.hasNextAction() ) {
+ if( flowStatus == UrlRewriteStepStatus.SUCCESS ) {
+ UrlRewriteStepStatus stepStatus = UrlRewriteStepStatus.SUCCESS;
+ UrlRewriteStepProcessorHolder step = state.nextAction( stepStatus );
+ stepStatus = step.process( context );
+ switch( stepStatus ) {
+ case FAILURE:
+ flowStatus = UrlRewriteStepStatus.FAILURE;
+ continue;
+ case FINISHED:
+ return stepStatus;
+ }
+ }
+ }
+ return flowStatus;
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ destroy( processor );
+ if( descriptor instanceof UrlRewriteFlowDescriptor ) {
+ for( UrlRewriteStepProcessorHolder childProcessor : childProcessors ) {
+ destroy( childProcessor );
+ }
+ }
+ }
+
+ public void destroy( UrlRewriteStepProcessor processor ) {
+ if( processor != null ) {
+ try {
+ processor.destroy();
+ } catch( Exception e ) {
+ // Maybe it makes sense to throw exception
+ LOG.failedToDestroyRewriteStepProcessor( e );
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorState.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorState.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorState.java
new file mode 100644
index 0000000..dead19d
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteStepProcessorState.java
@@ -0,0 +1,88 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteStepStatus;
+
+import java.util.Iterator;
+
+class UrlRewriteStepProcessorState {
+
+ private UrlRewriteStepStatus status;
+ private UrlRewriteStepProcessorHolder next;
+ private Iterator<UrlRewriteStepProcessorHolder> steps;
+
+ UrlRewriteStepProcessorState( Iterator<UrlRewriteStepProcessorHolder> steps ) {
+ this.status = UrlRewriteStepStatus.SUCCESS;
+ this.next = null;
+ this.steps = steps;
+ }
+
+ private UrlRewriteStepProcessorHolder peek() {
+ if( next == null && steps.hasNext() ) {
+ next = steps.next();
+ return next;
+ } else if ( next != null ) {
+ return next;
+ } else {
+ return null;
+ }
+ }
+
+ public boolean hasNextCondition() {
+ UrlRewriteStepProcessorHolder curr = peek();
+ return curr != null && curr.isCondition();
+ }
+
+ public boolean hasNextAction() {
+ UrlRewriteStepProcessorHolder curr = peek();
+ return curr != null && curr.isAction();
+ }
+
+ private UrlRewriteStepProcessorHolder take( UrlRewriteStepStatus lastStatus ) {
+ UrlRewriteStepProcessorHolder step = peek();
+ status = lastStatus;
+ next = null;
+ return step;
+ }
+
+ public UrlRewriteStepProcessorHolder nextCondition( UrlRewriteStepStatus lastStatus ){
+ if( hasNextCondition() ) {
+ return take( lastStatus );
+ } else {
+ return null;
+ }
+ }
+
+ public UrlRewriteStepProcessorHolder nextAction( UrlRewriteStepStatus lastStatus ){
+ if( hasNextAction() ) {
+ return take( lastStatus );
+ } else {
+ return null;
+ }
+ }
+
+ public UrlRewriteStepStatus status(){
+ return status;
+ }
+
+ public boolean hasNext() {
+ return next != null || steps.hasNext();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteUtil.java
----------------------------------------------------------------------
diff --git a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteUtil.java b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteUtil.java
new file mode 100644
index 0000000..4e68d27
--- /dev/null
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/UrlRewriteUtil.java
@@ -0,0 +1,92 @@
+/**
+ * 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.knox.gateway.filter.rewrite.impl;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterApplyDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterContentDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterPathDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteRulesDescriptor;
+
+import javax.activation.MimeType;
+
+public class UrlRewriteUtil {
+
+ public static String pickFirstRuleWithEqualsIgnoreCasePathMatch( UrlRewriteFilterContentDescriptor config, String name ) {
+ String rule = "*";
+ if( config != null && !config.getSelectors().isEmpty() && name != null ) {
+ rule = "";
+ for( UrlRewriteFilterPathDescriptor selector : config.getSelectors() ) {
+ if( name.equalsIgnoreCase( selector.path() ) ) {
+ if( selector instanceof UrlRewriteFilterApplyDescriptor) {
+ rule = ((UrlRewriteFilterApplyDescriptor)selector).rule();
+ }
+ break;
+ }
+ }
+ }
+ return rule;
+ }
+
+ public static UrlRewriteFilterContentDescriptor getRewriteFilterConfig(
+ UrlRewriteRulesDescriptor config, String filterName, MimeType mimeType ) {
+ UrlRewriteFilterContentDescriptor filterContentConfig = null;
+ if( config != null ) {
+ UrlRewriteFilterDescriptor filterConfig = config.getFilter( filterName );
+ if( filterConfig != null ) {
+ filterContentConfig = filterConfig.getContent( mimeType );
+ }
+ }
+ return filterContentConfig;
+ }
+
+ public static String filterJavaScript( String inputValue, UrlRewriteFilterContentDescriptor config,
+ UrlRewriteFilterReader filterReader, UrlRewriteFilterPathDescriptor.Compiler<Pattern> regexCompiler ) {
+ StringBuffer tbuff = new StringBuffer();
+ StringBuffer sbuff = new StringBuffer();
+ sbuff.append( inputValue );
+ if( config != null && !config.getSelectors().isEmpty() ) {
+ for( UrlRewriteFilterPathDescriptor selector : config.getSelectors() ) {
+ if ( selector instanceof UrlRewriteFilterApplyDescriptor ) {
+ UrlRewriteFilterApplyDescriptor apply = (UrlRewriteFilterApplyDescriptor)selector;
+ Matcher matcher = apply.compiledPath( regexCompiler ).matcher( sbuff );
+ int index = 0;
+ while ( matcher.find() ) {
+ int start = matcher.start();
+ int end = matcher.end();
+ if ( start != -1 && end != -1 ) {
+ tbuff.append( sbuff, index, start );
+ String value = matcher.group();
+ value = filterReader.filterValueString( null, value, apply.rule() );
+ tbuff.append(value);
+ index = end;
+ }
+ }
+ tbuff.append( sbuff, index, sbuff.length() );
+ sbuff.setLength( 0 );
+ sbuff.append( tbuff );
+ tbuff.setLength( 0 );
+ }
+ }
+ }
+ return sbuff.toString();
+ }
+}