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: ServiceSchemaManager.java,v 1.12 2009/07/25 05:11:55 qcheng Exp $ 026 * 027 * Portions Copyrighted 2012-2015 ForgeRock AS. 028 */ 029package com.sun.identity.sm; 030 031import com.iplanet.services.util.AMEncryption; 032import com.iplanet.sso.SSOException; 033import com.iplanet.sso.SSOToken; 034import com.iplanet.ums.IUMSConstants; 035import com.sun.identity.shared.debug.Debug; 036import com.sun.identity.shared.xml.XMLUtils; 037import java.io.IOException; 038import java.io.InputStream; 039import java.util.Collections; 040import java.util.HashSet; 041import java.util.Iterator; 042import java.util.List; 043import java.util.Set; 044 045import org.forgerock.util.Function; 046import org.w3c.dom.Document; 047import org.w3c.dom.Node; 048 049/** 050 * The class <code>ServiceSchemaManager</code> provides interfaces to manage 051 * the service's schema. It provides access to <code>ServiceSchema</code>, 052 * which represents a single "schema" in the service. 053 * 054 * @supported.api 055 */ 056public class ServiceSchemaManager { 057 058 private SSOToken token; 059 060 private String serviceName; 061 062 private String version; 063 064 private ServiceSchemaManagerImpl ssm; 065 066 private static Debug debug = Debug.getInstance("amSMS"); 067 068 /** 069 * Constructor for service's schema manager to manage the attributes and 070 * sub configurations. Assumes service version number to be <class>1.0 071 * </class>. 072 * 073 * @throws SMSException 074 * if an error occurred while trying to perform the operation 075 * @throws SSOException 076 * if the single sign on token is invalid or expired 077 */ 078 public ServiceSchemaManager(String serviceName, SSOToken token) 079 throws SMSException, SSOException { 080 this(token, serviceName, ServiceManager.isCoexistenceMode() ? 081 ServiceManager.serviceDefaultVersion(token, serviceName) : 082 ServiceManager.getVersion(serviceName)); 083 } 084 085 /** 086 * Creates an instance of 087 * <code>ServiceSchemaManager</code> for the given service and version 088 * pair. It requires an user identity, that will used to perform operations 089 * with. It is assumed that the application calling this constructor should 090 * authenticate the user. 091 * 092 * @param token 093 * single sign on token of the user identity on whose behalf the 094 * operations are performed. 095 * @param serviceName 096 * the name of the service. 097 * @param version 098 * the version of the service. 099 * @throws SMSException 100 * if an error occurred while trying to perform the operation 101 * @throws SSOException 102 * if the single sign on token is invalid or expired 103 * 104 * @supported.api 105 */ 106 public ServiceSchemaManager(SSOToken token, String serviceName, 107 String version) throws SMSException, SSOException { 108 if (token == null || serviceName == null || version == null) { 109 throw new IllegalArgumentException(SMSEntry.bundle 110 .getString(IUMSConstants.SMS_INVALID_PARAMETERS)); 111 } 112 SMSEntry.validateToken(token); 113 this.token = token; 114 this.serviceName = serviceName; 115 this.version = version; 116 ssm = ServiceSchemaManagerImpl.getInstance(token, serviceName, version); 117 } 118 119 /** 120 * Returns the name of the service. 121 * 122 * @return the name of the service 123 * 124 * @supported.api 125 */ 126 public String getName() { 127 return (serviceName); 128 } 129 130 /** 131 * Returns the version of the service. 132 * 133 * @return the version of the service 134 * 135 * @supported.api 136 */ 137 public String getVersion() { 138 return (version); 139 } 140 141 /** 142 * Returns the I18N properties file name for the 143 * service. 144 * 145 * @return the I18N properties file name for the service 146 * 147 * @supported.api 148 */ 149 public String getI18NFileName() { 150 validate(); 151 return (ssm.getI18NFileName()); 152 } 153 154 /** 155 * Sets the I18N properties file name for the service 156 * 157 * @param url 158 * properties file name 159 * @throws SMSException 160 * if an error occurred while trying to perform the operation 161 * @throws SSOException 162 * if the single sign on token is invalid or expired 163 * 164 * @supported.api 165 */ 166 public void setI18NFileName(String url) throws SMSException, SSOException { 167 SMSEntry.validateToken(token); 168 validateServiceSchemaManagerImpl(); 169 String tmpS = ssm.getI18NFileName(); 170 ssm.setI18NFileName(url); 171 try { 172 replaceSchema(ssm.getDocument()); 173 } catch (SMSException se) { 174 ssm.setI18NFileName(tmpS); 175 throw se; 176 } 177 } 178 179 /** 180 * Returns the URL of the JAR file that contains the 181 * I18N properties file. The method could return null, in which case the 182 * properties file should be in <code>CLASSPATH</code>. 183 * 184 * @return the URL of the JAR file containing the <code>I18N</code> 185 * properties file. 186 * 187 * @supported.api 188 */ 189 public String getI18NJarURL() { 190 validate(); 191 return (ssm.getI18NJarURL()); 192 } 193 194 /** 195 * Sets the URL of the JAR file that contains the I18N 196 * properties 197 * 198 * @param url 199 * URL 200 * @throws SMSException 201 * if an error occurred while trying to perform the operation 202 * @throws SSOException 203 * if the single sign on token is invalid or expired 204 * 205 * @supported.api 206 */ 207 208 public void setI18NJarURL(String url) throws SMSException, SSOException { 209 SMSEntry.validateToken(token); 210 validateServiceSchemaManagerImpl(); 211 String tmpS = ssm.getI18NJarURL(); 212 ssm.setI18NJarURL(url); 213 try { 214 replaceSchema(ssm.getDocument()); 215 } catch (SMSException se) { 216 ssm.setI18NJarURL(tmpS); 217 throw se; 218 } 219 } 220 221 /** 222 * Returns the service's hierarchy. 223 * 224 * @return service hierarchy in slash format. 225 * 226 * @supported.api 227 */ 228 public String getServiceHierarchy() { 229 validate(); 230 return (ssm.getServiceHierarchy()); 231 } 232 233 /** 234 * Sets the service's hierarchy 235 * 236 * @param newhierarchy 237 * service hierarchy 238 * @throws SMSException 239 * if an error occurred while trying to perform the operation 240 * @throws SSOException 241 * if the single sign on token is invalid or expired 242 * 243 * @supported.api 244 */ 245 public void setServiceHierarchy(String newhierarchy) throws SMSException, 246 SSOException { 247 SMSEntry.validateToken(token); 248 validateServiceSchemaManagerImpl(); 249 String tmpS = getServiceHierarchy(); 250 ssm.setServiceHierarchy(newhierarchy); 251 try { 252 replaceSchema(ssm.getDocument()); 253 } catch (SMSException e) { 254 ssm.setServiceHierarchy(tmpS); 255 throw e; 256 } 257 } 258 259 /** 260 * Returns i18nKey of the schema. 261 * 262 * @return i18nKey of the schema. 263 * 264 * @supported.api 265 */ 266 public String getI18NKey() { 267 validate(); 268 return (ssm.getI18NKey()); 269 } 270 271 /** 272 * Sets the i18nKey of the schema. 273 * 274 * @param i18nKey 275 * <code>i18nKey</code> of the schema. 276 * @throws SMSException 277 * if an error occurred while trying to perform the operation. 278 * @throws SSOException 279 * if the single sign on token is invalid or expired. 280 * 281 * @supported.api 282 */ 283 public void setI18NKey(String i18nKey) throws SMSException, SSOException { 284 SMSEntry.validateToken(token); 285 validateServiceSchemaManagerImpl(); 286 String tmp = ssm.getI18NKey(); 287 ssm.setI18NKey(i18nKey); 288 289 try { 290 replaceSchema(ssm.getDocument()); 291 } catch (SMSException e) { 292 ssm.setI18NKey(tmp); 293 throw e; 294 } 295 } 296 297 /** 298 * Returns URL of the view bean for the service 299 * 300 * @return URL for view bean 301 * 302 * @supported.api 303 */ 304 public String getPropertiesViewBeanURL() { 305 validate(); 306 return (ssm.getPropertiesViewBeanURL()); 307 } 308 309 /** 310 * Sets the URL of the view bean for the service. 311 * 312 * @param url 313 * of the view bean for the service. 314 * @throws SMSException 315 * if an error occurred while trying to perform the operation. 316 * @throws SSOException 317 * if the single sign on token is invalid or expired. 318 * 319 * @supported.api 320 */ 321 public void setPropertiesViewBeanURL(String url) throws SMSException, 322 SSOException { 323 SMSEntry.validateToken(token); 324 validateServiceSchemaManagerImpl(); 325 String tmpS = ssm.getPropertiesViewBeanURL(); 326 ssm.setPropertiesViewBeanURL(url); 327 try { 328 replaceSchema(ssm.getDocument()); 329 } catch (SMSException e) { 330 ssm.setPropertiesViewBeanURL(tmpS); 331 throw e; 332 } 333 } 334 335 /** 336 * Returns the service's resource name for CREST representation, or the 337 * service name if a resource name is not defined. 338 * @supported.api 339 */ 340 public String getResourceName() { 341 validate(); 342 String resourceName = ssm.getResourceName(); 343 return resourceName == null ? getName() : resourceName; 344 } 345 346 /** 347 * Sets the service's resource name for CREST representation. 348 * 349 * @param name 350 * resource name for CREST representation 351 * @throws SMSException 352 * if an error occurred while trying to perform the operation 353 * @throws SSOException 354 * if the single sign on token is invalid or expired 355 * 356 * @supported.api 357 */ 358 public void setResourceName(String name) throws SMSException, 359 SSOException { 360 SMSEntry.validateToken(token); 361 validateServiceSchemaManagerImpl(); 362 String tmpS = getResourceName(); 363 ssm.setResourceName(name); 364 try { 365 replaceSchema(ssm.getDocument()); 366 } catch (SMSException e) { 367 ssm.setResourceName(tmpS); 368 throw e; 369 } 370 } 371 372 /** 373 * iPlanet_PUBLIC-METHOD Returns the revision number of the service schema. 374 * 375 * @return the revision number of the service schema 376 */ 377 public int getRevisionNumber() { 378 validate(); 379 return (ssm.getRevisionNumber()); 380 } 381 382 /** 383 * iPlanet_PUBLIC-METHOD Sets the revision number for the service schema. 384 * 385 * @param revisionNumber 386 * revision number of the service schema. 387 * @throws SMSException 388 * if there is a problem setting the value in the data store. 389 * @throws SSOException 390 * If the user has an invalid SSO token. 391 */ 392 public void setRevisionNumber(int revisionNumber) throws SMSException, 393 SSOException { 394 SMSEntry.validateToken(token); 395 validateServiceSchemaManagerImpl(); 396 int tmpS = ssm.getRevisionNumber(); 397 ssm.setRevisionNumber(revisionNumber); 398 try { 399 replaceSchema(ssm.getDocument()); 400 } catch (SMSException e) { 401 ssm.setRevisionNumber(tmpS); 402 throw (e); 403 } 404 } 405 406 /** 407 * Returns the schema types available with this 408 * service. 409 * 410 * @return set of <code>SchemaTypes</code> in this service. 411 * @throws SMSException 412 * if an error occurred while trying to perform the operation 413 * 414 * @supported.api 415 */ 416 public Set getSchemaTypes() throws SMSException { 417 SMSEntry.validateToken(token); 418 validate(); 419 return (ssm.getSchemaTypes()); 420 } 421 422 /** 423 * Returns the configuration schema for the given 424 * schema type 425 * 426 * @param type 427 * schema type. 428 * @return service schema. 429 * @throws SMSException 430 * if an error occurred while trying to perform the operation 431 * 432 * @supported.api 433 */ 434 public ServiceSchema getSchema(String type) throws SMSException { 435 validate(); 436 SchemaType t = null; 437 if (type.equalsIgnoreCase("role") 438 || type.equalsIgnoreCase("filteredrole") 439 || type.equalsIgnoreCase("realm")) { 440 t = SchemaType.DYNAMIC; 441 } else if (type.equalsIgnoreCase("user")) { 442 t = SchemaType.USER; 443 } else { 444 t = new SchemaType(type); 445 } 446 return (getSchema(t)); 447 } 448 449 /** 450 * Returns the configuration schema for the given 451 * schema type 452 * 453 * @param type 454 * schema type. 455 * @return service schema. 456 * @throws SMSException 457 * if an error occurred while trying to perform the operation 458 * 459 * @supported.api 460 */ 461 public ServiceSchema getSchema(SchemaType type) throws SMSException { 462 SMSEntry.validateToken(token); 463 validate(); 464 ServiceSchemaImpl ss = ssm.getSchema(type); 465 if ((ss == null) && type.equals(SchemaType.USER)) { 466 type = SchemaType.DYNAMIC; 467 ss = ssm.getSchema(type); 468 } 469 if (ss != null) { 470 return (new ServiceSchema(ss, "", type, this)); 471 } 472 return (null); 473 } 474 475 /** 476 * Returns the organization creation configuration schema if present; else 477 * returns <code>null</code> 478 * 479 * @return service schema. 480 * @throws SMSException 481 * if an error occurred while trying to perform the operation 482 */ 483 public ServiceSchema getOrganizationCreationSchema() throws SMSException { 484 SMSEntry.validateToken(token); 485 validate(); 486 ServiceSchemaImpl ss = ssm.getSchema(SchemaType.ORGANIZATION); 487 if (ss != null) { 488 ServiceSchemaImpl ssi = ss.getOrgAttrSchema(); 489 if (ssi != null) { 490 return (new ServiceSchema(ssi, "", SchemaType.ORGANIZATION, 491 this, true)); 492 } 493 } 494 return (null); 495 } 496 497 /** 498 * Returns the attribute schemas for the given schema 499 * type excluding status and service identifier attributes. 500 * 501 * @param type 502 * schema type. 503 * @return service schema. 504 * @throws SMSException 505 * if an error occurred while trying to perform the operation 506 * 507 * @supported.api 508 */ 509 public Set getServiceAttributeNames(SchemaType type) throws SMSException { 510 SMSEntry.validateToken(token); 511 validate(); 512 ServiceSchema ss = getSchema(type); 513 return (ss.getServiceAttributeNames()); 514 } 515 516 /** 517 * Returns the global service configuration schema. 518 * 519 * @return the global service configuration schema 520 * @throws SMSException 521 * if an error occurred while trying to perform the operation 522 * 523 * @supported.api 524 */ 525 public ServiceSchema getGlobalSchema() throws SMSException { 526 return (getSchema(SchemaType.GLOBAL)); 527 } 528 529 /** 530 * Returns the organization service configuration 531 * schema. 532 * 533 * @return the organization service configuration schema 534 * @throws SMSException 535 * if an error occurred while trying to perform the operation 536 * 537 * @supported.api 538 */ 539 public ServiceSchema getOrganizationSchema() throws SMSException { 540 return (getSchema(SchemaType.ORGANIZATION)); 541 } 542 543 /** 544 * Returns the dynamic service configuration schema. 545 * 546 * @return the dynamic service configuration schema 547 * @throws SMSException 548 * if an error occurred while trying to perform the operation 549 * 550 * @supported.api 551 */ 552 public ServiceSchema getDynamicSchema() throws SMSException { 553 return (getSchema(SchemaType.DYNAMIC)); 554 } 555 556 /** 557 * Returns the user service configuration schema. 558 * 559 * @return the user service configuration schema 560 * @throws SMSException 561 * if an error occurred while trying to perform the operation 562 * 563 * @supported.api 564 */ 565 public ServiceSchema getUserSchema() throws SMSException { 566 return (getSchema(SchemaType.USER)); 567 } 568 569 /** 570 * Returns the policy service configuration schema. 571 * 572 * @return the policy service configuration schema 573 * @throws SMSException 574 * if an error occurred while trying to perform the operation 575 * 576 * @supported.api 577 */ 578 public ServiceSchema getPolicySchema() throws SMSException { 579 return (getSchema(SchemaType.POLICY)); 580 } 581 582 /** 583 * Returns the service schema in XML for this service. 584 * 585 * @return the service schema in XML for this service 586 * @throws SMSException 587 * if an error occurred while trying to perform the operation 588 * 589 * @supported.api 590 */ 591 public InputStream getSchema() throws SMSException { 592 SMSEntry.validateToken(token); 593 validate(); 594 return (ssm.getSchema()); 595 } 596 597 /** 598 * Replaces the existing service schema with the given 599 * schema defined by the XML input stream that follows the SMS DTD. 600 * 601 * @param xmlServiceSchema 602 * the XML format of the service schema 603 * @throws SMSException 604 * if an error occurred while trying to perform the operation 605 * @throws SSOException 606 * if the single sign on token is invalid or expired 607 * @throws IOException 608 * if an error occurred with the <code> InputStream </code> 609 * 610 * @supported.api 611 */ 612 public void replaceSchema(InputStream xmlServiceSchema) 613 throws SSOException, SMSException, IOException { 614 SMSEntry.validateToken(token); 615 validateServiceSchemaManagerImpl(); 616 CachedSMSEntry smsEntry = ssm.getCachedSMSEntry(); 617 smsEntry.writeXMLSchema(token, xmlServiceSchema); 618 } 619 620 // @Override 621 public int hashCode() { 622 int hash = 7; 623 hash = 67 * hash + (serviceName != null ? serviceName.hashCode() : 0); 624 hash = 67 * hash + (version != null ? version.hashCode() : 0); 625 return hash; 626 } 627 628 /** 629 * Returns true if the given object equals this 630 * object. 631 * 632 * @param o 633 * object for comparison. 634 * @return true if the given object equals this object. 635 * 636 * @supported.api 637 */ 638 public boolean equals(Object o) { 639 if (o instanceof ServiceSchemaManager) { 640 ServiceSchemaManager ossm = (ServiceSchemaManager) o; 641 if (serviceName.equals(ossm.serviceName) 642 && version.equals(ossm.version)) { 643 return (true); 644 } 645 } 646 return (false); 647 } 648 649 /** 650 * Returns the string representation of the Service 651 * Schema. 652 * 653 * @return the string representation of the Service Schema. 654 * 655 * @supported.api 656 */ 657 public String toString() { 658 validate(); 659 return (ssm.toString()); 660 } 661 662 /** 663 * Registers for changes to service's schema. The 664 * object will be called when schema for this service and version is 665 * changed. 666 * 667 * @param listener 668 * callback object that will be invoked when schema changes. 669 * @return an ID of the registered listener. 670 * 671 * @supported.api 672 */ 673 public String addListener(ServiceListener listener) { 674 validate(); 675 return (ssm.addListener(listener)); 676 } 677 678 /** 679 * Removes the listener from the service for the given 680 * listener ID. The ID was issued when the listener was registered. 681 * 682 * @param listenerID 683 * the listener ID issued when the listener was registered 684 * 685 * @supported.api 686 */ 687 public void removeListener(String listenerID) { 688 if (ssm !=null ) { 689 ssm.removeListener(listenerID); 690 } 691 } 692 693 /** 694 * Returns the last modified time stamp of this service schema. This method 695 * is expensive because it does not cache the modified time stamp but goes 696 * directly to the data store to obtain the value of this entry 697 * 698 * @return The last modified time stamp as a string with the format of 699 * <code>yyyyMMddhhmmss</code> 700 * @throws SMSException if there is an error trying to read from the 701 * datastore. 702 * @throws SSOException if the single sign-on token of the user is invalid. 703 */ 704 public String getLastModifiedTime() throws SMSException, SSOException { 705 validateServiceSchemaManagerImpl(); 706 CachedSMSEntry ce = ssm.getCachedSMSEntry(); 707 if (ce.isDirty()) { 708 ce.refresh(); 709 } 710 SMSEntry e = ce.getSMSEntry(); 711 String vals[] = e.getAttributeValues(SMSEntry.ATTR_MODIFY_TIMESTAMP, 712 true); 713 String mTS = null; 714 if (vals != null) { 715 mTS = vals[0]; 716 } 717 return mTS; 718 } 719 720 // ================= Plugin Interface Methods ======== 721 722 /** 723 * Returns the names of the plugin interfaces used by the service 724 * 725 * @return service's plugin interface names 726 */ 727 public Set getPluginInterfaceNames() { 728 validate(); 729 return (ssm.getPluginInterfaceNames()); 730 } 731 732 /** 733 * Returns the <code>PluginInterface</code> object of the service for the 734 * specified plugin interface name 735 * 736 * @param pluginInterfaceName 737 * name of the plugin interface 738 * @return plugin interface configured for the service; else 739 * <code>null</code> 740 */ 741 public PluginInterface getPluginInterface(String pluginInterfaceName) { 742 validate(); 743 return (ssm.getPluginInterface(pluginInterfaceName)); 744 } 745 746 /** 747 * Adds a new plugin interface objct to service's schema. 748 * 749 * @param interfaceName 750 * name for the plugin interface 751 * @param interfaceClass 752 * fully qualified interface class name 753 * @param i18nKey 754 * I18N key that will by used by UI to get messages to display 755 * the interface name 756 */ 757 public void addPluginInterface(String interfaceName, String interfaceClass, 758 String i18nKey) throws SMSException, SSOException { 759 SMSEntry.validateToken(token); 760 validateServiceSchemaManagerImpl(); 761 if ((interfaceName == null) || (interfaceClass == null)) { 762 throw (new IllegalArgumentException()); 763 } 764 StringBuilder sb = new StringBuilder(100); 765 sb.append("<").append(SMSUtils.PLUGIN_INTERFACE).append(" ").append( 766 SMSUtils.NAME).append("=\"").append(interfaceName) 767 .append("\" ").append(SMSUtils.PLUGIN_INTERFACE_CLASS).append( 768 "=\"").append(interfaceClass).append("\""); 769 if (i18nKey != null) { 770 sb.append(" ").append(SMSUtils.I18N_KEY).append("=\"").append( 771 i18nKey).append("\""); 772 } 773 sb.append("></").append(SMSUtils.PLUGIN_INTERFACE).append(">"); 774 // Construct XML document 775 Document pluginDoc = SMSSchema.getXMLDocument(sb.toString(), false); 776 Node node = XMLUtils.getRootNode(pluginDoc, SMSUtils.PLUGIN_INTERFACE); 777 778 // Added to XML document and write it 779 Document schemaDoc = ssm.getDocumentCopy(); 780 Node pluginNode = schemaDoc.importNode(node, true); 781 Node schemaNode = XMLUtils.getRootNode(schemaDoc, SMSUtils.SCHEMA); 782 schemaNode.appendChild(pluginNode); 783 replaceSchema(schemaDoc); 784 } 785 786 /** 787 * Removes the plugin interface object from the service schema. 788 * 789 * @param interfacename Name of the plugin class. 790 */ 791 public void removePluginInterface(String interfacename) 792 throws SMSException, SSOException { 793 SMSEntry.validateToken(token); 794 validateServiceSchemaManagerImpl(); 795 Document schemaDoc = ssm.getDocumentCopy(); 796 Node schemaNode = XMLUtils.getRootNode(schemaDoc, SMSUtils.SCHEMA); 797 // Get the plugin interface node 798 Node pluginNode = XMLUtils.getNamedChildNode(schemaNode, 799 SMSUtils.PLUGIN_INTERFACE, SMSUtils.NAME, interfacename); 800 if (pluginNode != null) { 801 schemaNode.removeChild(pluginNode); 802 replaceSchema(schemaDoc); 803 } 804 } 805 806 // ----------------------------------------------------------- 807 // Plugin Schema 808 // ----------------------------------------------------------- 809 /** 810 * Returns the names of plugins configured for the plugin interface. If 811 * organization is <code>null</code>, returns the plugins configured for 812 * the "root" organization. 813 */ 814 public Set getPluginSchemaNames(String interfaceName, String orgName) 815 throws SMSException { 816 SMSEntry.validateToken(token); 817 validate(); 818 // Construct the DN to get CachedSubEntries 819 StringBuilder sb = new StringBuilder(100); 820 sb.append("ou=").append(interfaceName).append(",").append( 821 CreateServiceConfig.PLUGIN_CONFIG_NODE).append("ou=").append( 822 version).append(",").append("ou=").append(serviceName).append( 823 ",").append(SMSEntry.SERVICES_RDN).append(",").append( 824 DNMapper.orgNameToDN(orgName)); 825 CachedSubEntries cse = CachedSubEntries.getInstance(token, sb 826 .toString()); 827 try { 828 return (cse.getSubEntries(token)); 829 } catch (SSOException s) { 830 debug.error("ServiceSchemaManager: Unable to get " 831 + "Plugin Schema Names", s); 832 } 833 return (Collections.EMPTY_SET); 834 } 835 836 /** 837 * Returns the PluginSchema object given the schema name and the interface 838 * name for the specified organization. If organization is 839 * <code>null</code>, returns the PluginSchema for the "root" organization. 840 */ 841 public PluginSchema getPluginSchema(String pluginSchemaName, 842 String interfaceName, String orgName) throws SMSException { 843 SMSEntry.validateToken(token); 844 validate(); 845 return (new PluginSchema(token, serviceName, version, pluginSchemaName, 846 interfaceName, orgName)); 847 } 848 849 /** 850 * Returns true if admin token cached within this class is valid 851 * 852 * @return true is admin token is valid 853 */ 854 public boolean isSSOTokenValid() { 855 try { 856 SMSEntry.validateToken(token); 857 return true; 858 } catch (SMSException smse) { 859 debug.warning("ServiceSchemaManager: token is not valid.", smse); 860 } 861 return false; 862 } 863 864 // ----------------------------------------------------------- 865 // Internal protected method 866 // ----------------------------------------------------------- 867 SSOToken getSSOToken() { 868 return (token); 869 } 870 871 protected Document getDocumentCopy() throws SMSException { 872 validate(); 873 return (ssm.getDocumentCopy()); 874 } 875 876 protected synchronized void replaceSchema(Document document) 877 throws SSOException, SMSException { 878 validate(); 879 CachedSMSEntry smsEntry = ssm.getCachedSMSEntry(); 880 SMSSchema smsSchema = new SMSSchema(document); 881 smsEntry.writeXMLSchema(token, smsSchema.getSchema()); 882 } 883 884 public <E extends Exception> void modifySchema(Function<Document, Boolean, E> modifier) throws E, SMSException, SSOException { 885 Document schema = getDocumentCopy(); 886 if (modifier.apply(schema)) { 887 replaceSchema(schema); 888 } 889 } 890 891 private void validate() { 892 try { 893 validateServiceSchemaManagerImpl(); 894 } catch (SSOException e) { 895 // Since method signatures cannot be changed, a runtime 896 // exception is thrown. This conditions would happen only 897 // when SSOToken has become invalid or service has been 898 // removed. 899 debug.error("ServiceSchemaManager:validate failed for SN: " + 900 serviceName, e); 901 throw (new RuntimeException(e.getMessage())); 902 } catch (SMSException e) { 903 // Ignore the exception 904 } 905 } 906 907 private void validateServiceSchemaManagerImpl() 908 throws SMSException, SSOException { 909 if (ssm == null || !ssm.isValid()) { 910 // Recreate the SSM 911 ssm = ServiceSchemaManagerImpl.getInstance(token, 912 serviceName, version); 913 } 914 } 915 916 // ----------------------------------------------------------- 917 // Static method to create a new service schema 918 // ----------------------------------------------------------- 919 static void createService(SSOToken token, SMSSchema smsSchema) 920 throws SMSException, SSOException { 921 // Service node 922 SMSEntry smsEntry = new SMSEntry(token, ServiceManager 923 .getServiceNameDN(smsSchema.getServiceName())); 924 925 if (smsEntry.isNewEntry()) { 926 // create this entry 927 smsEntry.addAttribute(SMSEntry.ATTR_OBJECTCLASS, SMSEntry.OC_TOP); 928 smsEntry.addAttribute(SMSEntry.ATTR_OBJECTCLASS, 929 SMSEntry.OC_SERVICE); 930 smsEntry.save(); 931 } 932 // Version node 933 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 934 ServiceManager.getServiceNameDN(smsSchema.getServiceName(), 935 smsSchema.getServiceVersion())); 936 if (cEntry.isDirty()) { 937 cEntry.refresh(); 938 } 939 smsEntry = cEntry.getSMSEntry(); 940 String[] schema = new String[1]; 941 if ((smsEntry.getAttributeValues(SMSEntry.ATTR_SCHEMA) == null) 942 || ((smsEntry.getAttributeValues(SMSEntry.ATTR_SCHEMA))[0] 943 .equalsIgnoreCase(SMSSchema.getDummyXML(smsSchema 944 .getServiceName(), smsSchema 945 .getServiceVersion())))) { 946 schema[0] = smsSchema.getSchema(); 947 smsEntry.setAttribute(SMSEntry.ATTR_SCHEMA, schema); 948 } else { 949 // Throw service already exists exception 950 Object[] args = { smsSchema.getServiceName(), 951 smsSchema.getServiceVersion() }; 952 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 953 IUMSConstants.SMS_service_already_exists, args)); 954 } 955 if (smsEntry.isNewEntry()) { 956 // add object classes 957 smsEntry.addAttribute(SMSEntry.ATTR_OBJECTCLASS, SMSEntry.OC_TOP); 958 smsEntry.addAttribute(SMSEntry.ATTR_OBJECTCLASS, 959 SMSEntry.OC_SERVICE); 960 } 961 smsEntry.save(token); 962 cEntry.refresh(smsEntry); 963 } 964 965 public String toXML(AMEncryption encryptObj) 966 throws SMSException { 967 validate(); 968 String xml = ssm.toXML(encryptObj); 969 int idx = xml.lastIndexOf("</" + SMSUtils.SERVICE + ">"); 970 StringBuffer buff = new StringBuffer(); 971 buff.append(xml.substring(0, idx)); 972 973 Set realms = new HashSet(); 974 realms.add("/"); 975 976 for (Iterator i = getPluginInterfaceNames().iterator(); i.hasNext(); ) { 977 String iName = (String)i.next(); 978 getPlugSchemaXML(buff, iName, realms); 979 } 980 981 buff.append("</" + SMSUtils.SERVICE + ">"); 982 return buff.toString(); 983 } 984 985 private void getPlugSchemaXML( 986 StringBuffer buff, 987 String interfaceName, 988 Set realms 989 ) throws SMSException { 990 for (Iterator i = realms.iterator(); i.hasNext(); ){ 991 String realm = (String)i.next(); 992 Set schemaNames = getPluginSchemaNames(interfaceName, realm); 993 for (Iterator j = schemaNames.iterator(); j.hasNext();) { 994 String pName = (String)j.next(); 995 PluginSchema pSchema = getPluginSchema( 996 pName, interfaceName, realm); 997 buff.append(pSchema.toXML()); 998 } 999 } 1000 } 1001}