001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/lock/CmsLock.java,v $
003: * Date : $Date: 2008-02-27 12:05:46 $
004: * Version: $Revision: 1.31 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.lock;
033:
034: import org.opencms.file.CmsProject;
035: import org.opencms.file.CmsUser;
036: import org.opencms.util.CmsUUID;
037:
038: /**
039: * Represents the lock state of a VFS resource.<p>
040: *
041: * The lock state is combination of how, by whom and in which project
042: * a resource is currently locked.<p>
043: *
044: * @author Thomas Weckert
045: * @author Andreas Zahner
046: * @author Michael Moossen
047: *
048: * @version $Revision: 1.31 $
049: *
050: * @since 6.0.0
051: *
052: * @see org.opencms.file.CmsObject#getLock(org.opencms.file.CmsResource)
053: * @see org.opencms.lock.CmsLockManager
054: */
055: public class CmsLock {
056:
057: /** The shared null lock object. */
058: private static final CmsLock NULL_LOCK = new CmsLock("", CmsUUID
059: .getNullUUID(), new CmsProject(), CmsLockType.UNLOCKED);
060:
061: /** The project where the resource is locked. */
062: private CmsProject m_project;
063:
064: /** The related lock. */
065: private CmsLock m_relatedLock;
066:
067: /** The name of the locked resource. */
068: private String m_resourceName;
069:
070: /** Indicates how the resource is locked. */
071: private CmsLockType m_type;
072:
073: /** The ID of the user who locked the resource. */
074: private CmsUUID m_userId;
075:
076: /**
077: * Constructor for a new Cms lock.<p>
078: *
079: * @param resourceName the full resource name including the site root
080: * @param userId the ID of the user who locked the resource
081: * @param project the project where the resource is locked
082: * @param type flag indicating how the resource is locked
083: */
084: public CmsLock(String resourceName, CmsUUID userId,
085: CmsProject project, CmsLockType type) {
086:
087: m_resourceName = resourceName;
088: m_userId = userId;
089: m_project = project;
090: m_type = type;
091: }
092:
093: /**
094: * Returns the shared Null CmsLock.<p>
095: *
096: * @return the shared Null CmsLock
097: */
098: public static CmsLock getNullLock() {
099:
100: return CmsLock.NULL_LOCK;
101: }
102:
103: /**
104: * Compares this lock to the specified object.<p>
105: *
106: * @param obj the object to compare to
107: * @return true if and only if member values of this CmsLock are the same with the compared CmsLock
108: */
109: public boolean equals(Object obj) {
110:
111: if (obj == this ) {
112: return true;
113: }
114: if (obj instanceof CmsLock) {
115: CmsLock other = (CmsLock) obj;
116: return other.m_resourceName.equals(m_resourceName)
117: && other.m_userId.equals(m_userId)
118: && other.m_project.equals(m_project)
119: && other.m_type.equals(m_type);
120: }
121: return false;
122: }
123:
124: /**
125: * Returns the edition lock.<p>
126: *
127: * @return the edition lock
128: */
129: public CmsLock getEditionLock() {
130:
131: if (isSystemLock()) {
132: return getRelatedLock();
133: }
134: return this ;
135: }
136:
137: /**
138: * Returns the project where the resource is currently locked.<p>
139: *
140: * @return the project where the resource is currently locked
141: */
142: public CmsProject getProject() {
143:
144: return m_project;
145: }
146:
147: /**
148: * Returns the ID of the project where the resource is currently locked.<p>
149: *
150: * @return the ID of the project
151: */
152: public CmsUUID getProjectId() {
153:
154: return m_project.getUuid();
155: }
156:
157: /**
158: * Returns the name of the locked resource.<p>
159: *
160: * @return the name of the locked resource
161: */
162: public String getResourceName() {
163:
164: return m_resourceName;
165: }
166:
167: /**
168: * Returns the system lock.<p>
169: *
170: * @return the system lock
171: */
172: public CmsLock getSystemLock() {
173:
174: if (!isSystemLock()) {
175: return getRelatedLock();
176: }
177: return this ;
178: }
179:
180: /**
181: * Returns the type about how the resource is locked.<p>
182: *
183: * @return the type of the lock
184: */
185: public CmsLockType getType() {
186:
187: return m_type;
188: }
189:
190: /**
191: * Returns the ID of the user who currently locked the resource.<p>
192: *
193: * @return the ID of the user
194: */
195: public CmsUUID getUserId() {
196:
197: return m_userId;
198: }
199:
200: /**
201: * @see java.lang.Object#hashCode()
202: */
203: public int hashCode() {
204:
205: return m_project.hashCode() + m_resourceName.hashCode()
206: + m_userId.hashCode() + m_type.hashCode();
207: }
208:
209: /**
210: * Returns <code>true</code> if this is an directly inherited lock.<p>
211: *
212: * @return <code>true</code> if this is an directly inherited lock
213: */
214: public boolean isDirectlyInherited() {
215:
216: return m_type.isDirectlyInherited();
217: }
218:
219: /**
220: * Returns <code>true</code> if this is an exclusive (or temporary exclusive) lock.<p>
221: *
222: * @return <code>true</code> if this is an exclusive (or temporary exclusive) lock
223: */
224: public boolean isExclusive() {
225:
226: return m_type.isExclusive();
227: }
228:
229: /**
230: * Returns <code>true</code> if this is an exclusive (or temporary exclusive) lock,
231: * and the given user is the owner of this lock.<p>
232: *
233: * @param user the user to compare to the owner of this lock
234: *
235: * @return <code>true</code> if this is an exclusive (or temporary exclusive) lock,
236: * and the given user is the owner of this lock
237: */
238: public boolean isExclusiveOwnedBy(CmsUser user) {
239:
240: return isExclusive() && isOwnedBy(user);
241: }
242:
243: /**
244: * Returns <code>true</code> if this is an exclusive (or temporary exclusive) lock,
245: * and the given user is the owner and the given project is the project of this lock.<p>
246: *
247: * @param user the user to compare to the owner of this lock
248: * @param project the project to compare to the project of this lock
249: *
250: * @return <code>true</code> if this is an exclusive (or temporary exclusive) lock,
251: * and the given user is the owner and the given project is the project of this lock
252: */
253: public boolean isExclusiveOwnedInProjectBy(CmsUser user,
254: CmsProject project) {
255:
256: return isExclusive() && isOwnedInProjectBy(user, project);
257: }
258:
259: /**
260: * Returns <code>true</code> if this is an inherited lock, which may either be directly or shared inherited.<p>
261: *
262: * @return <code>true</code> if this is an inherited lock, which may either be directly or shared inherited
263: */
264: public boolean isInherited() {
265:
266: return m_type.isInherited();
267: }
268:
269: /**
270: * Returns <code>true</code> if the given project is the project of this lock.<p>
271: *
272: * @param project the project to compare to the project of this lock
273: *
274: * @return <code>true</code> if the given project is the project of this lock
275: */
276: public boolean isInProject(CmsProject project) {
277:
278: return m_project.equals(project);
279: }
280:
281: /**
282: * Checks if a resource can be locked by a user.<p>
283: *
284: * The resource is not lockable if it already has a lock of type {@link CmsLockType#PUBLISH}.<p>
285: *
286: * The resource is lockable either
287: * - if it is currently unlocked
288: * - if it has a lock of another type set and the user is the lock owner
289: *
290: * @param user the user to test lockeability for
291: *
292: * @return <code>true</code> if this lock blocks any operation on the locked resource until it is unlocked
293: */
294: public boolean isLockableBy(CmsUser user) {
295:
296: if (getSystemLock().isPublish()) {
297: return false;
298: }
299: if (getEditionLock().isUnlocked()
300: && getSystemLock().isUnlocked()) {
301: return true;
302: }
303: return getEditionLock().isOwnedBy(user);
304: }
305:
306: /**
307: * Returns <code>true</code> if this lock is the <code>NULL</code> lock which can
308: * be obtained by {@link #getNullLock()}.<p>
309: *
310: * Only for the <code>NULL</code> lock, {@link #isUnlocked()} is <code>true</code>.<p>
311: *
312: * @return <code>true</code> if this lock is the <code>NULL</code> lock
313: */
314: public boolean isNullLock() {
315:
316: return isUnlocked();
317: }
318:
319: /**
320: * Returns <code>true</code> if the given user is the owner of this lock.<p>
321: *
322: * @param user the user to compare to the owner of this lock
323: *
324: * @return <code>true</code> if the given user is the owner of this lock
325: */
326: public boolean isOwnedBy(CmsUser user) {
327:
328: return m_userId.equals(user.getId());
329: }
330:
331: /**
332: * Returns <code>true</code> if the given user is the owner of this lock,
333: * and this lock belongs to the given project.<p>
334: *
335: * @param user the user to compare to the owner of this lock
336: * @param project the project to compare to the project of this lock
337: *
338: * @return <code>true</code> if the given user is the owner of this lock,
339: * and this lock belongs to the given project
340: */
341: public boolean isOwnedInProjectBy(CmsUser user, CmsProject project) {
342:
343: return isOwnedBy(user) && isInProject(project);
344: }
345:
346: /**
347: * Returns <code>true</code> if this is a persistent lock that should be saved when the systems shuts down.<p>
348: *
349: * @return <code>true</code> if this is a persistent lock that should be saved when the systems shuts down
350: */
351: public boolean isPersistent() {
352:
353: return m_type.isPersistent();
354: }
355:
356: /**
357: * Returns <code>true</code> if this is a publish lock.<p>
358: *
359: * @return <code>true</code> if this is a publish lock
360: */
361: public boolean isPublish() {
362:
363: return m_type.isPublish();
364: }
365:
366: /**
367: * Returns <code>true</code> if this is a shared lock.<p>
368: *
369: * @return <code>true</code> if this is a shared lock
370: */
371: public boolean isShared() {
372:
373: return m_type.isShared();
374: }
375:
376: /**
377: * Returns <code>true</code> if this is a system (2nd level) lock.<p>
378: *
379: * @return <code>true</code> if this is a system (2nd level) lock
380: */
381: public boolean isSystemLock() {
382:
383: return m_type.isSystem();
384: }
385:
386: /**
387: * Returns <code>true</code> if this is a temporary lock.<p>
388: *
389: * @return <code>true</code> if this is a temporary lock
390: */
391: public boolean isTemporary() {
392:
393: return m_type.isTemporary();
394: }
395:
396: /**
397: * Returns <code>true</code> if this lock is in fact unlocked.<p>
398: *
399: * Only if this is <code>true</code>, the result lock is equal to the <code>NULL</code> lock,
400: * which can be obtained by {@link #getNullLock()}.<p>
401: *
402: * @return <code>true</code> if this lock is in fact unlocked
403: */
404: public boolean isUnlocked() {
405:
406: return m_type.isUnlocked();
407: }
408:
409: /**
410: * Builds a string representation of the current state.<p>
411: *
412: * @see java.lang.Object#toString()
413: */
414: public String toString() {
415:
416: StringBuffer buf = new StringBuffer();
417:
418: buf.append("[CmsLock: resource: ");
419: buf.append(getResourceName());
420: buf.append(", type: ");
421: buf.append(getType());
422: buf.append(", project: ");
423: buf.append(getProjectId());
424: buf.append(", user: ");
425: buf.append(getUserId());
426: if (getRelatedLock() != null) {
427: buf.append(", related lock: ");
428: buf.append(getRelatedLock().getType());
429: }
430: buf.append("]");
431:
432: return buf.toString();
433: }
434:
435: /**
436: * @see java.lang.Object#clone()
437: */
438: protected Object clone() {
439:
440: CmsLock lock = new CmsLock(m_resourceName, m_userId, m_project,
441: m_type);
442: if ((m_relatedLock != null) && !m_relatedLock.isNullLock()) {
443: lock.setRelatedLock(new CmsLock(
444: m_relatedLock.m_resourceName,
445: m_relatedLock.m_userId, m_relatedLock.m_project,
446: m_relatedLock.m_type));
447: }
448: return lock;
449: }
450:
451: /**
452: * Returns the related Lock.<p>
453: *
454: * @return the related Lock
455: */
456: protected CmsLock getRelatedLock() {
457:
458: if (m_relatedLock == null) {
459: CmsLockType type;
460: if (isSystemLock()) {
461: type = CmsLockType.UNLOCKED;
462: } else {
463: type = CmsLockType.SYSTEM_UNLOCKED;
464: }
465: CmsLock lock = new CmsLock(getResourceName(), getUserId(),
466: getProject(), type);
467: lock.setRelatedLock(this );
468: if (isUnlocked()) {
469: // prevent the null lock gets modified
470: return lock;
471: }
472: m_relatedLock = lock;
473: }
474: return m_relatedLock;
475: }
476:
477: /**
478: * Sets the related Lock.<p>
479: *
480: * @param relatedLock the related Lock to set
481: */
482: protected void setRelatedLock(CmsLock relatedLock) {
483:
484: if (this == NULL_LOCK) {
485: throw new RuntimeException("null lock");
486: }
487: if ((relatedLock == null) || relatedLock.isUnlocked()) {
488: m_relatedLock = null;
489: } else {
490: m_relatedLock = relatedLock;
491: m_relatedLock.m_relatedLock = this;
492: }
493: }
494: }
|