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 if (realmEnabled) { 603 try { 604 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 605 subOrgDN); 606 if (cEntry.isDirty()) { 607 cEntry.refresh(); 608 } 609 SMSEntry entry = cEntry.getClonedSMSEntry(); 610 if (!recursive) { 611 // Check if there are sub organization entries 612 // and if exist 613 // throw exception that this sub organization cannot be 614 // deleted. 615 if ((subRlmSet !=null) && (!subRlmSet.isEmpty())) { 616 throw (new SMSException(SMSEntry.bundle 617 .getString("sms-entries-exists"), 618 "sms-entries-exists")); 619 } 620 } 621 // Obtain the SMSEntry for the suborg and 622 // sub tree and delete it. 623 entry.delete(token); 624 cEntry.refresh(entry); 625 } catch (SSOException ssoe) { 626 SMSEntry.debug.error( 627 "OrganizationConfigManager: deleteSubOrganization(" + 628 "String subOrgName, boolean recursive) Unable to " + 629 "delete sub organization ", ssoe); 630 throw (new SMSException(SMSEntry.bundle 631 .getString(SMS_INVALID_SSO_TOKEN), 632 SMS_INVALID_SSO_TOKEN)); 633 } 634 } 635 636 // If in legacy mode or (realm mode and copy org enabled) 637 // delete the corresponding organization. 638 if ((coexistMode) || (realmEnabled && isCopyOrgEnabled())) { 639 String amsdkName = DNMapper.realmNameToAMSDKName(subOrgDN); 640 if (!SMSEntry.getRootSuffix().equalsIgnoreCase( 641 SMSEntry.getAMSdkBaseDN())) { 642 String convOrg = subOrgName; 643 if (subOrgName.startsWith("/")) { 644 convOrg = DNMapper.convertToDN(subOrgName).toString(); 645 } 646 amsdkName = convOrg + SMSEntry.COMMA + amSDKOrgDN; 647 } 648 amsdk.deleteSubOrganization(amsdkName); 649 } 650 } 651 652 /** 653 * Returns the <code>OrganizationConfigManager</code> 654 * for the given organization name. 655 * 656 * @param subOrgName 657 * the name of the organization. 658 * @return the configuration manager for the given organization. 659 * 660 * @throws SMSException 661 * if the organization name cannot be found or user doesn't have 662 * access to that organization. 663 */ 664 public OrganizationConfigManager getSubOrgConfigManager(String subOrgName) 665 throws SMSException { 666 validateConfigImpl(); 667 // Normalize sub organization name 668 return (new OrganizationConfigManager(token, normalizeDN(subOrgName, 669 orgDN))); 670 } 671 672 /** 673 * Returns the organization creation attributes for 674 * the service. 675 * 676 * @param serviceName 677 * name of the service. 678 * @return map of organization creation attribute values for service 679 * @throws SMSException 680 * if there is an error accessing the data store to read the 681 * attributes of the service. 682 */ 683 public Map getAttributes(String serviceName) throws SMSException { 684 validateConfigImpl(); 685 if (serviceName == null) { 686 return (Collections.EMPTY_MAP); 687 } 688 Map attrValues = null; 689 // Attributes can be obtained only if DIT is migrated to AM 7.0 690 if (migratedTo70) { 691 // Lowercase the service name 692 serviceName = serviceName.toLowerCase(); 693 try { 694 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 695 orgDN); 696 if (cEntry.isDirty() || (coexistMode) || 697 (realmEnabled && isCopyOrgEnabled())) { 698 // Since AMSDK org notifications will not be 699 // obtained, the entry must be read again 700 cEntry.refresh(); 701 } 702 SMSEntry entry = cEntry.getSMSEntry(); 703 Map map = SMSUtils.getAttrsFromEntry(entry); 704 if ((map != null) && (!map.isEmpty())) { 705 Iterator itr = map.keySet().iterator(); 706 while (itr.hasNext()) { 707 String name = (String) itr.next(); 708 if ((name.toLowerCase()).startsWith(serviceName)) { 709 Set values = (Set) map.get(name); 710 // Remove the serviceName and '-' and return only 711 // the attribute name,value. 712 String key; 713 714 if (!serviceName.isEmpty()) { 715 key = name.substring(serviceName.length() + 1); 716 } else { 717 key = name; 718 } 719 if (attrValues == null) { 720 attrValues = new HashMap(); 721 } 722 attrValues.put(key, values); 723 } 724 } 725 } 726 } catch (SSOException ssoe) { 727 SMSEntry.debug.error("OrganizationConfigManager: " 728 + "getAttributes(String serviceName) Unable to " 729 + "get Attributes", ssoe); 730 throw (new SMSException(SMSEntry.bundle 731 .getString(SMS_INVALID_SSO_TOKEN), 732 SMS_INVALID_SSO_TOKEN)); 733 } 734 } 735 736 // If in coexistMode and serviceName is idRepoService 737 // get attributes from AMSDK organization 738 if ((coexistMode || (realmEnabled && isCopyOrgEnabled())) 739 && serviceName 740 .equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) { 741 Map amsdkMap = amsdk.getAttributes(); 742 Map mergesdkMap = new HashMap(2); 743 if (amsdkMap != null && !amsdkMap.isEmpty()) { 744 Set mergeValues = new HashSet(2); 745 Iterator itr = amsdkMap.keySet().iterator(); 746 while (itr.hasNext()) { 747 String key = (String) itr.next(); 748 if (key.equalsIgnoreCase(SUNDNS_ALIAS) || 749 key.equalsIgnoreCase(SUNPREF_DOMAIN) || 750 key.equalsIgnoreCase(SUNORG_ALIAS)) { 751 buildSet(key, amsdkMap, mergeValues); 752 } 753 } 754 mergesdkMap.put(SUNORG_ALIAS, mergeValues); 755 mergesdkMap.put(SUNORG_STATUS, 756 (Set) amsdkMap.get(SUNORG_STATUS)); 757 } 758 if (attrValues == null) { 759 attrValues = mergesdkMap; 760 } else { 761 attrValues.putAll(mergesdkMap); 762 } 763 } 764 return ((attrValues == null) ? Collections.EMPTY_MAP : attrValues); 765 } 766 767 /** 768 * Builds and returns the appropriate Set for the attributes to be 769 * merged from org and realm if the system is 770 * in intrusive mode (Both org DIT and realm DIT are present). 771 * This happens when the Copy Config flag is enabled. 772 */ 773 private Set buildSet(String attrName, Map attributes, Set resultSet) { 774 Set vals = (Set) attributes.get(attrName); 775 if ((vals != null) && !vals.isEmpty()) { 776 resultSet.addAll(vals); 777 } 778 return (resultSet); 779 } 780 781 /** 782 * Adds organization attributes for the service. If 783 * the attribute already exists, the values will be appended to it, provided 784 * it is a multi-valued attribute. It will throw exception if we try to add 785 * a value to an attribute which has the same value already. 786 * 787 * @param serviceName 788 * name of the service. 789 * @param attrName 790 * name of the attribute. 791 * @param values 792 * values for the attribute. 793 * @throws SMSException 794 * if we try to add a value to an attribute which has the same 795 * value already. 796 */ 797 public void addAttributeValues(String serviceName, String attrName, 798 Set values) throws SMSException { 799 validateConfigImpl(); 800 if (serviceName == null || attrName == null) { 801 return; 802 } 803 804 if (migratedTo70) { 805 // Lowercase the servicename 806 serviceName = serviceName.toLowerCase(); 807 try { 808 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 809 orgDN); 810 if (cEntry.isDirty()) { 811 cEntry.refresh(); 812 } 813 SMSEntry e = cEntry.getClonedSMSEntry(); 814 ServiceSchemaManager ssm = new ServiceSchemaManager( 815 serviceName, token); 816 ServiceSchema ss = ssm.getOrganizationCreationSchema(); 817 if (ss == null) { 818 throw (new SMSException(SMSEntry.bundle 819 .getString("sms-SMSSchema_service_notfound"), 820 "sms-SMSSchema_service_notfound")); 821 } 822 823 Map map = new HashMap(2); 824 Set newValues = new HashSet(values); 825 Map allAttributes = ss.getAttributeDefaults(); 826 Set existingValues = (Set)allAttributes.get(attrName); 827 if ((existingValues != null) && !existingValues.isEmpty()) { 828 newValues.addAll(existingValues); 829 } 830 map.put(attrName, newValues); 831 ss.validateAttributes(map); 832 SMSUtils.addAttribute(e, serviceName + "-" + attrName, 833 values, ss.getSearchableAttributeNames()); 834 e.save(token); 835 cEntry.refresh(e); 836 } catch (SSOException ssoe) { 837 SMSEntry.debug.error("OrganizationConfigManager: Unable " 838 + "to add Attribute Values", ssoe); 839 throw (new SMSException(SMSEntry.bundle 840 .getString(SMS_INVALID_SSO_TOKEN), 841 SMS_INVALID_SSO_TOKEN)); 842 } 843 } 844 845 // If in coexistMode and serviceName is idRepoService 846 // add the attributes to AMSDK organization 847 if (coexistMode 848 && serviceName 849 .equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) { 850 amsdk.addAttributeValues(attrName, values); 851 } 852 } 853 854 /** 855 * Sets/Creates organization attributes for the 856 * service. If the attributes already exists, the given attribute values 857 * will replace them. 858 * 859 * @param serviceName 860 * name of the service. 861 * @param attributes 862 * attribute-values pairs. 863 * @throws SMSException 864 * if the serviceName cannot be found. 865 */ 866 public void setAttributes(String serviceName, Map attributes) 867 throws SMSException { 868 validateConfigImpl(); 869 if (serviceName == null) { 870 return; 871 } 872 873 if (migratedTo70) { 874 // Lowercase the serviceName 875 serviceName = serviceName.toLowerCase(); 876 try { 877 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 878 orgDN); 879 if (cEntry.isDirty()) { 880 cEntry.refresh(); 881 } 882 SMSEntry e = cEntry.getClonedSMSEntry(); 883 if ((attributes != null) && (!attributes.isEmpty())) { 884 // Validate the attributes 885 ServiceSchemaManager ssm = new ServiceSchemaManager( 886 serviceName, token); 887 ServiceSchema ss = ssm.getOrganizationCreationSchema(); 888 ss.validateAttributes(attributes); 889 890 // Normalize the attributes with service name 891 Map attrsMap = new HashMap(); 892 Iterator itr = attributes.keySet().iterator(); 893 while (itr.hasNext()) { 894 String name = (String) itr.next(); 895 Set values = (Set) attributes.get(name); 896 /* 897 * To make the attributes qualified by service name we 898 * prefix the attribute names with the service name. 899 */ 900 attrsMap.put(serviceName + "-" + name, values); 901 } 902 903 // Look for old attrs. in the storage and add them too. 904 Map oldAttrs = getAttributes(serviceName); 905 Iterator it = oldAttrs.keySet().iterator(); 906 while (it.hasNext()) { 907 String skey = (String) it.next(); 908 if (!attributes.containsKey(skey)) 909 attrsMap.put(serviceName + "-" + skey, oldAttrs 910 .get(skey)); 911 } 912 913 // Set the attributes in SMSEntry 914 SMSUtils.setAttributeValuePairs(e, attrsMap, ss 915 .getSearchableAttributeNames()); 916 917 String dataStore = SMSEntry.getDataStore(token); 918 // Add these OCs only for SunOne DS. Do not add the 919 // OCs for Active Directory. 920 // Will get WILL_NOT_PERFORM in AD. 921 if ((dataStore != null) && !dataStore.equals( 922 SMSEntry.DATASTORE_ACTIVE_DIR) 923 ) { 924 // This is for storing organization attributes 925 // in top/default realm node. eg.,ou=services,o=isp 926 if (e.getDN().equalsIgnoreCase(SERVICES_NODE)) { 927 String[] ocVals = e 928 .getAttributeValues(SMSEntry.ATTR_OBJECTCLASS); 929 boolean exists = false; 930 for (int ic = 0; ocVals != null 931 && ic < ocVals.length; ic++) 932 { 933 if (ocVals[ic].startsWith( 934 SMSEntry.OC_SERVICE_COMP)) { 935 // OC needs to be added outside the for loop 936 // else will throw concurrent mod exception 937 exists = true; 938 break; 939 } 940 } 941 if (!exists) { 942 e.addAttribute(SMSEntry.ATTR_OBJECTCLASS, 943 SMSEntry.OC_SERVICE_COMP); 944 } 945 } else if (e.getDN().startsWith( 946 SMSEntry.ORGANIZATION_RDN + SMSEntry.EQUALS)) { 947 // This is for storing organization attributes in 948 // organizations created via sdk through realm 949 // console. 950 String[] vals = e 951 .getAttributeValues(SMSEntry.ATTR_OBJECTCLASS); 952 boolean rsvcExists = false; 953 for (int n = 0; vals != null && n < vals.length; 954 n++) { 955 if (vals[n].equalsIgnoreCase( 956 SMSEntry.OC_REALM_SERVICE)) 957 { 958 // OC needs to be added outside the for loop 959 // else will throw concurrent mod exception 960 rsvcExists = true; 961 break; 962 } 963 } 964 if (!rsvcExists) { 965 e.addAttribute(SMSEntry.ATTR_OBJECTCLASS, 966 SMSEntry.OC_REALM_SERVICE); 967 } 968 } 969 } 970 971 // Save in backend data store and refresh the cache 972 e.save(token); 973 cEntry.refresh(e); 974 } 975 976 } catch (SSOException ssoe) { 977 SMSEntry.debug.error("OrganizationConfigManager: Unable " 978 + "to set Attributes", ssoe); 979 throw (new SMSException(SMSEntry.bundle 980 .getString(SMS_INVALID_SSO_TOKEN), 981 SMS_INVALID_SSO_TOKEN)); 982 } 983 } 984 985 // If in coexistMode and serviceName is idRepoService 986 // set the attributes to AMSDK organization 987 if ((coexistMode || (realmEnabled && isCopyOrgEnabled())) 988 && serviceName 989 .equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) { 990 amsdk.setAttributes(attributes); 991 } 992 } 993 994 /** 995 * Removes the given organization creation attribute 996 * for the service. 997 * 998 * @param serviceName 999 * name of service. 1000 * @param attrName 1001 * name of attribute. 1002 * @throws SMSException 1003 * if the organization attribute for the service to be removed 1004 * cannot be found, or if the service name cannot be found. 1005 */ 1006 public void removeAttribute(String serviceName, String attrName) 1007 throws SMSException { 1008 validateConfigImpl(); 1009 if (serviceName == null || attrName == null) { 1010 return; 1011 } 1012 1013 if (migratedTo70) { 1014 try { 1015 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 1016 orgDN); 1017 if (cEntry.isDirty()) { 1018 cEntry.refresh(); 1019 } 1020 SMSEntry e = cEntry.getClonedSMSEntry(); 1021 SMSUtils.removeAttribute(e, serviceName.toLowerCase() + "-" 1022 + attrName); 1023 e.save(token); 1024 cEntry.refresh(e); 1025 } catch (SSOException ssoe) { 1026 SMSEntry.debug.error("OrganizationConfigManager: Unable " 1027 + "to remove Attribute", ssoe); 1028 throw (new SMSException(SMSEntry.bundle 1029 .getString(SMS_INVALID_SSO_TOKEN), 1030 SMS_INVALID_SSO_TOKEN)); 1031 } 1032 } 1033 1034 // If in coexistMode and serviceName is idRepoService 1035 // remove the attributes to AMSDK organization 1036 if (coexistMode 1037 && serviceName 1038 .equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) { 1039 amsdk.removeAttribute(attrName); 1040 } 1041 } 1042 1043 /** 1044 * Removes the given organization creation attribute 1045 * values for the service. 1046 * 1047 * @param serviceName 1048 * name of service. 1049 * @param attrName 1050 * name of attribute. 1051 * @param values 1052 * attribute values to be removed. 1053 * @throws SMSException 1054 * if the organization attribute for the service to be removed 1055 * cannot be found, or if the service name cannot be found, or 1056 * if the value cannot be removed. 1057 */ 1058 public void removeAttributeValues(String serviceName, String attrName, 1059 Set values) throws SMSException { 1060 validateConfigImpl(); 1061 if (serviceName == null || attrName == null) { 1062 return; 1063 } 1064 if (migratedTo70) { 1065 try { 1066 CachedSMSEntry cEntry = CachedSMSEntry.getInstance(token, 1067 orgDN); 1068 if (cEntry.isDirty()) { 1069 cEntry.refresh(); 1070 } 1071 SMSEntry e = cEntry.getClonedSMSEntry(); 1072 ServiceSchemaManager ssm = new ServiceSchemaManager( 1073 serviceName, token); 1074 ServiceSchema ss = ssm.getOrganizationCreationSchema(); 1075 Map map = new HashMap(2); 1076 map.put(attrName, values); 1077 ss.validateAttributes(map); 1078 SMSUtils.removeAttributeValues(e, serviceName.toLowerCase() 1079 + "-" + attrName, values, ss 1080 .getSearchableAttributeNames()); 1081 e.save(token); 1082 cEntry.refresh(e); 1083 1084 } catch (SSOException ssoe) { 1085 SMSEntry.debug.error("OrganizationConfigManager: Unable " 1086 + "to remove Attribute Values", ssoe); 1087 throw (new SMSException(SMSEntry.bundle 1088 .getString(SMS_INVALID_SSO_TOKEN), 1089 SMS_INVALID_SSO_TOKEN)); 1090 } 1091 } 1092 1093 // If in coexistMode and serviceName is idRepoService 1094 // remove the attributes to AMSDK organization 1095 if (coexistMode 1096 && serviceName 1097 .equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) { 1098 amsdk.removeAttributeValues(attrName, values); 1099 } 1100 } 1101 1102 /** 1103 * Returns the service configuration object for the 1104 * given service name. 1105 * 1106 * @param serviceName 1107 * name of a service. 1108 * @return service configuration object for the service. 1109 * @throws SMSException 1110 * if there is an error accessing the data store to read the 1111 * service configuration, or if the service name cannot be 1112 * found. 1113 */ 1114 public ServiceConfig getServiceConfig(String serviceName) 1115 throws SMSException { 1116 try { 1117 ServiceConfigManager scmgr = new ServiceConfigManager(serviceName, 1118 token); 1119 ServiceConfig scg = scmgr.getOrganizationConfig(orgName, null); 1120 return (scg); 1121 } catch (SSOException ssoe) { 1122 SMSEntry.debug.error("OrganizationConfigManager: Unable to " 1123 + "get Service Config", ssoe); 1124 throw (new SMSException(SMSEntry.bundle 1125 .getString(SMS_INVALID_SSO_TOKEN), 1126 SMS_INVALID_SSO_TOKEN)); 1127 } 1128 } 1129 1130 ServiceSchema getServiceSchema(String serviceName) throws SMSException { 1131 try { 1132 return new ServiceSchemaManager(serviceName, token).getOrganizationSchema(); 1133 } catch (SSOException ssoe) { 1134 SMSEntry.debug.error("OrganizationConfigManager: Unable to get Service Schema", ssoe); 1135 throw new SMSException(SMSEntry.bundle.getString(SMS_INVALID_SSO_TOKEN), SMS_INVALID_SSO_TOKEN); 1136 } 1137 } 1138 1139 /** 1140 * Adds a service configuration object for the given 1141 * service name for this organization. If the service has been already added 1142 * a <code>SMSException</code> will be thrown. 1143 * 1144 * @param serviceName 1145 * name of the service. 1146 * @param attributes 1147 * service configuration attributes. 1148 * @return service configuration object. 1149 * @throws SMSException 1150 * if the service configuration has been added already. 1151 */ 1152 public ServiceConfig addServiceConfig(String serviceName, Map attributes) 1153 throws SMSException { 1154 try { 1155 ServiceConfigManagerImpl scmi = ServiceConfigManagerImpl 1156 .getInstance(token, serviceName, 1157 ServiceManager.getVersion(serviceName)); 1158 ServiceConfigImpl sci = scmi.getOrganizationConfig(token, orgName, 1159 null); 1160 if (sci == null || sci.isNewEntry()) { 1161 ServiceConfigManager scm = new ServiceConfigManager( 1162 serviceName, token); 1163 return (scm.createOrganizationConfig(orgName, attributes)); 1164 } else { 1165 SMSEntry.debug.error("OrganizationConfigManager: " 1166 + "ServiceConfig already exists: " + sci.getDN()); 1167 throw (new SMSException(SMSEntry.bundle 1168 .getString("sms-service_already_exists1"))); 1169 } 1170 } catch (SSOException ssoe) { 1171 SMSEntry.debug.error("OrganizationConfigManager: Unable to " 1172 + "add Service Config", ssoe); 1173 throw (new SMSException(SMSEntry.bundle 1174 .getString(SMS_INVALID_SSO_TOKEN), 1175 SMS_INVALID_SSO_TOKEN)); 1176 } 1177 } 1178 1179 /** 1180 * Removes the service configuration object for the 1181 * given service name for this organization. 1182 * 1183 * @param serviceName 1184 * name of the service. 1185 * @throws SMSException 1186 * if the service name cannot be found, or not added to the 1187 * organization. 1188 */ 1189 public void removeServiceConfig(String serviceName) throws SMSException { 1190 try { 1191 ServiceConfigManager scm = new ServiceConfigManager(serviceName, 1192 token); 1193 scm.deleteOrganizationConfig(orgName); 1194 } catch (SSOException ssoe) { 1195 SMSEntry.debug.error("OrganizationConfigManager: Unable to " 1196 + "delete Service Config", ssoe); 1197 throw (new SMSException(SMSEntry.bundle 1198 .getString(SMS_INVALID_SSO_TOKEN), 1199 SMS_INVALID_SSO_TOKEN)); 1200 } 1201 } 1202 1203 /** 1204 * Registers for changes to organization's 1205 * configuration. The object will be called when configuration for this 1206 * organization is changed. 1207 * 1208 * @param listener 1209 * callback object that will be invoked when organization 1210 * configuration has changed 1211 * @return an ID of the registered listener. 1212 */ 1213 public String addListener(ServiceListener listener) { 1214 return (orgConfigImpl.addListener(listener)); 1215 } 1216 1217 /** 1218 * Removes the listener from the organization for the 1219 * given listener ID. The ID was issued when the listener was registered. 1220 * 1221 * @param listenerID 1222 * the listener ID issued when the listener was registered 1223 */ 1224 public void removeListener(String listenerID) { 1225 orgConfigImpl.removeListener(listenerID); 1226 } 1227 1228 /** 1229 * Returns normalized DN for realm model 1230 */ 1231 private static String normalizeDN(String subOrgName, String orgDN) { 1232 // Return orgDN if subOrgName is either null or empty 1233 if (subOrgName == null || subOrgName.length() == 0) { 1234 return (orgDN); 1235 } 1236 if (SMSEntry.debug.messageEnabled()) { 1237 SMSEntry.debug.message("OrganizationConfigManager." 1238 + "normalizeDN()-subOrgName " + subOrgName); 1239 } 1240 String subOrgDN = null; 1241 if (LDAPUtils.isDN(subOrgName) && (!subOrgName.startsWith("///"))) { 1242 int ndx = subOrgName.lastIndexOf(DNMapper.serviceDN); 1243 if (ndx == -1) { 1244 // Check for baseDN 1245 ndx = subOrgName.lastIndexOf(SMSEntry.getRootSuffix()); 1246 } 1247 if (ndx > 0) { 1248 subOrgName = subOrgName.substring(0, ndx - 1); 1249 } 1250 subOrgDN = DNMapper.normalizeDN(subOrgName) + orgDN; 1251 } else if (subOrgName.indexOf('/') != -1) { 1252 String tmp = DNMapper.convertToDN(subOrgName).toString(); 1253 if (SMSEntry.debug.messageEnabled()) { 1254 SMSEntry.debug.message("OrganizationConfigManager." 1255 + "normalizeDN()-slashConvertedString: " + tmp); 1256 } 1257 if (tmp != null && tmp.length() > 0) { 1258 if (tmp.charAt(tmp.length() - 1) == ',') { 1259 subOrgDN = tmp + DNMapper.serviceDN; 1260 } else { 1261 int dx = tmp.indexOf(SMSEntry.COMMA); 1262 if (dx >= 0) { 1263 subOrgDN = tmp + SMSEntry.COMMA + DNMapper.serviceDN; 1264 } else { 1265 subOrgDN = tmp + SMSEntry.COMMA + orgDN; 1266 } 1267 } 1268 } else { 1269 subOrgDN = orgDN; 1270 } 1271 } else if (subOrgName.startsWith(SMSEntry.SUN_INTERNAL_REALM_NAME)) { 1272 subOrgDN = SMSEntry.ORG_PLACEHOLDER_RDN + subOrgName 1273 + SMSEntry.COMMA + DNMapper.serviceDN; 1274 } else { 1275 if (coexistMode) { 1276 subOrgDN = orgNamingAttrInLegacyMode + SMSEntry.EQUALS 1277 + subOrgName + SMSEntry.COMMA 1278 + DNMapper.realmNameToAMSDKName(orgDN); 1279 } else { 1280 subOrgDN = SMSEntry.ORG_PLACEHOLDER_RDN + subOrgName 1281 + SMSEntry.COMMA + orgDN; 1282 } 1283 } 1284 if (SMSEntry.debug.messageEnabled()) { 1285 SMSEntry.debug.message("OrganizationConfigManager::" 1286 + "normalizeDN() suborgdn " + subOrgDN); 1287 } 1288 return (subOrgDN); 1289 } 1290 1291 /** 1292 * Returns all service names configured for AM 1293 */ 1294 static Set getServiceNames(SSOToken token) throws SMSException, 1295 SSOException { 1296 // Get the service names from ServiceManager 1297 CachedSubEntries cse = CachedSubEntries.getInstance(token, 1298 DNMapper.serviceDN); 1299 return (cse.getSubEntries(token)); 1300 } 1301 1302 /** 1303 * Returns a set of service names that can be assigned 1304 * to a realm. This set excludes name of services that are already assigned 1305 * to the realm and services that are required for the existence of a realm. 1306 * 1307 * @return a set of service names that can be assigned to a realm. 1308 * @throws SMSException 1309 * if there is an error accessing the data store to read the 1310 * service configuration 1311 */ 1312 public Set getAssignableServices() throws SMSException { 1313 // Get all service names, and remove the assigned services 1314 // Set containing service names that has organization schema 1315 Set orgSchemaServiceNames = new HashSet(); 1316 try { 1317 for (Iterator names = getServiceNames(token).iterator(); names 1318 .hasNext();) { 1319 String serviceName = (String) names.next(); 1320 ServiceSchemaManagerImpl ssmi = ServiceSchemaManagerImpl 1321 .getInstance(token, serviceName, 1322 ServiceManager.getVersion(serviceName)); 1323 if (ssmi.getSchema(SchemaType.ORGANIZATION) != null) { 1324 // Need to check if the user has permission 1325 // to add/assign the service 1326 StringBuilder d = new StringBuilder(100); 1327 // Need to construct 1328 // "ou=default,ou=organizationconfig,ou=1.0,ou=" 1329 d.append(SMSEntry.PLACEHOLDER_RDN).append(SMSEntry.EQUALS) 1330 .append(SMSUtils.DEFAULT).append(SMSEntry.COMMA) 1331 .append(CreateServiceConfig.ORG_CONFIG_NODE) 1332 .append(SMSEntry.PLACEHOLDER_RDN).append( 1333 SMSEntry.EQUALS).append("1.0").append( 1334 SMSEntry.COMMA).append( 1335 SMSEntry.PLACEHOLDER_RDN).append( 1336 SMSEntry.EQUALS); 1337 // Append service name, and org name 1338 d.append(serviceName); 1339 if (!orgDN.equalsIgnoreCase(DNMapper.serviceDN)) { 1340 d.append(SMSEntry.COMMA).append(SMSEntry.SERVICES_RDN); 1341 } 1342 d.append(SMSEntry.COMMA).append(orgDN); 1343 try { 1344 // The function will throw exception if 1345 // user does not have permissions 1346 SMSEntry.getDelegationPermission(token, d.toString(), 1347 SMSEntry.modifyActionSet); 1348 orgSchemaServiceNames.add(serviceName); 1349 } catch (SMSException smse) { 1350 if (smse.getExceptionCode() != 1351 SMSException.STATUS_NO_PERMISSION) 1352 { 1353 throw (smse); 1354 } 1355 } 1356 } 1357 } 1358 // Need to remove mandatory services 1359 // %%% TODO. Need to have SMS Service with this information 1360 // orgSchemaServiceNames.removeAll(getMandatoryServices()); 1361 } catch (SSOException ssoe) { 1362 SMSEntry.debug.error("OrganizationConfigManager." 1363 + "getAssignableServices(): SSOException", ssoe); 1364 throw (new SMSException(SMSEntry.bundle 1365 .getString(SMS_INVALID_SSO_TOKEN), 1366 SMS_INVALID_SSO_TOKEN)); 1367 } 1368 // Remove assigned services 1369 HashSet answer = new HashSet(orgSchemaServiceNames); 1370 answer.removeAll(getAssignedServices()); 1371 return (answer); 1372 } 1373 1374 /** 1375 * Returns a set of service names that are assigned to 1376 * a realm. 1377 * 1378 * @return a set of service names that are assigned to a realm. 1379 * @throws SMSException 1380 * if there is an error accessing the data store to read the 1381 * service configuration 1382 */ 1383 public Set<String> getAssignedServices() throws SMSException { 1384 return (getAssignedServices(true)); 1385 } 1386 1387 /** 1388 * Returns a set of service names that are assigned to a realm. 1389 * 1390 * @param includeMandatory 1391 * <code>true</code> to include mandatory service names. 1392 * @return a set of service names that are assigned to a realm. 1393 * @throws SMSException 1394 * if there is an error accessing the data store to read the 1395 * service configuration 1396 */ 1397 public Set<String> getAssignedServices(boolean includeMandatory) 1398 throws SMSException { 1399 validateConfigImpl(); 1400 Set<String> assignedServices = Collections.EMPTY_SET; 1401 if (coexistMode) { 1402 // Get assigned services from OrgConfigViaAMSDK 1403 assignedServices = amsdk.getAssignedServices(); 1404 } else { 1405 // Get assigned service names from OrganizationConfigManagerImpl 1406 assignedServices = orgConfigImpl.getAssignedServices(token); 1407 } 1408 if (!includeMandatory) { 1409 // Get services assigned by default 1410 Set ds = ServiceManager.requiredServices(); 1411 assignedServices.removeAll(ds); 1412 } 1413 return (assignedServices); 1414 } 1415 1416 /** 1417 * Assigns the given service to the orgnization with 1418 * the respective attributes. If the service has been already added a <code> 1419 * SMSException</code> 1420 * will be thrown. 1421 * 1422 * @param serviceName 1423 * name of the service 1424 * @param attributes 1425 * service configuration attributes 1426 * @throws SMSException 1427 * if the service configuration has been added already. 1428 */ 1429 public void assignService(String serviceName, Map attributes) 1430 throws SMSException { 1431 addServiceConfig(serviceName, attributes); 1432 } 1433 1434 /** 1435 * Returns attributes configured for the service. 1436 * 1437 * @param serviceName 1438 * name of the service 1439 * @return a map of attributes for the service 1440 * @throws SMSException 1441 * if there is an error accessing the data store to read the 1442 * service configuration, or if the service name cannot be 1443 * found. 1444 */ 1445 public Map getServiceAttributes(String serviceName) throws SMSException { 1446 ServiceConfig scg = getServiceConfig(serviceName); 1447 if (scg == null) { 1448 Object args[] = { serviceName }; 1449 SMSEntry.debug.error( 1450 "OrganizationConfigManager.getServiceAttributes() Unable " + 1451 "to get service attributes. "); 1452 throw (new SMSException(IUMSConstants.UMS_BUNDLE_NAME, 1453 "sms-no-organization-schema", 1454 args)); 1455 1456 } 1457 return (scg.getAttributes()); 1458 } 1459 1460 /** 1461 * Unassigns the service from the organization. 1462 * 1463 * @param serviceName 1464 * name of the service 1465 * @throws SMSException 1466 * if the service name cannot be found or assigned, or if the 1467 * service is a mandatory service. 1468 */ 1469 public void unassignService(String serviceName) throws SMSException { 1470 // if (coexistMode) { 1471 // amsdk.unassignService(serviceName); 1472 // } else { 1473 removeServiceConfig(serviceName); 1474 // } 1475 } 1476 1477 /** 1478 * Sets the attributes related to provided service. 1479 * The assumption is that the service is already assigned to the 1480 * organization. The attributes for the service are validated against the 1481 * service schema. 1482 * 1483 * @param serviceName 1484 * name of the service 1485 * @param attributes 1486 * attributes of the service 1487 * @throws SMSException 1488 * if the service name cannot be found or not assigned to the 1489 * organization. 1490 */ 1491 public void modifyService(String serviceName, Map attributes) 1492 throws SMSException { 1493 try { 1494 getServiceConfig(serviceName).setAttributes(attributes); 1495 } catch (SSOException ssoe) { 1496 SMSEntry.debug.error("OrganizationConfigManager.modifyService " 1497 + "SSOException in modify service ", ssoe); 1498 throw (new SMSException(SMSEntry.bundle 1499 .getString(SMS_INVALID_SSO_TOKEN), 1500 SMS_INVALID_SSO_TOKEN)); 1501 } 1502 } 1503 1504 public String getNamingAttrForOrg() { 1505 return OrgConfigViaAMSDK.getNamingAttrForOrg(); 1506 } 1507 1508 /** 1509 * Returns the <code>OrganizationConfigManager</code> 1510 * of the parent for the given organization name. 1511 * 1512 * @return the configuration manager of the parent for the given 1513 * organization. 1514 * @throws SMSException 1515 * if user doesn't have access to that organization. 1516 */ 1517 public OrganizationConfigManager getParentOrgConfigManager() 1518 throws SMSException { 1519 OrganizationConfigManager ocm = null; 1520 String parentDN = null; 1521 if (LDAPUtils.isDN(orgDN)) { 1522 if (orgDN.equalsIgnoreCase(DNMapper.serviceDN)) { 1523 return (this); 1524 } 1525 parentDN = DN.valueOf(orgDN).parent().toString(); 1526 if (SMSEntry.debug.messageEnabled()) { 1527 SMSEntry.debug.message("OrganizationConfigManager." 1528 + "getParentOrgConfigManager() parentDN : " + parentDN); 1529 } 1530 if (parentDN != null && parentDN.length() > 0) { 1531 ocm = new OrganizationConfigManager(token, parentDN); 1532 } 1533 } 1534 return ocm; 1535 } 1536 1537 /** 1538 * Loads default services to a newly created realm 1539 */ 1540 public static void loadDefaultServices(SSOToken token, 1541 OrganizationConfigManager ocm) throws SMSException { 1542 // Check if DIT has been migrated to 7.0 1543 if (!migratedTo70) { 1544 return; 1545 } 1546 Set defaultServices = ServiceManager.servicesAssignedByDefault(); 1547 // Load the default services automatically 1548 OrganizationConfigManager parentOrg = ocm.getParentOrgConfigManager(); 1549 if (defaultServices == null) { 1550 // There are no services to be loaded 1551 return; 1552 } 1553 1554 Set assignedServices = new CaseInsensitiveHashSet( 1555 parentOrg.getAssignedServices()); 1556 if (SMSEntry.debug.messageEnabled()) { 1557 SMSEntry.debug.message("OrganizationConfigManager" 1558 + "::loadDefaultServices " + "assignedServices : " 1559 + assignedServices); 1560 } 1561 boolean doAuthServiceLater = false; 1562 boolean doAuthHttpBasicLater = false; 1563 String serviceName = null; 1564 1565 // Copy service configuration 1566 Iterator items = defaultServices.iterator(); 1567 while (items.hasNext() || doAuthHttpBasicLater || doAuthServiceLater) { 1568 if (items.hasNext()) { 1569 serviceName = (String) items.next(); 1570 if (serviceName.equals(ISAuthConstants.AUTH_SERVICE_NAME)) { 1571 doAuthServiceLater = true; 1572 continue; 1573 } else if (serviceName.equals( 1574 ISAuthConstants.AUTH_HTTP_BASIC_SERVICE_NAME)) { 1575 1576 doAuthHttpBasicLater = true; 1577 continue; 1578 } 1579 } else if (doAuthHttpBasicLater) { 1580 serviceName = ISAuthConstants.AUTH_HTTP_BASIC_SERVICE_NAME; 1581 doAuthHttpBasicLater = false; 1582 } else if (doAuthServiceLater) { 1583 serviceName = ISAuthConstants.AUTH_SERVICE_NAME; 1584 doAuthServiceLater = false; 1585 } 1586 if (SMSEntry.debug.messageEnabled()) { 1587 SMSEntry.debug.message("OrganizationConfigManager" + 1588 "::loadDefaultServices:ServiceName " + serviceName); 1589 } 1590 try { 1591 ServiceConfig sc = parentOrg.getServiceConfig(serviceName); 1592 ServiceSchema ss = parentOrg.getServiceSchema(serviceName); 1593 Map attrs = null; 1594 if (sc != null && assignedServices.contains(serviceName)) { 1595 attrs = sc.getAttributesWithoutDefaults(); 1596 if (SMSEntry.debug.messageEnabled()) { 1597 SMSEntry.debug 1598 .message("OrganizationConfigManager" 1599 + "::loadDefaultServices " 1600 + "Copying service from parent: " 1601 + serviceName); 1602 } 1603 ServiceConfig scn = ocm 1604 .addServiceConfig(serviceName, attrs); 1605 // Copy sub-configurations, if any 1606 copySubConfig(sc, scn, ss); 1607 } 1608 } catch (SSOException ssoe) { 1609 if (SMSEntry.debug.messageEnabled()) { 1610 SMSEntry.debug.message( 1611 "OrganizationConfigManager.loadDefaultServices " + 1612 "SSOException in loading default services ", 1613 ssoe); 1614 } 1615 throw (new SMSException(SMSEntry.bundle 1616 .getString(SMS_INVALID_SSO_TOKEN), 1617 SMS_INVALID_SSO_TOKEN)); 1618 } 1619 } 1620 } 1621 1622 1623 /** 1624 * Registers default services to newly created suborganizations. 1625 */ 1626 private void registerSvcsForOrg(String subOrgName, String subOrgDN) 1627 { 1628 try { 1629 Set defaultServices = 1630 ServiceManager.servicesAssignedByDefault(); 1631 if (SMSEntry.debug.messageEnabled()) { 1632 SMSEntry.debug.message("OrganizationConfigManager::"+ 1633 "registerSvcsForOrg. "+ 1634 "defaultServices : " + defaultServices); 1635 } 1636 1637 // Register the default services to the newly created orgs,so 1638 // they will be marked with the OC sunRegisteredServiceName. 1639 if (defaultServices != null) { 1640 Set assignedServices = amsdk.getAssignedServices(); 1641 if (SMSEntry.debug.messageEnabled()) { 1642 SMSEntry.debug.message("OrganizationConfigManager::" + 1643 "registerSvcsForOrg:assignedServices: " + 1644 assignedServices); 1645 } 1646 Iterator items = defaultServices.iterator(); 1647 String serviceName = null; 1648 if (SMSEntry.getRootSuffix().equalsIgnoreCase( 1649 SMSEntry.getAMSdkBaseDN())) { 1650 amsdk = new OrgConfigViaAMSDK(token, 1651 orgNamingAttrInLegacyMode + SMSEntry.EQUALS + 1652 subOrgName + SMSEntry.COMMA + 1653 DNMapper.realmNameToAMSDKName(orgDN), subOrgDN); 1654 } else { 1655 amsdk = new OrgConfigViaAMSDK(token, 1656 orgNamingAttrInLegacyMode + SMSEntry.EQUALS + 1657 subOrgName + SMSEntry.COMMA + amSDKOrgDN, subOrgDN); 1658 } 1659 while (items.hasNext()) { 1660 serviceName = (String) items.next(); 1661 if (assignedServices.contains(serviceName)) { 1662 if (SMSEntry.debug.messageEnabled()) { 1663 SMSEntry.debug.message( 1664 "OrganizationConfigManager::"+ 1665 "registerSvcsForOrg:ServiceName : " + 1666 serviceName); 1667 } 1668 amsdk.assignService(serviceName); 1669 } 1670 } 1671 } 1672 } catch (SMSException smse) { 1673 // Unable to load default services 1674 if (SMSEntry.debug.warningEnabled()) { 1675 SMSEntry.debug.warning("OrganizationConfigManager::" + 1676 "registerSvcsForOrg. " + 1677 "SMSException in registering services: ", smse); 1678 } 1679 } 1680 } 1681 1682 /** 1683 * Copies service configurations recursively from source to destination 1684 */ 1685 static void copySubConfig(ServiceConfig from, ServiceConfig to, ServiceSchema serviceSchema) 1686 throws SMSException, SSOException { 1687 Set subConfigNames = from.getSubConfigNames(); 1688 for (Iterator items = subConfigNames.iterator(); items.hasNext();) { 1689 String subConfigName = (String) items.next(); 1690 ServiceConfig scf = from.getSubConfig(subConfigName); 1691 ServiceSchema subSchema = serviceSchema.getSubSchema(scf.getSchemaID()); 1692 if (subSchema.isRealmCloneable()) { 1693 to.addSubConfig(subConfigName, scf.getSchemaID(), scf.getPriority(), scf.getAttributesWithoutDefaults()); 1694 ServiceConfig sct = to.getSubConfig(subConfigName); 1695 copySubConfig(scf, sct, subSchema); 1696 } 1697 } 1698 } 1699 1700 1701 /** 1702 * Determines whether an organization ought to be created for each 1703 * realm in realm only mode of installation based on the boolean flag 1704 * in amSDK plugin. 1705 * This requirement is for portal customers. 1706 */ 1707 protected boolean isCopyOrgEnabled() { 1708 if (copyOrgInitialized) { 1709 return (copyOrgEnabled); 1710 } 1711 if (SMSEntry.debug.messageEnabled()) { 1712 SMSEntry.debug.message("OrganizationConfigManager: "+ 1713 "in isCopyOrgEnabled() "); 1714 } 1715 // Check if AMSDK is configured for the realm 1716 try { 1717 ServiceConfig s = getServiceConfig(ServiceManager.REALM_SERVICE); 1718 if (s != null) { 1719 Iterator items = s.getSubConfigNames().iterator(); 1720 while (items.hasNext()) { 1721 String name = items.next().toString(); 1722 ServiceConfig subConfig = s.getSubConfig(name); 1723 if (subConfig == null) { 1724 SMSEntry.debug.error("OrganizationConfigManager.is" + 1725 "CopyOrgEnabled. SubConfig is NULL: " + 1726 "SC Name: " + name + " For org: " + orgDN); 1727 return (false); 1728 } 1729 if (subConfig.getSchemaID().equalsIgnoreCase( 1730 IdConstants.AMSDK_PLUGIN_NAME)) { 1731 Map configMap = subConfig.getAttributes(); 1732 if ((configMap != null) && !configMap.isEmpty()) { 1733 // Get the amsdkOrgName from the amSDKRepo to build 1734 // OrgConfigViaSDK instance. 1735 Set orgs = (Set) configMap.get("amSDKOrgName"); 1736 if (orgs != null && !orgs.isEmpty()) { 1737 amSDKOrgDN = (String) orgs.iterator().next(); 1738 Set cfgs = (Set) configMap.get(CONF_ENABLED); 1739 if ( (cfgs != null) && (!cfgs.isEmpty()) && 1740 (cfgs.contains("true")) && 1741 (amSDKOrgDN !=null) ) { 1742 amsdk = new OrgConfigViaAMSDK(token, 1743 amSDKOrgDN, orgDN); 1744 if (orgNamingAttrInLegacyMode == null) { 1745 orgNamingAttrInLegacyMode = 1746 getNamingAttrForOrg(); 1747 } 1748 copyOrgEnabled = true; 1749 } 1750 break; 1751 } 1752 } 1753 } 1754 } 1755 } 1756 } catch (SSOException sse) { 1757 // Use default values i.e., false 1758 if (SMSEntry.debug.messageEnabled()) { 1759 SMSEntry.debug.message("OrganizationConfigManager:" + 1760 "isCopyOrgEnabled() Unable to get service: " + 1761 ServiceManager.REALM_SERVICE, sse); 1762 } 1763 } catch (SMSException e) { 1764 // Use default values i.e., false 1765 if (SMSEntry.debug.messageEnabled()) { 1766 SMSEntry.debug.message("OrganizationConfigManager:" + 1767 "isCopyOrgEnabled() Unable to get service: " + 1768 ServiceManager.REALM_SERVICE, e); 1769 } 1770 } 1771 copyOrgInitialized = true; 1772 if (SMSEntry.debug.messageEnabled()) { 1773 SMSEntry.debug.message("OrganizationConfigManager: "+ 1774 "copyOrgEnabled == " + copyOrgEnabled); 1775 } 1776 return (copyOrgEnabled); 1777 } 1778 1779 static void initializeFlags() { 1780 realmEnabled = ServiceManager.isRealmEnabled(); 1781 coexistMode = ServiceManager.isCoexistenceMode(); 1782 migratedTo70 = ServiceManager.isConfigMigratedTo70(); 1783 } 1784 1785 void validateConfigImpl() throws SMSException { 1786 // Instantiate the OrgConfigImpl and cache it 1787 if ((orgConfigImpl == null) || !orgConfigImpl.isValid()) { 1788 try { 1789 orgConfigImpl = OrganizationConfigManagerImpl.getInstance( 1790 token, orgName); 1791 } catch (SSOException ssoe) { 1792 throw (new SMSException(ssoe, SMS_INVALID_SSO_TOKEN)); 1793 } 1794 } 1795 } 1796 1797 class OrganizationConfigManagerListener implements ServiceListener { 1798 public void schemaChanged(String serviceName, String version) { 1799 // Call ServiceManager to notify 1800 ServiceManager.schemaChanged(); 1801 // If naming service has changed, reload the AM Servers 1802 if (serviceName.equalsIgnoreCase(ServiceManager.PLATFORM_SERVICE)) { 1803 ServiceManager.accessManagerServers = null; 1804 } 1805 } 1806 1807 public void globalConfigChanged(String serviceName, String version, 1808 String groupName, String serviceComponent, int type) { 1809 if (serviceName.equalsIgnoreCase(ServiceManager.REALM_SERVICE)) { 1810 try { 1811 ServiceManager.checkFlags(token); 1812 } catch (SSOException ssoe) { 1813 SMSEntry.debug.error("OrganizationConfigManager: " 1814 + "globalConfigChanged ", ssoe); 1815 } catch (SMSException smse) { 1816 SMSEntry.debug.error("OrganizationConfigManager: " 1817 + "globalConfigChanged ", smse); 1818 } 1819 realmEnabled = ServiceManager.isRealmEnabled(); 1820 coexistMode = ServiceManager.isCoexistenceMode(); 1821 migratedTo70 = ServiceManager.isConfigMigratedTo70(); 1822 } 1823 } 1824 1825 public void organizationConfigChanged(String serviceName, 1826 String version, String orgName, String groupName, 1827 String serviceComponent, int type) { 1828 // Reset the cached configuration in OrgConfigViaAMSDK 1829 if (serviceName.equalsIgnoreCase(OrgConfigViaAMSDK.IDREPO_SERVICE)) 1830 { 1831 OrgConfigViaAMSDK.attributeMappings = new HashMap(); 1832 OrgConfigViaAMSDK.reverseAttributeMappings = new HashMap(); 1833 } 1834 } 1835 } 1836 1837 // ******* Static Variables ************ 1838 // To determine if notification object has been registered for config 1839 // changes 1840 private static boolean registeredForConfigNotifications; 1841 1842 // Realm & Co-existence modes 1843 private static boolean realmEnabled; 1844 1845 private static boolean coexistMode; 1846 1847 private static boolean migratedTo70; 1848}