0bc0e6f6462ce116143a1927708199d2a494a420
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / aa / arp / Rule.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;
51
52 import java.net.URI;
53 import java.net.URISyntaxException;
54 import java.net.URL;
55
56 import org.apache.log4j.Logger;
57 import org.apache.xerces.parsers.DOMParser;
58 import org.w3c.dom.CharacterData;
59 import org.w3c.dom.Document;
60 import org.w3c.dom.Element;
61 import org.w3c.dom.Node;
62 import org.w3c.dom.NodeList;
63
64 /**
65  *  An Attribute Release Policy Rule.
66  *
67  * @author Walter Hoehn (wassa@columbia.edu)
68  */
69
70 public class Rule {
71
72         private String description;
73         private Target target;
74         private static Logger log = Logger.getLogger(Rule.class.getName());
75
76         /**
77          * Returns the description for this <code>Rule</code>.
78          * @return String
79          */
80
81         public String getDescription() {
82                 return description;
83         }
84
85         /**
86          * Sets the description for this <code>Rule</code>.
87          * @param description The description to set
88          */
89
90         public void setDescription(String description) {
91                 this.description = description;
92         }
93
94         /**
95          * Unmarshalls the <code>Rule</code> into an xml <code>Element</code>.
96          * @return the xml <code>Element</code>
97          */
98
99         public Element unmarshall() {
100
101                 DOMParser parser = new DOMParser();
102                 Document placeHolder = parser.getDocument();
103                 Element ruleNode = placeHolder.createElement("Rule");
104
105                 if (description != null) {
106                         Element descriptionNode = placeHolder.createElement("Description");
107                         descriptionNode.appendChild(placeHolder.createTextNode(description));
108                         ruleNode.appendChild(descriptionNode);
109                 }
110
111                 return ruleNode;
112         }
113
114         /**
115          * Creates an ARP Rule from an xml representation.
116          * @param the xml <code>Element</code> containing the ARP Rule.
117          */
118
119         public void marshall(Element element) throws ArpMarshallingException {
120
121                 //Make sure we are dealing with a Rule
122                 if (!element.getTagName().equals("Rule")) {
123                         log.error("Element data does not represent an ARP Rule.");
124                         throw new ArpMarshallingException("Element data does not represent an ARP Rule.");
125                 }
126
127                 //Grab the description
128                 NodeList descriptionNodes = element.getElementsByTagName("Description");
129                 if (descriptionNodes.getLength() > 0) {
130                         Element descriptionNode = (Element) descriptionNodes.item(0);
131                         if (descriptionNode.hasChildNodes()
132                                 && descriptionNode.getFirstChild().getNodeType() == Node.TEXT_NODE) {
133                                 description = ((CharacterData) descriptionNode.getFirstChild()).getData();
134                         }
135                 }
136
137                 //Create the Target
138                 NodeList targetNodes = element.getElementsByTagName("Target");
139                 if (targetNodes.getLength() != 1) {
140                         log.error(
141                                 "Element data does not represent an ARP Rule.  An ARP Rule must contain 1 and "
142                                         + "only 1 Target definition.");
143                         throw new ArpMarshallingException(
144                                 "Element data does not represent an ARP Rule.  An"
145                                         + " ARP Rule must contain 1 and only 1 Target definition.");
146                 }
147                 target = new Target();
148                 target.marshall((Element) targetNodes.item(0));
149         }
150
151         /**
152          * Method matchesRequest.
153          * @param requester
154          * @param resource
155          * @return boolean
156          */
157         public boolean matchesRequest(String requester, URL resource) {
158                 if (target.matchesAny()) {
159                         return true;
160                 }
161                 try {
162                         MatchFunction requesterFunction =
163                                 ArpEngine.lookupMatchFunction(target.getRequester().getMatchFunctionIdentifier());
164                         if (!requesterFunction.match(target.getRequester().getValue(), requester)) {
165                                 return false;
166                         }
167                         if (target.getResource().matchesAny()) {
168                                 return true;
169                         }
170                         MatchFunction resourceFunction =
171                                 ArpEngine.lookupMatchFunction(target.getResource().getMatchFunctionIdentifier());
172                         if (resourceFunction.match(target.getResource().getValue(), resource)) {
173                                 return true;
174                         }
175                         return false;
176                 } catch (ArpException e) {
177                         log.warn("Encountered a problem while trying to find matching ARP rules: " + e);
178                         return false;
179                 }
180         }
181
182         class Target {
183                 private Requester requester = null;
184                 private Resource resource = null;
185                 private boolean matchesAny = false;
186
187                 void marshall(Element element) throws ArpMarshallingException {
188
189                         //Make sure we are deling with a Target
190                         if (!element.getTagName().equals("Target")) {
191                                 log.error("Element data does not represent an ARP Rule Target.");
192                                 throw new ArpMarshallingException("Element data does not represent an ARP Rule target.");
193                         }
194                         NodeList targetNodeList = element.getChildNodes();
195                         if (targetNodeList.getLength() < 1 || targetNodeList.getLength() > 2) {
196                                 log.error("ARP Rule Target contains invalid data: incorrect number of elements");
197                                 throw new ArpMarshallingException("ARP Rule Target contains invalid data: incorrect number of elements");
198                         }
199
200                         //Handle <AnyTarget/> definitions
201                         if (targetNodeList.getLength() == 1) {
202                                 if (targetNodeList.item(0).getNodeType() == Node.ELEMENT_NODE
203                                         && ((Element) targetNodeList.item(0)).getTagName().equals("AnyTarget")) {
204                                         matchesAny = true;
205                                         return;
206                                 }
207                                 log.error("ARP Rule Target contains invalid data.");
208                                 throw new ArpMarshallingException("ARP Rule Target contains invalid data.");
209                         }
210
211                         //Create Requester
212                         if (targetNodeList.item(0).getNodeType() == Node.ELEMENT_NODE
213                                 && ((Element) targetNodeList.item(0)).getTagName().equals("Requester")) {
214                                 requester = new Requester();
215                                 requester.marshall((Element) targetNodeList.item(0));
216                         } else {
217                                 log.error("ARP Rule Target contains invalid data.");
218                                 throw new ArpMarshallingException("ARP Rule Target contains invalid data.");
219                         }
220                         //Handle <AnyResource/>
221                         //Create Resource
222                 }
223
224                 boolean matchesAny() {
225                         return matchesAny;
226                 }
227                 Requester getRequester() {
228                         return requester;
229                 }
230                 Resource getResource() {
231                         return resource;
232                 }
233         }
234
235         class Resource {
236                 private String value;
237                 private URI matchFunctionIdentifier;
238                 private boolean matchesAny;
239                 boolean matchesAny() {
240                         return matchesAny;
241                 }
242                 URI getMatchFunctionIdentifier() {
243                         return matchFunctionIdentifier;
244                 }
245                 String getValue() {
246                         return value;
247                 }
248         }
249
250         class Requester {
251                 private String value;
252                 private URI matchFunctionIdentifier;
253                 URI getMatchFunctionIdentifier() {
254                         return matchFunctionIdentifier;
255                 }
256                 String getValue() {
257                         return value;
258                 }
259                 void marshall(Element element) throws ArpMarshallingException {
260                         //Make sure we are deling with a Requester
261                         if (!element.getTagName().equals("Requester")) {
262                                 log.error("Element data does not represent an ARP Rule Target.");
263                                 throw new ArpMarshallingException("Element data does not represent an ARP Rule target.");
264                         }
265                         if (element.hasChildNodes() && element.getFirstChild().getNodeType() == Node.TEXT_NODE) {
266                                 value = ((CharacterData) element.getFirstChild()).getData();
267                         } else {
268                                 log.error("Element data does not represent an ARP Rule Target.");
269                                 throw new ArpMarshallingException("Element data does not represent an ARP Rule target.");
270                         }
271                         try {
272                                 if (element.hasAttribute("matchFunction")) {
273                                         matchFunctionIdentifier = new URI(element.getAttribute("matchFunction"));
274                                 } else {
275                                         matchFunctionIdentifier = new URI("urn:mace:shibboleth:arp:matchFunction:exactShar");
276                                 }
277                         } catch (URISyntaxException e) {
278                                 log.error("ARP match function not identified by a proper URI.");
279                                 throw new ArpMarshallingException("ARP match function not identified by a proper URI.");
280                         }
281                 }
282         }
283
284 }