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: DynamicGroup.java,v 1.6 2009/01/28 05:34:50 ww203982 Exp $ 026 * 027 */ 028 029/** 030 * Portions Copyrighted [2011] [ForgeRock AS] 031 */ 032package com.iplanet.ums; 033 034import com.iplanet.services.ldap.Attr; 035import com.iplanet.services.ldap.AttrSet; 036import com.iplanet.services.ldap.ModSet; 037import com.iplanet.services.util.I18n; 038import com.sun.identity.shared.debug.Debug; 039import com.sun.identity.shared.encode.URLEncDec; 040import java.security.Principal; 041import com.sun.identity.shared.ldap.LDAPDN; 042import com.sun.identity.shared.ldap.LDAPUrl; 043import com.sun.identity.shared.ldap.LDAPv2; 044 045/** 046 * Represents a dynamic group entry. 047 * 048 * @supported.api 049 */ 050public class DynamicGroup extends PersistentObject implements 051 IDynamicMembership { 052 053 private static I18n i18n = I18n.getInstance(IUMSConstants.UMS_PKG); 054 055 private static Debug debug; 056 static { 057 debug = Debug.getInstance(IUMSConstants.UMS_DEBUG); 058 } 059 060 /** 061 * Default constructor. 062 */ 063 protected DynamicGroup() { 064 } 065 066 /** 067 * Constructs a group object from an ID by reading from persistent storage. 068 * 069 * @param session Authenticated session. 070 * @param guid globally unique identifier for the group entry. 071 * @exception UMSException if fail to instantiate from persistent storage. 072 * @deprecated 073 */ 074 DynamicGroup(Principal principal, Guid guid) throws UMSException { 075 super(principal, guid); 076 verifyClass(); 077 } 078 079 /** 080 * Constructs a <code>DynamicGroup</code> in memory using the default 081 * registered template for <code>DynamicGroup</code>. This is an 082 * in-memory representation of a new object and one needs to call the 083 * <code>save</code> method to save this new object to persistent storage. 084 * 085 * @param attrSet Attribute/value set, which should contain 086 * <code>memberUrl</code>. 087 * @exception UMSException if fail to instantiate from persistent storage. 088 */ 089 DynamicGroup(AttrSet attrSet) throws UMSException { 090 this(TemplateManager.getTemplateManager().getCreationTemplate(_class, 091 null), attrSet); 092 } 093 094 /** 095 * Constructs a <code>DynamicGroup</code> in memory with a given template 096 * for <code>DynamicGroup</code>. This is an in-memory representation of a 097 * new object; the <code>save</code> method must be called to save this 098 * new object to persistent storage. 099 * 100 * @param template Template for creating a group. 101 * @param attrSet Attribute/value set, which should contain 102 * <code>memberUrl</code>. 103 * @exception UMSException if fail to instantiate from persistent storage. 104 * 105 * @supported.api 106 */ 107 public DynamicGroup(CreationTemplate template, AttrSet attrSet) 108 throws UMSException { 109 super(template, attrSet); 110 } 111 112 /** 113 * Constructs a <code>DynamicGroup</code> in memory using the default 114 * registered template for <code>DynamicGroup</code>. This is an in memory 115 * representation of a new object and the <code>save</code> method must be 116 * called to save this new object to persistent storage. 117 * 118 * @param attrSet Attribute/value set, which should not contain 119 * <code>memberUrl</code>; any values of <code>memberUrl</code> will 120 * be overwritten by the explicit search criteria arguments. 121 * @param base Search base for evaluating members of the group. 122 * @param filter Search filter for evaluating members of the group. 123 * @param scope Search scope for evaluating members of the group. 124 * @exception UMSException if fail to instantiate from persistent storage. 125 */ 126 DynamicGroup(AttrSet attrSet, Guid baseGuid, String filter, int scope) 127 throws UMSException { 128 this(TemplateManager.getTemplateManager().getCreationTemplate(_class, 129 null), attrSet, baseGuid, filter, scope); 130 } 131 132 /** 133 * Constructs a <code>DynamicGroup</code> in memory given a template for 134 * <code>DynamicGroup</code>. This is an in-memory representation of a new 135 * object and the <code>save</code> method must be called to save this new 136 * object to persistent storage. 137 * 138 * @param template Template for creating a group. 139 * @param attrSet Attribute/value set, which should not contain member Url; 140 * any values of memberUrl will be overwritten by the explicit search 141 * criteria arguments. 142 * @param baseGuid Search base for evaluating members of the group. 143 * @param filter Search filter for evaluating members of the group. 144 * @param scope Search scope for evaluating members of the group has to be 145 * <code>LDAPv2.SCOPE_ONE</code> or <code>LDAPv2.SCOPE_SUB</code>. 146 * 147 * @exception UMSException if fail to instantiate from persistent storage. 148 * 149 * @supported.api 150 */ 151 public DynamicGroup( 152 CreationTemplate template, 153 AttrSet attrSet, 154 Guid baseGuid, 155 String filter, 156 int scope 157 ) throws UMSException { 158 super(template, attrSet); 159 try { 160 setUrl(baseGuid, filter, scope); 161 } catch (Exception e) { 162 // TODO - Log Exception 163 debug.error("DynamicGroup : Exception : " + e.getMessage()); 164 } 165 } 166 167 /** 168 * Sets the search filter used to evaluate this dynamic group. 169 * 170 * @param filter Search filter for evaluating members of the group. 171 * 172 * @supported.api 173 */ 174 public void setSearchFilter(String filter) { 175 LDAPUrl url = getUrl(); 176 int scope = url.getScope(); 177 178 Guid baseGuid = new Guid(url.getDN()); 179 try { 180 setUrl(baseGuid, filter, scope); 181 } catch (Exception e) { 182 // TODO - Log Exception 183 debug.error("DynamicGroup.setSearchFilter : Exception : " 184 + e.getMessage()); 185 } 186 } 187 188 /** 189 * Returns the search filter used to evaluate this dynamic group. 190 * 191 * @return Search filter for evaluating members of the group the scope in 192 * the filter has to be <code>LDAPv2.SCOPE_ONE</code> or 193 * <code>LDAPv2.SCOPE_SUB</code>. 194 * 195 * @supported.api 196 */ 197 public String getSearchFilter() { 198 return getUrl().getFilter(); 199 } 200 201 /** 202 * Sets the search base used to evaluate this dynamic group. 203 * 204 * @param baseGuid Search base for evaluating members of the group. 205 * 206 * @supported.api 207 */ 208 public void setSearchBase(Guid baseGuid) { 209 LDAPUrl url = getUrl(); 210 int scope = url.getScope(); 211 String filter = url.getFilter(); 212 try { 213 setUrl(baseGuid, filter, scope); 214 } catch (Exception e) { 215 // TODO - Log Exception 216 debug.error("DynamicGroup.setSearchFilter : Exception : " 217 + e.getMessage()); 218 } 219 } 220 221 /** 222 * Returns the search base used to evaluate this dynamic group. 223 * 224 * @return Search base for evaluating members of the group. 225 * 226 * @supported.api 227 */ 228 public Guid getSearchBase() { 229 return new Guid(getUrl().getDN()); 230 } 231 232 /** 233 * Sets the search scope used to evaluate this dynamic group. 234 * 235 * @param scope Search scope for evaluating members of the group. Use one of 236 * the search scope <code>SCOPE_BASE</code>, 237 * <code>SCOPE_ONE</code>, or <code>SCOPE_SUB</code>. 238 * 239 * @supported.api 240 */ 241 public void setSearchScope(int scope) { 242 LDAPUrl url = getUrl(); 243 Guid baseGuid = new Guid(url.getDN()); 244 String filter = url.getFilter(); 245 try { 246 setUrl(baseGuid, filter, scope); 247 } catch (Exception e) { 248 // TODO - Log Exception 249 debug.error("DynamicGroup.setSearchFilter : Exception : " 250 + e.getMessage()); 251 } 252 } 253 254 /** 255 * Returns the search scope used to evaluate this dynamic group. 256 * 257 * @return Search scope for evaluating members of the group. 258 * 259 * @supported.api 260 */ 261 public int getSearchScope() { 262 return getUrl().getScope(); 263 } 264 265 /** 266 * Convert the given parameters into an LDAP URL string. No LDAP host, port, 267 * and attribute to return are present in the LDAP URL. Only search base, 268 * filter and scope are given. 269 * 270 * @param base Search Base DN in the LDAP URL. 271 * @param filter Search filter in LDAP URL. 272 * @param scope Search scope in LDAP URL. 273 * @return LDAP URL. 274 */ 275 protected String toUrlStr(String base, String filter, int scope) { 276 StringBuilder urlBuf = new StringBuilder(); 277 urlBuf.append("ldap:///").append(base).append("?"); 278 279 switch (scope) { 280 case LDAPv2.SCOPE_BASE: 281 urlBuf.append("?base"); 282 break; 283 case LDAPv2.SCOPE_ONE: 284 urlBuf.append("?one"); 285 break; 286 default: 287 case LDAPv2.SCOPE_SUB: 288 urlBuf.append("?sub"); 289 break; 290 } 291 292 if (filter != null && filter.length() > 0) { 293 urlBuf.append("?").append(filter); 294 } else { 295 urlBuf.append("?"); 296 } 297 298 return urlBuf.toString(); 299 } 300 301 /** 302 * Creates a new search definition; the change is not persistent until 303 * save() is called. 304 * 305 * @param baseGuid Search base for evaluating members of the group. 306 * @param filter Search filter for evaluating members of the group. 307 * @param scope Search scope for evaluating members of the group. 308 */ 309 protected void setUrl(Guid baseGuid, String filter, int scope) { 310 // Only valid scope is "sub" and "one" 311 // 312 if (scope != LDAPv2.SCOPE_ONE && scope != LDAPv2.SCOPE_SUB) { 313 String msg = i18n.getString(IUMSConstants.ILLEGAL_GROUP_SCOPE); 314 throw new IllegalArgumentException(msg); 315 } 316 317 String urlStr = toUrlStr(baseGuid.getDn(), filter, scope); 318 319 // Sanity check on the url 320 // 321 try { 322 new LDAPUrl(urlStr); 323 } catch (java.net.MalformedURLException e) { 324 throw new IllegalArgumentException(e.getMessage()); 325 } 326 327 // TODO: Need to support multiple values of memberUrl? If so, do 328 // an ADD instead of a replace. 329 // 330 modify(new Attr(MEMBER_URL_NAME, urlStr), ModSet.REPLACE); 331 } 332 333 /** 334 * Returns the native LDAP URL used to evaluate this dynamic group. 335 * 336 * @return LDAP URL for evaluating members of the group 337 */ 338 protected LDAPUrl getUrl() { 339 Attr attr = getAttribute(MEMBER_URL_NAME); 340 LDAPUrl url = null; 341 try { 342 // TODO: Need to support multiple values of memberUrl? 343 if ((attr != null) && (attr.getStringValues().length > 0)) { 344 345 // Converting the url string to 346 // application/x-www-form-urlencoded as expected by 347 // LDAPUrl constructor. 348 url = new LDAPUrl(URLEncDec.encodeLDAPUrl(attr 349 .getStringValues()[0])); 350 } 351 if (url == null) { 352 url = new LDAPUrl(null, 0, "", (String[]) null, 353 LDAPv2.SCOPE_ONE, ""); 354 } 355 } catch (java.net.MalformedURLException ex) { 356 debug.error("DynamicGroup.setSearchFilter : Exception : " 357 + ex.getMessage()); 358 throw new IllegalArgumentException(ex.getMessage()); 359 } 360 return url; 361 } 362 363 /** 364 * Sets the native LDAP URL used to evaluate this dynamic group. 365 * 366 * @param url LDAP URL for evaluating members of the group search scope in 367 * the url has to be <code>LDAPv2.SCOPE_ONE</code> or 368 * <code>LDAPv2.SCOPE_SUB</code>. 369 */ 370 protected void setUrl(LDAPUrl url) { 371 String ldapurl = url.toString(); 372 try { 373 ldapurl = LDAPUrl.decode(ldapurl); 374 } catch (Exception ex) { 375 if (debug.messageEnabled()) { 376 debug.message("DynamicGroup.setUrl : " + 377 "Exception:" + ex.getMessage()); 378 } 379 } 380 if (url.getScope() != LDAPv2.SCOPE_ONE 381 && url.getScope() != LDAPv2.SCOPE_SUB) { 382 String msg = i18n.getString(IUMSConstants.ILLEGAL_GROUP_SCOPE); 383 throw new IllegalArgumentException(msg); 384 } 385 // TODO: Need to support multiple values of memberUrl? If so, do 386 // an ADD instead of a replace. 387 modify(new Attr(MEMBER_URL_NAME, ldapurl), ModSet.REPLACE); 388 // modify( new Attr( MEMBER_URL_NAME, url.toString() ), ModSet.ADD ); 389 } 390 391 /** 392 * Returns the members of the group. 393 * 394 * @param attributes Attributes to return. 395 * @return Iterator for unique identifiers for members of the group. 396 * @exception UMSException if fail to search. 397 */ 398 protected SearchResults getMemberIDs(String[] attributes) 399 throws UMSException { 400 return DataLayer.getInstance().search(getPrincipal(), getSearchBase(), 401 getSearchScope(), getSearchFilter(), attributes, false, null); 402 } 403 404 /** 405 * Returns the members of the group. 406 * 407 * @return Iterator for unique identifiers for members of the group. 408 * @exception UMSException if fail to search. 409 * 410 * @supported.api 411 */ 412 public SearchResults getMemberIDs() throws UMSException { 413 String[] attributesToGet = { "objectclass" }; 414 return getMemberIDs(attributesToGet); 415 } 416 417 /** 418 * Returns the member count. 419 * 420 * @return Number of members of the group. 421 * @exception UMSException if fail to search. 422 * 423 * @supported.api 424 */ 425 public int getMemberCount() throws UMSException { 426 int count = 0; 427 String[] attributesToGet = { "dn" }; 428 SearchResults searchResults = getMemberIDs(attributesToGet); 429 while (searchResults.hasMoreElements()) { 430 searchResults.next().getDN(); 431 count++; 432 } 433 return count; 434 } 435 436 /** 437 * Returns a member given an index (zero-based). 438 * 439 * @param index Zero-based index into the group container. 440 * @return Unique identifier for a member. 441 * @exception UMSException if fail to search. 442 * 443 * @supported.api 444 */ 445 public Guid getMemberIDAt(int index) throws UMSException { 446 if (index < 0) { 447 throw new IllegalArgumentException(Integer.toString(index)); 448 } 449 String filter = getSearchFilter(); 450 if (filter == null) { 451 return null; 452 } 453 String[] attributesToGet = { "dn" }; 454 SearchResults searchResults = getMemberIDs(attributesToGet); 455 while (searchResults.hasMoreElements()) { 456 String s = searchResults.next().getDN(); 457 if (index == 0) { 458 searchResults.abandon(); 459 return new Guid(s); 460 } 461 index--; 462 } 463 throw new ArrayIndexOutOfBoundsException(Integer.toString(index)); 464 } 465 466 /** 467 * Returns <code>true</code> if a given identifier is a member of the 468 * group. 469 * 470 * @param guid Identity of member to be checked for membership. 471 * @return <code>true</code> if it is a member. 472 * @exception UMSException if fail to evaluate group 473 * 474 * @supported.api 475 */ 476 public boolean hasMember(Guid guid) throws UMSException { 477 String filter = getSearchFilter(); 478 if (filter == null) { 479 return false; 480 } 481 // Narrow the filter by using the RDN of the target 482 // TODO: Should not have to use a DN here 483 String dn = guid.getDn(); 484 String rdn = LDAPDN.explodeDN(dn, false)[0]; 485 filter = "(&" + filter + "(" + rdn + "))"; 486 String[] attributesToGet = { "dn" }; 487 SearchResults searchResults = DataLayer.getInstance().search( 488 getPrincipal(), getSearchBase(), getSearchScope(), filter, 489 attributesToGet, false, null); 490 while (searchResults.hasMoreElements()) { 491 String s = searchResults.next().getDN(); 492 if (Guid.equals(s, dn)) { 493 searchResults.abandon(); 494 return true; 495 } 496 } 497 return false; 498 } 499 500 private static final String MEMBER_URL_NAME = "memberurl"; 501 502 private static final Class _class = com.iplanet.ums.DynamicGroup.class; 503}
Copyright © 2010-2017, ForgeRock All Rights Reserved.