Merged V3.0 to HEAD

12140: Merged V2.2 to V3.0
    11732: Fixed ETWOTWO-804: Node and Transaction Cleanup Job
    11747: Missed config for Node and Txn purging
    11826: WCM - fix ETWOTWO-817
    11951: Fixed ETWOTWO-901: NodeService cleanup must be pluggable
    11961: Merged V2.1 to V2.2
      11561: ETWOONE-224: when renaming duplicates during copy association names where not renamed 
      11583: (ALREADY PRESENT) Updated NTLM config example in web.xml - adding missing servlet mappings
      11584: Fix for ETWOONE-209 - JavaScript People.createGroup() API now correctly checks for actual group name when testing for existence
      11585: Fix for ETWOONE-214 - View In CIFS link now works even when users des not have view permissions on the parent folder
      11612: Fix for ETWOONE-91: the description textarea in the modify space properties web form eats one leading newline each time it is submitted
      11613: Fix 2.1 build and adjust implementation of ETWOONE-224 fix
      11621: Fix for ETWOONE-343
      11669: Improved debug from index tracking when exceptions occur
  12141: Avoid annoying Spring WARN messages for ClientAbortException
  12143: File that should have been deleted in CHK-5460 (rev 12140)
  12177: Fix failing FS Deployment Tests since introduction of transaction check advice.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@12507 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jan Vonka
2008-12-19 10:21:51 +00:00
parent 16861e9117
commit 21bb599e20
24 changed files with 1086 additions and 253 deletions

View File

@@ -0,0 +1,147 @@
package org.alfresco.repo.node.cleanup;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import org.alfresco.error.StackTraceUtil;
import org.alfresco.repo.node.db.DbNodeServiceImpl;
import org.alfresco.repo.node.db.NodeDaoService;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Base class for Node cleaners. This class ensures calls through
* after having created a read-write transaction that is authenticated
* as system.
*
* @author Derek Hulley
* @since 2.2 SP2
*/
public abstract class AbstractNodeCleanupWorker implements NodeCleanupWorker
{
protected final Log logger;
private final ReentrantLock cleanupLock;
private NodeCleanupRegistry registry;
protected TransactionService transactionService;
protected DbNodeServiceImpl dbNodeService;
protected NodeDaoService nodeDaoService;
public AbstractNodeCleanupWorker()
{
logger = LogFactory.getLog(this.getClass());
cleanupLock = new ReentrantLock();
}
public void setRegistry(NodeCleanupRegistry registry)
{
this.registry = registry;
}
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
public void setDbNodeService(DbNodeServiceImpl dbNodeService)
{
this.dbNodeService = dbNodeService;
}
public void setNodeDaoService(NodeDaoService nodeDaoService)
{
this.nodeDaoService = nodeDaoService;
}
public void register()
{
PropertyCheck.mandatory(this, "registry", registry);
PropertyCheck.mandatory(this, "transactionService", transactionService);
PropertyCheck.mandatory(this, "dbNodeService", dbNodeService);
PropertyCheck.mandatory(this, "nodeDaoService", nodeDaoService);
registry.register(this);
}
/**
* Calls {@link #doCleanInternal()} in a System-user authenticated read-write transaction.
* This method is non-blocking but passes all second and subsequent concurrent invocations
* straight through.
*/
public List<String> doClean()
{
/** Prevent multiple executions of the implementation method */
boolean locked = cleanupLock.tryLock();
if (locked)
{
try
{
return doCleanWithTxn();
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
StringBuilder sb = new StringBuilder(1024);
StackTraceUtil.buildStackTrace(
"Node cleanup failed: " +
" Worker: " + this.getClass().getName() + "\n" +
" Error: ",
e.getStackTrace(),
sb,
Integer.MAX_VALUE);
logger.debug(sb.toString());
}
StringBuilder sb = new StringBuilder(1024);
StackTraceUtil.buildStackTrace(
"Node cleanup failed: " +
" Worker: " + this.getClass().getName() + "\n" +
" Error: ",
e.getStackTrace(),
sb,
20);
return Collections.singletonList(sb.toString());
}
finally
{
cleanupLock.unlock();
}
}
else
{
return Collections.emptyList();
}
}
private List<String> doCleanWithTxn()
{
final RetryingTransactionCallback<List<String>> doCleanCallback = new RetryingTransactionCallback<List<String>>()
{
public List<String> execute() throws Throwable
{
return doCleanInternal();
}
};
final RunAsWork<List<String>> doCleanRunAs = new RunAsWork<List<String>>()
{
public List<String> doWork() throws Exception
{
return transactionService.getRetryingTransactionHelper().doInTransaction(doCleanCallback, false, true);
}
};
return AuthenticationUtil.runAs(doCleanRunAs, AuthenticationUtil.getSystemUserName());
}
/**
* Do the actual cleanup. Any errors are handled by this base class.
*
* @return Returns the cleanup messages.
*/
protected abstract List<String> doCleanInternal() throws Throwable;
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2005-2007 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.node.cleanup;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
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;
/**
* Scheduled job to call a {@link NodeCleanupWorker}.
* <p>
* Job data is: <b>nodeCleanupWorker</b>
*
* @author Derek Hulley
* @since 2.2SP2
*/
public class NodeCleanupJob implements Job
{
private static Log logger = LogFactory.getLog(NodeCleanupJob.class);
public void execute(JobExecutionContext context) throws JobExecutionException
{
JobDataMap jobData = context.getJobDetail().getJobDataMap();
// extract the content Cleanup to use
Object nodeCleanupWorkerObj = jobData.get("nodeCleanupWorker");
if (nodeCleanupWorkerObj == null || !(nodeCleanupWorkerObj instanceof NodeCleanupWorker))
{
throw new AlfrescoRuntimeException(
"NodeCleanupJob data must contain valid 'nodeCleanupWorker' reference");
}
NodeCleanupWorker nodeCleanupWorker = (NodeCleanupWorker) nodeCleanupWorkerObj;
List<String> cleanupLog = nodeCleanupWorker.doClean();
// Done
if (logger.isDebugEnabled())
{
logger.debug("Node cleanup log:");
for (String log : cleanupLog)
{
logger.debug(log);
}
}
}
}

