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