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: Attribute.java,v 1.4 2008/09/03 22:28:40 weisun2 Exp $ 026 * 027 */ 028 029 030package com.sun.identity.saml.assertion; 031 032import com.sun.identity.common.SystemConfigurationUtil; 033import java.util.*; 034import org.w3c.dom.*; 035import com.sun.identity.saml.common.SAMLUtilsCommon; 036import com.sun.identity.saml.common.SAMLConstants; 037import com.sun.identity.saml.common.SAMLException; 038import com.sun.identity.saml.common.SAMLRequesterException; 039import com.sun.identity.shared.xml.XMLUtils; 040 041/** 042 * The <code>Attribute</code> element specifies an attribute of the assertion 043 * subject. The <code>Attribute</code> element is an extension of the 044 * <code>AttributeDesignator</code> element 045 * that allows the attribute value to be specified. 046 * 047 * @supported.all.api 048 */ 049public class Attribute extends AttributeDesignator { 050 protected List _attributeValue; 051 052 /** 053 * Constructs an attribute element from an existing XML block. 054 * 055 * @param element representing a DOM tree element. 056 * @exception SAMLException if there is an error in the sender or in the 057 * element definition. 058 */ 059 public Attribute(Element element) throws SAMLException { 060 // make sure that the input xml block is not null 061 if (element == null) { 062 SAMLUtilsCommon.debug.message("Attribute: Input is null."); 063 throw new SAMLRequesterException( 064 SAMLUtilsCommon.bundle.getString("nullInput")); 065 } 066 // Make sure this is an Attribute. 067 String tag = null; 068 tag = element.getLocalName(); 069 if ((tag == null) || (!tag.equals("Attribute"))) { 070 SAMLUtilsCommon.debug.message("Attribute: wrong input"); 071 throw new SAMLRequesterException( 072 SAMLUtilsCommon.bundle.getString("wrongInput")); 073 } 074 int i = 0; 075 // handle attributes 076 NamedNodeMap atts = element.getAttributes(); 077 int attrCount = atts.getLength(); 078 for (i = 0; i < attrCount; i++) { 079 Node att = atts.item(i); 080 if (att.getNodeType() == Node.ATTRIBUTE_NODE) { 081 String attName = att.getLocalName(); 082 if(attName == null) { 083 attName = att.getNodeName(); 084 } 085 if (attName == null || attName.length() == 0) { 086 if (SAMLUtilsCommon.debug.messageEnabled()) { 087 SAMLUtilsCommon.debug.message("Attribute:" + 088 "Attribute Name is either null or empty."); 089 } 090 continue; 091 //throw new SAMLRequesterException( 092 // SAMLUtilsCommon.bundle.getString("nullInput")); 093 } 094 if (attName.equals("AttributeName")) { 095 this._attributeName =((Attr)att).getValue().trim(); 096 } else if (attName.equals("AttributeNamespace")) { 097 this._attributeNameSpace = ((Attr)att).getValue().trim(); 098 } 099 } 100 } 101 // AttributeName is required 102 if (_attributeName == null || _attributeName.length() == 0) { 103 if (SAMLUtilsCommon.debug.messageEnabled()) { 104 SAMLUtilsCommon.debug.message("Attribute: "+ 105 "AttributeName is required attribute"); 106 } 107 throw new SAMLRequesterException( 108 SAMLUtilsCommon.bundle.getString("missingAttribute")); 109 } 110 111 // AttributeNamespace is required 112 if (_attributeNameSpace == null || _attributeNameSpace.length() == 0) { 113 if (SAMLUtilsCommon.debug.messageEnabled()) { 114 SAMLUtilsCommon.debug.message("Attribute: "+ 115 "AttributeNamespace is required attribute"); 116 } 117 throw new SAMLRequesterException( 118 SAMLUtilsCommon.bundle.getString("missingAttribute")); 119 } 120 121 // handle the children of Attribute element 122 NodeList nodes = element.getChildNodes(); 123 int nodeCount = nodes.getLength(); 124 if (nodeCount > 0) { 125 for (i = 0; i < nodeCount; i++) { 126 Node currentNode = nodes.item(i); 127 if (currentNode.getNodeType() == Node.ELEMENT_NODE) { 128 String tagName = currentNode.getLocalName(); 129 String tagNS = currentNode.getNamespaceURI(); 130 if ((tagName == null) || tagName.length() == 0 || 131 tagNS == null || tagNS.length() == 0) { 132 if (SAMLUtilsCommon.debug.messageEnabled()) { 133 SAMLUtilsCommon.debug.message("Attribute:" + 134 " The tag name or tag namespace of child" + 135 " element is either null or empty."); 136 } 137 throw new SAMLRequesterException( 138 SAMLUtilsCommon.bundle.getString("nullInput")); 139 } 140 if (tagName.equals("AttributeValue") && 141 tagNS.equals(SAMLConstants.assertionSAMLNameSpaceURI)) { 142 if (_attributeValue == null) { 143 _attributeValue = new ArrayList(); 144 } 145 if (!(_attributeValue.add((Element)currentNode))){ 146 if (SAMLUtilsCommon.debug.messageEnabled()) { 147 SAMLUtilsCommon.debug.message( 148 "Attribute: failed to "+ 149 "add to the attribute value list."); 150 } 151 throw new SAMLRequesterException( 152 SAMLUtilsCommon.bundle.getString( 153 "addListError")); 154 } 155 } else { 156 if (SAMLUtilsCommon.debug.messageEnabled()) { 157 SAMLUtilsCommon.debug.message("Attribute:" + 158 "wrong element:" + tagName); 159 } 160 throw new SAMLRequesterException( 161 SAMLUtilsCommon.bundle.getString("wrongInput")); 162 } 163 } // end of if (currentNode.getNodeType() == Node.ELEMENT_NODE) 164 } // end of for loop 165 } // end of if (nodeCount > 0) 166 167 if (_attributeValue == null || _attributeValue.isEmpty()) { 168 if (SAMLUtilsCommon.debug.messageEnabled()) { 169 SAMLUtilsCommon.debug.message("Attribute: " + 170 "should contain at least one AttributeValue."); 171 } 172 throw new SAMLRequesterException( 173 SAMLUtilsCommon.bundle.getString("missingElement")); 174 } 175 } 176 177 /** 178 * Constructs an instance of <code>Attribute</code>. 179 * 180 * @param name A String representing <code>AttributeName</code> (the name 181 * of the attribute). 182 * @param nameSpace A String representing the namespace in which 183 * <code>AttributeName</code> elements are interpreted. 184 * @param values A List of DOM element representing the 185 * <code>AttributeValue</code> object. 186 * @exception SAMLException if there is an error in the sender or in the 187 * element definition. 188 */ 189 public Attribute(String name, String nameSpace, List values) 190 throws SAMLException { 191 super(name, nameSpace); 192 if (values == null || values.isEmpty()) { 193 if (SAMLUtilsCommon.debug.messageEnabled()) { 194 SAMLUtilsCommon.debug.message("Attribute: AttributeValue is" + 195 "required."); 196 } 197 throw new SAMLRequesterException( 198 SAMLUtilsCommon.bundle.getString("nullInput")); 199 } 200 if (_attributeValue == null) { 201 _attributeValue = new ArrayList(); 202 } 203 // Make sure this is a list of AttributeValue 204 Iterator iter = values.iterator(); 205 String tag = null; 206 while (iter.hasNext()) { 207 tag = ((Element) iter.next()).getLocalName(); 208 if ((tag == null) || (!tag.equals("AttributeValue"))) { 209 if (SAMLUtilsCommon.debug.messageEnabled()) { 210 SAMLUtilsCommon.debug.message( 211 "AttributeValue: wrong input."); 212 } 213 throw new SAMLRequesterException( 214 SAMLUtilsCommon.bundle.getString("wrongInput")); 215 } 216 } 217 _attributeValue = values; 218 } 219 220 /** 221 * Constructs an instance of <code>Attribute</code>. 222 * 223 * @param name The name of the attribute. 224 * @param nameSpace The namespace in which <code>AttributeName</code> 225 * elements are interpreted. 226 * @param attributeValue an <code>AttributeValue</code> object. 227 * @exception SAMLException if there is an error in the sender or in 228 * the element definition. 229 */ 230 public Attribute(String name, String nameSpace, String attributeValue) 231 throws SAMLException { 232 super(name, nameSpace); 233 String escapeAttVal = SystemConfigurationUtil.getProperty( 234 SAMLConstants.ESCAPE_ATTR_VALUE, "true"); 235 boolean escapeAtt = "true".equalsIgnoreCase(escapeAttVal) ? 236 true : false; 237 if (escapeAtt) { 238 this.addAttributeValue(XMLUtils. 239 escapeSpecialCharacters(attributeValue)); 240 } else { 241 this.addAttributeValue(attributeValue); 242 } 243 } 244 245 /** 246 * Returns <code>AttributeValue</code> from the Attribute. 247 * 248 * @return A list of DOM Element representing the 249 * <code>AttributeValue</code> block. 250 * @throws SAMLException 251 */ 252 public List getAttributeValue() throws SAMLException { 253 return _attributeValue; 254 } 255 256 /** 257 * Adds <code>AttributeValue</code> to the Attribute. 258 * 259 * @param value A String representing <code>AttributeValue</code>. 260 * @exception SAMLException 261 */ 262 public void addAttributeValue(String value) throws SAMLException { 263 if (value == null || value.length() == 0) { 264 if (SAMLUtilsCommon.debug.messageEnabled()) { 265 SAMLUtilsCommon.debug.message( 266 "addAttributeValue: Input is null"); 267 } 268 throw new SAMLRequesterException( 269 SAMLUtilsCommon.bundle.getString("nullInput")); 270 } 271 StringBuffer sb = new StringBuffer(300); 272 sb.append("<").append(SAMLConstants.ASSERTION_PREFIX). 273 append("AttributeValue"). 274 append(SAMLConstants.assertionDeclareStr). 275 append(">").append(value).append("</"). 276 append(SAMLConstants.ASSERTION_PREFIX). 277 append("AttributeValue>"); 278 try { 279 Element ele = XMLUtils.toDOMDocument( 280 sb.toString().trim(), 281 SAMLUtilsCommon.debug).getDocumentElement(); 282 if (_attributeValue == null) { 283 _attributeValue = new ArrayList(); 284 } 285 if (!(_attributeValue.add(ele))){ 286 if (SAMLUtilsCommon.debug.messageEnabled()) { 287 SAMLUtilsCommon.debug.message("Attribute: failed to "+ 288 "add to the attribute value list."); 289 } 290 throw new SAMLRequesterException( 291 SAMLUtilsCommon.bundle.getString("addListError")); 292 } 293 } catch (Exception e) { 294 SAMLUtilsCommon.debug.error("addAttributeValue error", e); 295 throw new SAMLRequesterException("Exception in addAttributeValue" + 296 e.getMessage()); 297 } 298 } 299 300 /** 301 * Adds <code>AttributeValue</code> to the Attribute. 302 * 303 * @param element An Element object representing 304 * <code>AttributeValue</code>. 305 * @exception SAMLException 306 */ 307 public void addAttributeValue(Element element) throws SAMLException { 308 if (element == null) { 309 if (SAMLUtilsCommon.debug.messageEnabled()) { 310 SAMLUtilsCommon.debug.message( 311 "addAttributeValue: input is null."); 312 } 313 throw new SAMLRequesterException( 314 SAMLUtilsCommon.bundle.getString("nullInput")); 315 } 316 317 String tag = element.getLocalName(); 318 if ((tag == null) || (!tag.equals("AttributeValue"))) { 319 if (SAMLUtilsCommon.debug.messageEnabled()) { 320 SAMLUtilsCommon.debug.message("AttributeValue: wrong input."); 321 } 322 throw new SAMLRequesterException( 323 SAMLUtilsCommon.bundle.getString("wrongInput")); 324 } 325 try { 326 if (_attributeValue == null) { 327 _attributeValue = new ArrayList(); 328 } 329 if (!(_attributeValue.add(element))){ 330 if (SAMLUtilsCommon.debug.messageEnabled()) { 331 SAMLUtilsCommon.debug.message("Attribute: failed to "+ 332 "add to the attribute value list."); 333 } 334 throw new SAMLRequesterException( 335 SAMLUtilsCommon.bundle.getString("addListError")); 336 } 337 } catch (Exception e) { 338 SAMLUtilsCommon.debug.error("addAttributeValue error", e); 339 throw new SAMLRequesterException("Exception in addAttributeValue" + 340 e.getMessage()); 341 } 342 } 343 344 345 /** 346 * Returns a String representation of the 347 * <code><saml:Attribute></code> element, 348 * 349 * @return A string containing the valid XML for this element. 350 */ 351 public String toString() { 352 return toString(true, false); 353 } 354 355 /** 356 * Returns a String representation of the 357 * <code><saml:Attribute></code> element. 358 * 359 * @param includeNS Determines whether or not the namespace qualifier 360 * is prepended to the Element when converted 361 * @param declareNS Determines whether or not the namespace is declared 362 * within the Element. 363 * @return A string containing the valid XML for this element 364 */ 365 public String toString(boolean includeNS, boolean declareNS) { 366 StringBuffer result = new StringBuffer(1000); 367 String prefix = ""; 368 String uri = ""; 369 if (includeNS) { 370 prefix = SAMLConstants.ASSERTION_PREFIX; 371 } 372 if (declareNS) { 373 uri = SAMLConstants.assertionDeclareStr; 374 } 375 result.append("<").append(prefix).append("Attribute").append(uri). 376 append(" AttributeName=\"").append(_attributeName). 377 append("\" AttributeNamespace=\"").append(_attributeNameSpace). 378 append("\">\n"); 379 380 Iterator iter = _attributeValue.iterator(); 381 while (iter.hasNext()) { 382 result.append(XMLUtils.printAttributeValue((Element)iter.next(), 383 prefix)).append("\n"); 384 } 385 result.append("</").append(prefix).append("Attribute>\n"); 386 return result.toString(); 387 } 388}