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: ServiceConfig.java,v 1.18 2009/01/28 05:35:03 ww203982 Exp $ 026 * 027 * Portions Copyrighted 2011-2018 ForgeRock AS. 028 * Portions Copyrighted 2012 Open Source Solution Technology Corporation 029 */ 030package com.sun.identity.sm; 031 032import java.util.Collections; 033import java.util.HashSet; 034import java.util.Iterator; 035import java.util.Map; 036import java.util.Set; 037 038import org.forgerock.opendj.ldap.DN; 039 040import com.iplanet.services.util.AMEncryption; 041import com.iplanet.sso.SSOException; 042import com.iplanet.sso.SSOToken; 043import com.iplanet.ums.IUMSConstants; 044 045/** 046 * The class <code>ServiceConfig</code> provides interfaces to manage the 047 * configuration information of a service configuration. It provides methods to 048 * get and set configuration parameters for this service configuration. 049 * 050 * @supported.all.api 051 */ 052public class ServiceConfig { 053 // Instance variables 054 private SSOToken token; 055 056 private ServiceConfigImpl sc; 057 058 private ServiceSchemaImpl ss; 059 060 private ServiceConfigManager scm; 061 062 /** 063 * Default constructor. Makes it private so that it can not be instantiated. 064 */ 065 private ServiceConfig() { 066 // hence can not be instantiated 067 } 068 069 /** 070 * Protected constructor 071 */ 072 protected ServiceConfig(ServiceConfigManager scm, ServiceConfigImpl sc) 073 throws SMSException, SSOException { 074 this.scm = scm; 075 token = scm.getSSOToken(); 076 this.sc = sc; 077 this.ss = sc.getServiceSchemaImpl(); 078 } 079 080 /** 081 * Returns the name of this service configuration. 082 * 083 * @return the name of this service configuration 084 */ 085 public String getServiceName() { 086 return (scm.getName()); 087 } 088 089 /** 090 * Returns the service version 091 * 092 * @return service version 093 */ 094 public String getVersion() { 095 return (scm.getVersion()); 096 } 097 098 /** 099 * Returns the service component name. It is "/" separated and the root 100 * component name is "/". 101 * 102 * @return service component name 103 */ 104 public String getComponentName() { 105 validate(); 106 return (sc.getComponentName()); 107 } 108 109 /** 110 * Returns the service name. 111 * 112 * @return service name 113 */ 114 public String getName() { 115 validate(); 116 return sc.getName(); 117 } 118 119 /** 120 * Returns the service component's schema ID. For global and organization's 121 * root configurations it returns an empty string. 122 * 123 * @return service component's schema ID 124 */ 125 public String getSchemaID() { 126 validate(); 127 return (sc.getSchemaID()); 128 } 129 130 /** 131 * Returns the priority assigned to the service configuration. 132 * 133 * @return the priority assigned to the service configuration 134 */ 135 public int getPriority() { 136 validate(); 137 return (sc.getPriority()); 138 } 139 140 /** 141 * Sets the priority to the service configuration. 142 * 143 * @param priority 144 * the priority to be assigned to the configuration 145 * @throws SMSException 146 * if there is an error occurred while performing the operation 147 * @throws SSOException 148 * if the user's single sign-on is invalid or expired 149 */ 150 public void setPriority(int priority) throws SSOException, SMSException { 151 validateServiceConfigImpl(); 152 StringBuilder sb = new StringBuilder(8); 153 String[] priorities = { sb.append(priority).toString() }; 154 SMSEntry e = sc.getSMSEntry(); 155 e.setAttribute(SMSEntry.ATTR_PRIORITY, priorities); 156 saveSMSEntry(e); 157 } 158 159 /** 160 * Returns the labeled uri assigned to the service configuration. 161 * 162 * @return the labeled uri assigned to the service configuration 163 * @deprecated The labeledURI setting shall not be used for storing configuration data. 164 */ 165 public String getLabeledUri() { 166 validate(); 167 return (sc.getLabeledUri()); 168 } 169 170 /** 171 * Sets the labeled uri to the service configuration. 172 * 173 * @param luri the labeled uri to be assigned to the configuration 174 * @throws SMSException 175 * if there is an error occurred while performing the operation 176 * @throws SSOException 177 * if the user's single sign-on is invalid or expired 178 * @deprecated The labeledURI setting shall not be used for storing configuration data. 179 */ 180 public void setLabeledUri(String luri) throws SSOException, SMSException { 181 validateServiceConfigImpl(); 182 StringBuilder sb = new StringBuilder(8); 183 String[] lUris = { sb.append(luri).toString() }; 184 SMSEntry e = sc.getSMSEntry(); 185 e.setAttribute(SMSEntry.ATTR_LABELED_URI, lUris); 186 saveSMSEntry(e); 187 } 188 189 /** 190 * delete the labeled uri to the service configuration. 191 * 192 * @param luri the labeled uri to be assigned to the configuration 193 * @throws SMSException 194 * if there is an error occurred while performing the operation 195 * @throws SSOException 196 * if the user's single sign-on is invalid or expired 197 * @deprecated The labeledURI setting shall not be used for storing configuration data. 198 */ 199 public void deleteLabeledUri(String luri) throws SSOException, SMSException { 200 validateServiceConfigImpl(); 201 SMSEntry e = sc.getSMSEntry(); 202 sc.setLabeledUri(null); 203 e.removeAttribute(SMSEntry.ATTR_LABELED_URI, luri); 204 saveSMSEntry(e); 205 } 206 207 /** 208 * Returns the names of all service's sub-configurations. 209 * 210 * @return set of names of all service's sub-configurations 211 * @throws SMSException 212 * if there is an error accessing the data store 213 */ 214 public Set<String> getSubConfigNames() throws SMSException { 215 validateServiceConfigImpl(); 216 try { 217 return sc.getSubConfigNames(token); 218 } catch (SSOException s) { 219 SMSEntry.debug.error("ServiceConfig: Unable to " 220 + "get subConfig Names", s); 221 } 222 return (Collections.EMPTY_SET); 223 } 224 225 /** 226 * Method to get names of service's sub-configurations that match the given 227 * pattern. 228 * 229 * @param pattern 230 * pattern to match for sub-configuration names 231 * @return names of the service sub-configuration 232 * @throws SMSException 233 * if an error occurred while performing the operation. 234 */ 235 public Set<String> getSubConfigNames(String pattern) throws SMSException { 236 validateServiceConfigImpl(); 237 try { 238 return (sc.getSubConfigNames(token, pattern)); 239 } catch (SSOException s) { 240 SMSEntry.debug.error("ServiceConfigManager: Unable to " 241 + "get subConfig Names for filter: " + pattern, s); 242 } 243 return Collections.emptySet(); 244 245 } 246 247 /** 248 * Method to get names of service's sub-configurations that match the given 249 * pattern and belongs to the specified service schema name. 250 * 251 * @param pattern 252 * pattern to match for other entities. 253 * @param schemaName 254 * service schema name. 255 * @return names of the service sub-configuration 256 * @throws SMSException 257 * if an error occurred while performing the operation. 258 */ 259 public Set<String> getSubConfigNames(String pattern, String schemaName) 260 throws SMSException { 261 validateServiceConfigImpl(); 262 try { 263 return sc.getSubConfigNames(token, pattern, schemaName); 264 } catch (SSOException s) { 265 SMSEntry.debug.error("ServiceConfigManager: Unable to " 266 + "get subConfig Names for filters: " + pattern + "AND" 267 + schemaName, s); 268 } 269 return Collections.emptySet(); 270 271 } 272 273 /** 274 * Method to retrieve a single service sub-configuration entry by name. 275 * Avoids otherwise having to filter through a large list of entries using 276 * getSubConfigNames(String pattern) 277 * 278 * @param entityName 279 * name to match for entity 280 * @return Details of the entry found 281 * @throws SMSException 282 * if an error occurred while performing the operation 283 */ 284 public Map<String, Set<String>> getSubConfigEntity(String entityName) throws SMSException { 285 validateServiceConfigImpl(); 286 try { 287 return sc.getSubConfigEntity(token, entityName); 288 } catch (SSOException ssoe) { 289 SMSEntry.debug.error("ServiceConfigManager: Unable to " 290 + "get subConfig entity for: {}", entityName, ssoe); 291 } 292 return null; 293 } 294 295 /** 296 * Returns a set of exported fully qualified sub-configuration names that 297 * can be imported used locally as service configuration 298 * 299 * @param serviceId 300 * service schema identifier 301 * @return names of fully qualified applicable service sub-configurations 302 * @throws SMSException 303 * if an error occurred while performing the operation. 304 */ 305 public Set getExportedSubConfigNames(String serviceId) throws SMSException { 306 return (null); 307 } 308 309 /** 310 * Returns the service's sub-configuration given the service's 311 * sub-configuration name. 312 * 313 * @param subConfigName 314 * The name of the service's sub-configuration to retrieve. 315 * @return The <code>ServiceConfig</code> object corresponding to the 316 * specified name of the service's sub-configuration. 317 * @throws SMSException 318 * if there is an error occurred while performing the operation 319 * @throws SSOException 320 * if the user's single sign-on is invalid or expired 321 */ 322 public ServiceConfig getSubConfig(String subConfigName) 323 throws SSOException, SMSException { 324 ServiceConfigImpl sci = sc.getSubConfig(token, subConfigName); 325 return ((sci == null) ? null : new ServiceConfig(scm, sci)); 326 } 327 328 /** 329 * Adds a service sub-configuration with configuration parameters. 330 * 331 * @param subConfigName 332 * the name of service sub-configuration to add 333 * @param subConfigId 334 * type of service sub-configuration 335 * @param priority 336 * the priority of the configuration 337 * @param attrs 338 * configuration parameters for the sub-configuration 339 * @throws SMSException 340 * if there is an error occurred while performing the operation 341 * @throws SSOException 342 * if the user's single sign-on is invalid or expired 343 */ 344 public void addSubConfig(String subConfigName, String subConfigId, 345 int priority, Map attrs) throws SMSException, SSOException { 346 validateServiceConfigImpl(); 347 // Check if this entry exists 348 if (sc.isNewEntry()) { 349 // Ideally these nodes should have been created, since they 350 // are not present we need to create them 351 scm.createOrganizationConfig(sc.getOrganizationName(), null); 352 // Check if rest of the component names are present 353 checkAndCreateComponents(sc.getDN()); 354 } 355 356 // Get service schemas 357 String subSchemaIdentifier = subConfigId == null ? subConfigName : subConfigId; 358 ServiceSchemaImpl nss = ss.getSubSchema(subSchemaIdentifier); 359 360 if (nss == null) { 361 String[] args = { subSchemaIdentifier }; 362 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 363 "sms-invalid-add-sub-config-unknown-schema-name", args)); 364 } 365 366 if (!nss.supportsMultipleConfigurations() 367 && !getSubConfigNames().isEmpty()) { 368 String[] args = { subConfigName }; 369 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 370 "sms-invalid-add-sub-config", args)); 371 } 372 373 // Convert priority to string 374 StringBuilder sb = new StringBuilder(8); 375 sb.append(priority); 376 377 // Create the entry 378 CreateServiceConfig.createSubConfigEntry(token, ("ou=" + subConfigName 379 + "," + sc.getDN()), nss, subConfigId, sb.toString(), 380 SMSUtils.copyAttributes(attrs), sc.getOrganizationName()); 381 } 382 383 /** 384 * Removes the service sub-configuration. 385 * 386 * @param subConfigName 387 * name of service sub-configuration to remove 388 * @throws SMSException 389 * if there is an error occurred while performing the operation 390 * @throws SSOException 391 * if the user's single sign-on is invalid or expired 392 */ 393 public void removeSubConfig(String subConfigName) throws SMSException, 394 SSOException { 395 validateServiceConfigImpl(); 396 // Obtain the SMSEntry for the subconfig and delete it 397 // unescape in case users provide such a subConfigName for deletion. 398 // "http:&#47;&#47;abc.east.sun.com:58080" 399 400 subConfigName = SMSSchema.unescapeName(subConfigName); 401 402 // First remove the entry from ServiceConfigImpl Cache. 403 404 // Construct subconfig DN 405 String sdn = "ou=" + subConfigName + "," + sc.getDN(); 406 407 // Construct ServiceConfigManagerImpl 408 ServiceConfigManagerImpl scmImpl = ServiceConfigManagerImpl. 409 getInstance(token, getServiceName(), getVersion()); 410 411 // Construct ServiceConfigImpl of the removed subconfig. 412 ServiceConfigImpl sConfigImpl = 413 sc.getSubConfig(token, subConfigName); 414 415 // Call ServiceConfigImpl's deleteInstance() to remove from cache. 416 if (sConfigImpl != null) { 417 ServiceConfigImpl.deleteInstance(token, scmImpl, null, sdn, "/", 418 sConfigImpl.getGroupName(), (getComponentName() + "/" 419 + SMSSchema.escapeSpecialCharacters(subConfigName)), false, 420 ss); 421 } 422 // Remove this entry from smsentry. 423 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, sdn); 424 if (cEntry.isDirty()) { 425 cEntry.refresh(); 426 } 427 SMSEntry entry = cEntry.getClonedSMSEntry(); 428 entry.delete(token); 429 cEntry.refresh(entry); 430 431 // Remove the entry from CachedSubEntries 432 CachedSubEntries cse = CachedSubEntries.getInstance(token, sc.getDN()); 433 cse.remove(subConfigName); 434 } 435 436 /** 437 * Imports a service sub-configuration to the list of localy defined 438 * sub-configuration. The imported sub-configuration name must be fully 439 * qualified, as obtained from <code>getExportedSubConfigNames</code>. 440 * 441 * @param subConfigName 442 * the name of service sub-configuration to add locally 443 * @param exportedSubConfigName 444 * the fully qualified name of the exported sub-configuration 445 * name 446 * @throws SMSException 447 * if there is an error occurred while performing the operation 448 * @throws SSOException 449 * if the user's single sign-on is invalid or expired 450 */ 451 public void importSubConfig(String subConfigName, 452 String exportedSubConfigName) throws SMSException, SSOException { 453 } 454 455 /** 456 * Returns the service configuration parameters. The keys in the 457 * <code>Map</code> contains the attribute names and their corresponding 458 * values in the <code>Map</code> is a <code>Set</code> that contains 459 * the values for the attribute. This method picks up the default values for 460 * any attributes not defined in the <code>ServiceConfig</code>. The 461 * default values for these attributes are picked up from the Service 462 * Schema. If there is no default value defined, then this method will still 463 * return the attribute-value pair, except that the Set will be a 464 * Collections.EMPTY_SET. This is distinct from an empty Set with no entries 465 * in it. AN empty set represents an attribute whose value has been set to 466 * an empty value by the application using the <code>setAttributes()</code> 467 * method. 468 * 469 * @return the <code>Map</code> where key is the attribute name and value 470 * is the <code>Set</code> of attribute values 471 */ 472 public Map getAttributes() { 473 validate(); 474 return (sc.getAttributes()); 475 } 476 477 /** 478 * Returns the service configuration parameters for read only. 479 * The keys in the <code>Map</code> contains the attribute names and 480 * their corresponding values in the <code>Map</code> is a 481 * <code>Set</code> that contains the values for the attribute. 482 */ 483 484 /** 485 * Returns the service configuration parameters without inheriting the 486 * default values from service's schema. The keys in the <code>Map</code> 487 * contains the attribute names and their corresponding values in the 488 * <code>Map</code> is a <code>Set</code> that contains the values for 489 * the attribute. 490 */ 491 public Map getAttributesWithoutDefaults() { 492 validate(); 493 return (sc.getAttributesWithoutDefaults()); 494 } 495 496 /** 497 * Returns the service configuration parameters for read only, 498 * modification cannot be performed on the return <code>Map</code>. 499 * The keys in the 500 * <code>Map</code> contains the attribute names and their 501 * corresponding values in the <code>Map</code> is a 502 * <code>Set</code> that contains the values for the attribute. 503 * This method picks up the default values for any attributes 504 * not defined in the <code>ServiceConfig</code>. The default values for 505 * these attributes are picked up from the Service Schema. 506 * If there is no default value defined, then this method 507 * will still return the attribute-value pair, except that 508 * the Set will be a Collections.EMPTY_SET. 509 * This is distinct from an empty Set with no entries in it. 510 * AN empty set represents an attribute whose value has 511 * been set to an empty value by the application using 512 * the <code>setAttributes()</code> method. 513 * 514 * @return the <code>Map</code> where key is the attribute name 515 * and value is the <code>Set</code> of attribute values 516 */ 517 public Map<String, Set<String>> getAttributesForRead() { 518 validate(); 519 return (sc.getAttributesForRead()); 520 } 521 522 /** 523 * Returns the service configuration parameters for read only without 524 * inheriting the default values from service's schema. The keys 525 * in the <code>Map</code> contains the attribute names and their 526 * corresponding values in the <code>Map</code> is a 527 * <code>Set</code> that contains the values for the attribute. 528 */ 529 public Map<String, Set<String>> getAttributesWithoutDefaultsForRead() { 530 validate(); 531 return (sc.getAttributesWithoutDefaultsForRead()); 532 } 533 534 /** 535 * Sets the service configuration parameters. The keys in the 536 * <code>Map</code> contains the attribute names and their corresponding 537 * values in the <code>Map</code> is a <code>Set</code> that contains 538 * the values for the attribute. This method will replace the existing 539 * attribute values with the given one. For attributes that are not 540 * specified in <code>attrs</code>, it will not be modified. 541 * 542 * @param attrs 543 * the <code>Map</code> where key is the attribute name and 544 * value is the <code>Set</code> of attribute values 545 * @throws SMSException 546 * if there is an error occurred while performing the operation 547 * @throws SSOException 548 * if the user's single sign-on is invalid or expired 549 */ 550 public void setAttributes(Map attrs) throws SMSException, SSOException { 551 validateServiceConfigImpl(); 552 Map oldAttrs = sc.getAttributesWithoutDefaults(); 553 Iterator it = oldAttrs.keySet().iterator(); 554 Map newAttrs = SMSUtils.copyAttributes(attrs); 555 while (it.hasNext()) { 556 String s = (String) it.next(); 557 if (!newAttrs.containsKey(s)) { 558 newAttrs.put(s, oldAttrs.get(s)); 559 } 560 } 561 /* 562 * For validation using ChoiceValues plugin we need to pass in 563 * OrganizationName, since the plugins use organization names to compute 564 * the choice values 565 */ 566 ss.validateAttributes(token, newAttrs, true, sc.getOrganizationName()); 567 SMSEntry e = sc.getSMSEntry(); 568 SMSUtils.setAttributeValuePairs(e, newAttrs, ss 569 .getSearchableAttributeNames()); 570 saveSMSEntry(e); 571 } 572 573 /** 574 * Adds a configuration parameter to the service configuration. 575 * 576 * @param attrName 577 * the name of the attribute to add 578 * @param values 579 * the set of values to add 580 * @throws SMSException 581 * if there is an error occurred while performing the operation 582 * @throws SSOException 583 * if the user's single sign-on is invalid or expired 584 */ 585 public void addAttribute(String attrName, Set values) throws SMSException, 586 SSOException { 587 validateServiceConfigImpl(); 588 // Get current attributes 589 Map attributes = getAttributes(); 590 // Validate attribute values 591 Set newVals = values; 592 Set oldVals = (Set) attributes.get(attrName); 593 if (oldVals != null) { 594 newVals = new HashSet(); 595 newVals.addAll(values); 596 newVals.addAll(oldVals); 597 } 598 ss 599 .validateAttrValues(token, attrName, newVals, true, sc 600 .getOrganizationName()); 601 // Store the entry 602 SMSEntry e = sc.getSMSEntry(); 603 SMSUtils.addAttribute(e, attrName, values, ss 604 .getSearchableAttributeNames()); 605 saveSMSEntry(e); 606 } 607 608 /** 609 * Removes a configuration parameter from the service configuration. 610 * 611 * @param attrName 612 * the name of the attribute to remove 613 * @throws SMSException 614 * if there is an error occurred while performing the operation 615 * @throws SSOException 616 * if the user's single sign-on is invalid or expired 617 */ 618 public void removeAttribute(String attrName) throws SMSException, 619 SSOException { 620 validateServiceConfigImpl(); 621 SMSEntry e = sc.getSMSEntry(); 622 SMSUtils.removeAttribute(e, attrName); 623 saveSMSEntry(e); 624 } 625 626 /** 627 * Removes a configuration parameters from the service configuration. 628 * 629 * @param attrNames 630 * <code>Set</code> of attribute names to remove 631 * @throws SMSException 632 * if there is an error occurred while performing the operation 633 * @throws SSOException 634 * if the user's single sign-on is invalid or expired 635 */ 636 public void removeAttributes(Set attrNames) throws SMSException, 637 SSOException { 638 validateServiceConfigImpl(); 639 SMSEntry e = sc.getSMSEntry(); 640 if (attrNames != null && !attrNames.isEmpty()) { 641 for (Iterator items = attrNames.iterator(); items.hasNext();) { 642 SMSUtils.removeAttribute(e, (String) items.next()); 643 } 644 saveSMSEntry(e); 645 } 646 } 647 648 /** 649 * Removes the specific values for the given configuration parameter. 650 * 651 * @param attrName 652 * the name of the attribute 653 * @param values 654 * set of attribute values to remove from the given attribute 655 * @throws SMSException 656 * if there is an error occurred while performing the operation 657 * @throws SSOException 658 * if the user's single sign-on is invalid or expired 659 */ 660 public void removeAttributeValues(String attrName, Set values) 661 throws SMSException, SSOException { 662 validateServiceConfigImpl(); 663 SMSEntry e = sc.getSMSEntry(); 664 SMSUtils.removeAttributeValues(e, attrName, values, ss 665 .getSearchableAttributeNames()); 666 saveSMSEntry(e); 667 } 668 669 /** 670 * Replaces old value of the configuration parameter with new value. 671 * 672 * @param attrName 673 * the name of the attribute 674 * @param oldValue 675 * the old value to remove from the attribute 676 * @param newValue 677 * the new value to add to the attribute 678 * @throws SMSException 679 * if there is an error occurred while performing the operation 680 * @throws SSOException 681 * if the user's single sign-on is invalid or expired 682 */ 683 public void replaceAttributeValue(String attrName, String oldValue, 684 String newValue) throws SMSException, SSOException { 685 validateServiceConfigImpl(); 686 // Get current attributes 687 Map attributes = getAttributes(); 688 // Validate values 689 690 Set currentValues = (Set) attributes.get(attrName); 691 if (currentValues != null && !currentValues.contains(oldValue)) { 692 throw (new SMSException("Current value doesn't match supplied value", 693 "sms-INVALID_PARAMETERS")); 694 } 695 696 Set newVals = new HashSet(); 697 Set oldVals = (Set) attributes.get(attrName); 698 if (oldVals != null) { 699 newVals.addAll(oldVals); 700 newVals.remove(oldValue); 701 } 702 newVals.add(newValue); 703 ss 704 .validateAttrValues(token, attrName, newVals, true, sc 705 .getOrganizationName()); 706 // Store the entry 707 SMSEntry e = sc.getSMSEntry(); 708 SMSUtils.replaceAttributeValue(e, attrName, oldValue, newValue, ss 709 .getSearchableAttributeNames()); 710 saveSMSEntry(e); 711 } 712 713 /** 714 * Replaces the old values of the configuration parameter with the new 715 * values. 716 * 717 * @param attrName 718 * the name of the attribute 719 * @param oldValues 720 * the set of old values to remove from the attribute 721 * @param newValues 722 * the set of new values to add to the attribute 723 * @throws SMSException 724 * if there is an error occurred while performing the operation 725 * @throws SSOException 726 * if the user's single sign-on is invalid or expired 727 */ 728 public void replaceAttributeValues(String attrName, Set oldValues, 729 Set newValues) throws SMSException, SSOException { 730 validateServiceConfigImpl(); 731 // Get current attributes 732 Map attributes = getAttributes(); 733 // Validate values 734 Set newVals = new HashSet(); 735 Set oldVals = (Set) attributes.get(attrName); 736 if (oldVals != null) { 737 newVals.addAll(oldVals); 738 newVals.removeAll(oldValues); 739 } 740 newVals.addAll(newValues); 741 ss.validateAttrValues(token, attrName, newVals, true, 742 sc.getOrganizationName()); 743 // Store the entry 744 SMSEntry e = sc.getSMSEntry(); 745 SMSUtils.replaceAttributeValues(e, attrName, oldValues, newValues, ss 746 .getSearchableAttributeNames()); 747 saveSMSEntry(e); 748 } 749 750 /** 751 * Returns the LDAP DN represented by this <code>ServiceConfig</code> 752 * object. 753 * 754 * @return the LDAP DN represented by this <code>ServiceConfig</code> 755 * object. 756 */ 757 public String getDN() { 758 validate(); 759 return (sc.getDN()); 760 } 761 762 /** 763 * Returns the last modified time stamp of this configuration This method is 764 * expensive because it does not cache the modified time stamp but goes 765 * directly to the data store to obtain the value of this entry 766 * 767 * @return The last modified time stamp as a string with the format of 768 * <code> yyyyMMddhhmmss </code> 769 * @throws SMSException 770 * if there is an error trying to read from the data store 771 * @throws SSOException 772 * if the single sign-on token of the user is invalid. 773 */ 774 775 public String getLastModifiedTime() throws SMSException, SSOException { 776 validateServiceConfigImpl(); 777 SMSEntry e = sc.getSMSEntry(); 778 String vals[] = e.getAttributeValues(SMSEntry.ATTR_MODIFY_TIMESTAMP, 779 true); 780 String mTS = null; 781 if (vals != null) { 782 mTS = vals[0]; 783 } 784 return mTS; 785 } 786 787 /** 788 * Returns the organization names to which the service configuration is 789 * being exported. The organization names would be fully qualified starting 790 * with a forward slash "/". To specify an entire sub-tree that can use the 791 * service configuration, a "*" would have to be appended after the final 792 * forward slash. For example "/a/b/c/*" would imply all sub-organization 793 * under "/a/b/c" can use this service configuration. Exporting implies 794 * privileges to read the service configuration data, but not to modify or 795 * delete. 796 * 797 * @return names of organizations to which service configuration 798 * configuration is exported 799 */ 800 public Set getExportedOrganizationNames() { 801 return (null); 802 } 803 804 /** 805 * Sets the organization names that can import the service configuration. 806 * The organization names must be fully qualified, starting with a forward 807 * slash "/". To specify an entire sub-tree that can use the service 808 * configuration, a "*" would have to be appended after the final forward 809 * slash. For example "/a/b/c/*" would imply all sub-organization under 810 * "/a/b/c" can use this service configuration. Exporting implies privileges 811 * to read the service configuration data and not to modify or delete. 812 * 813 * @param names 814 * names of the organizations that can import the service 815 * configuration 816 */ 817 public void setExportedOrganizationNames(Set names) throws SMSException, 818 SSOException { 819 } 820 821 /** 822 * Adds the organization names to the list of organization names that can 823 * import this service configutation. If one does not exist it will be 824 * created. The organization names must be fully qualified, starting with a 825 * forward slash "/". To specify an entire sub-tree that can use the service 826 * configuration, a "*" would have to be appended after the final forward 827 * slash. For example "/a/b/c/*" would imply all sub-organization under 828 * "/a/b/c" can use this service configuration. Exporting implies privileges 829 * to read the service configuration data and not to modify or delete. 830 * 831 * @param names 832 * names of the organizations that can import the service 833 * configuration 834 */ 835 public void addExportedOrganizationNames(Set names) throws SMSException, 836 SSOException { 837 } 838 839 /** 840 * Removes the organization names from the list of organization names that 841 * can import the service configuration. If the organization has already 842 * imported the service configutation, it would have to be undone before the 843 * organization name can be removed from the list. The organization names 844 * must be fully qualified, starting with a forward slash "/". To specify an 845 * entire sub-tree that can use the service configuration, a "*" would have 846 * to be appended after the final forward slash. For example "/a/b/c/*" 847 * would imply all sub-organization under "/a/b/c" can use this service 848 * configuration. 849 * 850 * @param names 851 * names of the organizations that will be removed from the list 852 * of organization names that can import the service 853 * configutation 854 */ 855 public void removeSharedOrganizationNames(Set names) throws SMSException, 856 SSOException { 857 } 858 859 /** 860 * Returns String representation of the <code>ServiceConfig</code> object. 861 * It returns attributes defined and sub configurations. 862 * 863 * @return String representation of the <code>ServiceConfig</code> object. 864 */ 865 public String toString() { 866 StringBuilder sb = new StringBuilder(); 867 // Print the attributes 868 sb.append("Service Component name: " + getComponentName()); 869 sb.append("\n\tAttributes: " + getAttributes()).append("\n"); 870 871 // Try sub-configs 872 try { 873 Iterator subConfigNames = getSubConfigNames().iterator(); 874 while (subConfigNames.hasNext()) { 875 ServiceConfig ssc = getSubConfig((String)subConfigNames.next()); 876 sb.append(ssc); 877 } 878 } catch (Exception e) { 879 sb.append(e.getMessage()); 880 } 881 return (sb.toString()); 882 } 883 884 // Protected methods 885 void saveSMSEntry(SMSEntry e) throws SMSException, SSOException { 886 if (e.isNewEntry()) { 887 // Check if base nodes exists 888 CreateServiceConfig.checkBaseNodesForOrg(token, DNMapper 889 .orgNameToDN(sc.getOrganizationName()), getServiceName(), 890 getVersion()); 891 // Check if parent DN is present 892 String parentDN = DN.valueOf(e.getDN()).parent().toString(); 893 checkAndCreateComponents(parentDN); 894 // Add object classses to this entry 895 e.addAttribute(SMSEntry.ATTR_OBJECTCLASS, SMSEntry.OC_TOP); 896 e.addAttribute(SMSEntry.ATTR_OBJECTCLASS, SMSEntry.OC_SERVICE_COMP); 897 } 898 e.save(token); 899 sc.refresh(e); 900 } 901 902 public void checkAndCreateGroup(String dn, String groupName) 903 throws SMSException, SSOException { 904 905 CachedSMSEntry entry = CachedSMSEntry.getInstance(token, dn); 906 if (entry.isDirty()) { 907 entry.refresh(); 908 } 909 if (entry.isNewEntry()) { 910 // Check if parent exisits 911 String pDN = DN.valueOf(dn).parent().toString(); 912 CachedSMSEntry pEntry = CachedSMSEntry.getInstance(token, pDN); 913 if (pEntry.isDirty()) { 914 pEntry.refresh(); 915 } 916 if (pEntry.isNewEntry()) { 917 checkAndCreateComponents(pDN); 918 } 919 // Create this entry 920 SMSEntry e = entry.getClonedSMSEntry(); 921 e.addAttribute(SMSEntry.ATTR_OBJECTCLASS, SMSEntry.OC_TOP); 922 e.addAttribute(SMSEntry.ATTR_OBJECTCLASS,SMSEntry.OC_SERVICE_COMP); 923 e.addAttribute(SMSEntry.ATTR_SERVICE_ID, groupName); 924 e.save(token); 925 entry.refresh(e); 926 } 927 } 928 929 void checkAndCreateComponents(String dn) throws SMSException, SSOException { 930 CachedSMSEntry entry = CachedSMSEntry.getInstance(token, dn); 931 if (entry.isDirty()) { 932 entry.refresh(); 933 } 934 if (entry.isNewEntry()) { 935 // Check if parent exisits 936 String pDN = DN.valueOf(dn).parent().toString(); 937 CachedSMSEntry pEntry = CachedSMSEntry.getInstance(token, pDN); 938 if (pEntry.isDirty()) { 939 pEntry.refresh(); 940 } 941 if (pEntry.isNewEntry()) { 942 checkAndCreateComponents(pDN); 943 } 944 // Create this entry 945 SMSEntry e = entry.getClonedSMSEntry(); 946 e.addAttribute(SMSEntry.ATTR_OBJECTCLASS, SMSEntry.OC_TOP); 947 e.addAttribute(SMSEntry.ATTR_OBJECTCLASS, SMSEntry.OC_SERVICE_COMP); 948 e.save(token); 949 entry.refresh(e); 950 } 951 } 952 953 private void validate() { 954 try { 955 validateServiceConfigImpl(); 956 } catch (SMSException e) { 957 // Ignore the exception 958 } 959 } 960 961 private void validateServiceConfigImpl() throws SMSException { 962 if (!sc.isValid()) { 963 throw (new SMSException("service-config: " + sc.getDN() + 964 " No longer valid. Cache has been cleared. Recreate from" + 965 "ServiceConfigManager")); 966 } 967 } 968 969 /** 970 * Returns the status of this Service Configuration Object. 971 * Must be used by classes that cache ServiceConfig. 972 * 973 * @return <code>true</code> if this object is still valid. 974 */ 975 public boolean isValid() { 976 return (sc.isValid()); 977 } 978 979 /** 980 * Returns <code>true</code> if the entry exist 981 */ 982 public boolean exists() { 983 return (!sc.isNewEntry()); 984 } 985 986 public String toXML(String NodeTag, AMEncryption encryptObj) 987 throws SMSException, SSOException { 988 validateServiceConfigImpl(); 989 return sc.toXML(token, NodeTag, encryptObj); 990 } 991 992 public String toXML(String NodeTag, AMEncryption encryptObj, String orgName) 993 throws SMSException, SSOException { 994 validateServiceConfigImpl(); 995 return sc.toXML(token, NodeTag, encryptObj, orgName); 996 } 997}