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