0604397023f19d9a8fa83aef1aed9f6e42335397
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / aa / attrresolv / provider / SimpleAttributeDefinition.java
1 /*
2  * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package edu.internet2.middleware.shibboleth.aa.attrresolv.provider;
18
19 import java.security.Principal;
20 import java.util.Arrays;
21 import java.util.Iterator;
22 import java.util.LinkedHashSet;
23 import java.util.Set;
24
25 import org.apache.log4j.Logger;
26 import org.w3c.dom.Element;
27
28 import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeDefinitionPlugIn;
29 import edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies;
30 import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException;
31 import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolverAttribute;
32
33 /**
34  * Basic <code>AttributeDefinitionPlugIn</code> implementation. Operates as a proxy for attributes gathered by
35  * Connectors.
36  * 
37  * @author Walter Hoehn (wassa@columbia.edu)
38  */
39 public class SimpleAttributeDefinition extends SimpleBaseAttributeDefinition implements AttributeDefinitionPlugIn {
40
41         private static Logger log = Logger.getLogger(SimpleAttributeDefinition.class.getName());
42         private String connectorMapping;
43         private String smartScope;
44         private ValueHandler valueHandler;
45         private boolean allowEmpty = false;
46         private boolean downCase = false;
47
48         /**
49          * Constructor for SimpleAttributeDefinition. Creates a PlugIn based on configuration information presented in a DOM
50          * Element.
51          */
52         public SimpleAttributeDefinition(Element e) throws ResolutionPlugInException {
53
54                 super(e);
55
56                 // Parse source name
57                 String sourceName = e.getAttribute("sourceName");
58                 if (sourceName == null || sourceName.equals("")) {
59                         int index = getId().lastIndexOf("#");
60                         if (index < 0) {
61                                 index = getId().lastIndexOf(":");
62                                 int slashIndex = getId().lastIndexOf("/");
63                                 if (slashIndex > index) {
64                                         index = slashIndex;
65                                 }
66                         }
67                         connectorMapping = getId().substring(index + 1);
68                 } else {
69                         connectorMapping = sourceName;
70                 }
71
72                 log.debug("Mapping attribute to name (" + connectorMapping + ") in connector.");
73
74                 // Configure smart scoping
75                 String smartScopingSpec = e.getAttribute("smartScope");
76                 if (smartScopingSpec != null && !smartScopingSpec.equals("")) {
77                         smartScope = smartScopingSpec;
78                 }
79                 if (smartScope != null) {
80                         log.debug("Smart Scope (" + smartScope + ") enabled for attribute (" + getId() + ").");
81                 } else {
82                         log.debug("Smart Scoping disabled for attribute (" + getId() + ").");
83                 }
84
85                 // Load a value handler
86                 String valueHandlerSpec = e.getAttribute("valueHandler");
87
88                 if (valueHandlerSpec != null && !valueHandlerSpec.equals("")) {
89                         if (smartScope == null) {
90                                 try {
91                                         Class handlerClass = Class.forName(valueHandlerSpec);
92                                         valueHandler = (ValueHandler) handlerClass.newInstance();
93                                 } catch (ClassNotFoundException cnfe) {
94                                         log.error("Value Handler implementation specified for attribute (" + getId()
95                                                         + ") cannot be found: " + cnfe);
96                                         throw new ResolutionPlugInException("Value Handler implementation specified for attribute ("
97                                                         + getId() + ") cannot be found.");
98                                 } catch (Exception oe) {
99                                         log.error("Value Handler implementation specified for attribute (" + getId()
100                                                         + ") coudl not be loaded: " + oe);
101                                         throw new ResolutionPlugInException("Value Handler implementation specified for attribute ("
102                                                         + getId() + ") could not be loaded.");
103                                 }
104                         } else {
105                                 log.error("Specification of \"valueHandler\' cannot be used in combination with \"smartScope\". "
106                                                 + " Ignoring Value Handler for attribute (" + getId() + ").");
107                         }
108                 }
109
110                 if (valueHandler != null) {
111                         log.debug("Custom Value Handler enabled for attribute (" + getId() + ").");
112                 }
113
114                 // Decide whether or not to allow empty string values
115                 String rawAllowEmpty = e.getAttribute("allowEmpty");
116                 if (rawAllowEmpty != null) {
117                         if (rawAllowEmpty.equalsIgnoreCase("TRUE")) {
118                                 allowEmpty = true;
119                         }
120                 }
121
122                 log.debug("Allowal of empty string values is set to (" + allowEmpty + ") for attribute (" + getId() + ").");
123
124                 // Decide whether or not to force values to lower case
125                 String rawDownCase = e.getAttribute("downCase");
126                 if (rawDownCase != null) {
127                         if (rawDownCase.equalsIgnoreCase("TRUE")) {
128                                 downCase = true;
129                                 log.debug("Forcing values to lower case for attribute (" + getId() + ").");
130                         }
131                 }
132
133         }
134
135         /**
136          * @see edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeDefinitionPlugIn#resolve(edu.internet2.middleware.shibboleth.aa.attrresolv.ResolverAttribute,
137          *      java.security.Principal, java.lang.String, java.lang.String,
138          *      edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies)
139          */
140         public void resolve(ResolverAttribute attribute, Principal principal, String requester, String responder,
141                         Dependencies depends) throws ResolutionPlugInException {
142
143                 log.debug("Resolving attribute: (" + getId() + ")");
144                 Set results = new LinkedHashSet();
145                 if (!connectorDependencyIds.isEmpty()) {
146                         results.addAll(Arrays.asList(getValuesFromConnectors(depends)));
147                 }
148
149                 if (!attributeDependencyIds.isEmpty()) {
150                         results.addAll(Arrays.asList(getValuesFromAttributes(depends)));
151                 }
152
153                 standardProcessing(attribute);
154
155                 if (smartScope != null) {
156                         attribute.registerValueHandler(new ScopedStringValueHandler(smartScope));
157                 }
158                 if (smartScope == null && valueHandler != null) {
159                         attribute.registerValueHandler(valueHandler);
160                 }
161
162                 Iterator resultsIt = results.iterator();
163                 while (resultsIt.hasNext()) {
164                         Object value = resultsIt.next();
165                         if (!allowEmpty && ((value == null || value.equals(""))) {
166                                 log.debug("Skipping empty string value.");
167                                 continue;
168                         }
169
170                         if (downCase && value instanceof String) {
171                                 value = ((String) value).toLowerCase();
172                         }
173
174                         attribute.addValue(value);
175                 }
176                 attribute.setResolved();
177         }
178 }