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 GmbH & Co. KG, 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.lock; 029 030import org.opencms.file.CmsUser; 031import org.opencms.main.CmsLog; 032import org.opencms.util.CmsUUID; 033 034import java.util.Collections; 035import java.util.HashSet; 036import java.util.Set; 037 038import org.apache.commons.logging.Log; 039 040/** 041 * A filter to retrieve the locks.<p> 042 * 043 * @since 6.5.4 044 */ 045public final class CmsLockFilter implements Cloneable { 046 047 /** Logger instance for this class. */ 048 private static final Log LOG = CmsLog.getLog(CmsLockFilter.class); 049 050 /** To filter all locks. */ 051 public static final CmsLockFilter FILTER_ALL = new CmsLockFilter(true).filterIncludeChildren(); 052 053 /** To filter all inherited locks. */ 054 public static final CmsLockFilter FILTER_INHERITED = new CmsLockFilter(true); 055 056 /** To filter all non inherited locks. */ 057 public static final CmsLockFilter FILTER_NON_INHERITED = new CmsLockFilter(false); 058 059 /** If set the filter restricts the result excluding locks owned by the given user. */ 060 private CmsUUID m_notOwnedByUserId; 061 062 /** If set the filter extends the result to non inherited locks. */ 063 private boolean m_includeChildren; 064 065 /** If set the filter restricts the result including only locks owned by the given user. */ 066 private CmsUUID m_ownedByUserId; 067 068 /** If set the filter extends the result to inherited locks. */ 069 private boolean m_includeParents; 070 071 /** If set the filter restricts the result to the given project. */ 072 private CmsUUID m_projectId; 073 074 /** If set the filter also matches shared exclusive locks. */ 075 private boolean m_sharedExclusive; 076 077 /** The types to filter. */ 078 private Set<CmsLockType> m_types = new HashSet<CmsLockType>(); 079 080 /** If set the filter restricts the result excluding locks not lockable by the given user. */ 081 private CmsUser m_notLockableByUser; 082 083 /** If set the filter restricts the result including only locks lockable by the given user. */ 084 private CmsUser m_lockableByUser; 085 086 /** 087 * Private constructor.<p> 088 * 089 * @param inherited if the this lock filter should checks inherited locks or not 090 */ 091 private CmsLockFilter(boolean inherited) { 092 093 m_includeChildren = !inherited; 094 m_includeParents = inherited; 095 } 096 097 /** 098 * @see java.lang.Object#clone() 099 */ 100 @Override 101 public Object clone() { 102 103 CmsLockFilter filter = new CmsLockFilter(false); 104 filter.m_includeChildren = m_includeChildren; 105 filter.m_includeParents = m_includeParents; 106 filter.m_types = new HashSet<CmsLockType>(m_types); 107 filter.m_ownedByUserId = m_ownedByUserId; 108 filter.m_notOwnedByUserId = m_notOwnedByUserId; 109 filter.m_projectId = m_projectId; 110 filter.m_notLockableByUser = m_notLockableByUser; 111 filter.m_lockableByUser = m_lockableByUser; 112 return filter; 113 } 114 115 /** 116 * Returns an extended filter that will extend the result to the given path and all its children.<p> 117 * 118 * @return an extended filter to search the subresources of the given path 119 */ 120 public CmsLockFilter filterIncludeChildren() { 121 122 CmsLockFilter filter = (CmsLockFilter)clone(); 123 filter.m_includeChildren = true; 124 return filter; 125 } 126 127 /** 128 * Returns an extended filter that will extend the result to the given path and all its parents.<p> 129 * 130 * @return an extended filter to search the subresources of the given path 131 */ 132 public CmsLockFilter filterIncludeParents() { 133 134 CmsLockFilter filter = (CmsLockFilter)clone(); 135 filter.m_includeParents = true; 136 return filter; 137 } 138 139 /** 140 * Returns an extended filter with the given user restriction.<p> 141 * 142 * @param user the user to filter 143 * 144 * @return an extended filter with the given user restriction 145 */ 146 public CmsLockFilter filterLockableByUser(CmsUser user) { 147 148 CmsLockFilter filter = (CmsLockFilter)clone(); 149 filter.m_lockableByUser = user; 150 return filter; 151 } 152 153 /** 154 * Returns an extended filter with the given user restriction.<p> 155 * 156 * @param user the user to filter 157 * 158 * @return an extended filter with the given user restriction 159 */ 160 public CmsLockFilter filterNotLockableByUser(CmsUser user) { 161 162 CmsLockFilter filter = (CmsLockFilter)clone(); 163 filter.m_notLockableByUser = user; 164 return filter; 165 } 166 167 /** 168 * Returns an extended filter with the given user restriction.<p> 169 * 170 * @param userId the user id to filter 171 * 172 * @return an extended filter with the given user restriction 173 */ 174 public CmsLockFilter filterNotOwnedByUserId(CmsUUID userId) { 175 176 CmsLockFilter filter = (CmsLockFilter)clone(); 177 filter.m_notOwnedByUserId = userId; 178 return filter; 179 } 180 181 /** 182 * Returns an extended filter with the given user restriction.<p> 183 * 184 * @param userId the user id to filter 185 * 186 * @return an extended filter with the given user restriction 187 */ 188 public CmsLockFilter filterOwnedByUserId(CmsUUID userId) { 189 190 CmsLockFilter filter = (CmsLockFilter)clone(); 191 filter.m_ownedByUserId = userId; 192 return filter; 193 } 194 195 /** 196 * Returns an extended filter with the given project restriction.<p> 197 * 198 * @param projectId the project to filter the locks with 199 * 200 * @return an extended filter with the given project restriction 201 */ 202 public CmsLockFilter filterProject(CmsUUID projectId) { 203 204 CmsLockFilter filter = (CmsLockFilter)clone(); 205 filter.m_projectId = projectId; 206 return filter; 207 } 208 209 /** 210 * Returns an extended filter that also matches shared exclusive locks (siblings).<p> 211 * 212 * @return an extended filter that also matches shared exclusive locks 213 */ 214 public CmsLockFilter filterSharedExclusive() { 215 216 CmsLockFilter filter = (CmsLockFilter)clone(); 217 filter.m_sharedExclusive = true; 218 return filter; 219 } 220 221 /** 222 * Returns an extended filter with the given type restriction.<p> 223 * 224 * @param type the lock type to filter 225 * 226 * @return an extended filter with the given type restriction 227 */ 228 public CmsLockFilter filterType(CmsLockType type) { 229 230 CmsLockFilter filter = (CmsLockFilter)clone(); 231 filter.m_types.add(type); 232 return filter; 233 } 234 235 /** 236 * Returns the user that can overwrite the locks.<p> 237 * 238 * @return the user that can overwrite the locks 239 */ 240 public CmsUser getLockableByUserId() { 241 242 return m_lockableByUser; 243 } 244 245 /** 246 * Returns the user that can not overwrite the locks.<p> 247 * 248 * @return the user that can not overwrite the locks 249 */ 250 public CmsUser getNotLockableByUserId() { 251 252 return m_notLockableByUser; 253 } 254 255 /** 256 * Returns the user that has not to own the locks.<p> 257 * 258 * @return the user that has not to own the locks 259 */ 260 public CmsUUID getNotOwnedByUserId() { 261 262 return m_notOwnedByUserId; 263 } 264 265 /** 266 * Returns the user that has to own the locks.<p> 267 * 268 * @return the user that has to own the locks 269 */ 270 public CmsUUID getOwnedByUserId() { 271 272 return m_ownedByUserId; 273 } 274 275 /** 276 * Returns the project restriction.<p> 277 * 278 * @return the project restriction 279 */ 280 public CmsUUID getProjectId() { 281 282 return m_projectId; 283 } 284 285 /** 286 * Returns the types to filter.<p> 287 * 288 * @return the types to filter 289 */ 290 public Set<CmsLockType> getTypes() { 291 292 return Collections.unmodifiableSet(m_types); 293 } 294 295 /** 296 * Returns the include children flag.<p> 297 * 298 * @return if set the filter extends the result to the given path and all its children 299 */ 300 public boolean isIncludeChildren() { 301 302 return m_includeChildren; 303 } 304 305 /** 306 * Returns the include parents flag.<p> 307 * 308 * @return if set the filter extends the result to the given path and all its parents 309 */ 310 public boolean isIncludeParent() { 311 312 return m_includeParents; 313 } 314 315 /** 316 * Returns the <code>true</code> if this filter also matches shared exclusive locks.<p> 317 * 318 * @return the <code>true</code> if this filter also matches shared exclusive locks 319 */ 320 public boolean isSharedExclusive() { 321 322 return m_sharedExclusive; 323 } 324 325 /** 326 * Matches the given lock against this filter and the given path.<p> 327 * 328 * @param rootPath the path to match the lock against 329 * @param lock the lock to match 330 * 331 * @return <code>true</code> if the given lock matches 332 */ 333 public boolean match(String rootPath, CmsLock lock) { 334 335 return match(rootPath, lock, false); 336 } 337 338 /** 339 * @see java.lang.Object#toString() 340 */ 341 @Override 342 public String toString() { 343 344 StringBuffer str = new StringBuffer(128); 345 str.append("["); 346 str.append("children").append("=").append(m_includeChildren).append(", "); 347 str.append("parents").append("=").append(m_includeParents).append(", "); 348 str.append("types").append("=").append(m_types).append(", "); 349 str.append("includedUser").append("=").append(m_ownedByUserId).append(", "); 350 str.append("excludedUser").append("=").append(m_notOwnedByUserId).append(", "); 351 str.append("project").append("=").append(m_projectId).append(", "); 352 str.append("lockableBy").append("=").append(m_lockableByUser).append(", "); 353 str.append("notLockableBy").append("=").append(m_notLockableByUser).append(", "); 354 str.append("includeShared").append("=").append(m_sharedExclusive); 355 str.append("]"); 356 return str.toString(); 357 } 358 359 /** 360 * Matches the given lock against this filter and the given path.<p> 361 * 362 * @param rootPath the path to match the lock against 363 * @param lock the lock to match 364 * @param isRelatedCheck if we are currently in the recursive call for the related lock 365 * 366 * @return <code>true</code> if the given lock matches 367 */ 368 protected boolean match(String rootPath, CmsLock lock, boolean isRelatedCheck) { 369 370 boolean match = false; 371 if (m_includeChildren) { 372 // safe since rootPath always ends with slash if a folder 373 match = lock.getResourceName().startsWith(rootPath); 374 } 375 if (!match && m_includeParents) { 376 // since parents can only be folders, check it only for folders 377 if (lock.getResourceName().endsWith("/")) { 378 match = rootPath.startsWith(lock.getResourceName()); 379 } 380 } 381 if (match && (m_projectId != null) && !m_projectId.isNullUUID() && (lock.getProjectId() != null)) { 382 match = lock.getProjectId().equals(m_projectId); 383 } 384 if (match && (m_ownedByUserId != null) && !m_ownedByUserId.isNullUUID()) { 385 match = lock.getUserId().equals(m_ownedByUserId); 386 } 387 if (match && (m_notOwnedByUserId != null) && !m_notOwnedByUserId.isNullUUID()) { 388 match = !lock.getUserId().equals(m_notOwnedByUserId); 389 } 390 if (match && (m_lockableByUser != null)) { 391 match = lock.isLockableBy(m_lockableByUser); 392 } 393 if (match && (m_notLockableByUser != null)) { 394 match = !lock.isLockableBy(m_notLockableByUser); 395 } 396 if (match && !m_types.isEmpty()) { 397 match = m_types.contains(lock.getType()); 398 match = match || (m_includeParents && lock.isInherited()); 399 } 400 // check the related lock if available 401 if (!match && !lock.getRelatedLock().isNullLock()) { 402 if (!isRelatedCheck) { 403 match = match(rootPath, lock.getRelatedLock(), true); 404 } else { 405 LOG.warn("Invalid lock state for locks (" + lock + ", " + lock.getRelatedLock() + ")"); 406 } 407 } 408 return match; 409 } 410}