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: ServiceManager.java,v 1.27 2009/10/28 04:24:26 hengming Exp $ 026 * 027 * Portions Copyrighted 2012-2015 ForgeRock AS. 028 */ 029 030package com.sun.identity.sm; 031 032import com.iplanet.services.util.AMEncryption; 033import com.iplanet.sso.SSOException; 034import com.iplanet.sso.SSOToken; 035import com.iplanet.sso.SSOTokenManager; 036import com.iplanet.ums.IUMSConstants; 037import com.sun.identity.authentication.util.ISAuthConstants; 038import com.sun.identity.common.CaseInsensitiveHashMap; 039import com.sun.identity.common.configuration.ServerConfiguration; 040import com.sun.identity.idm.IdConstants; 041import com.sun.identity.shared.debug.Debug; 042import com.sun.identity.shared.xml.XMLUtils; 043import com.sun.identity.security.AdminTokenAction; 044import com.sun.identity.security.DecodeAction; 045import com.sun.identity.security.EncodeAction; 046import java.io.InputStream; 047import java.io.UnsupportedEncodingException; 048import java.security.AccessController; 049import java.text.MessageFormat; 050import java.util.ArrayList; 051import java.util.Collections; 052import java.util.HashMap; 053import java.util.HashSet; 054import java.util.Iterator; 055import java.util.List; 056import java.util.Map; 057import java.util.Set; 058import org.w3c.dom.Document; 059import org.w3c.dom.DocumentType; 060import org.w3c.dom.Node; 061import org.w3c.dom.NodeList; 062 063/** 064 * The <code>ServiceManager</code> class provides methods to register/remove 065 * services and to list currently registered services. It also provides methods 066 * to obtain an instance of <code>ServiceSchemaManager</code> and an instance 067 * of <code>ServiceConfigManager</code>. 068 * 069 * @supported.api 070 */ 071public class ServiceManager { 072 073 // Initialization parameters 074 private static boolean initialized; 075 076 private static boolean loadedAuthServices; 077 078 protected static final String serviceDN = SMSEntry.SERVICES_RDN 079 + "," + SMSEntry.baseDN; 080 081 // For realms and co-existance support 082 protected static final String COEXISTENCE_ATTR_NAME = "coexistenceMode"; 083 084 protected static HashMap serviceNameDefaultVersion = 085 new CaseInsensitiveHashMap(); 086 087 protected static final String REALM_ATTR_NAME = "realmMode"; 088 089 public static final String REALM_SERVICE = 090 "sunidentityrepositoryservice"; 091 092 protected static final String DEFAULT_SERVICES_FOR_REALMS = 093 "serviceNamesForAutoAssignment"; 094 095 protected static final String SERVICE_VERSION = "1.0"; 096 097 protected static final String REALM_ENTRY = "ou=" + SERVICE_VERSION 098 + ",ou=" + REALM_SERVICE + "," + serviceDN; 099 100 public static final String PLATFORM_SERVICE = "iPlanetAMPlatformService"; 101 102 protected static final String ATTR_SERVER_LIST = 103 "iplanet-am-platform-server-list"; 104 105 private static boolean realmCache; 106 107 private static boolean coexistenceCache = true; 108 109 private static boolean ditUpgradedCache; 110 111 protected static Set requiredServices; 112 113 protected static Set defaultServicesToLoad; 114 115 // constants for IdRepo management 116 private static final String SERVICE_OC_ATTR_NAME = "serviceObjectClasses"; 117 118 private static final String ALL_SERVICES = "null"; 119 120 private static Map serviceNameAndOCs = new CaseInsensitiveHashMap(); 121 122 // List of sub-services 123 protected static SMSEntry smsEntry; 124 125 protected static CachedSubEntries serviceNames; 126 127 protected static HashMap serviceVersions = new CaseInsensitiveHashMap(); 128 129 protected static Set accessManagerServers; 130 131 // SSOToken of the caller 132 private SSOToken token; 133 134 private CachedSubEntries subEntries = null; 135 136 // Debug & I18n 137 private static Debug debug = SMSEntry.debug; 138 139 private static boolean amsdkChecked; 140 141 private static boolean isAMSDKEnabled; 142 143 /** 144 * Creates an instance of <code>ServiceManager</code>. 145 * The <code>SSOToken</code> is used to identify the user performing 146 * service operations. 147 * 148 * @param token 149 * the authenticated single sign on token. 150 * @throws SSOException 151 * if the user's single sign on token is invalid or expired 152 * @throws SMSException 153 * if an error occurred while performing the operation 154 * 155 * @supported.api 156 */ 157 public ServiceManager(SSOToken token) throws SSOException, SMSException { 158 // Initilaize the static variables and caches 159 initialize(token); 160 161 // Validate SSOToken 162 SSOTokenManager.getInstance().validateToken(token); 163 this.token = token; 164 } 165 166 /** 167 * Returns the <code>ServiceSchemaManager</code> for 168 * the given service name and version. 169 * 170 * @param serviceName 171 * the name of the service 172 * @param version 173 * the version of the service 174 * @return the <code>ServiceSchemaManager</code> for the given service 175 * name and version 176 * @throws SSOException 177 * if the user's single sign on token is invalid or expired 178 * @throws SMSException 179 * if an error occurred while performing the operation 180 * 181 * @supported.api 182 */ 183 public ServiceSchemaManager getSchemaManager(String serviceName, 184 String version) throws SMSException, SSOException { 185 return (new ServiceSchemaManager(token, serviceName, version)); 186 } 187 188 /** 189 * Returns the <code>ServiceConfigManager</code> for 190 * the given service name and version. 191 * 192 * @param serviceName 193 * the name of the service 194 * @param version 195 * the version of the service 196 * @return the <code>ServiceConfigManager</code> for the given service 197 * name and version. 198 * @throws SSOException 199 * if the user's single sign on token is invalid or expired 200 * @throws SMSException 201 * if an error occurred while performing the operation 202 * 203 * @supported.api 204 */ 205 public ServiceConfigManager getConfigManager(String serviceName, 206 String version) throws SMSException, SSOException { 207 return (new ServiceConfigManager(token, serviceName, version)); 208 } 209 210 /** 211 * Returns the <code>OrganizationConfigManager</code> for the given 212 * organization name. If the <code>orgName</code> either <code> 213 * null</code> 214 * or empty or "/", the organization configuration for the root organization 215 * will be returned. 216 * 217 * @param orgName 218 * the name of the organization 219 * @return the <code>OrganizationConfigManager</code> for the given 220 * organization name 221 * 222 * @throws SSOException 223 * if the user's single sign on token is invalid or expired 224 * @throws SMSException 225 * if an error occurred while performing the operation 226 */ 227 public OrganizationConfigManager getOrganizationConfigManager( 228 String orgName) throws SMSException, SSOException { 229 return (new OrganizationConfigManager(token, orgName)); 230 } 231 232 /** 233 * Returns all the service names that have been 234 * registered. 235 * 236 * @return the set of names of services that have been registered 237 * @throws SMSException 238 * if an error occurred while performing the operation 239 * 240 * @supported.api 241 */ 242 public Set getServiceNames() throws SMSException { 243 try { 244 if (serviceNames == null) { 245 serviceNames = CachedSubEntries.getInstance(token, serviceDN); 246 } 247 return (serviceNames.getSubEntries(token)); 248 } catch (SSOException s) { 249 debug.error("ServiceManager: Unable to get service names", s); 250 throw (new SMSException(s, "sms-service-not-found")); 251 } 252 } 253 254 /** 255 * Returns a map of service names and the related object classes for the 256 * given <code>schemaType</code>. 257 * 258 * @param schemaType 259 * name of the schema 260 * @return Map of service names and objectclasses 261 */ 262 public Map getServiceNamesAndOCs(String schemaType) { 263 if (schemaType == null) { 264 schemaType = ALL_SERVICES; 265 } else if (schemaType.equalsIgnoreCase("realm")) { 266 schemaType = "filteredrole"; 267 } 268 Map answer = (Map) serviceNameAndOCs.get(schemaType); 269 if (answer == null) { 270 try { 271 answer = new HashMap(); 272 Set sNames = getServiceNames(); 273 if (sNames != null && !sNames.isEmpty()) { 274 Iterator it = sNames.iterator(); 275 while (it.hasNext()) { 276 try { 277 String service = (String) it.next(); 278 ServiceSchemaManagerImpl ssm; 279 if (isCoexistenceMode()) { 280 // For backward compatibility, get the 281 // version from the service. 282 // no hardcoding to '1.0', even if it 283 // improves performance in OpenAM. 284 // Otherwise, it breaks for services like 285 // iplanetAMProviderConfigService with 286 // '1.1' as version. 287 ssm = ServiceSchemaManagerImpl.getInstance( 288 token, service, serviceDefaultVersion( 289 token, service)); 290 } else { 291 ssm = ServiceSchemaManagerImpl.getInstance( 292 token, service, 293 ServiceManager.getVersion(service)); 294 } 295 if (ssm != null) { 296 // Check if service has schemaType 297 if (schemaType != null && 298 ssm.getSchema(new SchemaType( 299 schemaType)) == null) { 300 // If the schema type is "User" 301 // check for "Dynamic" also 302 if (schemaType.equalsIgnoreCase( 303 SMSUtils.USER_SCHEMA) 304 && ssm.getSchema(SchemaType.DYNAMIC) 305 == null) 306 { 307 continue; 308 } 309 // If the schema type is "Role: 310 // check for "Dynamic" also 311 if (schemaType.toLowerCase() 312 .indexOf("role") != -1 313 && ssm.getSchema(SchemaType.DYNAMIC) 314 == null) 315 { 316 continue; 317 } 318 } 319 ServiceSchemaImpl ss = ssm 320 .getSchema(SchemaType.GLOBAL); 321 if (ss != null) { 322 Map attrs = ss.getAttributeDefaults(); 323 if (attrs.containsKey(SERVICE_OC_ATTR_NAME)) 324 { 325 answer.put(service, attrs 326 .get(SERVICE_OC_ATTR_NAME)); 327 } 328 } 329 } 330 } catch (SMSException smse) { 331 // continue with next service. Best effort to get 332 // all service names. 333 if (debug.messageEnabled()) { 334 debug.message( 335 "ServiceManager.getServiceNamesandOCs" 336 + " caught SMSException ", smse); 337 } 338 } 339 } 340 } 341 serviceNameAndOCs.put(schemaType, answer); 342 } catch (SMSException smse) { 343 // ignore 344 if (debug.messageEnabled()) { 345 debug.message("ServiceManager.getServiceNamesandOCs" 346 + " caught SMSException ", smse); 347 } 348 } catch (SSOException ssoe) { 349 // ignore 350 if (debug.messageEnabled()) { 351 debug.message("ServiceManager.getServiceNamesandOCs" 352 + " caught SSOException ", ssoe); 353 } 354 } 355 } 356 return (SMSUtils.copyAttributes(answer)); 357 } 358 359 /** 360 * Returns all versions supported by the service. 361 * 362 * @param serviceName 363 * service name. 364 * @return the set of versions supported by the service 365 * @throws SMSException 366 * if an error occurred while performing the operation 367 * 368 * @supported.api 369 */ 370 public Set getServiceVersions(String serviceName) throws SMSException { 371 try { 372 return (getVersions(token, serviceName)); 373 } catch (SSOException s) { 374 debug.error("ServiceManager: Unable to get service versions", s); 375 throw (new SMSException(s, "sms-version-not-found")); 376 } 377 } 378 379 /** 380 * Registers one or more services, defined by the XML 381 * input stream that follows the SMS DTD. 382 * 383 * @param xmlServiceSchema 384 * the input stream of service metadata in XML conforming to SMS 385 * DTD. 386 * @return set of registered service names. 387 * @throws SMSException if an error occurred while performing the operation. 388 * @throws SSOException if the user's single sign on token is invalid or 389 * expired. 390 * 391 * @supported.api 392 */ 393 public Set registerServices(InputStream xmlServiceSchema) 394 throws SMSException, SSOException { 395 return registerServices(xmlServiceSchema, null); 396 } 397 398 /** 399 * Registers one or more services, defined by the XML 400 * input stream that follows the SMS DTD. 401 * 402 * @param xmlServiceSchema 403 * the input stream of service metadata in XML conforming to SMS 404 * DTD. 405 * @param decryptObj Object to decrypt the password in the XML. 406 * @return set of registered service names. 407 * @throws SMSException if an error occurred while performing the operation 408 * @throws SSOException if the user's single sign on token is invalid or 409 * expired. 410 */ 411 public Set registerServices( 412 InputStream xmlServiceSchema, 413 AMEncryption decryptObj 414 ) throws SMSException, SSOException { 415 // Validate SSO Token 416 SMSEntry.validateToken(token); 417 Set sNames = new HashSet(); 418 List serviceNodes = new ArrayList(); 419 // Get the XML document and get the list of service nodes 420 Document doc = SMSSchema.getXMLDocument(xmlServiceSchema); 421 422 if (!validSMSDtdDocType(doc)) { 423 throw new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 424 IUMSConstants.SMS_xml_invalid_doc_type, null); 425 } 426 427 // Before validating service schema, we need to check 428 // for AttributeSchema having the syntax of "password" 429 // and if present, encrypt the DefaultValues if any 430 checkAndEncryptPasswordSyntax(doc, true, decryptObj); 431 432 // Create service schema 433 NodeList nodes = doc.getElementsByTagName(SMSUtils.SERVICE); 434 for (int i = 0; (nodes != null) && (i < nodes.getLength()); i++) { 435 Node serviceNode = nodes.item(i); 436 String name = XMLUtils.getNodeAttributeValue(serviceNode, 437 SMSUtils.NAME); 438 String version = XMLUtils.getNodeAttributeValue(serviceNode, 439 SMSUtils.VERSION); 440 441 // Obtain the SMSSchema for Schema and PluginSchema 442 SMSSchema smsSchema = new SMSSchema(name, version, doc); 443 444 // Check if the schema element exists 445 if (XMLUtils.getChildNode(serviceNode, SMSUtils.SCHEMA) != null) { 446 validateServiceSchema(serviceNode); 447 ServiceSchemaManager.createService(token, smsSchema); 448 449 // Update the service name and version cached SMSEntry 450 if (serviceNames == null) { 451 serviceNames = CachedSubEntries.getInstance(token, 452 serviceDN); 453 } 454 serviceNames.add(name); 455 CachedSubEntries sVersions = (CachedSubEntries) serviceVersions 456 .get(name); 457 if (sVersions == null) { 458 // Not present, hence create it and add it 459 sVersions = CachedSubEntries.getInstance(token, 460 getServiceNameDN(name)); 461 serviceVersions.put(name, sVersions); 462 } 463 sVersions.add(version); 464 sNames.add(name); 465 } 466 467 // Check if PluginSchema nodes exists 468 for (Iterator pluginNodes = XMLUtils.getChildNodes(serviceNode, 469 SMSUtils.PLUGIN_SCHEMA).iterator(); pluginNodes.hasNext();) 470 { 471 Node pluginNode = (Node) pluginNodes.next(); 472 PluginSchema.createPluginSchema(token, pluginNode, smsSchema); 473 } 474 475 if (XMLUtils.getChildNode(serviceNode, SMSUtils.CONFIGURATION) 476 != null) { 477 serviceNodes.add(serviceNode); 478 } 479 } 480 481 if (serviceNodes.size() > 0) { 482 clearCache(); 483 } 484 /* 485 * Need to do this after all the schema has been loaded 486 */ 487 for (Iterator i = serviceNodes.iterator(); i.hasNext(); ) { 488 Node svcNode = (Node)i.next(); 489 String name = XMLUtils.getNodeAttributeValue(svcNode, 490 SMSUtils.NAME); 491 String version = XMLUtils.getNodeAttributeValue(svcNode, 492 SMSUtils.VERSION); 493 Node configNode = XMLUtils.getChildNode(svcNode, 494 SMSUtils.CONFIGURATION); 495 /* 496 * Store the configuration, will throw exception if 497 * the service configuration already exists 498 */ 499 CreateServiceConfig.createService(this, name, version, 500 configNode, true, decryptObj); 501 } 502 return sNames; 503 } 504 505 public Document parseServicesFile(InputStream xmlServiceSchema) 506 throws SMSException, SSOException { 507 return parseServicesFile(xmlServiceSchema, null); 508 } 509 510 public Document parseServicesFile( 511 InputStream xmlServiceSchema, 512 AMEncryption decryptObj 513 ) throws SMSException, SSOException { 514 // Validate SSO Token 515 SMSEntry.validateToken(token); 516 //Set<SMSSchema> smsSchemas = new HashSet<SMSSchema>(); 517 Map<String, SMSSchema> smsSchemas = new HashMap<String, SMSSchema>(); 518 List serviceNodes = new ArrayList(); 519 // Get the XML document and get the list of service nodes 520 Document doc = SMSSchema.getXMLDocument(xmlServiceSchema); 521 522 return doc; 523 } 524 525 /* 526 if (!validSMSDtdDocType(doc)) { 527 throw new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 528 IUMSConstants.SMS_xml_invalid_doc_type, null); 529 } 530 531 // Before validating service schema, we need to check 532 // for AttributeSchema having the syntax of "password" 533 // and if present, encrypt the DefaultValues if any 534 checkAndEncryptPasswordSyntax(doc, true, decryptObj); 535 536 // Create service schema 537 NodeList nodes = doc.getElementsByTagName(SMSUtils.SERVICE); 538 for (int i = 0; (nodes != null) && (i < nodes.getLength()); i++) { 539 Node serviceNode = nodes.item(i); 540 String name = XMLUtils.getNodeAttributeValue(serviceNode, 541 SMSUtils.NAME); 542 String version = XMLUtils.getNodeAttributeValue(serviceNode, 543 SMSUtils.VERSION); 544 545 // Obtain the SMSSchema for Schema and PluginSchema 546 SMSSchema smsSchema = new SMSSchema(name, version, doc); 547 smsSchemas.put(name, smsSchema); 548 549 } 550 551 // Check if the schema element exists 552 /*if (XMLUtils.getChildNode(serviceNode, SMSUtils.SCHEMA) != null) { 553 validateServiceSchema(serviceNode); 554 ServiceSchemaManager.createService(token, smsSchema); 555 556 // Update the service name and version cached SMSEntry 557 if (serviceNames == null) { 558 serviceNames = CachedSubEntries.getInstance(token, 559 serviceDN); 560 } 561 serviceNames.add(name); 562 CachedSubEntries sVersions = (CachedSubEntries) serviceVersions 563 .get(name); 564 if (sVersions == null) { 565 // Not present, hence create it and add it 566 sVersions = CachedSubEntries.getInstance(token, 567 getServiceNameDN(name)); 568 serviceVersions.put(name, sVersions); 569 } 570 sVersions.add(version); 571 sNames.add(name); 572 } 573 574 // Check if PluginSchema nodes exists 575 for (Iterator pluginNodes = XMLUtils.getChildNodes(serviceNode, 576 SMSUtils.PLUGIN_SCHEMA).iterator(); pluginNodes.hasNext();) 577 { 578 Node pluginNode = (Node) pluginNodes.next(); 579 PluginSchema.createPluginSchema(token, pluginNode, smsSchema); 580 } 581 582 if (XMLUtils.getChildNode(serviceNode, SMSUtils.CONFIGURATION) 583 != null) { 584 serviceNodes.add(serviceNode); 585 } 586 587 } 588 589 if (serviceNodes.size() > 0) { 590 clearCache(); 591 } 592 /* 593 * Need to do this after all the schema has been loaded 594 */ 595 /* 596 for (Iterator i = serviceNodes.iterator(); i.hasNext(); ) { 597 Node svcNode = (Node)i.next(); 598 String name = XMLUtils.getNodeAttributeValue(svcNode, 599 SMSUtils.NAME); 600 String version = XMLUtils.getNodeAttributeValue(svcNode, 601 SMSUtils.VERSION); 602 Node configNode = XMLUtils.getChildNode(svcNode, 603 SMSUtils.CONFIGURATION); 604 /* 605 * Store the configuration, will throw exception if 606 * the service configuration already exists 607 */ 608 /* 609 CreateServiceConfig.createService(this, name, version, 610 configNode, true, decryptObj); 611 } 612 return sNames; 613 return smsSchemas; 614 }*/ 615 616 private boolean validSMSDtdDocType(Document doc) { 617 boolean valid = false; 618 DocumentType docType = doc.getDoctype(); 619 620 if (docType != null) { 621 String dtdPath = docType.getSystemId(); 622 if (dtdPath != null) { 623 int idx = dtdPath.lastIndexOf('/'); 624 if (idx != -1) { 625 dtdPath = dtdPath.substring(idx + 1); 626 } 627 valid = dtdPath.equals("sms.dtd"); 628 } 629 } 630 631 return valid; 632 } 633 634 /** 635 * Adds a new plugin schema to an existing service 636 * 637 * @param pluginDoc 638 * @throws SMSException if an error occurred while performing the operation 639 * @throws SSOException if the user's single sign on token is invalid or 640 * expired. 641 */ 642 public void addPluginSchema(Document pluginDoc) 643 throws SMSException, SSOException { 644 // Validate SSO Token 645 SMSEntry.validateToken(token); 646 647 Node serviceNode = XMLUtils.getRootNode(pluginDoc, SMSUtils.SERVICE); 648 String serviceName = XMLUtils.getNodeAttributeValue(serviceNode, 649 SMSUtils.NAME); 650 ServiceSchemaManager ssm = new ServiceSchemaManager(serviceName, token); 651 Document schemaDoc = ssm.getDocumentCopy(); 652 653 Node pluginSchemaDoc = XMLUtils.getRootNode(pluginDoc, SMSUtils.PLUGIN_SCHEMA); 654 655 // Obtain the SMSSchema for Schema and PluginSchema 656 SMSSchema smsSchema = new SMSSchema(schemaDoc); 657 PluginSchema.createPluginSchema(token, pluginSchemaDoc, smsSchema); 658 } 659 660 /** 661 * Removes a plugin schema from a service 662 * 663 * @param serviceName The name of the service 664 * @param interfaceName The name of the plugin interface 665 * @param pluginName The name of the plugin schema 666 * @throws SMSException if an error occurred while performing the operation 667 * @throws SSOException if the user's single sign on token is invalid or 668 * expired. 669 */ 670 public void removePluginSchema(String serviceName, 671 String interfaceName, 672 String pluginName) 673 throws SMSException, SSOException { 674 ServiceSchemaManager ssm = new ServiceSchemaManager(serviceName, token); 675 String version = ssm.getVersion(); 676 677 // Check if PluginSchema nodes exists 678 Set pluginSchemaNames = ssm.getPluginSchemaNames(interfaceName, null); 679 680 // if they match, delete 681 if (pluginSchemaNames.contains(pluginName)) { 682 StringBuilder sb = new StringBuilder(100); 683 684 // Construct the DN and get CachedSMSEntry 685 sb.append("ou=").append(pluginName).append(",").append("ou=").append( 686 interfaceName).append(",").append( 687 CreateServiceConfig.PLUGIN_CONFIG_NODE).append("ou=").append( 688 version).append(",").append("ou=").append(serviceName).append( 689 ",").append(SMSEntry.SERVICES_RDN).append(","); 690 691 CachedSMSEntry ce; 692 693 try { 694 ce = CachedSMSEntry.getInstance(token, sb.toString() 695 + SMSEntry.baseDN); 696 SMSEntry smsEntry = ce.getClonedSMSEntry(); 697 smsEntry.forceDelete(token); 698 ce.refresh(smsEntry); 699 } catch (SSOException ssoe) { 700 throw (new SMSException(ssoe, "sms-INVALID_SSO_TOKEN")); 701 } 702 } else { 703 throw new SMSException("Condition does not exist"); 704 } 705 706 if (debug.messageEnabled()) { 707 debug.message("removePluginSchema: remove plugin " + pluginName + 708 "from service " + serviceName); 709 } 710 } 711 712 /** 713 * Removes the service schema and configuration for 714 * the given service name. 715 * 716 * @param serviceName 717 * the name of the service 718 * @param version 719 * the version of the service 720 * @throws SMSException 721 * if an error occurred while performing the operation 722 * @throws SSOException 723 * if the user's single sign on token is invalid or expired 724 * 725 * @supported.api 726 */ 727 public void removeService(String serviceName, String version) 728 throws SMSException, SSOException { 729 // Find all service entries that have the DN 730 // Search for (&(ou=<serviceName>)(objectclass=top)) 731 // construct the rdn with the given version, look for the entry 732 // in iDS and if entry exists(service with that version), delete. 733 if (serviceName.equalsIgnoreCase(IdConstants.REPO_SERVICE) || 734 serviceName.equalsIgnoreCase(ISAuthConstants.AUTH_SERVICE_NAME)) { 735 Object args[] = { serviceName }; 736 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 737 "sms-SERVICE_CORE_CANNOT_DELETE", args)); 738 } 739 SMSEntry.validateToken(token); 740 String[] objs = { serviceName }; 741 Iterator results = SMSEntry.search(token, SMSEntry.baseDN, 742 MessageFormat.format(SMSEntry.FILTER_PATTERN, (Object[])objs), 743 0, 0, false, false).iterator(); 744 while (results.hasNext()) { 745 String dn = (String) results.next(); 746 String configdn = SMSEntry.PLACEHOLDER_RDN + SMSEntry.EQUALS 747 + version + SMSEntry.COMMA + dn; 748 CachedSMSEntry configsmse = CachedSMSEntry.getInstance(token, 749 configdn); 750 if (configsmse.isDirty()) { 751 configsmse.refresh(); 752 } 753 SMSEntry confige = configsmse.getClonedSMSEntry(); 754 if (!confige.isNewEntry()) { 755 confige.delete(token); 756 configsmse.refresh(confige); 757 } 758 // If there are no other service version nodes for that service, 759 // delete that node(schema). 760 CachedSMSEntry smse = CachedSMSEntry.getInstance(token, dn); 761 if (smse.isDirty()) { 762 smse.refresh(); 763 } 764 SMSEntry e = smse.getSMSEntry(); 765 Iterator versions = 766 e.subEntries(token, "*", 0, false, false).iterator(); 767 if (!versions.hasNext()) { 768 e.delete(token); 769 smse.refresh(e); 770 } 771 } 772 } 773 774 /** 775 * Deletes only the schema for the given service name. This is provided only 776 * for backward compatibility for DSAME 5.0 and will be deprecated in the 777 * future release. Alternative is to use 778 * <code>ServiceSchemaManager.replaceSchema()</code>. 779 * 780 * @param serviceName 781 * Name of service to be deleted. 782 * @throws SMSException 783 * if an error occurred while performing the operation 784 * @throws SSOException 785 * if the user's single sign on token is invalid or expired 786 */ 787 public void deleteService(String serviceName) throws SMSException, 788 SSOException { 789 if (serviceName.equalsIgnoreCase(IdConstants.REPO_SERVICE) || 790 serviceName.equalsIgnoreCase(ISAuthConstants.AUTH_SERVICE_NAME)) { 791 Object args[] = { serviceName }; 792 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 793 "sms-SERVICE_CORE_CANNOT_DELETE", args)); 794 } 795 796 Iterator versions = getServiceVersions(serviceName).iterator(); 797 while (versions.hasNext()) { 798 String version = (String) versions.next(); 799 CachedSMSEntry ce = CachedSMSEntry.getInstance(token, 800 getServiceNameDN(serviceName, version)); 801 if (ce.isDirty()) { 802 ce.refresh(); 803 } 804 SMSEntry e = ce.getClonedSMSEntry(); 805 String[] values = { SMSSchema.getDummyXML(serviceName, version) }; 806 e.setAttribute(SMSEntry.ATTR_SCHEMA, values); 807 e.save(token); 808 ce.refresh(e); 809 } 810 } 811 812 /** 813 * Returns the base DN (or root DN) that was set in 814 * <code>serverconfig.xml</code> at install time. 815 */ 816 public static String getBaseDN() { 817 return (SMSEntry.baseDN); 818 } 819 820 /** 821 * Returns the DN beneath the {@link #getBaseDN()} in which service data is stored. 822 */ 823 public static String getServiceDN() { 824 return serviceDN; 825 } 826 827 /** 828 * Returns all AM Server instance. Read the configured servers from platform 829 * service's <code>iplanet-am-platform-server-list</code> 830 */ 831 public static Set getAMServerInstances() { 832 // Check cache 833 if (accessManagerServers == null) { 834 // Get AdminToken 835 try { 836 SSOToken token = (SSOToken) AccessController 837 .doPrivileged(AdminTokenAction.getInstance()); 838 accessManagerServers = ServerConfiguration.getServers(token); 839 if (debug.messageEnabled()) { 840 debug.message("ServiceManager.getAMServerInstances: " 841 + "server list: " + accessManagerServers); 842 } 843 } catch (SMSException e) { 844 if (debug.warningEnabled()) { 845 debug.warning("ServiceManager.getAMServerInstances: " + 846 "Unable to get server list", e); 847 } 848 } catch (SSOException e) { 849 if (debug.warningEnabled()) { 850 debug.warning("ServiceManager.getAMServerInstances: " + 851 "Unable to get server list", e); 852 } 853 } 854 } 855 return (accessManagerServers == null ? new HashSet() : new HashSet( 856 accessManagerServers)); 857 } 858 859 /** 860 * Returns organization names that match the given attribute name and 861 * values. Only exact matching is supported, and if more than one value is 862 * provided the organization must have all these values for the attribute. 863 * Basically an AND is performed for attribute values for searching. 864 * 865 * @param serviceName 866 * service name under which the attribute is to be sought. 867 * @param attrName 868 * name of the attribute to search. 869 * @param values 870 * set of attribute values to search. 871 * @return organizations that match the attribute name and values. 872 * @throws SMSException 873 * if an error occurred while performing the operation. 874 * @throws SSOException 875 * if the user's single sign on token is invalid or expired. 876 */ 877 public Set searchOrganizationNames(String serviceName, String attrName, 878 Set values) throws SMSException, SSOException { 879 880 try { 881 if (subEntries == null) { 882 subEntries = CachedSubEntries.getInstance(token, 883 SMSEntry.SERVICES_RDN + SMSEntry.COMMA 884 + SMSEntry.baseDN); 885 } 886 return (subEntries.searchOrgNames(token, serviceName.toLowerCase(), 887 attrName, values)); 888 } catch (SSOException ssoe) { 889 debug.error("OrganizationConfigManagerImpl: Unable to " 890 + "get sub organization names", ssoe); 891 throw (new SMSException(SMSEntry.bundle 892 .getString("sms-INVALID_SSO_TOKEN"), 893 "sms-INVALID_SSO_TOKEN")); 894 } 895 } 896 897 /** 898 * Removes all the SMS cached entries. This method 899 * should be called to clear the cache for example, if ACIs for the SMS 900 * entries are changed in the directory. Also, this clears the SMS entries 901 * only in this JVM instance. If multiple instances (of JVM) are running 902 * this method must be called within each instance. 903 * 904 * @supported.api 905 */ 906 public synchronized void clearCache() { 907 // Clear the local caches 908 serviceNameAndOCs = new CaseInsensitiveHashMap(); 909 serviceVersions = new CaseInsensitiveHashMap(); 910 serviceNameDefaultVersion = new CaseInsensitiveHashMap(); 911 accessManagerServers = null; 912 amsdkChecked = false; 913 914 // Call respective Impl classes 915 CachedSMSEntry.clearCache(); 916 CachedSubEntries.clearCache(); 917 // ServiceSchemaManagerImpl.clearCache(); 918 PluginSchemaImpl.clearCache(); 919 ServiceInstanceImpl.clearCache(); 920 ServiceConfigImpl.clearCache(); 921 ServiceConfigManagerImpl.clearCache(); 922 OrganizationConfigManagerImpl.clearCache(); 923 OrgConfigViaAMSDK.clearCache(); 924 925 // Re-initialize the flags 926 try { 927 checkFlags(token); 928 OrganizationConfigManager.initializeFlags(); 929 DNMapper.clearCache(); 930 } catch (Exception e) { 931 debug.error("ServiceManager::clearCache unable to " + 932 "re-initialize global flags", e); 933 } 934 } 935 936 /** 937 * Returns the flag which lets IdRepo and SM know that we are running in the 938 * co-existence mode. 939 * 940 * @return true or false depending on if the coexistence flag is enabled or 941 * not. 942 */ 943 public static boolean isCoexistenceMode() { 944 isRealmEnabled(); 945 return (coexistenceCache); 946 } 947 948 /** 949 * Returns the version for a service. This is to handle the co-existence 950 * of OpenSSO and AM 7.1 in realm mode. The co-existence of OpenSSO and 951 * AM 7.1 in legacy mode is handled by the call to isCoexistenceMode() 952 * method. There is a special service named "iPlanetAMProviderConfigService" 953 * used in AM 7.x code for ID-FF metadata, the version for the service 954 * is "1.1", all the rest of service is "1.0" right now. This method can 955 * be removed if no need to support Co-existence of OpenSSO and AM 7.x 956 * any more. 957 * @param serviceName Name of the service. 958 * @return version of the service, the value will be 1.0 or 1.1. 959 */ 960 protected static String getVersion(String serviceName) { 961 if ("iPlanetAMProviderConfigService".equals(serviceName)) { 962 return "1.1"; 963 } else { 964 return "1.0"; 965 } 966 } 967 968 /** 969 * Returns <code>true</code> if current service 970 * configuration uses the realm model to store the configuration data. 971 * 972 * @return <code>true</code> is realm model is used for storing 973 * configuration data; <code>false</code> otherwise. 974 * 975 * @supported.api 976 */ 977 public static boolean isRealmEnabled() { 978 if (!initialized) { 979 try { 980 initialize((SSOToken) AccessController 981 .doPrivileged(AdminTokenAction.getInstance())); 982 } catch (Exception ssme) { 983 debug.error("ServiceManager::isRealmEnabled unable to " 984 + "initialize", ssme); 985 } 986 } 987 return (realmCache); 988 } 989 990 991 /** 992 * Returns <code>true</code> if AMSDK IdRepo plugin is 993 * configured in any of the realms 994 */ 995 public static boolean isAMSDKConfigured() throws SMSException { 996 if (!isRealmEnabled() || OrgConfigViaAMSDK.isAMSDKConfigured("/")) { 997 // Legacy mode, AMSDK is configured by default 998 return (true); 999 } 1000 1001 // Iterate through all the realms to check if AMSDK is configured 1002 SSOToken token = (SSOToken) AccessController 1003 .doPrivileged(AdminTokenAction.getInstance()); 1004 Set realms = (new OrganizationConfigManager(token, "/")) 1005 .getSubOrganizationNames("*", true); 1006 for (Iterator items = realms.iterator(); items.hasNext();) { 1007 String realm = items.next().toString(); 1008 if (OrgConfigViaAMSDK.isAMSDKConfigured(realm)) { 1009 return (true); 1010 } 1011 } 1012 return (false); 1013 } 1014 1015 /** 1016 * Returns <code>true</code> if configuration data has been migrated to 1017 * Access Manager 7.0. Else <code>false</code> otherwise. 1018 * 1019 * @return <code>true</code> if configuration data has been migrated to AM 1020 * 7.0; <code>false</code> otherwise 1021 */ 1022 public static boolean isConfigMigratedTo70() { 1023 isRealmEnabled(); 1024 return (ditUpgradedCache); 1025 } 1026 1027 // ------------------------------------------------------------ 1028 // Protected methods 1029 // ------------------------------------------------------------ 1030 1031 // Called by CreateServiceConfig.java to create LDAP entries 1032 SSOToken getSSOToken() { 1033 return (token); 1034 } 1035 1036 protected static String getCacheIndex(String serviceName, String version) { 1037 StringBuilder sb = new StringBuilder(20); 1038 return ( 1039 sb.append(serviceName).append(version).toString().toLowerCase()); 1040 } 1041 1042 protected static String getServiceNameDN(String serviceName) { 1043 StringBuilder sb = new StringBuilder(100); 1044 sb.append(SMSEntry.PLACEHOLDER_RDN).append(SMSEntry.EQUALS).append( 1045 serviceName).append(SMSEntry.COMMA).append(serviceDN); 1046 return (sb.toString()); 1047 } 1048 1049 protected static String getServiceNameDN(String serviceName, String version) 1050 { 1051 StringBuilder sb = new StringBuilder(100); 1052 sb.append(SMSEntry.PLACEHOLDER_RDN).append(SMSEntry.EQUALS).append( 1053 version).append(SMSEntry.COMMA).append( 1054 getServiceNameDN(serviceName)); 1055 return (sb.toString()); 1056 } 1057 1058 protected static Set getVersions(SSOToken token, String serviceName) 1059 throws SMSException, SSOException { 1060 CachedSubEntries sVersions = (CachedSubEntries) serviceVersions 1061 .get(serviceName); 1062 if (sVersions == null) { 1063 sVersions = CachedSubEntries.getInstance(token, 1064 getServiceNameDN(serviceName)); 1065 if (sVersions == null || sVersions.getSMSEntry().isNewEntry() 1066 || sVersions.getSubEntries(token).isEmpty()) { 1067 String[] msgs = { serviceName }; 1068 throw (new ServiceNotFoundException( 1069 IUMSConstants.UMS_BUNDLE_NAME, 1070 IUMSConstants.SMS_service_does_not_exist, msgs)); 1071 } 1072 serviceVersions.put(serviceName, sVersions); 1073 } 1074 return (sVersions.getSubEntries(token)); 1075 } 1076 1077 protected static void checkAndEncryptPasswordSyntax(Document doc, 1078 boolean encrypt 1079 ) throws SMSException { 1080 checkAndEncryptPasswordSyntax(doc, encrypt, null); 1081 } 1082 1083 protected static void checkAndEncryptPasswordSyntax( 1084 Document doc, 1085 boolean encrypt, 1086 AMEncryption encryptObj 1087 ) throws SMSException { 1088 // Get the node list of all AttributeSchema 1089 NodeList nl = doc.getElementsByTagName(SMSUtils.SCHEMA_ATTRIBUTE); 1090 for (int i = 0; i < nl.getLength(); i++) { 1091 Node node = nl.item(i); 1092 // Check if the "syntax" attribute is "password" 1093 String syntax = XMLUtils.getNodeAttributeValue(node, 1094 SMSUtils.ATTRIBUTE_SYNTAX); 1095 if (syntax.equals(AttributeSchema.Syntax.PASSWORD.toString())) { 1096 if (debug.messageEnabled()) { 1097 debug.message("ServiceManager: encrypting password syntax"); 1098 } 1099 // Get the DefaultValues and encrypt then 1100 Node defaultNode; 1101 if ((defaultNode = XMLUtils.getChildNode(node, 1102 SMSUtils.ATTRIBUTE_DEFAULT_ELEMENT)) != null) { 1103 // Get NodeList of "Value" nodes and encrypt them 1104 for (Iterator items = XMLUtils.getChildNodes(defaultNode, 1105 SMSUtils.ATTRIBUTE_VALUE).iterator(); items 1106 .hasNext();) { 1107 Node valueNode = (Node) items.next(); 1108 String value = XMLUtils.getValueOfValueNode(valueNode); 1109 String encValue; 1110 1111 // skip empty passwords 1112 if (value.equals("null")) { 1113 continue; 1114 } 1115 1116 if (encrypt) { 1117 if (encryptObj != null) { 1118 value = (String)AccessController 1119 .doPrivileged(new DecodeAction( 1120 value, encryptObj)); 1121 if (value.equals("&#160;")) { 1122 try { 1123 byte[] b = new byte[1]; 1124 b[0] = -96; 1125 value = new String(b, "ISO-8859-1"); 1126 } catch (UnsupportedEncodingException e) { 1127 //ignore 1128 } 1129 } 1130 } 1131 encValue = (String)AccessController.doPrivileged( 1132 new EncodeAction(value)); 1133 } else { 1134 encValue = AccessController.doPrivileged(new DecodeAction(value)); 1135 1136 if (encValue == null) { 1137 encValue = "&#160;"; 1138 } else { 1139 try { 1140 //this is catch the whitespace for password 1141 byte[] b = encValue.getBytes("ISO-8859-1"); 1142 if ((b.length == 1) && (b[0] == -96)) { 1143 encValue = "&#160;"; 1144 } 1145 } catch (UnsupportedEncodingException e) { 1146 //ignore 1147 } 1148 } 1149 if (encryptObj != null) { 1150 encValue = (String)AccessController 1151 .doPrivileged(new EncodeAction( 1152 encValue, encryptObj)); 1153 } 1154 } 1155 1156 // Construct the encrypted "Value" node 1157 StringBuilder sb = new StringBuilder(100); 1158 sb.append(AttributeSchema.VALUE_BEGIN).append(encValue) 1159 .append(AttributeSchema.VALUE_END); 1160 Document newDoc = SMSSchema.getXMLDocument( 1161 sb.toString(), false); 1162 Node newValueNode = XMLUtils.getRootNode(newDoc, 1163 SMSUtils.ATTRIBUTE_VALUE); 1164 // Replace the node 1165 Node nValueNode = doc.importNode(newValueNode, true); 1166 defaultNode.replaceChild(nValueNode, valueNode); 1167 } 1168 } 1169 } 1170 } 1171 } 1172 1173 protected static boolean validateServiceSchema(Node serviceNode) 1174 throws SMSException { 1175 Node schemaRoot = XMLUtils.getChildNode(serviceNode, SMSUtils.SCHEMA); 1176 String[] schemaNames = { SMSUtils.GLOBAL_SCHEMA, SMSUtils.ORG_SCHEMA, 1177 SMSUtils.DYNAMIC_SCHEMA, SMSUtils.USER_SCHEMA, 1178 SMSUtils.POLICY_SCHEMA, SMSUtils.GROUP_SCHEMA, 1179 SMSUtils.DOMAIN_SCHEMA }; 1180 for (int i = 0; i < schemaNames.length; i++) { 1181 Node childNode = XMLUtils.getChildNode(schemaRoot, schemaNames[i]); 1182 if (childNode != null) { 1183 ServiceSchemaImpl ssi = new ServiceSchemaImpl(null, childNode); 1184 Map attrs = ssi.getAttributeDefaults(); 1185 ssi.validateAttributes(attrs, false); 1186 } 1187 } 1188 return (true); 1189 } 1190 1191 // Gets called by OrganizationConfigManager when service schema has changed 1192 protected static void schemaChanged() { 1193 // Reset the service names and OCs used by IdRepo 1194 serviceNameAndOCs = new CaseInsensitiveHashMap(); 1195 // Reset the schema types and service names 1196 // Reset the service names 1197 serviceNames = null; 1198 } 1199 1200 protected static String serviceDefaultVersion(SSOToken token, 1201 String serviceName) throws SMSException, SSOException { 1202 String version = (String) serviceNameDefaultVersion.get(serviceName); 1203 if (version == null) { 1204 Iterator iter = getVersions(token, serviceName).iterator(); 1205 if (iter.hasNext()) { 1206 version = (String) iter.next(); 1207 } else { 1208 String msgs[] = { serviceName }; 1209 throw (new ServiceNotFoundException( 1210 IUMSConstants.UMS_BUNDLE_NAME, 1211 IUMSConstants.SMS_service_does_not_exist, 1212 msgs)); 1213 } 1214 serviceNameDefaultVersion.put(serviceName, version); 1215 } 1216 return (version); 1217 } 1218 1219 /** 1220 * Returns service names that will be assigned to a realm during creation. 1221 */ 1222 public static Set servicesAssignedByDefault() { 1223 if (!loadedAuthServices) { 1224 AuthenticationServiceNameProvider provider = 1225 AuthenticationServiceNameProviderFactory.getProvider(); 1226 defaultServicesToLoad.addAll(provider 1227 .getAuthenticationServiceNames()); 1228 if (debug.messageEnabled()) { 1229 debug.message("ServiceManager::servicesAssignedByDefault:" 1230 + "defaultServicesToLoad = " + defaultServicesToLoad); 1231 } 1232 loadedAuthServices = true; 1233 defaultServicesToLoad = Collections 1234 .unmodifiableSet(defaultServicesToLoad); 1235 } 1236 return (defaultServicesToLoad); 1237 } 1238 1239 /** 1240 * Returns service names configured via IdRepo service to be 1241 * added as required services 1242 */ 1243 static Set requiredServices() { 1244 return (requiredServices); 1245 } 1246 1247 static void initialize(SSOToken token) throws SMSException, SSOException { 1248 // Validate SSOToken 1249 SMSEntry.validateToken(token); 1250 1251 // Check if already initialized 1252 if (initialized) 1253 return; 1254 // Initilaize the parameters 1255 try { 1256 // Get the service names and cache it 1257 serviceNames = CachedSubEntries.getInstance(token, serviceDN); 1258 if (serviceNames.getSMSEntry().isNewEntry()) { 1259 if (debug.warningEnabled()) { 1260 debug.warning("SeviceManager:: Root service node " 1261 + "does not exists: " + serviceDN); 1262 } 1263 String[] msgs = new String[1]; 1264 msgs[0] = serviceDN; 1265 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 1266 IUMSConstants.SMS_services_node_does_not_exist, msgs)); 1267 } 1268 } catch (SMSException e) { 1269 debug.error("ServiceManager::unable to get " + "services node: " 1270 + serviceDN, e); 1271 throw (e); 1272 } 1273 // Check if realm is enabled and set appropriate flags 1274 checkFlags(token); 1275 initialized = true; 1276 } 1277 1278 static void checkFlags(SSOToken token) throws SMSException, SSOException { 1279 try { 1280 CachedSMSEntry entry = CachedSMSEntry.getInstance(token, 1281 REALM_ENTRY); 1282 if (entry.isDirty()) { 1283 entry.refresh(); 1284 } 1285 if (!entry.isNewEntry()) { 1286 ditUpgradedCache = true; 1287 ServiceConfigManagerImpl ssm = ServiceConfigManagerImpl 1288 .getInstance(token, REALM_SERVICE, SERVICE_VERSION); 1289 ServiceConfigImpl sc = null; 1290 Map map = null; 1291 if (ssm == null 1292 || (sc = ssm.getGlobalConfig(token, null)) == null 1293 || (map = sc.getAttributes()) == null) { 1294 return; 1295 } 1296 Set coexistEntry = (Set) map.get(COEXISTENCE_ATTR_NAME); 1297 if (coexistEntry != null && coexistEntry.contains("false")) { 1298 coexistenceCache = false; 1299 } 1300 Set realmEntry = (Set) map.get(REALM_ATTR_NAME); 1301 if (realmEntry != null && realmEntry.contains("true")) { 1302 realmCache = true; 1303 } 1304 // Get the default services to be loaded 1305 requiredServices = (Set) map 1306 .get(DEFAULT_SERVICES_FOR_REALMS); 1307 defaultServicesToLoad = new HashSet(); 1308 defaultServicesToLoad.addAll(requiredServices); 1309 1310 // Make this flag false, for always the union of 1311 // auto assignment services from idRepoService.xml and 1312 // auth services from AMAuthenticationManager code 1313 // should be returned for deep copy for a newly created 1314 // sub realm. 1315 loadedAuthServices = false; 1316 } 1317 if (debug.messageEnabled()) { 1318 debug.message("ServiceManager::checkFlags:realmEnabled=" 1319 + realmCache); 1320 debug.message("ServiceManager::checkFlags:coexistenceMode=" 1321 + coexistenceCache); 1322 } 1323 } catch (SMSException e) { 1324 debug.error("ServiceManager::unable to check " 1325 + "if Realm is enabled: ", e); 1326 throw (e); 1327 } 1328 } 1329 1330 public String toXML(AMEncryption encryptObj) 1331 throws SMSException, SSOException 1332 { 1333 StringBuilder buff = new StringBuilder(); 1334 buff.append(SMSSchema.XML_ENC) 1335 .append("\n") 1336 .append("<!DOCTYPE ServicesConfiguration\n") 1337 .append( 1338 "PUBLIC \"=//iPlanet//Service Management Services (SMS) 1.0 DTD//EN\"\n") 1339 .append("\"jar://com/sun/identity/sm/sms.dtd\">\n\n"); 1340 buff.append("<ServicesConfiguration>\n"); 1341 1342 Set serviceNames = getServiceNames(); 1343 1344 for (Iterator i = serviceNames.iterator(); i.hasNext(); ) { 1345 String serviceName = (String)i.next(); 1346 Set versions = getServiceVersions(serviceName); 1347 1348 for (Iterator j = versions.iterator(); j.hasNext(); ) { 1349 String version = (String)j.next(); 1350 ServiceSchemaManager ssm = new 1351 ServiceSchemaManager(token, serviceName, version); 1352 String xml = ssm.toXML(encryptObj); 1353 ServiceConfigManager scm = new ServiceConfigManager( 1354 serviceName, token); 1355 int idx = xml.lastIndexOf("</" + SMSUtils.SERVICE + ">"); 1356 xml = xml.substring(0, idx) + scm.toXML(encryptObj) + "</" + 1357 SMSUtils.SERVICE + ">"; 1358 buff.append(xml).append("\n"); 1359 } 1360 } 1361 1362 buff.append("</ServicesConfiguration>\n"); 1363 return buff.toString().replaceAll("&#160;", " "); 1364 } 1365 1366 /** 1367 * Returns <code>true</code> if AMSDK IdRepo plugin is enabled/present 1368 * in IdRepo Service Configuration schema 1369 */ 1370 public static boolean isAMSDKEnabled() { 1371 if (amsdkChecked) { 1372 return (isAMSDKEnabled); 1373 } 1374 SSOToken adminToken = (SSOToken) AccessController 1375 .doPrivileged(AdminTokenAction.getInstance()); 1376 try { 1377 if (!ServiceManager.isRealmEnabled()) { 1378 amsdkChecked = true; 1379 // If in legacy mode, then amSDK plugin would always be there. 1380 isAMSDKEnabled = true; 1381 } else { 1382 ServiceSchemaManager ssm = new ServiceSchemaManager( 1383 IdConstants.REPO_SERVICE, adminToken); 1384 ServiceSchema idRepoSubSchema = ssm.getOrganizationSchema(); 1385 Set idRepoPlugins = idRepoSubSchema.getSubSchemaNames(); 1386 if (idRepoPlugins.contains("amSDK")) { 1387 isAMSDKEnabled = true; 1388 } 1389 amsdkChecked = true; 1390 } 1391 } catch (Exception e) { 1392 debug.error("IdUtils.isAMSDKEnabled() " + 1393 "Error in checking AM.SDK being configured", e); 1394 } 1395 amsdkChecked = true; 1396 return (isAMSDKEnabled); 1397 } 1398}