001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2010–2011 ApexIdentity Inc. 015 * Portions Copyright 2011-2014 ForgeRock AS. 016 */ 017 018package org.forgerock.openig.filter; 019 020import static org.forgerock.openig.util.Json.*; 021 022import java.io.IOException; 023import java.util.Collections; 024import java.util.List; 025import java.util.Map; 026 027import org.forgerock.json.fluent.JsonValue; 028import org.forgerock.openig.handler.Handler; 029import org.forgerock.openig.handler.HandlerException; 030import org.forgerock.openig.heap.GenericHeaplet; 031import org.forgerock.openig.heap.HeapException; 032import org.forgerock.openig.http.Exchange; 033import org.forgerock.openig.http.Headers; 034import org.forgerock.openig.http.Message; 035import org.forgerock.openig.http.MessageType; 036import org.forgerock.openig.util.CaseInsensitiveSet; 037 038/** 039 * Removes headers from and adds headers to a message. 040 */ 041public class HeaderFilter extends GenericFilter { 042 043 /** Indicates the type of message in the exchange to filter headers for. */ 044 private final MessageType messageType; 045 046 /** The names of header fields to remove from the message. */ 047 private final CaseInsensitiveSet removedHeaders = new CaseInsensitiveSet(); 048 049 /** Header fields to add to the message. */ 050 private final Headers addedHeaders = new Headers(); 051 052 /** 053 * Builds a HeaderFilter processing either the incoming or outgoing message. 054 * @param messageType {@link MessageType#REQUEST} or {@link MessageType#RESPONSE} 055 */ 056 public HeaderFilter(final MessageType messageType) { 057 this.messageType = messageType; 058 } 059 060 /** 061 * Returns the names of header fields to remove from the message. 062 * @return the names of header fields to remove from the message. 063 */ 064 public CaseInsensitiveSet getRemovedHeaders() { 065 return removedHeaders; 066 } 067 068 /** 069 * Returns the header fields to add to the message. 070 * This is a essentially a Map of String to a List of String, each listed value representing 071 * an expression that will be evaluated. 072 * @return the header fields to add to the message. 073 */ 074 public Headers getAddedHeaders() { 075 return addedHeaders; 076 } 077 078 /** 079 * Removes all specified headers, then adds all specified headers. 080 * 081 * @param message the message to remove headers from and add headers to. 082 */ 083 private void process(Message<?> message, Exchange exchange) { 084 for (String s : this.removedHeaders) { 085 message.getHeaders().remove(s); 086 } 087 for (String key : this.addedHeaders.keySet()) { 088 for (String value : this.addedHeaders.get(key)) { 089 JsonValue jsonValue = new JsonValue(value); 090 message.getHeaders().add(key, (String) asExpression(jsonValue).eval(exchange)); 091 } 092 } 093 } 094 095 @Override 096 public void filter(Exchange exchange, Handler next) throws HandlerException, IOException { 097 if (messageType == MessageType.REQUEST) { 098 process(exchange.request, exchange); 099 } 100 next.handle(exchange); 101 if (messageType == MessageType.RESPONSE) { 102 process(exchange.response, exchange); 103 } 104 } 105 106 /** Creates and initializes a header filter in a heap environment. */ 107 public static class Heaplet extends GenericHeaplet { 108 @Override 109 public Object create() throws HeapException { 110 HeaderFilter filter = new HeaderFilter(config.get("messageType") 111 .required() 112 .asEnum(MessageType.class)); 113 filter.removedHeaders.addAll(config.get("remove") 114 .defaultTo(Collections.emptyList()) 115 .asList(String.class)); 116 JsonValue add = config.get("add") 117 .defaultTo(Collections.emptyMap()) 118 .expect(Map.class); 119 for (String key : add.keys()) { 120 List<String> values = add.get(key).required().asList(String.class); 121 filter.addedHeaders.addAll(key, values); 122 } 123 return filter; 124 } 125 } 126}