mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
ALF-5028 - More tag scope updates and unit tests. Shortly after the system is started, check for un-applied tag scope updates, and apply them.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22997 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -26,44 +26,55 @@ import java.util.Map;
|
||||
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.jscript.ClasspathScriptLocation;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.action.ActionTrackingService;
|
||||
import org.alfresco.service.cmr.audit.AuditService;
|
||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
||||
import org.alfresco.service.cmr.repository.ScriptService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||
import org.alfresco.service.cmr.tagging.TagDetails;
|
||||
import org.alfresco.service.cmr.tagging.TagScope;
|
||||
import org.alfresco.service.cmr.tagging.TaggingService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.BaseAlfrescoSpringTest;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
/**
|
||||
* Tagging service implementation unit test
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
* @author Nick Burch
|
||||
*/
|
||||
public class TaggingServiceImplTest extends BaseAlfrescoSpringTest
|
||||
public class TaggingServiceImplTest extends TestCase
|
||||
{
|
||||
private static ConfigurableApplicationContext ctx =
|
||||
(ConfigurableApplicationContext)ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
/** Services */
|
||||
private TaggingService taggingService;
|
||||
private NodeService nodeService;
|
||||
private CopyService copyService;
|
||||
private CheckOutCheckInService checkOutCheckInService;
|
||||
private ScriptService scriptService;
|
||||
private PolicyComponent policyComponent;
|
||||
private AuditService auditService;
|
||||
private ActionService actionService;
|
||||
private ActionTrackingService actionTrackingService;
|
||||
private TransactionService transactionService;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
|
||||
private static StoreRef storeRef;
|
||||
private static NodeRef rootNode;
|
||||
@@ -84,32 +95,28 @@ public class TaggingServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
private static boolean init = false;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSetUpBeforeTransaction() throws Exception
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.onSetUpBeforeTransaction();
|
||||
|
||||
// Get services
|
||||
this.taggingService = (TaggingService)this.applicationContext.getBean("TaggingService");
|
||||
this.nodeService = (NodeService) this.applicationContext.getBean("NodeService");
|
||||
this.copyService = (CopyService) this.applicationContext.getBean("CopyService");
|
||||
this.contentService = (ContentService) this.applicationContext.getBean("ContentService");
|
||||
this.checkOutCheckInService = (CheckOutCheckInService) this.applicationContext.getBean("CheckoutCheckinService");
|
||||
this.authenticationService = (MutableAuthenticationService) this.applicationContext.getBean("authenticationService");
|
||||
this.actionService = (ActionService)this.applicationContext.getBean("ActionService");
|
||||
this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent");
|
||||
this.scriptService = (ScriptService)this.applicationContext.getBean("scriptService");
|
||||
this.policyComponent = (PolicyComponent)this.applicationContext.getBean("policyComponent");
|
||||
this.actionTrackingService = (ActionTrackingService)this.applicationContext.getBean("actionTrackingService");
|
||||
this.taggingService = (TaggingService)ctx.getBean("TaggingService");
|
||||
this.nodeService = (NodeService) ctx.getBean("NodeService");
|
||||
this.copyService = (CopyService) ctx.getBean("CopyService");
|
||||
this.checkOutCheckInService = (CheckOutCheckInService) ctx.getBean("CheckoutCheckinService");
|
||||
this.actionService = (ActionService)ctx.getBean("ActionService");
|
||||
this.transactionService = (TransactionService)ctx.getBean("transactionComponent");
|
||||
this.auditService = (AuditService)ctx.getBean("auditService");
|
||||
this.scriptService = (ScriptService)ctx.getBean("scriptService");
|
||||
this.actionTrackingService = (ActionTrackingService)ctx.getBean("actionTrackingService");
|
||||
this.authenticationComponent = (AuthenticationComponent)ctx.getBean("authenticationComponent");
|
||||
|
||||
if (init == false)
|
||||
{
|
||||
UserTransaction tx = this.transactionService.getUserTransaction();
|
||||
UserTransaction tx = this.transactionService.getNonPropagatingUserTransaction();
|
||||
tx.begin();
|
||||
|
||||
// Authenticate as the system user
|
||||
AuthenticationComponent authenticationComponent = (AuthenticationComponent) this.applicationContext
|
||||
.getBean("authenticationComponent");
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
// Create the store and get the root node
|
||||
@@ -133,14 +140,22 @@ public class TaggingServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
// Create the folders and documents to be tagged
|
||||
createTestDocumentsAndFolders();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
protected void tearDown() throws Exception {
|
||||
removeTestDocumentsAndFolders();
|
||||
}
|
||||
|
||||
private void createTestDocumentsAndFolders() throws Exception
|
||||
{
|
||||
UserTransaction tx = this.transactionService.getNonPropagatingUserTransaction();
|
||||
tx.begin();
|
||||
|
||||
// Authenticate as the system user
|
||||
AuthenticationComponent authenticationComponent = (AuthenticationComponent) this.applicationContext
|
||||
.getBean("authenticationComponent");
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
String guid = GUID.generate();
|
||||
@@ -183,9 +198,40 @@ public class TaggingServiceImplTest extends BaseAlfrescoSpringTest
|
||||
ContentModel.TYPE_CONTENT,
|
||||
props).getChildRef();
|
||||
|
||||
//tx.commit();
|
||||
setComplete();
|
||||
endTransaction();
|
||||
tx.commit();
|
||||
}
|
||||
private void removeTestDocumentsAndFolders() throws Exception
|
||||
{
|
||||
UserTransaction tx = this.transactionService.getNonPropagatingUserTransaction();
|
||||
tx.begin();
|
||||
|
||||
// Authenticate as the system user
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
// If anything is a tag scope, stop it being
|
||||
NodeRef[] nodes = new NodeRef[] { subDocument, subFolder, document, folder };
|
||||
for(NodeRef nodeRef : nodes)
|
||||
{
|
||||
if(taggingService.isTagScope(nodeRef))
|
||||
{
|
||||
taggingService.removeTagScope(nodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the sample nodes
|
||||
for(NodeRef nodeRef : nodes)
|
||||
{
|
||||
nodeService.deleteNode(nodeRef);
|
||||
}
|
||||
|
||||
// Tidy up the audit component, now all the nodes have gone
|
||||
auditService.clearAudit(
|
||||
TaggingServiceImpl.TAGGING_AUDIT_APPLICATION_NAME,
|
||||
0l, System.currentTimeMillis()+1
|
||||
);
|
||||
|
||||
// All done
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
public void testTagCRUD()
|
||||
@@ -203,10 +249,7 @@ public class TaggingServiceImplTest extends BaseAlfrescoSpringTest
|
||||
this.taggingService.createTag(TaggingServiceImplTest.storeRef, TAG_1);
|
||||
this.taggingService.createTag(TaggingServiceImplTest.storeRef, UPPER_TAG);
|
||||
|
||||
//setComplete();
|
||||
//endTransaction();
|
||||
tx.commit();
|
||||
|
||||
tx = this.transactionService.getUserTransaction();
|
||||
tx.begin();
|
||||
|
||||
@@ -905,7 +948,7 @@ public class TaggingServiceImplTest extends BaseAlfrescoSpringTest
|
||||
UserTransaction tx = this.transactionService.getUserTransaction();
|
||||
tx.begin();
|
||||
|
||||
Map model = new HashMap<String, Object>(0);
|
||||
Map<String, Object> model = new HashMap<String, Object>(0);
|
||||
model.put("folder", this.folder);
|
||||
model.put("subFolder", this.subFolder);
|
||||
model.put("document", this.document);
|
||||
@@ -915,6 +958,8 @@ public class TaggingServiceImplTest extends BaseAlfrescoSpringTest
|
||||
ScriptLocation location = new ClasspathScriptLocation("org/alfresco/repo/tagging/script/test_taggingService.js");
|
||||
this.scriptService.executeScript(location, model);
|
||||
|
||||
// Let the script run
|
||||
tx = waitForActionExecution(tx);
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
@@ -950,9 +995,8 @@ public class TaggingServiceImplTest extends BaseAlfrescoSpringTest
|
||||
tx = waitForActionExecution(tx);
|
||||
this.taggingService.addTag(this.folder, TAG_1);
|
||||
tx = waitForActionExecution(tx);
|
||||
tx.commit();
|
||||
|
||||
Map model = new HashMap<String, Object>(0);
|
||||
Map<String, Object> model = new HashMap<String, Object>(0);
|
||||
model.put("folder", this.folder);
|
||||
model.put("subFolder", this.subFolder);
|
||||
model.put("document", this.document);
|
||||
@@ -962,9 +1006,197 @@ public class TaggingServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
ScriptLocation location = new ClasspathScriptLocation("org/alfresco/repo/tagging/script/test_taggingService.js");
|
||||
this.scriptService.executeScript(location, model);
|
||||
|
||||
// Let the script run
|
||||
tx = waitForActionExecution(tx);
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
private static Object mutex = new Object();
|
||||
/**
|
||||
* Test that the scheduled task will do the right thing
|
||||
* when it runs.
|
||||
*/
|
||||
public void testOnStartupJob() throws Exception
|
||||
{
|
||||
UserTransaction tx = this.transactionService.getUserTransaction();
|
||||
tx.begin();
|
||||
|
||||
// Nothing is pending to start with
|
||||
UpdateTagScopesActionExecuter updateTagsAction = (UpdateTagScopesActionExecuter)
|
||||
ctx.getBean("update-tagscope");
|
||||
assertEquals(0, updateTagsAction.searchForTagScopesPendingUpdates().size());
|
||||
|
||||
|
||||
// Take the tag scope lock, so that no real updates will happen
|
||||
String lockF = updateTagsAction.lockTagScope(this.folder);
|
||||
String lockSF = updateTagsAction.lockTagScope(this.subFolder);
|
||||
|
||||
// Do some tagging
|
||||
this.taggingService.addTagScope(this.folder);
|
||||
this.taggingService.addTagScope(this.subFolder);
|
||||
|
||||
this.taggingService.addTag(this.subDocument, TAG_1);
|
||||
this.taggingService.addTag(this.subDocument, TAG_2);
|
||||
this.taggingService.addTag(this.subFolder, TAG_1);
|
||||
this.taggingService.addTag(this.document, TAG_1);
|
||||
this.taggingService.addTag(this.folder, TAG_1);
|
||||
this.taggingService.addTag(this.folder, TAG_3);
|
||||
tx = waitForActionExecution(tx);
|
||||
|
||||
|
||||
// Tag scope updates shouldn't have happened yet,
|
||||
// as the scopes are locked
|
||||
TagScope ts1 = this.taggingService.findTagScope(this.folder);
|
||||
TagScope ts2 = this.taggingService.findTagScope(this.subFolder);
|
||||
assertEquals(
|
||||
"Wrong tags on folder tagscope: " + ts1.getTags(),
|
||||
0, ts1.getTags().size()
|
||||
);
|
||||
assertEquals(
|
||||
"Wrong tags on folder tagscope: " + ts1.getTags(),
|
||||
0, ts2.getTags().size()
|
||||
);
|
||||
|
||||
|
||||
// Check the pending list now
|
||||
assertEquals(2, updateTagsAction.searchForTagScopesPendingUpdates().size());
|
||||
List<NodeRef> pendingScopes = updateTagsAction.searchForTagScopesPendingUpdates();
|
||||
assertTrue("Not found in " + pendingScopes, pendingScopes.contains(this.folder));
|
||||
assertTrue("Not found in " + pendingScopes, pendingScopes.contains(this.subFolder));
|
||||
|
||||
|
||||
// Give back our locks, so we can proceed
|
||||
updateTagsAction.unlockTagScope(this.folder, lockF);
|
||||
updateTagsAction.unlockTagScope(this.subFolder, lockSF);
|
||||
|
||||
|
||||
// Fire off the quartz bean
|
||||
UpdateTagScopesQuartzJob job = new UpdateTagScopesQuartzJob();
|
||||
job.execute(actionService, updateTagsAction);
|
||||
|
||||
|
||||
// Now check again
|
||||
assertEquals(0, updateTagsAction.searchForTagScopesPendingUpdates().size());
|
||||
|
||||
ts1 = this.taggingService.findTagScope(this.folder);
|
||||
ts2 = this.taggingService.findTagScope(this.subFolder);
|
||||
assertEquals(
|
||||
"Wrong tags on folder tagscope: " + ts1.getTags(),
|
||||
3, ts1.getTags().size()
|
||||
);
|
||||
assertEquals(
|
||||
"Wrong tags on folder tagscope: " + ts1.getTags(),
|
||||
2, ts2.getTags().size()
|
||||
);
|
||||
|
||||
assertEquals(4, ts1.getTag(TAG_1).getCount());
|
||||
assertEquals(1, ts1.getTag(TAG_2).getCount());
|
||||
assertEquals(1, ts1.getTag(TAG_3.toLowerCase()).getCount());
|
||||
|
||||
assertEquals(2, ts2.getTag(TAG_1).getCount());
|
||||
assertEquals(1, ts2.getTag(TAG_2).getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that when multiple threads do tag updates, the right
|
||||
* thing still happens
|
||||
*/
|
||||
public void DISABLEDtestMultiThreaded() throws Exception
|
||||
{
|
||||
UserTransaction tx = this.transactionService.getNonPropagatingUserTransaction();
|
||||
tx.begin();
|
||||
this.taggingService.addTagScope(this.folder);
|
||||
this.taggingService.addTagScope(this.subFolder);
|
||||
tx.commit();
|
||||
|
||||
// Prepare a bunch of threads to do tagging
|
||||
final List<Thread> threads = new ArrayList<Thread>();
|
||||
String[] tags = new String[] { TAG_1, TAG_2, TAG_3, TAG_4, TAG_5 };
|
||||
for(String tmpTag : tags)
|
||||
{
|
||||
final String tag = tmpTag;
|
||||
Thread t = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Let everything catch up
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
} catch(InterruptedException e) {}
|
||||
System.out.println(Thread.currentThread() + " - About to start tagging");
|
||||
|
||||
// Do the updates
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||
new RetryingTransactionCallback<Void>() {
|
||||
public Void execute() throws Throwable {
|
||||
taggingService.addTag(folder, tag);
|
||||
taggingService.addTag(subFolder, tag);
|
||||
taggingService.addTag(subDocument, tag);
|
||||
System.out.println(Thread.currentThread() + " - Tagging");
|
||||
return null;
|
||||
}
|
||||
}, false, true
|
||||
);
|
||||
System.out.println(Thread.currentThread() + " - Done tagging");
|
||||
}
|
||||
});
|
||||
threads.add(t);
|
||||
t.start();
|
||||
}
|
||||
|
||||
|
||||
// Release the threads
|
||||
Thread.sleep(50);
|
||||
for(Thread t : threads) {
|
||||
t.interrupt();
|
||||
}
|
||||
Thread.sleep(100);
|
||||
System.out.println("Done waiting, proceeding with multi-threaded test");
|
||||
|
||||
|
||||
// Wait for all the threads to finish working
|
||||
try {
|
||||
// Wait for a maximum of 10 seconds
|
||||
for(int i=0; i<1000; i++)
|
||||
{
|
||||
if(actionTrackingService.getAllExecutingActions().size() > 0)
|
||||
{
|
||||
Thread.sleep(10);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(InterruptedException e) {}
|
||||
|
||||
|
||||
// Now check that things ended up as planned
|
||||
tx = this.transactionService.getUserTransaction();
|
||||
tx.begin();
|
||||
|
||||
TagScope ts1 = this.taggingService.findTagScope(this.folder);
|
||||
TagScope ts2 = this.taggingService.findTagScope(this.subFolder);
|
||||
assertEquals(
|
||||
"Wrong tags on folder tagscope: " + ts1.getTags(),
|
||||
5, ts1.getTags().size()
|
||||
);
|
||||
assertEquals(
|
||||
"Wrong tags on folder tagscope: " + ts1.getTags(),
|
||||
5, ts2.getTags().size()
|
||||
);
|
||||
|
||||
// Each tag should crop up 3 times on the folder
|
||||
// and twice for the subfolder
|
||||
for(String tag : tags)
|
||||
{
|
||||
assertEquals(3, ts1.getTag(tag.toLowerCase()).getCount());
|
||||
assertEquals(2, ts2.getTag(tag.toLowerCase()).getCount());
|
||||
}
|
||||
|
||||
// All done
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
|
||||
private UserTransaction waitForActionExecution(UserTransaction txn)
|
||||
throws Exception
|
||||
|
@@ -22,8 +22,10 @@ import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.ParameterDefinitionImpl;
|
||||
@@ -87,7 +89,16 @@ public class UpdateTagScopesActionExecuter extends ActionExecuterAbstractBase
|
||||
|
||||
/** What's the largest number of updates we should claim for a tag scope in one transaction? */
|
||||
private static final int tagUpdateBatchSize = 100;
|
||||
|
||||
|
||||
// For searching
|
||||
private static final String noderefPath =
|
||||
TaggingServiceImpl.TAGGING_AUDIT_ROOT_PATH + "/" +
|
||||
TaggingServiceImpl.TAGGING_AUDIT_KEY_NODEREF + "/value";
|
||||
private static final String tagsPath =
|
||||
TaggingServiceImpl.TAGGING_AUDIT_ROOT_PATH + "/" +
|
||||
TaggingServiceImpl.TAGGING_AUDIT_KEY_TAGS + "/value";
|
||||
|
||||
|
||||
/**
|
||||
* Set the node service
|
||||
*
|
||||
@@ -174,10 +185,7 @@ public class UpdateTagScopesActionExecuter extends ActionExecuterAbstractBase
|
||||
// to worry as they'll handle the update for us!
|
||||
try
|
||||
{
|
||||
QName lockQName = QName.createQName("TagScope_" + tagScope.toString());
|
||||
String lock = jobLockService.getLock(
|
||||
lockQName, 2500, 0, 0
|
||||
);
|
||||
String lock = lockTagScope(tagScope);
|
||||
|
||||
// If we got here, we're the only thread currently
|
||||
// processing this tag scope
|
||||
@@ -236,7 +244,7 @@ public class UpdateTagScopesActionExecuter extends ActionExecuterAbstractBase
|
||||
);
|
||||
|
||||
// We're done with this tag scope
|
||||
jobLockService.releaseLock(lock, lockQName);
|
||||
unlockTagScope(tagScope, lock);
|
||||
} catch(LockAcquisitionException e) {}
|
||||
|
||||
// Now proceed to the next tag scope
|
||||
@@ -257,19 +265,13 @@ public class UpdateTagScopesActionExecuter extends ActionExecuterAbstractBase
|
||||
*/
|
||||
private List<Long> searchForUpdates(final NodeRef tagScopeNode, final Map<String,Integer> updates)
|
||||
{
|
||||
final String noderefPath =
|
||||
TaggingServiceImpl.TAGGING_AUDIT_ROOT_PATH + "/" +
|
||||
TaggingServiceImpl.TAGGING_AUDIT_KEY_NODEREF + "/value";
|
||||
final String tagsPath =
|
||||
TaggingServiceImpl.TAGGING_AUDIT_ROOT_PATH + "/" +
|
||||
TaggingServiceImpl.TAGGING_AUDIT_KEY_TAGS + "/value";
|
||||
|
||||
// Build the query
|
||||
AuditQueryParameters params = new AuditQueryParameters();
|
||||
final AuditQueryParameters params = new AuditQueryParameters();
|
||||
params.setApplicationName(TaggingServiceImpl.TAGGING_AUDIT_APPLICATION_NAME);
|
||||
params.addSearchKey(noderefPath, tagScopeNode.toString());
|
||||
|
||||
// Execute it
|
||||
// Execute the query, in a new transaction
|
||||
// (Avoid contention issues with repeated runs / updates)
|
||||
final List<Long> ids = new ArrayList<Long>();
|
||||
auditService.auditQuery(new AuditQueryCallback() {
|
||||
@Override
|
||||
@@ -412,6 +414,92 @@ public class UpdateTagScopesActionExecuter extends ActionExecuterAbstractBase
|
||||
contentWriter.putContent(tagContent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks several batches of updates in the Audit event log,
|
||||
* and returns the list of Tag Scope Node References found there.
|
||||
* You should generally call this action to process the list of
|
||||
* tag nodes before re-calling this method.
|
||||
* You may need to call this method several times if lots of work
|
||||
* is backed up, when an empty list is returned then you know
|
||||
* that all work is handled.
|
||||
*/
|
||||
public List<NodeRef> searchForTagScopesPendingUpdates()
|
||||
{
|
||||
final Set<String> tagNodesStrs = new HashSet<String>();
|
||||
|
||||
// We want all entries for tagging
|
||||
final AuditQueryParameters params = new AuditQueryParameters();
|
||||
params.setApplicationName(TaggingServiceImpl.TAGGING_AUDIT_APPLICATION_NAME);
|
||||
|
||||
// Execute the query, in a new transaction
|
||||
// (Avoid contention issues with repeated runs / updates)
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||
new RetryingTransactionCallback<Void>() {
|
||||
public Void execute() throws Throwable {
|
||||
auditService.auditQuery(new AuditQueryCallback() {
|
||||
@Override
|
||||
public boolean valuesRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleAuditEntryError(Long entryId, String errorMsg,
|
||||
Throwable error) {
|
||||
logger.warn("Error fetching tagging update entry - " + errorMsg, error);
|
||||
// Keep trying
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleAuditEntry(Long entryId, String applicationName,
|
||||
String user, long time, Map<String, Serializable> values) {
|
||||
// Save the NodeRef
|
||||
if(values.containsKey(noderefPath))
|
||||
{
|
||||
String nodeRefStr = (String)values.get(noderefPath);
|
||||
if(! tagNodesStrs.contains(nodeRefStr))
|
||||
tagNodesStrs.add(nodeRefStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Unexpected Tag Scope update entry of " + values);
|
||||
}
|
||||
|
||||
// Next entry please!
|
||||
return true;
|
||||
}
|
||||
}, params, 4*tagUpdateBatchSize);
|
||||
return null;
|
||||
}
|
||||
}, false, true
|
||||
);
|
||||
|
||||
// Turn it into NodeRefs
|
||||
List<NodeRef> tagNodes = new ArrayList<NodeRef>();
|
||||
for(String nodeRefStr : tagNodesStrs)
|
||||
{
|
||||
tagNodes.add( new NodeRef(nodeRefStr) );
|
||||
}
|
||||
return tagNodes;
|
||||
}
|
||||
|
||||
private QName tagScopeToLockQName(NodeRef tagScope)
|
||||
{
|
||||
QName lockQName = QName.createQName("TagScope_" + tagScope.toString());
|
||||
return lockQName;
|
||||
}
|
||||
protected String lockTagScope(NodeRef tagScope)
|
||||
{
|
||||
String lock = jobLockService.getLock(
|
||||
tagScopeToLockQName(tagScope), 2500, 0, 0
|
||||
);
|
||||
return lock;
|
||||
}
|
||||
protected void unlockTagScope(NodeRef tagScope, String lockToken)
|
||||
{
|
||||
jobLockService.releaseLock(lockToken, tagScopeToLockQName(tagScope));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List)
|
||||
@@ -421,5 +509,4 @@ public class UpdateTagScopesActionExecuter extends ActionExecuterAbstractBase
|
||||
{
|
||||
paramList.add(new ParameterDefinitionImpl(PARAM_TAG_SCOPES, DataTypeDefinition.ANY, true, getParamDisplayLabel(PARAM_TAG_SCOPES)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.tagging;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Finds Tag Scope updates that haven't been applied, and triggers
|
||||
* then to be run.
|
||||
* Works with the {@link UpdateTagScopesActionExecuter}, and is typically
|
||||
* run after server restart.
|
||||
* Also refer to scheduled-jobs-context.xml for more information
|
||||
*/
|
||||
public class UpdateTagScopesQuartzJob implements Job {
|
||||
private static Log logger = LogFactory.getLog(UpdateTagScopesQuartzJob.class);
|
||||
|
||||
public UpdateTagScopesQuartzJob() {}
|
||||
|
||||
/**
|
||||
* Finds the tag scopes to be updated, and has them worked on
|
||||
*/
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException
|
||||
{
|
||||
JobDataMap jobData = context.getJobDetail().getJobDataMap();
|
||||
|
||||
// Extract out our beans
|
||||
Object actionServiceO = jobData.get("actionService");
|
||||
if(actionServiceO == null || !(actionServiceO instanceof ActionService))
|
||||
{
|
||||
throw new AlfrescoRuntimeException(
|
||||
"UpdateTagScopesQuartzJob data must contain a valid 'actionService' reference");
|
||||
}
|
||||
|
||||
Object updateTagsActionO = jobData.get("updateTagsAction");
|
||||
if(updateTagsActionO == null || !(updateTagsActionO instanceof UpdateTagScopesActionExecuter))
|
||||
{
|
||||
throw new AlfrescoRuntimeException(
|
||||
"UpdateTagScopesQuartzJob data must contain a valid 'updateTagsAction' reference");
|
||||
}
|
||||
|
||||
ActionService actionService = (ActionService)actionServiceO;
|
||||
UpdateTagScopesActionExecuter updateTagsAction = (UpdateTagScopesActionExecuter)updateTagsActionO;
|
||||
|
||||
// Do the work
|
||||
execute(actionService, updateTagsAction);
|
||||
}
|
||||
|
||||
protected void execute(final ActionService actionService, final UpdateTagScopesActionExecuter updateTagsAction)
|
||||
{
|
||||
// Process
|
||||
final ArrayList<NodeRef> tagNodes = new ArrayList<NodeRef>();
|
||||
while(true)
|
||||
{
|
||||
// Fetch the list of changes
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>()
|
||||
{
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
tagNodes.clear();
|
||||
tagNodes.addAll(
|
||||
updateTagsAction.searchForTagScopesPendingUpdates()
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName()
|
||||
);
|
||||
|
||||
// Log what we found
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Checked for tag scopes with pending tag updates, found " + tagNodes);
|
||||
}
|
||||
|
||||
if(tagNodes.size() == 0)
|
||||
break;
|
||||
|
||||
// Have the action run for these tag scope nodes
|
||||
// Needs to run synchronously
|
||||
Action action = actionService.createAction(UpdateTagScopesActionExecuter.NAME);
|
||||
action.setParameterValue(UpdateTagScopesActionExecuter.PARAM_TAG_SCOPES, (Serializable)tagNodes);
|
||||
actionService.executeAction(action, null, false, false);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user