View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  package org.opencastproject.security.aai.api;
22  
23  import org.slf4j.Logger;
24  import org.slf4j.LoggerFactory;
25  import org.springframework.beans.factory.InitializingBean;
26  import org.springframework.expression.Expression;
27  import org.springframework.expression.ExpressionParser;
28  import org.springframework.expression.spel.standard.SpelExpressionParser;
29  import org.springframework.util.Assert;
30  import org.springframework.util.CollectionUtils;
31  
32  import java.util.HashMap;
33  import java.util.LinkedHashSet;
34  import java.util.List;
35  import java.util.Map;
36  import java.util.Set;
37  
38  import javax.servlet.http.HttpServletRequest;
39  /**
40   * Generic AAI Attribute mapper using Spring Expression language mappings.
41   *
42   */
43  public class AttributeMapper implements InitializingBean {
44  
45    /** The logging facility */
46    private static final Logger logger = LoggerFactory.getLogger(AttributeMapper.class);
47  
48    /** List of all attributes that should be fetched */
49    private List<String> aaiAttributes;
50  
51    /**
52     * Map of List of expressions. Key is a mapping name, value a list of
53     * expressions
54     */
55    private Map<String, List<String>> attributeMap;
56  
57    /** Use HTTP Header or environment attributes */
58    private boolean useHeader = true;
59  
60    /** The delimiter for multivalue attributes */
61    private String multiValueDelimiter = ";";
62  
63    public void afterPropertiesSet() throws Exception {
64      Assert.notNull(attributeMap, "attributeMap must be set");
65    }
66  
67    /**
68     * Apply all expressions on the sourceAttributes
69     *
70     * @param sourceAttributes
71     *    Key is attribute name, value a list of split AAI attribute values
72     * @param mappingId
73     *    The mapping list to use
74     * @return
75     */
76    public List<String> getMappedAttributes(
77        Map<String, List<String>> sourceAttributes, String mappingId) {
78      Set<String> mappedAttributes = new LinkedHashSet<String>();
79      ExpressionParser parser = new SpelExpressionParser();
80  
81      List<String> expressions = attributeMap.get(mappingId);
82  
83      if (expressions == null) {
84        throw new IllegalArgumentException("No mapping for \"" + mappingId
85            + "\" specified. Did you forget to configure a <util:map id=\""
86            + mappingId + "\" ...?");
87      }
88  
89      for (String expression : expressions) {
90        Expression exp = null;
91        try {
92          exp = parser.parseExpression(expression);
93          Object res = exp.getValue(sourceAttributes);
94          logger.debug("Mapping {} to {}", exp.getExpressionString(), res);
95          if (res == null) {
96            continue;
97          }
98          if (res instanceof String) {
99            mappedAttributes.add((String) res);
100         } else if (res instanceof List<?>) {
101           for (Object resListItem : (List<?>) res) {
102             if (resListItem instanceof String) {
103               mappedAttributes.add((String) resListItem);
104             }
105           }
106         }
107       } catch (Exception e) {
108         logger.warn("Mapping for '{}' with expression {} exp.getExpressionString() failed: {}",
109             mappingId, exp.getExpressionString(), e.getMessage());
110       }
111     }
112 
113     return CollectionUtils.arrayToList(mappedAttributes.toArray());
114   }
115 
116   /**
117    *
118    * @param request
119    *    The current HttpServletRequest
120    * @param mappingId
121    *    The mapping list to use
122    * @return
123    */
124   public List<String> getMappedAttributes(HttpServletRequest request,
125       String mappingId) {
126     Assert
127         .notNull(
128             aaiAttributes,
129             "aaiAttributes must be set. Did you forget to configure <util:list id=\"aaiAttribute\"?");
130     Assert.isTrue(aaiAttributes.size() > 0,
131             "At least one aaiAttribute must be set. Did you forget to configure some in "
132                     + "<util:list id=\"aaiAttribute\"?");
133 
134     Map<String, List<String>> sourceAttributes = new HashMap<String, List<String>>();
135 
136     for (String aaiAttribute : aaiAttributes) {
137       String value = null;
138       if (this.isUseHeader()) {
139         value = request.getHeader(aaiAttribute);
140         if (value == null) {
141           logger.warn("No header '{}' found in request.", aaiAttribute);
142           continue;
143         }
144       } else {
145         value = (String) request.getAttribute(aaiAttribute);
146         if (value == null) {
147           logger.warn("No attribute '{}' found in request.", aaiAttribute);
148           continue;
149         }
150       }
151       sourceAttributes.put(aaiAttribute,
152           CollectionUtils.arrayToList(value.split(multiValueDelimiter)));
153     }
154     return this.getMappedAttributes(sourceAttributes, mappingId);
155   }
156 
157   public Map<String, List<String>> getAttributeMap() {
158     return attributeMap;
159   }
160 
161   public void setAttributeMap(Map<String, List<String>> attributeMap) {
162     this.attributeMap = attributeMap;
163   }
164 
165   public List<String> getAaiAttributes() {
166     return aaiAttributes;
167   }
168 
169   public void setAaiAttributes(List<String> aaiAttributes) {
170     this.aaiAttributes = aaiAttributes;
171   }
172 
173   public boolean isUseHeader() {
174     return useHeader;
175   }
176 
177   public void setUseHeader(boolean useHeader) {
178     this.useHeader = useHeader;
179   }
180 
181   public String getMultiValueDelimiter() {
182     return multiValueDelimiter;
183   }
184 
185   public void setMultiValueDelimiter(String multiValueDelimiter) {
186     this.multiValueDelimiter = multiValueDelimiter;
187   }
188 
189 }