001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.security; 029 030import org.opencms.db.CmsDbEntryNotFoundException; 031import org.opencms.file.CmsGroup; 032import org.opencms.file.CmsObject; 033import org.opencms.file.CmsUser; 034import org.opencms.main.CmsException; 035import org.opencms.main.OpenCms; 036import org.opencms.util.CmsStringUtil; 037import org.opencms.util.CmsUUID; 038import org.opencms.workplace.I_CmsGroupNameTranslation; 039 040import java.util.Iterator; 041import java.util.List; 042import java.util.Locale; 043 044/** 045 * Common methods shared among user and group principals, 046 * also contains several utility functions to deal with principal instances.<p> 047 * 048 * @since 6.2.0 049 */ 050public abstract class CmsPrincipal implements I_CmsPrincipal, Comparable<I_CmsPrincipal> { 051 052 /** The serial version id. */ 053 private static final long serialVersionUID = -323281048875786320L; 054 055 /** The description of this principal. */ 056 protected String m_description; 057 058 /** The flags of this principal. */ 059 protected int m_flags; 060 061 /** The unique id of this principal. */ 062 protected CmsUUID m_id; 063 064 /** The fully qualified name of this principal. */ 065 protected String m_name; 066 067 /** 068 * Empty constructor for subclassing.<p> 069 */ 070 protected CmsPrincipal() { 071 072 // empty constructor for subclassing 073 } 074 075 /** 076 * Filters out all principals that do not have the given flag set, 077 * but leaving principals with flags less than <code>{@link I_CmsPrincipal#FLAG_CORE_LIMIT}</code> untouched.<p> 078 * 079 * The given parameter list is directly modified, so the returned list is the same object as the input list.<p> 080 * 081 * @param principals a list of <code>{@link CmsPrincipal}</code> objects 082 * @param flag the flag for filtering 083 * 084 * @return the filtered principal list 085 */ 086 public static List<? extends CmsPrincipal> filterCoreFlag(List<? extends CmsPrincipal> principals, int flag) { 087 088 Iterator<? extends CmsPrincipal> it = principals.iterator(); 089 while (it.hasNext()) { 090 CmsPrincipal p = it.next(); 091 if ((p.getFlags() > I_CmsPrincipal.FLAG_CORE_LIMIT) && ((p.getFlags() & flag) != flag)) { 092 it.remove(); 093 } 094 } 095 return principals; 096 } 097 098 /** 099 * Filters out all groups with flags greater than <code>{@link I_CmsPrincipal#FLAG_CORE_LIMIT}</code>.<p> 100 * 101 * The given parameter list is directly modified, so the returned list is the same object as the input list.<p> 102 * 103 * @param groups a list of <code>{@link CmsGroup}</code> objects 104 * 105 * @return the filtered principal list 106 */ 107 public static List<CmsGroup> filterCoreGroups(List<CmsGroup> groups) { 108 109 Iterator<CmsGroup> it = groups.iterator(); 110 while (it.hasNext()) { 111 CmsGroup p = it.next(); 112 if (p.getFlags() > I_CmsPrincipal.FLAG_CORE_LIMIT) { 113 it.remove(); 114 } 115 } 116 return groups; 117 } 118 119 /** 120 * Filters out all users with flags greater than <code>{@link I_CmsPrincipal#FLAG_CORE_LIMIT}</code>.<p> 121 * 122 * The given parameter list is directly modified, so the returned list is the same object as the input list.<p> 123 * 124 * @param users a list of <code>{@link CmsUser}</code> objects 125 * 126 * @return the filtered principal list 127 */ 128 public static List<CmsUser> filterCoreUsers(List<CmsUser> users) { 129 130 Iterator<CmsUser> it = users.iterator(); 131 while (it.hasNext()) { 132 I_CmsPrincipal p = it.next(); 133 if (p.getFlags() > I_CmsPrincipal.FLAG_CORE_LIMIT) { 134 it.remove(); 135 } 136 } 137 return users; 138 } 139 140 /** 141 * Filters out all principals that do not have the given flag set.<p> 142 * 143 * The given parameter list is directly modified, so the returned list is the same object as the input list.<p> 144 * 145 * @param principals the list of <code>{@link CmsPrincipal}</code> objects 146 * @param flag the flag for filtering 147 * 148 * @return the filtered principal list 149 */ 150 public static List<? extends CmsPrincipal> filterFlag(List<? extends CmsPrincipal> principals, int flag) { 151 152 Iterator<? extends CmsPrincipal> it = principals.iterator(); 153 while (it.hasNext()) { 154 CmsPrincipal p = it.next(); 155 if ((p.getFlags() & flag) != flag) { 156 it.remove(); 157 } 158 } 159 return principals; 160 } 161 162 /** 163 * Returns the provided group name prefixed with <code>{@link I_CmsPrincipal#PRINCIPAL_GROUP}.</code>.<p> 164 * 165 * @param name the name to add the prefix to 166 * @return the provided group name prefixed with <code>{@link I_CmsPrincipal#PRINCIPAL_GROUP}.</code> 167 */ 168 public static String getPrefixedGroup(String name) { 169 170 StringBuffer result = new StringBuffer(name.length() + 10); 171 result.append(I_CmsPrincipal.PRINCIPAL_GROUP); 172 result.append('.'); 173 result.append(name); 174 return result.toString(); 175 } 176 177 /** 178 * Returns the provided user name prefixed with <code>{@link I_CmsPrincipal#PRINCIPAL_USER}.</code>.<p> 179 * 180 * @param name the name to add the prefix to 181 * @return the provided user name prefixed with <code>{@link I_CmsPrincipal#PRINCIPAL_USER}.</code> 182 */ 183 public static String getPrefixedUser(String name) { 184 185 StringBuffer result = new StringBuffer(name.length() + 10); 186 result.append(I_CmsPrincipal.PRINCIPAL_USER); 187 result.append('.'); 188 result.append(name); 189 return result.toString(); 190 } 191 192 /** 193 * Gets the type of a principal.<p> 194 * 195 * @param principal the principal 196 * @return the principal type 197 */ 198 public static String getType(I_CmsPrincipal principal) { 199 200 if (principal == null) { 201 return null; 202 } 203 if (principal.isGroup()) { 204 return I_CmsPrincipal.PRINCIPAL_GROUP; 205 } else { 206 return I_CmsPrincipal.PRINCIPAL_USER; 207 } 208 } 209 210 /** 211 * Utility function to read a prefixed principal from the OpenCms database using the 212 * provided OpenCms user context.<p> 213 * 214 * The principal must be either prefixed with <code>{@link I_CmsPrincipal#PRINCIPAL_GROUP}.</code> or 215 * <code>{@link I_CmsPrincipal#PRINCIPAL_USER}.</code>.<p> 216 * 217 * @param cms the OpenCms user context to use when reading the principal 218 * @param name the prefixed principal name 219 * 220 * @return the principal read from the OpenCms database 221 * 222 * @throws CmsException in case the principal could not be read 223 */ 224 public static I_CmsPrincipal readPrefixedPrincipal(CmsObject cms, String name) throws CmsException { 225 226 if (CmsGroup.hasPrefix(name)) { 227 // this principal is a group 228 return cms.readGroup(CmsGroup.removePrefix(name)); 229 } else if (CmsUser.hasPrefix(name)) { 230 // this principal is a user 231 return cms.readUser(CmsUser.removePrefix(name)); 232 } 233 // invalid principal name was given 234 throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_INVALID_PRINCIPAL_1, name)); 235 } 236 237 /** 238 * Utility function to read a principal by its id from the OpenCms database using the 239 * provided OpenCms user context.<p> 240 * 241 * @param cms the OpenCms user context to use when reading the principal 242 * @param id the id of the principal to read 243 * 244 * @return the principal read from the OpenCms database 245 * 246 * @throws CmsException in case the principal could not be read 247 */ 248 public static I_CmsPrincipal readPrincipal(CmsObject cms, CmsUUID id) throws CmsException { 249 250 try { 251 // first try to read the principal as a user 252 return cms.readUser(id); 253 } catch (CmsException exc) { 254 // assume user does not exist 255 } 256 try { 257 // now try to read the principal as a group 258 return cms.readGroup(id); 259 } catch (CmsException exc) { 260 // assume group does not exist 261 } 262 // invalid principal name was given 263 throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_INVALID_PRINCIPAL_1, id)); 264 } 265 266 /** 267 * Utility function to read a principal by its id from the OpenCms database using the 268 * provided OpenCms user context.<p> 269 * 270 * @param cms the OpenCms user context to use when reading the principal 271 * @param name the name of the principal to read 272 * 273 * @return the principal read from the OpenCms database 274 * 275 * @throws CmsException in case the principal could not be read 276 */ 277 public static I_CmsPrincipal readPrincipal(CmsObject cms, String name) throws CmsException { 278 279 try { 280 // first try to read the principal as a user 281 return cms.readUser(name); 282 } catch (CmsException exc) { 283 // assume user does not exist 284 } 285 try { 286 // now try to read the principal as a group 287 return cms.readGroup(name); 288 } catch (CmsException exc) { 289 // assume group does not exist 290 } 291 // invalid principal name was given 292 throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_INVALID_PRINCIPAL_1, name)); 293 } 294 295 /** 296 * Utility function to read a principal of the given type from the OpenCms database using the 297 * provided OpenCms user context.<p> 298 * 299 * The type must either be <code>{@link I_CmsPrincipal#PRINCIPAL_GROUP}</code> or 300 * <code>{@link I_CmsPrincipal#PRINCIPAL_USER}</code>.<p> 301 * 302 * @param cms the OpenCms user context to use when reading the principal 303 * @param type the principal type 304 * @param name the principal name 305 * 306 * @return the principal read from the OpenCms database 307 * 308 * @throws CmsException in case the principal could not be read 309 */ 310 public static I_CmsPrincipal readPrincipal(CmsObject cms, String type, String name) throws CmsException { 311 312 if (CmsStringUtil.isNotEmpty(type)) { 313 String upperCaseType = type.toUpperCase(); 314 if (PRINCIPAL_GROUP.equals(upperCaseType)) { 315 // this principal is a group 316 return cms.readGroup(name); 317 } else if (PRINCIPAL_USER.equals(upperCaseType)) { 318 // this principal is a user 319 return cms.readUser(name); 320 } 321 } 322 // invalid principal type was given 323 throw new CmsDbEntryNotFoundException( 324 Messages.get().container(Messages.ERR_INVALID_PRINCIPAL_TYPE_2, type, name)); 325 } 326 327 /** 328 * Utility function to read a principal by its id from the OpenCms database using the 329 * provided OpenCms user context.<p> 330 * 331 * @param cms the OpenCms user context to use when reading the principal 332 * @param id the id of the principal to read 333 * 334 * @return the principal read from the OpenCms database 335 * 336 * @throws CmsException in case the principal could not be read 337 */ 338 public static I_CmsPrincipal readPrincipalIncludingHistory(CmsObject cms, CmsUUID id) throws CmsException { 339 340 try { 341 // first try to read the principal as a user 342 return cms.readUser(id); 343 } catch (CmsException exc) { 344 // assume user does not exist 345 } 346 try { 347 // now try to read the principal as a group 348 return cms.readGroup(id); 349 } catch (CmsException exc) { 350 // assume group does not exist 351 } 352 try { 353 // at the end try to read the principal from the history 354 return cms.readHistoryPrincipal(id); 355 } catch (CmsException exc) { 356 // assume the principal does not exist at all 357 } 358 // invalid principal name was given 359 throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_INVALID_PRINCIPAL_1, id)); 360 } 361 362 /** 363 * @see java.lang.Comparable#compareTo(java.lang.Object) 364 */ 365 public int compareTo(I_CmsPrincipal obj) { 366 367 if ((this == obj) || equals(obj)) { 368 return 0; 369 } 370 return getName().compareTo(obj.getName()); 371 } 372 373 /** 374 * @see java.lang.Object#equals(java.lang.Object) 375 */ 376 @Override 377 public boolean equals(Object obj) { 378 379 if (obj == this) { 380 return true; 381 } 382 if (obj instanceof I_CmsPrincipal) { 383 if (m_id != null) { 384 return m_id.equals(((I_CmsPrincipal)obj).getId()); 385 } 386 } 387 return false; 388 } 389 390 /** 391 * @see org.opencms.security.I_CmsPrincipal#getDescription() 392 */ 393 public String getDescription() { 394 395 return m_description; 396 } 397 398 /** 399 * Returns the display name of this principal including the organizational unit.<p> 400 * 401 * @param cms the cms context 402 * @param locale the locale 403 * 404 * @return the display name of this principal including the organizational unit 405 * 406 * @throws CmsException if the organizational unit could not be read 407 */ 408 public String getDisplayName(CmsObject cms, Locale locale) throws CmsException { 409 410 return Messages.get().getBundle(locale).key( 411 Messages.GUI_PRINCIPAL_DISPLAY_NAME_2, 412 getSimpleName(), 413 OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, getOuFqn()).getDisplayName(locale)); 414 } 415 416 /** 417 * Returns the translated display name of this principal if it is a group and the display name otherwise.<p> 418 * 419 * @param cms the current CMS context 420 * @param locale the locale 421 * @param translation the group name translation to use 422 * 423 * @return the translated display name 424 * 425 * @throws CmsException if something goes wrong 426 */ 427 public String getDisplayName(CmsObject cms, Locale locale, I_CmsGroupNameTranslation translation) 428 throws CmsException { 429 430 if (!isGroup() || (translation == null)) { 431 return getDisplayName(cms, locale); 432 } 433 return Messages.get().getBundle(locale).key( 434 Messages.GUI_PRINCIPAL_DISPLAY_NAME_2, 435 translation.translateGroupName(getName(), false), 436 OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, getOuFqn()).getDisplayName(locale)); 437 } 438 439 /** 440 * @see org.opencms.security.I_CmsPrincipal#getFlags() 441 */ 442 public int getFlags() { 443 444 return m_flags; 445 } 446 447 /** 448 * @see org.opencms.security.I_CmsPrincipal#getId() 449 */ 450 public CmsUUID getId() { 451 452 return m_id; 453 } 454 455 /** 456 * Returns the fully qualified name of this principal.<p> 457 * 458 * @return the fully qualified name of this principal 459 * 460 * @see java.security.Principal#getName() 461 */ 462 public String getName() { 463 464 return m_name; 465 } 466 467 /** 468 * Returns the fully qualified name of the associated organizational unit.<p> 469 * 470 * @return the fully qualified name of the associated organizational unit 471 */ 472 public String getOuFqn() { 473 474 return CmsOrganizationalUnit.getParentFqn(m_name); 475 } 476 477 /** 478 * @see org.opencms.security.I_CmsPrincipal#getPrefixedName() 479 */ 480 public String getPrefixedName() { 481 482 if (isUser()) { 483 return getPrefixedUser(getName()); 484 } else if (isGroup()) { 485 return getPrefixedGroup(getName()); 486 } 487 return getName(); 488 } 489 490 /** 491 * Returns the simple name of this organizational unit. 492 * 493 * @return the simple name of this organizational unit. 494 */ 495 public String getSimpleName() { 496 497 return CmsOrganizationalUnit.getSimpleName(m_name); 498 } 499 500 /** 501 * @see java.lang.Object#hashCode() 502 */ 503 @Override 504 public int hashCode() { 505 506 if (m_id != null) { 507 return m_id.hashCode(); 508 } 509 return CmsUUID.getNullUUID().hashCode(); 510 } 511 512 /** 513 * @see org.opencms.security.I_CmsPrincipal#isEnabled() 514 */ 515 public boolean isEnabled() { 516 517 return (getFlags() & I_CmsPrincipal.FLAG_DISABLED) == 0; 518 } 519 520 /** 521 * @see org.opencms.security.I_CmsPrincipal#isGroup() 522 */ 523 public boolean isGroup() { 524 525 return (this instanceof CmsGroup); 526 } 527 528 /** 529 * @see org.opencms.security.I_CmsPrincipal#isUser() 530 */ 531 public boolean isUser() { 532 533 return (this instanceof CmsUser); 534 } 535 536 /** 537 * @see org.opencms.security.I_CmsPrincipal#setDescription(java.lang.String) 538 */ 539 public void setDescription(String description) { 540 541 m_description = description; 542 } 543 544 /** 545 * @see org.opencms.security.I_CmsPrincipal#setEnabled(boolean) 546 */ 547 public void setEnabled(boolean enabled) { 548 549 if (enabled != isEnabled()) { 550 // toggle disabled flag if required 551 setFlags(getFlags() ^ I_CmsPrincipal.FLAG_DISABLED); 552 } 553 } 554 555 /** 556 * @see org.opencms.security.I_CmsPrincipal#setFlags(int) 557 */ 558 public void setFlags(int value) { 559 560 m_flags = value; 561 } 562 563 /** 564 * @see org.opencms.security.I_CmsPrincipal#setName(java.lang.String) 565 */ 566 public void setName(String name) { 567 568 checkName(CmsOrganizationalUnit.getSimpleName(name)); 569 m_name = name; 570 } 571}