5ce016b5085bad5377547d031c02804c8c19a0b3
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / aa / AAAttribute.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 package edu.internet2.middleware.shibboleth.aa;
27
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.Iterator;
32 import java.util.List;
33
34 import javax.xml.namespace.QName;
35
36 import org.apache.log4j.Logger;
37 import org.opensaml.SAMLAttribute;
38 import org.opensaml.SAMLException;
39 import org.w3c.dom.Document;
40 import org.w3c.dom.Element;
41
42 import edu.internet2.middleware.shibboleth.aa.arp.ArpAttribute;
43 import edu.internet2.middleware.shibboleth.aa.attrresolv.ResolverAttribute;
44 import edu.internet2.middleware.shibboleth.aa.attrresolv.provider.ValueHandler;
45 import edu.internet2.middleware.shibboleth.aa.attrresolv.provider.ValueHandlerException;
46
47 /**
48  * An attribute for which the Shibboleth Attribute Authority has been asked to provide an assertion.
49  * 
50  * @author Walter Hoehn (wassa@columbia.edu)
51  */
52 public class AAAttribute extends SAMLAttribute implements ResolverAttribute, ArpAttribute {
53
54         private static Logger log = Logger.getLogger(AAAttribute.class.getName());
55         private boolean resolved = false;
56
57         public final static String SHIB_ATTRIBUTE_NAMESPACE_URI = "urn:mace:shibboleth:1.0:attributeNamespace:uri";
58
59         /** Default lifetime, in seconds * */
60         private static long defaultLifetime = 1800; // 30 minutes
61         private ValueHandler valueHandler = new StringValueHandler();
62
63         /**
64          * Constructs a skeleton attribute with no values.
65          * 
66          * @param name
67          *            the name of the attribute
68          * @param legacyCompat
69          *            boolean indicator of whether or not the legacy namespace hack should be used (this is required for SPs
70          *            running old versions of xerces)
71          * @throws SAMLException
72          */
73         public AAAttribute(String name, boolean legacyCompat) throws SAMLException {
74
75                 super(name, SHIB_ATTRIBUTE_NAMESPACE_URI, legacyCompat ? new QName("urn:mace:shibboleth:1.0",
76                                 "AttributeValueType") : null, defaultLifetime, null);
77         }
78
79         /**
80          * Constructs a skeleton attribute with no values.
81          * 
82          * @param name
83          *            the name of the attribute
84          * @throws SAMLException
85          *             if the attribute could not be created
86          */
87         public AAAttribute(String name) throws SAMLException {
88
89                 super(name, SHIB_ATTRIBUTE_NAMESPACE_URI, null, defaultLifetime, null);
90         }
91
92         public AAAttribute(String name, Object[] values) throws SAMLException {
93
94                 this(name);
95                 setValues(values);
96         }
97
98         public AAAttribute(String name, Object[] values, ValueHandler handler) throws SAMLException {
99
100                 this(name);
101                 setValues(values);
102                 registerValueHandler(handler);
103         }
104
105         public boolean hasValues() {
106
107                 if (values.isEmpty()) { return false; }
108                 return true;
109         }
110
111         public Iterator getValues() {
112
113                 return valueHandler.getValues(values);
114         }
115
116         public void setValues(Object[] values) {
117
118                 if (!this.values.isEmpty()) {
119                         this.values.clear();
120                 }
121                 List newList = Arrays.asList(values);
122                 if (newList.contains(null)) {
123                         newList.remove(null);
124                 }
125                 this.values.addAll(newList);
126         }
127
128         /**
129          * @see java.lang.Object#hashCode()
130          */
131         public int hashCode() {
132
133                 int code = 0;
134                 if (values != null) {
135                         Iterator iterator = values.iterator();
136                         while (iterator.hasNext()) {
137                                 code += iterator.next().hashCode();
138                         }
139                 }
140                 return name.hashCode() + code;
141         }
142
143         /**
144          * @see edu.internet2.middleware.shibboleth.aa.attrresolv.ArpAttribute#resolved()
145          */
146         public boolean resolved() {
147
148                 return resolved;
149         }
150
151         /**
152          * @see edu.internet2.middleware.shibboleth.aa.attrresolv.ArpAttribute#setResolved()
153          */
154         public void setResolved() {
155
156                 resolved = true;
157         }
158
159         /**
160          * @see edu.internet2.middleware.shibboleth.aa.attrresolv.ArpAttribute#resolveFromCached(edu.internet2.middleware.shibboleth.aa.attrresolv.ArpAttribute)
161          */
162         public void resolveFromCached(ResolverAttribute attribute) {
163
164                 resolved = true;
165                 setLifetime(attribute.getLifetime());
166
167                 if (!this.values.isEmpty()) {
168                         this.values.clear();
169                 }
170                 for (Iterator iterator = attribute.getValues(); iterator.hasNext();) {
171                         values.add(iterator.next());
172                 }
173
174                 registerValueHandler(attribute.getRegisteredValueHandler());
175         }
176
177         public void setLifetime(long lifetime) {
178
179                 this.lifetime = lifetime;
180
181         }
182
183         public void addValue(Object value) {
184
185                 if (value != null) {
186                         values.add(value);
187                 }
188         }
189
190         /*
191          * @see org.opensaml.SAMLAttribute#valueToDOM(int, org.w3c.dom.Element)
192          */
193         protected void valueToDOM(int index, Element e) throws SAMLException {
194
195                 try {
196                         valueHandler.toDOM(e, values.get(index), e.getOwnerDocument());
197
198                 } catch (ValueHandlerException ex) {
199                         log.error("Value Handler unable to convert value to DOM Node: " + ex);
200                 }
201         }
202
203         /**
204          * @see edu.internet2.middleware.shibboleth.aa.attrresolv.ArpAttribute#registerValueHandler(edu.internet2.middleware.shibboleth.aa.attrresolv.provider.ValueHandler)
205          */
206         public void registerValueHandler(ValueHandler handler) {
207
208                 valueHandler = handler;
209         }
210
211         /**
212          * @see edu.internet2.middleware.shibboleth.aa.attrresolv.ArpAttribute#getRegisteredValueHandler()
213          */
214         public ValueHandler getRegisteredValueHandler() {
215
216                 return valueHandler;
217         }
218
219         /**
220          * @see java.lang.Object#equals(java.lang.Object)
221          */
222         public boolean equals(Object object) {
223
224                 if (!(object instanceof AAAttribute)) { return false; }
225                 if (lifetime != ((AAAttribute) object).lifetime) { return false; }
226                 if (!name.equals(((AAAttribute) object).name)) { return false; }
227                 if (!valueHandler.equals(((AAAttribute) object).valueHandler)) { return false; }
228
229                 ArrayList localValues = new ArrayList();
230                 for (Iterator iterator = getValues(); iterator.hasNext();) {
231                         localValues.add(iterator.next());
232                 }
233
234                 ArrayList objectValues = new ArrayList();
235                 for (Iterator iterator = ((AAAttribute) object).getValues(); iterator.hasNext();) {
236                         objectValues.add(iterator.next());
237                 }
238
239                 return localValues.equals(objectValues);
240         }
241
242 }
243
244 /**
245  * Default <code>ValueHandler</code> implementation. Expects all values to be String objects.
246  * 
247  * @author Walter Hoehn (wassa@columbia.edu)
248  */
249
250 class StringValueHandler implements ValueHandler {
251
252         public void toDOM(Element valueElement, Object value, Document document) {
253
254                 valueElement.appendChild(document.createTextNode(value.toString()));
255         }
256
257         public Iterator getValues(Collection internalValues) {
258
259                 return internalValues.iterator();
260         }
261
262         /**
263          * @see java.lang.Object#equals(java.lang.Object)
264          */
265         public boolean equals(Object object) {
266
267                 if (object instanceof StringValueHandler) { return true; }
268                 return false;
269         }
270
271 }