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: AttributeSchema.java,v 1.13 2009/01/13 06:56:08 mahesh_prasad_r Exp $ 026 * 027 * Portions Copyrighted 2014-2016 ForgeRock AS. 028 */ 029 030package com.sun.identity.sm; 031 032import java.security.AccessController; 033import java.text.MessageFormat; 034import java.util.Collections; 035import java.util.HashMap; 036import java.util.HashSet; 037import java.util.Iterator; 038import java.util.Map; 039import java.util.Set; 040 041import org.w3c.dom.Document; 042import org.w3c.dom.Element; 043import org.w3c.dom.Node; 044 045import com.sun.identity.shared.debug.Debug; 046import com.sun.identity.shared.xml.XMLUtils; 047import com.iplanet.sso.SSOException; 048import com.sun.identity.security.EncodeAction; 049 050/** 051 * The class <code>AttributeSchema</code> provides methods to access the 052 * schema of a configuration parameter. Also, it provides methods to set default 053 * and choice values. 054 * 055 * @supported.all.api 056 */ 057public class AttributeSchema { 058 // Debug 059 private Debug debug = Debug.getInstance("amSMS"); 060 061 // Instance variable 062 ServiceSchemaManager ssm; 063 064 ServiceSchema ss; 065 066 PluginSchema ps; 067 068 AttributeSchemaImpl as; 069 070 /** 071 * Constructor. Makes it private so that it cannot be instantiated. 072 */ 073 private AttributeSchema() { 074 } 075 076 /** 077 * Constructor used by ServiceSchema to instantiate 078 * <code>AttributeSchema</code> objects. 079 */ 080 protected AttributeSchema(AttributeSchemaImpl as, ServiceSchemaManager ssm, 081 ServiceSchema ss) { 082 this.ssm = ssm; 083 this.ss = ss; 084 this.as = as; 085 if (as == null) { 086 debug.error("AttributeSchema:: IMPL is NULL"); 087 } 088 } 089 090 protected AttributeSchema(AttributeSchemaImpl as, PluginSchema ps) { 091 this.as = as; 092 this.ps = ps; 093 } 094 095 /** 096 * Returns the name of the attribute. 097 * 098 * @return the name of the attribute 099 */ 100 public String getName() { 101 return (as.getName()); 102 } 103 104 /** 105 * Returns the type of the attribute. 106 * 107 * @return the type of the attribute 108 */ 109 public AttributeSchema.Type getType() { 110 return (as.getType()); 111 } 112 113 /** 114 * Returns Service Schema. 115 * 116 * @return Service Schema. 117 */ 118 public ServiceSchema getServiceSchema() { 119 return ss; 120 } 121 122 /** 123 * Sets the type. 124 * 125 * @param type 126 * to be changed to 127 * @throws SMSException 128 * if an error is encountered when trying to set 129 * @throws SSOException 130 * if the single sign on token is invalid or expired 131 */ 132 public void setType(String type) throws SMSException, SSOException { 133 updateXMLDocument(SMSUtils.ATTRIBUTE_TYPE, type); 134 } 135 136 /** 137 * Returns the list order of the attribute. 138 * 139 * @return The list order of the attribute, or {@code null} if the list order is not defined. 140 */ 141 public AttributeSchema.ListOrder getListOrder() { 142 return as.getListOrder(); 143 } 144 145 /** 146 * Returns the UI type of the attribute. 147 * 148 * @return the UI type of the attribute; or null if the UI Type is not 149 * defined 150 */ 151 public AttributeSchema.UIType getUIType() { 152 return (as.getUIType()); 153 } 154 155 /** 156 * Sets the <code>UIType</code> attribute. 157 * 158 * @param uiType 159 * user interface type. 160 * @throws SMSException 161 * if an error is encountered when trying to set 162 * <code>UIType</code> to the attribute schema. 163 * @throws SSOException 164 * if the single sign on token is invalid or expired 165 */ 166 public void setUIType(String uiType) throws SMSException, SSOException { 167 updateXMLDocument(SMSUtils.ATTRIBUTE_UITYPE, uiType); 168 } 169 170 /** 171 * Returns the syntax of the attribute. 172 * 173 * @return the syntax of the attribute 174 */ 175 public AttributeSchema.Syntax getSyntax() { 176 return (as.getSyntax()); 177 } 178 179 /** 180 * Sets the Syntax attribute. 181 * 182 * @param synt 183 * syntax 184 * @throws SMSException 185 * if an error is encountered when trying to set the attribute 186 * syntax 187 * @throws SSOException 188 * if the single sign on token is invalid or expired 189 */ 190 public void setSyntax(String synt) throws SMSException, SSOException { 191 updateXMLDocument(SMSUtils.ATTRIBUTE_SYNTAX, synt); 192 } 193 194 /** 195 * Returns the I18N key to describe the configuration attribute. 196 * 197 * @return the I18N key to describe the configuration attribute 198 */ 199 public String getI18NKey() { 200 return (as.getI18NKey()); 201 } 202 203 /** 204 * Returns the order of this attribute. 205 * 206 * @return the order of this attribute, null if not defined 207 */ 208 public Integer getOrder() { 209 return as.getOrder(); 210 } 211 212 /** 213 * Sets the I18N key to describe the configuration attribute. 214 * 215 * @param i18nKey 216 * the I18N key to describe the attribute 217 * @throws SMSException 218 * if an error is encountered when trying to set I18N key to the 219 * attribute schema 220 * @throws SSOException 221 * if the single sign on token is invalid or expired 222 */ 223 public void setI18NKey(String i18nKey) throws SMSException, SSOException { 224 updateXMLDocument(SMSUtils.I18N_KEY, i18nKey); 225 } 226 227 /** 228 * Sets the order of this attribute. 229 * 230 * @param order 231 * the integer value representing the order 232 * @throws SMSException 233 * if an error is encountered 234 * @throws SSOException 235 * if the single sign on token is invalid or expired 236 */ 237 public void setOrder(Integer order) throws SMSException, SSOException { 238 updateXMLDocument(SMSUtils.ORDER, String.valueOf(order)); 239 } 240 241 /** 242 * Returns the value of the <code>cosQualifier</code> for this attribute 243 * that is <code>default, override, operational or merge-cos</code>. 244 * 245 * @return the value of the <code>cosQualifier</code>. 246 */ 247 public String getCosQualifier() { 248 return (as.getCosQualifier()); 249 } 250 251 /** 252 * Sets the <code>cosQualifier</code> attribute 253 * 254 * @param cosq 255 * value of <code>cosQualifier</code>. 256 * @throws SMSException 257 * if an error is encountered when trying to set. 258 * @throws SSOException 259 * if the single sign on token is invalid or expired 260 */ 261 public void setCosQualifier(String cosq) throws SMSException, SSOException { 262 updateXMLDocument(SMSUtils.ATTRIBUTE_COS_QUALIFIER, cosq); 263 } 264 265 /** 266 * Returns the default values of the attribute. If there are no default 267 * values defined for this attribute in the schema then this method returns 268 * a Collections.EMPTY_SET 269 * 270 * @return set of default values of the attribute 271 */ 272 public Set getDefaultValues() { 273 return (as.getDefaultValues()); 274 } 275 276 /** 277 * Returns the default values of the attribute for the given environment 278 * parameters. If there are no default values defined for this attribute in 279 * the schema then this method returns a Collections.EMPTY_SET 280 * 281 * @param envParams 282 * Map of environment parameter to a set of values 283 * @return set of default values of the attribute 284 */ 285 public Set getDefaultValues(Map envParams) { 286 return (as.getDefaultValues(envParams)); 287 } 288 289 /** 290 * Returns the example values of the attribute. If there are no example 291 * values defined for this attribute in the schema then this method returns 292 * a Collections.EMPTY_SET 293 * 294 * @return set of example values of the attribute 295 */ 296 public Set<String> getExampleValues() { 297 return (as.getExampleValues()); 298 } 299 300 /** 301 * Sets the default values of the attribute. 302 * 303 * @param values 304 * the set of default values 305 * @throws SMSException 306 * if an error is encountered when trying to set. 307 * @throws SSOException 308 * if the single sign on token is invalid or expired 309 */ 310 public void setDefaultValues(Set values) throws SMSException, SSOException { 311 updateDefaultValues(values); 312 } 313 314 /** 315 * Protected method to set the default values in the given XML document. 316 * 317 * @throws SMSException 318 * if an error is encountered when trying to set. 319 * @throws SSOException 320 * if the single sign on token is invalid or expired 321 */ 322 void setDefaultValues(Set values, Document document) throws SMSException, 323 SSOException { 324 updateDefaultValues(values, document); 325 } 326 327 /** 328 * Adds a default value to the existing set of default values. 329 * 330 * @param value 331 * the default value to add 332 * @throws SMSException 333 * if an error is encountered when trying to set. 334 * @throws SSOException 335 * if the single sign on token is invalid or expired 336 */ 337 public void addDefaultValue(String value) throws SMSException, SSOException 338 { 339 Set defaultValues = getDefaultValues(); 340 if (defaultValues != Collections.EMPTY_SET) { 341 defaultValues.add(value); 342 } else { 343 defaultValues = new HashSet(); 344 defaultValues.add(value); 345 } 346 updateDefaultValues(defaultValues); 347 } 348 349 /** 350 * Removes the all the default values for the attribute. 351 * 352 * @throws SMSException 353 * if an error is encountered when trying to set. 354 * @throws SSOException 355 * if the single sign on token is invalid or expired 356 * 357 */ 358 public void removeDefaultValues() throws SMSException, SSOException { 359 updateDefaultValues(new HashSet()); 360 } 361 362 /** 363 * Removes the given value from the set of default values. 364 * 365 * @param value 366 * the default value to remove 367 * @throws SMSException 368 * if an error is encountered when trying to set. 369 * @throws SSOException 370 * if the single sign on token is invalid or expired 371 */ 372 public void removeDefaultValue(String value) throws SMSException, 373 SSOException { 374 Set defaultValues = getDefaultValues(); 375 if (defaultValues != Collections.EMPTY_SET) { 376 defaultValues.remove(value); 377 updateDefaultValues(defaultValues); 378 } 379 } 380 381 /** 382 * Returns the possible choice values for the attribute if the attribute 383 * type is either <code>SINGLE_CHOICE</code> or 384 * <code>MULTIPLE_CHOICE</code>. 385 * 386 * @return set of possible choice values 387 */ 388 public String[] getChoiceValues() { 389 return (as.getChoiceValues()); 390 } 391 392 /** 393 * Returns the possible choice values for the attribute if the attribute 394 * type is either <code>SINGLE_CHOICE</code> or 395 * <code>MULTIPLE_CHOICE</code>, for the given environment parameters. 396 * 397 * @param envParams 398 * Map of environment parameter to a set of values 399 * @return set of possible choice values 400 */ 401 public String[] getChoiceValues(Map envParams) { 402 return (as.getChoiceValues(envParams)); 403 } 404 405 /** 406 * Returns the possible choice values for the attribute if the attribute 407 * type is either <code>SINGLE_CHOICE</code> or 408 * <code>MULTIPLE_CHOICE</code>, for the given environment parameters, 409 * along with the values' i18n keys. 410 * 411 * @param envParams 412 * Map of environment parameter to a set of values 413 * @return Map of value to i18n key. 414 */ 415 public Map getChoiceValuesMap(Map envParams) { 416 return as.getChoiceValuesMap(envParams); 417 } 418 419 /** 420 * Indicates whether this AttributeSchema has choice values defined. 421 */ 422 public boolean hasChoiceValues() { 423 return as.hasChoiceValues(); 424 } 425 426 /** 427 * Returns the I18N key for the given choice value. 428 * 429 * @param cValue 430 * choice value. 431 * @return the I18N key for the given choice value 432 */ 433 public String getChoiceValueI18NKey(String cValue) { 434 return (as.getChoiceValueI18NKey(cValue)); 435 } 436 437 /** 438 * Adds a choice value and its i18n key to the existing set of choice 439 * values. 440 * 441 * @param value 442 * the choice value to add 443 * @param i18nKey 444 * the I18N key for the choice value 445 * @throws SMSException 446 * if an error is encountered when trying to set. 447 * @throws SSOException 448 * if the single sign on token is invalid or expired 449 */ 450 public void addChoiceValue(String value, String i18nKey) 451 throws SMSException, SSOException { 452 Map choiceValues = as.getChoiceValuesMap(); 453 choiceValues.put(value, i18nKey); 454 updateChoiceValues(choiceValues); 455 } 456 457 /** 458 * Removes the given value from the set of choice values. 459 * 460 * @param value 461 * the choice value to remove 462 * @throws SMSException 463 * if an error is encountered when trying to set. 464 * @throws SSOException 465 * if the single sign on token is invalid or expired 466 */ 467 public void removeChoiceValue(String value) throws SMSException, 468 SSOException { 469 Map choiceValues = as.getChoiceValuesMap(); 470 if (choiceValues.remove(value) != null) { 471 updateChoiceValues(choiceValues); 472 } 473 } 474 475 /** 476 * Returns the start range if the attribute syntax is either 477 * <code>NUMBER_RANGE</code> or <code>DECIMAL_RANGE</code>. 478 * 479 * @return the start range for the attribute value 480 */ 481 public String getStartRange() { 482 return (as.getStartRange()); 483 } 484 485 /** 486 * Sets the start range attribute. 487 * 488 * @param stRange 489 * start range. 490 * @throws SMSException 491 * if an error is encountered when trying to set 492 * @throws SSOException 493 * if the single sign on token is invalid or expired 494 */ 495 public void setStartRange(String stRange) throws SMSException, SSOException 496 { 497 updateXMLDocument(SMSUtils.ATTRIBUTE_RANGE_START, stRange); 498 } 499 500 /** 501 * Returns the end range if the attribute syntax is either 502 * <code>NUMBER_RANGE</code> or <code>DECIMAL_RANGE</code>. 503 * 504 * @return the end range for the attribute value 505 */ 506 public String getEndRange() { 507 return (as.getEndRange()); 508 } 509 510 /** 511 * Sets the end range Attribute. 512 * 513 * @param edRange 514 * end range. 515 * @throws SMSException 516 * if an error is encountered when trying to set 517 * @throws SSOException 518 * if the single sign on token is invalid or expired 519 */ 520 public void setEndRange(String edRange) throws SMSException, SSOException { 521 updateXMLDocument(SMSUtils.ATTRIBUTE_RANGE_END, edRange); 522 } 523 524 /** 525 * Method to get the validator name for using to validate this service 526 * attribute 527 * 528 * @return the validator name 529 */ 530 public String getValidator() { 531 return (as.getValidator()); 532 } 533 534 /** 535 * Sets the Validator attribute 536 * 537 * @param valid 538 * validator 539 * @throws SMSException 540 * if an error is encountered when trying to set 541 * @throws SSOException 542 * if the single sign on token is invalid or expired 543 */ 544 public void setValidator(String valid) throws SMSException, SSOException { 545 updateXMLDocument(SMSUtils.ATTRIBUTE_VALIDATOR, valid); 546 } 547 548 /** 549 * Returns the minimum number of values for the attribute if the attribute 550 * is of type <code>MULTIPLE_CHOICE</code>. 551 * 552 * @return the minimum number of values 553 */ 554 public int getMinValue() { 555 return (as.getMinValue()); 556 } 557 558 /** 559 * Sets the minimum value attribute. 560 * 561 * @param minV 562 * minimum value. 563 * @throws SMSException 564 * if an error is encountered when trying to set 565 * @throws SSOException 566 * if the single sign on token is invalid or expired 567 */ 568 public void setMinValue(String minV) throws SMSException, SSOException { 569 updateXMLDocument(SMSUtils.ATTRIBUTE_MIN_VALUE, minV); 570 } 571 572 /** 573 * Returns the maximum number of values for the attribute if the attribute 574 * is of type <code>MULTIPLE_CHOICE</code>. 575 * 576 * @return the maximum number of values 577 */ 578 public int getMaxValue() { 579 return (as.getMaxValue()); 580 } 581 582 /** 583 * Sets the maximum value attribute. 584 * 585 * @param maxV 586 * maximum value. 587 * @throws SMSException 588 * if an error is encountered when trying to set 589 * @throws SSOException 590 * if the single sign on token is invalid or expired 591 */ 592 public void setMaxValue(String maxV) throws SMSException, SSOException { 593 updateXMLDocument(SMSUtils.ATTRIBUTE_MAX_VALUE, maxV); 594 } 595 596 /** 597 * Sets the boolean values of the attribute. 598 * 599 * @param trueValue string value for <code>BooleanTrueValue</code>. 600 * @param trueValueI18nKey <code>I18N</code> key for 601 * <code>BooleanTrueValue</code>. 602 * @param falseValue string value for <code>BooleanFalseValue</code>. 603 * @param falseValueI18nKey <code>I18N</code> Key for 604 * <code>BooleanFalseValue</code>. 605 * @throws SMSException if an error is encountered when trying to set. 606 * @throws SSOException if the single sign on token is invalid or expired 607 */ 608 public void setBooleanValues( 609 String trueValue, 610 String trueValueI18nKey, 611 String falseValue, 612 String falseValueI18nKey 613 ) throws SSOException, SMSException { 614 updateBooleanValues(trueValue, trueValueI18nKey, 615 falseValue, falseValueI18nKey, null); 616 } 617 618 619 /** 620 * Returns the string value for <code>BooleanTrueValue</code>. 621 * 622 * @return the string value for <code>BooleanTrueValue</code>. 623 */ 624 public String getTrueValue() { 625 return (as.getTrueValue()); 626 } 627 628 /** 629 * Returns the <code>I18N</code> key for <code>BooleanTrueValue</code>. 630 * 631 * @return the <code>I18N</code> key for <code>BooleanTrueValue</code>. 632 */ 633 public String getTrueValueI18NKey() { 634 return (as.getTrueValueI18NKey()); 635 } 636 637 /** 638 * Returns the string value for <code>BooleanFalseValue</code>. 639 * 640 * @return the string value for <code>BooleanFalseValue</code>. 641 */ 642 public String getFalseValue() { 643 return (as.getFalseValue()); 644 } 645 646 /** 647 * Returns the <code>I18N</code> Key for <code>BooleanFalseValue</code>. 648 * 649 * @return the <code>I18N</code> Key for <code>BooleanFalseValue</code>. 650 */ 651 public String getFalseValueI18NKey() { 652 return (as.getFalseValueI18NKey()); 653 } 654 655 /** 656 * Returns true if the attribute is an optional attribute. 657 * 658 * @return true if the attribute is an optional attribute. 659 */ 660 public boolean isOptional() { 661 return (as.isOptional()); 662 } 663 664 /** 665 * Returns true if the attribute is a service identifier (i.e., in the case 666 * of LDAP it would be the COS Specifier attribute). 667 * 668 * @return true if the attribute is service identifier attribute. 669 */ 670 public boolean isServiceIdentifier() { 671 return (as.isServiceIdentifier()); 672 } 673 674 /** 675 * Checks if the attribute allows to have resource name. 676 * 677 * @return true if the attribute allows to have resource name; false 678 * otherwise 679 */ 680 public boolean isResourceNameAllowed() { 681 return (as.isResourceNameAllowed()); 682 } 683 684 /** 685 * Returns true if the attribute is a service's status attribute. 686 * 687 * @return true if the attribute is a status attribute. 688 */ 689 public boolean isStatusAttribute() { 690 return (as.isStatusAttribute()); 691 } 692 693 /** 694 * Method to get service specific attributes. It return the value of the 695 * "any" attribute, if set in the XML schema for the service 696 * 697 * @return value of "any" attribute 698 */ 699 public String getAny() { 700 return (as.getAny()); 701 } 702 703 /** 704 * Sets the any attribute. 705 * 706 * @param a 707 * value for any attribute. 708 * @throws SMSException 709 * if an error is encountered when trying to set. 710 * @throws SSOException 711 * if the single sign on token is invalid or expired. 712 */ 713 public void setAny(String a) throws SMSException, SSOException { 714 updateXMLDocument(SMSUtils.ATTRIBUTE_ANY, a); 715 } 716 717 /** 718 * Returns URL of the view bean for the attribute. 719 * 720 * @return URL for view bean 721 */ 722 public String getPropertiesViewBeanURL() { 723 return (as.getPropertiesViewBeanURL()); 724 } 725 726 /** 727 * Sets the URL of the view bean for the attribute. 728 * 729 * @param prop 730 * properties view bean URL. 731 * @throws SMSException 732 * if an error is encountered when trying to set. 733 * @throws SSOException 734 * if the single sign on token is invalid or expired. 735 */ 736 public void setPropertiesViewBeanUR(String prop) throws SMSException, 737 SSOException { 738 updateXMLDocument(SMSUtils.ATTRIBUTE_VIEW_BEAN_URL, prop); 739 } 740 741 /** 742 * Returns <code>true</code> if the attribute is searchable; 743 * <code>false</code> otherwise 744 * 745 * @return <code>true</code> if the attribute is an optional attribute; 746 * <code>false</code> otherwise 747 */ 748 public boolean isSearchable() { 749 return (as.isSearchable()); 750 } 751 752 /** 753 * Sets the attribute isSearchable, if value is set to <code>true 754 * </code>, 755 * or <code>false</code>. 756 * 757 * @param value 758 * if set to <code>true</code> the attribute will be 759 * searchable; else searches cannot be performed on this 760 * attribute. 761 * @throws SMSException 762 * if an error is encountered when trying to set 763 * @throws SSOException 764 * if the single sign on token is invalid or expired 765 */ 766 public void setSearchable(String value) throws SMSException, SSOException { 767 if ((!(value.toLowerCase()).equals("yes")) 768 && (!(value.toLowerCase()).equals("no"))) { 769 String[] arg = { value }; 770 debug.error("AttributeSchema: Invalid isSearchable value"); 771 throw new SMSException(SMSEntry.bundle 772 .getString("sms-invalid-searchable-value") 773 + ":" + arg, "sms-invalid-searchable-value"); 774 } 775 updateXMLDocument(SMSUtils.ISSEARCHABLE, value); 776 } 777 778 /** 779 * Returns the name of this attribute when used in a CREST representation. 780 */ 781 public String getResourceName() { 782 String resourceName = as.getResourceName(); 783 return resourceName == null ? getName() : resourceName; 784 } 785 786 /** 787 * Sets the CREST representation name for the attribute. 788 * 789 * @param name 790 * the name of the CREST property. 791 * @throws SMSException 792 * if an error is encountered when trying to set. 793 * @throws SSOException 794 * if the single sign on token is invalid or expired. 795 */ 796 public void setResourceName(String name) throws SSOException, SMSException { 797 updateXMLDocument(SMSUtils.RESOURCE_NAME, name); 798 } 799 800 /** 801 * Returns a string representation of this <code> AttributeSchema </code> 802 * object. 803 * 804 * @return String representation of this object 805 */ 806 public String toString() { 807 return (as.toString()); 808 } 809 810 /** 811 * Method for modifying default values 812 */ 813 protected void updateDefaultValues(Set defaultValues) throws SMSException, 814 SSOException { 815 updateDefaultValues(defaultValues, null); 816 } 817 818 /** 819 * Method for modifying default values given the XML document 820 */ 821 protected void updateDefaultValues(Set defaultValues, Document doc) 822 throws SMSException, SSOException { 823 // Check if the values are valid 824 if (ss != null) { 825 Map tempattrs = new HashMap(1); 826 tempattrs.put(getName(), defaultValues); 827 ss.validateAttributes(tempattrs); 828 } 829 830 // Check if the attributes have to be encoded 831 boolean encode = false; 832 if (getSyntax().equals(Syntax.PASSWORD) 833 || getSyntax().equals(Syntax.ENCRYPTED_PASSWORD)) { 834 encode = true; 835 } 836 837 // Construct DefaultValues node 838 StringBuffer sb = new StringBuffer(100); 839 sb.append(XML_PREFIX).append(DEFAULT_VALUES_BEGIN); 840 Iterator items = defaultValues.iterator(); 841 while (items.hasNext()) { 842 sb.append(VALUE_BEGIN); 843 if (encode) { 844 String encString = (String) items.next(); 845 try { 846 encString = (String) AccessController 847 .doPrivileged(new EncodeAction(encString)); 848 } catch (Throwable e) { 849 debug.error("AttributeSchema: Unable to encode", e); 850 } 851 sb.append(encString); 852 } else { 853 sb.append(SMSSchema.escapeSpecialCharacters((String) items 854 .next())); 855 } 856 sb.append(VALUE_END); 857 } 858 sb.append(DEFAULT_VALUES_END); 859 updateXMLDocument(sb, SMSUtils.ATTRIBUTE_DEFAULT_ELEMENT, doc); 860 } 861 862 protected void updateChoiceValues(Map choiceValues) throws SMSException, 863 SSOException { 864 updateChoiceValues(choiceValues, null); 865 } 866 867 protected void updateChoiceValues(Map choiceValues, Document doc) 868 throws SMSException, SSOException { 869 // Construct ChoiceValues 870 StringBuffer sb = new StringBuffer(100); 871 sb.append(XML_PREFIX).append(CHOICE_VALUES_BEGIN); 872 Iterator items = choiceValues.keySet().iterator(); 873 while (items.hasNext()) { 874 String[] vals = new String[2]; 875 String value = SMSSchema.escapeSpecialCharacters((String) items 876 .next()); 877 String i18nKey = (String) choiceValues.get(value); 878 if (i18nKey == null) { 879 vals[0] = value; 880 sb.append(MessageFormat.format(CHOICE_VALUE, (Object[])vals)); 881 } else { 882 vals[0] = i18nKey; 883 vals[1] = value; 884 sb.append(MessageFormat.format( 885 CHOICE_VALUE_KEY, (Object[])vals)); 886 } 887 } 888 sb.append(CHOICE_VALUES_END); 889 updateXMLDocument(sb, SMSUtils.ATTRIBUTE_CHOICE_VALUES_ELEMENT, doc); 890 } 891 892 protected void updateBooleanValues( 893 String trueValue, 894 String trueValueI18nKey, 895 String falseValue, 896 String falseValueI18nKey, 897 Document doc 898 ) throws SMSException, SSOException { 899 // Construct BooleanValues 900 StringBuffer sb = new StringBuffer(100); 901 sb.append(XML_PREFIX).append(BOOLEAN_VALUES_BEGIN); 902 903 String[] trueVals = new String[2]; 904 if ((trueValueI18nKey != null) && (trueValue != null)) { 905 trueVals[0] = trueValueI18nKey; 906 trueVals[1] = SMSSchema.escapeSpecialCharacters(trueValue); 907 } else { 908 trueVals[0] = getTrueValueI18NKey(); 909 trueVals[1] = getTrueValue(); 910 } 911 sb.append(MessageFormat.format(TRUE_BOOLEAN_KEY, (Object[])trueVals)); 912 913 String[] falseVals = new String[2]; 914 if ((falseValueI18nKey != null) && (falseValue != null)) { 915 falseVals[0] = falseValueI18nKey; 916 falseVals[1] = SMSSchema.escapeSpecialCharacters(falseValue); 917 } else { 918 falseVals[0] = getFalseValueI18NKey(); 919 falseVals[1] = getFalseValue(); 920 } 921 sb.append(MessageFormat.format(FALSE_BOOLEAN_KEY, (Object[])falseVals)); 922 923 sb.append(BOOLEAN_VALUES_END); 924 updateXMLDocument(sb, SMSUtils.ATTRIBUTE_BOOLEAN_VALUES_ELEMENT, doc); 925 } 926 927 protected void updateXMLDocument(StringBuffer sb, String elementName, 928 Document updateDoc) throws SMSException, SSOException { 929 // Update the default element in XML 930 try { 931 // Construct the XML document 932 Document doc = SMSSchema.getXMLDocument(sb.toString(), false); 933 Node node = XMLUtils.getRootNode(doc, elementName); 934 935 // Convert to Schema's document 936 Document schemaDoc = null; 937 if (updateDoc != null) { 938 schemaDoc = updateDoc; 939 } else if (ssm != null) { 940 schemaDoc = ssm.getDocumentCopy(); 941 } else { 942 schemaDoc = ps.getDocumentCopy(); 943 } 944 Node nNode = schemaDoc.importNode(node, true); 945 946 // Traverse the document to get this attribute element 947 Node schemaNode = null; 948 if (ss != null) { 949 schemaNode = ss.getSchemaNode(schemaDoc); 950 } else { 951 schemaNode = ps.getPluginSchemaNode(schemaDoc); 952 } 953 Node attrSchemaNode = XMLUtils.getNamedChildNode(schemaNode, 954 SMSUtils.SCHEMA_ATTRIBUTE, SMSUtils.NAME, getName()); 955 956 // Try getting OrganizationAttributeSchema if AttributeSchema 957 // node is not there within Organization node. 958 // This will be a special case for idrepo service. 959 if (attrSchemaNode == null) { 960 schemaNode = ss.getOrgAttrSchemaNode(schemaDoc); 961 attrSchemaNode = XMLUtils.getNamedChildNode(schemaNode, 962 SMSUtils.SCHEMA_ATTRIBUTE, SMSUtils.NAME, getName()); 963 } 964 Node oNode = XMLUtils.getChildNode(attrSchemaNode, elementName); 965 if (oNode != null) { 966 attrSchemaNode.replaceChild(nNode, oNode); 967 } else { 968 attrSchemaNode.appendChild(nNode); 969 } 970 // Update the schema in the directory 971 if (updateDoc != null) { 972 // do nothing 973 } else if (ssm != null) { 974 ssm.replaceSchema(schemaDoc); 975 } else { 976 ps.replacePluginSchema(schemaDoc); 977 } 978 } catch (Exception e) { 979 throw (new SMSException(e.getMessage(), e, 980 "sms-cannot-update-xml-document")); 981 } 982 } 983 984 /** 985 * update attribute value in attribute schema element 986 */ 987 protected void updateXMLDocument(String attrName, String attrValue) 988 throws SMSException, SSOException { 989 // Update the default element in XML 990 try { 991 // Construct the XML document 992 Document schemaDoc = null; 993 if (ssm != null) { 994 schemaDoc = ssm.getDocumentCopy(); 995 } else { 996 schemaDoc = ps.getDocumentCopy(); 997 } 998 999 // Traverse the document to get this attribute element 1000 Node schemaNode = null; 1001 if (ss != null) { 1002 schemaNode = ss.getSchemaNode(schemaDoc); 1003 } else { 1004 schemaNode = ps.getPluginSchemaNode(schemaDoc); 1005 } 1006 1007 Node attrSchemaNode = XMLUtils.getNamedChildNode(schemaNode, 1008 SMSUtils.SCHEMA_ATTRIBUTE, SMSUtils.NAME, getName()); 1009 ((Element) attrSchemaNode).setAttribute(attrName, attrValue); 1010 1011 // Update the schema in the directory 1012 if (ssm != null) { 1013 ssm.replaceSchema(schemaDoc); 1014 } else { 1015 ps.replacePluginSchema(schemaDoc); 1016 } 1017 } catch (Exception e) { 1018 throw (new SMSException(e.getMessage(), e, 1019 "sms-cannot-update-xml-document")); 1020 } 1021 } 1022 1023 /** 1024 * The class <code>Type</code> defines the types of schema attributes and 1025 * provides static constants for these types. This could also be viewed as a 1026 * higher level structured data types like Set, List, etc. The primitive 1027 * data types are defined by <code>Syntax</code>. Currently defined 1028 * schema attribute types are <code>SINGLE</code>, <code>LIST</code>, 1029 * <code>SINGLE_CHOICE</code>, <code>MULTIPLE_CHOICE</code>, 1030 * <code>SIGNATURE</code> and <code>VALIDATOR</code>. 1031 */ 1032 public static class Type extends Object { 1033 1034 /** 1035 * The <code>SINGLE</code> attribute type specifies that the attribute 1036 * can have only a single value. 1037 */ 1038 public static final Type SINGLE = new Type("single"); 1039 1040 /** 1041 * The <code>LIST</code> attribute type specifies that the attribute 1042 * can have multiple values, i.e., multi-valued attribute. 1043 */ 1044 public static final Type LIST = new Type("list"); 1045 1046 /** 1047 * The <code>SINGLE_CHOICE</code> attribute type specifies that the 1048 * attribute can have value defined by the <code>getChoiceValues</code> 1049 * method of <code>AttributeSchema</code>. 1050 */ 1051 public static final Type SINGLE_CHOICE = new Type("single_choice"); 1052 1053 /** 1054 * The <code>MULTIPLE_CHOICE</code> attribute type specifies that the 1055 * attribute can have multiple values defined by the 1056 * <code>getChoiceValues</code> method of <code>AttributeSchema</code>. 1057 */ 1058 public static final Type MULTIPLE_CHOICE = new Type("multiple_choice"); 1059 1060 /** 1061 * The <code>SIGNATURE</code> attribute type specifies that the 1062 * attribute is a signing attribute. 1063 */ 1064 public static final Type SIGNATURE = new Type("signature"); 1065 1066 /** 1067 * The <code>VALIDATOR</code> attribute type specifies that the 1068 * attribute defines a attribute validator plugin. 1069 */ 1070 public static final Type VALIDATOR = new Type("validator"); 1071 1072 private String attrType; 1073 1074 private Type() { 1075 } 1076 1077 private Type(String type) { 1078 attrType = type; 1079 } 1080 1081 /** 1082 * The method returns the string representation of the schema attribute 1083 * type. 1084 * 1085 * @return String string representation of schema attribute type 1086 */ 1087 public String toString() { 1088 return attrType; 1089 } 1090 1091 /** 1092 * Method to check if two schema attribute types are equal. 1093 * 1094 * @param schemaAttrType 1095 * the reference object with which to compare 1096 * 1097 * @return <code>true</code> if the objects are same; <code> 1098 * false</code> 1099 * otherwise 1100 */ 1101 public boolean equals(Object schemaAttrType) { 1102 if (schemaAttrType instanceof Type) { 1103 Type s = (Type) schemaAttrType; 1104 return (s.attrType.equals(attrType)); 1105 } 1106 return (false); 1107 } 1108 1109 /** 1110 * Returns a hash code value for the object. 1111 * 1112 * @return a hash code value for the object 1113 */ 1114 public int hashCode() { 1115 return attrType.hashCode(); 1116 } 1117 } 1118 1119 /** 1120 * This enum {@code ListOrder} defines the list orders of schema attributes and provides constants for these list 1121 * orders. These types will mainly be used by the GUI to determine how to display the schema attributes. 1122 */ 1123 public enum ListOrder { 1124 /** Orders lists naturally. */ 1125 NATURAL, 1126 /** Orders lists in the order they are entered in LDAP. */ 1127 INSERTION 1128 } 1129 1130 /** 1131 * The class <code>UIType</code> defines the UI types of schema attributes 1132 * and provides static constants for these types. These types mainly will be 1133 * used by the GUI to determine how to display the schema attributes. 1134 * Currently defined schema attribute UI types are <code>RADIO</code>, 1135 * <code>LINK</code>, <code>BUTTON</code> and 1136 * <code>NAME_VALUE_LIST</code> 1137 */ 1138 public static class UIType extends Object { 1139 1140 /** 1141 * The <code>RADIO</code> attribute type specifies that the attribute 1142 * should be display as radio button. 1143 */ 1144 public static final UIType RADIO = new UIType("radio"); 1145 1146 /** 1147 * The <code>LINK</code> attribute type specifies that the attribute 1148 * should be display as a link. 1149 */ 1150 public static final UIType LINK = new UIType("link"); 1151 1152 /** 1153 * The <code>BUTTON</code> attribute type specifies that the attribute 1154 * should be display as a button. 1155 */ 1156 public static final UIType BUTTON = new UIType("button"); 1157 1158 /** 1159 * The <code>NAME_VALUE_LIST</code> attribute type specifies that the 1160 * attribute should be display as a name value list widget. 1161 */ 1162 public static final UIType NAME_VALUE_LIST = new UIType( 1163 "name_value_list"); 1164 1165 /** 1166 * The <code>UNORDERED_LIST</code> attribute type specifies that the 1167 * attribute should be display as an unordered list widget. 1168 */ 1169 public static final UIType UNORDEREDLIST = new UIType("unorderedlist"); 1170 1171 /** 1172 * The <code>ORDERED_LIST</code> attribute type specifies that the 1173 * attribute should be display as an ordered list widget. 1174 */ 1175 public static final UIType ORDEREDLIST = new UIType("orderedlist"); 1176 1177 /** 1178 * The <code>MAP_LIST</code> attribute type specifies that the 1179 * attribute should be display as an map list widget. 1180 */ 1181 public static final UIType MAPLIST = new UIType("maplist"); 1182 1183 /** 1184 * The <code>GLOBALMAP_LIST</code> attribute type specifies that the 1185 * attribute should be display as a global map list widget. 1186 */ 1187 public static final UIType GLOBALMAPLIST = new UIType("globalmaplist"); 1188 1189 /** 1190 * The <code>ADDREMOVELIST</code> attribute type specifies that the 1191 * multiple choice attribute should be display as add remove list 1192 * widget. 1193 */ 1194 public static final UIType ADDREMOVELIST = new UIType("addremovelist"); 1195 1196 /** 1197 * The <code>SCRIPTSELECT</code> attribute type specifies that the 1198 * attribute should be display as drop down widget. 1199 */ 1200 public static final UIType SCRIPTSELECT = new UIType("scriptSelect"); 1201 1202 /** 1203 * The <code>GLOBALSCRIPTSELECT</code> attribute type specifies that the 1204 * attribute should be display as drop down widget with only global scripts. 1205 */ 1206 public static final UIType GLOBALSCRIPTSELECT = new UIType("globalScriptSelect"); 1207 1208 private String attrType; 1209 1210 private UIType() { 1211 } 1212 1213 private UIType(String type) { 1214 attrType = type; 1215 } 1216 1217 /** 1218 * The method returns the string representation of the schema attribute 1219 * UI type. 1220 * 1221 * @return String string representation of schema attribute UI type 1222 */ 1223 public String toString() { 1224 return attrType; 1225 } 1226 1227 /** 1228 * Method to check if two schema attribute UI types are equal. 1229 * 1230 * @param schemaAttrType 1231 * the reference object with which to compare 1232 * 1233 * @return <code>true</code> if the objects are same; <code> 1234 * false</code> 1235 * otherwise 1236 */ 1237 public boolean equals(Object schemaAttrType) { 1238 if (schemaAttrType instanceof UIType) { 1239 UIType s = (UIType) schemaAttrType; 1240 return (s.attrType.equals(attrType)); 1241 } 1242 return (false); 1243 } 1244 1245 /** 1246 * Returns a hash code value for the object. 1247 * 1248 * @return a hash code value for the object 1249 */ 1250 public int hashCode() { 1251 return attrType.hashCode(); 1252 } 1253 } 1254 1255 /** 1256 * The class <code>Syntax</code> defines the syntax of the schema 1257 * attributes and provides static constants for these types. In other words, 1258 * this class defines the primitive data types for the schema attributes. 1259 */ 1260 public static class Syntax { 1261 1262 /** 1263 * The <code>BOOLEAN</code> attribute syntax specifies that the 1264 * attribute is of boolean type, i.e., can have a value of either 1265 * <code>true</code> or <code> 1266 * false</code> 1267 */ 1268 public static final Syntax BOOLEAN = new Syntax("boolean"); 1269 1270 /** 1271 * The <code>EMAIL</code> attribute syntax specifies that the 1272 * attribute is a email address. 1273 */ 1274 public static final Syntax EMAIL = new Syntax("email"); 1275 1276 /** 1277 * The <code>URL</code> attribute syntax specifies that the attribute 1278 * is a URL. 1279 */ 1280 public static final Syntax URL = new Syntax("url"); 1281 1282 /** 1283 * The <code>STRING</code> attribute syntax specifies that the 1284 * attribute is of text type, i.e., can have any unicode characters. 1285 */ 1286 public static final Syntax STRING = new Syntax("string"); 1287 1288 /** 1289 * The <code>PARAGRAPH</code> attribute syntax specifies that the 1290 * attribute is of multi-lined text type. 1291 */ 1292 public static final Syntax PARAGRAPH = new Syntax("paragraph"); 1293 1294 /** 1295 * The <code>XML</code> attribute syntax specifies that the attribute 1296 * is of XML type, i.e., can have any unicode characters. 1297 */ 1298 public static final Syntax XML = new Syntax("xml"); 1299 1300 /** 1301 * The <code>SCRIPT</code> attribute syntax specifies that the 1302 * attribute is of multi-lined text type and more specifically a script. 1303 */ 1304 public static final Syntax SCRIPT = new Syntax("script"); 1305 1306 /** 1307 * The <code>PASSWORD</code> attribute syntax specifies that the 1308 * attribute is of password type, will be used by UI to mask the 1309 * password typed. 1310 */ 1311 public static final Syntax PASSWORD = new Syntax("password"); 1312 1313 /** 1314 * The <code>ENCRYPTED PASSWORD</code> attribute syntax specifies that 1315 * the attribute is of password type, will be used by UI to mask the 1316 * password typed. 1317 */ 1318 public static final Syntax ENCRYPTED_PASSWORD = new Syntax( 1319 "encrypted_password"); 1320 1321 /** 1322 * The <code>DATE</code> attribute syntax specifies that the attribute 1323 * is of date type. 1324 */ 1325 public static final Syntax DATE = new Syntax("date"); 1326 1327 /** 1328 * The <code>NUMERIC</code> attribute syntax specifies that the 1329 * attribute is numeric, i.e., can have numbers only. 1330 */ 1331 public static final Syntax NUMERIC = new Syntax("numeric"); 1332 1333 /** 1334 * The <code>NUMBER</code> attribute syntax specifies that the 1335 * attribute is a number. 1336 */ 1337 public static final Syntax NUMBER = new Syntax("number"); 1338 1339 /** 1340 * The <code>DECIMAL</code> attribute syntax specifies that the 1341 * attribute is a decimal value. 1342 */ 1343 public static final Syntax DECIMAL = new Syntax("decimal"); 1344 1345 /** 1346 * The <code>PERCENT</code> attribute syntax specifies that the 1347 * attribute is a percentage. 1348 */ 1349 public static final Syntax PERCENT = new Syntax("percent"); 1350 1351 /** 1352 * The <code>NUMBER_RANGE</code> attribute syntax specifies that the 1353 * attribute is a number within a range. 1354 */ 1355 public static final Syntax NUMBER_RANGE = new Syntax("number_range"); 1356 1357 /** 1358 * The <code>DECIMAL_RANGE</code> attribute syntax specifies that the 1359 * attribute is a decimal number within a range. 1360 */ 1361 public static final Syntax DECIMAL_RANGE = new Syntax("decimal_range"); 1362 1363 /** 1364 * The <code>DECIMAL_NUMBER</code> attribute syntax specifies that the 1365 * attribute is a floating point number, e.g., 1.5, 3.56, etc. 1366 */ 1367 public static final Syntax DECIMAL_NUMBER = 1368 new Syntax("decimal_number"); 1369 1370 /** 1371 * The <code>DN</code> attribute syntax specifies that the attribute 1372 * should be an LDAP distinguished name (DN). 1373 */ 1374 public static final Syntax DN = new Syntax("dn"); 1375 1376 private String attrSyntax; 1377 1378 private Syntax() { 1379 } 1380 1381 private Syntax(String syntax) { 1382 attrSyntax = syntax; 1383 } 1384 1385 /** 1386 * The method returns the string representation of the schema attribute 1387 * syntax. 1388 * 1389 * @return String string representation of schema attribute syntax 1390 */ 1391 public String toString() { 1392 return (attrSyntax); 1393 } 1394 1395 /** 1396 * Method to check if two schema attribute syntax are equal. 1397 * 1398 * @param schemaAttrSyntax 1399 * the reference object with which to compare 1400 * 1401 * @return <code>true</code> if the objects are same; <code> 1402 * false</code> 1403 * otherwise 1404 */ 1405 public boolean equals(Object schemaAttrSyntax) { 1406 if (schemaAttrSyntax instanceof Syntax) { 1407 Syntax s = (Syntax) schemaAttrSyntax; 1408 return (s.attrSyntax.equals(attrSyntax)); 1409 } 1410 return (false); 1411 } 1412 1413 /** 1414 * Returns a hash code value for the object. 1415 * 1416 * @return a hash code value for the object 1417 */ 1418 public int hashCode() { 1419 return attrSyntax.hashCode(); 1420 } 1421 } 1422 1423 private static final String XML_PREFIX = 1424 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 1425 1426 private static final String DEFAULT_VALUES_BEGIN = "<" 1427 + SMSUtils.ATTRIBUTE_DEFAULT_ELEMENT + ">"; 1428 1429 private static final String DEFAULT_VALUES_END = "</" 1430 + SMSUtils.ATTRIBUTE_DEFAULT_ELEMENT + ">"; 1431 1432 static final String VALUE_BEGIN = "<" + SMSUtils.ATTRIBUTE_VALUE + ">"; 1433 1434 static final String VALUE_END = "</" + SMSUtils.ATTRIBUTE_VALUE + ">"; 1435 1436 private static final String CHOICE_VALUES_BEGIN = "<" 1437 + SMSUtils.ATTRIBUTE_CHOICE_VALUES_ELEMENT + ">"; 1438 1439 private static final String CHOICE_VALUES_END = "</" 1440 + SMSUtils.ATTRIBUTE_CHOICE_VALUES_ELEMENT + ">"; 1441 1442 private static final String CHOICE_VALUE_KEY = "<" 1443 + SMSUtils.ATTRIBUTE_CHOICE_VALUE_ELEMENT + " " + SMSUtils.I18N_KEY 1444 + "=\"{0}\">{1}</" + SMSUtils.ATTRIBUTE_CHOICE_VALUE_ELEMENT + ">"; 1445 1446 private static final String CHOICE_VALUE = "<" 1447 + SMSUtils.ATTRIBUTE_CHOICE_VALUE_ELEMENT + ">{0}</" 1448 + SMSUtils.ATTRIBUTE_CHOICE_VALUE_ELEMENT + ">"; 1449 1450 private static final String BOOLEAN_VALUES_BEGIN = 1451 "<" + SMSUtils.ATTRIBUTE_BOOLEAN_VALUES_ELEMENT + ">"; 1452 1453 private static final String BOOLEAN_VALUES_END = 1454 "</" + SMSUtils.ATTRIBUTE_BOOLEAN_VALUES_ELEMENT + ">"; 1455 1456 private static final String TRUE_BOOLEAN_KEY = 1457 "<" + SMSUtils.ATTRIBUTE_TRUE_BOOLEAN_ELEMENT + 1458 " " + SMSUtils.I18N_KEY + "=\"{0}\">{1}</" + 1459 SMSUtils.ATTRIBUTE_TRUE_BOOLEAN_ELEMENT + ">"; 1460 1461 private static final String FALSE_BOOLEAN_KEY = 1462 "<" + SMSUtils.ATTRIBUTE_FALSE_BOOLEAN_ELEMENT + 1463 " " + SMSUtils.I18N_KEY + "=\"{0}\">{1}</" + 1464 SMSUtils.ATTRIBUTE_FALSE_BOOLEAN_ELEMENT + ">"; 1465}