diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-job-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-job-context.xml index 80d7c95f95..8244f87e89 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-job-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-job-context.xml @@ -10,27 +10,25 @@ --> - org.alfresco.module.org_alfresco_module_rm.job.NotifyOfRecordsDueForReviewJob + org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJob - - - + + + + - - - - - + + - - - - - - + + + + + + @@ -49,25 +47,27 @@ - org.alfresco.module.org_alfresco_module_rm.job.DispositionLifecycleJob + org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJob - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -84,42 +84,38 @@ - org.alfresco.module.org_alfresco_module_rm.job.PublishUpdatesJob + org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJob - - - - - - - - - - - - - - - + + + + + + + - - - - - - + + 0/30 * * * * ? + + + + + + + + - + - + diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml index 71bab37b46..12a33f08f0 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml @@ -229,10 +229,9 @@ - + - @@ -273,15 +272,11 @@ - --> + diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityService.java index 1de5b79b8a..362bb43a14 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityService.java @@ -49,21 +49,24 @@ public interface CapabilityService Capability getCapability(String name); /** + * Get a list of all the assignable capabilities. * - * @return + * @return {@link Set}<{@link Capability}> set of all the assignable capabilities */ Set getCapabilities(); /** + * Get a list of all the capabilities, optionally including those that are non-assignable. * - * @param includePrivate - * @return + * @param includePrivate indicates that the private, or non-assignable capabilities are included in the result + * @return {@link Set}<{@link Capability}> set of capabilities */ Set getCapabilities(boolean includePrivate); /** + * Get all the capabilities access state based on the current user. * - * @param nodeRef + * @param nodeRef node reference * @return */ Map getCapabilitiesAccessState(NodeRef nodeRef); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/DispositionLifecycleJob.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/DispositionLifecycleJob.java deleted file mode 100644 index 8f5b3d51ea..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/DispositionLifecycleJob.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2009-2011 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -package org.alfresco.module.org_alfresco_module_rm.job; - -import java.util.List; - -import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction; -import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.ResultSet; -import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.transaction.TransactionService; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.quartz.Job; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; - -/** - * The Disposition Lifecycle Job Finds all disposition action nodes which are - * for "retain" or "cutOff" actions Where asOf > now OR - * dispositionEventsEligible = true; - * - * Runs the cut off or retain action for - * elligible records. - * - * @author mrogers - */ -public class DispositionLifecycleJob implements Job -{ - private static Log logger = LogFactory.getLog(DispositionLifecycleJob.class); - - /** - * @see org.quartz.Job#execute(org.quartz.JobExecutionContext) - */ - public void execute(JobExecutionContext context) throws JobExecutionException - { - final RecordsManagementActionService rmActionService = (RecordsManagementActionService) context - .getJobDetail().getJobDataMap().get("recordsManagementActionService"); - final NodeService nodeService = (NodeService) context.getJobDetail().getJobDataMap().get( - "nodeService"); - final SearchService search = (SearchService) context.getJobDetail().getJobDataMap().get( - "searchService"); - final TransactionService trxService = (TransactionService) context.getJobDetail() - .getJobDataMap().get("transactionService"); - - logger.debug("Job Starting"); - - AuthenticationUtil.runAs(new RunAsWork() - { - public Object doWork() throws Exception - { - StringBuilder sb = new StringBuilder(); - sb.append("+TYPE:\"rma:dispositionAction\" "); - sb.append("+(@rma\\:dispositionAction:(\"cutoff\" OR \"retain\"))"); - sb.append("+ISNULL:\"rma:dispositionActionCompletedAt\" "); - sb.append("+( "); - sb.append("@rma\\:dispositionEventsEligible:true "); - sb.append("OR @rma\\:dispositionAsOf:[MIN TO NOW] "); - sb.append(") "); - - String query = sb.toString(); - - ResultSet results = search.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, - SearchService.LANGUAGE_LUCENE, query); - List resultNodes = results.getNodeRefs(); - results.close(); - - RetryingTransactionHelper trn = trxService.getRetryingTransactionHelper(); - - for (NodeRef node : resultNodes) - { - final NodeRef currentNode = node; - - RetryingTransactionCallback processTranCB = new RetryingTransactionCallback() - { - public Boolean execute() throws Throwable - { - final String dispAction = (String) nodeService.getProperty(currentNode, - RecordsManagementModel.PROP_DISPOSITION_ACTION); - - // Run "retain" and "cutoff" actions. - - if (dispAction != null) - { - if (dispAction.equalsIgnoreCase("cutoff") || - dispAction.equalsIgnoreCase("retain")) - { - ChildAssociationRef parent = nodeService.getPrimaryParent(currentNode); - if (parent.getTypeQName().equals(RecordsManagementModel.ASSOC_NEXT_DISPOSITION_ACTION)) - { - // Check that the action is executable - RecordsManagementAction rmAction = rmActionService.getDispositionAction(dispAction); - if (rmAction.isExecutable(parent.getParentRef(), null) == true) - { - rmActionService.executeRecordsManagementAction(parent.getParentRef(), dispAction); - if (logger.isDebugEnabled()) - { - logger.debug("Processed action: " + dispAction + "on" + parent); - } - } - else - { - logger.debug("The disposition action " + dispAction + " is not executable."); - } - } - return null; - } - } - return Boolean.TRUE; - } - }; - /** - * Now do the work, one action in each transaction - */ - trn.doInTransaction(processTranCB); - } - return null; - }; - - }, AuthenticationUtil.getSystemUserName()); - - logger.debug("Job Finished"); - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/DispositionLifecycleJobExecuter.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/DispositionLifecycleJobExecuter.java new file mode 100644 index 0000000000..160b86ba10 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/DispositionLifecycleJobExecuter.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2009-2011 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.module.org_alfresco_module_rm.job; + +import java.util.List; + +import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction; +import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * The Disposition Lifecycle Job Finds all disposition action nodes which are + * for "retain" or "cutOff" actions Where asOf > now OR + * dispositionEventsEligible = true; + * + * Runs the cut off or retain action for + * elligible records. + * + * @author mrogers + */ +public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecuter +{ + private static Log logger = LogFactory.getLog(DispositionLifecycleJobExecuter.class); + + private RecordsManagementActionService recordsManagementActionService; + + private NodeService nodeService; + + private SearchService searchService; + + public void setRecordsManagementActionService(RecordsManagementActionService recordsManagementActionService) + { + this.recordsManagementActionService = recordsManagementActionService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJobExecuter#execute() + */ + public void execute() + { + logger.debug("Job Starting"); + + StringBuilder sb = new StringBuilder(); + sb.append("+TYPE:\"rma:dispositionAction\" "); + sb.append("+(@rma\\:dispositionAction:(\"cutoff\" OR \"retain\"))"); + sb.append("+ISNULL:\"rma:dispositionActionCompletedAt\" "); + sb.append("+( "); + sb.append("@rma\\:dispositionEventsEligible:true "); + sb.append("OR @rma\\:dispositionAsOf:[MIN TO NOW] "); + sb.append(") "); + + String query = sb.toString(); + + ResultSet results = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, + SearchService.LANGUAGE_LUCENE, query); + List resultNodes = results.getNodeRefs(); + results.close(); + + + for (NodeRef node : resultNodes) + { + final NodeRef currentNode = node; + + RetryingTransactionCallback processTranCB = new RetryingTransactionCallback() + { + public Boolean execute() throws Throwable + { + final String dispAction = (String) nodeService.getProperty(currentNode, + RecordsManagementModel.PROP_DISPOSITION_ACTION); + + // Run "retain" and "cutoff" actions. + + if (dispAction != null) + { + if (dispAction.equalsIgnoreCase("cutoff") || + dispAction.equalsIgnoreCase("retain")) + { + ChildAssociationRef parent = nodeService.getPrimaryParent(currentNode); + if (parent.getTypeQName().equals(RecordsManagementModel.ASSOC_NEXT_DISPOSITION_ACTION)) + { + // Check that the action is executable + RecordsManagementAction rmAction = recordsManagementActionService.getDispositionAction(dispAction); + if (rmAction.isExecutable(parent.getParentRef(), null) == true) + { + recordsManagementActionService.executeRecordsManagementAction(parent.getParentRef(), dispAction); + if (logger.isDebugEnabled()) + { + logger.debug("Processed action: " + dispAction + "on" + parent); + } + } + else + { + logger.debug("The disposition action " + dispAction + " is not executable."); + } + } + return null; + } + } + return Boolean.TRUE; + } + }; + + /** + * Now do the work, one action in each transaction + */ + retryingTransactionHelper.doInTransaction(processTranCB); + } + + logger.debug("Job Finished"); + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/NotifyOfRecordsDueForReviewJob.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/NotifyOfRecordsDueForReviewJobExecuter.java similarity index 77% rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/NotifyOfRecordsDueForReviewJob.java rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/NotifyOfRecordsDueForReviewJobExecuter.java index 8b29d60e0b..43057e0bc8 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/NotifyOfRecordsDueForReviewJob.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/NotifyOfRecordsDueForReviewJobExecuter.java @@ -25,19 +25,14 @@ import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.notification.RecordsManagementNotificationHelper; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.transaction.TransactionService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.quartz.Job; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; /** * This job finds all Vital Records which are due for review, optionally @@ -45,20 +40,37 @@ import org.quartz.JobExecutionException; * * @author Neil McErlean */ -public class NotifyOfRecordsDueForReviewJob implements Job +public class NotifyOfRecordsDueForReviewJobExecuter extends RecordsManagementJobExecuter { - private static Log logger = LogFactory.getLog(NotifyOfRecordsDueForReviewJob.class); + private static Log logger = LogFactory.getLog(NotifyOfRecordsDueForReviewJobExecuter.class); + + private RecordsManagementNotificationHelper recordsManagementNotificationHelper; + + private NodeService nodeService; + + private SearchService searchService; + + public void setRecordsManagementNotificationHelper( + RecordsManagementNotificationHelper recordsManagementNotificationHelper) + { + this.recordsManagementNotificationHelper = recordsManagementNotificationHelper; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } /** - * @see org.quartz.Job#execute(org.quartz.JobExecutionContext) + * @see org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJobExecuter#execute() */ - public void execute(JobExecutionContext context) throws JobExecutionException - { - final RecordsManagementNotificationHelper notificationHelper = (RecordsManagementNotificationHelper)context.getJobDetail().getJobDataMap().get("recordsManagementNotificationHelper"); - final NodeService nodeService = (NodeService) context.getJobDetail().getJobDataMap().get("nodeService"); - final SearchService searchService = (SearchService) context.getJobDetail().getJobDataMap().get("searchService"); - final TransactionService trxService = (TransactionService) context.getJobDetail().getJobDataMap().get("transactionService"); - + public void execute() + { if (logger.isDebugEnabled()) { logger.debug("Job " + this.getClass().getSimpleName() + " starting."); @@ -91,8 +103,6 @@ public class NotifyOfRecordsDueForReviewJob implements Job //If we have something to do and a template to do it with if(resultNodes.size() != 0) { - RetryingTransactionHelper trn = trxService.getRetryingTransactionHelper(); - //Send the email message - but we must not retry since email is not transactional RetryingTransactionCallback txCallbackSendEmail = new RetryingTransactionCallback() { @@ -100,7 +110,7 @@ public class NotifyOfRecordsDueForReviewJob implements Job public Boolean execute() throws Throwable { // Send notification - notificationHelper.recordsDueForReviewEmailNotification(resultNodes); + recordsManagementNotificationHelper.recordsDueForReviewEmailNotification(resultNodes); return null; } @@ -122,10 +132,10 @@ public class NotifyOfRecordsDueForReviewJob implements Job /** * Now do the work, one action in each transaction */ - trn.setMaxRetries(0); // don't retry the send email - trn.doInTransaction(txCallbackSendEmail); - trn.setMaxRetries(10); - trn.doInTransaction(txUpdateNodesCallback); + retryingTransactionHelper.setMaxRetries(0); // don't retry the send email + retryingTransactionHelper.doInTransaction(txCallbackSendEmail); + retryingTransactionHelper.setMaxRetries(10); + retryingTransactionHelper.doInTransaction(txUpdateNodesCallback); } return null; } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/PublishUpdatesJob.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/PublishUpdatesJobExecuter.java similarity index 84% rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/PublishUpdatesJob.java rename to rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/PublishUpdatesJobExecuter.java index 0d998729e2..1d9d428438 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/PublishUpdatesJob.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/PublishUpdatesJobExecuter.java @@ -24,7 +24,6 @@ import java.util.List; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.module.org_alfresco_module_rm.job.publish.PublishExecutor; import org.alfresco.module.org_alfresco_module_rm.job.publish.PublishExecutorRegistry; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; @@ -37,47 +36,51 @@ import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.quartz.Job; -import org.quartz.JobDataMap; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; /** * Job to publish any pending updates on marked node references. * * @author Roy Wetherall */ -public class PublishUpdatesJob implements Job, RecordsManagementModel +public class PublishUpdatesJobExecuter extends RecordsManagementJobExecuter { /** Logger */ - private static Log logger = LogFactory.getLog(PublishUpdatesJob.class); + private static Log logger = LogFactory.getLog(PublishUpdatesJobExecuter.class); /** Node service */ private NodeService nodeService; /** Search service */ - private SearchService searchService; - - /** Retrying transaction helper */ - private RetryingTransactionHelper retryingTransactionHelper; + private SearchService searchService; /** Publish executor register */ - private PublishExecutorRegistry register; + private PublishExecutorRegistry publishExecutorRegistry; /** Behaviour filter */ private BehaviourFilter behaviourFilter; - /** Indicates whether the job bean has been initialised or not */ - private boolean initialised = false; - - /** - * @see org.quartz.Job#execute(org.quartz.JobExecutionContext) - */ - public void execute(JobExecutionContext context) throws JobExecutionException + public void setNodeService(NodeService nodeService) { - // Initialise the service references - initServices(context); - + this.nodeService = nodeService; + } + + public void setSearchService(SearchService searchService) + { + this.searchService = searchService; + } + + public void setPublishExecutorRegistry(PublishExecutorRegistry publishExecutorRegistry) + { + this.publishExecutorRegistry = publishExecutorRegistry; + } + + public void setBehaviourFilter(BehaviourFilter behaviourFilter) + { + this.behaviourFilter = behaviourFilter; + } + + public void execute() + { if (logger.isDebugEnabled() == true) { logger.debug("Job Starting"); @@ -156,25 +159,6 @@ public class PublishUpdatesJob implements Job, RecordsManagementModel return retryingTransactionHelper.doInTransaction(execution, true); } - /** - * Initialise service based on the job execution context - * @param context job execution context - */ - private void initServices(JobExecutionContext context) - { - if (initialised == false) - { - // Get references to the required services - JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); - nodeService = (NodeService)jobDataMap.get("nodeService"); - searchService = (SearchService)jobDataMap.get("searchService"); - retryingTransactionHelper = (RetryingTransactionHelper)jobDataMap.get("retryingTransactionHelper"); - register = (PublishExecutorRegistry)jobDataMap.get("publishExecutorRegistry"); - behaviourFilter = (BehaviourFilter)jobDataMap.get("behaviourFilter"); - initialised = true; - } - } - /** * Mark the node as publish in progress. This is often used as a marker to prevent any further updates * to a node. @@ -235,7 +219,7 @@ public class PublishUpdatesJob implements Job, RecordsManagementModel } // Get the publish executor - PublishExecutor executor = register.get(updateTo); + PublishExecutor executor = publishExecutorRegistry.get(updateTo); if (executor == null) { if (logger.isDebugEnabled() == true) diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java new file mode 100644 index 0000000000..1def909851 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2009-2011 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.job; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.lock.JobLockService; +import org.alfresco.repo.lock.LockAcquisitionException; +import org.alfresco.repo.lock.JobLockService.JobLockRefreshCallback; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +/** + * Base records management job implementation. + *

+ * Delegates job execution and ensures locking + * is enforced. + * + * @author Roy Wetherall + */ +public class RecordsManagementJob implements Job +{ + private static long DEFAULT_TIME = 2000L; + + private JobLockService jobLockService; + + private RecordsManagementJobExecuter jobExecuter; + + private String jobName; + + private QName getLockQName() + { + return QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, jobName); + } + + /** + * Attempts to get the lock. If the lock couldn't be taken, then null is returned. + * + * @return Returns the lock token or null + */ + private String getLock() + { + try + { + return jobLockService.getLock(getLockQName(), DEFAULT_TIME); + } + catch (LockAcquisitionException e) + { + return null; + } + } + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException + { + // get the job lock service + jobLockService = (JobLockService)context.getJobDetail().getJobDataMap().get("jobLockService"); + if (jobLockService == null) + { + throw new AlfrescoRuntimeException("Job lock service has not been specified."); + } + + // get the job executer + jobExecuter = (RecordsManagementJobExecuter)context.getJobDetail().getJobDataMap().get("jobExecuter"); + if (jobExecuter == null) + { + throw new AlfrescoRuntimeException("Job executer has not been specified."); + } + + // get the job name + jobName = (String)context.getJobDetail().getJobDataMap().get("jobName"); + if (jobName == null) + { + throw new AlfrescoRuntimeException("Job name has not been specified."); + } + + AuthenticationUtil.runAs(new RunAsWork() + { + public Void doWork() throws Exception + { + // try and get the lock + String lockToken = getLock(); + if (lockToken == null) + { + // exit + return null; + } + + // use a flag to keep track of the running job + final AtomicBoolean running = new AtomicBoolean(true); + jobLockService.refreshLock(lockToken, getLockQName(), DEFAULT_TIME, new JobLockRefreshCallback() + { + @Override + public boolean isActive() + { + return running.get(); + } + @Override + public void lockReleased() + { + running.set(false); + } + }); + + try + { + // do work + jobExecuter.execute(); + } + finally + { + // The lock will self-release if answer isActive in the negative + running.set(false); + } + + // return + return null; + } + }, AuthenticationUtil.getSystemUserName()); + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJobExecuter.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJobExecuter.java new file mode 100644 index 0000000000..871a65bb28 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJobExecuter.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2009-2011 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.job; + +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.repo.transaction.RetryingTransactionHelper; + +/** + * @author Roy Wetherall + */ +public abstract class RecordsManagementJobExecuter implements RecordsManagementModel +{ + protected RetryingTransactionHelper retryingTransactionHelper; + + public void setRetryingTransactionHelper(RetryingTransactionHelper retryingTransactionHelper) + { + this.retryingTransactionHelper = retryingTransactionHelper; + } + + public abstract void execute(); +}