001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: RequestImpl.java,v 1.4 2008/11/10 22:57:05 veiming Exp $ 026 * 027 */ 028 029package com.sun.identity.xacml.context.impl; 030 031import com.sun.identity.xacml.common.XACMLSDKUtils; 032import com.sun.identity.shared.xml.XMLUtils; 033import com.sun.identity.xacml.common.XACMLConstants; 034import com.sun.identity.xacml.common.XACMLException; 035import com.sun.identity.xacml.context.Attribute; 036import com.sun.identity.xacml.context.ContextFactory; 037import com.sun.identity.xacml.context.Resource; 038import com.sun.identity.xacml.context.Request; 039import com.sun.identity.xacml.context.Subject; 040import com.sun.identity.xacml.context.Action; 041import com.sun.identity.xacml.context.Environment; 042import com.sun.identity.xacml.context.impl.ActionImpl; 043import com.sun.identity.xacml.context.impl.EnvironmentImpl; 044import java.util.ArrayList; 045import java.util.HashSet; 046 047import java.util.List; 048import java.util.Set; 049import org.w3c.dom.Document; 050import org.w3c.dom.Element; 051import org.w3c.dom.Node; 052import org.w3c.dom.NodeList; 053 054/** 055 * The <code>Request</code> element is the top-level element in the XACML 056 * context schema. Its an abstraction layer used by the policy language. 057 * It contains <code>Subject</code>, <code>Resource</code>, <code>Action 058 * </code> and <code>Environment<code> elements. 059 * <p> 060 * <pre> 061 * <xs:complexType name="RequestType"> 062 * <xs:sequence> 063 * <xs:element ref="xacml-context:Subject" maxOccurs="unbounded"/> 064 * <xs:element ref="xacml-context:Resource" maxOccurs="unbounded"/> 065 * <xs:element ref="xacml-context:Action"/> 066 * <xs:element ref="xacml-context:Environment"/> 067 * <xs:sequence> 068 * <xs:complexType> 069 * </pre> 070 *@supported.all.api 071 */ 072public class RequestImpl implements Request { 073 074 private List subjects = new ArrayList(); 075 private List resources = new ArrayList(); 076 private Action action = null; 077 private Environment env = null; 078 private boolean isMutable = true; 079 080 private static Set supportedSubjectCategory = new HashSet(); 081 static { 082 supportedSubjectCategory.add(XACMLConstants.ACCESS_SUBJECT); 083 supportedSubjectCategory.add(XACMLConstants. 084 INTERMEDIARY_SUBJECT); 085 }; 086 /** 087 * Default constructor 088 */ 089 public RequestImpl() { 090 } 091 092 /** 093 * This constructor is used to build <code>Request</code> object from a 094 * XML string. 095 * 096 * @param xml A <code>java.lang.String</code> representing 097 * a <code>Request</code> object 098 * @exception XACMLException if it could not process the XML string 099 */ 100 public RequestImpl(String xml) throws XACMLException { 101 Document document = XMLUtils.toDOMDocument(xml, XACMLSDKUtils.debug); 102 if (document != null) { 103 Element rootElement = document.getDocumentElement(); 104 processElement(rootElement); 105 makeImmutable(); 106 } else { 107 XACMLSDKUtils.debug.error( 108 "RequestImpl.processElement(): invalid XML input"); 109 throw new XACMLException( 110 XACMLSDKUtils.xacmlResourceBundle.getString( 111 "errorObtainingElement")); 112 } 113 } 114 115 /** 116 * This constructor is used to build <code>Request</code> object from a 117 * block of existing XML that has already been built into a DOM. 118 * 119 * @param element A <code>org.w3c.dom.Element</code> representing 120 * DOM tree for <code>Request</code> object 121 * @exception XACML2Exception if it could not process the Element 122 */ 123 public RequestImpl(Element element) throws XACMLException { 124 processElement(element); 125 makeImmutable(); 126 } 127 128 private void processElement(Element element) throws XACMLException { 129 if (element == null) { 130 XACMLSDKUtils.debug.error( 131 "RequestImpl.processElement(): invalid root element"); 132 throw new XACMLException( 133 XACMLSDKUtils.xacmlResourceBundle.getString( 134 "invalid_element")); 135 } 136 String elemName = element.getLocalName(); 137 if (elemName == null) { 138 XACMLSDKUtils.debug.error( 139 "RequestImpl.processElement(): local name missing"); 140 throw new XACMLException( 141 XACMLSDKUtils.xacmlResourceBundle.getString( 142 "missing_local_name")); 143 } 144 145 if (!elemName.equals(XACMLConstants.REQUEST)) { 146 XACMLSDKUtils.debug.error( 147 "RequestImpl.processElement(): invalid local name " + 148 elemName); 149 throw new XACMLException( 150 XACMLSDKUtils.xacmlResourceBundle.getString( 151 "invalid_local_name")); 152 } 153 154 // starts processing subelements 155 NodeList nodes = element.getChildNodes(); 156 int numOfNodes = nodes.getLength(); 157 if (numOfNodes < 1) { 158 XACMLSDKUtils.debug.error( 159 "RequestImpl.processElement(): request has no subelements"); 160 throw new XACMLException( 161 XACMLSDKUtils.xacmlResourceBundle.getString( 162 "missing_subelements")); 163 } 164 165 ContextFactory factory = ContextFactory.getInstance(); 166 List children = new ArrayList(); 167 int i = 0; 168 Node child; 169 while ( i < numOfNodes) { 170 child = (Node)nodes.item(i); 171 if (child.getNodeType() == Node.ELEMENT_NODE) { 172 children.add(child); 173 } 174 i++; 175 } 176 if (children.isEmpty()) { 177 XACMLSDKUtils.debug.error("RequestImpl.processElement():" 178 + " request has no subelements"); 179 throw new XACMLException( 180 XACMLSDKUtils.xacmlResourceBundle.getString( 181 "missing_subelements")); 182 } 183 child = (Node)children.get(0); 184 // The first subelement should be <Subject> 185 String childName = child.getLocalName(); 186 if ((childName == null) || (!childName. 187 equals(XACMLConstants.SUBJECT))) { 188 XACMLSDKUtils.debug.error("RequestImpl.processElement():"+ 189 " the first element is not <Subject>"); 190 throw new XACMLException( 191 XACMLSDKUtils.xacmlResourceBundle.getString( 192 "missing_subelement_subject")); 193 } 194 Subject subject = factory.getInstance().createSubject((Element)child); 195 if (!supportedSubjectCategory.contains( 196 subject.getSubjectCategory().toString())) 197 { 198 XACMLSDKUtils.debug.error("RequestImpl.processElement():subject " 199 +"category in subject not supported"); 200 throw new XACMLException( 201 XACMLSDKUtils.xacmlResourceBundle.getString( 202 "unsupported_subject_category")); 203 } 204 subjects.add(subject); 205 boolean resourceFound = false; 206 boolean actionFound = false; 207 boolean envFound = false; 208 for ( int j = 1; j < children.size(); j++) { 209 child = (Node)children.get(j); 210 // so far <Resource> is not encountered 211 // Go through next sub elements for <Subject> and <Resource> 212 // The next subelement may be <Resource> or <Subject> 213 childName = child.getLocalName(); 214 if ((childName != null) && 215 (childName.equals(XACMLConstants.RESOURCE) || childName. 216 equals(XACMLConstants.SUBJECT))) { 217 if (resourceFound) { 218 if (childName.equals(XACMLConstants.SUBJECT)) { 219 // all <Subject> should be before <Resource> 220 XACMLSDKUtils.debug.error("RequestImpl." 221 +"processElement(): <Subject> should be " 222 + "before <Resource>"); 223 throw new XACMLException( 224 XACMLSDKUtils.xacmlResourceBundle.getString( 225 "element_out_of_place")); 226 } else { // found another resource 227 Resource resource = factory.getInstance() 228 .createResource(( 229 Element)child); 230 resources.add(resource); 231 } 232 } else if (childName.equals(XACMLConstants.SUBJECT)) { 233 subject = factory.getInstance().createSubject( 234 (Element)child); 235 subjects.add(subject); 236 } else { // childname is resource 237 resourceFound = true; 238 Resource resource = factory.getInstance() 239 .createResource(( 240 Element)child); 241 resources.add(resource); 242 } 243 } else if ((childName != null) && (childName. 244 equals(XACMLConstants.ACTION))) { 245 if (!resourceFound) { 246 XACMLSDKUtils.debug.error("RequestImpl." 247 +"processElement(): <Resource> should be " 248 + "before <Action>"); 249 throw new XACMLException( 250 XACMLSDKUtils.xacmlResourceBundle.getString( 251 "element_out_of_place")); 252 } else { 253 actionFound = true; 254 action = factory.createAction((Element)child); 255 } 256 } else if ((childName != null) && (childName. 257 equals(XACMLConstants.ENVIRONMENT))) { 258 if (!resourceFound || !actionFound){ 259 XACMLSDKUtils.debug.error("RequestImpl." 260 +"processElement(): <Resource> and " 261 +"Action should be before <Environment>"); 262 throw new XACMLException( 263 XACMLSDKUtils.xacmlResourceBundle.getString( 264 "element_out_of_place")); 265 } else { 266 envFound = true; 267 env = factory.createEnvironment((Element) child); 268 } 269 } 270 } 271 if (XACMLSDKUtils.debug.messageEnabled()) { 272 XACMLSDKUtils.debug.message("resourceFound:"+resourceFound); 273 XACMLSDKUtils.debug.message("actionFound:"+actionFound); 274 XACMLSDKUtils.debug.message("envFound:"+envFound); 275 } 276 if (!resourceFound || !actionFound || !envFound) { 277 XACMLSDKUtils.debug.error("RequestImpl.processElement(): Some" 278 +"of required elements are missing"); 279 throw new XACMLException( 280 XACMLSDKUtils.xacmlResourceBundle.getString( 281 "missing_subelements")); 282 } 283 } 284 285 286 /** 287 * Returns the one to many <code>Subject</code> elements of this object 288 * 289 * @return the <code>Subject</code> elements of this object 290 */ 291 public List getSubjects() { 292 return subjects; 293 } 294 295 /** 296 * Sets the one to many <code>Subject</code> elements of this object 297 * 298 * @param subjects the one to many <code>Subject</code> elements of this 299 * object 300 * 301 * @exception XACMLException if the object is immutable 302 * An object is considered <code>immutable</code> if <code> 303 * makeImmutable()</code> has been invoked on it. It can 304 * be determined by calling <code>isMutable</code> on the object. 305 */ 306 public void setSubjects(List subjects) throws XACMLException { 307 if (!isMutable) { 308 throw new XACMLException( 309 XACMLSDKUtils.xacmlResourceBundle.getString( 310 "objectImmutable")); 311 } 312 if (subjects == null || subjects.isEmpty()) { 313 throw new XACMLException( 314 XACMLSDKUtils.xacmlResourceBundle.getString( 315 "null_not_valid")); 316 } 317 this.subjects.addAll(subjects); 318 } 319 320 321 /** 322 * Returns the one to many <code>Resource</code> elements of this object 323 * 324 * @return the <code>Resource</code> elements of this object 325 */ 326 public List getResources() { 327 return resources; 328 } 329 330 /** 331 * Sets the one to many <code>Resource</code> elements of this object 332 * 333 * @param resources the one to many <code>Resource</code> elements of this 334 * object 335 * 336 * @exception XACMLException if the object is immutable 337 * An object is considered <code>immutable</code> if <code> 338 * makeImmutable()</code> has been invoked on it. It can 339 * be determined by calling <code>isMutable</code> on the object. 340 */ 341 public void setResources(List resources) throws XACMLException { 342 if (!isMutable) { 343 throw new XACMLException( 344 XACMLSDKUtils.xacmlResourceBundle.getString( 345 "objectImmutable")); 346 } 347 if (resources == null || resources.isEmpty()) { 348 throw new XACMLException( 349 XACMLSDKUtils.xacmlResourceBundle.getString("null_not_valid")); 350 } 351 this.resources.addAll(resources); 352 } 353 354 /** 355 * Returns the instance of <code>Action</code> element 356 * 357 * @return the instance of <code>Action</code>. 358 */ 359 public Action getAction() { 360 return action; 361 } 362 363 /** 364 * Sets the instance of <code>Action</code> 365 * 366 * @param argAction instance of <code>Action</code>. 367 * 368 * @exception XACMLException if the object is immutable 369 * An object is considered <code>immutable</code> if <code> 370 * makeImmutable()</code> has been invoked on it. It can 371 * be determined by calling <code>isMutable</code> on the object. 372 */ 373 public void setAction(Action argAction) throws XACMLException { 374 if (!isMutable) { 375 throw new XACMLException( 376 XACMLSDKUtils.xacmlResourceBundle.getString( 377 "objectImmutable")); 378 } 379 380 if (argAction == null) { 381 throw new XACMLException( 382 XACMLSDKUtils.xacmlResourceBundle.getString("null_not_valid")); 383 } 384 action = argAction; 385 386 } 387 388 /** 389 * Returns the instance of <code>Environment</code> element. 390 * 391 * @return the instance of <code>Environment</code>. 392 */ 393 public Environment getEnvironment() { 394 return env; 395 } 396 397 /** 398 * Sets the instance of the <code>Environment</code> 399 * 400 * @param argEnv instance of <code>Environment</code>. 401 * @throws XACMLException if the object is immutable 402 * An object is considered <code>immutable</code> if <code> 403 * makeImmutable()</code> has been invoked on it. It can 404 * be determined by calling <code>isMutable</code> on the object. 405 */ 406 public void setEnvironment(Environment argEnv) throws XACMLException { 407 if (!isMutable) { 408 throw new XACMLException( 409 XACMLSDKUtils.xacmlResourceBundle.getString( 410 "objectImmutable")); 411 } 412 if (argEnv == null ) { 413 throw new XACMLException( 414 XACMLSDKUtils.xacmlResourceBundle.getString("null_not_valid")); 415 } 416 env = argEnv; 417 } 418 419 /** 420 * Returns a <code>String</code> representation of this object 421 * @param includeNSPrefix Determines whether or not the namespace qualifier 422 * is prepended to the Element when converted 423 * @param declareNS Determines whether or not the namespace is declared 424 * within the Element. 425 * @return a string representation of this object 426 * @exception XACMLException if conversion fails for any reason 427 */ 428 public String toXMLString(boolean includeNSPrefix, boolean declareNS) 429 throws XACMLException { 430 StringBuffer sb = new StringBuffer(2000); 431 StringBuffer namespaceBuffer = new StringBuffer(100); 432 String nsDeclaration = ""; 433 if (declareNS) { 434 namespaceBuffer.append(XACMLConstants.CONTEXT_NS_DECLARATION). 435 append(XACMLConstants.SPACE); 436 namespaceBuffer.append(XACMLConstants.XSI_NS_URI). 437 append(XACMLConstants.SPACE).append(XACMLConstants. 438 CONTEXT_SCHEMA_LOCATION); 439 } 440 if (includeNSPrefix) { 441 nsDeclaration = XACMLConstants.CONTEXT_NS_PREFIX + ":"; 442 } 443 sb.append("\n<").append(nsDeclaration).append(XACMLConstants.REQUEST). 444 append(namespaceBuffer).append(">\n"); 445 int length = 0; 446 if (subjects != null && !subjects.isEmpty()) { 447 length = subjects.size(); 448 for (int i = 0; i < length; i++) { 449 Subject sub = (Subject)subjects.get(i); 450 sb.append(sub.toXMLString(includeNSPrefix, false)); 451 } 452 } 453 if (resources != null && !resources.isEmpty()) { 454 length = resources.size(); 455 for (int i = 0; i < length; i++) { 456 Resource resource = (Resource)resources.get(i); 457 sb.append(resource.toXMLString(includeNSPrefix, false)); 458 } 459 } 460 if (action != null) { 461 sb.append(action.toXMLString(includeNSPrefix, false)); 462 } 463 if (env != null) { 464 sb.append(env.toXMLString(includeNSPrefix, false)); 465 } 466 sb.append("</").append(nsDeclaration).append(XACMLConstants.REQUEST). 467 append(">\n"); 468 return sb.toString(); 469 } 470 471 /** 472 * Returns a string representation of this object 473 * 474 * @return a string representation of this object 475 * @exception XACMLException if conversion fails for any reason 476 */ 477 public String toXMLString() throws XACMLException { 478 return this.toXMLString(true, false); 479 } 480 481 /** 482 * Makes the object immutable 483 */ 484 public void makeImmutable() {} 485 486 /** 487 * Checks if the object is mutable 488 * 489 * @return <code>true</code> if the object is mutable, 490 * <code>false</code> otherwise 491 */ 492 public boolean isMutable() { 493 return isMutable; 494 } 495}
Copyright © 2010-2017, ForgeRock All Rights Reserved.