Integrated SCT's attribute definition classes.
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / aa / attrresolv / provider / SimpleBaseAttributeDefinition.java
1 /*
2  * The Shibboleth License, Version 1. Copyright (c) 2002 University Corporation for Advanced Internet Development, Inc.
3  * All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted
4  * provided that the following conditions are met: Redistributions of source code must retain the above copyright
5  * notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above
6  * copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials
7  * provided with the distribution, if any, must include the following acknowledgment: "This product includes software
8  * developed by the University Corporation for Advanced Internet Development <http://www.ucaid.edu>Internet2 Project.
9  * Alternately, this acknowledegement may appear in the software itself, if and wherever such third-party
10  * acknowledgments normally appear. Neither the name of Shibboleth nor the names of its contributors, nor Internet2, nor
11  * the University Corporation for Advanced Internet Development, Inc., nor UCAID may be used to endorse or promote
12  * products derived from this software without specific prior written permission. For written permission, please contact
13  * shibboleth@shibboleth.org Products derived from this software may not be called Shibboleth, Internet2, UCAID, or the
14  * University Corporation for Advanced Internet Development, nor may Shibboleth appear in their name, without prior
15  * written permission of the University Corporation for Advanced Internet Development. THIS SOFTWARE IS PROVIDED BY THE
16  * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE
18  * DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. IN NO
19  * EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC.
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 /*
27  * Contributed by SungGard SCT.
28  */
29
30 package edu.internet2.middleware.shibboleth.aa.attrresolv.provider;
31
32 import java.security.Principal;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Iterator;
36 import java.util.LinkedHashSet;
37 import java.util.Set;
38
39 import javax.naming.NamingEnumeration;
40 import javax.naming.NamingException;
41 import javax.naming.directory.Attribute;
42 import javax.naming.directory.Attributes;
43
44 import org.apache.log4j.Logger;
45 import org.w3c.dom.Element;
46
47 import edu.internet2.middleware.shibboleth.aa.attrresolv.AttributeDefinitionPlugIn;
48 import edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies;
49 import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolutionPlugInException;
50 import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolverAttribute;
51
52 /**
53  * This is an abstract class that all other attribute definitions in this package extend. It provides processing of
54  * common attributes as well as dependency resolutions.
55  * 
56  * @author <a href="mailto:vgoenka@sungardsct.com">Vishal Goenka </a>
57  */
58 abstract class SimpleBaseAttributeDefinition extends BaseAttributeDefinition implements AttributeDefinitionPlugIn {
59
60         private static Logger log = Logger.getLogger(SimpleBaseAttributeDefinition.class.getName());
61
62         protected ValueHandler valueHandler;
63         protected String connectorMapping;
64
65         protected SimpleBaseAttributeDefinition(Element e) throws ResolutionPlugInException {
66
67                 super(e);
68
69                 String sourceName = e.getAttribute("sourceName");
70                 if (sourceName == null || sourceName.equals("")) {
71                         int index = getId().lastIndexOf("#");
72                         if (index < 0) {
73                                 index = getId().lastIndexOf(":");
74                                 int slashIndex = getId().lastIndexOf("/");
75                                 if (slashIndex > index) {
76                                         index = slashIndex;
77                                 }
78                         }
79                         connectorMapping = getId().substring(index + 1);
80                 } else {
81                         connectorMapping = sourceName;
82                 }
83
84                 String valueHandlerSpec = e.getAttribute("valueHandler");
85
86                 if (valueHandlerSpec != null && !valueHandlerSpec.equals("")) {
87                         try {
88                                 Class handlerClass = Class.forName(valueHandlerSpec);
89                                 valueHandler = (ValueHandler) handlerClass.newInstance();
90                         } catch (ClassNotFoundException cnfe) {
91                                 log.error("Value Handler implementation specified for attribute (" + getId() + ") cannot be found: "
92                                                 + cnfe);
93                                 throw new ResolutionPlugInException("Value Handler implementation specified for attribute (" + getId()
94                                                 + ") cannot be found.");
95                         } catch (Exception oe) {
96                                 log.error("Value Handler implementation specified for attribute (" + getId()
97                                                 + ") coudl not be loaded: " + oe);
98                                 throw new ResolutionPlugInException("Value Handler implementation specified for attribute (" + getId()
99                                                 + ") could not be loaded.");
100                         }
101                 }
102
103                 if (valueHandler != null) {
104                         log.debug("Custom Value Handler enabled for attribute (" + getId() + ").");
105                 }
106
107         }
108
109         protected Collection resolveDependencies(ResolverAttribute attribute, Principal principal, String requester,
110                         Dependencies depends) throws ResolutionPlugInException {
111
112                 log.debug("Resolving attribute: (" + getId() + ")");
113                 Set results = new LinkedHashSet();
114                 if (!connectorDependencyIds.isEmpty()) {
115                         results.addAll(Arrays.asList(getValuesFromConnectors(depends)));
116                 }
117
118                 if (!attributeDependencyIds.isEmpty()) {
119                         results.addAll(Arrays.asList(getValuesFromAttributes(depends)));
120                 }
121
122                 if (lifeTime != -1) {
123                         attribute.setLifetime(lifeTime);
124                 }
125
126                 if (valueHandler != null) {
127                         attribute.registerValueHandler(valueHandler);
128                 }
129
130                 return results;
131         }
132
133         protected Object[] getValuesFromAttributes(Dependencies depends) {
134
135                 Set results = new LinkedHashSet();
136
137                 Iterator attrDependIt = attributeDependencyIds.iterator();
138                 while (attrDependIt.hasNext()) {
139                         ResolverAttribute attribute = depends.getAttributeResolution((String) attrDependIt.next());
140                         if (attribute != null) {
141                                 log.debug("Found value(s) for attribute (" + getId() + ").");
142                                 for (Iterator iterator = attribute.getValues(); iterator.hasNext();) {
143                                         results.add(iterator.next());
144                                 }
145                         } else {
146                                 log.error("An attribute dependency of attribute (" + getId()
147                                                 + ") was not included in the dependency chain.");
148                         }
149                 }
150
151                 if (results.isEmpty()) {
152                         log.debug("An attribute dependency of attribute (" + getId() + ") supplied no values.");
153                 }
154                 return results.toArray();
155         }
156
157         protected Object[] getValuesFromConnectors(Dependencies depends) {
158
159                 Set results = new LinkedHashSet();
160
161                 Iterator connectorDependIt = connectorDependencyIds.iterator();
162                 while (connectorDependIt.hasNext()) {
163                         Attributes attrs = depends.getConnectorResolution((String) connectorDependIt.next());
164                         if (attrs != null) {
165                                 Attribute attr = attrs.get(connectorMapping);
166                                 if (attr != null) {
167                                         log.debug("Found value(s) for attribute (" + getId() + ").");
168                                         try {
169                                                 NamingEnumeration valuesEnum = attr.getAll();
170                                                 while (valuesEnum.hasMore()) {
171                                                         results.add(valuesEnum.next());
172                                                 }
173                                         } catch (NamingException e) {
174                                                 log.error("An problem was encountered resolving the dependencies of attribute (" + getId()
175                                                                 + "): " + e);
176                                         }
177                                 }
178                         }
179                 }
180
181                 if (results.isEmpty()) {
182                         log.debug("A connector dependency of attribute (" + getId() + ") supplied no values.");
183                 }
184                 return results.toArray();
185         }
186
187         protected String getString(Object value) {
188
189                 // if (value instanceof String) return (String)value;
190                 // This was inspired by the fact that certain attributes (such as userPassword, when read using JNDI) are
191                 // returned
192                 // from data connectors as byte [] rather than String, and doing a .toString() returns something like
193                 // B[@aabljadj,
194                 // which is a reference to the array, rather than the string value.
195                 if (value instanceof byte[]) return new String((byte[]) value);
196                 return value.toString();
197         }
198
199 }