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: AMStoreConnection.java,v 1.13 2009/01/28 05:34:47 ww203982 Exp $ 026 * 027 */ 028 029/** 030 * Portions Copyrighted 2011-2012 ForgeRock Inc 031 */ 032package com.iplanet.am.sdk; 033 034import com.iplanet.am.sdk.common.IDirectoryServices; 035import com.iplanet.sso.SSOException; 036import com.iplanet.sso.SSOToken; 037import com.iplanet.sso.SSOTokenManager; 038import com.sun.identity.sm.SMSEntry; 039import com.sun.identity.sm.SMSException; 040import com.sun.identity.sm.SchemaType; 041import com.sun.identity.sm.ServiceConfig; 042import com.sun.identity.sm.ServiceManager; 043import com.sun.identity.sm.ServiceSchemaManager; 044import java.text.NumberFormat; 045import java.text.ParseException; 046import java.text.ParsePosition; 047import java.text.SimpleDateFormat; 048import java.util.ArrayList; 049import java.util.Collections; 050import java.util.Date; 051import java.util.HashSet; 052import java.util.Iterator; 053import java.util.List; 054import java.util.Map; 055import java.util.Set; 056import java.util.StringTokenizer; 057import com.sun.identity.shared.ldap.LDAPDN; 058import com.sun.identity.shared.ldap.util.DN; 059 060 061/** 062 * The <code>AMStoreConnection</code> class represents a connection to the Sun 063 * Java System Access Manager data store. It provides methods to create, remove 064 * and get different type of Sun Java System Access Manager SDK objects in the 065 * data tore. <code>AMStoreConnection</code> controls and manages access to 066 * the data store. 067 * <p> 068 * An instance of <code>AMStoreConnection</code> object should always be 069 * obtained by anyone using the AM SDK since this object is the entry point to 070 * all other AM SDK managed objects. The constructor takes the SSO token of the 071 * user. Here is some sample code on how to get a user's attributes, using AM 072 * SDK: 073 * 074 * <PRE> 075 * 076 * AMStoreConnection amsc = new AMStoreConnection(ssotoken); AMUser user = 077 * amsc.getUser(ssotoken.getPrincipal()); Map attributes = user.getAttributes(); 078 * 079 * </PRE> 080 * 081 * <p> 082 * <code>AMStoreConnection</code> also has other helper methods which are very 083 * useful. Some examples below: 084 * 085 * <PRE> 086 * 087 * int otype = amsc.getAMObjectType(fullDN); 088 * 089 * </PRE> 090 * 091 * <p> 092 * <code>otype</code> returned is one of the managed <code>AMObject</code> 093 * types, like <code>AMObject.USER</code>, <code>AMObject.ROLE</code>, 094 * <code>AMObject.ORGANIZATION</code>. If the entry being checked in not of 095 * the type managed by AM SDK, then an <code>AMException</code> is thrown. 096 * 097 * <PRE> 098 * 099 * boolean exists = amsc.isValidEntry(fullDN); 100 * 101 * </PRE> 102 * 103 * <p> 104 * If there is a <code>fullDN</code> that you want to know if it exists or not 105 * in the data store, then use the above method. The typical use of this method 106 * is in the case when you know that you need to get a managed object from 107 * <code>amsc</code>, but you want to verify that it exists before you create 108 * the managed object instance: 109 * 110 * <PRE> 111 * 112 * if (amsc.isValidEntry(userDN)) { AMUser user = amsc.getUser(userDN); - More 113 * code here - } 114 * 115 * </PRE> 116 * 117 * <p> 118 * Helper method <code>getOrganizationDN()</code>: Use this method to perform 119 * a subtree scoped search for organization,based on various attribute values. 120 * 121 * <PRE> 122 * 123 * String orgDN = amsc.getOrganizationDN("sun.com", null); 124 * 125 * </PRE> 126 * 127 * <p> 128 * The above method will return the DN of a organization, which matches the 129 * search criterias of having either domain name of <code>sun.com</code>, 130 * Domain alias name of <code>sun.com</code> or it's naming attribute value is 131 * <code>sun.com</code>. More examples of how to use this method are provided 132 * in the Javadocs of the method below. 133 * 134 * @deprecated As of Sun Java System Access Manager 7.1. 135 * @supported.all.api 136 */ 137public final class AMStoreConnection implements AMConstants { 138 // ~ Static fields/initializers 139 // --------------------------------------------- 140 141 public static String rootSuffix; 142 143 protected static String defaultOrg; 144 145 protected static Map orgMapCache = new AMHashMap(); 146 147 // ~ Instance fields 148 // -------------------------------------------------------- 149 150 private IDirectoryServices dsServices; 151 152 private SSOToken token; 153 154 private String locale = "en_US"; 155 156 // ~ Constructors 157 // ----------------------------------------------------------- 158 159 /** 160 * Gets the connection to the Sun Java System Access Manager data store if 161 * the Session is valid. 162 * 163 * @param ssoToken 164 * a valid SSO token object to authenticate before getting the 165 * connection 166 * @throws SSOException 167 * if single sign on token is invalid or expired. 168 */ 169 public AMStoreConnection(SSOToken ssoToken) throws SSOException { 170 // initialize whatever you want to here. 171 SSOTokenManager.getInstance().validateToken(ssoToken); 172 this.token = ssoToken; 173 this.locale = AMCommonUtils.getUserLocale(ssoToken); 174 dsServices = AMDirectoryAccessFactory.getDirectoryServices(); 175 } 176 177 // ~ Methods 178 // ---------------------------------------------------------------- 179 180 /** 181 * Returns the root suffix for user management node. 182 * 183 * @return root suffix for user management node. 184 * 185 */ 186 public static String getAMSdkBaseDN() { 187 defaultOrg = rootSuffix = 188 com.sun.identity.common.DNUtils.normalizeDN( 189 SMSEntry.getAMSdkBaseDN()); 190 // Get an instance as required otherwise it causes issues on container restart. 191 if (AMCommonUtils.debug.messageEnabled()) { 192 AMCommonUtils.debug.message("AMStoreConnection:getAMSdkBaseDN():rootsuffix " + 193 rootSuffix); 194 } 195 if (AMCommonUtils.debug.messageEnabled()) { 196 AMCommonUtils.debug.message("default org: " + defaultOrg); 197 AMCommonUtils.debug.message("AMStoreConnection:getAMSdkBaseDN():default org " + 198 defaultOrg); 199 } 200 return defaultOrg; 201 } 202 203 /** 204 * Returns the filtered role naming attribute. 205 * 206 * @return filtered role naming attribute 207 * @deprecated This method is deprecated. Use 208 * {@link #getNamingAttribute(int) 209 * getNamingAttribute(int objectType)} 210 */ 211 public static String getFilteredRoleNamingAttribute() { 212 return AMNamingAttrManager.getNamingAttr(AMObject.FILTERED_ROLE); 213 } 214 215 /** 216 * Returns the group container naming attribute. 217 * 218 * @return group container naming attribute 219 * @deprecated This method is deprecated. Use 220 * {@link #getNamingAttribute(int) 221 * getNamingAttribute(int objectType)} 222 */ 223 public static String getGroupContainerNamingAttribute() { 224 return AMNamingAttrManager.getNamingAttr(AMObject.GROUP_CONTAINER); 225 } 226 227 /** 228 * Returns the group naming attribute. 229 * 230 * @return group naming attribute 231 * @deprecated This method is deprecated. Use 232 * {@link #getNamingAttribute(int) 233 * getNamingAttribute(int objectType)} 234 */ 235 public static String getGroupNamingAttribute() { 236 return AMNamingAttrManager.getNamingAttr(AMObject.GROUP); 237 } 238 239 /** 240 * Returns the naming attribute of an object type. 241 * 242 * @param objectType 243 * Object type can be one of the following: 244 * <ul> 245 * <li> {@link AMObject#USER AMObject.USER} 246 * <li> {@link AMObject#ROLE AMObject.ROLE} 247 * <li> {@link AMObject#FILTERED_ROLE AMObject.FILTERED_ROLE} 248 * <li> {@link AMObject#ORGANIZATION AMObject.ORGANIZATION} 249 * <li> {@link AMObject#ORGANIZATIONAL_UNIT 250 * AMObject.ORGANIZATIONAL_UNIT} 251 * <li> {@link AMObject#GROUP AMObject.GROUP} 252 * <li> {@link AMObject#DYNAMIC_GROUP AMObject.DYNAMIC_GROUP} 253 * <li> {@link AMObject#ASSIGNABLE_DYNAMIC_GROUP 254 * AMObject.ASSIGNABLE_DYNAMIC_GROUP} 255 * <li> 256 * {@link AMObject#PEOPLE_CONTAINER AMObject.PEOPLE_CONTAINER} 257 * <li> {@link AMObject#GROUP_CONTAINER AMObject.GROUP_CONTAINER} 258 * </ul> 259 * @return the naming attribute corresponding to the <code>objectType</code> 260 * @throws AMException 261 * if an error occurred in obtaining the naming attribute 262 */ 263 public static String getNamingAttribute(int objectType) throws AMException { 264 return AMNamingAttrManager.getNamingAttr(objectType); 265 } 266 267 /** 268 * Returns the organization naming attribute. 269 * 270 * @return organization naming attribute 271 * @deprecated This method is deprecated. Use 272 * {@link #getNamingAttribute(int) 273 * getNamingAttribute(int objectType)} 274 */ 275 public static String getOrganizationNamingAttribute() { 276 return AMNamingAttrManager.getNamingAttr(AMObject.ORGANIZATION); 277 } 278 279 /** 280 * Returns the organizational unit naming attribute. 281 * 282 * @return organizational unit naming attribute 283 * @deprecated This method is deprecated. Use 284 * {@link #getNamingAttribute(int) 285 * getNamingAttribute(int objectType)} 286 */ 287 public static String getOrganizationalUnitNamingAttribute() { 288 return AMNamingAttrManager.getNamingAttr(AMObject.ORGANIZATIONAL_UNIT); 289 } 290 291 /** 292 * Returns the people container naming attribute. 293 * 294 * @return people container naming attribute 295 * @deprecated This method is deprecated. Use 296 * {@link #getNamingAttribute(int) 297 * getNamingAttribute(int objectType)} 298 */ 299 public static String getPeopleContainerNamingAttribute() { 300 return AMNamingAttrManager.getNamingAttr(AMObject.PEOPLE_CONTAINER); 301 } 302 303 /** 304 * Returns the role naming attribute. 305 * 306 * @return role naming attribute 307 * @deprecated This method is deprecated. Use 308 * {@link #getNamingAttribute(int) 309 * getNamingAttribute(int objectType)} 310 */ 311 public static String getRoleNamingAttribute() { 312 return AMNamingAttrManager.getNamingAttr(AMObject.ROLE); 313 } 314 315 /** 316 * Returns the user naming attribute. 317 * 318 * @return user naming attribute 319 * @deprecated This method is deprecated. Use 320 * {@link #getNamingAttribute(int) 321 * getNamingAttribute(int objectType)} 322 */ 323 public static String getUserNamingAttribute() { 324 return AMNamingAttrManager.getNamingAttr(AMObject.USER); 325 } 326 327 /** 328 * Returns the type of the object given its DN. 329 * 330 * @param dn 331 * DN of the object whose type is to be known. 332 * @return the type of the object given its DN. 333 * @throws AMException 334 * if the data store is unavailable or if the object type is 335 * unknown. 336 * @throws SSOException 337 * if single sign on token is invalid or expired. 338 */ 339 public int getAMObjectType(String dn) throws AMException, SSOException { 340 return dsServices.getObjectType(token, dn); 341 } 342 343 /** 344 * Take a supported type, and returns the matching name of the supported 345 * managed type. For example, if <code> AMObject.USER</code> is passed in, 346 * it will return "user" (one of the basic supported types in AM SDK. But 347 * this method (and configuration in the service <code>DAI</code>) can be 348 * used to extend the basic supported types to include customer-specific 349 * entities, like "agents", "printers" etc. 350 * 351 * @param type 352 * Integer type (as returned by <code>getAMObjectType</code>) 353 * @return identifier for the above type. Returns null if type is unknown. 354 */ 355 public String getAMObjectName(int type) { 356 return ((String) AMCommonUtils.supportedNames.get(Integer 357 .toString(type))); 358 } 359 360 /** 361 * Take a supported type, and returns the matching name of the supported 362 * managed type. For example, if <code> AMObject.USER</code> is passed in, 363 * it will return "user" (one of the basic supported types in AM SDK. But 364 * this method (and configuration in the service <code>DAI</code>) can be 365 * used to extend the basic supported types to include customer-specific 366 * entities, like "agents", "printers" etc. 367 * 368 * @param type 369 * Integer type (as returned by <code>getAMObjectType</code>) 370 * @return identifier for the above type. Returns null if type is unknown. 371 */ 372 public static String getObjectName(int type) { 373 return ((String) AMCommonUtils.supportedNames.get(Integer 374 .toString(type))); 375 } 376 377 /** 378 * Returns the handle to the <code>AMAssignableDynamicGroup</code> object 379 * represented by DN. However, the validity of the handle returned by this 380 * method cannot be guaranteed, since the object is created in memory, and 381 * not instantiated from the data store. Using the 382 * <code>AMAssignableDynamicGroup</code> returned from this method may 383 * result in exceptions thrown in the later part of the application, if the 384 * DN is not valid or represents an entry that does not exist. 385 * <p> 386 * 387 * Validity of the DN can be verified is using <code>isValidEntry()</code> 388 * method of the object returned. 389 * 390 * @see #isValidEntry 391 * 392 * @param assignableDynamicGroupDN 393 * assignable dynamic group DN 394 * @return <code>AMAssignableDynamicGroup</code> object represented by DN. 395 * @throws SSOException 396 * if single sign on token is invalid or expired. 397 */ 398 public AMAssignableDynamicGroup getAssignableDynamicGroup( 399 String assignableDynamicGroupDN) throws SSOException { 400 AMAssignableDynamicGroup assignableDynamicGroup = 401 new AMAssignableDynamicGroupImpl(this.token, 402 assignableDynamicGroupDN); 403 404 return assignableDynamicGroup; 405 } 406 407 /** 408 * Returns the service attribute names for a given service name and schema 409 * type. 410 * 411 * @param serviceName 412 * the name of the service 413 * @param schemaType 414 * the type of service schema 415 * @return Set of service attribute names 416 * @throws AMException 417 * if an error is encountered while retrieving information. 418 * @deprecated use <code>com.sun.identity.sm.ServiceSchemaManager. 419 * getServiceAttributeNames(com.sun.identity.sm.SchemaType)</code> 420 */ 421 public Set getAttributeNames(String serviceName, AMSchema.Type schemaType) 422 throws AMException { 423 try { 424 ServiceSchemaManager ssm = new ServiceSchemaManager(serviceName, 425 token); 426 SchemaType st = schemaType.getInternalSchemaType(); 427 428 return ssm.getServiceAttributeNames(st); 429 } catch (SSOException se) { 430 AMCommonUtils.debug.message("AMStoreConnection.getAttributeNames(String, " 431 + "AMSchema.Type)", se); 432 throw new AMException(AMSDKBundle.getString("902", locale), "902"); 433 } catch (SMSException se) { 434 AMCommonUtils.debug.message("AMStoreConnection.getAttributeNames(String, " + 435 "AMSchema.Type)", se); 436 throw new AMException(AMSDKBundle.getString("911", locale), "911"); 437 } 438 } 439 440 /** 441 * Returns the handle to the <code>AMDynamicGroup</code> object 442 * represented by DN. However, the validity of the handle returned by this 443 * method cannot be guaranteed, since the object is created in memory, and 444 * not instantiated from the data store. Using the 445 * <code>AMDynamicGroup</code> returned from this method may result in 446 * exceptions thrown in the later part of the application, if the DN is not 447 * valid or represents an entry that does not exist. 448 * <p> 449 * 450 * Validity of the DN can be verified is using <code>isValidEntry()</code> 451 * method of the object returned. 452 * 453 * @see #isValidEntry 454 * 455 * @param dynamicGroupDN 456 * group DN 457 * @return <code>AMDynamicGroup</code> object represented by DN. 458 * @throws SSOException 459 * if single sign on token is invalid or expired. 460 */ 461 public AMDynamicGroup getDynamicGroup(String dynamicGroupDN) 462 throws SSOException { 463 AMDynamicGroup dynamicGroup = new AMDynamicGroupImpl(this.token, 464 dynamicGroupDN); 465 466 return dynamicGroup; 467 } 468 469 /** 470 * Returns the handle to the <code>AMFilteredRole</code> object 471 * represented by DN. However, the validity of the handle returned by this 472 * method cannot be guaranteed, since the object is created in memory, and 473 * not instantiated from the data store. Using the 474 * <code>AMFilteredRole</code> returned from this method may result in 475 * exceptions thrown in the later part of the application, if the DN is not 476 * valid or represents an entry that does not exist. 477 * <p> 478 * 479 * Validity of the DN can be verified is using <code>isValidEntry()</code> 480 * method of the object returned. 481 * 482 * @see #isValidEntry 483 * 484 * @param roleDN 485 * role DN. 486 * @return <code>AMFilteredRole</code> object represented by DN. 487 * @throws SSOException 488 * if single sign on token is invalid or expired. 489 */ 490 public AMFilteredRole getFilteredRole(String roleDN) throws SSOException { 491 AMFilteredRole role = new AMFilteredRoleImpl(this.token, roleDN); 492 493 return role; 494 } 495 496 /** 497 * Returns the handle to the <code>AMGroupContainer</code> object 498 * represented by DN. However, the validity of the handle returned by this 499 * method cannot be guaranteed, since the object is created in memory, and 500 * not instantiated from the data store. Using the 501 * <code>AMGroupContainer</code> returned from this method may result in 502 * exceptions thrown in the later part of the application, if the DN is not 503 * valid or represents an entry that does not exist. 504 * <p> 505 * 506 * Validity of the DN can be verified is using <code>isValidEntry()</code> 507 * method of the object returned. 508 * 509 * @see #isValidEntry 510 * 511 * @param groupContainerDN 512 * group container DN. 513 * @return <code>AMGroupContainer</code> object represented by DN. 514 * @throws SSOException 515 * if single sign on token is invalid or expired. 516 */ 517 public AMGroupContainer getGroupContainer(String groupContainerDN) 518 throws SSOException { 519 AMGroupContainer groupContainer = new AMGroupContainerImpl(this.token, 520 groupContainerDN); 521 522 return groupContainer; 523 } 524 525 /** 526 * Returns the I18N properties file name that contains the internationalized 527 * messages. 528 * 529 * @param serviceName 530 * the service name 531 * @return String String representing i18N properties file name 532 * @throws AMException 533 * if an error is encountered while retrieving information 534 */ 535 public String getI18NPropertiesFileName(String serviceName) 536 throws AMException { 537 try { 538 ServiceSchemaManager scm = new ServiceSchemaManager(serviceName, 539 token); 540 541 return scm.getI18NFileName(); 542 } catch (SSOException so) { 543 AMCommonUtils.debug.error("AMStoreConnection.getI18NPropertiesFileName(): ", so); 544 throw new AMException(AMSDKBundle.getString("902", locale), "902"); 545 } catch (SMSException se) { 546 AMCommonUtils.debug.error("AMStoreConnection.getServiceNames(): ", se); 547 throw new AMException(AMSDKBundle.getString("909", locale), "909"); 548 } 549 } 550 551 /** 552 * Returns the handle to the <code>AMOrganization</code> object 553 * represented by DN. However, the validity of the handle returned by this 554 * method cannot be guaranteed, since the object is created in memory, and 555 * not instantiated from the data store. Using the 556 * <code>AMOrganization</code> returned from this method may result in 557 * exceptions thrown in the later part of the application, if the DN is not 558 * valid or represents an entry that does not exist. 559 * <p> 560 * 561 * Validity of the DN can be verified is using <code>isValidEntry()</code> 562 * method of the object returned. 563 * 564 * @see #isValidEntry 565 * 566 * @param orgDN 567 * organization DN 568 * @return <code>AMOrganization</code> object represented by DN. 569 * @throws SSOException 570 * if single sign on token is invalid or expired. 571 */ 572 public AMOrganization getOrganization(String orgDN) throws SSOException { 573 AMOrganization organization = new AMOrganizationImpl(this.token, orgDN); 574 575 return organization; 576 } 577 578 /** 579 * Returns the DN of the organization, using the <code>domainname</code> 580 * provided and the <code>searchTemplate</code> (if provided). If 581 * <code>searchTemplate</code> is null, SDK uses the default 582 * <code>searchTemplate</code> to perform the <code>orgDN</code> search. 583 * If the DC tree global flag is enabled, the DC tree is used to obtain the 584 * organization DN, otherwise an LDAP search is conducted using the 585 * <code>searchfilter</code> in the <code>searchtemplate</code>. All 586 * <code>%V</code> in the filter are replaced with <code>domainname</code>. 587 * If the search returns more than one entries, then an Exception is thrown. 588 * Otherwise the DN obtained is returned. 589 * 590 * @param domainname 591 * Organization identifier passed. It can be a domain name 592 * (example: <code>sun.com</code>) or it could be a full DN or 593 * it could be null or <code>* "/"</code>. A full DN is 594 * verified to be an organization and returned as is. A "/" is 595 * assumed to be a request for the root DN and the root DN is 596 * returned. A "/" separated string is assumed to represent an 597 * existing organization DN in the DIT. For example: 598 * <code>/iplanet/sun</code> is converted to a DN 599 * <code>(o=iplanet,o=sun,<base DN>)</code> and the validity 600 * of this DN is checked and returned. Any other string is 601 * assumed to be either a domain or an associated domain or the 602 * organization name. The search filter is created accordingly. 603 * @param orgSearchTemplate 604 * template to use for the search. 605 * @return The full organization DN 606 * @throws AMException 607 * If there is a problem connecting or searching the data store. 608 * @throws SSOException 609 * If the user has an invalid SSO token. 610 */ 611 public String getOrganizationDN(String domainname, String orgSearchTemplate) 612 throws AMException, SSOException { 613 if (domainname == null) { 614 return rootSuffix; 615 } 616 617 // If a DN is passed and is a valid organization DN, then 618 // return it. 619 if (DN.isDN(domainname) && isValidEntry(domainname) 620 && (getAMObjectType(domainname) == AMObject.ORGANIZATION)) { 621 return domainname; 622 } 623 624 if (!domainname.startsWith("http://") && (domainname.indexOf("/") > -1)) 625 { 626 String orgdn = orgNameToDN(domainname); 627 628 if (isValidEntry(orgdn) 629 && (getAMObjectType(orgdn) == AMObject.ORGANIZATION)) { 630 return (orgdn); 631 } else { 632 Object[] args = { orgdn }; 633 String locale = AMCommonUtils.getUserLocale(token); 634 throw new AMException(AMSDKBundle 635 .getString("467", args, locale), "467", args); 636 } 637 } 638 639 try { 640 String orgdn; 641 642 if (AMDCTree.isRequired()) { 643 orgdn = AMDCTree.getOrganizationDN(token, domainname); 644 645 if (orgdn != null) { 646 return orgdn; 647 } 648 } 649 } catch (AMException ae) { 650 // do nothing. will try to search the organization 651 // using search template 652 AMCommonUtils.debug.error("AMStoreConnection.getOrganizationDN-> " 653 + "In DC tree mode, unabe to find organization " 654 + " for domain: " + domainname); 655 } 656 657 String orgdn = (String) orgMapCache.get(domainname.toLowerCase()); 658 659 if (orgdn != null) { 660 return (orgdn); 661 } else { 662 // use the searchfilter to obtain org DN 663 // replace %V with domainname. 664 String searchFilter = AMSearchFilterManager.getSearchFilter( 665 AMObject.ORGANIZATION, null, orgSearchTemplate, false); 666 667 if ((orgSearchTemplate != null) 668 && (searchFilter.indexOf("%V") > -1)) { 669 searchFilter = AMObjectImpl.constructFilter(AMNamingAttrManager 670 .getNamingAttr(AMObject.ORGANIZATION), searchFilter, 671 domainname); 672 } else { 673 StringBuilder sb = new StringBuilder(); 674 sb.append("(|(&").append(searchFilter).append("(").append( 675 AMNamingAttrManager 676 .getNamingAttr(AMObject.ORGANIZATION)).append( 677 "=").append(domainname).append(")").append(")(&") 678 .append(searchFilter).append("(").append( 679 "sunPreferredDomain=").append(domainname) 680 .append(")").append(")(&").append(searchFilter).append( 681 "(").append("associatedDomain=").append( 682 domainname).append(")").append(")(&").append( 683 searchFilter).append("(").append( 684 "sunOrganizationAlias=").append(domainname) 685 .append(")").append("))"); 686 searchFilter = sb.toString(); 687 } 688 689 if (AMCommonUtils.debug.messageEnabled()) { 690 AMCommonUtils.debug.message("AMSC:getOrgDN-> " + "using searchfilter " 691 + searchFilter); 692 } 693 694 Set orgSet = dsServices.search(token, rootSuffix, searchFilter, 695 SCOPE_SUB); 696 697 if ((orgSet == null) || (orgSet.size() > 1) || orgSet.isEmpty()) { 698 // throw an exception 699 Object[] args = { domainname }; 700 String locale = AMCommonUtils.getUserLocale(token); 701 throw new AMException(AMSDKBundle 702 .getString("971", args, locale), "971", args); 703 } else { 704 Iterator it = orgSet.iterator(); 705 orgdn = (String) it.next(); 706 addToOrgMapCache(token, orgdn); 707 708 return (orgdn); 709 } 710 } 711 } 712 713 /** 714 * Returns the handle to the <code>AMOrganizationalUnit</code> object 715 * represented by DN. However, the validity of the handle returned by this 716 * method cannot be guaranteed, since the object is created in memory, and 717 * not instantiated from the data store. Using the 718 * <code>AMOrganizationialUnit</code> returned from this method may result 719 * in exceptions thrown in the later part of the application, if the DN is 720 * not valid or represents an entry that does not exist. 721 * <p> 722 * 723 * Validity of the DN can be verified is using <code>isValidEntry()</code> 724 * method of the object returned. 725 * 726 * @see #isValidEntry 727 * 728 * @param orgUnitDN 729 * organizational unit DN 730 * @return <code>AMOrganizationalUnit</code> object represented by DN. 731 * @throws SSOException 732 * if single sign on token is invalid or expired. 733 */ 734 public AMOrganizationalUnit getOrganizationalUnit(String orgUnitDN) 735 throws SSOException { 736 AMOrganizationalUnit organizationalUnit = new AMOrganizationalUnitImpl( 737 this.token, orgUnitDN); 738 739 return organizationalUnit; 740 } 741 742 /** 743 * Returns the handle to the <code>AMPeopleContainer</code> object 744 * represented by DN. However, the validity of the handle returned by this 745 * method cannot be guaranteed, since the object is created in memory, and 746 * not instantiated from the data store. Using the 747 * <code>AMPeopleContainer</code> returned from this method may result in 748 * exceptions thrown in the later part of the application, if the DN is not 749 * valid or represents an entry that does not exist. 750 * <p> 751 * 752 * Validity of the DN can be verified is using <code>isValidEntry()</code> 753 * method of the object returned. 754 * 755 * @see #isValidEntry 756 * 757 * @param peopleContainerDN 758 * people container DN 759 * @return <code>AMPeopleContainer</code> object represented by DN. 760 * @throws SSOException 761 * if single sign on token is invalid or expired. 762 */ 763 public AMPeopleContainer getPeopleContainer(String peopleContainerDN) 764 throws SSOException { 765 AMPeopleContainer peopleContainer = new AMPeopleContainerImpl( 766 this.token, peopleContainerDN); 767 768 return peopleContainer; 769 } 770 771 /** 772 * Returns the handle to the <code>AMTemplate</code> object represented by 773 * DN. However, the validity of the handle returned by this method cannot be 774 * guaranteed, since the object is created in memory, and not instantiated 775 * from the data store. Using the <code>AMTemplate</code> returned from 776 * this method may result in exceptions thrown in the later part of the 777 * application, if the DN is not valid or represents an entry that does not 778 * exist. 779 * <p> 780 * 781 * Validity of the DN can be verified is using <code>isValidEntry()</code> 782 * method of the object returned. 783 * 784 * @deprecated 785 * @see #isValidEntry 786 * 787 * @param templateDN 788 * a policy template DN. 789 * @return <code>AMTemplate</code> object represented by DN. 790 * @throws AMException 791 * if the DN does not represent a Policy template DN 792 * @throws SSOException 793 * if single sign on token is invalid or expired. 794 */ 795 public AMTemplate getPolicyTemplate(String templateDN) throws AMException, 796 SSOException { 797 throw new UnsupportedOperationException(); 798 } 799 800 /** 801 * Returns the URL of the view bean for the service 802 * 803 * @param serviceName 804 * the service name 805 * @return String URL of the view bean for the service 806 * @throws AMException 807 * if an error is encountered while retrieving information 808 */ 809 public String getPropertiesViewBeanURL(String serviceName) 810 throws AMException { 811 try { 812 ServiceSchemaManager scm = new ServiceSchemaManager(serviceName, 813 token); 814 815 return scm.getPropertiesViewBeanURL(); 816 } catch (SSOException so) { 817 AMCommonUtils.debug.error("AMStoreConnection.getPropertiesViewBeanURL(): ", so); 818 throw new AMException(AMSDKBundle.getString("902", locale), "902"); 819 } catch (SMSException se) { 820 AMCommonUtils.debug.error("AMStoreConnection.getServiceNames(): ", se); 821 throw new AMException(AMSDKBundle.getString("910", locale), "910"); 822 } 823 } 824 825 /** 826 * Returns the handle to the <code>AMResource</code> object represented by 827 * DN. However, the validity of the handle returned by this method cannot be 828 * guaranteed, since the object is created in memory, and not instantiated 829 * from the data store. Using the <code>AMResource</code> returned from 830 * this method may result in exceptions thrown in the later part of the 831 * application, if the DN is not valid or represents an entry that does not 832 * exist. 833 * <p> 834 * 835 * Validity of the DN can be verified is using <code>isValidEntry()</code> 836 * method of the object returned. 837 * 838 * @see #isValidEntry 839 * 840 * @param resourceDN 841 * resource DN. 842 * @return <code>AMResource</code> object represented by DN. 843 * @throws SSOException 844 * if single sign on token is invalid or expired. 845 */ 846 public AMResource getResource(String resourceDN) throws SSOException { 847 AMResource res = new AMResourceImpl(this.token, resourceDN); 848 849 return res; 850 } 851 852 /** 853 * Returns the handle to the <code>AMRole</code> object represented by DN. 854 * However, the validity of the handle returned by this method cannot be 855 * guaranteed, since the object is created in memory, and not instantiated 856 * from the data store. Using the <code>AMRole</code> returned from this 857 * method may result in exceptions thrown in the later part of the 858 * application, if the DN is not valid or represents an entry that does not 859 * exist. 860 * <p> 861 * 862 * Validity of the DN can be verified is using <code>isValidEntry()</code> 863 * method of the object returned. 864 * 865 * @see #isValidEntry 866 * 867 * @param roleDN 868 * role DN 869 * @return <code>AMRole</code> object represented by DN. 870 * @throws SSOException 871 * if single sign on token is invalid or expired. 872 */ 873 public AMRole getRole(String roleDN) throws SSOException { 874 AMRole role = new AMRoleImpl(this.token, roleDN); 875 876 return role; 877 } 878 879 /** 880 * Returns the <code>AMSchema</code> for the given service name and 881 * service type. 882 * 883 * @param serviceName 884 * the name of the service 885 * @param schemaType 886 * the type of service schema that needs to be retrieved. 887 * 888 * @return <code>AMSchema</code> corresponding to the given service name 889 * and schema type. 890 * 891 * @throws AMException 892 * if an error is encountered in retrieving the 893 * <code>AMSchema</code>. 894 * 895 * @deprecated This method has been deprecated. Please use 896 * <code>com.sun.identity.sm.ServiceSchemaManager.getSchema() 897 * </code>. 898 */ 899 public AMSchema getSchema(String serviceName, AMSchema.Type schemaType) 900 throws AMException { 901 throw new UnsupportedOperationException(); 902 } 903 904 /** 905 * Returns the schema types available for a particular service. 906 * 907 * @param serviceName 908 * the name of the service whose schema types needs to be 909 * retrieved 910 * @return Set of <code>AMSchema.Type</code> objects 911 * @throws AMException 912 * if an error is encountered in retrieving the 913 * <code>schemaTypes</code>. 914 * 915 * @deprecated This method has been deprecated. Please use 916 * <code> 917 * com.sun.identity.sm.ServiceSchemaManager.getSchemaTypes() 918 * </code>. 919 */ 920 public Set getSchemaTypes(String serviceName) throws AMException { 921 throw new UnsupportedOperationException(); 922 } 923 924 /** 925 * Returns the service hierarchy for all registered services. 926 * 927 * @return the service hierarchy for all registered services. 928 * @throws AMException 929 * if an error is encountered in retrieving the service 930 * hierarchy. The return value is a Set of strings in slash 931 * format. 932 */ 933 public Set getServiceHierarchy() throws AMException { 934 try { 935 Set retSet = new HashSet(); 936 ServiceManager sm = new ServiceManager(token); 937 Set serviceNames = sm.getServiceNames(); 938 Iterator itr = serviceNames.iterator(); 939 940 while (itr.hasNext()) { 941 String st = (String) itr.next(); 942 ServiceSchemaManager scm = new ServiceSchemaManager(st, token); 943 String sh = scm.getServiceHierarchy(); 944 945 if ((sh != null) && (sh.length() != 0)) { 946 retSet.add(sh); 947 } 948 } 949 950 return retSet; 951 } catch (SSOException so) { 952 AMCommonUtils.debug.error("AMStoreConnection.getServiceNames(): ", so); 953 throw new AMException(AMSDKBundle.getString("902", locale), "902"); 954 } catch (SMSException se) { 955 AMCommonUtils.debug.error("AMStoreConnection.getServiceNames(): ", se); 956 throw new AMException(AMSDKBundle.getString("905", locale), "905"); 957 } 958 } 959 960 /** 961 * Returns the set of name of services that have been loaded to the data 962 * store. 963 * 964 * @return set of name of services. 965 * @throws AMException 966 * if an error is encountered in retrieving the names of the 967 * services 968 */ 969 public Set getServiceNames() throws AMException { 970 try { 971 ServiceManager sm = new ServiceManager(token); 972 973 return sm.getServiceNames(); 974 } catch (SSOException so) { 975 AMCommonUtils.debug.error("AMStoreConnection.getServiceNames(): ", so); 976 throw new AMException(AMSDKBundle.getString("902", locale), "902"); 977 } catch (SMSException se) { 978 AMCommonUtils.debug.error("AMStoreConnection.getServiceNames(): ", se); 979 throw new AMException(AMSDKBundle.getString("906", locale), "906"); 980 } 981 } 982 983 /** 984 * Returns the handle to the <code>AMStaticGroup</code> object represented 985 * by DN. However, the validity of the handle returned by this method cannot 986 * be guaranteed, since the object is created in memory, and not 987 * instantiated from the data store. Using the <code>AMStaticGroup</code> 988 * returned from this method may result in exceptions thrown in the later 989 * part of the application, if the DN is not valid or represents an entry 990 * that does not exist. 991 * <p> 992 * 993 * Validity of the DN can be verified is using <code>isValidEntry()</code> 994 * method of the object returned. 995 * 996 * @see #isValidEntry 997 * 998 * @param groupDN 999 * group DN 1000 * @return <code>AMStaticGroup</code> object represented by DN. 1001 * @throws SSOException 1002 * if single sign on token is invalid or expired. 1003 */ 1004 public AMStaticGroup getStaticGroup(String groupDN) throws SSOException { 1005 AMStaticGroup group = new AMStaticGroupImpl(this.token, groupDN); 1006 return group; 1007 } 1008 1009 /** 1010 * Returns the top level containers (Organizations, People Containers, 1011 * Roles, etc) for the particular user based on single sign on token as the 1012 * starting point in the tree. 1013 * 1014 * @return set of <code>DBObjects</code> that are top level containers for 1015 * the signed in user. 1016 * @throws AMException 1017 * if an error occurred when retrieving the information from the 1018 * data store. 1019 * @throws SSOException 1020 * if single sign on token is invalid or expired. 1021 */ 1022 public Set getTopLevelContainers() throws AMException, SSOException { 1023 SSOTokenManager.getInstance().validateToken(this.token); 1024 return dsServices.getTopLevelContainers(token); 1025 } 1026 1027 /** 1028 * Returns the "real" or "physical" top level organizations as the starting 1029 * point in the tree. 1030 * 1031 * @return Set Set of DN Strings for top level Organizations 1032 * @throws AMException 1033 * if an error occurred when retrieving the information from the 1034 * data store. 1035 * @throws SSOException 1036 * if single sign on token is invalid or expired. 1037 */ 1038 public Set getTopLevelOrganizations() throws AMException, SSOException { 1039 SSOTokenManager.getInstance().validateToken(this.token); 1040 1041 return dsServices.search(this.token, rootSuffix, AMSearchFilterManager 1042 .getGlobalSearchFilter(AMObject.ORGANIZATION), SCOPE_ONE); 1043 } 1044 1045 /** 1046 * Returns the handle to the <code>AMUser</code> object represented by DN. 1047 * However, the validity of the handle returned by this method cannot be 1048 * guaranteed, since the object is created in memory, and not instantiated 1049 * from the data store. Using the <code>AMUser</code> returned from this 1050 * method may result in exceptions thrown in the later part of the 1051 * application, if the DN is not valid or represents an entry that does not 1052 * exist. 1053 * <p> 1054 * 1055 * Validity of the DN can be verified is using <code>isValidEntry()</code> 1056 * method of the object returned. 1057 * 1058 * @see #isValidEntry 1059 * 1060 * @param userDN 1061 * user DN 1062 * @return <code>AMUser</code> object represented by DN 1063 * @throws SSOException 1064 * if single sign on token is invalid or expired. 1065 */ 1066 public AMUser getUser(String userDN) throws SSOException { 1067 AMUser user = new AMUserImpl(this.token, userDN); 1068 return user; 1069 } 1070 1071 /** 1072 * Returns the handle to the <code>AMEntity</code> object represented by 1073 * DN. However, the validity of the handle returned by this method cannot be 1074 * guaranteed, since the object is created in memory, and not instantiated 1075 * from the data store. Using the <code>AMEntity</code> returned from this 1076 * method may result in exceptions thrown in the later part of the 1077 * application, if the DN is not valid or represents an entry that does not 1078 * exist. 1079 * <p> 1080 * 1081 * Validity of the DN can be verified is using <code>isValidEntry()</code> 1082 * method of the object returned. 1083 * 1084 * @see #isValidEntry 1085 * 1086 * @param eDN 1087 * entity DN. 1088 * @return <code>AMEntity</code> object represented by DN. 1089 * @throws SSOException 1090 * if single sign on token is invalid or expired. 1091 */ 1092 public AMEntity getEntity(String eDN) throws SSOException { 1093 AMEntity entity = null; 1094 try { 1095 entity = new AMEntityImpl(this.token, eDN, getAMObjectType(eDN)); 1096 } catch (AMException ame) { 1097 // Return AMEntity without object type 1098 entity = new AMEntityImpl(this.token, eDN); 1099 } 1100 return entity; 1101 } 1102 1103 /** 1104 * Checks if the entry exists in the directory or not. First a syntax check 1105 * is done on the DN string corresponding to the entry. If the DN syntax is 1106 * valid, a directory call will be made to check for the existence of the 1107 * entry. 1108 * <p> 1109 * 1110 * <b>NOTE:</b> This method internally invokes a call to the directory to 1111 * verify the existence of the entry. There could be a performance overhead. 1112 * Hence, please use your discretion while using this method. 1113 * 1114 * @param dn 1115 * DN of the entry that needs to be validated. 1116 * 1117 * @return false if the entry does not have a valid DN syntax or if the 1118 * entry does not exists in the Directory. True otherwise. 1119 * 1120 * @throws SSOException 1121 * if the single sign on token is no longer valid. 1122 */ 1123 public boolean isValidEntry(String dn) throws SSOException { 1124 // First check if DN syntax is valid. Avoid making iDS call 1125 if (!com.sun.identity.shared.ldap.util.DN.isDN(dn)) { // May be a exception thrown 1126 1127 return false; // would be better here. 1128 } 1129 1130 SSOTokenManager.getInstance().validateToken(token); 1131 1132 if (AMCommonUtils.debug.messageEnabled()) { 1133 AMCommonUtils.debug.message("AMStoreConnection.isValidEntry(): DN=" + dn); 1134 } 1135 1136 return dsServices.doesEntryExists(token, dn); 1137 } 1138 1139 /** 1140 * Bootstraps the Organization tree by creating the Top Organization tree. 1141 * 1142 * @param orgName 1143 * name of the top organization 1144 * @param avPairs 1145 * Attribute-Value pairs for the top organization 1146 * @return Top Organization object. 1147 * @throws AMException 1148 * if an error occurred during the process of creation. 1149 * @throws SSOException 1150 * if single sign on token is invalid or expired. 1151 */ 1152 public AMOrganization createTopOrganization(String orgName, Map avPairs) 1153 throws AMException, SSOException { 1154 StringBuilder orgDNSB = new StringBuilder(); 1155 orgDNSB 1156 .append( 1157 AMNamingAttrManager 1158 .getNamingAttr(AMObject.ORGANIZATION)).append( 1159 "=").append(orgName).append(",").append(rootSuffix); 1160 1161 AMOrganizationImpl orgImpl = new AMOrganizationImpl(this.token, orgDNSB 1162 .toString()); 1163 orgImpl.setAttributes(avPairs); 1164 orgImpl.create(); 1165 1166 return orgImpl; 1167 } 1168 1169 /** 1170 * This method takes an organization DN and purges all objects marked for 1171 * deletion. If the organization itself is marked for deletion, then a 1172 * recursive delete of everything under the organization is called, followed 1173 * by the organization deletion. This method works in the mode where 1174 * soft-delete option in Access Manager is turned on. The Pre/Post 1175 * <code>callbacks</code> for users are executed during this method. 1176 * 1177 * @param domainName 1178 * domain to be purged 1179 * @param graceperiod 1180 * time in days which should have passed since the entry was last 1181 * modified before it can be deleted from the system. 1182 * @throws AMException 1183 * if an error occurred when retrieving the information from the 1184 * data store. 1185 * @throws SSOException 1186 * if single sign on token is invalid or expired. 1187 */ 1188 public void purge(String domainName, int graceperiod) throws AMException, 1189 SSOException { 1190 String orgDN; 1191 Set orgSet; 1192 boolean deleted = false; 1193 if (AMDCTree.isRequired()) { 1194 orgDN = AMDCTree.getOrganizationDN(token, domainName); 1195 orgSet = new HashSet(); 1196 orgSet.add(orgDN); 1197 } else { 1198 // Use special org search filter for searching for deleted 1199 // organizations. 1200 String filter = AMCompliance 1201 .getDeletedObjectFilter(AMObject.ORGANIZATION); 1202 filter = AMObjectImpl.constructFilter(AMNamingAttrManager 1203 .getNamingAttr(AMObject.ORGANIZATION), filter, domainName); 1204 1205 if (AMCommonUtils.debug.messageEnabled()) { 1206 AMCommonUtils.debug.message("AMStoreConnection.purgeOrg: " 1207 + "Using org filter= " + filter); 1208 } 1209 1210 orgSet = dsServices.search(token, rootSuffix, filter, SCOPE_SUB); 1211 1212 if ((orgSet == null) || orgSet.isEmpty()) { 1213 orgSet = getOrganizations(domainName, null); 1214 deleted = false; 1215 } else { 1216 deleted = true; 1217 } 1218 } 1219 1220 if (orgSet == null || orgSet.isEmpty()) { 1221 return; 1222 } 1223 Iterator delIter = orgSet.iterator(); 1224 while (delIter.hasNext()) { 1225 orgDN = (String) delIter.next(); 1226 if (AMCommonUtils.debug.messageEnabled()) { 1227 AMCommonUtils.debug.message("AMStoreConnection.purge: " + "Organization= " 1228 + orgDN); 1229 } 1230 1231 AMOrganization org = getOrganization(orgDN); 1232 1233 // Check to see if grace period has expired. 1234 if (deleted && graceperiod < daysSinceModified(token, orgDN)) { 1235 // Delete all objects using the hardDelete method. 1236 org.purge(true, -1); 1237 } else { 1238 // Search for objects marked as deleted and 1239 // try to purge them, if graceperiod as expired. 1240 String filter = AMCompliance.getDeletedObjectFilter(-1); 1241 1242 if (AMCommonUtils.debug.messageEnabled()) { 1243 AMCommonUtils.debug.message("AMStoreConnection.purge: " 1244 + "Searching deleted objects. Filter: " + filter); 1245 } 1246 1247 Set deletedObjs = dsServices.search(token, orgDN, filter, 1248 SCOPE_SUB); 1249 1250 if (deletedObjs == null) { 1251 // No objecxts to delete 1252 if (AMCommonUtils.debug.messageEnabled()) { 1253 AMCommonUtils.debug.message("AMStoreConnection.purge: " 1254 + "No objects to be deleted found for " 1255 + orgDN); 1256 } 1257 } 1258 1259 Iterator iter = deletedObjs.iterator(); 1260 List list = new ArrayList(); 1261 1262 // get number of RDNs in the entry itself 1263 int entryRDNs = (new DN(orgDN)).countRDNs(); 1264 1265 // to count maximum level of RDNs in the search return 1266 int maxRDNCount = entryRDNs; 1267 1268 // go through all search results, add DN to the list, and 1269 // set the maximun RDN count, will be used to remove DNs 1270 while (iter.hasNext()) { 1271 String thisDN = (String) iter.next(); 1272 DN dn = new DN(thisDN); 1273 int count = dn.countRDNs(); 1274 1275 if (count > maxRDNCount) { 1276 maxRDNCount = count; 1277 } 1278 1279 list.add(dn); 1280 } 1281 1282 int len = list.size(); 1283 for (int i = maxRDNCount; i >= entryRDNs; i--) { 1284 for (int j = 0; j < len; j++) { 1285 // depending on object type, 1286 DN thisdn = (DN) list.get(j); 1287 1288 if (thisdn.countRDNs() == i) { 1289 String thisDN = thisdn.toRFCString(); 1290 int objType = getAMObjectType(thisDN); 1291 AMObject thisObj; 1292 1293 if (AMCommonUtils.debug.messageEnabled()) { 1294 AMCommonUtils.debug.message("AMStoreConnection:purgeOrg: " 1295 + "deleting child " + thisDN); 1296 } 1297 try { // catch PreCallBackException 1298 switch (objType) { 1299 case AMObject.USER: 1300 thisObj = getUser(thisDN); 1301 thisObj.purge(false, graceperiod); 1302 1303 break; 1304 1305 case AMObject.ASSIGNABLE_DYNAMIC_GROUP: 1306 thisObj = getAssignableDynamicGroup(thisDN); 1307 thisObj.purge(false, graceperiod); 1308 1309 break; 1310 1311 case AMObject.DYNAMIC_GROUP: 1312 thisObj = getDynamicGroup(thisDN); 1313 thisObj.purge(false, graceperiod); 1314 1315 break; 1316 1317 case AMObject.STATIC_GROUP: 1318 case AMObject.GROUP: 1319 thisObj = getStaticGroup(thisDN); 1320 thisObj.purge(false, graceperiod); 1321 1322 break; 1323 1324 case AMObject.RESOURCE: 1325 thisObj = getResource(thisDN); 1326 thisObj.purge(false, -1); 1327 break; 1328 1329 case AMObject.ORGANIZATION: 1330 thisObj = getOrganization(thisDN); 1331 1332 if (!(new DN(thisDN)).equals(new DN(orgDN))) 1333 { 1334 thisObj.purge(true, graceperiod); 1335 } 1336 1337 break; 1338 1339 default: 1340 1341 // should not show up in the searched 1342 // objects. 1343 // as none of the other objects are 1344 // supported 1345 // for being marked as soft-deleted/ 1346 // purging. 1347 break; 1348 } // switch 1349 } catch (AMPreCallBackException amp) { 1350 AMCommonUtils.debug.error("AMStoreConnection.purge: " 1351 + "Aborting delete of: " 1352 + thisDN 1353 + " due to pre-callback exception", 1354 amp); 1355 } 1356 } // if 1357 } // for 1358 } // for 1359 1360 } // else 1361 } // delIter 1362 1363 return; 1364 } 1365 1366 /** 1367 * This method takes a user ID and a domain name, It uses default search 1368 * templates to search for the organization and uses the deleted objects 1369 * search filter for Users as defined in the Administration Service of 1370 * Access Manager. This filter is used to search for the deleted user under 1371 * the organization. If the user is marked for deletion and the grace period 1372 * is passed then the user is purged. The pre-delete call backs as listed in 1373 * the Administration service, are called before the user is deleted. If any 1374 * of the <code>callbacks</code> throw an exception the delete operation 1375 * is aborted. 1376 * 1377 * @param uid 1378 * user ID 1379 * @param domainName 1380 * domain in which the user belongs. 1381 * @param graceperiod 1382 * time in days which should have passed before this user can be 1383 * deleted. 1384 * 1385 * @throws AMException 1386 * if there is an error in deleting the user, or if the user 1387 * <code>callbacks</code> thrown an exception 1388 * @throws SSOException 1389 */ 1390 public void purgeUser(String uid, String domainName, int graceperiod) 1391 throws AMException, SSOException { 1392 String orgDN = getOrganizationDN(domainName, null); 1393 String filter = AMCompliance.getDeletedObjectFilter(AMObject.USER); 1394 filter = AMObjectImpl.constructFilter(AMNamingAttrManager 1395 .getNamingAttr(AMObject.USER), filter, uid); 1396 1397 if (AMCommonUtils.debug.messageEnabled()) { 1398 AMCommonUtils.debug.message("AMStoreConnection.purgeGroup: " 1399 + "Using deleted user filter= " + filter); 1400 } 1401 1402 Set uSet = dsServices.search(token, orgDN, filter, SCOPE_SUB); 1403 1404 if ((uSet == null) || (uSet.size() > 1) || uSet.isEmpty()) { 1405 // throw an exception 1406 Object args[] = { uid }; 1407 throw new AMException(AMSDKBundle.getString("971", args, locale), 1408 "971", args); 1409 } 1410 1411 String uDN = (String) uSet.iterator().next(); 1412 AMUser user = getUser(uDN); 1413 user.purge(false, graceperiod); 1414 1415 return; 1416 } 1417 1418 /** 1419 * This method takes a resource ID and a domain name, It uses default search 1420 * templates to search for the organization and uses the deleted objects 1421 * search filter for Resources as defined in the Administration Service of 1422 * Access Manager. This filter is used to search for the deleted resource 1423 * under the organization. If the resource is marked for deletion and the 1424 * grace period is passed then the resource is purged. The pre-delete call 1425 * backs as listed in the Administration service, are called before the user 1426 * is deleted. If any of the <code>callbacks</code> throw an exception the 1427 * delete operation is aborted. 1428 * 1429 * @param rid 1430 * resource ID 1431 * @param domainName 1432 * domain in which the user belongs. 1433 * @param graceperiod 1434 * time in days which should have passed before this user can be 1435 * deleted. 1436 * 1437 * @throws AMException 1438 * if there is an error in deleting the user, or if the user 1439 * <code>callbacks</code> thrown an exception 1440 * @throws SSOException 1441 */ 1442 public void purgeResource(String rid, String domainName, int graceperiod) 1443 throws AMException, SSOException { 1444 String orgDN = getOrganizationDN(domainName, null); 1445 String filter = AMCompliance.getDeletedObjectFilter(AMObject.RESOURCE); 1446 filter = AMObjectImpl.constructFilter(AMNamingAttrManager 1447 .getNamingAttr(AMObject.RESOURCE), filter, rid); 1448 1449 if (AMCommonUtils.debug.messageEnabled()) { 1450 AMCommonUtils.debug.message("AMStoreConnection.purgeGroup: " 1451 + "Using deleted user filter= " + filter); 1452 } 1453 1454 Set uSet = dsServices.search(token, orgDN, filter, SCOPE_SUB); 1455 1456 if ((uSet == null) || (uSet.size() > 1) || uSet.isEmpty()) { 1457 // throw an exception 1458 Object args[] = { rid }; 1459 throw new AMException(AMSDKBundle.getString("971", args, locale), 1460 "971", args); 1461 } 1462 1463 String uDN = (String) uSet.iterator().next(); 1464 AMResource resource = getResource(uDN); 1465 resource.purge(false, graceperiod); 1466 1467 return; 1468 } 1469 1470 /** 1471 * This method takes a group name and a domain name, It uses default search 1472 * templates to search for the organization and uses the deleted objects 1473 * search filter for Groups as defined in the Administration Service of 1474 * Access Manager. This filter is used to search for the deleted user under 1475 * the organization. If the group is marked for deletion and the grace 1476 * period is passed then the group is purged. The pre-delete call backs as 1477 * listed in the Administration service, are called before the group is 1478 * deleted. If any of the <code>callbacks</code> throw an exception the 1479 * delete operation is aborted. 1480 * 1481 * @param gid 1482 * group name 1483 * @param domainName 1484 * domain in which the group belongs. 1485 * @param graceperiod 1486 * time in days which should have passed before this user can be 1487 * deleted. If a -1 is passed, group is deleted right away 1488 * without check on <code>graceperiod</code>. 1489 * 1490 * @throws AMException 1491 * if there is an error in deleting the group, or if the 1492 * <code>callbacks</code> thrown an exception 1493 * @throws SSOException 1494 */ 1495 public void purgeGroup(String gid, String domainName, int graceperiod) 1496 throws AMException, SSOException { 1497 String orgDN = getOrganizationDN(domainName, null); 1498 String filter = AMCompliance.getDeletedObjectFilter(AMObject.GROUP); 1499 filter = AMObjectImpl.constructFilter(AMNamingAttrManager 1500 .getNamingAttr(AMObject.GROUP), filter, gid); 1501 1502 if (AMCommonUtils.debug.messageEnabled()) { 1503 AMCommonUtils.debug.message("AMStoreConnection.purgeGroup: " 1504 + "Using deleted group filter= " + filter); 1505 } 1506 1507 Set gSet = dsServices.search(token, orgDN, filter, SCOPE_SUB); 1508 1509 if ((gSet == null) || (gSet.size() > 1) || gSet.isEmpty()) { 1510 // throw an exception 1511 Object args[] = { gid }; 1512 throw new AMException(AMSDKBundle.getString("971", args, locale), 1513 "971", args); 1514 } 1515 1516 String uDN = (String) gSet.iterator().next(); 1517 AMGroup g = null; 1518 int type = getAMObjectType(uDN); 1519 switch (type) { 1520 case AMObject.GROUP: 1521 case AMObject.STATIC_GROUP: 1522 g = new AMStaticGroupImpl(token, uDN); 1523 break; 1524 case AMObject.ASSIGNABLE_DYNAMIC_GROUP: 1525 g = new AMAssignableDynamicGroupImpl(token, uDN); 1526 break; 1527 case AMObject.DYNAMIC_GROUP: 1528 g = new AMDynamicGroupImpl(token, uDN); 1529 break; 1530 default: 1531 } 1532 if (g != null) { 1533 g.purge(false, graceperiod); 1534 } 1535 return; 1536 } 1537 1538 /** 1539 * Returns a set of <code>com.iplanet.am.sdk.AMEntityType</code> objects, 1540 * which is the set of objects which are supported by the 1541 * <code>com.iplanet.am.sdk.AMEntity</code> APIs. 1542 * 1543 * @return Set of <code>AMEntityType</code> objects. 1544 */ 1545 public Set getEntityTypes() { 1546 return AMCommonUtils.getSupportedEntityTypes(); 1547 } 1548 1549 protected String getBaseDN(ServiceConfig sc) { 1550 if (sc != null) { 1551 Map attrMap = sc.getAttributes(); 1552 Set vals = (Set) attrMap.get("baseDN"); 1553 1554 if ((vals == null) || vals.isEmpty()) { 1555 return null; 1556 } else { 1557 Iterator it = vals.iterator(); 1558 1559 return ((String) it.next()); 1560 } 1561 } else { 1562 return null; 1563 } 1564 } 1565 1566 protected boolean isRFC2247(ServiceConfig sc) { 1567 // ServiceConfig sc = getSearchTemplateConfig(orgTemplate); 1568 if (sc != null) { 1569 Map attrMap = sc.getAttributes(); 1570 Set vals = (Set) attrMap.get("rfc2247flag"); 1571 1572 if ((vals == null) || (vals.isEmpty())) { 1573 return (false); 1574 } else { 1575 Iterator it = vals.iterator(); 1576 1577 return (((String) it.next()).equalsIgnoreCase("true") ? true 1578 : false); 1579 } 1580 } else { 1581 return (false); 1582 } 1583 } 1584 1585 /** 1586 * Protected method to update the <code>orgMapCache</code> 1587 * 1588 */ 1589 protected static void addToOrgMapCache(SSOToken stoken, String dn) 1590 throws AMException, SSOException { 1591 if ((dn == null) || !DN.isDN(dn)) { 1592 return; 1593 } 1594 1595 // String rfcDN = (new DN(dn)).toRFCString().toLowerCase(); 1596 String rfcDN = dn; 1597 Set attrNames = new HashSet(); 1598 attrNames.add("objectclass"); 1599 attrNames.add("sunpreferreddomain"); 1600 attrNames.add("associateddomain"); 1601 attrNames.add("sunorganizationalias"); 1602 1603 Map attributes = AMDirectoryAccessFactory.getDirectoryServices() 1604 .getAttributes(stoken, dn, attrNames, AMObject.ORGANIZATION); 1605 1606 // Add to cache 1607 String rdn = LDAPDN.explodeDN(dn, true)[0]; 1608 Set prefDomain = (Set) attributes.get("sunpreferreddomain"); 1609 Set associatedDomain = (Set) attributes.get("associateddomain"); 1610 Set orgAlias = (Set) attributes.get("sunorganizationalias"); 1611 1612 synchronized (orgMapCache) { 1613 orgMapCache.put(rdn.toLowerCase(), rfcDN); 1614 1615 if ((prefDomain != null) && (prefDomain.size() == 1)) { 1616 String preferredDomain = (String) prefDomain.iterator().next(); 1617 1618 // AMHashMap so no need to lowercase 1619 orgMapCache.put(preferredDomain, rfcDN); 1620 } 1621 1622 if ((associatedDomain != null) && !associatedDomain.isEmpty()) { 1623 Iterator itr = associatedDomain.iterator(); 1624 1625 while (itr.hasNext()) { 1626 String value = (String) itr.next(); 1627 orgMapCache.put(value, rfcDN); 1628 } 1629 } 1630 1631 if ((orgAlias != null) && !orgAlias.isEmpty()) { 1632 Iterator itr = orgAlias.iterator(); 1633 1634 while (itr.hasNext()) { 1635 String value = (String) itr.next(); 1636 orgMapCache.put(value, rfcDN); 1637 } 1638 } 1639 } 1640 } 1641 1642 /** 1643 * Protected method to obtain the number of days since this DN was last 1644 * modified. 1645 */ 1646 protected static int daysSinceModified(SSOToken stoken, String entryDN) 1647 throws AMException, SSOException { 1648 NumberFormat nf = NumberFormat.getInstance(); 1649 SimpleDateFormat df = new SimpleDateFormat("yyyyMMddhhmmss"); 1650 ParsePosition pp = new ParsePosition(0); 1651 1652 Set attrNames = new HashSet(1); 1653 1654 // Why are we adding objectclass when it is not being used? 1655 // If a specific reason, then we need to change the method call. 1656 // Same question applicable to other places where we add into orgmap 1657 // cache 1658 // attrNames.add("objectclass"); 1659 attrNames.add("modifytimestamp"); 1660 1661 Map attributes = AMDirectoryAccessFactory.getDirectoryServices() 1662 .getAttributes(stoken, entryDN, attrNames, 1663 AMObject.UNDETERMINED_OBJECT_TYPE); 1664 Set values = (Set) attributes.get("modifytimestamp"); 1665 1666 if ((values == null) || values.isEmpty()) { 1667 return -1; 1668 } 1669 1670 String value = (String) values.iterator().next(); 1671 1672 if ((value == null) || value.length() == 0) { 1673 return -1; 1674 } 1675 1676 Number n; 1677 1678 try { 1679 n = nf.parse(value); 1680 } catch (ParseException pe) { 1681 if (AMCommonUtils.debug.warningEnabled()) { 1682 AMCommonUtils.debug.warning("AMStoreConnection.daysSinceModified: " 1683 + "unable to parse date: " + value 1684 + " :Returning default= -1", pe); 1685 } 1686 1687 return (-1); 1688 } 1689 1690 Date modDate = df.parse(n.toString(), pp); 1691 Date nowDate = new Date(); 1692 1693 // getTime() fn returns number of milliseconds 1694 // since January 1, 1970, 00:00:00 GMT 1695 long modTimeMSecs = modDate.getTime(); 1696 long nowTimeMSecs = nowDate.getTime(); 1697 1698 long elapsedTimeMSecs = nowTimeMSecs - modTimeMSecs; 1699 int elapsedDays = (int) (elapsedTimeMSecs / (1000 * 60 * 60 * 24)); 1700 1701 if (AMCommonUtils.debug.messageEnabled()) { 1702 AMCommonUtils.debug.message("AMStoreConnection.daysSinceModified() for dn: " 1703 + entryDN + ", days: " + elapsedDays + " days"); 1704 } 1705 1706 return (elapsedDays); 1707 } 1708 1709 /** 1710 * Protected method to update <code>orgMapCache</code>. 1711 */ 1712 protected static void updateCache(String dn, int eventType) { 1713 if ((dn == null) || !DN.isDN(dn)) { 1714 return; 1715 } 1716 1717 String rfcDN = AMCommonUtils.formatToRFC(dn); 1718 switch (eventType) { 1719 case AMEvent.OBJECT_ADDED: 1720 // nothing to do 1721 return; 1722 1723 case AMEvent.OBJECT_RENAMED: 1724 synchronized (orgMapCache) { 1725 orgMapCache.clear(); 1726 } 1727 return; 1728 1729 case AMEvent.OBJECT_REMOVED: 1730 case AMEvent.OBJECT_CHANGED: 1731 // Go through the entire cache and check and delete 1732 // any entries with values matching this DN 1733 synchronized (orgMapCache) { 1734 Iterator keys = orgMapCache.keySet().iterator(); 1735 1736 // String removeKey = null; 1737 Set removeKeys = new HashSet(); 1738 1739 while (keys.hasNext()) { 1740 String key = (String) keys.next(); 1741 String val = (String) orgMapCache.get(key); 1742 1743 if (val.equalsIgnoreCase(rfcDN)) { 1744 removeKeys.add(key); 1745 } 1746 } 1747 1748 if (removeKeys != null) { 1749 keys = removeKeys.iterator(); 1750 1751 while (keys.hasNext()) { 1752 String removeKey = (String) keys.next(); 1753 orgMapCache.remove(removeKey); 1754 } 1755 } 1756 // orgMapCache.clear(); 1757 } 1758 } 1759 } 1760 1761 private Set getOrganizations(String domainname, String orgSearchTemplate) 1762 throws AMException, SSOException { 1763 if (domainname == null) { 1764 return Collections.EMPTY_SET; 1765 } 1766 1767 // use the searchfilter to obtain organization DN 1768 // replace %V with domainname. 1769 String searchFilter = AMSearchFilterManager.getSearchFilter( 1770 AMObject.ORGANIZATION, null, orgSearchTemplate, false); 1771 1772 if ((orgSearchTemplate != null) && (searchFilter.indexOf("%V") > -1)) { 1773 searchFilter = AMObjectImpl.constructFilter(AMNamingAttrManager 1774 .getNamingAttr(AMObject.ORGANIZATION), searchFilter, 1775 domainname); 1776 } else { 1777 StringBuilder sb = new StringBuilder(); 1778 sb.append("(|(&(").append( 1779 AMNamingAttrManager.getNamingAttr(AMObject.ORGANIZATION)) 1780 .append("=").append(domainname).append(")").append( 1781 searchFilter).append(")(&(").append( 1782 "sunPreferredDomain=").append(domainname).append( 1783 ")").append(searchFilter).append(")(&(").append( 1784 "associatedDomain=").append(domainname).append(")") 1785 .append(searchFilter).append(")(&(").append( 1786 "sunOrganizationAlias=").append(domainname).append( 1787 ")").append(searchFilter).append("))"); 1788 searchFilter = sb.toString(); 1789 } 1790 1791 if (AMCommonUtils.debug.messageEnabled()) { 1792 AMCommonUtils.debug.message("AMSC:getOrgDN-> " + "using searchfilter " 1793 + searchFilter); 1794 } 1795 1796 Set orgSet = dsServices.search(token, rootSuffix, searchFilter, 1797 SCOPE_SUB); 1798 return orgSet; 1799 } 1800 1801 /** 1802 * Converts organization name which is "/" separated to DN. 1803 */ 1804 private static String orgNameToDN(String orgName) { 1805 // Check if it is null or empty 1806 if ((orgName == null) || (orgName.length() == 0)) { 1807 return (rootSuffix); 1808 } 1809 1810 // Check if it is org name 1811 if (DN.isDN(orgName)) { 1812 return (orgName); 1813 } 1814 1815 // Construct the DN 1816 StringBuilder buf = new StringBuilder(); 1817 ArrayList arr = new ArrayList(); 1818 StringTokenizer strtok = new StringTokenizer(orgName, "/"); 1819 1820 while (strtok.hasMoreElements()) { 1821 arr.add(strtok.nextToken()); 1822 } 1823 1824 int size = arr.size(); 1825 1826 for (int i = 0; i < size; i++) { 1827 String theOrg = (String) arr.get(i); 1828 buf 1829 .append(AMNamingAttrManager 1830 .getNamingAttr(AMObject.ORGANIZATION)); 1831 buf.append('=').append(theOrg).append(','); 1832 } 1833 1834 if (rootSuffix.length() > 0) { 1835 buf.append(rootSuffix); 1836 } else { 1837 buf.deleteCharAt(buf.length() - 1); 1838 } 1839 1840 return (buf.toString()); 1841 } 1842}