From 1fcdfc0a5d38183486802b2292c8c4b7d804cf3c Mon Sep 17 00:00:00 2001 From: Derek Hulley Date: Thu, 9 Apr 2009 15:27:19 +0000 Subject: [PATCH] Part of MOB-436: Cluster-wide Locking Service: Implement DB Changes and Service - Unit test not checked in as it requires some schema change work that has been done manually - Moved activities DAO code and renamed data services to DAOs (as per iBatis and Wikipedia, etc) - DAO code should now go into org.alfresco.repo.domain... - DAO components are bean:xyzDAO and class:XyzDAO - Entity beans are XyzEntity, etc git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13922 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../activities/activities-feed-context.xml | 34 +-- config/alfresco/application-context.xml | 1 + config/alfresco/dao/dao-context.xml | 23 ++ config/alfresco/ibatis/ibatis-context.xml | 16 +- config/alfresco/ibatis/locks-SqlMapConfig.xml | 12 + .../activities-common-SqlMap.xml | 6 +- .../locks-common-SqlMap.xml | 77 ++++++ .../locks-insert-SqlMap.xml | 23 ++ .../repo/activities/ActivityServiceImpl.java | 64 ++--- .../feed/AbstractFeedGenerator.java | 14 +- .../activities/feed/FeedTaskProcessor.java | 39 +-- .../activities/feed/cleanup/FeedCleaner.java | 12 +- .../feed/local/LocalFeedTaskProcessor.java | 46 ++-- .../activities/hibernate/Activities.hbm.xml | 6 +- .../activities/post/cleanup/PostCleaner.java | 14 +- .../activities/post/lookup/PostLookup.java | 34 +-- .../activities/ActivitiesDAO.java} | 4 +- .../activities/ActivityFeedDAO.java} | 12 +- .../activities/ActivityFeedEntity.java} | 4 +- .../activities/ActivityPostDAO.java} | 16 +- .../activities/ActivityPostEntity.java} | 4 +- .../activities/FeedControlDAO.java} | 12 +- .../activities/FeedControlEntity.java} | 10 +- .../ibatis/ActivityFeedDAOImpl.java} | 36 +-- .../ibatis/ActivityPostDAOImpl.java} | 30 +-- .../ibatis/FeedControlDAOImpl.java} | 20 +- .../activities/ibatis/IBatisSqlMapper.java | 6 +- .../domain/locks/AbstractLockDAOImpl.java | 255 ++++++++++++++++++ .../alfresco/repo/domain/locks/LockDAO.java | 48 ++++ .../repo/domain/locks/LockDetails.java | 99 +++++++ .../repo/domain/locks/LockEntity.java | 185 +++++++++++++ .../repo/domain/locks/LockResourceEntity.java | 91 +++++++ .../repo/domain/locks/ibatis/LockDAOImpl.java | 109 ++++++++ 33 files changed, 1136 insertions(+), 226 deletions(-) create mode 100644 config/alfresco/dao/dao-context.xml create mode 100644 config/alfresco/ibatis/locks-SqlMapConfig.xml create mode 100644 config/alfresco/ibatis/org.hibernate.dialect.Dialect/locks-common-SqlMap.xml create mode 100644 config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/locks-insert-SqlMap.xml rename source/java/org/alfresco/repo/{activities/ibatis/ActivityDaoService.java => domain/activities/ActivitiesDAO.java} (94%) rename source/java/org/alfresco/repo/{activities/feed/ActivityFeedDaoService.java => domain/activities/ActivityFeedDAO.java} (72%) rename source/java/org/alfresco/repo/{activities/feed/ActivityFeedDAO.java => domain/activities/ActivityFeedEntity.java} (98%) rename source/java/org/alfresco/repo/{activities/post/ActivityPostDaoService.java => domain/activities/ActivityPostDAO.java} (72%) rename source/java/org/alfresco/repo/{activities/post/ActivityPostDAO.java => domain/activities/ActivityPostEntity.java} (98%) rename source/java/org/alfresco/repo/{activities/feed/control/FeedControlDaoService.java => domain/activities/FeedControlDAO.java} (74%) rename source/java/org/alfresco/repo/{activities/feed/control/FeedControlDAO.java => domain/activities/FeedControlEntity.java} (93%) rename source/java/org/alfresco/repo/{activities/ibatis/IBatisActivityFeedDaoServiceImpl.java => domain/activities/ibatis/ActivityFeedDAOImpl.java} (66%) rename source/java/org/alfresco/repo/{activities/ibatis/IBatisActivityPostDaoServiceImpl.java => domain/activities/ibatis/ActivityPostDAOImpl.java} (72%) rename source/java/org/alfresco/repo/{activities/ibatis/IBatisFeedControlDaoServiceImpl.java => domain/activities/ibatis/FeedControlDAOImpl.java} (67%) rename source/java/org/alfresco/repo/{ => domain}/activities/ibatis/IBatisSqlMapper.java (91%) create mode 100644 source/java/org/alfresco/repo/domain/locks/AbstractLockDAOImpl.java create mode 100644 source/java/org/alfresco/repo/domain/locks/LockDAO.java create mode 100644 source/java/org/alfresco/repo/domain/locks/LockDetails.java create mode 100644 source/java/org/alfresco/repo/domain/locks/LockEntity.java create mode 100644 source/java/org/alfresco/repo/domain/locks/LockResourceEntity.java create mode 100644 source/java/org/alfresco/repo/domain/locks/ibatis/LockDAOImpl.java diff --git a/config/alfresco/activities/activities-feed-context.xml b/config/alfresco/activities/activities-feed-context.xml index d081968321..e5f7dd08e7 100644 --- a/config/alfresco/activities/activities-feed-context.xml +++ b/config/alfresco/activities/activities-feed-context.xml @@ -4,9 +4,9 @@ - - - + + + @@ -14,21 +14,9 @@ - - - - - - - - - - - - - + 44640 @@ -36,7 +24,7 @@ - + 30 @@ -44,7 +32,7 @@ - + @@ -53,7 +41,7 @@ - + @@ -68,11 +56,11 @@ - + - - - + + + diff --git a/config/alfresco/application-context.xml b/config/alfresco/application-context.xml index 31da431859..ebae104f5f 100644 --- a/config/alfresco/application-context.xml +++ b/config/alfresco/application-context.xml @@ -18,6 +18,7 @@ + diff --git a/config/alfresco/dao/dao-context.xml b/config/alfresco/dao/dao-context.xml new file mode 100644 index 0000000000..9b6462d8ad --- /dev/null +++ b/config/alfresco/dao/dao-context.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/alfresco/ibatis/ibatis-context.xml b/config/alfresco/ibatis/ibatis-context.xml index 0689e54738..7de95b0443 100644 --- a/config/alfresco/ibatis/ibatis-context.xml +++ b/config/alfresco/ibatis/ibatis-context.xml @@ -37,7 +37,8 @@ - + + @@ -45,17 +46,16 @@ - - + - classpath:alfresco/ibatis/dmNode-SqlMapConfig.xml + classpath:alfresco/ibatis/locks-SqlMapConfig.xml ---> + + + diff --git a/config/alfresco/ibatis/locks-SqlMapConfig.xml b/config/alfresco/ibatis/locks-SqlMapConfig.xml new file mode 100644 index 0000000000..d7bc3bce16 --- /dev/null +++ b/config/alfresco/ibatis/locks-SqlMapConfig.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-common-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-common-SqlMap.xml index 693c61edc2..5950e7b550 100644 --- a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-common-SqlMap.xml +++ b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/activities-common-SqlMap.xml @@ -6,9 +6,9 @@ - - - + + + diff --git a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/locks-common-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/locks-common-SqlMap.xml new file mode 100644 index 0000000000..33401192c2 --- /dev/null +++ b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/locks-common-SqlMap.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into alf_lock_resource (version, qname_ns_id, qname_localname) + values (#version#, #qnameNamespaceId#, lower(#qnameLocalName#)) + + + + insert into alf_lock (version, shared_resource_id, excl_resource_id, lock_holder) + values (#version#, #sharedResourceId#, #exclusiveResourceId#, lower(#lockHolder#)) + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/locks-insert-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/locks-insert-SqlMap.xml new file mode 100644 index 0000000000..5f347b0ed9 --- /dev/null +++ b/config/alfresco/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/locks-insert-SqlMap.xml @@ -0,0 +1,23 @@ + + + + + + + + + + KEY_COLUMN:GENERATED_KEY + + + + + + + KEY_COLUMN:GENERATED_KEY + + + + \ No newline at end of file diff --git a/source/java/org/alfresco/repo/activities/ActivityServiceImpl.java b/source/java/org/alfresco/repo/activities/ActivityServiceImpl.java index cbe5a958f6..d96a4a96bc 100644 --- a/source/java/org/alfresco/repo/activities/ActivityServiceImpl.java +++ b/source/java/org/alfresco/repo/activities/ActivityServiceImpl.java @@ -30,13 +30,13 @@ import java.util.Date; import java.util.List; import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.activities.feed.ActivityFeedDAO; -import org.alfresco.repo.activities.feed.ActivityFeedDaoService; import org.alfresco.repo.activities.feed.FeedGenerator; -import org.alfresco.repo.activities.feed.control.FeedControlDAO; -import org.alfresco.repo.activities.feed.control.FeedControlDaoService; -import org.alfresco.repo.activities.post.ActivityPostDAO; -import org.alfresco.repo.activities.post.ActivityPostDaoService; +import org.alfresco.repo.domain.activities.ActivityFeedDAO; +import org.alfresco.repo.domain.activities.ActivityFeedEntity; +import org.alfresco.repo.domain.activities.ActivityPostDAO; +import org.alfresco.repo.domain.activities.ActivityPostEntity; +import org.alfresco.repo.domain.activities.FeedControlDAO; +import org.alfresco.repo.domain.activities.FeedControlEntity; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.activities.ActivityService; @@ -64,9 +64,9 @@ public class ActivityServiceImpl implements ActivityService private static final int MAX_LEN_ACTIVITY_DATA = 4000; // needs to match schema: activity_data private static final int MAX_LEN_APP_TOOL_ID = 36; // needs to match schema: app_tool - private ActivityPostDaoService postDaoService; - private ActivityFeedDaoService feedDaoService; - private FeedControlDaoService feedControlDaoService; + private ActivityPostDAO postDAO; + private ActivityFeedDAO feedDAO; + private FeedControlDAO feedControlDAO; private AuthorityService authorityService; private FeedGenerator feedGenerator; @@ -86,19 +86,19 @@ public class ActivityServiceImpl implements ActivityService this.userNamesAreCaseSensitive = userNamesAreCaseSensitive; } - public void setPostDaoService(ActivityPostDaoService postDaoService) + public void setPostDAO(ActivityPostDAO postDAO) { - this.postDaoService = postDaoService; + this.postDAO = postDAO; } - public void setFeedDaoService(ActivityFeedDaoService feedDaoService) + public void setFeedDAO(ActivityFeedDAO feedDAO) { - this.feedDaoService = feedDaoService; + this.feedDAO = feedDAO; } - public void setFeedControlDaoService(FeedControlDaoService feedControlDaoService) + public void setFeedControlDAO(FeedControlDAO feedControlDAO) { - this.feedControlDaoService = feedControlDaoService; + this.feedControlDAO = feedControlDAO; } public void setAuthorityService(AuthorityService authorityService) @@ -122,7 +122,7 @@ public class ActivityServiceImpl implements ActivityService */ public void postActivity(String activityType, String siteId, String appTool, String activityData) { - postActivity(activityType, siteId, appTool, activityData, ActivityPostDAO.STATUS.PENDING); + postActivity(activityType, siteId, appTool, activityData, ActivityPostEntity.STATUS.PENDING); } /* (non-Javadoc) @@ -135,7 +135,7 @@ public class ActivityServiceImpl implements ActivityService StringBuffer sb = new StringBuffer(); sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append("}"); - postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostDAO.STATUS.PENDING); + postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); } /* (non-Javadoc) @@ -150,7 +150,7 @@ public class ActivityServiceImpl implements ActivityService .append("\"name\":\"").append(name).append("\"") .append("}"); - postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostDAO.STATUS.PENDING); + postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); } /* (non-Javadoc) @@ -171,10 +171,10 @@ public class ActivityServiceImpl implements ActivityService .append("\"parentNodeRef\":\"").append(parentNodeRef.toString()).append("\"") .append("}"); - postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostDAO.STATUS.PENDING); + postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); } - private void postActivity(String activityType, String siteId, String appTool, String activityData, ActivityPostDAO.STATUS status) + private void postActivity(String activityType, String siteId, String appTool, String activityData, ActivityPostEntity.STATUS status) { String currentUser = AuthenticationUtil.getFullyAuthenticatedUser(); @@ -241,7 +241,7 @@ public class ActivityServiceImpl implements ActivityService try { Date postDate = new Date(); - ActivityPostDAO activityPost = new ActivityPostDAO(); + ActivityPostEntity activityPost = new ActivityPostEntity(); activityPost.setUserId(currentUser); activityPost.setSiteNetwork(tenantService.getName(siteId)); @@ -262,7 +262,7 @@ public class ActivityServiceImpl implements ActivityService try { - long postId = postDaoService.insertPost(activityPost); + long postId = postDAO.insertPost(activityPost); if (logger.isDebugEnabled()) { @@ -312,16 +312,16 @@ public class ActivityServiceImpl implements ActivityService try { - List activityFeeds = null; + List activityFeeds = null; if (siteId != null) { siteId = tenantService.getName(siteId); } - activityFeeds = feedDaoService.selectUserFeedEntries(feedUserId, format, siteId, excludeThisUser, excludeOtherUsers); + activityFeeds = feedDAO.selectUserFeedEntries(feedUserId, format, siteId, excludeThisUser, excludeOtherUsers); int count = 0; - for (ActivityFeedDAO activityFeed : activityFeeds) + for (ActivityFeedEntity activityFeed : activityFeeds) { count++; if (count > maxFeedItems) @@ -363,10 +363,10 @@ public class ActivityServiceImpl implements ActivityService { siteId = tenantService.getName(siteId); - List activityFeeds = feedDaoService.selectSiteFeedEntries(siteId, format); + List activityFeeds = feedDAO.selectSiteFeedEntries(siteId, format); int count = 0; - for (ActivityFeedDAO activityFeed : activityFeeds) + for (ActivityFeedEntity activityFeed : activityFeeds) { count++; if (count > maxFeedItems) @@ -411,7 +411,7 @@ public class ActivityServiceImpl implements ActivityService { if (! existsFeedControl(feedControl)) { - feedControlDaoService.insertFeedControl(new FeedControlDAO(userId, feedControl)); + feedControlDAO.insertFeedControl(new FeedControlEntity(userId, feedControl)); } } catch (SQLException e) @@ -458,9 +458,9 @@ public class ActivityServiceImpl implements ActivityService try { - List feedControlDaos = feedControlDaoService.selectFeedControls(userId); + List feedControlDaos = feedControlDAO.selectFeedControls(userId); List feedControls = new ArrayList(feedControlDaos.size()); - for (FeedControlDAO feedControlDao : feedControlDaos) + for (FeedControlEntity feedControlDao : feedControlDaos) { feedControls.add(feedControlDao.getFeedControl()); } @@ -490,7 +490,7 @@ public class ActivityServiceImpl implements ActivityService try { - feedControlDaoService.deleteFeedControl(new FeedControlDAO(userId, feedControl)); + feedControlDAO.deleteFeedControl(new FeedControlEntity(userId, feedControl)); } catch (SQLException e) { @@ -516,7 +516,7 @@ public class ActivityServiceImpl implements ActivityService try { - long id = feedControlDaoService.selectFeedControl(new FeedControlDAO(userId, feedControl)); + long id = feedControlDAO.selectFeedControl(new FeedControlEntity(userId, feedControl)); return (id != -1); } catch (SQLException e) diff --git a/source/java/org/alfresco/repo/activities/feed/AbstractFeedGenerator.java b/source/java/org/alfresco/repo/activities/feed/AbstractFeedGenerator.java index 2b13e1b502..94b257ce16 100644 --- a/source/java/org/alfresco/repo/activities/feed/AbstractFeedGenerator.java +++ b/source/java/org/alfresco/repo/activities/feed/AbstractFeedGenerator.java @@ -24,7 +24,7 @@ */ package org.alfresco.repo.activities.feed; -import org.alfresco.repo.activities.post.ActivityPostDaoService; +import org.alfresco.repo.domain.activities.ActivityPostDAO; import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.util.PropertyCheck; import org.alfresco.util.VmShutdownListener; @@ -43,7 +43,7 @@ public abstract class AbstractFeedGenerator implements FeedGenerator private int maxItemsPerCycle = 100; - private ActivityPostDaoService postDaoService; + private ActivityPostDAO postDAO; private AuthenticationService authenticationService; private String repoEndPoint; // http://hostname:port/webapp (eg. http://localhost:8080/alfresco) @@ -54,9 +54,9 @@ public abstract class AbstractFeedGenerator implements FeedGenerator private volatile boolean busy; - public void setPostDaoService(ActivityPostDaoService postDaoService) + public void setPostDAO(ActivityPostDAO postDAO) { - this.postDaoService = postDaoService; + this.postDAO = postDAO; } public void setAuthenticationService(AuthenticationService authenticationService) @@ -84,9 +84,9 @@ public abstract class AbstractFeedGenerator implements FeedGenerator return this.maxItemsPerCycle; } - public ActivityPostDaoService getPostDaoService() + public ActivityPostDAO getPostDaoService() { - return this.postDaoService; + return this.postDAO; } public AuthenticationService getAuthenticationService() @@ -112,7 +112,7 @@ public abstract class AbstractFeedGenerator implements FeedGenerator */ private void checkProperties() { - PropertyCheck.mandatory(this, "postDaoService", postDaoService); + PropertyCheck.mandatory(this, "postDAO", postDAO); } diff --git a/source/java/org/alfresco/repo/activities/feed/FeedTaskProcessor.java b/source/java/org/alfresco/repo/activities/feed/FeedTaskProcessor.java index 211564cdb5..5beb021590 100644 --- a/source/java/org/alfresco/repo/activities/feed/FeedTaskProcessor.java +++ b/source/java/org/alfresco/repo/activities/feed/FeedTaskProcessor.java @@ -45,8 +45,9 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; -import org.alfresco.repo.activities.feed.control.FeedControlDAO; -import org.alfresco.repo.activities.post.ActivityPostDAO; +import org.alfresco.repo.domain.activities.ActivityFeedEntity; +import org.alfresco.repo.domain.activities.ActivityPostEntity; +import org.alfresco.repo.domain.activities.FeedControlEntity; import org.alfresco.repo.template.ISO8601DateFormatMethod; import org.alfresco.util.Base64; import org.alfresco.util.JSONtoFmModel; @@ -86,15 +87,15 @@ public abstract class FeedTaskProcessor logger.debug(">>> Process: jobTaskNode '" + jobTaskNode + "' from seq '" + minSeq + "' to seq '" + maxSeq + "' on this node from grid job."); } - ActivityPostDAO selector = new ActivityPostDAO(); + ActivityPostEntity selector = new ActivityPostEntity(); selector.setJobTaskNode(jobTaskNode); selector.setMinId(minSeq); selector.setMaxId(maxSeq); - selector.setStatus(ActivityPostDAO.STATUS.POSTED.toString()); + selector.setStatus(ActivityPostEntity.STATUS.POSTED.toString()); String ticket = ctx.getTicket(); - List activityPosts = null; + List activityPosts = null; int totalGenerated = 0; try @@ -112,7 +113,7 @@ public abstract class FeedTaskProcessor Map templateCache = new TreeMap(); // for each activity post ... - for (ActivityPostDAO activityPost : activityPosts) + for (ActivityPostEntity activityPost : activityPosts) { String postingUserId = activityPost.getUserId(); String activityType = activityPost.getActivityType(); @@ -172,7 +173,7 @@ public abstract class FeedTaskProcessor if (fmTemplates.size() == 0) { logger.error(">>> Skipping activity post " + activityPost.getId() + " since no specific/generic templates for activityType: " + activityType ); - updatePostStatus(activityPost.getId(), ActivityPostDAO.STATUS.ERROR); + updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR); continue; } @@ -184,7 +185,7 @@ public abstract class FeedTaskProcessor catch(JSONException je) { logger.error(">>> Skipping activity post " + activityPost.getId() + " due to invalid activity data: " + je); - updatePostStatus(activityPost.getId(), ActivityPostDAO.STATUS.ERROR); + updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR); continue; } @@ -221,7 +222,7 @@ public abstract class FeedTaskProcessor catch(Exception e) { logger.error(">>> Skipping activity post " + activityPost.getId() + " since failed to get site members: " + e); - updatePostStatus(activityPost.getId(), ActivityPostDAO.STATUS.ERROR); + updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR); continue; } } @@ -240,7 +241,7 @@ public abstract class FeedTaskProcessor for (String connectedUser : connectedUsers) { - List feedControls = null; + List feedControls = null; if (! connectedUser.equals("")) { feedControls = getFeedControls(connectedUser); @@ -272,7 +273,7 @@ public abstract class FeedTaskProcessor logger.warn("Unknown format for: " + fmTemplate + " default to '"+formatFound+"'"); } - ActivityFeedDAO feed = new ActivityFeedDAO(); + ActivityFeedEntity feed = new ActivityFeedEntity(); // Generate activity feed summary feed.setFeedUserId(connectedUser); @@ -312,7 +313,7 @@ public abstract class FeedTaskProcessor } } - updatePostStatus(activityPost.getId(), ActivityPostDAO.STATUS.PROCESSED); + updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.PROCESSED); commitTransaction(); @@ -344,13 +345,13 @@ public abstract class FeedTaskProcessor public abstract void endTransaction() throws SQLException; - public abstract List selectPosts(ActivityPostDAO selector) throws SQLException; + public abstract List selectPosts(ActivityPostEntity selector) throws SQLException; - public abstract List selectUserFeedControls(String userId) throws SQLException; + public abstract List selectUserFeedControls(String userId) throws SQLException; - public abstract long insertFeedEntry(ActivityFeedDAO feed) throws SQLException; + public abstract long insertFeedEntry(ActivityFeedEntity feed) throws SQLException; - public abstract int updatePostStatus(long id, ActivityPostDAO.STATUS status) throws SQLException; + public abstract int updatePostStatus(long id, ActivityPostEntity.STATUS status) throws SQLException; protected String callWebScript(String urlString, String ticket) throws MalformedURLException, URISyntaxException, IOException @@ -531,20 +532,20 @@ public abstract class FeedTaskProcessor return textWriter.toString(); } - protected List getFeedControls(String connectedUser) throws SQLException + protected List getFeedControls(String connectedUser) throws SQLException { // TODO cache for this run return selectUserFeedControls(connectedUser); } - protected boolean acceptActivity(ActivityPostDAO activityPost, List feedControls) + protected boolean acceptActivity(ActivityPostEntity activityPost, List feedControls) { if (feedControls == null) { return true; } - for (FeedControlDAO feedControl : feedControls) + for (FeedControlEntity feedControl : feedControls) { if (((feedControl.getSiteNetwork() == null) || (feedControl.getSiteNetwork().length() == 0)) && (feedControl.getAppTool() != null)) { diff --git a/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleaner.java b/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleaner.java index d8471595e3..e20c3bf535 100644 --- a/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleaner.java +++ b/source/java/org/alfresco/repo/activities/feed/cleanup/FeedCleaner.java @@ -28,7 +28,7 @@ import java.sql.SQLException; import java.util.Date; import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.activities.feed.ActivityFeedDaoService; +import org.alfresco.repo.domain.activities.ActivityFeedDAO; import org.alfresco.util.PropertyCheck; import org.alfresco.util.VmShutdownListener; import org.apache.commons.logging.Log; @@ -46,11 +46,11 @@ public class FeedCleaner private int maxAgeMins = 0; - private ActivityFeedDaoService feedDaoService; + private ActivityFeedDAO feedDAO; - public void setFeedDaoService(ActivityFeedDaoService feedDaoService) + public void setFeedDAO(ActivityFeedDAO feedDAO) { - this.feedDaoService = feedDaoService; + this.feedDAO = feedDAO; } public void setMaxAgeMins(int mins) @@ -63,7 +63,7 @@ public class FeedCleaner */ private void checkProperties() { - PropertyCheck.mandatory(this, "feedDaoService", feedDaoService); + PropertyCheck.mandatory(this, "feedDAO", feedDAO); // check the max age if (maxAgeMins <= 0) @@ -82,7 +82,7 @@ public class FeedCleaner Date keepDate = new Date(keepTimeOffset); // clean old entries - int deletedCount = feedDaoService.deleteFeedEntries(keepDate); + int deletedCount = feedDAO.deleteFeedEntries(keepDate); if (logger.isDebugEnabled()) { diff --git a/source/java/org/alfresco/repo/activities/feed/local/LocalFeedTaskProcessor.java b/source/java/org/alfresco/repo/activities/feed/local/LocalFeedTaskProcessor.java index cd4c0288ab..7333b8fcb0 100644 --- a/source/java/org/alfresco/repo/activities/feed/local/LocalFeedTaskProcessor.java +++ b/source/java/org/alfresco/repo/activities/feed/local/LocalFeedTaskProcessor.java @@ -27,13 +27,13 @@ package org.alfresco.repo.activities.feed.local; import java.sql.SQLException; import java.util.List; -import org.alfresco.repo.activities.feed.ActivityFeedDAO; -import org.alfresco.repo.activities.feed.ActivityFeedDaoService; import org.alfresco.repo.activities.feed.FeedTaskProcessor; -import org.alfresco.repo.activities.feed.control.FeedControlDAO; -import org.alfresco.repo.activities.feed.control.FeedControlDaoService; -import org.alfresco.repo.activities.post.ActivityPostDAO; -import org.alfresco.repo.activities.post.ActivityPostDaoService; +import org.alfresco.repo.domain.activities.ActivityFeedDAO; +import org.alfresco.repo.domain.activities.ActivityFeedEntity; +import org.alfresco.repo.domain.activities.ActivityPostDAO; +import org.alfresco.repo.domain.activities.ActivityPostEntity; +import org.alfresco.repo.domain.activities.FeedControlDAO; +import org.alfresco.repo.domain.activities.FeedControlEntity; import com.ibatis.sqlmap.client.SqlMapClient; @@ -42,27 +42,27 @@ import com.ibatis.sqlmap.client.SqlMapClient; */ public class LocalFeedTaskProcessor extends FeedTaskProcessor { - private ActivityPostDaoService postDaoService; - private ActivityFeedDaoService feedDaoService; - private FeedControlDaoService feedControlDaoService; + private ActivityPostDAO postDAO; + private ActivityFeedDAO feedDAO; + private FeedControlDAO feedControlDAO; // used to start/end/commit transaction // note: currently assumes that all dao services are configured with this mapper / data source private SqlMapClient sqlMapper; - public void setPostDaoService(ActivityPostDaoService postDaoService) + public void setPostDAO(ActivityPostDAO postDAO) { - this.postDaoService = postDaoService; + this.postDAO = postDAO; } - public void setFeedDaoService(ActivityFeedDaoService feedDaoService) + public void setFeedDAO(ActivityFeedDAO feedDAO) { - this.feedDaoService = feedDaoService; + this.feedDAO = feedDAO; } - public void setFeedControlDaoService(FeedControlDaoService feedControlDaoService) + public void setFeedControlDAO(FeedControlDAO feedControlDAO) { - this.feedControlDaoService = feedControlDaoService; + this.feedControlDAO = feedControlDAO; } public void setSqlMapClient(SqlMapClient sqlMapper) @@ -85,23 +85,23 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor sqlMapper.endTransaction(); } - public List selectPosts(ActivityPostDAO selector) throws SQLException + public List selectPosts(ActivityPostEntity selector) throws SQLException { - return postDaoService.selectPosts(selector); + return postDAO.selectPosts(selector); } - public long insertFeedEntry(ActivityFeedDAO feed) throws SQLException + public long insertFeedEntry(ActivityFeedEntity feed) throws SQLException { - return feedDaoService.insertFeedEntry(feed); + return feedDAO.insertFeedEntry(feed); } - public int updatePostStatus(long id, ActivityPostDAO.STATUS status) throws SQLException + public int updatePostStatus(long id, ActivityPostEntity.STATUS status) throws SQLException { - return postDaoService.updatePostStatus(id, status); + return postDAO.updatePostStatus(id, status); } - public List selectUserFeedControls(String userId) throws SQLException + public List selectUserFeedControls(String userId) throws SQLException { - return feedControlDaoService.selectFeedControls(userId); + return feedControlDAO.selectFeedControls(userId); } } diff --git a/source/java/org/alfresco/repo/activities/hibernate/Activities.hbm.xml b/source/java/org/alfresco/repo/activities/hibernate/Activities.hbm.xml index f2ed7c92de..9a60fcf431 100644 --- a/source/java/org/alfresco/repo/activities/hibernate/Activities.hbm.xml +++ b/source/java/org/alfresco/repo/activities/hibernate/Activities.hbm.xml @@ -9,7 +9,7 @@ @@ -30,7 +30,7 @@ @@ -52,7 +52,7 @@ diff --git a/source/java/org/alfresco/repo/activities/post/cleanup/PostCleaner.java b/source/java/org/alfresco/repo/activities/post/cleanup/PostCleaner.java index 82362ed8a1..733babcab9 100644 --- a/source/java/org/alfresco/repo/activities/post/cleanup/PostCleaner.java +++ b/source/java/org/alfresco/repo/activities/post/cleanup/PostCleaner.java @@ -28,8 +28,8 @@ import java.sql.SQLException; import java.util.Date; import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.activities.post.ActivityPostDAO; -import org.alfresco.repo.activities.post.ActivityPostDaoService; +import org.alfresco.repo.domain.activities.ActivityPostDAO; +import org.alfresco.repo.domain.activities.ActivityPostEntity; import org.alfresco.util.PropertyCheck; import org.alfresco.util.VmShutdownListener; import org.apache.commons.logging.Log; @@ -47,11 +47,11 @@ public class PostCleaner private int maxAgeMins = 0; - private ActivityPostDaoService postDaoService; + private ActivityPostDAO postDAO; - public void setPostDaoService(ActivityPostDaoService postDaoService) + public void setPostDAO(ActivityPostDAO postDAO) { - this.postDaoService = postDaoService; + this.postDAO = postDAO; } public void setMaxAgeMins(int mins) @@ -64,7 +64,7 @@ public class PostCleaner */ private void checkProperties() { - PropertyCheck.mandatory(this, "postDaoService", postDaoService); + PropertyCheck.mandatory(this, "postDAO", postDAO); // check the max age if (maxAgeMins <= 0) @@ -83,7 +83,7 @@ public class PostCleaner Date keepDate = new Date(keepTimeOffset); // clean old entries - PROCESSED - does not clean POSTED or PENDING, which will need to be done manually, if stuck - int deletedCount = postDaoService.deletePosts(keepDate, ActivityPostDAO.STATUS.PROCESSED); + int deletedCount = postDAO.deletePosts(keepDate, ActivityPostEntity.STATUS.PROCESSED); if (logger.isDebugEnabled()) { diff --git a/source/java/org/alfresco/repo/activities/post/lookup/PostLookup.java b/source/java/org/alfresco/repo/activities/post/lookup/PostLookup.java index d822d486a5..3300703e3d 100644 --- a/source/java/org/alfresco/repo/activities/post/lookup/PostLookup.java +++ b/source/java/org/alfresco/repo/activities/post/lookup/PostLookup.java @@ -29,8 +29,8 @@ import java.util.Date; import java.util.List; import org.alfresco.model.ContentModel; -import org.alfresco.repo.activities.post.ActivityPostDAO; -import org.alfresco.repo.activities.post.ActivityPostDaoService; +import org.alfresco.repo.domain.activities.ActivityPostDAO; +import org.alfresco.repo.domain.activities.ActivityPostEntity; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.tenant.TenantService; @@ -61,16 +61,16 @@ public class PostLookup private static VmShutdownListener vmShutdownListener = new VmShutdownListener(PostLookup.class.getName()); - private ActivityPostDaoService postDaoService; + private ActivityPostDAO postDAO; private NodeService nodeService; private PermissionService permissionService; private TransactionService transactionService; private PersonService personService; private TenantService tenantService; - public void setPostDaoService(ActivityPostDaoService postDaoService) + public void setPostDAO(ActivityPostDAO postDAO) { - this.postDaoService = postDaoService; + this.postDAO = postDAO; } public void setNodeService(NodeService nodeService) @@ -103,7 +103,7 @@ public class PostLookup */ private void checkProperties() { - PropertyCheck.mandatory(this, "postDaoService", postDaoService); + PropertyCheck.mandatory(this, "postDAO", postDAO); PropertyCheck.mandatory(this, "nodeService", nodeService); PropertyCheck.mandatory(this, "permissionService", permissionService); PropertyCheck.mandatory(this, "transactionService", transactionService); @@ -116,21 +116,21 @@ public class PostLookup checkProperties(); try { - ActivityPostDAO params = new ActivityPostDAO(); - params.setStatus(ActivityPostDAO.STATUS.PENDING.toString()); + ActivityPostEntity params = new ActivityPostEntity(); + params.setStatus(ActivityPostEntity.STATUS.PENDING.toString()); - List activityPosts = postDaoService.selectPosts(params); + List activityPosts = postDAO.selectPosts(params); if (activityPosts.size() > 0) { logger.info("Update: " + activityPosts.size() + " activity posts"); } - for (final ActivityPostDAO activityPost : activityPosts) + for (final ActivityPostEntity activityPost : activityPosts) { try { - postDaoService.startTransaction(); + postDAO.startTransaction(); final JSONObject jo = new JSONObject(new JSONTokener(activityPost.getActivityData())); final String postUserId = activityPost.getUserId(); @@ -167,10 +167,10 @@ public class PostLookup activityPost.setLastModified(new Date()); - postDaoService.updatePost(activityPost.getId(), activityPost.getSiteNetwork(), activityPost.getActivityData(), ActivityPostDAO.STATUS.POSTED); + postDAO.updatePost(activityPost.getId(), activityPost.getSiteNetwork(), activityPost.getActivityData(), ActivityPostEntity.STATUS.POSTED); if (logger.isDebugEnabled()) { - activityPost.setStatus(ActivityPostDAO.STATUS.POSTED.toString()); // for debug output + activityPost.setStatus(ActivityPostEntity.STATUS.POSTED.toString()); // for debug output logger.debug("Updated: " + activityPost); } @@ -178,15 +178,15 @@ public class PostLookup } }, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain)); - postDaoService.commitTransaction(); + postDAO.commitTransaction(); } catch (JSONException e) { // log error, but consume exception (skip this post) logger.error("Skipping activity post " + activityPost.getId() + ": " + e); - postDaoService.updatePostStatus(activityPost.getId(), ActivityPostDAO.STATUS.ERROR); + postDAO.updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR); - postDaoService.commitTransaction(); + postDAO.commitTransaction(); } catch (SQLException e) { @@ -195,7 +195,7 @@ public class PostLookup } finally { - postDaoService.endTransaction(); + postDAO.endTransaction(); } } } diff --git a/source/java/org/alfresco/repo/activities/ibatis/ActivityDaoService.java b/source/java/org/alfresco/repo/domain/activities/ActivitiesDAO.java similarity index 94% rename from source/java/org/alfresco/repo/activities/ibatis/ActivityDaoService.java rename to source/java/org/alfresco/repo/domain/activities/ActivitiesDAO.java index 9d383583aa..cdc7003104 100644 --- a/source/java/org/alfresco/repo/activities/ibatis/ActivityDaoService.java +++ b/source/java/org/alfresco/repo/domain/activities/ActivitiesDAO.java @@ -22,14 +22,14 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.ibatis; +package org.alfresco.repo.domain.activities; import java.sql.SQLException; /** * Common interface for activity DAO service */ -public interface ActivityDaoService +public interface ActivitiesDAO { public void startTransaction() throws SQLException; diff --git a/source/java/org/alfresco/repo/activities/feed/ActivityFeedDaoService.java b/source/java/org/alfresco/repo/domain/activities/ActivityFeedDAO.java similarity index 72% rename from source/java/org/alfresco/repo/activities/feed/ActivityFeedDaoService.java rename to source/java/org/alfresco/repo/domain/activities/ActivityFeedDAO.java index 69c942c19e..5da40625f1 100644 --- a/source/java/org/alfresco/repo/activities/feed/ActivityFeedDaoService.java +++ b/source/java/org/alfresco/repo/domain/activities/ActivityFeedDAO.java @@ -22,24 +22,22 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.feed; +package org.alfresco.repo.domain.activities; import java.sql.SQLException; import java.util.Date; import java.util.List; -import org.alfresco.repo.activities.ibatis.ActivityDaoService; - /** * Interface for activity feed DAO service */ -public interface ActivityFeedDaoService extends ActivityDaoService +public interface ActivityFeedDAO extends ActivitiesDAO { - public long insertFeedEntry(ActivityFeedDAO activityFeed) throws SQLException; + public long insertFeedEntry(ActivityFeedEntity activityFeed) throws SQLException; public int deleteFeedEntries(Date keepDate) throws SQLException; - public List selectUserFeedEntries(String feedUserId, String format, String siteId, boolean excludeThisUser, boolean excludeOtherUsers) throws SQLException; + public List selectUserFeedEntries(String feedUserId, String format, String siteId, boolean excludeThisUser, boolean excludeOtherUsers) throws SQLException; - public List selectSiteFeedEntries(String siteUserId, String format) throws SQLException; + public List selectSiteFeedEntries(String siteUserId, String format) throws SQLException; } diff --git a/source/java/org/alfresco/repo/activities/feed/ActivityFeedDAO.java b/source/java/org/alfresco/repo/domain/activities/ActivityFeedEntity.java similarity index 98% rename from source/java/org/alfresco/repo/activities/feed/ActivityFeedDAO.java rename to source/java/org/alfresco/repo/domain/activities/ActivityFeedEntity.java index 9d5957847d..e0aac12cba 100644 --- a/source/java/org/alfresco/repo/activities/feed/ActivityFeedDAO.java +++ b/source/java/org/alfresco/repo/domain/activities/ActivityFeedEntity.java @@ -22,7 +22,7 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.feed; +package org.alfresco.repo.domain.activities; import java.util.Date; @@ -33,7 +33,7 @@ import org.json.JSONObject; /** * Activity Feed DAO */ -public class ActivityFeedDAO +public class ActivityFeedEntity { private Long id; // internal DB-generated id private String activityType; diff --git a/source/java/org/alfresco/repo/activities/post/ActivityPostDaoService.java b/source/java/org/alfresco/repo/domain/activities/ActivityPostDAO.java similarity index 72% rename from source/java/org/alfresco/repo/activities/post/ActivityPostDaoService.java rename to source/java/org/alfresco/repo/domain/activities/ActivityPostDAO.java index 5c2608f8e3..8771672a68 100644 --- a/source/java/org/alfresco/repo/activities/post/ActivityPostDaoService.java +++ b/source/java/org/alfresco/repo/domain/activities/ActivityPostDAO.java @@ -22,20 +22,18 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.post; +package org.alfresco.repo.domain.activities; import java.sql.SQLException; import java.util.Date; import java.util.List; -import org.alfresco.repo.activities.ibatis.ActivityDaoService; - /** * Interface for activity post DAO service */ -public interface ActivityPostDaoService extends ActivityDaoService +public interface ActivityPostDAO extends ActivitiesDAO { - public List selectPosts(ActivityPostDAO activityPost) throws SQLException; + public List selectPosts(ActivityPostEntity activityPost) throws SQLException; public Long getMaxActivitySeq() throws SQLException; @@ -43,11 +41,11 @@ public interface ActivityPostDaoService extends ActivityDaoService public Integer getMaxNodeHash() throws SQLException; - public int deletePosts(Date keepDate, ActivityPostDAO.STATUS status) throws SQLException; + public int deletePosts(Date keepDate, ActivityPostEntity.STATUS status) throws SQLException; - public long insertPost(ActivityPostDAO activityPost) throws SQLException; + public long insertPost(ActivityPostEntity activityPost) throws SQLException; - public int updatePost(long id, String network, String activityData, ActivityPostDAO.STATUS status) throws SQLException; + public int updatePost(long id, String network, String activityData, ActivityPostEntity.STATUS status) throws SQLException; - public int updatePostStatus(long id, ActivityPostDAO.STATUS status) throws SQLException; + public int updatePostStatus(long id, ActivityPostEntity.STATUS status) throws SQLException; } diff --git a/source/java/org/alfresco/repo/activities/post/ActivityPostDAO.java b/source/java/org/alfresco/repo/domain/activities/ActivityPostEntity.java similarity index 98% rename from source/java/org/alfresco/repo/activities/post/ActivityPostDAO.java rename to source/java/org/alfresco/repo/domain/activities/ActivityPostEntity.java index 3d6450a9a8..686b9250c0 100644 --- a/source/java/org/alfresco/repo/activities/post/ActivityPostDAO.java +++ b/source/java/org/alfresco/repo/domain/activities/ActivityPostEntity.java @@ -22,14 +22,14 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.post; +package org.alfresco.repo.domain.activities; import java.util.Date; /** * Activity Post DAO */ -public class ActivityPostDAO +public class ActivityPostEntity { public enum STATUS { POSTED, PENDING, PROCESSED, ERROR }; diff --git a/source/java/org/alfresco/repo/activities/feed/control/FeedControlDaoService.java b/source/java/org/alfresco/repo/domain/activities/FeedControlDAO.java similarity index 74% rename from source/java/org/alfresco/repo/activities/feed/control/FeedControlDaoService.java rename to source/java/org/alfresco/repo/domain/activities/FeedControlDAO.java index d05df58b9a..0184197f6e 100644 --- a/source/java/org/alfresco/repo/activities/feed/control/FeedControlDaoService.java +++ b/source/java/org/alfresco/repo/domain/activities/FeedControlDAO.java @@ -22,7 +22,7 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.feed.control; +package org.alfresco.repo.domain.activities; import java.sql.SQLException; import java.util.List; @@ -30,13 +30,13 @@ import java.util.List; /** * Interface for user activity feed controls DAO service */ -public interface FeedControlDaoService +public interface FeedControlDAO { - public long insertFeedControl(FeedControlDAO activityFeedControl) throws SQLException; + public long insertFeedControl(FeedControlEntity activityFeedControl) throws SQLException; - public int deleteFeedControl(FeedControlDAO activityFeedControl) throws SQLException; + public int deleteFeedControl(FeedControlEntity activityFeedControl) throws SQLException; - public List selectFeedControls(String userId) throws SQLException; + public List selectFeedControls(String userId) throws SQLException; - public long selectFeedControl(FeedControlDAO activityFeedControl) throws SQLException; + public long selectFeedControl(FeedControlEntity activityFeedControl) throws SQLException; } diff --git a/source/java/org/alfresco/repo/activities/feed/control/FeedControlDAO.java b/source/java/org/alfresco/repo/domain/activities/FeedControlEntity.java similarity index 93% rename from source/java/org/alfresco/repo/activities/feed/control/FeedControlDAO.java rename to source/java/org/alfresco/repo/domain/activities/FeedControlEntity.java index 3424e58ec2..2228562992 100644 --- a/source/java/org/alfresco/repo/activities/feed/control/FeedControlDAO.java +++ b/source/java/org/alfresco/repo/domain/activities/FeedControlEntity.java @@ -22,7 +22,7 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.feed.control; +package org.alfresco.repo.domain.activities; import java.util.Date; @@ -31,7 +31,7 @@ import org.alfresco.service.cmr.activities.FeedControl; /** * Activity Feed Control DAO */ -public class FeedControlDAO +public class FeedControlEntity { private Long id; // internal DB-generated id private String feedUserId; @@ -44,16 +44,16 @@ public class FeedControlDAO // it is possible for a feed control to be applied even if lastModified is greater than postDate - could check the date ! // it is also possible for a feed control to not be applied if it is deleted just after the post - would need to keep, at least until next generation - public FeedControlDAO() + public FeedControlEntity() { } - public FeedControlDAO(String feedUserId) + public FeedControlEntity(String feedUserId) { this.feedUserId = feedUserId; } - public FeedControlDAO(String feedUserId, FeedControl feedControl) + public FeedControlEntity(String feedUserId, FeedControl feedControl) { this.feedUserId = feedUserId; this.siteNetwork = feedControl.getSiteId(); diff --git a/source/java/org/alfresco/repo/activities/ibatis/IBatisActivityFeedDaoServiceImpl.java b/source/java/org/alfresco/repo/domain/activities/ibatis/ActivityFeedDAOImpl.java similarity index 66% rename from source/java/org/alfresco/repo/activities/ibatis/IBatisActivityFeedDaoServiceImpl.java rename to source/java/org/alfresco/repo/domain/activities/ibatis/ActivityFeedDAOImpl.java index 2bcfe93198..cba2e11d8f 100644 --- a/source/java/org/alfresco/repo/activities/ibatis/IBatisActivityFeedDaoServiceImpl.java +++ b/source/java/org/alfresco/repo/domain/activities/ibatis/ActivityFeedDAOImpl.java @@ -22,7 +22,7 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.ibatis; +package org.alfresco.repo.domain.activities.ibatis; import java.sql.SQLException; import java.util.ArrayList; @@ -30,12 +30,12 @@ import java.util.Date; import java.util.List; import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.activities.feed.ActivityFeedDAO; -import org.alfresco.repo.activities.feed.ActivityFeedDaoService; +import org.alfresco.repo.domain.activities.ActivityFeedDAO; +import org.alfresco.repo.domain.activities.ActivityFeedEntity; -public class IBatisActivityFeedDaoServiceImpl extends IBatisSqlMapper implements ActivityFeedDaoService +public class ActivityFeedDAOImpl extends IBatisSqlMapper implements ActivityFeedDAO { - public long insertFeedEntry(ActivityFeedDAO activityFeed) throws SQLException + public long insertFeedEntry(ActivityFeedEntity activityFeed) throws SQLException { Long id = (Long)getSqlMapClient().insert("insert.activity.feed", activityFeed); return (id != null ? id : -1); @@ -47,9 +47,9 @@ public class IBatisActivityFeedDaoServiceImpl extends IBatisSqlMapper implements } @SuppressWarnings("unchecked") - public List selectUserFeedEntries(String feedUserId, String format, String siteId, boolean excludeThisUser, boolean excludeOtherUsers) throws SQLException + public List selectUserFeedEntries(String feedUserId, String format, String siteId, boolean excludeThisUser, boolean excludeOtherUsers) throws SQLException { - ActivityFeedDAO params = new ActivityFeedDAO(); + ActivityFeedEntity params = new ActivityFeedEntity(); params.setFeedUserId(feedUserId); params.setActivitySummaryFormat(format); @@ -61,22 +61,22 @@ public class IBatisActivityFeedDaoServiceImpl extends IBatisSqlMapper implements if (excludeThisUser && excludeOtherUsers) { // effectively NOOP - return empty feed - return new ArrayList(0); + return new ArrayList(0); } if ((!excludeThisUser) && (!excludeOtherUsers)) { // no excludes => everyone => where feed user is me - return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.and.site", params); + return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.and.site", params); } else if ((excludeThisUser) && (!excludeOtherUsers)) { // exclude feed user => others => where feed user is me and post user is not me - return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.others.and.site", params); + return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.others.and.site", params); } else if ((excludeOtherUsers) && (!excludeThisUser)) { // exclude others => me => where feed user is me and post user is me - return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.me.and.site", params); + return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.me.and.site", params); } } else @@ -86,22 +86,22 @@ public class IBatisActivityFeedDaoServiceImpl extends IBatisSqlMapper implements if (excludeThisUser && excludeOtherUsers) { // effectively NOOP - return empty feed - return new ArrayList(0); + return new ArrayList(0); } if (!excludeThisUser && !excludeOtherUsers) { // no excludes => everyone => where feed user is me - return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser", params); + return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser", params); } else if (excludeThisUser) { // exclude feed user => others => where feed user is me and post user is not me - return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.others", params); + return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.others", params); } else if (excludeOtherUsers) { // exclude others => me => where feed user is me and post user is me - return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.me", params); + return (List)getSqlMapClient().queryForList("select.activity.feed.for.feeduser.me", params); } } @@ -110,13 +110,13 @@ public class IBatisActivityFeedDaoServiceImpl extends IBatisSqlMapper implements } @SuppressWarnings("unchecked") - public List selectSiteFeedEntries(String siteId, String format) throws SQLException + public List selectSiteFeedEntries(String siteId, String format) throws SQLException { - ActivityFeedDAO params = new ActivityFeedDAO(); + ActivityFeedEntity params = new ActivityFeedEntity(); params.setSiteNetwork(siteId); params.setActivitySummaryFormat(format); // for given site - return (List)getSqlMapClient().queryForList("select.activity.feed.for.site", params); + return (List)getSqlMapClient().queryForList("select.activity.feed.for.site", params); } } diff --git a/source/java/org/alfresco/repo/activities/ibatis/IBatisActivityPostDaoServiceImpl.java b/source/java/org/alfresco/repo/domain/activities/ibatis/ActivityPostDAOImpl.java similarity index 72% rename from source/java/org/alfresco/repo/activities/ibatis/IBatisActivityPostDaoServiceImpl.java rename to source/java/org/alfresco/repo/domain/activities/ibatis/ActivityPostDAOImpl.java index dae02b58d1..a8193a7760 100644 --- a/source/java/org/alfresco/repo/activities/ibatis/IBatisActivityPostDaoServiceImpl.java +++ b/source/java/org/alfresco/repo/domain/activities/ibatis/ActivityPostDAOImpl.java @@ -22,35 +22,35 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.ibatis; +package org.alfresco.repo.domain.activities.ibatis; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; -import org.alfresco.repo.activities.post.ActivityPostDAO; -import org.alfresco.repo.activities.post.ActivityPostDaoService; +import org.alfresco.repo.domain.activities.ActivityPostDAO; +import org.alfresco.repo.domain.activities.ActivityPostEntity; -public class IBatisActivityPostDaoServiceImpl extends IBatisSqlMapper implements ActivityPostDaoService +public class ActivityPostDAOImpl extends IBatisSqlMapper implements ActivityPostDAO { @SuppressWarnings("unchecked") - public List selectPosts(ActivityPostDAO activityPost) throws SQLException + public List selectPosts(ActivityPostEntity activityPost) throws SQLException { if ((activityPost.getJobTaskNode() != -1) && (activityPost.getMinId() != -1) && (activityPost.getMaxId() != -1) && (activityPost.getStatus() != null)) { - return (List)getSqlMapClient().queryForList("select.activity.posts", activityPost); + return (List)getSqlMapClient().queryForList("select.activity.posts", activityPost); } else if (activityPost.getStatus() != null) { - return (List)getSqlMapClient().queryForList("select.activity.posts.by.status.only", activityPost); + return (List)getSqlMapClient().queryForList("select.activity.posts.by.status.only", activityPost); } else { - return new ArrayList(0); + return new ArrayList(0); } } @@ -69,9 +69,9 @@ public class IBatisActivityPostDaoServiceImpl extends IBatisSqlMapper implements return (Integer)getSqlMapClient().queryForObject("select.activity.post.max.jobtasknode"); } - public int updatePost(long id, String siteNetwork, String activityData, ActivityPostDAO.STATUS status) throws SQLException + public int updatePost(long id, String siteNetwork, String activityData, ActivityPostEntity.STATUS status) throws SQLException { - ActivityPostDAO post = new ActivityPostDAO(); + ActivityPostEntity post = new ActivityPostEntity(); post.setId(id); post.setSiteNetwork(siteNetwork); post.setActivityData(activityData); @@ -81,9 +81,9 @@ public class IBatisActivityPostDaoServiceImpl extends IBatisSqlMapper implements return getSqlMapClient().update("update.activity.post.data", post); } - public int updatePostStatus(long id, ActivityPostDAO.STATUS status) throws SQLException + public int updatePostStatus(long id, ActivityPostEntity.STATUS status) throws SQLException { - ActivityPostDAO post = new ActivityPostDAO(); + ActivityPostEntity post = new ActivityPostEntity(); post.setId(id); post.setStatus(status.toString()); post.setLastModified(new Date()); @@ -91,16 +91,16 @@ public class IBatisActivityPostDaoServiceImpl extends IBatisSqlMapper implements return getSqlMapClient().update("update.activity.post.status", post); } - public int deletePosts(Date keepDate, ActivityPostDAO.STATUS status) throws SQLException + public int deletePosts(Date keepDate, ActivityPostEntity.STATUS status) throws SQLException { - ActivityPostDAO params = new ActivityPostDAO(); + ActivityPostEntity params = new ActivityPostEntity(); params.setPostDate(keepDate); params.setStatus(status.toString()); return getSqlMapClient().delete("delete.activity.posts.older.than.date", params); } - public long insertPost(ActivityPostDAO activityPost) throws SQLException + public long insertPost(ActivityPostEntity activityPost) throws SQLException { Long id = (Long)getSqlMapClient().insert("insert.activity.post", activityPost); return (id != null ? id : -1); diff --git a/source/java/org/alfresco/repo/activities/ibatis/IBatisFeedControlDaoServiceImpl.java b/source/java/org/alfresco/repo/domain/activities/ibatis/FeedControlDAOImpl.java similarity index 67% rename from source/java/org/alfresco/repo/activities/ibatis/IBatisFeedControlDaoServiceImpl.java rename to source/java/org/alfresco/repo/domain/activities/ibatis/FeedControlDAOImpl.java index c337751d4c..7948fb4b5f 100644 --- a/source/java/org/alfresco/repo/activities/ibatis/IBatisFeedControlDaoServiceImpl.java +++ b/source/java/org/alfresco/repo/domain/activities/ibatis/FeedControlDAOImpl.java @@ -22,36 +22,36 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.ibatis; +package org.alfresco.repo.domain.activities.ibatis; import java.sql.SQLException; import java.util.List; -import org.alfresco.repo.activities.feed.control.FeedControlDAO; -import org.alfresco.repo.activities.feed.control.FeedControlDaoService; +import org.alfresco.repo.domain.activities.FeedControlDAO; +import org.alfresco.repo.domain.activities.FeedControlEntity; -public class IBatisFeedControlDaoServiceImpl extends IBatisSqlMapper implements FeedControlDaoService +public class FeedControlDAOImpl extends IBatisSqlMapper implements FeedControlDAO { - public long insertFeedControl(FeedControlDAO activityFeedControl) throws SQLException + public long insertFeedControl(FeedControlEntity activityFeedControl) throws SQLException { Long id = (Long)getSqlMapClient().insert("insert.activity.feedcontrol", activityFeedControl); return (id != null ? id : -1); } - public int deleteFeedControl(FeedControlDAO activityFeedControl) throws SQLException + public int deleteFeedControl(FeedControlEntity activityFeedControl) throws SQLException { return getSqlMapClient().delete("delete.activity.feedcontrol", activityFeedControl); } @SuppressWarnings("unchecked") - public List selectFeedControls(String feedUserId) throws SQLException + public List selectFeedControls(String feedUserId) throws SQLException { - FeedControlDAO params = new FeedControlDAO(feedUserId); + FeedControlEntity params = new FeedControlEntity(feedUserId); - return (List)getSqlMapClient().queryForList("select.activity.feedcontrols.for.user", params); + return (List)getSqlMapClient().queryForList("select.activity.feedcontrols.for.user", params); } - public long selectFeedControl(FeedControlDAO activityFeedControl) throws SQLException + public long selectFeedControl(FeedControlEntity activityFeedControl) throws SQLException { Long id = (Long)getSqlMapClient().queryForObject("select.activity.feedcontrol", activityFeedControl); return (id != null ? id : -1); diff --git a/source/java/org/alfresco/repo/activities/ibatis/IBatisSqlMapper.java b/source/java/org/alfresco/repo/domain/activities/ibatis/IBatisSqlMapper.java similarity index 91% rename from source/java/org/alfresco/repo/activities/ibatis/IBatisSqlMapper.java rename to source/java/org/alfresco/repo/domain/activities/ibatis/IBatisSqlMapper.java index 42a981ff81..25146fda1d 100644 --- a/source/java/org/alfresco/repo/activities/ibatis/IBatisSqlMapper.java +++ b/source/java/org/alfresco/repo/domain/activities/ibatis/IBatisSqlMapper.java @@ -22,13 +22,15 @@ * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ -package org.alfresco.repo.activities.ibatis; +package org.alfresco.repo.domain.activities.ibatis; import java.sql.SQLException; +import org.alfresco.repo.domain.activities.ActivitiesDAO; + import com.ibatis.sqlmap.client.SqlMapClient; -public class IBatisSqlMapper implements ActivityDaoService +public class IBatisSqlMapper implements ActivitiesDAO { private SqlMapClient sqlMapper; diff --git a/source/java/org/alfresco/repo/domain/locks/AbstractLockDAOImpl.java b/source/java/org/alfresco/repo/domain/locks/AbstractLockDAOImpl.java new file mode 100644 index 0000000000..c89b9051d1 --- /dev/null +++ b/source/java/org/alfresco/repo/domain/locks/AbstractLockDAOImpl.java @@ -0,0 +1,255 @@ +/* + * 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; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import org.alfresco.repo.domain.QNameDAO; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; +import org.springframework.dao.ConcurrencyFailureException; + +/** + * Abstract implementation of the Locks DAO. + * + * @author Derek Hulley + * @since 3.2 + */ +public abstract class AbstractLockDAOImpl implements LockDAO +{ + private QNameDAO qnameDAO; + + /** + * @return Returns the DAO for namespace ID resolution + */ + protected QNameDAO getQNameDAO() + { + return qnameDAO; + } + + /** + * @param qnameDAO DAO for namespace ID resolution + */ + public void setQnameDAO(QNameDAO qnameDAO) + { + this.qnameDAO = qnameDAO; + } + + public boolean getLock(QName lockQName, String lockApplicant, long timeToLive) + { + String qnameNamespaceUri = lockQName.getNamespaceURI(); + String qnameLocalName = lockQName.getLocalName(); + // Force lower case for case insensitivity + if (!qnameLocalName.toLowerCase().equals(qnameLocalName)) + { + lockQName = QName.createQName(qnameNamespaceUri, qnameLocalName.toLowerCase()); + qnameLocalName = lockQName.getLocalName(); + } + // Force the lock applicant to lowercase + lockApplicant = lockApplicant.toLowerCase(); + + // Resolve the namespace + Long qnameNamespaceId = qnameDAO.getOrCreateNamespace(qnameNamespaceUri).getFirst(); + + // Get the lock resource for the exclusive lock. + // All the locks that are created will need the exclusive case. + LockResourceEntity exclusiveLockResource = getLockResource(qnameNamespaceId, qnameLocalName); + if (exclusiveLockResource == null) + { + // Create it + exclusiveLockResource = createLockResource(qnameNamespaceId, qnameLocalName); + } + Long requiredExclusiveLockResourceId = exclusiveLockResource.getId(); + // Split the lock name + List lockQNames = splitLockQName(lockQName); + List requiredLockResourceIds = new ArrayList(lockQNames.size()); + // Create the lock resources + for (QName lockQNameIter : lockQNames) + { + String localname = lockQNameIter.getLocalName(); + // Get the basic lock resource, forcing a create + // TODO: Pull back all lock resources in a single query + LockResourceEntity lockResource = getLockResource(qnameNamespaceId, localname); + if (lockResource == null) + { + // Create it + lockResource = createLockResource(qnameNamespaceId, localname); + } + requiredLockResourceIds.add(lockResource.getId()); + } + + // Now, get all locks for the resources we will need + List existingLocks = getLocks(requiredLockResourceIds); + Map existingLocksMap = new HashMap(); + // Check them and make sure they don't prevent locks + for (LockEntity existingLock : existingLocks) + { + boolean canTakeLock = canTakeLock(existingLock, lockApplicant, requiredExclusiveLockResourceId); + if (!canTakeLock) + { + return false; + } + existingLocksMap.put(existingLock, existingLock); + } + // Take the locks for the resources. + // Existing locks must be updated, if required. + for (Long requiredLockResourceId : requiredLockResourceIds) + { + LockEntity requiredLock = new LockEntity(); + requiredLock.setSharedResourceId(requiredLockResourceId); + requiredLock.setExclusiveResourceId(requiredExclusiveLockResourceId); + // Does it exist? + if (existingLocksMap.containsKey(requiredLock)) + { + requiredLock = existingLocksMap.get(requiredLock); + // Do an update + throw new UnsupportedOperationException(); + } + else + { + // Create it + requiredLock = createLock( + requiredLockResourceId, + requiredExclusiveLockResourceId, + lockApplicant, + timeToLive); + } + } + return true; + } + + private boolean canTakeLock(LockEntity existingLock, String lockApplicant, Long desiredExclusiveLock) + { + if (EqualsHelper.nullSafeEquals(existingLock.getLockHolder(), lockApplicant)) + { + // The lock applicant to be is also the current lock holder. + // Regardless of lock expiry, the lock can be taken + return true; + } + else if (existingLock.hasExpired()) + { + // Expired locks are fair game + return true; + } + else if (existingLock.isExclusive()) + { + // It's a valid, exclusive lock held by someone else ... + return false; + } + else if (desiredExclusiveLock.equals(existingLock.getSharedResourceId())) + { + // We can't take an exclusive lock if a shared lock is active + return false; + } + else + { + // Good to go + return true; + } + } + + /** + * Override to get the unique, lock resource entity if one exists. + * + * @param qnameNamespaceId the namespace entity ID + * @param qnameLocalName the lock localname + * @return Returns the lock resource entity, + * or null if it doesn't exist + */ + protected abstract LockResourceEntity getLockResource(Long qnameNamespaceId, String qnameLocalName); + + /** + * Create a unique lock resource + * + * @param qnameNamespaceId the namespace entity ID + * @param qnameLocalName the lock localname + * @return Returns the newly created lock resource entity + */ + protected abstract LockResourceEntity createLockResource(Long qnameNamespaceId, String qnameLocalName); + + /** + * Get any existing lock data for the resources required. The locks returned are not filtered and + * may be expired. + * + * @param lockResourceIds a list of resource IDs for which to retrieve the current locks + * @return Returns a list of locks (expired or not) for the given lock resources + */ + protected abstract List getLocks(List lockResourceIds); + + /** + * Create a new lock. + * @param sharedResourceId the specific resource to lock + * @param exclusiveResourceId the exclusive lock that is being sought + * @param lockApplicant the ID of the lock applicant + * @param timeToLive the time, in milliseconds, for the lock to remain valid + * @return Returns the new lock + * @throws ConcurrencyFailureException if the lock was already taken at the time of creation + */ + protected abstract LockEntity createLock( + Long sharedResourceId, + Long exclusiveResourceId, + String lockApplicant, + long timeToLive); + + /** + * Split a lock's qualified name into the component parts using the '.' (period) as a + * separator on the localname. The namespace is preserved. The provided qualified + * name will always be the last component in the returned list. + * + * @param lockQName the lock name to split into it's higher-level paths + * @return Returns the namespace ID along with the ordered localnames + */ + protected List splitLockQName(QName lockQName) + { + String ns = lockQName.getNamespaceURI(); + String name = lockQName.getLocalName(); + + StringTokenizer tokenizer = new StringTokenizer(name, "."); + List ret = new ArrayList(tokenizer.countTokens()); + StringBuilder sb = new StringBuilder(); + // Fill it + boolean first = true; + while (tokenizer.hasMoreTokens()) + { + if (first) + { + first = false; + } + else + { + sb.append("."); + } + sb.append(tokenizer.nextToken()); + QName parentLockQName = QName.createQName(ns, sb.toString()); + ret.add(parentLockQName); + } + // Done + return ret; + } +} diff --git a/source/java/org/alfresco/repo/domain/locks/LockDAO.java b/source/java/org/alfresco/repo/domain/locks/LockDAO.java new file mode 100644 index 0000000000..0b9ba2222e --- /dev/null +++ b/source/java/org/alfresco/repo/domain/locks/LockDAO.java @@ -0,0 +1,48 @@ +/* + * 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; + +import org.alfresco.service.namespace.QName; + +/** + * DAO services for alf_lock and related tables + * + * @author Derek Hulley + * @since 3.2 + */ +public interface LockDAO +{ + /** + * Aquire a given exclusive lock, assigning it (and any implicitly shared locks) a + * timeout. All shared locks are implicitly taken as well. + * + * @param lockQName the unique name of the lock to acquire + * @param lockApplicant the potential lock holder's identifier (max 36 chars) + * @param timeToLive the time (in milliseconds) that the lock must remain + * @return Returns true if the lock was taken, + * otherwise false + */ + boolean getLock(QName lockQName, String lockApplicant, long timeToLive); +} diff --git a/source/java/org/alfresco/repo/domain/locks/LockDetails.java b/source/java/org/alfresco/repo/domain/locks/LockDetails.java new file mode 100644 index 0000000000..c45e526821 --- /dev/null +++ b/source/java/org/alfresco/repo/domain/locks/LockDetails.java @@ -0,0 +1,99 @@ +/* + * 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; + +import org.alfresco.service.namespace.QName; + +/** + * Class to contain details regarding a lock. A lock is specific to a given + * qualified name. For any given lock, there may exist an EXCLUSIVE + * lock or several SHARED locks. + * + * @author Derek Hulley + * @since 3.2 + */ +public class LockDetails +{ + /** + * The type of lock + * + * @author Derek Hulley + * @since 3.2 + */ + public enum LockType + { + /** + * A lock held by a specific transaction. No other (exclusive or shared) locks + * may be held for the same qualified name. + */ + EXCLUSIVE, + /** + * A lock that may be held by several transactions when no exclusive lock is held + * for the same qualified name. + */ + SHARED; + } + + private final String txnId; + private final QName lockQName; + private final LockType lockType; + + /** + * + * @param txnId the transaction holding the lock + * @param lockQName the qualified name of the lock + * @param lockType the type of lock + */ + public LockDetails(String txnId, QName lockQName, LockType lockType) + { + this.txnId = txnId; + this.lockQName = lockQName; + this.lockType = lockType; + } + + /** + * @return Returns the transaction holding the lock + */ + public String getTxnId() + { + return txnId; + } + + /** + * @return Returns the qualified name of the lock + */ + public QName getLockQName() + { + return lockQName; + } + + /** + * @return Returns the lock type + */ + public LockType getLockType() + { + return lockType; + } +} diff --git a/source/java/org/alfresco/repo/domain/locks/LockEntity.java b/source/java/org/alfresco/repo/domain/locks/LockEntity.java new file mode 100644 index 0000000000..bc325b0ac5 --- /dev/null +++ b/source/java/org/alfresco/repo/domain/locks/LockEntity.java @@ -0,0 +1,185 @@ +/* + * 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; + +import org.alfresco.util.EqualsHelper; + +/** + * Entity bean for alf_lock table. + *

+ * 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 getLocks(List lockResourceIds) + { + List locks = template.queryForList(SELECT_LOCK_BY_SHARED_IDS, lockResourceIds); + // Done + return locks; + } + + @Override + protected LockEntity createLock( + Long sharedResourceId, + Long exclusiveResourceId, + String lockApplicant, + long timeToLive) + { + LockEntity lock = new LockEntity(); + lock.setVersion(CONST_LONG_ZERO); + lock.setSharedResourceId(sharedResourceId); + lock.setExclusiveResourceId(exclusiveResourceId); + lock.setLockHolder(lockApplicant); + long now = System.currentTimeMillis(); + long exp = now + timeToLive; + lock.setStartTime(now); + lock.setExpiryTime(exp); + Long id = (Long) template.insert(INSERT_LOCK, lock); + lock.setId(id); + // Done + return lock; + } +}