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