mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Merged V2.2 to HEAD
7498: Deployment callback and event changes 7499: Build fix 7505: Fixed deployment script issue in IE 7525: Added sample job that will clean deployment attempts older than 180 days (by default) 7526: Typo compilation fix git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8383 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.avm;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.model.WCMAppModel;
|
||||
import org.alfresco.repo.importer.ImporterBootstrap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
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.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Bean that is responsible for locating expired content and routing
|
||||
* it for review to the most relevant user.
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public class AVMDeploymentAttemptCleaner
|
||||
{
|
||||
// defaults in case these properties are not configured in Spring
|
||||
protected String adminUserName = "admin";
|
||||
protected long maxAge = 180L;
|
||||
|
||||
protected NodeService nodeService;
|
||||
protected TransactionService transactionService;
|
||||
protected SearchService searchService;
|
||||
protected ImporterBootstrap importerBootstrap;
|
||||
|
||||
private static Log logger = LogFactory.getLog(AVMDeploymentAttemptCleaner.class);
|
||||
|
||||
public AVMDeploymentAttemptCleaner()
|
||||
{
|
||||
}
|
||||
|
||||
public void setAdminUserName(String adminUserName)
|
||||
{
|
||||
this.adminUserName = adminUserName;
|
||||
}
|
||||
|
||||
public void setMaxAge(long maxAge)
|
||||
{
|
||||
this.maxAge = new Long(maxAge);
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
public void setImporterBootstrap(ImporterBootstrap importerBootstrap)
|
||||
{
|
||||
this.importerBootstrap = importerBootstrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the expired content processor.
|
||||
* The work is performed within a transaction running as the system user.
|
||||
*/
|
||||
public void execute()
|
||||
{
|
||||
// setup a wrapper object to run the processor within a transaction.
|
||||
AuthenticationUtil.RunAsWork<String> authorisedWork = new AuthenticationUtil.RunAsWork<String>()
|
||||
{
|
||||
public String doWork() throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<String> expiredContentWork = new RetryingTransactionCallback<String>()
|
||||
{
|
||||
public String execute() throws Exception
|
||||
{
|
||||
cleanAttempts();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
return transactionService.getRetryingTransactionHelper().doInTransaction(expiredContentWork);
|
||||
}
|
||||
};
|
||||
|
||||
// perform the work as the system user
|
||||
AuthenticationUtil.runAs(authorisedWork, this.adminUserName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point.
|
||||
*/
|
||||
private void cleanAttempts()
|
||||
{
|
||||
// calculate the date 'maxAge' days before today
|
||||
long daysInMs = 1000L*60L*60L*24L*this.maxAge;
|
||||
Date toDate = new Date(new Date().getTime() - daysInMs);
|
||||
|
||||
// build the query to find deployment attempts older than this.maxAge
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(toDate);
|
||||
StringBuilder query = new StringBuilder("@");
|
||||
query.append(NamespaceService.WCMAPP_MODEL_PREFIX);
|
||||
query.append("\\:");
|
||||
query.append(WCMAppModel.PROP_DEPLOYATTEMPTTIME.getLocalName());
|
||||
query.append(":[0001\\-01\\-01T00:00:00 TO ");
|
||||
query.append(cal.get(Calendar.YEAR));
|
||||
query.append("\\-");
|
||||
query.append((cal.get(Calendar.MONTH)+1));
|
||||
query.append("\\-");
|
||||
query.append(cal.get(Calendar.DAY_OF_MONTH));
|
||||
query.append("T00:00:00]");
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Finding old deploymentattempt nodes using query: " + query.toString());
|
||||
|
||||
// do the query
|
||||
ResultSet results = null;
|
||||
try
|
||||
{
|
||||
// execute the query
|
||||
results = searchService.query(this.importerBootstrap.getStoreRef(),
|
||||
SearchService.LANGUAGE_LUCENE, query.toString());
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Deleting " + results.length() + " old deployment attempts");
|
||||
|
||||
// iterate through the attempt nodes and delete them
|
||||
for (NodeRef attempt : results.getNodeRefs())
|
||||
{
|
||||
this.nodeService.deleteNode(attempt);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Deleted deployment attempt: " + attempt);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (results != null)
|
||||
{
|
||||
results.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.avm;
|
||||
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
/**
|
||||
* Job to periodically execute the deployment attempt cleaner.
|
||||
*
|
||||
* <p>
|
||||
* The following parameters are required:
|
||||
* <ul>
|
||||
* <li><b>deploymentAttemptCleaner</b>: The deployment attempt cleaner instance</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public class AVMDeploymentAttemptCleanerJob implements Job
|
||||
{
|
||||
/**
|
||||
* Searches for old deployment attempts and removes them.
|
||||
*
|
||||
* @param context The job context
|
||||
*/
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException
|
||||
{
|
||||
// get the expired content processor bean from the job context
|
||||
AVMDeploymentAttemptCleaner cleaner =
|
||||
(AVMDeploymentAttemptCleaner)context.getJobDetail().getJobDataMap().get("deploymentAttemptCleaner");
|
||||
if (cleaner == null)
|
||||
{
|
||||
throw new JobExecutionException("Missing job data: deploymentAttemptCleaner");
|
||||
}
|
||||
|
||||
// execute the cleaner to do the actual work
|
||||
cleaner.execute();
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
package org.alfresco.repo.avm;
|
||||
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.repo.avm.AVMDeploymentAttemptCleaner;
|
||||
import org.alfresco.repo.importer.ImporterBootstrap;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.avm.AVMDeploymentAttemptCleaner
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public class AVMDeploymentAttemptCleanerTest extends TestCase
|
||||
{
|
||||
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
private AVMDeploymentAttemptCleaner cleaner;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean("ServiceRegistry");
|
||||
ImporterBootstrap importerBootstrap = (ImporterBootstrap)ctx.getBean("spacesBootstrap");
|
||||
NodeService nodeService = serviceRegistry.getNodeService();
|
||||
SearchService searchService = serviceRegistry.getSearchService();
|
||||
TransactionService transactionService = serviceRegistry.getTransactionService();
|
||||
this.cleaner = new AVMDeploymentAttemptCleaner();
|
||||
this.cleaner.setNodeService(nodeService);
|
||||
this.cleaner.setSearchService(searchService);
|
||||
this.cleaner.setTransactionService(transactionService);
|
||||
this.cleaner.setImporterBootstrap(importerBootstrap);
|
||||
// this.cleaner.setMaxAge(30);
|
||||
}
|
||||
|
||||
public void testProcessor() throws Exception
|
||||
{
|
||||
this.cleaner.execute();
|
||||
}
|
||||
}
|
@@ -28,7 +28,6 @@ package org.alfresco.repo.avm.actions;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@@ -80,6 +79,7 @@ public class AVMDeployWebsiteAction extends ActionExecuterAbstractBase
|
||||
private String defaultRemoteUsername = "admin";
|
||||
private String defaultRemotePassword = "admin";
|
||||
private String defaultTargetName = "default";
|
||||
private List<DeploymentCallback> configuredCallbacks;
|
||||
private DeploymentService deployService;
|
||||
private ContentService contentService;
|
||||
private NodeService nodeService;
|
||||
@@ -176,6 +176,11 @@ public class AVMDeployWebsiteAction extends ActionExecuterAbstractBase
|
||||
{
|
||||
this.defaultTargetName = defaultTargetName;
|
||||
}
|
||||
|
||||
public void setCallbacks(List<DeploymentCallback> callbacks)
|
||||
{
|
||||
this.configuredCallbacks = callbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param service The NodeService instance
|
||||
@@ -335,6 +340,20 @@ public class AVMDeployWebsiteAction extends ActionExecuterAbstractBase
|
||||
patterns.add(excludes);
|
||||
regexMatcher.setPatterns(patterns);
|
||||
}
|
||||
|
||||
// create a list of all the callback objects
|
||||
List<DeploymentCallback> callbacks = new ArrayList<DeploymentCallback>();
|
||||
if (callback != null)
|
||||
{
|
||||
// if present add the callback passed as a parameter (usually for UI purposes)
|
||||
callbacks.add(callback);
|
||||
}
|
||||
if (this.configuredCallbacks != null && this.configuredCallbacks.size() > 0)
|
||||
{
|
||||
// add the configured callbacks
|
||||
callbacks.addAll(this.configuredCallbacks);
|
||||
}
|
||||
|
||||
// take a note of the current date/time
|
||||
Date startDate = new Date();
|
||||
|
||||
@@ -362,13 +381,6 @@ public class AVMDeployWebsiteAction extends ActionExecuterAbstractBase
|
||||
logger.debug("Performing file server deployment to " + host + ":" + port +
|
||||
" using deploymentserver: " + serverProps);
|
||||
|
||||
// TODO: Added new NameMatcher parameter to deploy methods. It acts as a filter.
|
||||
// Any matching path names are ignored for deployment purposes.
|
||||
List<DeploymentCallback> callbacks = new ArrayList<DeploymentCallback>();
|
||||
if (callback != null)
|
||||
{
|
||||
callbacks.add(callback);
|
||||
}
|
||||
report = this.deployService.deployDifferenceFS(version, path, host, port,
|
||||
remoteUsername, remotePassword, targetName, regexMatcher, true, false, false, callbacks);
|
||||
}
|
||||
@@ -378,13 +390,6 @@ public class AVMDeployWebsiteAction extends ActionExecuterAbstractBase
|
||||
logger.debug("Performing Alfresco deployment to " + host + ":" + port +
|
||||
" using deploymentserver: " + serverProps);
|
||||
|
||||
// TODO: Added new NameMatcher parameter to deploy methods. It acts as a filter.
|
||||
// Any matching path names are ignored for deployment purposes.
|
||||
List<DeploymentCallback> callbacks = new ArrayList<DeploymentCallback>();
|
||||
if (callback != null)
|
||||
{
|
||||
callbacks.add(callback);
|
||||
}
|
||||
report = this.deployService.deployDifference(version, path, host, port,
|
||||
remoteUsername, remotePassword, targetPath, regexMatcher, true, false, false, callbacks);
|
||||
}
|
||||
@@ -393,25 +398,6 @@ public class AVMDeployWebsiteAction extends ActionExecuterAbstractBase
|
||||
{
|
||||
deployError = err;
|
||||
logger.error(deployError);
|
||||
|
||||
// report the error to the callback object
|
||||
// TODO: See if this can be incorporated into the DeploymentCallback I/F
|
||||
if (callback != null)
|
||||
{
|
||||
// to avoid a circular dependency use reflection to call the method
|
||||
try
|
||||
{
|
||||
Method method = callback.getClass().getMethod("errorOccurred", new Class[] {Throwable.class});
|
||||
if (method != null)
|
||||
{
|
||||
method.invoke(callback, new Object[] {err});
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
logger.warn("Failed to inform deployment monitor of deployment failure", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (report != null)
|
||||
@@ -472,8 +458,16 @@ public class AVMDeployWebsiteAction extends ActionExecuterAbstractBase
|
||||
reportProps.put(WCMAppModel.PROP_DEPLOYSUCCESSFUL, (report != null));
|
||||
if (report == null && error != null)
|
||||
{
|
||||
// add error message as fail reason if appropriate
|
||||
reportProps.put(WCMAppModel.PROP_DEPLOYFAILEDREASON, error.getMessage());
|
||||
// add error message as fail reason if appropriate (the reported
|
||||
// exception is a wrapper so get the detail from the cause)
|
||||
String errorMsg = error.getMessage();
|
||||
Throwable cause = error.getCause();
|
||||
if (cause != null)
|
||||
{
|
||||
errorMsg = cause.getMessage();
|
||||
}
|
||||
|
||||
reportProps.put(WCMAppModel.PROP_DEPLOYFAILEDREASON, errorMsg);
|
||||
}
|
||||
reportRef = this.nodeService.createNode(attempt,
|
||||
WCMAppModel.ASSOC_DEPLOYMENTREPORTS, WCMAppModel.ASSOC_DEPLOYMENTREPORTS,
|
||||
|
@@ -30,6 +30,7 @@ import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.policy.PolicyScope;
|
||||
import org.alfresco.service.cmr.lock.LockService;
|
||||
import org.alfresco.service.cmr.lock.LockStatus;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
@@ -137,9 +138,12 @@ public class WorkingCopyAspect
|
||||
// Get the origional node
|
||||
NodeRef origNodeRef = (NodeRef)this.nodeService.getProperty(nodeRef, ContentModel.PROP_COPY_REFERENCE);
|
||||
if (origNodeRef != null)
|
||||
{
|
||||
// Release the lock on the origional node
|
||||
this.lockService.unlock(origNodeRef);
|
||||
{
|
||||
if (this.lockService.getLockStatus(origNodeRef).equals(LockStatus.NO_LOCK) == false)
|
||||
{
|
||||
// Release the lock on the origional node
|
||||
this.lockService.unlock(origNodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -282,7 +282,7 @@ public class DeploymentServiceImpl implements DeploymentService
|
||||
{
|
||||
DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.FAILED,
|
||||
new Pair<Integer, String>(version, srcPath),
|
||||
dstPath);
|
||||
dstPath, e.getMessage());
|
||||
for (DeploymentCallback callback : callbacks)
|
||||
{
|
||||
callback.eventOccurred(event);
|
||||
@@ -310,7 +310,7 @@ public class DeploymentServiceImpl implements DeploymentService
|
||||
{
|
||||
DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.FAILED,
|
||||
new Pair<Integer, String>(version, srcPath),
|
||||
dstPath);
|
||||
dstPath, e.getMessage());
|
||||
for (DeploymentCallback callback : callbacks)
|
||||
{
|
||||
callback.eventOccurred(event);
|
||||
@@ -799,10 +799,11 @@ public class DeploymentServiceImpl implements DeploymentService
|
||||
List<DeploymentCallback> callbacks)
|
||||
{
|
||||
DeploymentReport report = new DeploymentReport();
|
||||
DeploymentReceiverService service = getReceiver(hostName, port);
|
||||
DeploymentReceiverService service = null;
|
||||
String ticket = null;
|
||||
try
|
||||
{
|
||||
service = getReceiver(hostName, port);
|
||||
DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.START,
|
||||
new Pair<Integer, String>(version, srcPath),
|
||||
target);
|
||||
@@ -840,12 +841,17 @@ public class DeploymentServiceImpl implements DeploymentService
|
||||
{
|
||||
DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.FAILED,
|
||||
new Pair<Integer, String>(version, srcPath),
|
||||
target);
|
||||
target, e.getMessage());
|
||||
for (DeploymentCallback callback : callbacks)
|
||||
{
|
||||
callback.eventOccurred(event);
|
||||
}
|
||||
service.abort(ticket);
|
||||
|
||||
if (service != null)
|
||||
{
|
||||
service.abort(ticket);
|
||||
}
|
||||
|
||||
throw new AVMException("Deployment to: " + target + " failed.", e);
|
||||
}
|
||||
}
|
||||
|
@@ -50,6 +50,7 @@ public class TransactionImpl extends LifecycleAdapter implements Transaction, Se
|
||||
|
||||
public TransactionImpl()
|
||||
{
|
||||
this.commitTimeMs = Long.valueOf(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -56,6 +56,8 @@ public class DeploymentEvent implements Serializable
|
||||
private Pair<Integer, String> fSource;
|
||||
|
||||
private String fDestination;
|
||||
|
||||
private String fMessage;
|
||||
|
||||
public DeploymentEvent(Type type, Pair<Integer, String> source, String destination)
|
||||
{
|
||||
@@ -63,6 +65,13 @@ public class DeploymentEvent implements Serializable
|
||||
fSource = source;
|
||||
fDestination = destination;
|
||||
}
|
||||
|
||||
public DeploymentEvent(Type type, Pair<Integer, String> source, String destination, String message)
|
||||
{
|
||||
this(type, source, destination);
|
||||
|
||||
fMessage = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the event.
|
||||
@@ -90,12 +99,28 @@ public class DeploymentEvent implements Serializable
|
||||
{
|
||||
return fDestination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message.
|
||||
* @return
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
return fMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a String representation.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return fType + ": " + fSource + " -> " + fDestination;
|
||||
String str = fType + ": " + fSource + " -> " + fDestination;
|
||||
|
||||
if (fMessage != null)
|
||||
{
|
||||
str = str + " (" + fMessage + ")";
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user