View File

@@ -0,0 +1,65 @@
package org.alfresco.repo.node.cleanup;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.error.StackTraceUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A {@link NodeCleanupWorker worker} that aggregates any number of
* {@link #register(NodeCleanupWorker) registered} workers.
*
* @author Derek Hulley
* @since 2.2 SP2
*/
public class NodeCleanupRegistry implements NodeCleanupWorker
{
private static Log logger = LogFactory.getLog(NodeCleanupRegistry.class);
private List<NodeCleanupWorker> cleanupWorkers;
public NodeCleanupRegistry()
{
cleanupWorkers = new ArrayList<NodeCleanupWorker>(5);
}
public void register(NodeCleanupWorker cleanupWorker)
{
cleanupWorkers.add(cleanupWorker);
}
/**
* Calls all registered cleaners in order, without transactions or authentication.
* The return messages are aggregated.
*/
public List<String> doClean()
{
List<String> results = new ArrayList<String>(100);
for (NodeCleanupWorker cleanupWorker : cleanupWorkers)
{
try
{
results.addAll(cleanupWorker.doClean());
}
catch (Throwable e)
{
// This failed. The cleaner should be handling this, but we can't guarantee it.
logger.error(
"NodeCleanupWork doesn't handle all exception conditions: " +
cleanupWorker.getClass().getName());
StringBuilder sb = new StringBuilder(1024);
StackTraceUtil.buildStackTrace(
"Node cleanup failed: " +
" Worker: " + cleanupWorker.getClass().getName() + "\n" +
" Error: ",
e.getStackTrace(),
sb,
20);
results.add(sb.toString());
}
}
return results;
}
}

View File

@@ -0,0 +1,20 @@
package org.alfresco.repo.node.cleanup;
import java.util.List;
/**
* Interface for classes that implement a snippet of node cleanup.
*
* @author Derek Hulley
* @since 2.2 SP2
*/
public interface NodeCleanupWorker
{
/**
* Perform some work to clean up data. All errors must be handled and converted
* to error messages.
*
* @return Returns a list of informational messages.
*/
List<String> doClean();
}