+ * These are unique (see {@link #equals(Object) equals} and {@link #hashCode() hashCode}) based
+ * on the shared and exclusive resource ID combination.
+ *
+ * @author Derek Hulley
+ * @since 3.2
+ */
+public class LockEntity
+{
+ private Long id;
+ private Long version;
+ private Long sharedResourceId;
+ private Long exclusiveResourceId;
+ private String lockHolder;
+ private Long startTime;
+ private Long expiryTime = Long.MAX_VALUE; // TODO:
+
+ @Override
+ public int hashCode()
+ {
+ return (sharedResourceId == null ? 0 : sharedResourceId.hashCode()) +
+ (exclusiveResourceId == null ? 0 : exclusiveResourceId.hashCode());
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ else if (obj instanceof LockEntity)
+ {
+ LockEntity that = (LockEntity) obj;
+ return EqualsHelper.nullSafeEquals(this.sharedResourceId, that.sharedResourceId) &&
+ EqualsHelper.nullSafeEquals(this.exclusiveResourceId, that.exclusiveResourceId);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Determine if the lock is logically exclusive. A lock is exclusive if the
+ * shared lock resource matches the exclusive lock resource.
+ *
+ * @return Returns true if the lock is exclusive or false if it is not
+ */
+ public boolean isExclusive()
+ {
+ if (sharedResourceId == null || exclusiveResourceId == null)
+ {
+ throw new IllegalStateException("LockEntity has not been populated");
+ }
+ return sharedResourceId.equals(exclusiveResourceId);
+ }
+
+ public boolean hasExpired()
+ {
+ return System.currentTimeMillis() > expiryTime;
+ }
+
+ public Long getId()
+ {
+ return id;
+ }
+
+ public void setId(Long id)
+ {
+ this.id = id;
+ }
+
+ public Long getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(Long version)
+ {
+ this.version = version;
+ }
+
+ public void incrementVersion()
+ {
+ this.version = new Long(version.longValue() + 1L);
+ }
+
+ /**
+ * @return Returns the ID of the shared lock resource
+ */
+ public Long getSharedResourceId()
+ {
+ return sharedResourceId;
+ }
+
+ /**
+ *
+ * @param sharedResourceId the ID of the shared lock resource
+ */
+ public void setSharedResourceId(Long sharedResourceId)
+ {
+ this.sharedResourceId = sharedResourceId;
+ }
+
+ public Long getExclusiveResourceId()
+ {
+ return exclusiveResourceId;
+ }
+
+ public void setExclusiveResourceId(Long exclusiveResourceId)
+ {
+ this.exclusiveResourceId = exclusiveResourceId;
+ }
+
+ /**
+ * @return Returns the ID of the lock holder
+ */
+ public String getLockHolder()
+ {
+ return lockHolder;
+ }
+
+ /**
+ * @param lockHolder the ID of the lock holder
+ */
+ public void setLockHolder(String lockHolder)
+ {
+ this.lockHolder = lockHolder;
+ }
+
+ /**
+ *
+ * @return Returns the time when the lock was started
+ */
+ public Long getStartTime()
+ {
+ return startTime;
+ }
+
+ public void setStartTime(Long startTime)
+ {
+ this.startTime = startTime;
+ }
+
+ public Long getExpiryTime()
+ {
+ return expiryTime;
+ }
+
+ public void setExpiryTime(Long expiryTime)
+ {
+ this.expiryTime = expiryTime;
+ }
+}
diff --git a/source/java/org/alfresco/repo/domain/locks/LockResourceEntity.java b/source/java/org/alfresco/repo/domain/locks/LockResourceEntity.java
new file mode 100644
index 0000000000..16eafc098f
--- /dev/null
+++ b/source/java/org/alfresco/repo/domain/locks/LockResourceEntity.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.domain.locks;
+
+/**
+ * Entity bean for alf_lock_resource table.
+ *
+ * @author Derek Hulley
+ * @since 3.2
+ */
+public class LockResourceEntity
+{
+ private Long id;
+ private Long version;
+ private Long qnameNamespaceId;
+ private String qnameLocalName;
+
+ public Long getId()
+ {
+ return id;
+ }
+
+ public void setId(Long id)
+ {
+ this.id = id;
+ }
+
+ public Long getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(Long version)
+ {
+ this.version = version;
+ }
+
+ /**
+ * @return Returns the ID of the namespace that the lock belongs to
+ */
+ public Long getQnameNamespaceId()
+ {
+ return qnameNamespaceId;
+ }
+
+ /**
+ * @param namespaceId the ID of the namespace that the lock belongs to
+ */
+ public void setQnameNamespaceId(Long namespaceId)
+ {
+ this.qnameNamespaceId = namespaceId;
+ }
+
+ /**
+ * @return Returns the lock qualified name localname
+ */
+ public String getQnameLocalName()
+ {
+ return qnameLocalName;
+ }
+
+ /**
+ * @param qnameLocalName the lock qualified name localname
+ */
+ public void setQnameLocalName(String qnameLocalName)
+ {
+ this.qnameLocalName = qnameLocalName;
+ }
+}
diff --git a/source/java/org/alfresco/repo/domain/locks/ibatis/LockDAOImpl.java b/source/java/org/alfresco/repo/domain/locks/ibatis/LockDAOImpl.java
new file mode 100644
index 0000000000..ac3419a3f0
--- /dev/null
+++ b/source/java/org/alfresco/repo/domain/locks/ibatis/LockDAOImpl.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.domain.locks.ibatis;
+
+import java.util.List;
+
+import org.alfresco.repo.domain.locks.AbstractLockDAOImpl;
+import org.alfresco.repo.domain.locks.LockEntity;
+import org.alfresco.repo.domain.locks.LockResourceEntity;
+import org.springframework.orm.ibatis.SqlMapClientTemplate;
+
+/**
+ * iBatis-specific implementation of the Locks DAO.
+ *
+ * @author Derek Hulley
+ * @since 3.2
+ */
+public class LockDAOImpl extends AbstractLockDAOImpl
+{
+ private static final Long CONST_LONG_ZERO = new Long(0L);
+ private static final String SELECT_LOCKRESOURCE_BY_QNAME = "select.LockResourceByQName";
+ private static final String SELECT_LOCK_BY_SHARED_IDS = "select.LockBySharedIds";
+ private static final String INSERT_LOCKRESOURCE = "insert.LockResource";
+ private static final String INSERT_LOCK = "insert.Lock";
+
+ private SqlMapClientTemplate template;
+
+ public void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate)
+ {
+ this.template = sqlMapClientTemplate;
+ }
+
+ @Override
+ protected LockResourceEntity getLockResource(Long qnameNamespaceId, String qnameLocalName)
+ {
+ LockResourceEntity lockResource = new LockResourceEntity();
+ lockResource.setQnameNamespaceId(qnameNamespaceId);
+ lockResource.setQnameLocalName(qnameLocalName);
+ lockResource = (LockResourceEntity) template.queryForObject(SELECT_LOCKRESOURCE_BY_QNAME, lockResource);
+ // Could be null
+ return lockResource;
+ }
+
+ @Override
+ protected LockResourceEntity createLockResource(Long qnameNamespaceId, String qnameLocalName)
+ {
+ LockResourceEntity lockResource = new LockResourceEntity();
+ lockResource.setVersion(CONST_LONG_ZERO);
+ lockResource.setQnameNamespaceId(qnameNamespaceId);
+ lockResource.setQnameLocalName(qnameLocalName);
+ Long id = (Long) template.insert(INSERT_LOCKRESOURCE, lockResource);
+ lockResource.setId(id);
+ // Done
+ return lockResource;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected List