Merged V3.2E to HEAD

17571: ETHREEOH-1863 -  alfresco-webscript-framework.jar is not available in the alfresco-enterprise-sdk-3.1
          - although the framework jar was already part of the SDK when I looked I have done some re-organising of 
          - names and paths and added missing source files.    By no means finished but its another step forward.
   17581: Fix for ETHREEOH-3380 - upload servlet in Explorer does not handle well upload errors as no error message is displayed on the client browser.
   17582: ETHREEOH-2760 - Sealing of standard library root scope objects to prevent script potentially interfering with another scripts processing.
          - Example provided to fix ACT ticket issue against fixed codeline.
   17583: Fixed ETHREEOH-3458 "If the rss feed to display returns bad formatted data or is unavailable an ugly free marker error is displayed"
          - Rss urls pointing to a "missing resource"/"bad formated rss data" is now displayed as "Rss feed is unavailable"/"Can't read rss feed" (before they displayed freemarker error making it impossible to re-configure)
          - Title is now updated after config (therefore the change to return json instead of html) (before a page refresh was needed)
          - The new url is now updated in the "2nd" config dialog after it has been changed in the first (before page refresh was needed)
          - Removed un-internationalised string from config respons template
   17584: ALFCOM-3675 - WebDAV script does not allow inline editing for documents with name in upper case.
          - Now allows any case, as per supplied patch.
          - Also added support for Office 2007 file types so they can now be opened in write mode via webdav in IE6/7 from the Explorer client.
          - Tested in IE6/7.
   17585: Yet another fix for ETHREEOH-1733 - agenda view all days events fixed
   17586: ETHREEOH-1843:  /api/sites/*/memberships search is slow on specific query
   17587: Add cluster lock for JPBM job/timer executor (for WCM submits in a clustered env - ETHREEOH-2230 / ETHREEOH-3319)
   17590: New icons for View Original & View Working Copy actions
   17591: ETHREEOH-2879 - Alfresco + OpenLDAP: Unable to retrieve user from repository.
          - Fixed SURF to handle users without (utterly bizarely) First or Last names or even, usefully, neither.
   17592: Merged V3.2 to V3.1
      17415: Fix for ETHREEOH-3293 - Editing user details on large user repository causes Hibernate exception.
             Fix for ETHREEOH-3294 - Extreemly slow repository performance adding a new user to large user repository via the Explorer Client admin console.
   17593: Icon for doclib View In Browser action
   17594: ETHREEOH-2864 - Share - Documents cannot be deleted (in "All Documents" view)
   17595: ETHREEOH-3203:  Impossibility to add comment to any object by SiteContributor user
   17596: ETHREEOH-1469 - SMTP errors not reported when sending an invitation
            - now errors are reported.
            - may upset unit tests, i've fixed those I know about
   17598: Fixed ETHREEOH-3445 "Admin Console - Group Search sometimes never displays results list"
   17601: ETHREEOH-3382 - Share Sites menu is broken in "debug" mode. Reworked menu css. Removed unused footer component.
   17602: Share global debug flags removed from web-framework-config-application.xml. Use share-config-custom.xml instead.
   17603: Changed wording on Create/Edit Site dialogs from "Access" to "Visibility". "Access" was no longer accurate now that Moderated Sites' content is private to non-members.
   17604: ETHREEOH-1469 - SMTP error when sending an invitation does not return a failure.
          - SiteServiceTest also needed "fixing"
   17606: ETHREEOH-3475 - IE: Second search on add groups to site gets yui error but works. Related to YUI bug 2286608. YUI patched instead of all DataTable client code. (Patch removed from DocLib)
   17607: ETHREEOH-3470 - "Add" button is unavailable if the group with the name of more than 60 characters is found
   17608: Fixed invalid use of Forms validator. Validators updated to handle specific case anyway.
   17610: Fixed ETHREEOH-3445 "Admin Console - Group Search sometimes never displays results list" - missed commit of non-default theme files
   17612: Fixed ETHREEOH-3480 "Browse" button no longer works after Groups Admin console page is refreshed
   17613: ETHREEOH-3450 Fixed illegal nested comment in web-client-config-custom.xml.sample
   17616: Fix for ETHREEOH-2863 - Code cache memory leak observed in JVM 1.6 when script action calls another script which in turn calls other functions.
          - Fixed use of Rhino optimization level when executing string based scripts.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18160 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2010-01-20 10:22:18 +00:00
parent f89af49875
commit 2ab713d0cb
6 changed files with 305 additions and 63 deletions

View File

@@ -35,6 +35,7 @@ import java.util.Set;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.template.DateCompareMethod;
@@ -56,6 +57,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.EmailValidator;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
@@ -80,7 +82,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
public static final String PARAM_TEXT = "text";
public static final String PARAM_FROM = "from";
public static final String PARAM_TEMPLATE = "template";
/**
* From address
*/
@@ -138,6 +140,15 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
*/
private String repoRemoteUrl = null;
/**
* Test mode prevents email messages from being sent.
* It is used when unit testing when we don't actually want to send out email messages.
*
* MER 20/11/2009 This is a quick and dirty fix. It should be replaced by being
* "mocked out" or some other better way of running the unit tests.
*/
private boolean testMode = false;
/**
* @param javaMailSender the java mail sender
*/
@@ -236,7 +247,9 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
}
/**
* Execute the rule action
* Send an email message
*
* @throws AlfrescoRuntimeExeption
*/
@Override
protected void executeImpl(
@@ -375,15 +388,17 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
}
}
};
try
{
// Send the message
javaMailSender.send(mailPreparer);
// Send the message unless we are in "testMode"
if(!testMode)
{
javaMailSender.send(mailPreparer);
}
}
catch (Throwable e)
catch (MailException e)
{
// don't stop the action but let admins know email is not getting sent
String to = (String)ruleAction.getParameterValue(PARAM_TO);
if (to == null)
{
@@ -395,6 +410,8 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
}
logger.error("Failed to send email to " + to, e);
throw new AlfrescoRuntimeException("Failed to send email to:" + to, e);
}
}
@@ -461,6 +478,16 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
paramList.add(new ParameterDefinitionImpl(PARAM_TEMPLATE, DataTypeDefinition.NODE_REF, false, getParamDisplayLabel(PARAM_TEMPLATE)));
}
public void setTestMode(boolean testMode)
{
this.testMode = testMode;
}
public boolean isTestMode()
{
return testMode;
}
public static class URLHelper
{
String contextPath;

View File

@@ -28,6 +28,7 @@ import java.util.Date;
import java.util.List;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.MailActionExecuter;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.site.SiteModel;
import org.alfresco.service.cmr.invitation.Invitation;
@@ -78,11 +79,17 @@ public class InvitationServiceImplTest extends BaseAlfrescoSpringTest
protected void onSetUpInTransaction() throws Exception
{
super.onSetUpInTransaction();
this.invitationService = (InvitationService)this.applicationContext.getBean("InvitationService");
this.siteService = (SiteService)this.applicationContext.getBean("SiteService");
this.personService = (PersonService)this.applicationContext.getBean("PersonService");
this.invitationService = (InvitationService) this.applicationContext.getBean("InvitationService");
this.siteService = (SiteService) this.applicationContext.getBean("SiteService");
this.personService = (PersonService) this.applicationContext.getBean("PersonService");
this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent");
// TODO MER 20/11/2009 Bodge - turn off email sending to prevent errors during unit testing
// (or sending out email by accident from tests)
MailActionExecuter mail = (MailActionExecuter)this.applicationContext.getBean("mail");
mail.setTestMode(true);
createPerson(USER_MANAGER, USER_MANAGER + "@alfrescotesting.com", PERSON_FIRSTNAME, PERSON_LASTNAME);
createPerson(USER_ONE, USER_ONE_EMAIL,USER_ONE_FIRSTNAME, USER_ONE_LASTNAME);
createPerson(USER_TWO, USER_TWO + "@alfrescotesting.com", PERSON_FIRSTNAME, PERSON_LASTNAME);

View File

@@ -404,7 +404,6 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
model = convertToRhinoModel(model);
Context cx = Context.enter();
cx.setOptimizationLevel(1);
try
{
// Create a thread-specific scope from one of the shared scopes.
@@ -542,7 +541,7 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
try
{
cx.setWrapFactory(wrapFactory);
this.secureScope = cx.initStandardObjects();
this.secureScope = cx.initStandardObjects(null, true);
// remove security issue related objects - this ensures the script may not access
// unsecure java.* libraries or import any other classes for direct access - only
@@ -555,7 +554,7 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
{
Context.exit();
}
// Initialise the non-secure scope
cx = Context.enter();
try
@@ -564,7 +563,7 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
// allow access to all libraries and objects, including the importer
// @see http://www.mozilla.org/rhino/ScriptingJava.html
this.nonSecureScope = new ImporterTopLevel(cx);
this.nonSecureScope = new ImporterTopLevel(cx, true);
}
finally
{

View File

@@ -39,6 +39,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.activities.ActivityType;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.search.QueryParameterDefImpl;
import org.alfresco.repo.search.impl.lucene.LuceneQueryParser;
import org.alfresco.repo.security.authentication.AuthenticationContext;
@@ -60,6 +61,8 @@ import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.QueryParameterDefinition;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus;
@@ -1145,25 +1148,42 @@ public class SiteServiceImpl implements SiteService, SiteModel
{
boolean addUser = false;
NodeRef personRef = this.personService.getPerson(username);
Map<QName, Serializable> props = this.nodeService.getProperties(personRef);
String firstName = (String)props.get(ContentModel.PROP_FIRSTNAME);
String lastName = (String)props.get(ContentModel.PROP_LASTNAME);
final String lowFirstName = (firstName != null ? firstName.toLowerCase() : "");
final String lowLastName = (lastName != null ? lastName.toLowerCase() : "");
for (int i=0; i<nameFilters.length; i++)
String query = "+TYPE:\"cm:person\" +@cm\\:userName:\"" + username + "\"";
SearchParameters searchParameters = new SearchParameters();
searchParameters.setLanguage(SearchService.LANGUAGE_LUCENE);
searchParameters.addStore(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
searchParameters.setQuery(query);
ResultSet resultSet = this.searchService.query(searchParameters);
try
{
if (lowFirstName.indexOf(nameFilters[i]) != -1)
if (resultSet.length() != 0)
{
addUser = true;
break;
}
else if (lowLastName.indexOf(nameFilters[i]) != -1)
{
addUser = true;
break;
ResultSetRow row = resultSet.getRow(0);
Map<String, Serializable> values = row.getValues();
String firstName = (String)values.get(ContentModel.PROP_FIRSTNAME.toString());
String lastName = (String)values.get(ContentModel.PROP_LASTNAME.toString());
final String lowFirstName = (firstName != null ? firstName.toLowerCase() : "");
final String lowLastName = (lastName != null ? lastName.toLowerCase() : "");
for (int i=0; i<nameFilters.length; i++)
{
if (lowFirstName.indexOf(nameFilters[i]) != -1)
{
addUser = true;
break;
}
else if (lowLastName.indexOf(nameFilters[i]) != -1)
{
addUser = true;
break;
}
}
}
}
finally
{
resultSet.close();
}
return addUser;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
* 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
@@ -24,6 +24,7 @@
*/
package org.alfresco.repo.workflow.jbpm;
import org.alfresco.repo.lock.JobLockService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
@@ -43,23 +44,32 @@ import org.springmodules.workflow.jbpm31.JbpmFactoryLocator;
public class AlfrescoJobExecutor extends JobExecutor
{
private static final long serialVersionUID = -4576396495395482111L;
private static Log log = LogFactory.getLog(JobExecutor.class);
private TransactionService transactionService;
private JbpmConfiguration jbpmConfiguration;
private JobLockService jobLockService;
private boolean jobExecutorLockEnabled = true;
public void setJobExecutorLockEnabled(boolean jobExecutorLockEnabled)
{
this.jobExecutorLockEnabled = jobExecutorLockEnabled;
}
/**
* Constructor
* Is Alfresco Job Executor Lock Enabled
*
* @return true if only one executor thread allowed (including across cluster)
*
* @since 3.2
*/
public AlfrescoJobExecutor()
public boolean getJobExecutorLockEnabled()
{
BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
transactionService = (TransactionService)factory.getFactory().getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName());
jbpmConfiguration = (JbpmConfiguration)factory.getFactory().getBean("jbpm_configuration");
return this.jobExecutorLockEnabled;
}
/**
* Gets Transaction Service
*
@@ -69,7 +79,34 @@ public class AlfrescoJobExecutor extends JobExecutor
{
return transactionService;
}
/**
* Gets Job Lock Service
*
* @return job lock service
*
* @since 3.2
*/
public JobLockService getJobLockService()
{
return jobLockService;
}
/**
* Constructor
*/
public AlfrescoJobExecutor()
{
BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
transactionService = (TransactionService)factory.getFactory().getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName());
jobLockService = (JobLockService)factory.getFactory().getBean(ServiceRegistry.JOB_LOCK_SERVICE.getLocalName());
jbpmConfiguration = (JbpmConfiguration)factory.getFactory().getBean("jbpm_configuration");
}
/* (non-Javadoc)
* @see org.jbpm.job.executor.JobExecutor#startThread()
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
* 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
@@ -28,8 +28,13 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import org.alfresco.repo.lock.LockAcquisitionException;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.job.Job;
import org.jbpm.job.executor.JobExecutorThread;
@@ -38,13 +43,24 @@ import org.jbpm.job.executor.JobExecutorThread;
/**
* Alfresco Job Executor Thread
*
* @author davidc
* @author davidc, janv
*/
public class AlfrescoJobExecutorThread extends JobExecutorThread
{
/** The name of the lock used to ensure that job executor does not run on more than one node at the same time. */
private static final QName LOCK_QNAME = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI,
"AlfrescoJbpmJobExecutor");
private static Log logger = LogFactory.getLog(AlfrescoJobExecutorThread.class);
private AlfrescoJobExecutor alfrescoJobExecutor;
private boolean isActive = true;
private long jbpmMaxLockTime;
private long jobLockTTL = 0;
private String jobLockToken = null;
@Override
public void setActive(boolean isActive)
{
@@ -58,26 +74,75 @@ public class AlfrescoJobExecutorThread extends JobExecutorThread
{
super(name, jobExecutor, jbpmConfiguration, idleInterval, maxIdleInterval, maxLockTime, maxHistory);
this.alfrescoJobExecutor = jobExecutor;
this.jbpmMaxLockTime = maxLockTime;
this.jobLockTTL = jbpmMaxLockTime+(1000 * 60 * 10);
}
@SuppressWarnings("unchecked")
@Override
protected Collection acquireJobs()
{
if (!isActive)
Collection jobs = Collections.EMPTY_LIST;
if ((isActive) && (! alfrescoJobExecutor.getTransactionService().isReadOnly()))
{
return Collections.EMPTY_LIST;
}
else if (alfrescoJobExecutor.getTransactionService().isReadOnly())
{
return Collections.EMPTY_LIST;
}
return alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionHelper.RetryingTransactionCallback<Collection>() {
public Collection execute() throws Throwable
try
{
jobs = alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionHelper.RetryingTransactionCallback<Collection>() {
public Collection execute() throws Throwable
{
if (jobLockToken != null)
{
refreshExecutorLock(jobLockToken);
}
else
{
jobLockToken = getExecutorLock();
}
try
{
return AlfrescoJobExecutorThread.super.acquireJobs();
}
catch (Throwable t)
{
logger.error("Failed to acquire jobs");
releaseExecutorLock(jobLockToken);
jobLockToken = null;
throw t;
}
}
});
if (jobs != null)
{
return AlfrescoJobExecutorThread.super.acquireJobs();
if (logger.isDebugEnabled() && (! logger.isTraceEnabled()) && (! jobs.isEmpty()))
{
logger.debug("acquired "+jobs.size()+" job"+((jobs.size() != 1) ? "s" : ""));
}
if (logger.isTraceEnabled())
{
logger.trace("acquired "+jobs.size()+" job"+((jobs.size() != 1) ? "s" : "")+((jobs.size() > 0) ? ": "+jobs.toString() : ""));
}
if (jobs.size() == 0)
{
releaseExecutorLock(jobLockToken);
jobLockToken = null;
}
}
});
}
catch (LockAcquisitionException e)
{
// ignore
jobLockToken = null;
}
}
return jobs;
}
@Override
@@ -87,6 +152,7 @@ public class AlfrescoJobExecutorThread extends JobExecutorThread
{
return null;
}
return alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionHelper.RetryingTransactionCallback<Date>() {
public Date execute() throws Throwable
@@ -95,24 +161,104 @@ public class AlfrescoJobExecutorThread extends JobExecutorThread
}
}, true);
}
/**
* {@inheritDoc}
*/
@Override
protected void executeJob(Job job)
{
if (!isActive)
if ((!isActive) || (alfrescoJobExecutor.getTransactionService().isReadOnly()))
{
return;
}
else if (alfrescoJobExecutor.getTransactionService().isReadOnly())
try
{
return;
alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper().doInTransaction(new TransactionJob(job));
}
catch (LockAcquisitionException e)
{
// ignore
jobLockToken = null;
}
alfrescoJobExecutor.getTransactionService().getRetryingTransactionHelper().doInTransaction(new TransactionJob(job));
}
private String getExecutorLock()
{
String jobLockToken = null;
if (alfrescoJobExecutor.getJobExecutorLockEnabled())
{
try
{
jobLockToken = alfrescoJobExecutor.getJobLockService().getLock(LOCK_QNAME, jobLockTTL, 3000, 10);
if (logger.isTraceEnabled())
{
logger.trace(Thread.currentThread().getName()+" got lock token: "+jobLockToken);
}
}
catch (LockAcquisitionException e)
{
if (logger.isTraceEnabled())
{
logger.trace("Failed to get Alfresco Job Executor lock - may already running in another thread");
}
throw e;
}
}
return jobLockToken;
}
private void refreshExecutorLock(String jobLockToken)
{
if (jobLockToken != null)
{
try
{
alfrescoJobExecutor.getJobLockService().refreshLock(jobLockToken, LOCK_QNAME, jobLockTTL);
if (logger.isTraceEnabled())
{
logger.trace(Thread.currentThread().getName()+" refreshed lock token: "+jobLockToken);
}
}
catch (LockAcquisitionException e)
{
if (logger.isTraceEnabled())
{
logger.trace("Failed to refresh Alfresco Job Executor lock - may no longer exist ("+jobLockToken+")");
}
throw e;
}
}
}
private void releaseExecutorLock(String jobLockToken)
{
if (jobLockToken != null)
{
try
{
alfrescoJobExecutor.getJobLockService().releaseLock(jobLockToken, LOCK_QNAME);
if (logger.isTraceEnabled())
{
logger.trace(Thread.currentThread().getName()+" released lock token: "+jobLockToken);
}
}
catch (LockAcquisitionException e)
{
if (logger.isTraceEnabled())
{
logger.trace("Failed to release Alfresco Job Executor lock - may no longer exist ("+jobLockToken+")");
}
throw e;
}
}
}
/**
* Helper class for holding Job reference
@@ -122,7 +268,7 @@ public class AlfrescoJobExecutorThread extends JobExecutorThread
private class TransactionJob implements RetryingTransactionCallback<Object>
{
private Job job;
/**
* Constructor
*
@@ -132,13 +278,19 @@ public class AlfrescoJobExecutorThread extends JobExecutorThread
{
this.job = job;
}
public Object execute() throws Throwable
{
refreshExecutorLock(jobLockToken);
AlfrescoJobExecutorThread.super.executeJob(job);
if (logger.isDebugEnabled())
{
logger.debug("executed job: "+job);
}
return null;
}
}
}