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 */ 028 029/* 030 * Portions Copyrighted 2012 ForgeRock Inc 031 */ 032package com.sun.identity.sm; 033 034import com.iplanet.services.util.AMEncryption; 035import com.iplanet.sso.SSOException; 036import com.iplanet.sso.SSOToken; 037import com.iplanet.ums.IUMSConstants; 038import com.sun.identity.shared.debug.Debug; 039import com.sun.identity.shared.xml.XMLUtils; 040import java.io.IOException; 041import java.io.InputStream; 042import java.util.Collections; 043import java.util.HashSet; 044import java.util.Iterator; 045import java.util.Set; 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 * iPlanet_PUBLIC-METHOD Returns the revision number of the service schema. 337 * 338 * @return the revision number of the service schema 339 */ 340 public int getRevisionNumber() { 341 validate(); 342 return (ssm.getRevisionNumber()); 343 } 344 345 /** 346 * iPlanet_PUBLIC-METHOD Sets the revision number for the service schema. 347 * 348 * @param revisionNumber 349 * revision number of the service schema. 350 * @throws SMSException 351 * if there is a problem setting the value in the data store. 352 * @throws SSOException 353 * If the user has an invalid SSO token. 354 */ 355 public void setRevisionNumber(int revisionNumber) throws SMSException, 356 SSOException { 357 SMSEntry.validateToken(token); 358 validateServiceSchemaManagerImpl(); 359 int tmpS = ssm.getRevisionNumber(); 360 ssm.setRevisionNumber(revisionNumber); 361 try { 362 replaceSchema(ssm.getDocument()); 363 } catch (SMSException e) { 364 ssm.setRevisionNumber(tmpS); 365 throw (e); 366 } 367 } 368 369 /** 370 * Returns the schema types available with this 371 * service. 372 * 373 * @return set of <code>SchemaTypes</code> in this service. 374 * @throws SMSException 375 * if an error occurred while trying to perform the operation 376 * 377 * @supported.api 378 */ 379 public Set getSchemaTypes() throws SMSException { 380 SMSEntry.validateToken(token); 381 validate(); 382 return (ssm.getSchemaTypes()); 383 } 384 385 /** 386 * Returns the configuration schema for the given 387 * schema type 388 * 389 * @param type 390 * schema type. 391 * @return service schema. 392 * @throws SMSException 393 * if an error occurred while trying to perform the operation 394 * 395 * @supported.api 396 */ 397 public ServiceSchema getSchema(String type) throws SMSException { 398 validate(); 399 SchemaType t = null; 400 if (type.equalsIgnoreCase("role") 401 || type.equalsIgnoreCase("filteredrole") 402 || type.equalsIgnoreCase("realm")) { 403 t = SchemaType.DYNAMIC; 404 } else if (type.equalsIgnoreCase("user")) { 405 t = SchemaType.USER; 406 } else { 407 t = new SchemaType(type); 408 } 409 return (getSchema(t)); 410 } 411 412 /** 413 * Returns the configuration schema for the given 414 * schema type 415 * 416 * @param type 417 * schema type. 418 * @return service schema. 419 * @throws SMSException 420 * if an error occurred while trying to perform the operation 421 * 422 * @supported.api 423 */ 424 public ServiceSchema getSchema(SchemaType type) throws SMSException { 425 SMSEntry.validateToken(token); 426 validate(); 427 ServiceSchemaImpl ss = ssm.getSchema(type); 428 if ((ss == null) && type.equals(SchemaType.USER)) { 429 type = SchemaType.DYNAMIC; 430 ss = ssm.getSchema(type); 431 } 432 if (ss != null) { 433 return (new ServiceSchema(ss, "", type, this)); 434 } 435 return (null); 436 } 437 438 /** 439 * Returns the organization creation configuration schema if present; else 440 * returns <code>null</code> 441 * 442 * @return service schema. 443 * @throws SMSException 444 * if an error occurred while trying to perform the operation 445 */ 446 public ServiceSchema getOrganizationCreationSchema() throws SMSException { 447 SMSEntry.validateToken(token); 448 validate(); 449 ServiceSchemaImpl ss = ssm.getSchema(SchemaType.ORGANIZATION); 450 if (ss != null) { 451 ServiceSchemaImpl ssi = ss.getOrgAttrSchema(); 452 if (ssi != null) { 453 return (new ServiceSchema(ssi, "", SchemaType.ORGANIZATION, 454 this, true)); 455 } 456 } 457 return (null); 458 } 459 460 /** 461 * Returns the attribute schemas for the given schema 462 * type excluding status and service identifier attributes. 463 * 464 * @param type 465 * schema type. 466 * @return service schema. 467 * @throws SMSException 468 * if an error occurred while trying to perform the operation 469 * 470 * @supported.api 471 */ 472 public Set getServiceAttributeNames(SchemaType type) throws SMSException { 473 SMSEntry.validateToken(token); 474 validate(); 475 ServiceSchema ss = getSchema(type); 476 return (ss.getServiceAttributeNames()); 477 } 478 479 /** 480 * Returns the global service configuration schema. 481 * 482 * @return the global service configuration schema 483 * @throws SMSException 484 * if an error occurred while trying to perform the operation 485 * 486 * @supported.api 487 */ 488 public ServiceSchema getGlobalSchema() throws SMSException { 489 return (getSchema(SchemaType.GLOBAL)); 490 } 491 492 /** 493 * Returns the organization service configuration 494 * schema. 495 * 496 * @return the organization service configuration schema 497 * @throws SMSException 498 * if an error occurred while trying to perform the operation 499 * 500 * @supported.api 501 */ 502 public ServiceSchema getOrganizationSchema() throws SMSException { 503 return (getSchema(SchemaType.ORGANIZATION)); 504 } 505 506 /** 507 * Returns the dynamic service configuration schema. 508 * 509 * @return the dynamic service configuration schema 510 * @throws SMSException 511 * if an error occurred while trying to perform the operation 512 * 513 * @supported.api 514 */ 515 public ServiceSchema getDynamicSchema() throws SMSException { 516 return (getSchema(SchemaType.DYNAMIC)); 517 } 518 519 /** 520 * Returns the user service configuration schema. 521 * 522 * @return the user service configuration schema 523 * @throws SMSException 524 * if an error occurred while trying to perform the operation 525 * 526 * @supported.api 527 */ 528 public ServiceSchema getUserSchema() throws SMSException { 529 return (getSchema(SchemaType.USER)); 530 } 531 532 /** 533 * Returns the policy service configuration schema. 534 * 535 * @return the policy service configuration schema 536 * @throws SMSException 537 * if an error occurred while trying to perform the operation 538 * 539 * @supported.api 540 */ 541 public ServiceSchema getPolicySchema() throws SMSException { 542 return (getSchema(SchemaType.POLICY)); 543 } 544 545 /** 546 * Returns the service schema in XML for this service. 547 * 548 * @return the service schema in XML for this service 549 * @throws SMSException 550 * if an error occurred while trying to perform the operation 551 * 552 * @supported.api 553 */ 554 public InputStream getSchema() throws SMSException { 555 SMSEntry.validateToken(token); 556 validate(); 557 return (ssm.getSchema()); 558 } 559 560 /** 561 * Replaces the existing service schema with the given 562 * schema defined by the XML input stream that follows the SMS DTD. 563 * 564 * @param xmlServiceSchema 565 * the XML format of the service schema 566 * @throws SMSException 567 * if an error occurred while trying to perform the operation 568 * @throws SSOException 569 * if the single sign on token is invalid or expired 570 * @throws IOException 571 * if an error occurred with the <code> InputStream </code> 572 * 573 * @supported.api 574 */ 575 public void replaceSchema(InputStream xmlServiceSchema) 576 throws SSOException, SMSException, IOException { 577 SMSEntry.validateToken(token); 578 validateServiceSchemaManagerImpl(); 579 CachedSMSEntry smsEntry = ssm.getCachedSMSEntry(); 580 smsEntry.writeXMLSchema(token, xmlServiceSchema); 581 } 582 583 // @Override 584 public int hashCode() { 585 int hash = 7; 586 hash = 67 * hash + (serviceName != null ? serviceName.hashCode() : 0); 587 hash = 67 * hash + (version != null ? version.hashCode() : 0); 588 return hash; 589 } 590 591 /** 592 * Returns true if the given object equals this 593 * object. 594 * 595 * @param o 596 * object for comparison. 597 * @return true if the given object equals this object. 598 * 599 * @supported.api 600 */ 601 public boolean equals(Object o) { 602 if (o instanceof ServiceSchemaManager) { 603 ServiceSchemaManager ossm = (ServiceSchemaManager) o; 604 if (serviceName.equals(ossm.serviceName) 605 && version.equals(ossm.version)) { 606 return (true); 607 } 608 } 609 return (false); 610 } 611 612 /** 613 * Returns the string representation of the Service 614 * Schema. 615 * 616 * @return the string representation of the Service Schema. 617 * 618 * @supported.api 619 */ 620 public String toString() { 621 validate(); 622 return (ssm.toString()); 623 } 624 625 /** 626 * Registers for changes to service's schema. The 627 * object will be called when schema for this service and version is 628 * changed. 629 * 630 * @param listener 631 * callback object that will be invoked when schema changes. 632 * @return an ID of the registered listener. 633 * 634 * @supported.api 635 */ 636 public String addListener(ServiceListener listener) { 637 validate(); 638 return (ssm.addListener(listener)); 639 } 640 641 /** 642 * Removes the listener from the service for the given 643 * listener ID. The ID was issued when the listener was registered. 644 * 645 * @param listenerID 646 * the listener ID issued when the listener was registered 647 * 648 * @supported.api 649 */ 650 public void removeListener(String listenerID) { 651 if (ssm !=null ) { 652 ssm.removeListener(listenerID); 653 } 654 } 655 656 /** 657 * Returns the last modified time stamp of this service schema. This method 658 * is expensive because it does not cache the modified time stamp but goes 659 * directly to the data store to obtain the value of this entry 660 * 661 * @return The last modified time stamp as a string with the format of 662 * <code>yyyyMMddhhmmss</code> 663 * @throws SMSException if there is an error trying to read from the 664 * datastore. 665 * @throws SSOException if the single sign-on token of the user is invalid. 666 */ 667 public String getLastModifiedTime() throws SMSException, SSOException { 668 validateServiceSchemaManagerImpl(); 669 CachedSMSEntry ce = ssm.getCachedSMSEntry(); 670 if (ce.isDirty()) { 671 ce.refresh(); 672 } 673 SMSEntry e = ce.getSMSEntry(); 674 String vals[] = e.getAttributeValues(SMSEntry.ATTR_MODIFY_TIMESTAMP, 675 true); 676 String mTS = null; 677 if (vals != null) { 678 mTS = vals[0]; 679 } 680 return mTS; 681 } 682 683 // ================= Plugin Interface Methods ======== 684 685 /** 686 * Returns the names of the plugin interfaces used by the service 687 * 688 * @return service's plugin interface names 689 */ 690 public Set getPluginInterfaceNames() { 691 validate(); 692 return (ssm.getPluginInterfaceNames()); 693 } 694 695 /** 696 * Returns the <code>PluginInterface</code> object of the service for the 697 * specified plugin interface name 698 * 699 * @param pluginInterfaceName 700 * name of the plugin interface 701 * @return plugin interface configured for the service; else 702 * <code>null</code> 703 */ 704 public PluginInterface getPluginInterface(String pluginInterfaceName) { 705 validate(); 706 return (ssm.getPluginInterface(pluginInterfaceName)); 707 } 708 709 /** 710 * Adds a new plugin interface objct to service's schema. 711 * 712 * @param interfaceName 713 * name for the plugin interface 714 * @param interfaceClass 715 * fully qualified interface class name 716 * @param i18nKey 717 * I18N key that will by used by UI to get messages to display 718 * the interface name 719 */ 720 public void addPluginInterface(String interfaceName, String interfaceClass, 721 String i18nKey) throws SMSException, SSOException { 722 SMSEntry.validateToken(token); 723 validateServiceSchemaManagerImpl(); 724 if ((interfaceName == null) || (interfaceClass == null)) { 725 throw (new IllegalArgumentException()); 726 } 727 StringBuilder sb = new StringBuilder(100); 728 sb.append("<").append(SMSUtils.PLUGIN_INTERFACE).append(" ").append( 729 SMSUtils.NAME).append("=\"").append(interfaceName) 730 .append("\" ").append(SMSUtils.PLUGIN_INTERFACE_CLASS).append( 731 "=\"").append(interfaceClass).append("\""); 732 if (i18nKey != null) { 733 sb.append(" ").append(SMSUtils.I18N_KEY).append("=\"").append( 734 i18nKey).append("\""); 735 } 736 sb.append("></").append(SMSUtils.PLUGIN_INTERFACE).append(">"); 737 // Construct XML document 738 Document pluginDoc = SMSSchema.getXMLDocument(sb.toString(), false); 739 Node node = XMLUtils.getRootNode(pluginDoc, SMSUtils.PLUGIN_INTERFACE); 740 741 // Added to XML document and write it 742 Document schemaDoc = ssm.getDocumentCopy(); 743 Node pluginNode = schemaDoc.importNode(node, true); 744 Node schemaNode = XMLUtils.getRootNode(schemaDoc, SMSUtils.SCHEMA); 745 schemaNode.appendChild(pluginNode); 746 replaceSchema(schemaDoc); 747 } 748 749 /** 750 * Removes the plugin interface object from the service schema. 751 * 752 * @param interfacename Name of the plugin class. 753 */ 754 public void removePluginInterface(String interfacename) 755 throws SMSException, SSOException { 756 SMSEntry.validateToken(token); 757 validateServiceSchemaManagerImpl(); 758 Document schemaDoc = ssm.getDocumentCopy(); 759 Node schemaNode = XMLUtils.getRootNode(schemaDoc, SMSUtils.SCHEMA); 760 // Get the plugin interface node 761 Node pluginNode = XMLUtils.getNamedChildNode(schemaNode, 762 SMSUtils.PLUGIN_INTERFACE, SMSUtils.NAME, interfacename); 763 if (pluginNode != null) { 764 schemaNode.removeChild(pluginNode); 765 replaceSchema(schemaDoc); 766 } 767 } 768 769 // ----------------------------------------------------------- 770 // Plugin Schema 771 // ----------------------------------------------------------- 772 /** 773 * Returns the names of plugins configured for the plugin interface. If 774 * organization is <code>null</code>, returns the plugins configured for 775 * the "root" organization. 776 */ 777 public Set getPluginSchemaNames(String interfaceName, String orgName) 778 throws SMSException { 779 SMSEntry.validateToken(token); 780 validate(); 781 // Construct the DN to get CachedSubEntries 782 StringBuilder sb = new StringBuilder(100); 783 sb.append("ou=").append(interfaceName).append(",").append( 784 CreateServiceConfig.PLUGIN_CONFIG_NODE).append("ou=").append( 785 version).append(",").append("ou=").append(serviceName).append( 786 ",").append(SMSEntry.SERVICES_RDN).append(",").append( 787 DNMapper.orgNameToDN(orgName)); 788 CachedSubEntries cse = CachedSubEntries.getInstance(token, sb 789 .toString()); 790 try { 791 return (cse.getSubEntries(token)); 792 } catch (SSOException s) { 793 debug.error("ServiceSchemaManager: Unable to get " 794 + "Plugin Schema Names", s); 795 } 796 return (Collections.EMPTY_SET); 797 } 798 799 /** 800 * Returns the PluginSchema object given the schema name and the interface 801 * name for the specified organization. If organization is 802 * <code>null</code>, returns the PluginSchema for the "root" organization. 803 */ 804 public PluginSchema getPluginSchema(String pluginSchemaName, 805 String interfaceName, String orgName) throws SMSException { 806 SMSEntry.validateToken(token); 807 validate(); 808 return (new PluginSchema(token, serviceName, version, pluginSchemaName, 809 interfaceName, orgName)); 810 } 811 812 // ----------------------------------------------------------- 813 // Internal protected method 814 // ----------------------------------------------------------- 815 SSOToken getSSOToken() { 816 return (token); 817 } 818 819 protected Document getDocumentCopy() throws SMSException { 820 validate(); 821 return (ssm.getDocumentCopy()); 822 } 823 824 protected synchronized void replaceSchema(Document document) 825 throws SSOException, SMSException { 826 validate(); 827 CachedSMSEntry smsEntry = ssm.getCachedSMSEntry(); 828 SMSSchema smsSchema = new SMSSchema(document); 829 smsEntry.writeXMLSchema(token, smsSchema.getSchema()); 830 } 831 832 private void validate() { 833 try { 834 validateServiceSchemaManagerImpl(); 835 } catch (SSOException e) { 836 // Since method signatures cannot be changed, a runtime 837 // exception is thrown. This conditions would happen only 838 // when SSOToken has become invalid or service has been 839 // removed. 840 debug.error("ServiceSchemaManager:validate failed for SN: " + 841 serviceName, e); 842 throw (new RuntimeException(e.getMessage())); 843 } catch (SMSException e) { 844 // Ignore the exception 845 } 846 } 847 848 private void validateServiceSchemaManagerImpl() 849 throws SMSException, SSOException { 850 if (ssm == null || !ssm.isValid()) { 851 // Recreate the SSM 852 ssm = ServiceSchemaManagerImpl.getInstance(token, 853 serviceName, version); 854 } 855 } 856 857 // ----------------------------------------------------------- 858 // Static method to create a new service schema 859 // ----------------------------------------------------------- 860 static void createService(SSOToken token, SMSSchema smsSchema) 861 throws SMSException, SSOException { 862 // Service node 863 SMSEntry smsEntry = new SMSEntry(token, ServiceManager 864 .getServiceNameDN(smsSchema.getServiceName())); 865 866 if (smsEntry.isNewEntry()) { 867 // create this entry 868 smsEntry.addAttribute(SMSEntry.ATTR_OBJECTCLASS, SMSEntry.OC_TOP); 869 smsEntry.addAttribute(SMSEntry.ATTR_OBJECTCLASS, 870 SMSEntry.OC_SERVICE); 871 smsEntry.save(); 872 } 873 // Version node 874 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 875 ServiceManager.getServiceNameDN(smsSchema.getServiceName(), 876 smsSchema.getServiceVersion())); 877 if (cEntry.isDirty()) { 878 cEntry.refresh(); 879 } 880 smsEntry = cEntry.getSMSEntry(); 881 String[] schema = new String[1]; 882 if ((smsEntry.getAttributeValues(SMSEntry.ATTR_SCHEMA) == null) 883 || ((smsEntry.getAttributeValues(SMSEntry.ATTR_SCHEMA))[0] 884 .equalsIgnoreCase(SMSSchema.getDummyXML(smsSchema 885 .getServiceName(), smsSchema 886 .getServiceVersion())))) { 887 schema[0] = smsSchema.getSchema(); 888 smsEntry.setAttribute(SMSEntry.ATTR_SCHEMA, schema); 889 } else { 890 // Throw service already exists exception 891 Object[] args = { smsSchema.getServiceName(), 892 smsSchema.getServiceVersion() }; 893 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 894 IUMSConstants.SMS_service_already_exists, args)); 895 } 896 if (smsEntry.isNewEntry()) { 897 // add object classes 898 smsEntry.addAttribute(SMSEntry.ATTR_OBJECTCLASS, SMSEntry.OC_TOP); 899 smsEntry.addAttribute(SMSEntry.ATTR_OBJECTCLASS, 900 SMSEntry.OC_SERVICE); 901 } 902 smsEntry.save(token); 903 cEntry.refresh(smsEntry); 904 } 905 906 public String toXML(AMEncryption encryptObj) 907 throws SMSException { 908 validate(); 909 String xml = ssm.toXML(encryptObj); 910 int idx = xml.lastIndexOf("</" + SMSUtils.SERVICE + ">"); 911 StringBuffer buff = new StringBuffer(); 912 buff.append(xml.substring(0, idx)); 913 914 Set realms = new HashSet(); 915 realms.add("/"); 916 917 for (Iterator i = getPluginInterfaceNames().iterator(); i.hasNext(); ) { 918 String iName = (String)i.next(); 919 getPlugSchemaXML(buff, iName, realms); 920 } 921 922 buff.append("</" + SMSUtils.SERVICE + ">"); 923 return buff.toString(); 924 } 925 926 private void getPlugSchemaXML( 927 StringBuffer buff, 928 String interfaceName, 929 Set realms 930 ) throws SMSException { 931 for (Iterator i = realms.iterator(); i.hasNext(); ){ 932 String realm = (String)i.next(); 933 Set schemaNames = getPluginSchemaNames(interfaceName, realm); 934 for (Iterator j = schemaNames.iterator(); j.hasNext();) { 935 String pName = (String)j.next(); 936 PluginSchema pSchema = getPluginSchema( 937 pName, interfaceName, realm); 938 buff.append(pSchema.toXML()); 939 } 940 } 941 } 942}