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