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: OrganizationConfigManager.java,v 1.31 2010/01/20 17:01:36 veiming Exp $ 026 * 027 * Portions Copyrighted 2011-2016 ForgeRock AS. 028 */ 029package com.sun.identity.sm; 030 031import java.util.Collections; 032import java.util.HashMap; 033import java.util.HashSet; 034import java.util.Iterator; 035import java.util.Map; 036import java.util.Set; 037import java.util.StringTokenizer; 038import java.util.regex.Pattern; 039 040import org.forgerock.openam.ldap.LDAPUtils; 041import org.forgerock.opendj.ldap.DN; 042 043import com.iplanet.am.util.SystemProperties; 044import com.iplanet.sso.SSOException; 045import com.iplanet.sso.SSOToken; 046import com.iplanet.ums.IUMSConstants; 047import com.sun.identity.authentication.util.ISAuthConstants; 048import com.sun.identity.common.CaseInsensitiveHashSet; 049import com.sun.identity.delegation.DelegationException; 050import com.sun.identity.delegation.DelegationUtils; 051import com.sun.identity.idm.IdConstants; 052import com.sun.identity.idm.IdRepoException; 053import com.sun.identity.idm.plugins.internal.AgentsRepo; 054import com.sun.identity.shared.Constants; 055 056/** 057 * The class <code>OrganizationConfigManager</code> provides interfaces to 058 * manage an organization's configuration data. It provides interfaces to create 059 * and delete organizations, service attributes for organizations and service 060 * configuration parameters. 061 * <p> 062 * The organization configuration can be managed in a hierarchical manner, and a 063 * forward slash "/" will be used to separate the name hierarchy. Hence the root 064 * of the organization hierarchy will be represented by a single forward slash 065 * "/", and sub-organizations will be separated by "/". For example "/a/b/c" 066 * would represent a "c" sub-organization within "b" which would be a 067 * sub-organization of "a". 068 * 069 * @supported.all.api 070 */ 071public class OrganizationConfigManager { 072 073 // Instance variables 074 private SSOToken token; 075 076 private String orgName; 077 078 private String orgDN; 079 080 private OrgConfigViaAMSDK amsdk; 081 082 private OrganizationConfigManagerImpl orgConfigImpl; 083 084 static String orgNamingAttrInLegacyMode; 085 086 static Pattern baseDNpattern = Pattern.compile(SMSEntry.getRootSuffix()); 087 088 protected static final String SERVICES_NODE = SMSEntry.SERVICES_RDN 089 + SMSEntry.COMMA + SMSEntry.getRootSuffix(); 090 091 // set the special characters which are not in realm names. 092 static String specialCharsString = "*|(|)|!|/|="; 093 094 private static String SEPERATOR = "|"; 095 096 private String CONF_ENABLED = 097 "sun-idrepo-amSDK-config-copyconfig-enabled"; 098 099 private boolean copyOrgInitialized; 100 101 private boolean copyOrgEnabled; 102 103 private String amSDKOrgDN; 104 105 // sunOrganizationAlias in org DIT. 106 public static final String SUNORG_ALIAS = "sunOrganizationAliases"; 107 108 // associatedDomain in org DIT. 109 private String SUNDNS_ALIAS = "sunDNSAliases"; 110 111 // sunPreferredDomain in org DIT. 112 private String SUNPREF_DOMAIN = "sunPreferredDomain"; 113 114 // inetDomainStatus in org DIT. 115 private String SUNORG_STATUS = "sunOrganizationStatus"; 116 117 private static final String SMS_INVALID_SSO_TOKEN = "sms-INVALID_SSO_TOKEN"; 118 119 static { 120 initializeFlags(); 121 } 122 123 /** 124 * Constructor to obtain an instance of 125 * <code>OrganizationConfigManager 126 * </code> for an organization by providing 127 * an authenticated identity of the user. The organization name would be "/" 128 * seperated to represent organization hierarchy. 129 * 130 * @param token 131 * single sign on token of authenticated user identity. 132 * @param orgName 133 * name of the organization. The value of <code>null 134 * </code> or 135 * "/" would represent the root organization. 136 * 137 * @throws SMSException 138 * if an error has occurred while getting the instance of 139 * <code>OrganizationConfigManager 140 * </code>. 141 */ 142 public OrganizationConfigManager(SSOToken token, String orgName) 143 throws SMSException { 144 // Copy instance variables 145 this.token = token; 146 this.orgName = orgName; 147 148 // Instantiate and validate 149 validateConfigImpl(); 150 orgDN = orgConfigImpl.getOrgDN(); 151 try { 152 if (migratedTo70 && !registeredForConfigNotifications) { 153 ServiceConfigManager scmr = new ServiceConfigManager( 154 ServiceManager.REALM_SERVICE, token); 155 scmr.addListener(new OrganizationConfigManagerListener()); 156 registeredForConfigNotifications = true; 157 } 158 } catch (SMSException s) { 159 String installTime = SystemProperties.get( 160 Constants.SYS_PROPERTY_INSTALL_TIME, "false"); 161 if (!installTime.equals("true")) { 162 SMSEntry.debug.warning("OrganizationConfigManager: " 163 + "constructor. Unable to " 164 + "construct ServiceConfigManager for idRepoService ", s); 165 } 166 throw s; 167 } catch (SSOException ssoe) { 168 SMSEntry.debug.error("OrganizationConfigManager:Constructor", ssoe); 169 throw (new SMSException(SMSEntry.bundle 170 .getString(SMS_INVALID_SSO_TOKEN), 171 SMS_INVALID_SSO_TOKEN)); 172 } 173 174 if (coexistMode) { 175 amsdk = new OrgConfigViaAMSDK(token, DNMapper 176 .realmNameToAMSDKName(orgDN), orgDN); 177 if (orgNamingAttrInLegacyMode == null) { 178 orgNamingAttrInLegacyMode = getNamingAttrForOrg(); 179 } 180 } 181 } 182 183 /** 184 * Returns the fully qualified name of the 185 * organization from the root 186 * 187 * @return the name of the organization 188 */ 189 public String getOrganizationName() { 190 return (orgName); 191 } 192 193 /** 194 * Returns the services configured for the organization. 195 * 196 * @return service names configured for the organization. 197 * @throws SMSException 198 * if there is an error accessing the data store to read the 199 * configured services. 200 * 201 * @deprecated This method has been deprecated, use <code> 202 * getAssignedServices()</code> 203 * instead. 204 */ 205 public Set getConfiguredServices() throws SMSException { 206 return (getAssignedServices()); 207 } 208 209 /** 210 * Returns a set of service schemas to be used for 211 * creation of an organization. The service schemas contain a list of 212 * attributes and their schema, and will be provided as 213 * <code>ServiceSchema</code>. 214 * 215 * @return Set of <code>ServiceSchema</code> to be used for creation of an 216 * organization. 217 * @throws SMSException 218 * if there is an error accessing the data store to read the 219 * service schemas. 220 */ 221 public Set getServiceSchemas() throws SMSException { 222 // Loop through the services and determine the 223 // organization creation schemas 224 Set serviceSchemaSet = null; 225 try { 226 Set serviceNames = getServiceNames(token); 227 serviceSchemaSet = new HashSet(serviceNames.size() * 2); 228 for (Iterator names = serviceNames.iterator(); names.hasNext();) { 229 ServiceSchemaManager ssm = new ServiceSchemaManager( 230 (String) names.next(), token); 231 ServiceSchema ss = ssm.getOrganizationCreationSchema(); 232 if (ss != null) { 233 serviceSchemaSet.add(ss); 234 } 235 } 236 } catch (SSOException ssoe) { 237 SMSEntry.debug.error("OrganizationConfigManager:getServiceSchemas" 238 + " unable to get service schema", ssoe); 239 throw (new SMSException(SMSEntry.bundle 240 .getString(SMS_INVALID_SSO_TOKEN), ssoe, 241 SMS_INVALID_SSO_TOKEN)); 242 } 243 return (serviceSchemaSet); 244 } 245 246 /** 247 * Creates a sub-organization under the current 248 * organization and sets the specified attributes. The sub-organization 249 * created can be only one level below the current organization. For 250 * multiple levels this method must be called recursively with the 251 * corresponding <code>OrganizationConfigManager 252 * </code>. The organization 253 * name must not have forward slash ("/"). For eg., the actual organization 254 * name 'iplanet' cannot be 'iplan/et' because we are using '/' as the 255 * seperator here. The attributes for the organization can be <code> 256 * null</code>; 257 * else would contain service name as the key and another <code>Map</code> 258 * as the value that would contain the key-values pair for the services. 259 * 260 * @param subOrgName 261 * the name of the sub-organization. 262 * @param attributes 263 * Map of attributes for the organization per service. The 264 * parameter Map attributes contains another Map as its value, 265 * which then has attribute names and values. The way it is 266 * arranged is: Map::attributes --> Key: String::ServiceName 267 * Value: Map::svcAttributes Map::svcAttributes --> Key: 268 * String::AttributeName Value: Set::AttributeValues 269 * 270 * @return organization config manager of the newly created 271 * sub-organization. 272 * @throws SMSException 273 * if creation of sub-organization failed, or if creation of 274 * sub-organization is attempted when configuration is not 275 * migrated to realms. 276 */ 277 public OrganizationConfigManager createSubOrganization(String subOrgName, 278 Map attributes) throws SMSException { 279 validateConfigImpl(); 280 /* 281 * Since the "Map attributes" can contain more than one service name, 282 * creation of the sub organization is be achieved in 2 steps. i) create 283 * the sub-organization without the attributes ii) for the service names 284 * in the Map call setAttributes(...) 285 */ 286 boolean orgExists = false; 287 String subOrgDN = normalizeDN(subOrgName, orgDN); 288 try { 289 // Check if realm exists, this throws SMSException 290 // if realm does not exist 291 // This is to avoid duplicate creation of realms. 292 new OrganizationConfigManager(token, subOrgDN); 293 SMSEntry.debug.error("OrganizationConfigManager::" 294 + "createSubOrganization() " + "Realm Already Exists.. " 295 + subOrgDN); 296 orgExists = true; 297 } catch (SMSException smse) { 298 try { 299 orgExists = !getRealmByAlias(subOrgName).isEmpty(); 300 } catch (SSOException e) { 301 SMSEntry.debug.error("OrganizationConfigManager::" + 302 "createSubOrganization:", e); 303 } 304 305 if (!orgExists) { 306 SMSEntry.debug.message("OrganizationConfigManager::createSubOrganization() New Realm, creating realm: {} - {}", subOrgName, smse); 307 } 308 } 309 Object args[] = { subOrgName }; 310 if (orgExists) { 311 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 312 "sms-organization_already_exists1", 313 args)); 314 } 315 StringTokenizer st = 316 new StringTokenizer(specialCharsString, SEPERATOR); 317 while (st.hasMoreTokens()) { 318 String obj = (String) st.nextToken(); 319 if (subOrgName.indexOf(obj) > -1) { 320 SMSEntry.debug.error("OrganizationConfigManager::"+ 321 "createSubOrganization() : Invalid realm name: "+ 322 subOrgName); 323 SMSEntry.debug.error("OrganizationConfigManager::"+ 324 "createSubOrganization() : Detected invalid chars: "+obj); 325 Object args1[] = {subOrgName}; 326 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 327 SMSEntry.bundle.getString("sms-invalid-org-name"),args1)); 328 } 329 } 330 validateOrgName(subOrgName); 331 332 // If in legacy mode or (realm mode and copy org enabled) 333 // Create the AMSDK organization first 334 if ((coexistMode) || (realmEnabled && isCopyOrgEnabled())) { 335 amsdk.createSubOrganization(subOrgName); 336 } 337 if ((realmEnabled || subOrgDN.toLowerCase().startsWith( 338 SMSEntry.SUN_INTERNAL_REALM_PREFIX)) 339 && getSubOrganizationNames(subOrgName, false).isEmpty()) { 340 CreateServiceConfig.createOrganization(token, subOrgDN); 341 } 342 // Update the attributes 343 // If in coexistMode and serviceName is idRepoService 344 // the following call sets the attributes to AMSDK organization also. 345 OrganizationConfigManager ocm = getSubOrgConfigManager(subOrgName); 346 if ((attributes != null) && (!attributes.isEmpty())) { 347 for (Iterator svcNames = attributes.keySet().iterator(); svcNames 348 .hasNext();) { 349 String serviceName = (String) svcNames.next(); 350 Map svcAttributes = (Map) attributes.get(serviceName); 351 if ((svcAttributes != null) && (!svcAttributes.isEmpty())) { 352 ocm.setAttributes(serviceName, svcAttributes); 353 } 354 } 355 } 356 357 if (realmEnabled) { 358 AgentsRepo agentsRepo = new AgentsRepo(); 359 HashMap config = new HashMap(1); 360 HashSet realmName = new HashSet(1); 361 realmName.add(subOrgDN); 362 config.put("agentsRepoRealmName", realmName); 363 try { 364 agentsRepo.initialize(config); 365 agentsRepo.createAgentGroupConfig(token); 366 } catch (IdRepoException ide) { 367 SMSEntry.debug.error("OrganizationConfigManager::"+ 368 "createSubOrganization:", ide); 369 } 370 } 371 372 // If in realm mode and not in legacy mode, default services needs 373 // to be added. 374 if (realmEnabled && !coexistMode) { 375 loadDefaultServices(token, ocm); 376 } 377 378 // If in realm mode and copy org enabled, default services needs 379 // to be registered for the newly created org/suborg and the 380 // amSDKOrgName/OpenAM Organization is updated with the 381 // new suborg dn. 382 if (realmEnabled && isCopyOrgEnabled()) { 383 registerSvcsForOrg(subOrgName, subOrgDN); 384 OrganizationConfigManager subOrg = 385 getSubOrgConfigManager(subOrgName); 386 ServiceConfig s = 387 subOrg.getServiceConfig(ServiceManager.REALM_SERVICE); 388 if (s != null) { 389 try { 390 Iterator items = s.getSubConfigNames().iterator(); 391 while (items.hasNext()) { 392 ServiceConfig subConfig = 393 s.getSubConfig((String) items.next()); 394 if (subConfig.getSchemaID().equalsIgnoreCase( 395 IdConstants.AMSDK_PLUGIN_NAME)) { 396 Map amsdkConfig = new HashMap(); 397 Set vals = new HashSet(); 398 vals.add(orgNamingAttrInLegacyMode + 399 SMSEntry.EQUALS + 400 subOrgName + SMSEntry.COMMA + amSDKOrgDN); 401 amsdkConfig.put("amSDKOrgName", vals); 402 subConfig.setAttributes(amsdkConfig); 403 } 404 break; 405 } 406 } catch (SSOException ssoe) { 407 SMSEntry.debug.error("OrganizationConfigManager::"+ 408 "createSubOrganization:", ssoe); 409 throw (new SMSException(SMSEntry.bundle.getString( 410 SMS_INVALID_SSO_TOKEN), SMS_INVALID_SSO_TOKEN)); 411 } 412 } 413 } 414 415 if (realmEnabled) { 416 try { 417 if (coexistMode) { 418 DelegationUtils.createRealmPrivileges(token, orgName); 419 } else { 420 OrganizationConfigManager parentOrg = 421 getParentOrgConfigManager(); 422 DelegationUtils.copyRealmPrivilegesFromParent( 423 token, parentOrg, ocm); 424 } 425 } catch (SSOException ssoe) { 426 if (SMSEntry.debug.messageEnabled()) { 427 SMSEntry.debug.message("Creating delegation permissions for: " + 428 orgName + " failed", ssoe); 429 } 430 } catch (SMSException smse) { 431 if (SMSEntry.debug.messageEnabled()) { 432 SMSEntry.debug.message("Creating delegation permissions for: " + 433 orgName + " failed", smse); 434 } 435 } catch (DelegationException de) { 436 if (SMSEntry.debug.messageEnabled()) { 437 SMSEntry.debug.message("Creating delegation permissions for: " + 438 orgName + " failed", de); 439 } 440 } 441 } 442 443 // Return the newly created organization config manager 444 return (ocm); 445 } 446 447 private Set getRealmByAlias(String subOrgName) throws SSOException, SMSException { 448 ServiceManager serviceManager = new ServiceManager(token); 449 return serviceManager.searchOrganizationNames( 450 IdConstants.REPO_SERVICE, 451 IdConstants.ORGANIZATION_ALIAS_ATTR, Collections.singleton(subOrgName)); 452 } 453 454 private void validateOrgName(final String subOrgName) throws SMSException { 455 String realm = DNMapper.orgNameToRealmName(subOrgName); 456 int idx = realm.lastIndexOf('/'); 457 if (idx > -1 && idx < realm.length() - 1) { 458 realm = realm.substring(idx+1); 459 } 460 461 if (InvalidRealmNameManager.getInvalidRealmNames().contains(realm)) { 462 SMSEntry.debug.error("OrganizationConfigManager::createSubOrganization() : Invalid realm name: " + 463 subOrgName + " - clashes with REST endpoint"); 464 throw new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 465 SMSEntry.bundle.getString("sms-invalid-org-name"), new Object[]{ subOrgName }); 466 } 467 } 468 469 470 /** 471 * Returns the names of all sub-organizations. 472 * 473 * @return set of names of all sub-organizations. 474 * @throws SMSException 475 * if there is an error accessing the data store to read the 476 * sub-organization names. 477 */ 478 479 public Set getSubOrganizationNames() throws SMSException { 480 try { 481 return (getSubOrganizationNames("*", false)); 482 } catch (SMSException s) { 483 SMSEntry.debug.error("OrganizationConfigManager: " 484 + "getSubOrganizationNames() Unable to " 485 + "get sub organization names ", s); 486 throw s; 487 } 488 } 489 490 /** 491 * Returns the names of all peer-organizations. 492 * 493 * @return set of names of all peer-organizations. 494 * @throws SMSException 495 * if there is an error accessing the data store to read the 496 * peer-organization names. 497 */ 498 499 public Set getPeerOrganizationNames() throws SMSException { 500 Set getPeerSet = Collections.EMPTY_SET; 501 if (realmEnabled) { 502 try { 503 OrganizationConfigManager ocmParent = 504 getParentOrgConfigManager(); 505 getPeerSet = ocmParent.getSubOrganizationNames(); 506 } catch (SMSException s) { 507 if (SMSEntry.debug.warningEnabled()) { 508 SMSEntry.debug.warning("OrganizationConfigManager: " 509 + "getPeerOrganizationNames() Unable to " 510 + "get Peer organization names ", s); 511 } 512 throw s; 513 } 514 } 515 return (getPeerSet); 516 } 517 518 /** 519 * Returns names of sub-organizations matching the 520 * given pattern. If the parameter <code>recursive</code> is set to 521 * <code>true</code>, search will be performed for the entire sub-tree. 522 * The pattern can contain "*" as the wildcard to represent zero or more 523 * characters. 524 * 525 * @param pattern 526 * pattern that will be used for searching, where "*" will be the 527 * wildcard. 528 * @param recursive 529 * if set to <code>true</code> the entire sub-tree will be 530 * searched for the organization names. 531 * @return names of sub-organizations matching the pattern. 532 * @throws SMSException 533 * if there is an error accessing the data store to read the 534 * sub-organization names. 535 */ 536 public Set getSubOrganizationNames(String pattern, boolean recursive) 537 throws SMSException { 538 validateConfigImpl(); 539 try { 540 if (realmEnabled) { 541 return (orgConfigImpl.getSubOrganizationNames(token, pattern, 542 recursive)); 543 } else { 544 // Must be in coexistence mode 545 return (amsdk.getSubOrganizationNames(pattern, recursive)); 546 } 547 } catch (SMSException s) { 548 SMSEntry.debug.error("OrganizationConfigManager: " 549 + "getSubOrganizationNames(String pattern, " 550 + "boolean recursive) Unable to get sub organization " 551 + "names for filter: " + pattern, s); 552 throw s; 553 } 554 } 555 556 /** 557 * Deletes the given sub-organization. If the 558 * parameter <code>recursive</code> is set to <code>true</code>, then 559 * the suborganization and the sub-tree will be deleted. 560 * 561 * If the parameter <code>recursive</code> is set to <code>false</code> 562 * then the sub-organization shall be deleted provided it is the leaf node. 563 * If there are entries beneath the sub-organization and if the parameter 564 * <code>recursive</code> is set to <code>false</code>, then an 565 * exception is thrown that this sub-organization cannot be deleted. 566 * 567 * @param subOrgName 568 * sub-organization name to be deleted. 569 * @param recursive 570 * if set to <code>true</code> the entire sub-tree will be 571 * deleted. 572 * @throws SMSException 573 * if the sub-organization name cannot be found, or if there are 574 * entries beneath the sub-organization and if the parameter 575 * <code>recursive</code> is set to <code>false</code>. 576 */ 577 public void deleteSubOrganization(String subOrgName, boolean recursive) 578 throws SMSException { 579 validateConfigImpl(); 580 // Should not delete the root realm, should throw exception if 581 // attempted. 582 String subOrgDN = normalizeDN(subOrgName, orgDN); 583 if (subOrgDN.equals(SMSEntry.SLASH_STR) || 584 subOrgDN.equalsIgnoreCase(SMSEntry.getRootSuffix()) || 585 subOrgDN.equalsIgnoreCase(SERVICES_NODE)) { 586 587 Object parms[] = { orgName }; 588 SMSEntry.debug.error( 589 "OrganizationConfigManager: deleteSubOrganization(" + 590 "Root realm "+orgName + " cannot be deleted. "); 591 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 592 "sms-cannot_delete_rootsuffix",parms)); 593 594 } 595 // Delete the sub-organization 596 OrganizationConfigManager subRlmConfigMgr = 597 getSubOrgConfigManager(subOrgName); 598 //set the filter "*" to be passed for the search. 599 Set subRlmSet = 600 subRlmConfigMgr.getSubOrganizationNames("*", true); 601 602 boolean isCopyOrgEnabled = isCopyOrgEnabled(); 603 if (realmEnabled) { 604 try { 605 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 606 subOrgDN); 607 if (cEntry.isDirty()) { 608 cEntry.refresh(); 609 } 610 SMSEntry entry = cEntry.getClonedSMSEntry(); 611 if (!recursive) { 612 // Check if there are sub organization entries 613 // and if exist 614 // throw exception that this sub organization cannot be 615 // deleted. 616 if ((subRlmSet !=null) && (!subRlmSet.isEmpty())) { 617 throw (new SMSException(SMSEntry.bundle 618 .getString("sms-entries-exists"), 619 "sms-entries-exists")); 620 } 621 } 622 // Obtain the SMSEntry for the suborg and 623 // sub tree and delete it. 624 entry.delete(token); 625 cEntry.refresh(entry); 626 } catch (SSOException ssoe) { 627 SMSEntry.debug.error( 628 "OrganizationConfigManager: deleteSubOrganization(" + 629 "String subOrgName, boolean recursive) Unable to " + 630 "delete sub organization ", ssoe); 631 throw (new SMSException(SMSEntry.bundle 632 .getString(SMS_INVALID_SSO_TOKEN), 633 SMS_INVALID_SSO_TOKEN)); 634 } 635 } 636 637 // If in legacy mode or (realm mode and copy org enabled) 638 // delete the corresponding organization. 639 if ((coexistMode) || (realmEnabled && isCopyOrgEnabled)) { 640 String amsdkName = DNMapper.realmNameToAMSDKName(subOrgDN); 641 if (!SMSEntry.getRootSuffix().equalsIgnoreCase( 642 SMSEntry.getAMSdkBaseDN())) { 643 String convOrg = subOrgName; 644 if (subOrgName.startsWith("/")) { 645 convOrg = DNMapper.convertToDN(subOrgName).toString(); 646 } 647 amsdkName = convOrg + SMSEntry.COMMA + amSDKOrgDN; 648 } 649 amsdk.deleteSubOrganization(amsdkName); 650 } 651 } 652 653 /** 654 * Returns the <code>OrganizationConfigManager</code> 655 * for the given organization name. 656 * 657 * @param subOrgName 658 * the name of the organization. 659 * @return the configuration manager for the given organization. 660 * 661 * @throws SMSException 662 * if the organization name cannot be found or user doesn't have 663 * access to that organization. 664 */ 665 public OrganizationConfigManager getSubOrgConfigManager(String subOrgName) 666 throws SMSException { 667 validateConfigImpl(); 668 // Normalize sub organization name 669 return (new OrganizationConfigManager(token, normalizeDN(subOrgName, 670 orgDN))); 671 } 672 673 /** 674 * Returns the organization creation attributes for 675 * the service. 676 * 677 * @param serviceName 678 * name of the service. 679 * @return map of organization creation attribute values for service 680 * @throws SMSException 681 * if there is an error accessing the data store to read the 682 * attributes of the service. 683 */ 684 public Map getAttributes(String serviceName) throws SMSException { 685 validateConfigImpl(); 686 if (serviceName == null) { 687 return (Collections.EMPTY_MAP); 688 } 689 Map attrValues = null; 690 // Attributes can be obtained only if DIT is migrated to AM 7.0 691 if (migratedTo70) { 692 // Lowercase the service name 693 serviceName = serviceName.toLowerCase(); 694 try { 695 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 696 orgDN); 697 if (cEntry.isDirty() || (coexistMode) || 698 (realmEnabled && isCopyOrgEnabled())) { 699 // Since AMSDK org notifications will not be 700 // obtained, the entry must be read again 701 cEntry.refresh(); 702 } 703 SMSEntry entry = cEntry.getSMSEntry(); 704 Map map = SMSUtils.getAttrsFromEntry(entry); 705 if ((map != null) && (!map.isEmpty())) { 706 Iterator itr = map.keySet().iterator(); 707 while (itr.hasNext()) { 708 String name = (String) itr.next(); 709 if ((name.toLowerCase()).startsWith(serviceName)) { 710 Set values = (Set) map.get(name); 711 // Remove the serviceName and '-' and return only 712 // the attribute name,value. 713 String key; 714 715 if (!serviceName.isEmpty()) { 716 key = name.substring(serviceName.length() + 1); 717 } else { 718 key = name; 719 } 720 if (attrValues == null) { 721 attrValues = new HashMap(); 722 } 723 attrValues.put(key, values); 724 } 725 } 726 } 727 } catch (SSOException ssoe) { 728 SMSEntry.debug.error("OrganizationConfigManager: " 729 + "getAttributes(String serviceName) Unable to " 730 + "get Attributes", ssoe); 731 throw (new SMSException(SMSEntry.bundle 732 .getString(SMS_INVALID_SSO_TOKEN), 733 SMS_INVALID_SSO_TOKEN)); 734 } 735 } 736 737 // If in coexistMode and serviceName is idRepoService 738 // get attributes from AMSDK organization 739 if ((coexistMode || (realmEnabled && isCopyOrgEnabled())) 740 && serviceName 741 .equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) { 742 Map amsdkMap = amsdk.getAttributes(); 743 Map mergesdkMap = new HashMap(2); 744 if (amsdkMap != null && !amsdkMap.isEmpty()) { 745 Set mergeValues = new HashSet(2); 746 Iterator itr = amsdkMap.keySet().iterator(); 747 while (itr.hasNext()) { 748 String key = (String) itr.next(); 749 if (key.equalsIgnoreCase(SUNDNS_ALIAS) || 750 key.equalsIgnoreCase(SUNPREF_DOMAIN) || 751 key.equalsIgnoreCase(SUNORG_ALIAS)) { 752 buildSet(key, amsdkMap, mergeValues); 753 } 754 } 755 mergesdkMap.put(SUNORG_ALIAS, mergeValues); 756 mergesdkMap.put(SUNORG_STATUS, 757 (Set) amsdkMap.get(SUNORG_STATUS)); 758 } 759 if (attrValues == null) { 760 attrValues = mergesdkMap; 761 } else { 762 attrValues.putAll(mergesdkMap); 763 } 764 } 765 return ((attrValues == null) ? Collections.EMPTY_MAP : attrValues); 766 } 767 768 /** 769 * Builds and returns the appropriate Set for the attributes to be 770 * merged from org and realm if the system is 771 * in intrusive mode (Both org DIT and realm DIT are present). 772 * This happens when the Copy Config flag is enabled. 773 */ 774 private Set buildSet(String attrName, Map attributes, Set resultSet) { 775 Set vals = (Set) attributes.get(attrName); 776 if ((vals != null) && !vals.isEmpty()) { 777 resultSet.addAll(vals); 778 } 779 return (resultSet); 780 } 781 782 /** 783 * Adds organization attributes for the service. If 784 * the attribute already exists, the values will be appended to it, provided 785 * it is a multi-valued attribute. It will throw exception if we try to add 786 * a value to an attribute which has the same value already. 787 * 788 * @param serviceName 789 * name of the service. 790 * @param attrName 791 * name of the attribute. 792 * @param values 793 * values for the attribute. 794 * @throws SMSException 795 * if we try to add a value to an attribute which has the same 796 * value already. 797 */ 798 public void addAttributeValues(String serviceName, String attrName, 799 Set values) throws SMSException { 800 validateConfigImpl(); 801 if (serviceName == null || attrName == null) { 802 return; 803 } 804 805 if (migratedTo70) { 806 // Lowercase the servicename 807 serviceName = serviceName.toLowerCase(); 808 try { 809 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 810 orgDN); 811 if (cEntry.isDirty()) { 812 cEntry.refresh(); 813 } 814 SMSEntry e = cEntry.getClonedSMSEntry(); 815 ServiceSchemaManager ssm = new ServiceSchemaManager( 816 serviceName, token); 817 ServiceSchema ss = ssm.getOrganizationCreationSchema(); 818 if (ss == null) { 819 throw (new SMSException(SMSEntry.bundle 820 .getString("sms-SMSSchema_service_notfound"), 821 "sms-SMSSchema_service_notfound")); 822 } 823 824 Map map = new HashMap(2); 825 Set newValues = new HashSet(values); 826 Map allAttributes = ss.getAttributeDefaults(); 827 Set existingValues = (Set)allAttributes.get(attrName); 828 if ((existingValues != null) && !existingValues.isEmpty()) { 829 newValues.addAll(existingValues); 830 } 831 map.put(attrName, newValues); 832 ss.validateAttributes(map); 833 SMSUtils.addAttribute(e, serviceName + "-" + attrName, 834 values, ss.getSearchableAttributeNames()); 835 e.save(token); 836 cEntry.refresh(e); 837 } catch (SSOException ssoe) { 838 SMSEntry.debug.error("OrganizationConfigManager: Unable " 839 + "to add Attribute Values", ssoe); 840 throw (new SMSException(SMSEntry.bundle 841 .getString(SMS_INVALID_SSO_TOKEN), 842 SMS_INVALID_SSO_TOKEN)); 843 } 844 } 845 846 // If in coexistMode and serviceName is idRepoService 847 // add the attributes to AMSDK organization 848 if (coexistMode 849 && serviceName 850 .equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) { 851 amsdk.addAttributeValues(attrName, values); 852 } 853 } 854 855 /** 856 * Sets/Creates organization attributes for the 857 * service. If the attributes already exists, the given attribute values 858 * will replace them. 859 * 860 * @param serviceName 861 * name of the service. 862 * @param attributes 863 * attribute-values pairs. 864 * @throws SMSException 865 * if the serviceName cannot be found. 866 */ 867 public void setAttributes(String serviceName, Map attributes) 868 throws SMSException { 869 validateConfigImpl(); 870 if (serviceName == null) { 871 return; 872 } 873 874 if (migratedTo70) { 875 // Lowercase the serviceName 876 serviceName = serviceName.toLowerCase(); 877 try { 878 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 879 orgDN); 880 if (cEntry.isDirty()) { 881 cEntry.refresh(); 882 } 883 SMSEntry e = cEntry.getClonedSMSEntry(); 884 if ((attributes != null) && (!attributes.isEmpty())) { 885 // Validate the attributes 886 ServiceSchemaManager ssm = new ServiceSchemaManager( 887 serviceName, token); 888 ServiceSchema ss = ssm.getOrganizationCreationSchema(); 889 ss.validateAttributes(attributes); 890 891 // Normalize the attributes with service name 892 Map attrsMap = new HashMap(); 893 Iterator itr = attributes.keySet().iterator(); 894 while (itr.hasNext()) { 895 String name = (String) itr.next(); 896 Set values = (Set) attributes.get(name); 897 /* 898 * To make the attributes qualified by service name we 899 * prefix the attribute names with the service name. 900 */ 901 attrsMap.put(serviceName + "-" + name, values); 902 } 903 904 // Look for old attrs. in the storage and add them too. 905 Map oldAttrs = getAttributes(serviceName); 906 Iterator it = oldAttrs.keySet().iterator(); 907 while (it.hasNext()) { 908 String skey = (String) it.next(); 909 if (!attributes.containsKey(skey)) 910 attrsMap.put(serviceName + "-" + skey, oldAttrs 911 .get(skey)); 912 } 913 914 // Set the attributes in SMSEntry 915 SMSUtils.setAttributeValuePairs(e, attrsMap, ss 916 .getSearchableAttributeNames()); 917 918 String dataStore = SMSEntry.getDataStore(token); 919 // Add these OCs only for SunOne DS. Do not add the 920 // OCs for Active Directory. 921 // Will get WILL_NOT_PERFORM in AD. 922 if ((dataStore != null) && !dataStore.equals( 923 SMSEntry.DATASTORE_ACTIVE_DIR) 924 ) { 925 // This is for storing organization attributes 926 // in top/default realm node. eg.,ou=services,o=isp 927 if (e.getDN().equalsIgnoreCase(SERVICES_NODE)) { 928 String[] ocVals = e 929 .getAttributeValues(SMSEntry.ATTR_OBJECTCLASS); 930 boolean exists = false; 931 for (int ic = 0; ocVals != null 932 && ic < ocVals.length; ic++) 933 { 934 if (ocVals[ic].startsWith( 935 SMSEntry.OC_SERVICE_COMP)) { 936 // OC needs to be added outside the for loop 937 // else will throw concurrent mod exception 938 exists = true; 939 break; 940 } 941 } 942 if (!exists) { 943 e.addAttribute(SMSEntry.ATTR_OBJECTCLASS, 944 SMSEntry.OC_SERVICE_COMP); 945 } 946 } else if (e.getDN().startsWith( 947 SMSEntry.ORGANIZATION_RDN + SMSEntry.EQUALS)) { 948 // This is for storing organization attributes in 949 // organizations created via sdk through realm 950 // console. 951 String[] vals = e 952 .getAttributeValues(SMSEntry.ATTR_OBJECTCLASS); 953 boolean rsvcExists = false; 954 for (int n = 0; vals != null && n < vals.length; 955 n++) { 956 if (vals[n].equalsIgnoreCase( 957 SMSEntry.OC_REALM_SERVICE)) 958 { 959 // OC needs to be added outside the for loop 960 // else will throw concurrent mod exception 961 rsvcExists = true; 962 break; 963 } 964 } 965 if (!rsvcExists) { 966 e.addAttribute(SMSEntry.ATTR_OBJECTCLASS, 967 SMSEntry.OC_REALM_SERVICE); 968 } 969 } 970 } 971 972 // Save in backend data store and refresh the cache 973 e.save(token); 974 cEntry.refresh(e); 975 } 976 977 } catch (SSOException ssoe) { 978 SMSEntry.debug.error("OrganizationConfigManager: Unable " 979 + "to set Attributes", ssoe); 980 throw (new SMSException(SMSEntry.bundle 981 .getString(SMS_INVALID_SSO_TOKEN), 982 SMS_INVALID_SSO_TOKEN)); 983 } 984 } 985 986 // If in coexistMode and serviceName is idRepoService 987 // set the attributes to AMSDK organization 988 if ((coexistMode || (realmEnabled && isCopyOrgEnabled())) 989 && serviceName 990 .equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) { 991 amsdk.setAttributes(attributes); 992 } 993 } 994 995 /** 996 * Removes the given organization creation attribute 997 * for the service. 998 * 999 * @param serviceName 1000 * name of service. 1001 * @param attrName 1002 * name of attribute. 1003 * @throws SMSException 1004 * if the organization attribute for the service to be removed 1005 * cannot be found, or if the service name cannot be found. 1006 */ 1007 public void removeAttribute(String serviceName, String attrName) 1008 throws SMSException { 1009 validateConfigImpl(); 1010 if (serviceName == null || attrName == null) { 1011 return; 1012 } 1013 1014 if (migratedTo70) { 1015 try { 1016 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 1017 orgDN); 1018 if (cEntry.isDirty()) { 1019 cEntry.refresh(); 1020 } 1021 SMSEntry e = cEntry.getClonedSMSEntry(); 1022 SMSUtils.removeAttribute(e, serviceName.toLowerCase() + "-" 1023 + attrName); 1024 e.save(token); 1025 cEntry.refresh(e); 1026 } catch (SSOException ssoe) { 1027 SMSEntry.debug.error("OrganizationConfigManager: Unable " 1028 + "to remove Attribute", ssoe); 1029 throw (new SMSException(SMSEntry.bundle 1030 .getString(SMS_INVALID_SSO_TOKEN), 1031 SMS_INVALID_SSO_TOKEN)); 1032 } 1033 } 1034 1035 // If in coexistMode and serviceName is idRepoService 1036 // remove the attributes to AMSDK organization 1037 if (coexistMode 1038 && serviceName 1039 .equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) { 1040 amsdk.removeAttribute(attrName); 1041 } 1042 } 1043 1044 /** 1045 * Removes the given organization creation attribute 1046 * values for the service. 1047 * 1048 * @param serviceName 1049 * name of service. 1050 * @param attrName 1051 * name of attribute. 1052 * @param values 1053 * attribute values to be removed. 1054 * @throws SMSException 1055 * if the organization attribute for the service to be removed 1056 * cannot be found, or if the service name cannot be found, or 1057 * if the value cannot be removed. 1058 */ 1059 public void removeAttributeValues(String serviceName, String attrName, 1060 Set values) throws SMSException { 1061 validateConfigImpl(); 1062 if (serviceName == null || attrName == null) { 1063 return; 1064 } 1065 if (migratedTo70) { 1066 try { 1067 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 1068 orgDN); 1069 if (cEntry.isDirty()) { 1070 cEntry.refresh(); 1071 } 1072 SMSEntry e = cEntry.getClonedSMSEntry(); 1073 ServiceSchemaManager ssm = new ServiceSchemaManager( 1074 serviceName, token); 1075 ServiceSchema ss = ssm.getOrganizationCreationSchema(); 1076 Map map = new HashMap(2); 1077 map.put(attrName, values); 1078 ss.validateAttributes(map); 1079 SMSUtils.removeAttributeValues(e, serviceName.toLowerCase() 1080 + "-" + attrName, values, ss 1081 .getSearchableAttributeNames()); 1082 e.save(token); 1083 cEntry.refresh(e); 1084 1085 } catch (SSOException ssoe) { 1086 SMSEntry.debug.error("OrganizationConfigManager: Unable " 1087 + "to remove Attribute Values", ssoe); 1088 throw (new SMSException(SMSEntry.bundle 1089 .getString(SMS_INVALID_SSO_TOKEN), 1090 SMS_INVALID_SSO_TOKEN)); 1091 } 1092 } 1093 1094 // If in coexistMode and serviceName is idRepoService 1095 // remove the attributes to AMSDK organization 1096 if (coexistMode 1097 && serviceName 1098 .equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) { 1099 amsdk.removeAttributeValues(attrName, values); 1100 } 1101 } 1102 1103 /** 1104 * Returns the service configuration object for the 1105 * given service name. 1106 * 1107 * @param serviceName 1108 * name of a service. 1109 * @return service configuration object for the service. 1110 * @throws SMSException 1111 * if there is an error accessing the data store to read the 1112 * service configuration, or if the service name cannot be 1113 * found. 1114 */ 1115 public ServiceConfig getServiceConfig(String serviceName) 1116 throws SMSException { 1117 try { 1118 ServiceConfigManager scmgr = new ServiceConfigManager(serviceName, 1119 token); 1120 ServiceConfig scg = scmgr.getOrganizationConfig(orgName, null); 1121 return (scg); 1122 } catch (SSOException ssoe) { 1123 SMSEntry.debug.error("OrganizationConfigManager: Unable to " 1124 + "get Service Config", ssoe); 1125 throw (new SMSException(SMSEntry.bundle 1126 .getString(SMS_INVALID_SSO_TOKEN), 1127 SMS_INVALID_SSO_TOKEN)); 1128 } 1129 } 1130 1131 ServiceSchema getServiceSchema(String serviceName) throws SMSException { 1132 try { 1133 return new ServiceSchemaManager(serviceName, token).getOrganizationSchema(); 1134 } catch (SSOException ssoe) { 1135 SMSEntry.debug.error("OrganizationConfigManager: Unable to get Service Schema", ssoe); 1136 throw new SMSException(SMSEntry.bundle.getString(SMS_INVALID_SSO_TOKEN), SMS_INVALID_SSO_TOKEN); 1137 } 1138 } 1139 1140 /** 1141 * Adds a service configuration object for the given 1142 * service name for this organization. If the service has been already added 1143 * a <code>SMSException</code> will be thrown. 1144 * 1145 * @param serviceName 1146 * name of the service. 1147 * @param attributes 1148 * service configuration attributes. 1149 * @return service configuration object. 1150 * @throws SMSException 1151 * if the service configuration has been added already. 1152 */ 1153 public ServiceConfig addServiceConfig(String serviceName, Map attributes) 1154 throws SMSException { 1155 try { 1156 ServiceConfigManagerImpl scmi = ServiceConfigManagerImpl 1157 .getInstance(token, serviceName, 1158 ServiceManager.getVersion(serviceName)); 1159 ServiceConfigImpl sci = scmi.getOrganizationConfig(token, orgName, 1160 null); 1161 if (sci == null || sci.isNewEntry()) { 1162 ServiceConfigManager scm = new ServiceConfigManager( 1163 serviceName, token); 1164 return (scm.createOrganizationConfig(orgName, attributes)); 1165 } else { 1166 SMSEntry.debug.error("OrganizationConfigManager: " 1167 + "ServiceConfig already exists: " + sci.getDN()); 1168 throw (new SMSException(SMSEntry.bundle 1169 .getString("sms-service_already_exists1"))); 1170 } 1171 } catch (SSOException ssoe) { 1172 SMSEntry.debug.error("OrganizationConfigManager: Unable to " 1173 + "add Service Config", ssoe); 1174 throw (new SMSException(SMSEntry.bundle 1175 .getString(SMS_INVALID_SSO_TOKEN), 1176 SMS_INVALID_SSO_TOKEN)); 1177 } 1178 } 1179 1180 /** 1181 * Removes the service configuration object for the 1182 * given service name for this organization. 1183 * 1184 * @param serviceName 1185 * name of the service. 1186 * @throws SMSException 1187 * if the service name cannot be found, or not added to the 1188 * organization. 1189 */ 1190 public void removeServiceConfig(String serviceName) throws SMSException { 1191 try { 1192 ServiceConfigManager scm = new ServiceConfigManager(serviceName, 1193 token); 1194 scm.deleteOrganizationConfig(orgName); 1195 } catch (SSOException ssoe) { 1196 SMSEntry.debug.error("OrganizationConfigManager: Unable to " 1197 + "delete Service Config", ssoe); 1198 throw (new SMSException(SMSEntry.bundle 1199 .getString(SMS_INVALID_SSO_TOKEN), 1200 SMS_INVALID_SSO_TOKEN)); 1201 } 1202 } 1203 1204 /** 1205 * Registers for changes to organization's 1206 * configuration. The object will be called when configuration for this 1207 * organization is changed. 1208 * 1209 * @param listener 1210 * callback object that will be invoked when organization 1211 * configuration has changed 1212 * @return an ID of the registered listener. 1213 */ 1214 public String addListener(ServiceListener listener) { 1215 return (orgConfigImpl.addListener(listener)); 1216 } 1217 1218 /** 1219 * Removes the listener from the organization for the 1220 * given listener ID. The ID was issued when the listener was registered. 1221 * 1222 * @param listenerID 1223 * the listener ID issued when the listener was registered 1224 */ 1225 public void removeListener(String listenerID) { 1226 orgConfigImpl.removeListener(listenerID); 1227 } 1228 1229 /** 1230 * Returns normalized DN for realm model 1231 */ 1232 private static String normalizeDN(String subOrgName, String orgDN) { 1233 // Return orgDN if subOrgName is either null or empty 1234 if (subOrgName == null || subOrgName.length() == 0) { 1235 return (orgDN); 1236 } 1237 if (SMSEntry.debug.messageEnabled()) { 1238 SMSEntry.debug.message("OrganizationConfigManager." 1239 + "normalizeDN()-subOrgName " + subOrgName); 1240 } 1241 String subOrgDN = null; 1242 if (LDAPUtils.isDN(subOrgName) && (!subOrgName.startsWith("///"))) { 1243 int ndx = subOrgName.lastIndexOf(DNMapper.serviceDN); 1244 if (ndx == -1) { 1245 // Check for baseDN 1246 ndx = subOrgName.lastIndexOf(SMSEntry.getRootSuffix()); 1247 } 1248 if (ndx > 0) { 1249 subOrgName = subOrgName.substring(0, ndx - 1); 1250 } 1251 subOrgDN = DNMapper.normalizeDN(subOrgName) + orgDN; 1252 } else if (subOrgName.indexOf('/') != -1) { 1253 String tmp = DNMapper.convertToDN(subOrgName).toString(); 1254 if (SMSEntry.debug.messageEnabled()) { 1255 SMSEntry.debug.message("OrganizationConfigManager." 1256 + "normalizeDN()-slashConvertedString: " + tmp); 1257 } 1258 if (tmp != null && tmp.length() > 0) { 1259 if (tmp.charAt(tmp.length() - 1) == ',') { 1260 subOrgDN = tmp + DNMapper.serviceDN; 1261 } else { 1262 int dx = tmp.indexOf(SMSEntry.COMMA); 1263 if (dx >= 0) { 1264 subOrgDN = tmp + SMSEntry.COMMA + DNMapper.serviceDN; 1265 } else { 1266 subOrgDN = tmp + SMSEntry.COMMA + orgDN; 1267 } 1268 } 1269 } else { 1270 subOrgDN = orgDN; 1271 } 1272 } else if (subOrgName.startsWith(SMSEntry.SUN_INTERNAL_REALM_NAME)) { 1273 subOrgDN = SMSEntry.ORG_PLACEHOLDER_RDN + subOrgName 1274 + SMSEntry.COMMA + DNMapper.serviceDN; 1275 } else { 1276 if (coexistMode) { 1277 subOrgDN = orgNamingAttrInLegacyMode + SMSEntry.EQUALS 1278 + subOrgName + SMSEntry.COMMA 1279 + DNMapper.realmNameToAMSDKName(orgDN); 1280 } else { 1281 subOrgDN = SMSEntry.ORG_PLACEHOLDER_RDN + subOrgName 1282 + SMSEntry.COMMA + orgDN; 1283 } 1284 } 1285 if (SMSEntry.debug.messageEnabled()) { 1286 SMSEntry.debug.message("OrganizationConfigManager::" 1287 + "normalizeDN() suborgdn " + subOrgDN); 1288 } 1289 return (subOrgDN); 1290 } 1291 1292 /** 1293 * Returns all service names configured for AM 1294 */ 1295 static Set getServiceNames(SSOToken token) throws SMSException, 1296 SSOException { 1297 // Get the service names from ServiceManager 1298 CachedSubEntries cse = CachedSubEntries.getInstance(token, 1299 DNMapper.serviceDN); 1300 return (cse.getSubEntries(token)); 1301 } 1302 1303 /** 1304 * Returns a set of service names that can be assigned 1305 * to a realm. This set excludes name of services that are already assigned 1306 * to the realm and services that are required for the existence of a realm. 1307 * 1308 * @return a set of service names that can be assigned to a realm. 1309 * @throws SMSException 1310 * if there is an error accessing the data store to read the 1311 * service configuration 1312 */ 1313 public Set<String> getAssignableServices() throws SMSException { 1314 // Get all service names, and remove the assigned services 1315 // Set containing service names that has organization schema 1316 Set orgSchemaServiceNames = new HashSet(); 1317 try { 1318 for (Iterator names = getServiceNames(token).iterator(); names 1319 .hasNext();) { 1320 String serviceName = (String) names.next(); 1321 ServiceSchemaManagerImpl ssmi = ServiceSchemaManagerImpl 1322 .getInstance(token, serviceName, 1323 ServiceManager.getVersion(serviceName)); 1324 if (ssmi.getSchema(SchemaType.ORGANIZATION) != null) { 1325 // Need to check if the user has permission 1326 // to add/assign the service 1327 StringBuilder d = new StringBuilder(100); 1328 // Need to construct 1329 // "ou=default,ou=organizationconfig,ou=1.0,ou=" 1330 d.append(SMSEntry.PLACEHOLDER_RDN).append(SMSEntry.EQUALS) 1331 .append(SMSUtils.DEFAULT).append(SMSEntry.COMMA) 1332 .append(CreateServiceConfig.ORG_CONFIG_NODE) 1333 .append(SMSEntry.PLACEHOLDER_RDN).append( 1334 SMSEntry.EQUALS).append("1.0").append( 1335 SMSEntry.COMMA).append( 1336 SMSEntry.PLACEHOLDER_RDN).append( 1337 SMSEntry.EQUALS); 1338 // Append service name, and org name 1339 d.append(serviceName); 1340 if (!orgDN.equalsIgnoreCase(DNMapper.serviceDN)) { 1341 d.append(SMSEntry.COMMA).append(SMSEntry.SERVICES_RDN); 1342 } 1343 d.append(SMSEntry.COMMA).append(orgDN); 1344 try { 1345 // The function will throw exception if 1346 // user does not have permissions 1347 SMSEntry.getDelegationPermission(token, d.toString(), 1348 SMSEntry.modifyActionSet); 1349 orgSchemaServiceNames.add(serviceName); 1350 } catch (SMSException smse) { 1351 if (smse.getExceptionCode() != 1352 SMSException.STATUS_NO_PERMISSION) 1353 { 1354 throw (smse); 1355 } 1356 } 1357 } 1358 } 1359 // Need to remove mandatory services 1360 // %%% TODO. Need to have SMS Service with this information 1361 // orgSchemaServiceNames.removeAll(getMandatoryServices()); 1362 } catch (SSOException ssoe) { 1363 SMSEntry.debug.error("OrganizationConfigManager." 1364 + "getAssignableServices(): SSOException", ssoe); 1365 throw (new SMSException(SMSEntry.bundle 1366 .getString(SMS_INVALID_SSO_TOKEN), 1367 SMS_INVALID_SSO_TOKEN)); 1368 } 1369 // Remove assigned services 1370 HashSet answer = new HashSet(orgSchemaServiceNames); 1371 answer.removeAll(getAssignedServices()); 1372 return (answer); 1373 } 1374 1375 /** 1376 * Returns a set of service names that are assigned to 1377 * a realm. 1378 * 1379 * @return a set of service names that are assigned to a realm. 1380 * @throws SMSException 1381 * if there is an error accessing the data store to read the 1382 * service configuration 1383 */ 1384 public Set<String> getAssignedServices() throws SMSException { 1385 return (getAssignedServices(true)); 1386 } 1387 1388 /** 1389 * Returns a set of service names that are assigned to a realm. 1390 * 1391 * @param includeMandatory 1392 * <code>true</code> to include mandatory service names. 1393 * @return a set of service names that are assigned to a realm. 1394 * @throws SMSException 1395 * if there is an error accessing the data store to read the 1396 * service configuration 1397 */ 1398 public Set<String> getAssignedServices(boolean includeMandatory) 1399 throws SMSException { 1400 validateConfigImpl(); 1401 Set<String> assignedServices = Collections.EMPTY_SET; 1402 if (coexistMode) { 1403 // Get assigned services from OrgConfigViaAMSDK 1404 assignedServices = amsdk.getAssignedServices(); 1405 } else { 1406 // Get assigned service names from OrganizationConfigManagerImpl 1407 assignedServices = orgConfigImpl.getAssignedServices(token); 1408 } 1409 if (!includeMandatory) { 1410 // Get services assigned by default 1411 Set ds = ServiceManager.requiredServices(); 1412 assignedServices.removeAll(ds); 1413 } 1414 return (assignedServices); 1415 } 1416 1417 /** 1418 * Assigns the given service to the orgnization with 1419 * the respective attributes. If the service has been already added a <code> 1420 * SMSException</code> 1421 * will be thrown. 1422 * 1423 * @param serviceName 1424 * name of the service 1425 * @param attributes 1426 * service configuration attributes 1427 * @throws SMSException 1428 * if the service configuration has been added already. 1429 */ 1430 public void assignService(String serviceName, Map attributes) 1431 throws SMSException { 1432 addServiceConfig(serviceName, attributes); 1433 } 1434 1435 /** 1436 * Returns attributes configured for the service. 1437 * 1438 * @param serviceName 1439 * name of the service 1440 * @return a map of attributes for the service 1441 * @throws SMSException 1442 * if there is an error accessing the data store to read the 1443 * service configuration, or if the service name cannot be 1444 * found. 1445 */ 1446 public Map getServiceAttributes(String serviceName) throws SMSException { 1447 ServiceConfig scg = getServiceConfig(serviceName); 1448 if (scg == null) { 1449 Object args[] = { serviceName }; 1450 SMSEntry.debug.error( 1451 "OrganizationConfigManager.getServiceAttributes() Unable " + 1452 "to get service attributes. "); 1453 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 1454 "sms-no-organization-schema", 1455 args)); 1456 1457 } 1458 return (scg.getAttributes()); 1459 } 1460 1461 /** 1462 * Unassigns the service from the organization. 1463 * 1464 * @param serviceName 1465 * name of the service 1466 * @throws SMSException 1467 * if the service name cannot be found or assigned, or if the 1468 * service is a mandatory service. 1469 */ 1470 public void unassignService(String serviceName) throws SMSException { 1471 // if (coexistMode) { 1472 // amsdk.unassignService(serviceName); 1473 // } else { 1474 removeServiceConfig(serviceName); 1475 // } 1476 } 1477 1478 /** 1479 * Sets the attributes related to provided service. 1480 * The assumption is that the service is already assigned to the 1481 * organization. The attributes for the service are validated against the 1482 * service schema. 1483 * 1484 * @param serviceName 1485 * name of the service 1486 * @param attributes 1487 * attributes of the service 1488 * @throws SMSException 1489 * if the service name cannot be found or not assigned to the 1490 * organization. 1491 */ 1492 public void modifyService(String serviceName, Map attributes) 1493 throws SMSException { 1494 try { 1495 getServiceConfig(serviceName).setAttributes(attributes); 1496 } catch (SSOException ssoe) { 1497 SMSEntry.debug.error("OrganizationConfigManager.modifyService " 1498 + "SSOException in modify service ", ssoe); 1499 throw (new SMSException(SMSEntry.bundle 1500 .getString(SMS_INVALID_SSO_TOKEN), 1501 SMS_INVALID_SSO_TOKEN)); 1502 } 1503 } 1504 1505 public String getNamingAttrForOrg() { 1506 return OrgConfigViaAMSDK.getNamingAttrForOrg(); 1507 } 1508 1509 /** 1510 * Returns the <code>OrganizationConfigManager</code> 1511 * of the parent for the given organization name. 1512 * 1513 * @return the configuration manager of the parent for the given 1514 * organization. 1515 * @throws SMSException 1516 * if user doesn't have access to that organization. 1517 */ 1518 public OrganizationConfigManager getParentOrgConfigManager() 1519 throws SMSException { 1520 OrganizationConfigManager ocm = null; 1521 String parentDN = null; 1522 if (LDAPUtils.isDN(orgDN)) { 1523 if (orgDN.equalsIgnoreCase(DNMapper.serviceDN)) { 1524 return (this); 1525 } 1526 parentDN = DN.valueOf(orgDN).parent().toString(); 1527 if (SMSEntry.debug.messageEnabled()) { 1528 SMSEntry.debug.message("OrganizationConfigManager." 1529 + "getParentOrgConfigManager() parentDN : " + parentDN); 1530 } 1531 if (parentDN != null && parentDN.length() > 0) { 1532 ocm = new OrganizationConfigManager(token, parentDN); 1533 } 1534 } 1535 return ocm; 1536 } 1537 1538 /** 1539 * Loads default services to a newly created realm 1540 */ 1541 public static void loadDefaultServices(SSOToken token, 1542 OrganizationConfigManager ocm) throws SMSException { 1543 // Check if DIT has been migrated to 7.0 1544 if (!migratedTo70) { 1545 return; 1546 } 1547 Set defaultServices = ServiceManager.servicesAssignedByDefault(); 1548 // Load the default services automatically 1549 OrganizationConfigManager parentOrg = ocm.getParentOrgConfigManager(); 1550 if (defaultServices == null) { 1551 // There are no services to be loaded 1552 return; 1553 } 1554 1555 Set assignedServices = new CaseInsensitiveHashSet( 1556 parentOrg.getAssignedServices()); 1557 if (SMSEntry.debug.messageEnabled()) { 1558 SMSEntry.debug.message("OrganizationConfigManager" 1559 + "::loadDefaultServices " + "assignedServices : " 1560 + assignedServices); 1561 } 1562 boolean doAuthServiceLater = false; 1563 boolean doAuthHttpBasicLater = false; 1564 String serviceName = null; 1565 1566 // Copy service configuration 1567 Iterator items = defaultServices.iterator(); 1568 while (items.hasNext() || doAuthHttpBasicLater || doAuthServiceLater) { 1569 if (items.hasNext()) { 1570 serviceName = (String) items.next(); 1571 if (serviceName.equals(ISAuthConstants.AUTH_SERVICE_NAME)) { 1572 doAuthServiceLater = true; 1573 continue; 1574 } else if (serviceName.equals( 1575 ISAuthConstants.AUTH_HTTP_BASIC_SERVICE_NAME)) { 1576 1577 doAuthHttpBasicLater = true; 1578 continue; 1579 } 1580 } else if (doAuthHttpBasicLater) { 1581 serviceName = ISAuthConstants.AUTH_HTTP_BASIC_SERVICE_NAME; 1582 doAuthHttpBasicLater = false; 1583 } else if (doAuthServiceLater) { 1584 serviceName = ISAuthConstants.AUTH_SERVICE_NAME; 1585 doAuthServiceLater = false; 1586 } 1587 if (SMSEntry.debug.messageEnabled()) { 1588 SMSEntry.debug.message("OrganizationConfigManager" + 1589 "::loadDefaultServices:ServiceName " + serviceName); 1590 } 1591 try { 1592 ServiceConfig sc = parentOrg.getServiceConfig(serviceName); 1593 ServiceSchema ss = parentOrg.getServiceSchema(serviceName); 1594 Map attrs = null; 1595 if (sc != null && assignedServices.contains(serviceName)) { 1596 attrs = sc.getAttributesWithoutDefaults(); 1597 if (SMSEntry.debug.messageEnabled()) { 1598 SMSEntry.debug 1599 .message("OrganizationConfigManager" 1600 + "::loadDefaultServices " 1601 + "Copying service from parent: " 1602 + serviceName); 1603 } 1604 ServiceConfig scn = ocm 1605 .addServiceConfig(serviceName, attrs); 1606 // Copy sub-configurations, if any 1607 copySubConfig(sc, scn, ss); 1608 } 1609 } catch (SSOException ssoe) { 1610 if (SMSEntry.debug.messageEnabled()) { 1611 SMSEntry.debug.message( 1612 "OrganizationConfigManager.loadDefaultServices " + 1613 "SSOException in loading default services ", 1614 ssoe); 1615 } 1616 throw (new SMSException(SMSEntry.bundle 1617 .getString(SMS_INVALID_SSO_TOKEN), 1618 SMS_INVALID_SSO_TOKEN)); 1619 } 1620 } 1621 } 1622 1623 1624 /** 1625 * Registers default services to newly created suborganizations. 1626 */ 1627 private void registerSvcsForOrg(String subOrgName, String subOrgDN) 1628 { 1629 try { 1630 Set defaultServices = 1631 ServiceManager.servicesAssignedByDefault(); 1632 if (SMSEntry.debug.messageEnabled()) { 1633 SMSEntry.debug.message("OrganizationConfigManager::"+ 1634 "registerSvcsForOrg. "+ 1635 "defaultServices : " + defaultServices); 1636 } 1637 1638 // Register the default services to the newly created orgs,so 1639 // they will be marked with the OC sunRegisteredServiceName. 1640 if (defaultServices != null) { 1641 Set assignedServices = amsdk.getAssignedServices(); 1642 if (SMSEntry.debug.messageEnabled()) { 1643 SMSEntry.debug.message("OrganizationConfigManager::" + 1644 "registerSvcsForOrg:assignedServices: " + 1645 assignedServices); 1646 } 1647 Iterator items = defaultServices.iterator(); 1648 String serviceName = null; 1649 if (SMSEntry.getRootSuffix().equalsIgnoreCase( 1650 SMSEntry.getAMSdkBaseDN())) { 1651 amsdk = new OrgConfigViaAMSDK(token, 1652 orgNamingAttrInLegacyMode + SMSEntry.EQUALS + 1653 subOrgName + SMSEntry.COMMA + 1654 DNMapper.realmNameToAMSDKName(orgDN), subOrgDN); 1655 } else { 1656 amsdk = new OrgConfigViaAMSDK(token, 1657 orgNamingAttrInLegacyMode + SMSEntry.EQUALS + 1658 subOrgName + SMSEntry.COMMA + amSDKOrgDN, subOrgDN); 1659 } 1660 while (items.hasNext()) { 1661 serviceName = (String) items.next(); 1662 if (assignedServices.contains(serviceName)) { 1663 if (SMSEntry.debug.messageEnabled()) { 1664 SMSEntry.debug.message( 1665 "OrganizationConfigManager::"+ 1666 "registerSvcsForOrg:ServiceName : " + 1667 serviceName); 1668 } 1669 amsdk.assignService(serviceName); 1670 } 1671 } 1672 } 1673 } catch (SMSException smse) { 1674 // Unable to load default services 1675 if (SMSEntry.debug.warningEnabled()) { 1676 SMSEntry.debug.warning("OrganizationConfigManager::" + 1677 "registerSvcsForOrg. " + 1678 "SMSException in registering services: ", smse); 1679 } 1680 } 1681 } 1682 1683 /** 1684 * Copies service configurations recursively from source to destination 1685 */ 1686 static void copySubConfig(ServiceConfig from, ServiceConfig to, ServiceSchema serviceSchema) 1687 throws SMSException, SSOException { 1688 Set subConfigNames = from.getSubConfigNames(); 1689 for (Iterator items = subConfigNames.iterator(); items.hasNext();) { 1690 String subConfigName = (String) items.next(); 1691 ServiceConfig scf = from.getSubConfig(subConfigName); 1692 ServiceSchema subSchema = serviceSchema.getSubSchema(scf.getSchemaID()); 1693 if (subSchema.isRealmCloneable()) { 1694 to.addSubConfig(subConfigName, scf.getSchemaID(), scf.getPriority(), scf.getAttributesWithoutDefaults()); 1695 ServiceConfig sct = to.getSubConfig(subConfigName); 1696 copySubConfig(scf, sct, subSchema); 1697 } 1698 } 1699 } 1700 1701 1702 /** 1703 * Determines whether an organization ought to be created for each 1704 * realm in realm only mode of installation based on the boolean flag 1705 * in amSDK plugin. 1706 * This requirement is for portal customers. 1707 */ 1708 protected boolean isCopyOrgEnabled() { 1709 if (copyOrgInitialized) { 1710 return (copyOrgEnabled); 1711 } 1712 if (SMSEntry.debug.messageEnabled()) { 1713 SMSEntry.debug.message("OrganizationConfigManager: "+ 1714 "in isCopyOrgEnabled() "); 1715 } 1716 // Check if AMSDK is configured for the realm 1717 try { 1718 ServiceConfig s = getServiceConfig(ServiceManager.REALM_SERVICE); 1719 if (s != null) { 1720 Iterator items = s.getSubConfigNames().iterator(); 1721 while (items.hasNext()) { 1722 String name = items.next().toString(); 1723 ServiceConfig subConfig = s.getSubConfig(name); 1724 if (subConfig == null) { 1725 SMSEntry.debug.error("OrganizationConfigManager.is" + 1726 "CopyOrgEnabled. SubConfig is NULL: " + 1727 "SC Name: " + name + " For org: " + orgDN); 1728 return (false); 1729 } 1730 if (subConfig.getSchemaID().equalsIgnoreCase( 1731 IdConstants.AMSDK_PLUGIN_NAME)) { 1732 Map configMap = subConfig.getAttributes(); 1733 if ((configMap != null) && !configMap.isEmpty()) { 1734 // Get the amsdkOrgName from the amSDKRepo to build 1735 // OrgConfigViaSDK instance. 1736 Set orgs = (Set) configMap.get("amSDKOrgName"); 1737 if (orgs != null && !orgs.isEmpty()) { 1738 amSDKOrgDN = (String) orgs.iterator().next(); 1739 Set cfgs = (Set) configMap.get(CONF_ENABLED); 1740 if ( (cfgs != null) && (!cfgs.isEmpty()) && 1741 (cfgs.contains("true")) && 1742 (amSDKOrgDN !=null) ) { 1743 amsdk = new OrgConfigViaAMSDK(token, 1744 amSDKOrgDN, orgDN); 1745 if (orgNamingAttrInLegacyMode == null) { 1746 orgNamingAttrInLegacyMode = 1747 getNamingAttrForOrg(); 1748 } 1749 copyOrgEnabled = true; 1750 } 1751 break; 1752 } 1753 } 1754 } 1755 } 1756 } 1757 } catch (SSOException sse) { 1758 // Use default values i.e., false 1759 if (SMSEntry.debug.messageEnabled()) { 1760 SMSEntry.debug.message("OrganizationConfigManager:" + 1761 "isCopyOrgEnabled() Unable to get service: " + 1762 ServiceManager.REALM_SERVICE, sse); 1763 } 1764 } catch (SMSException e) { 1765 // Use default values i.e., false 1766 if (SMSEntry.debug.messageEnabled()) { 1767 SMSEntry.debug.message("OrganizationConfigManager:" + 1768 "isCopyOrgEnabled() Unable to get service: " + 1769 ServiceManager.REALM_SERVICE, e); 1770 } 1771 } 1772 copyOrgInitialized = true; 1773 if (SMSEntry.debug.messageEnabled()) { 1774 SMSEntry.debug.message("OrganizationConfigManager: "+ 1775 "copyOrgEnabled == " + copyOrgEnabled); 1776 } 1777 return (copyOrgEnabled); 1778 } 1779 1780 static void initializeFlags() { 1781 realmEnabled = ServiceManager.isRealmEnabled(); 1782 coexistMode = ServiceManager.isCoexistenceMode(); 1783 migratedTo70 = ServiceManager.isConfigMigratedTo70(); 1784 } 1785 1786 void validateConfigImpl() throws SMSException { 1787 // Instantiate the OrgConfigImpl and cache it 1788 if ((orgConfigImpl == null) || !orgConfigImpl.isValid()) { 1789 try { 1790 orgConfigImpl = OrganizationConfigManagerImpl.getInstance( 1791 token, orgName); 1792 } catch (SSOException ssoe) { 1793 throw (new SMSException(ssoe, SMS_INVALID_SSO_TOKEN)); 1794 } 1795 } 1796 } 1797 1798 class OrganizationConfigManagerListener implements ServiceListener { 1799 public void schemaChanged(String serviceName, String version) { 1800 // Call ServiceManager to notify 1801 ServiceManager.schemaChanged(); 1802 // If naming service has changed, reload the AM Servers 1803 if (serviceName.equalsIgnoreCase(ServiceManager.PLATFORM_SERVICE)) { 1804 ServiceManager.accessManagerServers = null; 1805 } 1806 } 1807 1808 public void globalConfigChanged(String serviceName, String version, 1809 String groupName, String serviceComponent, int type) { 1810 if (serviceName.equalsIgnoreCase(ServiceManager.REALM_SERVICE)) { 1811 try { 1812 ServiceManager.checkFlags(token); 1813 } catch (SSOException ssoe) { 1814 SMSEntry.debug.error("OrganizationConfigManager: " 1815 + "globalConfigChanged ", ssoe); 1816 } catch (SMSException smse) { 1817 SMSEntry.debug.error("OrganizationConfigManager: " 1818 + "globalConfigChanged ", smse); 1819 } 1820 realmEnabled = ServiceManager.isRealmEnabled(); 1821 coexistMode = ServiceManager.isCoexistenceMode(); 1822 migratedTo70 = ServiceManager.isConfigMigratedTo70(); 1823 } 1824 } 1825 1826 public void organizationConfigChanged(String serviceName, 1827 String version, String orgName, String groupName, 1828 String serviceComponent, int type) { 1829 // Reset the cached configuration in OrgConfigViaAMSDK 1830 if (serviceName.equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) 1831 { 1832 OrgConfigViaAMSDK.attributeMappings = new HashMap(); 1833 OrgConfigViaAMSDK.reverseAttributeMappings = new HashMap(); 1834 } 1835 } 1836 } 1837 1838 // ******* Static Variables ************ 1839 // To determine if notification object has been registered for config 1840 // changes 1841 private static boolean registeredForConfigNotifications; 1842 1843 // Realm & Co-existence modes 1844 private static boolean realmEnabled; 1845 1846 private static boolean coexistMode; 1847 1848 private static boolean migratedTo70; 1849}