e081fa57a9ce07f675b70ce35cc318521705a852
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / aa / arp / provider / BaseArpRepository.java
1 /* 
2  * The Shibboleth License, Version 1. 
3  * Copyright (c) 2002 
4  * University Corporation for Advanced Internet Development, Inc. 
5  * All rights reserved
6  * 
7  * 
8  * Redistribution and use in source and binary forms, with or without 
9  * modification, are permitted provided that the following conditions are met:
10  * 
11  * Redistributions of source code must retain the above copyright notice, this 
12  * list of conditions and the following disclaimer.
13  * 
14  * Redistributions in binary form must reproduce the above copyright notice, 
15  * this list of conditions and the following disclaimer in the documentation 
16  * and/or other materials provided with the distribution, if any, must include 
17  * the following acknowledgment: "This product includes software developed by 
18  * the University Corporation for Advanced Internet Development 
19  * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement 
20  * may appear in the software itself, if and wherever such third-party 
21  * acknowledgments normally appear.
22  * 
23  * Neither the name of Shibboleth nor the names of its contributors, nor 
24  * Internet2, nor the University Corporation for Advanced Internet Development, 
25  * Inc., nor UCAID may be used to endorse or promote products derived from this 
26  * software without specific prior written permission. For written permission, 
27  * please contact shibboleth@shibboleth.org
28  * 
29  * Products derived from this software may not be called Shibboleth, Internet2, 
30  * UCAID, or the University Corporation for Advanced Internet Development, nor 
31  * may Shibboleth appear in their name, without prior written permission of the 
32  * University Corporation for Advanced Internet Development.
33  * 
34  * 
35  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
36  * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
37  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
38  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK 
39  * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. 
40  * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY 
41  * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, 
42  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49
50 package edu.internet2.middleware.shibboleth.aa.arp.provider;
51
52 import java.io.IOException;
53 import java.security.Principal;
54 import java.util.HashMap;
55 import java.util.HashSet;
56 import java.util.Map;
57 import java.util.Properties;
58 import java.util.Set;
59
60 import org.apache.log4j.Logger;
61 import org.w3c.dom.Element;
62 import org.xml.sax.SAXException;
63
64 import edu.internet2.middleware.shibboleth.aa.arp.Arp;
65 import edu.internet2.middleware.shibboleth.aa.arp.ArpMarshallingException;
66 import edu.internet2.middleware.shibboleth.aa.arp.ArpRepository;
67 import edu.internet2.middleware.shibboleth.aa.arp.ArpRepositoryException;
68
69 /**
70  * Provides marshalling/unmarshalling functionality common among 
71  * <code>ArpRepository</code> implementations.
72  * 
73  * @author Walter Hoehn (wassa@columbia.edu)
74  */
75
76 public abstract class BaseArpRepository implements ArpRepository {
77
78         private static Logger log = Logger.getLogger(BaseArpRepository.class.getName());
79         private ArpCache arpCache;
80
81         BaseArpRepository(Properties properties) {
82                 if (properties
83                         .getProperty(
84                                 "edu.internet2.middleware.shibboleth.aa.arp.BaseArpRepository.ArpTTL",
85                                 null)
86                         != null) {
87                         arpCache = ArpCache.instance();
88                         arpCache.setCacheLength(
89                                 Long.parseLong(
90                                         properties.getProperty(
91                                                 "edu.internet2.middleware.shibboleth.aa.arp.BaseArpRepository.ArpTTL",
92                                                 null)));
93                 }
94         }
95
96         /**
97          * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getAllPolicies(Principal)
98          */
99
100         public Arp[] getAllPolicies(Principal principal) throws ArpRepositoryException {
101                 log.debug(
102                         "Received a query for all policies applicable to principal: ("
103                                 + principal.getName()
104                                 + ").");
105                 Set allPolicies = new HashSet();
106                 Arp sitePolicy = getSitePolicy();
107                 if (sitePolicy != null) {
108                         log.debug("Returning site policy.");
109                         allPolicies.add(sitePolicy);
110                 }
111                 
112                 Arp userPolicy = getUserPolicy(principal);
113                 if (userPolicy != null) {
114                         allPolicies.add(userPolicy);
115                         log.debug("Returning user policy.");
116                 }
117                 if (allPolicies.isEmpty()) {
118                         log.debug("No policies found.");
119                 }
120                 return (Arp[]) allPolicies.toArray(new Arp[0]);
121         }
122
123         /**
124          * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getSitePolicy()
125          */
126         public Arp getSitePolicy() throws ArpRepositoryException {
127
128                 try {
129                         if (arpCache != null) {
130                                 Arp cachedArp = arpCache.retrieveSiteArpFromCache();
131                                 if (cachedArp != null) {
132                                         log.debug("Using cached site ARP.");
133                                         return cachedArp;
134                                 }
135                         }
136
137                         Element xml = retrieveSiteArpXml();
138                         if (xml == null) {
139                                 return null;
140                         }
141
142                         Arp siteArp = new Arp();
143                         siteArp.marshall(xml);
144                         if (arpCache != null) {
145                                 arpCache.cache(siteArp);
146                         }
147                         return siteArp;
148                 } catch (ArpMarshallingException ame) {
149                         log.error("An error occurred while marshalling an ARP: " + ame);
150                         throw new ArpRepositoryException("An error occurred while marshalling an ARP.");
151                 } catch (IOException ioe) {
152                         log.error("An error occurred while loading an ARP: " + ioe);
153                         throw new ArpRepositoryException("An error occurred while loading an ARP.");
154                 } catch (SAXException se) {
155                         log.error("An error occurred while parsing an ARP: " + se);
156                         throw new ArpRepositoryException("An error occurred while parsing an ARP.");
157                 }
158         }
159
160         /**
161          * Inheritors must return the site Arp as an xml element.
162          * @return Element
163          */
164         protected abstract Element retrieveSiteArpXml() throws IOException, SAXException;
165
166         /**
167          * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getUserPolicy(Principal)
168          */
169         public Arp getUserPolicy(Principal principal) throws ArpRepositoryException {
170
171                 if (arpCache != null) {
172                         Arp cachedArp = arpCache.retrieveUserArpFromCache(principal);
173                         if (cachedArp != null) {
174                                 log.debug("Using cached user ARP.");
175                                 return cachedArp;
176                         }
177                 }
178
179                 try {
180                         Element xml = retrieveUserArpXml(principal);
181                         if (xml == null) {
182                                 return null;
183                         }
184
185                         Arp userArp = new Arp();
186                         userArp.setPrincipal(principal);
187
188                         userArp.marshall(xml);
189                         if (arpCache != null) {
190                                 arpCache.cache(userArp);
191                         }
192                         return userArp;
193                 } catch (ArpMarshallingException ame) {
194                         log.error("An error occurred while marshalling an ARP: " + ame);
195                         throw new ArpRepositoryException("An error occurred while marshalling an ARP.");
196                 } catch (IOException ioe) {
197                         log.error("An error occurred while loading an ARP: " + ioe);
198                         throw new ArpRepositoryException("An error occurred while loading an ARP.");
199                 } catch (SAXException se) {
200                         log.error("An error occurred while parsing an ARP: " + se);
201                         throw new ArpRepositoryException("An error occurred while parsing an ARP.");
202                 }
203         }
204
205         /**
206          * Inheritors must return the user Arp as an xml element.
207          * @return Element
208          */
209         protected abstract Element retrieveUserArpXml(Principal principal)
210                 throws IOException, SAXException;
211
212 }
213
214 class ArpCache {
215
216         private static ArpCache instance = null;
217         private long cacheLength;
218         private Map cache = new HashMap();
219
220         protected ArpCache() {
221         }
222
223         static ArpCache instance() {
224                 if (instance == null) {
225                         return new ArpCache();
226                 }
227                 return instance;
228         }
229
230         void setCacheLength(long cacheLength) {
231                 this.cacheLength = cacheLength;
232         }
233
234         void cache(Arp arp) {
235                 if (arp.isSitePolicy() == false) {
236                         cache.put(arp.getPrincipal(), new CachedArp(arp, System.currentTimeMillis()));
237                 } else {
238                         cache.put(new SiteCachePrincipal(), new CachedArp(arp, System.currentTimeMillis()));
239                 }
240         }
241
242         Arp retrieveUserArpFromCache(Principal principal) {
243                 return retrieveArpFromCache(principal);
244         }
245
246         Arp retrieveSiteArpFromCache() {
247                 return retrieveArpFromCache(new SiteCachePrincipal());
248         }
249
250         private Arp retrieveArpFromCache(Principal principal) {
251                 CachedArp cachedArp = (CachedArp) cache.get(principal);
252                 if (cachedArp == null) {
253                         return null;
254                 }
255
256                 if ((System.currentTimeMillis() - cachedArp.creationTimeMillis) < cacheLength) {
257                         return cachedArp.arp;
258                 }
259                 cache.remove(principal);
260                 return null;
261         }
262
263         class CachedArp {
264                 Arp arp;
265                 long creationTimeMillis;
266
267                 CachedArp(Arp arp, long creationTimeMillis) {
268                         this.arp = arp;
269                         this.creationTimeMillis = creationTimeMillis;
270                 }
271         }
272
273         class SiteCachePrincipal implements Principal {
274
275                 public String getName() {
276                         return "ARP admin";
277                 }
278
279                 /**
280                  * @see java.lang.Object#equals(Object)
281                  */
282                 public boolean equals(Object object) {
283                         if (object instanceof SiteCachePrincipal) {
284                                 return true;
285                         }
286                         return false;
287                 }
288
289                 /**
290                  * @see java.lang.Object#hashCode()
291                  */
292                 public int hashCode() {
293                         return "edu.internet2.middleware.shibboleth.aa.arp.provider.BaseArpRepository.SiteCachePrincipal"
294                                 .hashCode();
295                 }
296         }
297 }