001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2005 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: ServiceSchema.java,v 1.12 2008/08/30 16:46:47 goodearth Exp $ 026 * 027 */ 028 029/* 030 * Portions Copyrighted 2011-2014 ForgeRock AS 031 */ 032package com.sun.identity.sm; 033 034import com.iplanet.sso.SSOException; 035import com.iplanet.ums.IUMSConstants; 036import com.sun.identity.shared.Constants; 037import com.sun.identity.common.CaseInsensitiveHashSet; 038import com.sun.identity.shared.debug.Debug; 039import com.sun.identity.shared.xml.XMLUtils; 040import java.io.InputStream; 041import java.util.Collections; 042import java.util.HashMap; 043import java.util.HashSet; 044import java.util.Iterator; 045import java.util.Map; 046import java.util.Set; 047import java.util.StringTokenizer; 048import org.w3c.dom.Document; 049import org.w3c.dom.Element; 050import org.w3c.dom.Node; 051import org.w3c.dom.NodeList; 052 053 054/** 055 * The class <code>ServiceSchema</code> provides interfaces to manage the 056 * schema information of a service. The schema for a service can be one of the 057 * following types: GLOBAL, ORGANIZATION, DYNAMIC, USER, and POLICY. 058 * 059 * @supported.all.api 060 */ 061public class ServiceSchema { 062 063 // Pointer to service's schema manager & type 064 ServiceSchemaImpl ss; 065 066 String componentName; 067 068 SchemaType type; 069 070 ServiceSchemaManager ssm; 071 072 boolean orgAttrSchema; 073 074 /** 075 * Default constructor (private). 076 */ 077 private ServiceSchema() { 078 // do nothing 079 } 080 081 protected ServiceSchema(ServiceSchemaImpl ssi, String compName, 082 SchemaType type, ServiceSchemaManager ssm) { 083 this(ssi, compName, type, ssm, false); 084 } 085 086 protected ServiceSchema(ServiceSchemaImpl ssi, String compName, 087 SchemaType type, ServiceSchemaManager ssm, boolean isOrgAttrSchema) 088 { 089 this.ss = ssi; 090 this.componentName = compName; 091 this.type = type; 092 this.ssm = ssm; 093 this.orgAttrSchema = isOrgAttrSchema; 094 this.ss.isOrgAttrSchema = isOrgAttrSchema; 095 this.ss.serviceName = ssm.getName(); 096 } 097 098 /** 099 * Returns the name of the service. 100 * 101 * @return the name of the schema 102 */ 103 public String getServiceName() { 104 return (ssm.getName()); 105 } 106 107 /** 108 * Returns the version of the service. 109 * 110 * @return version of the service schema 111 */ 112 public String getVersion() { 113 return (ssm.getVersion()); 114 } 115 116 /** 117 * Returns the name of the schema. 118 * 119 * @return the name of the schema 120 */ 121 public String getName() { 122 return (ss.getName()); 123 } 124 125 /** 126 * Returns the schema type. 127 * 128 * @return the schema type. 129 */ 130 public SchemaType getServiceType() { 131 return (type); 132 } 133 134 /** 135 * Returns the I18N key that points to the description of the service. 136 * 137 * @return the I18N key that points to the description of the service 138 */ 139 public String getI18NKey() { 140 return (ss.getI18NKey()); 141 } 142 143 /** 144 * Returns <code>true</code> if service schema supports multiple 145 * configurations; <code>false</code> otherwise 146 * 147 * @return <code>true</code> if service schema supports multiple 148 * configurations; <code>false</code> otherwise 149 */ 150 public boolean supportsMultipleConfigurations() { 151 return (ss.supportsMultipleConfigurations()); 152 } 153 154 /** 155 * Sets the value of the I18N key in the service schema. 156 * 157 * @param key 158 * Value to be set for the I18N key of the service schema. 159 * @throws SMSException 160 * if there is a problem setting the value in the data store. 161 * @throws SSOException 162 * If the user has an invalid SSO token. 163 */ 164 public void setI18Nkey(String key) throws SMSException, SSOException { 165 SMSEntry.validateToken(ssm.getSSOToken()); 166 Node sNode = ss.getSchemaNode(); 167 ((Element) sNode).setAttribute(SMSUtils.I18N_KEY, key); 168 ssm 169 .replaceSchema((ServiceSchemaManagerImpl.getInstance(ssm 170 .getSSOToken(), ssm.getName(), ssm.getVersion())) 171 .getDocument()); 172 ss.i18nKey = key; 173 } 174 175 /** 176 * Set the value of inheritance attribute in service schema. 177 * 178 * @param value 179 * New value of inheritance attribute. 180 * @throws SMSException 181 * if there is a problem setting the value in the data store. 182 * @throws SSOException 183 * if the user has an invalid single sign on token. 184 */ 185 public void setInheritance(String value) throws SMSException, SSOException { 186 if (!value.equals("single") && !value.equals("multiple")) { 187 String[] arg = { value }; 188 throw new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 189 "sms-invalid-inheritance-value", arg); 190 } 191 192 SMSEntry.validateToken(ssm.getSSOToken()); 193 Node sNode = ss.getSchemaNode(); 194 ((Element) sNode).setAttribute(SMSUtils.INHERITANCE, value); 195 ssm 196 .replaceSchema((ServiceSchemaManagerImpl.getInstance(ssm 197 .getSSOToken(), ssm.getName(), ssm.getVersion())) 198 .getDocument()); 199 ss.inheritance = value; 200 } 201 202 /** 203 * Returns the view bean URL for this service 204 * 205 * @return file name that contains I18N messages 206 */ 207 public String getPropertiesViewBeanURL() { 208 return (ssm.getPropertiesViewBeanURL()); 209 } 210 211 /** 212 * Returns the name of the status attribute, as defined in the Service 213 * schema 214 * 215 * @return String name of status attribute 216 */ 217 public String getStatusAttribute() { 218 return (ss.getStatusAttribute()); 219 } 220 221 /** 222 * Returns <code>true</code> if the service configuration created can be 223 * exported to other organizations. 224 * 225 * @return <code>true</code> if service configurations for this schema can 226 * be exported to other organizations; <code>false</code> 227 * otherwise. 228 */ 229 public boolean isExportable() { 230 return (false); 231 } 232 233 /** 234 * Sets the exportable nature of the service configurations created for this 235 * schema. Setting it to <code>true</code> allows the configurations to be 236 * exported to other organizations and a value of <code>false</code> 237 * disables exporting of configuration data. 238 * 239 * @param exportable 240 * <code>true</code> if service configurations for this schema 241 * can be exported to other organizations; <code>false</code> 242 * otherwise. 243 */ 244 public void setExportable(boolean exportable) { 245 } 246 247 /** 248 * Returns the I18N properties file name for the service schema. 249 * 250 * @return the I18N properties file name for the service schema 251 */ 252 public String getI18NFileName() { 253 return (ssm.getI18NFileName()); 254 } 255 256 /** 257 * Sets the I18N properties file name for the service schema 258 * 259 * @param url 260 * properties file name 261 * @throws SMSException 262 * if an error occurred while trying to perform the operation 263 * @throws SSOException 264 * if the single sign on token is invalid or expired 265 */ 266 public void setI18NFileName(String url) throws SMSException, SSOException { 267 ssm.setI18NFileName(url); 268 } 269 270 /** 271 * Returns the names of the schema attributes defined for the service. It 272 * does not return the schema attributes defined for the sub-schema. 273 * 274 * @return the names of schema attributes defined for the service 275 */ 276 public Set getAttributeSchemaNames() { 277 return (ss.getAttributeSchemaNames()); 278 } 279 280 /** 281 * Returns the names of the schema attributes defined for the service which 282 * are searchable. It does not return the schema attributes defined for the 283 * sub-schema. 284 * 285 * @return the names of schema attributes defined for the service which are 286 * searchable attributes. 287 */ 288 protected Set getSearchableAttributeNames() { 289 return (ss.getSearchableAttributeNames()); 290 } 291 292 /** 293 * Returns the schema for an attribute given the name of the attribute, 294 * defined for this service. It returns only the attribute schema defined at 295 * the top level for the service and not from the sub-schema. 296 * 297 * @param attributeName 298 * the name of the schema attribute 299 * @return the schema for the attribute 300 */ 301 public AttributeSchema getAttributeSchema(String attributeName) { 302 AttributeSchemaImpl as = ss.getAttributeSchema(attributeName); 303 return ((as == null) ? null : new AttributeSchema(as, ssm, this)); 304 } 305 306 /** 307 * Returns the attribute schemas defined for the service. It does not return 308 * the schema attributes defined for the sub-schema. 309 * 310 * @return attribute schemas defined for the service 311 */ 312 public Set getAttributeSchemas() { 313 Set answer = new HashSet(); 314 for (Iterator items = getAttributeSchemaNames().iterator(); items 315 .hasNext();) { 316 String attrName = (String) items.next(); 317 answer.add(getAttributeSchema(attrName)); 318 } 319 return (answer); 320 } 321 322 /** 323 * Returns the attribute schemas defined for the service that is not a 324 * status attribute and is not a service attribute. It does not return the 325 * schema attributes defined for the sub-schema. 326 * 327 * @return attribute schemas defined for the service 328 */ 329 public Set getServiceAttributeNames() { 330 return (ss.getServiceAttributeNames()); 331 } 332 333 /** 334 * Validates the <code>attrMap</code> against the attributes defined in 335 * this schema of the service. It will throw an exception if the map 336 * contains any attribute not listed in the schema. It will also pick up 337 * default values for any attributes not in the map but which are listed in 338 * the schema, if the boolean <Code>inherit</Code> is set to true. 339 * 340 * @param attrMap 341 * map of attributes 342 * @param inherit 343 * if true, then inherit the default values 344 * @return Map of validated attributes with default values 345 * @throws SMSException 346 * if invalid attribute names are present in the 347 * <code>attrMap</code>. 348 */ 349 public Map validateAndInheritDefaults(Map attrMap, boolean inherit) 350 throws SMSException { 351 return (validateAndInheritDefaults(attrMap, null, inherit)); 352 } 353 354 /** 355 * Validates the <code>attrMap</code> against the attributes defined in 356 * this schema of the service for the given organization. It will throw an 357 * exception if the map contains any attribute not listed in the schema. It 358 * will also pick up default values for any attributes not in the map but 359 * which are listed in the schema, if the boolean <Code>inherit</Code> is 360 * set to true. 361 * 362 * @param attrMap 363 * map of attributes 364 * @param inherit 365 * if true, then inherit the default values 366 * @return Map of validated attributes with default values 367 * @throws SMSException 368 * if invalid attribute names are present in the 369 * <code>attrMap</code>. 370 */ 371 public Map validateAndInheritDefaults(Map attrMap, String orgName, 372 boolean inherit) throws SMSException { 373 SMSEntry.validateToken(ssm.getSSOToken()); 374 375 if (attrMap == null || attrMap.isEmpty()) { 376 attrMap = new HashMap(); 377 } 378 Iterator keys = attrMap.keySet().iterator(); 379 Set defAttrSet = ss.getAttributeSchemaNames(); 380 while (keys.hasNext()) { 381 String attr = (String) keys.next(); 382 if (!defAttrSet.contains(attr)) { 383 // This attribute is not listed in the service. 384 debug.error("ServiceSchema.validateAndInheritDefaults: " + attr 385 + " is not listed in the service " + getServiceName()); 386 throw new InvalidAttributeNameException( 387 IUMSConstants.UMS_BUNDLE_NAME, 388 "services_validator_invalid_attr_name", null); 389 } 390 } 391 392 // If orgName is not null, populate the envMap 393 Map envMap = Collections.EMPTY_MAP; 394 if (orgName != null) { 395 envMap = new HashMap(); 396 envMap.put(Constants.ORGANIZATION_NAME, orgName); 397 envMap.put(Constants.SSO_TOKEN, ssm.getSSOToken()); 398 } 399 Iterator ass = ss.getAttributeSchemaNames().iterator(); 400 while (ass.hasNext()) { 401 String attr = (String) ass.next(); 402 AttributeSchemaImpl as = ss.getAttributeSchema(attr); 403 AttributeValidator av = ss.getAttributeValidator(attr); 404 String anyValue = as.getAny(); 405 if (inherit && (anyValue != null) && 406 (anyValue.indexOf("required") > -1)) { 407 // Inherit default values of this attribute, if 408 // required 409 attrMap = av.inheritDefaults(attrMap); 410 Set attrVals = (Set) attrMap.get(attr); 411 if (attrVals == null || attrVals.isEmpty()) { 412 // A required attribute is being deleted 413 // throw an exception. 414 debug.error("ServiceSchema.validateAndInheritDefaults: " 415 + attr + " is a required attribute and cannot" 416 + " be deleted"); 417 Object args[] = { attr }; 418 throw new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 419 "sms-required-attribute-delete", args); 420 } 421 } else if (inherit) { 422 attrMap = av.inheritDefaults(attrMap); 423 } 424 // validate the attribute against Schema 425 Set valSet = (Set) attrMap.get(attr); 426 if (valSet != null) { 427 String i18nFileName = (ssm != null) ? ssm.getI18NFileName() 428 : null; 429 av.validate(valSet, i18nFileName, false, envMap); 430 } 431 } 432 if (debug.messageEnabled()) { 433 debug.error("ServiceSchema.validate&InheritDef: " 434 + " returning attrMap: " + attrMap.toString()); 435 } 436 return attrMap; 437 } 438 439 /** 440 * Adds the attribute schema to this service. The schema is defined in XML 441 * input stream that follows the SMS DTD. 442 * 443 * @param xmlAttrSchema 444 * the XML format of the attribute schema 445 * @throws SMSException 446 * if an error occurred while performing the operation 447 * @throws SSOException 448 * if the single sign on token is invalid or expired 449 */ 450 public void addAttributeSchema(InputStream xmlAttrSchema) 451 throws SSOException, SMSException { 452 SMSEntry.validateToken(ssm.getSSOToken()); 453 // Check if attribute exists 454 Document doc = SMSSchema.getXMLDocument(xmlAttrSchema, false); 455 NodeList nl = doc.getElementsByTagName(SMSUtils.SCHEMA_ATTRIBUTE); 456 CaseInsensitiveHashSet asNames = 457 new CaseInsensitiveHashSet(ss.getAttributeSchemaNames()); 458 for (int i = 0; i < nl.getLength(); i++) { 459 Node node = nl.item(i); 460 AttributeSchemaImpl as = new AttributeSchemaImpl(node); 461 if (asNames.contains(as.getName())) { 462 Object[] args = { as.getName() }; 463 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 464 "sms-attributeschema-already-exists", args)); 465 } 466 } 467 appendAttributeSchema(nl); 468 } 469 470 /** 471 * Removes the attribute schema from this service. 472 * 473 * @param attrName 474 * the name of the attribute schema 475 * @throws SMSException 476 * if an error occurred while performing the operation 477 * @throws SSOException 478 * if the single sign on token is invalid or expired 479 */ 480 public void removeAttributeSchema(String attrName) throws SSOException, 481 SMSException { 482 removeChildNode(SMSUtils.SCHEMA_ATTRIBUTE, attrName); 483 } 484 485 /** 486 * Returns a map of all the attribute and their default values in this 487 * schema. 488 * 489 * @return Map of Attribute Names and Sets of their default values as 490 * defined in the Schema 491 */ 492 public Map getAttributeDefaults() { 493 return (ss.getAttributeDefaults()); 494 } 495 496 /** 497 * Returns an unmodifiable map of all the attribute and their default values 498 * in this schema. 499 * 500 * @return Map of Attribute Names and Sets of their default values as 501 * defined in the Schema 502 */ 503 public Map getReadOnlyAttributeDefaults() { 504 return (ss.getReadOnlyAttributeDefaults()); 505 } 506 507 /** 508 * Method to change the default values of attributes in the schema. 509 * 510 * @param attrs 511 * A map of the names of <code>AttributeSchema</code> to 512 * modify, and a Set of Values which should replace the default 513 * values of the current schema. 514 * @throws SMSException 515 * if an error occurred while performing the operation 516 * @throws SSOException 517 * if the single sign on token is invalid or expired 518 */ 519 public void setAttributeDefaults(Map attrs) throws SSOException, 520 SMSException { 521 SMSEntry.validateToken(ssm.getSSOToken()); 522 // Get a copy of the XML document 523 Document document = ssm.getDocumentCopy(); 524 Iterator items = attrs.keySet().iterator(); 525 while (items.hasNext()) { 526 String attrName = (String) items.next(); 527 AttributeSchema as = getAttributeSchema(attrName); 528 if (as == null) { 529 Object[] args = { attrName }; 530 throw (new SchemaException(IUMSConstants.UMS_BUNDLE_NAME, 531 "sms-invalid-attr-name", args)); 532 } 533 as.setDefaultValues((Set) attrs.get(attrName), document); 534 } 535 // Save the document 536 ssm.replaceSchema(document); 537 } 538 539 /** 540 * Method to change default value for a specific attribute. 541 * 542 * @param attrName 543 * Name of the attribute for which defaults values need to be 544 * replaced. 545 * @param values 546 * Set of new values to replace the old ones. 547 * @throws SchemaException 548 * if an error occurred while parsing the XML 549 * @throws SMSException 550 * if an error occurred while performing the operation 551 * @throws SSOException 552 * if the single sign on token is invalid or expired 553 */ 554 public void setAttributeDefaults(String attrName, Set values) 555 throws SchemaException, SMSException, SSOException { 556 SMSEntry.validateToken(ssm.getSSOToken()); 557 AttributeSchema as = getAttributeSchema(attrName); 558 if (as == null) { 559 Object[] args = { attrName }; 560 throw (new SchemaException(IUMSConstants.UMS_BUNDLE_NAME, 561 "sms-invalid-attr-name", args)); 562 } 563 as.setDefaultValues(values); 564 } 565 566 /** 567 * Removes the default values of attributes in the schema. 568 * 569 * @param attrs 570 * A set of the names of <code>AttributeSchema</code>. 571 * @throws SMSException 572 * if an error occurred while performing the operation 573 * @throws SSOException 574 * if the single sign on token is invalid or expired 575 */ 576 public void removeAttributeDefaults(Set attrs) throws SMSException, 577 SSOException { 578 SMSEntry.validateToken(ssm.getSSOToken()); 579 Iterator it = attrs.iterator(); 580 while (it.hasNext()) { 581 String asName = (String) it.next(); 582 AttributeSchema as = getAttributeSchema(asName); 583 if (as == null) { 584 throw (new InvalidAttributeNameException( 585 IUMSConstants.UMS_BUNDLE_NAME, 586 IUMSConstants.services_validator_invalid_attr_name, 587 null)); 588 } 589 as.removeDefaultValues(); 590 } 591 } 592 593 /** 594 * Returns the names of sub-schemas for the service. 595 * 596 * @return the names of service's sub-schemas 597 */ 598 public Set getSubSchemaNames() { 599 return (ss.getSubSchemaNames()); 600 } 601 602 /** 603 * Returns <code>ServiceSchema</code> object given the name of the 604 * service's sub-schema. 605 * 606 * @param subSchemaName 607 * the name of the service's sub-schema 608 * @return <code>ServiceSchema</code> object 609 * @throws SMSException 610 * if an error occurred while performing the operation 611 * 612 */ 613 public ServiceSchema getSubSchema(String subSchemaName) throws SMSException 614 { 615 SMSEntry.validateToken(ssm.getSSOToken()); 616 ServiceSchema answer = null; 617 ServiceSchemaImpl ssi = ss.getSubSchema(subSchemaName); 618 if (ssi != null) { 619 answer = new ServiceSchema(ssi, 620 componentName + "/" + subSchemaName, type, ssm); 621 } 622 return (answer); 623 } 624 625 /** 626 * Adds the service's sub-schema given the XML input stream that follows the 627 * SMS DTD. 628 * 629 * @param xmlSubSchema 630 * the XML format of the sub-schema 631 * @throws SMSException 632 * if an error occurred while performing the operation 633 * @throws SSOException 634 * if the single sign on token is invalid or expired 635 */ 636 public void addSubSchema(InputStream xmlSubSchema) throws SSOException, 637 SMSException { 638 SMSEntry.validateToken(ssm.getSSOToken()); 639 // Check if attribute exists 640 Document doc = SMSSchema.getXMLDocument(xmlSubSchema, false); 641 NodeList nl = doc.getElementsByTagName(SMSUtils.SUB_SCHEMA); 642 Set asNames = ss.getSubSchemaNames(); 643 for (int i = 0; i < nl.getLength(); i++) { 644 Node node = nl.item(i); 645 String nodeName = XMLUtils.getNodeAttributeValue(node, 646 SMSUtils.NAME); 647 if (asNames.contains(nodeName)) { 648 Object[] args = { nodeName }; 649 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 650 "sms-subschema-already-exists", args)); 651 } 652 } 653 654 appendSubSchema(doc); 655 } 656 657 /** 658 * Removes the service's sub-schema from the service. 659 * 660 * @param subSchemaName 661 * the name of the service's sub-schema 662 * @throws SMSException 663 * if an error occurred while performing the operation 664 * @throws SSOException 665 * if the single sign on token is invalid or expired 666 */ 667 public void removeSubSchema(String subSchemaName) throws SSOException, 668 SMSException { 669 SMSEntry.validateToken(ssm.getSSOToken()); 670 removeChildNode(SMSUtils.SUB_SCHEMA, subSchemaName); 671 } 672 673 /** 674 * Determines whether each attribute in the attribute set is valid. Iterates 675 * though the set checking each element to see if there is a validator that 676 * needs to execute. 677 * 678 * @param attributeSet 679 * the <code>Map</code> where key is the attribute name and 680 * value is the <code>Set</code> of attribute values 681 * @return true if all attributes are valid 682 * @throws SMSException 683 * if an error occurred while performing the operation 684 */ 685 public boolean validateAttributes(Map attributeSet) throws SMSException { 686 SMSEntry.validateToken(ssm.getSSOToken()); 687 return (ss.validateAttributes(ssm.getSSOToken(), attributeSet, false, 688 null)); 689 } 690 691 /** 692 * Determines whether each attribute in the attribute set is valid for the 693 * given organization. Iterates though the set checking each element to see 694 * if there is a validator that needs to execute. 695 * 696 * @param attributeSet 697 * the <code>Map</code> where key is the attribute name and 698 * value is the <code>Set</code> of attribute values 699 * @param orgName 700 * organization name 701 * @return true if all attributes are valid 702 * @throws SMSException 703 * if an error occurred while performing the operation 704 */ 705 public boolean validateAttributes(Map attributeSet, String orgName) 706 throws SMSException { 707 SMSEntry.validateToken(ssm.getSSOToken()); 708 return (ss.validateAttributes(ssm.getSSOToken(), attributeSet, false, 709 orgName)); 710 } 711 712 /** 713 * Returns string representation of the schema. 714 * 715 * @return string representation of the schema. 716 */ 717 public String toString() { 718 return (ss.toString()); 719 } 720 721 /** 722 * Returns the Node of this schema element. Used by Policy component's 723 * <code>ServiceType</code> to get <code>ActionSchema</code>. 724 * 725 * @return the Node of this schema element. Used by Policy component's 726 * <code>ServiceType</code> to get <code>ActionSchema</code>. 727 */ 728 public Node getSchemaNode() { 729 Node node = null; 730 try { 731 node = getSchemaNode(ssm.getDocumentCopy()); 732 } catch (SMSException ssme) { 733 debug.error("ServiceSchema::getSchemaNode: invalid schema"); 734 } 735 return (node); 736 } 737 738 /** 739 * Removes the attribute schema from this service. 740 * 741 * @param attrName 742 * the name of the attribute schema 743 * @throws SMSException 744 * if an error occurred while performing the operation 745 * @throws SSOException 746 * if the single sign on token is invalid or expired 747 */ 748 public void replaceAttributeSchema(String attrName, Node attributeSchemaNode) throws SSOException, 749 SMSException { 750 replaceChildNode(SMSUtils.SCHEMA_ATTRIBUTE, attrName, attributeSchemaNode); 751 } 752 753 private void appendAttributeSchema(NodeList nodes) throws SSOException, SMSException { 754 if (nodes == null || nodes.getLength() == 0) { 755 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 756 IUMSConstants.SMS_SMSSchema_no_schema_element, null)); 757 } 758 Document schemaDoc = ssm.getDocumentCopy(); 759 try { 760 Node schemaNode = getSchemaNode(schemaDoc); 761 NodeList childrens = schemaNode.getChildNodes(); 762 Node nextSibling = null; 763 for (int i = 0; i < childrens.getLength(); i++) { 764 Node child = childrens.item(i); 765 if (Node.ELEMENT_NODE == child.getNodeType() 766 && !SMSUtils.SCHEMA_ATTRIBUTE.equals(child.getNodeName())) { 767 nextSibling = child; 768 break; 769 } 770 } 771 for (int i = 0; i < nodes.getLength(); i++) { 772 Node node = nodes.item(i); 773 Node iNode = schemaDoc.importNode(node, true); 774 schemaNode.insertBefore(iNode, nextSibling); 775 } 776 } catch (Exception e) { 777 throw (new SMSException(e.getMessage(), e, "sms-cannot_append_NODE")); 778 } 779 ssm.replaceSchema(schemaDoc); 780 } 781 782 private void appendSubSchema(Document doc) throws SSOException, SMSException { 783 if (doc == null) { 784 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 785 IUMSConstants.SMS_SMSSchema_no_schema_element, null)); 786 } 787 788 Document schemaDoc = ssm.getDocumentCopy(); 789 790 try { 791 Node schemaNode = getSchemaNode(schemaDoc); 792 Node node = XMLUtils.getRootNode(doc, SMSUtils.SUB_SCHEMA); 793 NodeList childrens = schemaNode.getChildNodes(); 794 Node nextSibling = null; 795 for (int i = 0; i < childrens.getLength(); i++) { 796 Node child = childrens.item(i); 797 if (Node.ELEMENT_NODE == child.getNodeType() 798 && !SMSUtils.SCHEMA_ATTRIBUTE.equals(child.getNodeName())) { 799 //In this case we've found an entry that is not an AttributeSchema, so this is definitely an 800 //element before which we can place a SubSchema. (i.e. the found element was a SubSchema or 801 //an OrganizationAttributeSchema). Note that this will change the order of the SubSchema 802 //elements in the service description, however the order should not matter for SMS. 803 nextSibling = child; 804 break; 805 } 806 } 807 Node iNode = schemaDoc.importNode(node, true); 808 schemaNode.insertBefore(iNode, nextSibling); 809 } catch (Exception ex) { 810 throw (new SMSException(ex.getMessage(), ex, "sms-cannot_append_NODE")); 811 } 812 813 ssm.replaceSchema(schemaDoc); 814 } 815 816 // ----------------------------------------------------------- 817 // Protected methods 818 // ----------------------------------------------------------- 819 void removeChildNode(String nodeType, String nodeName) throws SSOException, 820 SMSException { 821 if (debug.messageEnabled()) { 822 debug.message("ServiceSchema::removeChildNode called for: " 823 + getServiceName() + "(" + ssm.getVersion() + ") " 824 + componentName); 825 } 826 Document schemaDoc = ssm.getDocumentCopy(); 827 Node schemaNode = getSchemaNode(schemaDoc); 828 if (schemaNode != null) { 829 Node node = XMLUtils.getNamedChildNode(schemaNode, nodeType, 830 SMSUtils.NAME, nodeName); 831 if (node != null) { 832 schemaNode.removeChild(node); 833 ssm.replaceSchema(schemaDoc); 834 } 835 } 836 } 837 838 void replaceChildNode(String nodeType, String nodeName, Node attributeSchemaNode) throws SSOException, 839 SMSException { 840 if (debug.messageEnabled()) { 841 debug.message("ServiceSchema::replaceChildNode called for: " 842 + getServiceName() + "(" + ssm.getVersion() + ") " 843 + componentName); 844 } 845 Document schemaDoc = ssm.getDocumentCopy(); 846 Node schemaNode = getSchemaNode(schemaDoc); 847 if (schemaNode != null) { 848 Node oldNode = XMLUtils.getNamedChildNode(schemaNode, nodeType, 849 SMSUtils.NAME, nodeName); 850 if (oldNode != null) { 851 Node newNode = schemaDoc.importNode(attributeSchemaNode, true); 852 schemaNode.replaceChild(newNode, oldNode); 853 ssm.replaceSchema(schemaDoc); 854 } 855 } else { 856 if (debug.messageEnabled()) { 857 debug.message("ServiceSchema::replaceChildNode failed to retrieve service schema for : " 858 + getServiceName() + "(" + ssm.getVersion() + ") " 859 + componentName); 860 } 861 } 862 } 863 864 // ----------------------------------------------------------- 865 // Method to obtain schema node 866 // ----------------------------------------------------------- 867 Node getSchemaNode(Document document) throws SMSException { 868 NodeList nodes = document.getElementsByTagName(SMSUtils.SCHEMA); 869 if ((nodes == null) || (nodes.getLength() == 0)) { 870 throwInvalidSchemaException(); 871 } 872 Node rNode = nodes.item(0); 873 874 // Get the schema type node 875 String schemaType = SMSUtils.GLOBAL_SCHEMA; 876 if (type.equals(SchemaType.ORGANIZATION)) { 877 schemaType = SMSUtils.ORG_SCHEMA; 878 } else if (type.equals(SchemaType.DYNAMIC)) { 879 schemaType = SMSUtils.DYNAMIC_SCHEMA; 880 } else if (type.equals(SchemaType.USER)) { 881 schemaType = SMSUtils.USER_SCHEMA; 882 } else if (type.equals(SchemaType.POLICY)) { 883 schemaType = SMSUtils.POLICY_SCHEMA; 884 } else if (type.equals(SchemaType.GROUP)) { 885 schemaType = SMSUtils.GROUP_SCHEMA; 886 } else if (type.equals(SchemaType.DOMAIN)) { 887 schemaType = SMSUtils.DOMAIN_SCHEMA; 888 } 889 890 Node stNode = XMLUtils.getChildNode(rNode, schemaType); 891 if (stNode == null) { 892 throwInvalidSchemaException(); 893 } 894 895 // Walk the component name 896 if ((componentName == null) || (componentName.length() == 0)) { 897 return (stNode); 898 } else if (orgAttrSchema) { 899 // OrganizationAttributeSchema 900 return (XMLUtils 901 .getChildNode(stNode, SMSUtils.ORG_ATTRIBUTE_SCHEMA)); 902 } 903 904 StringTokenizer st = new StringTokenizer(componentName, "/"); 905 while (st.hasMoreTokens()) { 906 String tokenName = st.nextToken(); 907 if ((tokenName == null) || (tokenName.length() == 0)) { 908 continue; 909 } 910 if ((stNode = XMLUtils.getNamedChildNode(stNode, 911 SMSUtils.SUB_SCHEMA, SMSUtils.NAME, tokenName)) == null) { 912 throwInvalidSchemaException(); 913 } 914 } 915 return (stNode); 916 } 917 918 // ----------------------------------------------------------- 919 // Method to obtain organizationattributeschema node 920 // ----------------------------------------------------------- 921 Node getOrgAttrSchemaNode(Document doc) throws SMSException { 922 NodeList nodes = doc.getElementsByTagName( 923 SMSUtils.ORG_ATTRIBUTE_SCHEMA); 924 if (nodes == null || (nodes.getLength() == 0)) { 925 // Throw an exception 926 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 927 "sms-invalid-orgattr-schema-document", null)); 928 } 929 Node rNode = nodes.item(0); 930 if (rNode == null) { 931 throwInvalidSchemaException(); 932 } 933 return (rNode); 934 } 935 936 void throwInvalidSchemaException() throws SMSException { 937 SMSEntry.debug.error("ServiceSchema::getSchemaNode: " 938 + "Invalid service schema XML: " + getServiceName() + "(" 939 + ssm.getVersion() + ")"); 940 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 941 IUMSConstants.SMS_SMSSchema_no_service_element, null)); 942 } 943 944 static Debug debug = SMSEntry.debug; 945}
Copyright © 2010-2017, ForgeRock All Rights Reserved.