001/* 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 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: SubjectTypeManager.java,v 1.5 2009/01/28 05:35:01 ww203982 Exp $ 026 * 027 * Portions Copyrighted 2014-2015 ForgeRock AS. 028 */ 029 030package com.sun.identity.policy; 031 032import java.util.*; 033 034import com.iplanet.am.sdk.AMCommonUtils; 035import com.iplanet.sso.SSOToken; 036import com.iplanet.sso.SSOException; 037import com.sun.identity.sm.*; 038import com.sun.identity.policy.interfaces.Subject; 039import com.sun.identity.shared.locale.AMResourceBundleCache; 040import com.sun.identity.shared.debug.Debug; 041import com.sun.identity.shared.locale.Locale; 042import org.forgerock.openam.ldap.LDAPUtils; 043 044/** 045 * The class <code>SubjectTypeManager</code> provides 046 * methods to get a list of configured <code>Subject 047 * </code> objects, and to obtain a factory object for it. 048 * 049 * @supported.all.api 050 * @deprecated since 12.0.0 051 */ 052@Deprecated 053public class SubjectTypeManager { 054 055 private static String SUBJECT = "Subject"; 056 057 private SSOToken token; 058 private PolicyManager pm; 059 060 private ResourceBundle rb; 061 private Subjects realmSubjects = null; 062 private Map sharedSubjects = Collections.synchronizedMap(new HashMap()); 063 private static AMResourceBundleCache amCache = 064 AMResourceBundleCache.getInstance(); 065 private String pmRealmName; 066 067 static Debug debug = PolicyManager.debug; 068 069 /** 070 * Constructs a <code>SubjectTypeManager</code> object 071 */ 072 protected SubjectTypeManager() throws SSOException { 073 token = ServiceTypeManager.getSSOToken(); 074 String lstr = token.getProperty("Locale"); 075 java.util.Locale loc = com.sun.identity.shared.locale.Locale.getLocale( 076 lstr); 077 rb = amCache.getResBundle(ResBundleUtils.rbName, loc); 078 } 079 080 /** 081 * Constructs a <code>SubjectTypeManager</code> object 082 * @param pm <code>PolicyManager</code> to initialize 083 * <code>SubjectTypeManager</code> with 084 */ 085 protected SubjectTypeManager(PolicyManager pm) { 086 this.pm = pm; 087 pmRealmName = LDAPUtils.formatToRFC(pm.getOrganizationDN()); 088 token = pm.token; 089 java.util.Locale loc; 090 try { 091 String lstr = token.getProperty("Locale"); 092 loc = com.sun.identity.shared.locale.Locale.getLocale(lstr); 093 } catch (SSOException ex) { 094 debug.error( 095 "SubjectTypeManager:Unable to retreive locale from SSOToken", 096 ex); 097 loc = Locale.getDefaultLocale(); 098 } 099 100 if (debug.messageEnabled()) { 101 debug.message("SubjectManager locale="+loc+"\tI18nFileName = "+ 102 ResBundleUtils.rbName); 103 } 104 rb = amCache.getResBundle(ResBundleUtils.rbName, loc); 105 } 106 107 /** 108 * Returns a set of all valid subject type names defined by the policy 109 * service. 110 * Examples are <code>LDAPRole</code>, <code>LDAPGroup</code>, etc. 111 * 112 * @return a set of all valid subject type names defined by the policy 113 * service. 114 * @throws SSOException if the <code>SSOToken</code> used to create 115 * the <code>PolicyManager</code> has become invalid 116 * @throws PolicyException for any other abnormal condition 117 */ 118 public Set getSubjectTypeNames() throws SSOException, 119 PolicyException { 120 return (PolicyManager.getPluginSchemaNames(SUBJECT)); 121 } 122 123 /** 124 * Returns a set of valid subject type names configured for the 125 * organization. 126 * Examples are <code>LDAPRole</code>, <code>LDAPGroup</code>, etc. 127 * 128 * @return a set of valid subject type names configured for the 129 * organization. 130 * @throws SSOException if the <code>SSOToken</code> used to create 131 * the <code>PolicyManager</code> has become invalid 132 * @throws PolicyException for any other abnormal condition 133 */ 134 public Set getSelectedSubjectTypeNames() throws SSOException, 135 PolicyException { 136 Map policyConfig = pm.getPolicyConfig(); 137 Set selectedSubjects = null; 138 if (policyConfig != null) { 139 selectedSubjects = 140 (Set)policyConfig.get(PolicyConfig.SELECTED_SUBJECTS); 141 } 142 if ( selectedSubjects == null) { 143 selectedSubjects = Collections.EMPTY_SET; 144 } 145 return selectedSubjects; 146 } 147 148 /** 149 * Returns the type of the <code>Subject</code> implementation. 150 * For example <code>LDAPRoles</code>, <code>LDAPGroups</code> etc. 151 * 152 * @param subject <code>Subject</code> for which this method will 153 * return its associated type 154 * 155 * @return type of the <code>Subject</code>, e.g., <code>LDAPRoles</code>, 156 * <code>LDAPGroups</code>, etc. Returns <code>null</code> if 157 * not present. 158 */ 159 public String getSubjectTypeName(Subject subject) { 160 return (subjectTypeName(subject)); 161 } 162 163 /** 164 * Returns the I18N properties file name that should be 165 * used to localize display names for the given 166 * subject type. 167 * 168 * @param subjectType subject type name 169 * 170 * @return i18n properties file name 171 */ 172 protected String getI18NPropertiesFileName(String subjectType) { 173 // %%% Need to get the file name from plugin schema 174 return (null); 175 } 176 177 /** 178 * Returns the I18N key to be used to localize the 179 * display name for the subject type name. 180 * 181 * @param subjectType subject type name 182 * 183 * @return i18n key to obtain the display name 184 */ 185 public String getI18NKey(String subjectType) { 186 PluginSchema ps = PolicyManager.getPluginSchema(SUBJECT, subjectType); 187 if (ps != null) { 188 return (ps.getI18NKey()); 189 } 190 return (null); 191 } 192 193 /** 194 * Returns the display name for the subject type 195 * @param subjectType subject type 196 * @return display name for the subject type 197 */ 198 public String getDisplayName(String subjectType) { 199 String displayName = null; 200 String i18nKey = getI18NKey(subjectType); 201 if (i18nKey == null || i18nKey.length() == 0) { 202 displayName = subjectType; 203 } else { 204 displayName = Locale.getString(rb,i18nKey,debug); 205 } 206 return displayName; 207 } 208 209 /** 210 * Returns an instance of the <code>Subject</code> given the subject type 211 * name. 212 * 213 * @param subjectType subject type. 214 * @return an instance of the <code>Subject</code> given the subject type 215 * name. 216 * @throws NameNotFoundException if the <code>Subject</code> for the 217 * <code>subjectType</code> name is not found 218 * @throws PolicyException for any other abnormal condition 219 */ 220 public Subject getSubject(String subjectType) 221 throws NameNotFoundException, PolicyException { 222 PluginSchema ps = PolicyManager.getPluginSchema(SUBJECT, subjectType); 223 if (ps == null) { 224 throw (new NameNotFoundException(ResBundleUtils.rbName, 225 "invalid_subject", null, 226 subjectType, PolicyException.USER_COLLECTION)); 227 } 228 229 // Construct the object 230 Subject answer = null; 231 try { 232 String className = ps.getClassName(); 233 answer = (Subject) Class.forName(className).newInstance(); 234 } catch (Exception e) { 235 throw (new PolicyException(e)); 236 } 237 238 //initialize with policy config 239 answer.initialize(pm.getPolicyConfig()); 240 return (answer); 241 } 242 243 /** 244 * Adds a policy subject at realm. 245 * 246 * @param subjectName name of the Subject instance 247 * @param subject Subject object to be added 248 * 249 * @throws NameAlreadyExistsException if a Subject with the given name 250 * already exists at the realm 251 * @throws InvalidNameException if the subject name is invalid 252 * 253 * @throws PolicyException if can not add the Subject 254 */ 255 public void addSubject(String subjectName, Subject subject) 256 throws NameAlreadyExistsException, InvalidNameException, 257 PolicyException, SSOException { 258 259 //we really do not use the exclusive flag at realm level 260 addSubject(subjectName, subject, false); 261 } 262 263 /** 264 * Adds a policy subject at realm. 265 * 266 * @param subjectName name of the Subject instance 267 * @param subject Subject object to be added 268 * 269 * @param exclusive boolean flag indicating whether the subject 270 * is to be exclusive subject. If subject is exclusive, 271 * policy applies to users who are not members of the 272 * subject. Otherwise, policy applies to members of the subject. 273 * 274 * @throws NameAlreadyExistsException if a Subject with the given name 275 * already exists at the realm 276 * @throws InvalidNameException if the subject name is invalid 277 * 278 * @throws PolicyException if can not add the Subject 279 * 280 * 281 */ 282 private void addSubject(String subjectName, Subject subject, 283 boolean exclusive) 284 throws NameAlreadyExistsException, InvalidNameException, 285 PolicyException, SSOException { 286 if (debug.messageEnabled()) { 287 debug.message("Adding realm subject : " + subjectName 288 + ", in realm:" + pmRealmName); 289 } 290 if (realmSubjects == null) { 291 initRealmSubjects(); 292 } 293 realmSubjects.addSubject(subjectName, subject, exclusive); 294 saveSubjects(); 295 if (debug.messageEnabled()) { 296 debug.message("Added realm subject : " + subjectName 297 + ", in realm:" + pmRealmName); 298 } 299 } 300 301 /** 302 * Removes the subject with the given name from the realm. 303 * This method would throw PolicyException if the subject 304 * is being used by any policy. 305 * 306 * @param subjectName name of the Subject 307 * 308 * @return returns the Subject object being removed, 309 * returns <code>null</code> if Subject with 310 * the given subjectName is not present 311 * 312 * @throws PolicyException if can not remove the Subject 313 */ 314 public Subject removeSubject(String subjectName) 315 throws ObjectInUseException, PolicyException, SSOException { 316 return removeSubject(subjectName, false); 317 } 318 319 /** 320 * Removes the subject with the given name from the realm. 321 * This method would throw PolicyException if the subject 322 * is being used by any policy unless <code>forcedRemove</code> 323 * argument is set to <code>true</code>. 324 * If the <code>forcedRemove</code> argument is set to 325 * <code>true</code> policies that are using the subject would 326 * be modified to remove the references to the subject 327 * 328 * @param subjectName name of the Subject 329 * @param forcedRemove if set to <code>true</code>, policies that 330 * use the subject would be modifed to remove the references 331 * to the subject. Otherwise, <code>ObjectInUseException</code> 332 * would be thrown if there is any policy using the subject 333 * 334 * @return returns the Subject object being removed, 335 * returns <code>null</code> if Subject with 336 * the given subjectName is not present 337 * 338 * @throws PolicyException if can not remove the Subject 339 */ 340 public Subject removeSubject(String subjectName, boolean forcedRemove) 341 throws ObjectInUseException, PolicyException, SSOException { 342 if (debug.messageEnabled()) { 343 debug.message("Removing realm subject : " + subjectName 344 + ", in realm:" + pmRealmName); 345 } 346 if (realmSubjects == null) { 347 initRealmSubjects(); 348 } 349 if (forcedRemove) { 350 Set userPolicies = pm.getPoliciesUsingRealmSubject(subjectName); 351 for (Iterator policyIter = userPolicies.iterator(); 352 policyIter.hasNext();) { 353 Policy policy = (Policy)policyIter.next(); 354 policy.removeSubject(subjectName); 355 } 356 } else { 357 Policy p = pm.getPolicyUsingRealmSubject(subjectName); 358 if ( p != null) { 359 //ObjectInUseException(String rbName, String errCode, 360 //Object[] args, String name, Object user) 361 throw new ObjectInUseException(null, null, null, null, null); 362 } 363 } 364 Subject subject = realmSubjects.removeSubject(subjectName); 365 saveSubjects(); 366 if (debug.messageEnabled()) { 367 debug.message("Removed realm subject : " + subjectName 368 + ", in realm:" + pmRealmName); 369 } 370 return subject; 371 } 372 373 /** 374 * Replaces an existing subject with the same name by the 375 * current one at the realm. If a subject with the same name does 376 * not exist, it will be added. 377 * 378 * @param subjectName name of the Subject instance 379 * @param subject Subject that will replace an existing Subject 380 * with the same name 381 * 382 * @throws NameNotFoundException if a Subject instance 383 * with the given name is not present 384 * 385 * @throws PolicyException if can not replace the Subject 386 */ 387 public void replaceSubject(String subjectName, Subject subject) 388 throws NameNotFoundException, PolicyException, SSOException { 389 390 //we really do not use the exclusive flag at realm level 391 replaceSubject(subjectName, subject, false); 392 } 393 394 /** 395 * Replaces an existing subject with the same name by the 396 * current one at the realm. If a subject with the same name does 397 * not exist, it will be added. 398 * 399 * @param subjectName name of the Subject instance 400 * @param subject Subject that will replace an existing Subject 401 * with the same name 402 * 403 * @param exclusive boolean flag indicating whether the subject 404 * is to be exclusive subject. If subject is exclusive, 405 * policy applies to users who are not members of the 406 * subject. Otherwise, policy applies to members of the subject. 407 * 408 * @throws NameNotFoundException if a Subject instance 409 * with the given name is not present 410 * 411 * @throws PolicyException if can not replace the Subject 412 * 413 * 414 */ 415 private void replaceSubject(String subjectName, Subject subject, 416 boolean exclusive) 417 throws NameNotFoundException, PolicyException, SSOException { 418 if (debug.messageEnabled()) { 419 debug.message("Replacing realm subject : " + subjectName 420 + ", in realm:" + pmRealmName); 421 } 422 if (realmSubjects == null) { 423 initRealmSubjects(); 424 } 425 realmSubjects.replaceSubject(subjectName, subject, exclusive); 426 saveSubjects(); 427 if (debug.messageEnabled()) { 428 debug.message("Replaced realm subject : " + subjectName 429 + ", in realm:" + pmRealmName); 430 } 431 } 432 433 /** 434 * Get the set of names of Subject(s) defined at the realm 435 * 436 * @return set of subject names 437 */ 438 public Set getSubjectNames() throws PolicyException, SSOException { 439 if (debug.messageEnabled()) { 440 debug.message("Getting subject names from realm: " 441 + pmRealmName); 442 } 443 if (realmSubjects == null) { 444 initRealmSubjects(); 445 } 446 Set subjectNames = realmSubjects.getSubjectNames(); 447 if (debug.messageEnabled()) { 448 debug.message("Returning subject names from realm: " 449 + pmRealmName + ",subjectNames=" + subjectNames); 450 } 451 return subjectNames; 452 } 453 454 /** 455 * Returns the Subject object identified by subjectName defined at 456 * the realm 457 * 458 * @param subjectName name of subject. 459 * 460 * @return Subject object 461 * 462 * @throws NameNotFoundException if a Subject with the given name 463 * does not exist 464 * 465 * @throws PolicyException if can not get the Subject 466 */ 467 public Subject getSubjectByName(String subjectName) 468 throws NameNotFoundException, PolicyException { 469 if (debug.messageEnabled()) { 470 debug.message("Getting subject by name from realm: " 471 + pmRealmName + ", subjectName=" + subjectName); 472 } 473 if (realmSubjects == null) { 474 initRealmSubjects(); 475 } 476 if (debug.messageEnabled()) { 477 debug.message("Returning subject by name from realm: " 478 + pmRealmName + ", subjectName=" + subjectName); 479 } 480 return (Subject)realmSubjects.getSubject(subjectName).clone(); 481 } 482 483 synchronized Subject getCachedSubjectByName(String subjectName) 484 throws PolicyException { 485 if (debug.messageEnabled()) { 486 debug.message("Getting cached subject by name from realm: " 487 + pmRealmName + ", subjectName=" + subjectName); 488 } 489 if (realmSubjects == null) { 490 initRealmSubjects(); 491 } 492 if (debug.messageEnabled()) { 493 debug.message("Returning cached subject by name from realm: " 494 + pmRealmName + ", subjectName=" + subjectName); 495 } 496 return (Subject)realmSubjects.fetchSubject(subjectName); 497 } 498 499 /** 500 * Returns a handle to the Subject object identified by subjectName 501 * defined at the realm, to add to a policy. 502 * Returned Subject is backed by 503 * the Subject at the realm. However, you can not change the values 504 * using the returned Subject. 505 * 506 * @param subjectName name of subject. 507 * 508 * @return Subject object 509 * 510 * @throws NameNotFoundException if a Subject with the given name 511 * does not exist 512 * 513 * @throws PolicyException if can not get the Subject 514 * 515 */ 516 Subject getSharedSubject(String subjectName) 517 throws PolicyException { 518 if (debug.messageEnabled()) { 519 debug.message("Getting shared subject from realm: " 520 + pmRealmName + ", subjectName=" + subjectName); 521 } 522 Subject subject = (Subject)sharedSubjects.get(subjectName); 523 if (subject == null) { 524 subject = new SharedSubject(subjectName, this); 525 sharedSubjects.put(subjectName, subject); 526 } 527 if (debug.messageEnabled()) { 528 debug.message("Returning shared subject from realm: " 529 + pmRealmName + ", subjectName=" + subjectName); 530 } 531 return subject; 532 } 533 534 /** 535 * Returns subject type name for the given <code>subject</code> 536 * @return subject type name for the given <code>subject</code> 537 */ 538 static String subjectTypeName(Subject subject) { 539 if (subject == null) { 540 return (null); 541 } 542 String answer = null; 543 String className = subject.getClass().getName(); 544 Iterator items = PolicyManager.getPluginSchemaNames(SUBJECT).iterator(); 545 while (items.hasNext()) { 546 String pluginName = (String) items.next(); 547 PluginSchema ps = PolicyManager.getPluginSchema(SUBJECT, 548 pluginName); 549 if (className.equals(ps.getClassName())) { 550 answer = pluginName; 551 break; 552 } 553 } 554 return (answer); 555 } 556 557 /** 558 * Returns the view bean URL given the Subject 559 * 560 * @param subject subject for which to get the view bean URL 561 * 562 * @return view bean URL defined for the subject plugin in the policy 563 * service <code>PluginSchema</code>. 564 */ 565 public String getViewBeanURL(Subject subject) { 566 return PolicyManager.getViewBeanURL(SUBJECT, 567 subject.getClass().getName()); 568 } 569 570 /** 571 * Returns <code>PolicyManager</code> used by this object 572 */ 573 PolicyManager getPolicyManager() { 574 return pm; 575 } 576 577 /** 578 * Saves the realm scoped <code>Subject</code> objects to persistent store 579 */ 580 private void saveSubjects() throws PolicyException, SSOException { 581 if (realmSubjects != null) { 582 pm.saveRealmSubjects(realmSubjects); 583 } 584 } 585 586 /** 587 * Initializes the realm scoped <code>Subject</code> objects reading from 588 * persistent store 589 */ 590 private void initRealmSubjects() throws PolicyException { 591 if (debug.messageEnabled()) { 592 debug.message("Initializing realm subjects in realm : " 593 + pmRealmName); 594 } 595 try { 596 realmSubjects = pm.readRealmSubjects(); 597 } catch (SSOException ssoe){ 598 throw new PolicyException(ResBundleUtils.rbName, 599 "could_not_initialize_realm_subjects", null, ssoe); 600 } 601 if (debug.messageEnabled()) { 602 debug.message("Initialized realm subjects in realm : " 603 + pmRealmName); 604 } 605 } 606 607 /** 608 * Resets the cached realm scoped <code>Subject</code> objects. 609 * Would read from persistent store on next access to realm scoped 610 * <code>Subject</code> object 611 */ 612 void resetRealmSubjects() { 613 if (debug.messageEnabled()) { 614 debug.message("Resetting realm subjects in realm : " 615 + pmRealmName); 616 } 617 synchronized(this) { 618 realmSubjects = null; 619 } 620 if (debug.messageEnabled()) { 621 debug.message("Reset realm subjects in realm : " 622 + pmRealmName); 623 } 624 } 625 626}