/** * 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.filter.rewrite.api; import org.apache.hadoop.gateway.filter.rewrite.ext.ScopedMatcher; import org.apache.hadoop.gateway.filter.rewrite.i18n.UrlRewriteMessages; import org.apache.hadoop.gateway.filter.rewrite.impl.UrlRewriteContextImpl; import org.apache.hadoop.gateway.filter.rewrite.impl.UrlRewriteFunctionProcessorFactory; import org.apache.hadoop.gateway.filter.rewrite.impl.UrlRewriteRuleProcessorHolder; import org.apache.hadoop.gateway.filter.rewrite.impl.UrlRewriteStepProcessorHolder; import org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteContext; import org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor; import org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteStepStatus; import org.apache.hadoop.gateway.i18n.messages.MessagesFactory; import org.apache.hadoop.gateway.util.urltemplate.Matcher; import org.apache.hadoop.gateway.util.urltemplate.Resolver; import org.apache.hadoop.gateway.util.urltemplate.Template; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriter.Direction.IN; import static org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriter.Direction.OUT; public class UrlRewriteProcessor implements UrlRewriter { private static final UrlRewriteMessages LOG = MessagesFactory.get( UrlRewriteMessages.class ); UrlRewriteEnvironment environment; UrlRewriteRulesDescriptor descriptor; Map<String,UrlRewriteRuleProcessorHolder> rules = new HashMap<String,UrlRewriteRuleProcessorHolder>(); ScopedMatcher inbound = new ScopedMatcher(); ScopedMatcher outbound = new ScopedMatcher(); Map<String,UrlRewriteFunctionProcessor> functions = new HashMap<String,UrlRewriteFunctionProcessor>(); public UrlRewriteProcessor() { } // Convert the descriptor into processors. public void initialize( UrlRewriteEnvironment environment, UrlRewriteRulesDescriptor descriptor ) { this.environment = environment; this.descriptor = descriptor; initializeFunctions( descriptor ); initializeRules( descriptor ); } public UrlRewriteRulesDescriptor getConfig() { return descriptor; } @SuppressWarnings("unchecked") private void initializeFunctions( UrlRewriteRulesDescriptor rules ) { for( String name : UrlRewriteFunctionDescriptorFactory.getNames() ) { try { UrlRewriteFunctionDescriptor descriptor = rules.getFunction( name ); UrlRewriteFunctionProcessor processor = UrlRewriteFunctionProcessorFactory.create( name, descriptor ); processor.initialize( environment, descriptor ); functions.put( name, processor ); } catch( Exception e ) { // Ignore it and it won't be available as a function. LOG.failedToInitializeRewriteFunctions( e ); } } } private void initializeRules( UrlRewriteRulesDescriptor descriptor ) { for( UrlRewriteRuleDescriptor ruleDescriptor : descriptor.getRules() ) { try { UrlRewriteRuleProcessorHolder ruleProcessor = new UrlRewriteRuleProcessorHolder(); ruleProcessor.initialize( environment, ruleDescriptor ); if( !rules.containsKey( ruleDescriptor.name() ) ) { rules.put( ruleDescriptor.name(), ruleProcessor ); } Template template = ruleDescriptor.template(); if( template != null ) { EnumSet<Direction> directions = ruleDescriptor.directions(); if( directions == null || directions.isEmpty() ) { inbound.add( template, ruleProcessor ); outbound.add( template, ruleProcessor ); } else if( directions.contains( IN ) ) { inbound.add( template, ruleProcessor ); } else if ( directions.contains( OUT ) ) { outbound.add( template, ruleProcessor ); } } } catch( Exception e ) { LOG.failedToInitializeRewriteRules( e ); } } } public void destroy() { for( UrlRewriteStepProcessorHolder rule : rules.values() ) { try { rule.destroy(); } catch ( Exception e ) { LOG.failedToDestroyRewriteStepProcessor( e ); } } for( UrlRewriteFunctionProcessor function : functions.values() ) { try { function.destroy(); } catch( Exception e ) { LOG.failedToDestroyRewriteFunctionProcessor( e ); } } } @Override public Template rewrite( Resolver resolver, Template inputUri, Direction direction, String ruleName ) { Template outputUri = inputUri; String serviceRole = null; if (resolver != null) { List<String> serviceRoles = resolver.resolve("service.role"); if ( serviceRoles != null && !serviceRoles.isEmpty() ) { serviceRole = serviceRoles.get(0); } } UrlRewriteStepProcessorHolder stepHolder = null; String effectiveRuleName = null; if( ruleName == null || "*".equals( ruleName ) ) { ruleName = null; // Used for logging later. Matcher<UrlRewriteRuleProcessorHolder>.Match match = null; switch( direction ) { case IN: match = inbound.match( outputUri, serviceRole ); break; case OUT: match = outbound.match( outputUri, serviceRole ); break; } if( match != null ) { stepHolder = match.getValue(); effectiveRuleName = match.getValue().getRuleName(); } } else if( !ruleName.isEmpty() ) { stepHolder = rules.get( ruleName ); effectiveRuleName = ruleName; } if( stepHolder != null ) { UrlRewriteContext context = new UrlRewriteContextImpl( environment, resolver, functions, direction, inputUri ); try { UrlRewriteStepStatus stepStatus = stepHolder.process( context ); if( UrlRewriteStepStatus.SUCCESS == stepStatus ) { outputUri = context.getCurrentUrl(); if( ruleName == null ) { LOG.rewroteUrlViaImplicitRule( inputUri, direction, effectiveRuleName, outputUri ); } else { LOG.rewroteUrlViaExplicitRule( inputUri, direction, effectiveRuleName, outputUri ); } } else { LOG.failedToRewriteUrl( inputUri, direction, effectiveRuleName, stepStatus ); outputUri = null; } } catch( Exception e ) { LOG.failedToRewriteUrlDueToException( inputUri, direction, effectiveRuleName, e ); outputUri = null; } } else { LOG.noRuleMatchingUrl( inputUri, direction ); } return outputUri; } }