diff --git a/config/alfresco/authentication-services-context.xml b/config/alfresco/authentication-services-context.xml
index 32fcba35c5..846c2642b6 100644
--- a/config/alfresco/authentication-services-context.xml
+++ b/config/alfresco/authentication-services-context.xml
@@ -411,6 +411,12 @@
false
+
+
+
+
+
+ AFTER_FIXED_TIME
diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml
index bf95720ed0..4ffad67fb3 100644
--- a/config/alfresco/core-services-context.xml
+++ b/config/alfresco/core-services-context.xml
@@ -421,6 +421,12 @@
+
+
+
+
+
+
@@ -438,13 +444,17 @@
-
-
-
+
+
+
@@ -544,6 +554,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${dir.indexes}
+
+
+
+
+
+
+
+
+ ${lucene.maxAtomicTransformationTime}
+
+
+ ${lucene.query.maxClauses}
+
+
+ ${lucene.indexer.batchSize}
+
+
+ ${dir.indexes.lock}
+
+
+ ${lucene.indexer.maxFieldLength}
+
+
+ ${lucene.write.lock.timeout}
+
+
+ ${lucene.commit.lock.timeout}
+
+
+ ${lucene.lock.poll.interval}
+
+
+ EXACT_LANGUAGE_AND_ALL
+
+
+ EXACT_LANGUAGE_AND_ALL
+
+
+
+
+
-
+
diff --git a/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java b/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java
index 9be9e5fab5..666b918b19 100644
--- a/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java
+++ b/source/java/org/alfresco/repo/action/executer/MailActionExecuter.java
@@ -34,7 +34,6 @@ 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;
@@ -54,6 +53,7 @@ import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PersonService;
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.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
@@ -261,7 +261,7 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
{
NodeRef person = personService.getPerson(authority);
String address = (String)nodeService.getProperty(person, ContentModel.PROP_EMAIL);
- if (address != null && address.length() != 0)
+ if (address != null && address.length() != 0 && validateAddress(address))
{
recipients.add(address);
}
@@ -351,6 +351,28 @@ public class MailActionExecuter extends ActionExecuterAbstractBase
logger.error("Failed to send email to " + to, e);
}
}
+
+ /**
+ * Return true if address has valid format
+ * @param address
+ * @return
+ */
+ private boolean validateAddress(String address)
+ {
+ boolean result = false;
+
+ EmailValidator emailValidator = EmailValidator.getInstance();
+ if (emailValidator.isValid(address))
+ {
+ result = true;
+ }
+ else
+ {
+ logger.error("Failed to send email to '" + address + "' as the address is incorrectly formatted" );
+ }
+
+ return result;
+ }
/**
* @param ref The node representing the current document ref
diff --git a/source/java/org/alfresco/repo/rule/RuleServiceImpl.java b/source/java/org/alfresco/repo/rule/RuleServiceImpl.java
index 2741f2682f..8fa8db6511 100644
--- a/source/java/org/alfresco/repo/rule/RuleServiceImpl.java
+++ b/source/java/org/alfresco/repo/rule/RuleServiceImpl.java
@@ -538,7 +538,8 @@ public class RuleServiceImpl implements RuleService, RuntimeRuleService
* @param ruleNodeRef the rule node reference
* @return the rule
*/
- public Rule getRule(NodeRef ruleNodeRef)
+ @SuppressWarnings("unchecked")
+ public Rule getRule(NodeRef ruleNodeRef)
{
// Get the rule properties
Map props = this.runtimeNodeService.getProperties(ruleNodeRef);
diff --git a/source/java/org/alfresco/repo/rule/RuleTypeImpl.java b/source/java/org/alfresco/repo/rule/RuleTypeImpl.java
index a2019c98a8..e235d14c30 100644
--- a/source/java/org/alfresco/repo/rule/RuleTypeImpl.java
+++ b/source/java/org/alfresco/repo/rule/RuleTypeImpl.java
@@ -129,14 +129,14 @@ public class RuleTypeImpl extends CommonResourceAbstractBase implements RuleType
this.nodeService.exists(actionedUponNodeRef) == true &&
this.nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_TEMPORARY) == false)
{
- if (this.ruleService.hasRules(nodeRef) == true)
+ List rules = this.ruleService.getRules(
+ nodeRef,
+ true,
+ this.name);
+
+ if (rules.size() != 0)
{
- List rules = this.ruleService.getRules(
- nodeRef,
- true,
- this.name);
-
- for (Rule rule : rules)
+ for (Rule rule : rules)
{
if (logger.isDebugEnabled() == true)
{
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java
index b8a3eeb2f2..25576b16fb 100644
--- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java
+++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java
@@ -42,15 +42,15 @@ import org.alfresco.service.namespace.NamespaceService;
*/
public class ADMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAndSearcherFactory implements SupportsBackgroundIndexing
{
- private DictionaryService dictionaryService;
+ protected DictionaryService dictionaryService;
private NamespaceService nameSpaceService;
- private NodeService nodeService;
+ protected NodeService nodeService;
- private FullTextSearchIndexer fullTextSearchIndexer;
+ protected FullTextSearchIndexer fullTextSearchIndexer;
- private ContentService contentService;
+ protected ContentService contentService;
/**
* Set the dictinary service
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java
index bb431efad8..88c97c87e7 100644
--- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java
+++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java
@@ -393,6 +393,18 @@ public class ADMLuceneIndexerImpl extends AbstractLuceneIndexerImpl imp
indexer.initialise(storeRef, deltaId);
return indexer;
}
+
+ public static ADMLuceneNoActionIndexerImpl getNoActionIndexer(StoreRef storeRef, String deltaId, LuceneConfig config) throws LuceneIndexException
+ {
+ if (s_logger.isDebugEnabled())
+ {
+ s_logger.debug("Creating indexer");
+ }
+ ADMLuceneNoActionIndexerImpl indexer = new ADMLuceneNoActionIndexerImpl();
+ indexer.setLuceneConfig(config);
+ indexer.initialise(storeRef, deltaId);
+ return indexer;
+ }
/*
* Transactional support Used by the resource manager for indexers.
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneNoActionIndexerImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneNoActionIndexerImpl.java
new file mode 100644
index 0000000000..9dca52d6e5
--- /dev/null
+++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneNoActionIndexerImpl.java
@@ -0,0 +1,100 @@
+/*
+ * 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.search.impl.lucene;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+
+public class ADMLuceneNoActionIndexerImpl extends ADMLuceneIndexerImpl
+{
+
+ public ADMLuceneNoActionIndexerImpl()
+ {
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public void createChildRelationship(ChildAssociationRef relationshipRef) throws LuceneIndexException
+ {
+ return;
+ }
+
+ @Override
+ public void createNode(ChildAssociationRef relationshipRef) throws LuceneIndexException
+ {
+ NodeRef childRef = relationshipRef.getChildRef();
+ // If we have the root node we delete all other root nodes first
+ if ((relationshipRef.getParentRef() == null) && childRef.equals(nodeService.getRootNode(childRef.getStoreRef())))
+ {
+ // do the root node only
+ super.createNode(relationshipRef);
+ }
+ else
+ {
+ // Nothing
+ }
+ }
+
+ @Override
+ public void deleteChildRelationship(ChildAssociationRef relationshipRef) throws LuceneIndexException
+ {
+ return;
+ }
+
+ @Override
+ public void deleteNode(ChildAssociationRef relationshipRef) throws LuceneIndexException
+ {
+ NodeRef childRef = relationshipRef.getChildRef();
+ // If we have the root node we delete all other root nodes first
+ if ((relationshipRef.getParentRef() == null) && childRef.equals(nodeService.getRootNode(childRef.getStoreRef())))
+ {
+ // do the root node only
+ super.deleteNode(relationshipRef);
+ }
+ else
+ {
+ // Nothing
+ }
+ }
+
+ @Override
+ public void updateChildRelationship(ChildAssociationRef relationshipBeforeRef, ChildAssociationRef relationshipAfterRef) throws LuceneIndexException
+ {
+ return;
+ }
+
+ @Override
+ public void updateNode(NodeRef nodeRef) throws LuceneIndexException
+ {
+ if((nodeService.hasAspect(nodeRef, ContentModel.ASPECT_ROOT) && nodeRef.equals(nodeService.getRootNode(nodeRef.getStoreRef()))))
+ {
+ super.updateNode(nodeRef);
+ }
+ }
+
+
+
+}
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneUnIndexedIndexAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneUnIndexedIndexAndSearcherFactory.java
new file mode 100644
index 0000000000..12e9247218
--- /dev/null
+++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneUnIndexedIndexAndSearcherFactory.java
@@ -0,0 +1,44 @@
+/*
+ * 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.search.impl.lucene;
+
+import org.alfresco.service.cmr.repository.StoreRef;
+
+public class ADMLuceneUnIndexedIndexAndSearcherFactory extends ADMLuceneIndexerAndSearcherFactory
+{
+
+ @Override
+ protected LuceneIndexer createIndexer(StoreRef storeRef, String deltaId)
+ {
+ ADMLuceneNoActionIndexerImpl indexer = ADMLuceneIndexerImpl.getNoActionIndexer(storeRef, deltaId, this);
+ indexer.setNodeService(nodeService);
+ indexer.setDictionaryService(dictionaryService);
+ // indexer.setLuceneIndexLock(luceneIndexLock);
+ indexer.setFullTextSearchIndexer(fullTextSearchIndexer);
+ indexer.setContentService(contentService);
+ indexer.setMaxAtomicTransformationTime(getMaxTransformationTime());
+ return indexer;
+ }
+}
diff --git a/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java b/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java
index 312a080b11..543c27b379 100644
--- a/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java
+++ b/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java
@@ -48,6 +48,7 @@ import net.sf.acegisecurity.providers.dao.SaltSource;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cache.SimpleCache;
+import org.alfresco.repo.security.authentication.InMemoryTicketComponentImpl.ExpiryMode;
import org.alfresco.repo.security.authentication.InMemoryTicketComponentImpl.Ticket;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.ServiceRegistry;
@@ -139,8 +140,7 @@ public class AuthenticationTest extends TestCase
authenticationManager = (AuthenticationManager) ctx.getBean("authenticationManager");
saltSource = (SaltSource) ctx.getBean("saltSource");
- TransactionService transactionService = (TransactionService) ctx.getBean(ServiceRegistry.TRANSACTION_SERVICE
- .getLocalName());
+ TransactionService transactionService = (TransactionService) ctx.getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName());
userTransaction = transactionService.getUserTransaction();
userTransaction.begin();
@@ -155,8 +155,7 @@ public class AuthenticationTest extends TestCase
systemNodeRef = nodeService.createNode(rootNodeRef, children, system, container).getChildRef();
typesNodeRef = nodeService.createNode(systemNodeRef, children, types, container).getChildRef();
Map props = createPersonProperties("Andy");
- personAndyNodeRef = nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props)
- .getChildRef();
+ personAndyNodeRef = nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props).getChildRef();
assertNotNull(personAndyNodeRef);
deleteAndy();
@@ -270,6 +269,10 @@ public class AuthenticationTest extends TestCase
authenticationService.authenticate("Andy_ Woof/Domain", "".toCharArray());
assertEquals("Andy_ Woof/Domain", authenticationService.getCurrentUserName());
+ authenticationService.createAuthentication("Andy `\u00ac\u00a6!\u00a3$%^&*()-_=+\t\n\u0000[]{};'#:@~,./<>?\\|", "".toCharArray());
+ authenticationService.authenticate("Andy `\u00ac\u00a6!\u00a3$%^&*()-_=+\t\n\u0000[]{};'#:@~,./<>?\\|", "".toCharArray());
+ assertEquals("Andy `\u00ac\u00a6!\u00a3$%^&*()-_=+\t\n\u0000[]{};'#:@~,./<>?\\|", authenticationService.getCurrentUserName());
+
if (! tenantService.isEnabled())
{
authenticationService.createAuthentication("Andy `\u00ac\u00a6!\u00a3$%^&*()-_=+\t\n\u0000[]{};'#:@~,./<>?\\|", "".toCharArray());
@@ -307,8 +310,7 @@ public class AuthenticationTest extends TestCase
assertTrue(AndyDetails.isCredentialsNonExpired());
assertTrue(AndyDetails.isEnabled());
assertNotSame("cabbage", AndyDetails.getPassword());
- assertEquals(AndyDetails.getPassword(), passwordEncoder.encodePassword("cabbage", saltSource
- .getSalt(AndyDetails)));
+ assertEquals(AndyDetails.getPassword(), passwordEncoder.encodePassword("cabbage", saltSource.getSalt(AndyDetails)));
assertEquals(1, AndyDetails.getAuthorities().length);
// Object oldSalt = dao.getSalt(AndyDetails);
@@ -465,8 +467,6 @@ public class AuthenticationTest extends TestCase
// assertNull(dao.getUserOrNull("Andy"));
}
-
-
public void testTicket()
{
dao.createUser("Andy", "ticket".toCharArray());
@@ -568,6 +568,147 @@ public class AuthenticationTest extends TestCase
// assertNull(dao.getUserOrNull("Andy"));
}
+ public void testTicketExpiryMode()
+ {
+ InMemoryTicketComponentImpl tc = new InMemoryTicketComponentImpl();
+ tc.setOneOff(false);
+ tc.setTicketsExpire(true);
+ tc.setValidDuration("P5S");
+ tc.setTicketsCache(ticketsCache);
+ tc.setExpiryMode(ExpiryMode.AFTER_FIXED_TIME.toString());
+
+ dao.createUser("Andy", "ticket".toCharArray());
+
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Andy", "ticket");
+ token.setAuthenticated(false);
+
+ Authentication result = authenticationManager.authenticate(token);
+ result.setAuthenticated(true);
+
+ String ticket = tc.getNewTicket(getUserName(result));
+ tc.validateTicket(ticket);
+ assertEquals(ticketComponent.getCurrentTicket("Andy"), ticket);
+ tc.validateTicket(ticket);
+ assertEquals(ticketComponent.getCurrentTicket("Andy"), ticket);
+ tc.validateTicket(ticket);
+ assertEquals(ticketComponent.getCurrentTicket("Andy"), ticket);
+
+ synchronized (this)
+ {
+ try
+ {
+ wait(10000);
+ }
+ catch (InterruptedException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ try
+ {
+ tc.validateTicket(ticket);
+ assertNotNull(null);
+ }
+ catch (AuthenticationException e)
+ {
+
+ }
+
+ try
+ {
+ tc.validateTicket(ticket);
+ assertNotNull(null);
+ }
+ catch (AuthenticationException e)
+ {
+
+ }
+
+ try
+ {
+ tc.validateTicket(ticket);
+ assertNotNull(null);
+ }
+ catch (AuthenticationException e)
+ {
+
+ }
+
+ synchronized (this)
+ {
+ try
+ {
+ wait(10000);
+ }
+ catch (InterruptedException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ try
+ {
+ tc.validateTicket(ticket);
+ assertNotNull(null);
+ }
+ catch (AuthenticationException e)
+ {
+
+ }
+
+ tc.setExpiryMode(ExpiryMode.AFTER_INACTIVITY.toString());
+ ticket = tc.getNewTicket(getUserName(result));
+
+ for (int i = 0; i < 50; i++)
+ {
+ synchronized (this)
+ {
+
+ try
+ {
+ wait(100);
+ }
+ catch (InterruptedException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ tc.validateTicket(ticket);
+
+ }
+ }
+
+ synchronized (this)
+ {
+ try
+ {
+ wait(10000);
+ }
+ catch (InterruptedException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ try
+ {
+ tc.validateTicket(ticket);
+ assertNotNull(null);
+ }
+ catch (AuthenticationException e)
+ {
+
+ }
+
+
+ dao.deleteUser("Andy");
+ // assertNull(dao.getUserOrNull("Andy"));
+ }
+
public void testTicketExpires()
{
InMemoryTicketComponentImpl tc = new InMemoryTicketComponentImpl();
@@ -704,7 +845,7 @@ public class AuthenticationTest extends TestCase
// assertNull(dao.getUserOrNull("Andy"));
}
-
+
public void testAuthenticationServiceGetNewTicket()
{
authenticationService.createAuthentication("GUEST", "".toCharArray());
@@ -718,16 +859,16 @@ public class AuthenticationTest extends TestCase
// assert the user is authenticated
assertEquals("Andy", authenticationService.getCurrentUserName());
-
+
String ticket1 = authenticationService.getCurrentTicket();
-
+
authenticationService.authenticate("Andy", "auth1".toCharArray());
// assert the user is authenticated
assertEquals("Andy", authenticationService.getCurrentUserName());
-
+
String ticket2 = authenticationService.getCurrentTicket();
-
+
assertFalse(ticket1.equals(ticket2));
}
diff --git a/source/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentImpl.java b/source/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentImpl.java
index ec63924f69..d85cc0ed83 100644
--- a/source/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentImpl.java
+++ b/source/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentImpl.java
@@ -49,7 +49,7 @@ public class InMemoryTicketComponentImpl implements TicketComponent
* Ticket prefix
*/
public static final String GRANTED_AUTHORITY_TICKET_PREFIX = "TICKET_";
-
+
private static ThreadLocal currentTicket = new ThreadLocal();
private boolean ticketsExpire;
@@ -61,10 +61,11 @@ public class InMemoryTicketComponentImpl implements TicketComponent
private String guid;
private SimpleCache ticketsCache; // Can't use Ticket as it's private
+
+ private ExpiryMode expiryMode = ExpiryMode.AFTER_FIXED_TIME;
/**
* IOC constructor
- *
*/
public InMemoryTicketComponentImpl()
{
@@ -89,7 +90,7 @@ public class InMemoryTicketComponentImpl implements TicketComponent
{
expiryDate = Duration.add(new Date(), validDuration);
}
- Ticket ticket = new Ticket(ticketsExpire, expiryDate, userName);
+ Ticket ticket = new Ticket(ticketsExpire ? expiryMode : ExpiryMode.DO_NOT_EXPIRE, expiryDate, userName, validDuration);
ticketsCache.put(ticket.getTicketId(), ticket);
String ticketString = GRANTED_AUTHORITY_TICKET_PREFIX + ticket.getTicketId();
currentTicket.set(ticketString);
@@ -119,6 +120,7 @@ public class InMemoryTicketComponentImpl implements TicketComponent
/**
* Helper method to find a ticket
+ *
* @param ticketString
* @return - the ticket
*/
@@ -129,7 +131,8 @@ public class InMemoryTicketComponentImpl implements TicketComponent
}
/**
- * Helper method to extract the ticket id from the ticket string
+ * Helper method to extract the ticket id from the ticket string
+ *
* @param ticketString
* @return - the ticket key
*/
@@ -271,14 +274,14 @@ public class InMemoryTicketComponentImpl implements TicketComponent
/**
* Ticket
+ *
* @author andyh
- *
*/
public static class Ticket implements Serializable
{
private static final long serialVersionUID = -5904510560161261049L;
- private boolean expires;
+ private ExpiryMode expires;
private Date expiryDate;
@@ -287,18 +290,18 @@ public class InMemoryTicketComponentImpl implements TicketComponent
private String ticketId;
private String guid;
+
+ private Duration validDuration;
- Ticket(boolean expires, Date expiryDate, String userName)
+ Ticket(ExpiryMode expires, Date expiryDate, String userName, Duration validDuration)
{
this.expires = expires;
this.expiryDate = expiryDate;
this.userName = userName;
+ this.validDuration = validDuration;
this.guid = UUIDGenerator.getInstance().generateRandomBasedUUID().toString();
-
- String encode = (expires ? "T" : "F") +
- ((expiryDate == null) ? new Date().toString(): expiryDate.toString()) +
- userName + guid;
+ String encode = (expires.toString()) + ((expiryDate == null) ? new Date().toString() : expiryDate.toString()) + userName + guid;
MessageDigest digester;
try
{
@@ -314,18 +317,18 @@ public class InMemoryTicketComponentImpl implements TicketComponent
}
catch (NoSuchAlgorithmException e1)
{
- CRC32 crc = new CRC32();
- crc.update(encode.getBytes());
- byte[] bytes = new byte[4];
- long value = crc.getValue();
- bytes[0] = (byte)(value & 0xFF);
- value >>>= 4;
- bytes[1] = (byte)(value & 0xFF);
- value >>>= 4;
- bytes[2] = (byte)(value & 0xFF);
- value >>>= 4;
- bytes[3] = (byte)(value & 0xFF);
- this.ticketId = new String(Hex.encodeHex(bytes));
+ CRC32 crc = new CRC32();
+ crc.update(encode.getBytes());
+ byte[] bytes = new byte[4];
+ long value = crc.getValue();
+ bytes[0] = (byte) (value & 0xFF);
+ value >>>= 4;
+ bytes[1] = (byte) (value & 0xFF);
+ value >>>= 4;
+ bytes[2] = (byte) (value & 0xFF);
+ value >>>= 4;
+ bytes[3] = (byte) (value & 0xFF);
+ this.ticketId = new String(Hex.encodeHex(bytes));
}
}
}
@@ -337,14 +340,33 @@ public class InMemoryTicketComponentImpl implements TicketComponent
*/
boolean hasExpired()
{
- if (expires && (expiryDate != null) && (expiryDate.compareTo(new Date()) < 0))
- {
- return true;
- }
- else
+ Date now = new Date();
+ switch (expires)
{
+ case AFTER_FIXED_TIME:
+ if ((expiryDate != null) && (expiryDate.compareTo(now) < 0))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ case AFTER_INACTIVITY:
+ if ((expiryDate != null) && (expiryDate.compareTo(now) < 0))
+ {
+ return true;
+ }
+ else
+ {
+ expiryDate = Duration.add(now, validDuration);
+ return false;
+ }
+ case DO_NOT_EXPIRE:
+ default:
return false;
}
+
}
public boolean equals(Object o)
@@ -358,9 +380,7 @@ public class InMemoryTicketComponentImpl implements TicketComponent
return false;
}
Ticket t = (Ticket) o;
- return (this.expires == t.expires)
- && this.expiryDate.equals(t.expiryDate) && this.userName.equals(t.userName)
- && this.ticketId.equals(t.ticketId);
+ return (this.expires == t.expires) && this.expiryDate.equals(t.expiryDate) && this.userName.equals(t.userName) && this.ticketId.equals(t.ticketId);
}
public int hashCode()
@@ -368,7 +388,7 @@ public class InMemoryTicketComponentImpl implements TicketComponent
return ticketId.hashCode();
}
- protected boolean getExpires()
+ protected ExpiryMode getExpires()
{
return expires;
}
@@ -390,10 +410,11 @@ public class InMemoryTicketComponentImpl implements TicketComponent
}
- /**
- * Are tickets single use
- * @param oneOff
- */
+ /**
+ * Are tickets single use
+ *
+ * @param oneOff
+ */
public void setOneOff(boolean oneOff)
{
this.oneOff = oneOff;
@@ -401,6 +422,7 @@ public class InMemoryTicketComponentImpl implements TicketComponent
/**
* Do tickets expire
+ *
* @param ticketsExpire
*/
public void setTicketsExpire(boolean ticketsExpire)
@@ -408,8 +430,19 @@ public class InMemoryTicketComponentImpl implements TicketComponent
this.ticketsExpire = ticketsExpire;
}
+
+ /**
+ * How should tickets expire.
+ * @param exipryMode
+ */
+ public void setExpiryMode(String expiryMode)
+ {
+ this.expiryMode = ExpiryMode.valueOf(expiryMode);
+ }
+
/**
* How long are tickets valid (XML duration as a string)
+ *
* @param validDuration
*/
public void setValidDuration(String validDuration)
@@ -430,12 +463,12 @@ public class InMemoryTicketComponentImpl implements TicketComponent
public String getCurrentTicket(String userName)
{
String ticket = currentTicket.get();
- if(ticket == null)
+ if (ticket == null)
{
return getNewTicket(userName);
}
String ticketUser = getAuthorityForTicket(ticket);
- if(userName.equals(ticketUser))
+ if (userName.equals(ticketUser))
{
return ticket;
}
@@ -449,9 +482,14 @@ public class InMemoryTicketComponentImpl implements TicketComponent
{
clearCurrentSecurityContext();
}
-
+
public static void clearCurrentSecurityContext()
{
currentTicket.set(null);
}
+
+ public enum ExpiryMode
+ {
+ AFTER_INACTIVITY, AFTER_FIXED_TIME, DO_NOT_EXPIRE;
+ }
}
diff --git a/source/java/org/alfresco/repo/workflow/jbpm/ForEachFork.java b/source/java/org/alfresco/repo/workflow/jbpm/ForEachFork.java
index 9785649447..370fa26988 100644
--- a/source/java/org/alfresco/repo/workflow/jbpm/ForEachFork.java
+++ b/source/java/org/alfresco/repo/workflow/jbpm/ForEachFork.java
@@ -47,6 +47,7 @@ import org.springframework.beans.factory.BeanFactory;
public class ForEachFork extends JBPMSpringActionHandler
{
private static final long serialVersionUID = 4643103713602441652L;
+
private ServiceRegistry services;
private Element foreach;
@@ -190,7 +191,7 @@ public class ForEachFork extends JBPMSpringActionHandler
protected String getTokenName(Token parent, String transitionName, int loopIndex)
{
String tokenName = null;
- if (transitionName != null)
+ if (transitionName != null && transitionName.length() > 0)
{
if (!parent.hasChild(transitionName))
{
@@ -210,12 +211,13 @@ public class ForEachFork extends JBPMSpringActionHandler
else
{
// no transition name
- int size = ( parent.getChildren()!=null ? parent.getChildren().size()+1 : 1 );
- tokenName = Integer.toString(size);
+ int size = (parent.getChildren() != null) ? parent.getChildren().size() + 1 : 1;
+ tokenName = "FOREACHFORK" + Integer.toString(size);
}
return tokenName + "." + loopIndex;
}
+
/**
* Fork Transition
*/
diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
index 93619a5f9f..b636e1404f 100644
--- a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
+++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
@@ -84,6 +84,7 @@ import org.hibernate.Session;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.proxy.HibernateProxy;
@@ -1302,7 +1303,6 @@ public class JBPMEngine extends BPMEngine
*/
private Criteria createTaskQueryCriteria(Session session, WorkflowTaskQuery query)
{
- Criteria process = null;
Criteria task = session.createCriteria(TaskInstance.class);
// task id
@@ -1358,35 +1358,9 @@ public class JBPMEngine extends BPMEngine
}
}
- // process active?
- if (query.isActive() != null)
- {
- process = (process == null) ? task.createCriteria("processInstance") : process;
- if (query.isActive())
- {
- process.add(Restrictions.isNull("end"));
- }
- else
- {
- process.add(Restrictions.isNotNull("end"));
- }
- }
+ // process criteria
+ Criteria process = createProcessCriteria(task, query);
- // process id
- if (query.getProcessId() != null)
- {
- process = (process == null) ? task.createCriteria("processInstance") : process;
- process.add(Restrictions.eq("id", getJbpmId(query.getProcessId())));
- }
-
- // process name
- if (query.getProcessName() != null)
- {
- process = (process == null) ? task.createCriteria("processInstance") : process;
- Criteria processDef = process.createCriteria("processDefinition");
- processDef.add(Restrictions.eq("name", query.getProcessName().toPrefixString(namespaceService)));
- }
-
// process custom properties
if (query.getProcessCustomProps() != null)
{
@@ -1398,7 +1372,7 @@ public class JBPMEngine extends BPMEngine
{
// create criteria for process variables
Criteria variables = session.createCriteria(VariableInstance.class);
- variables.setProjection(Property.forName("processInstance"));
+ variables.setProjection(Projections.distinct(Property.forName("processInstance")));
Disjunction values = Restrictions.disjunction();
for (Map.Entry prop : props.entrySet())
{
@@ -1409,6 +1383,9 @@ public class JBPMEngine extends BPMEngine
}
variables.add(values);
+ // note: constrain process variables to same criteria as tasks
+ createProcessCriteria(variables, query);
+
// retrieve list of processes matching specified variables
List processList = variables.list();
Object[] processIds = null;
@@ -1491,6 +1468,49 @@ public class JBPMEngine extends BPMEngine
return task;
}
+ /**
+ * Create process-specific query criteria
+ *
+ * @param root
+ * @param query
+ * @return
+ */
+ private Criteria createProcessCriteria(Criteria root, WorkflowTaskQuery query)
+ {
+ Criteria process = null;
+
+ // process active?
+ if (query.isActive() != null)
+ {
+ process = (process == null) ? root.createCriteria("processInstance") : process;
+ if (query.isActive())
+ {
+ process.add(Restrictions.isNull("end"));
+ }
+ else
+ {
+ process.add(Restrictions.isNotNull("end"));
+ }
+ }
+
+ // process id
+ if (query.getProcessId() != null)
+ {
+ process = (process == null) ? root.createCriteria("processInstance") : process;
+ process.add(Restrictions.eq("id", getJbpmId(query.getProcessId())));
+ }
+
+ // process name
+ if (query.getProcessName() != null)
+ {
+ process = (process == null) ? root.createCriteria("processInstance") : process;
+ Criteria processDef = process.createCriteria("processDefinition");
+ processDef.add(Restrictions.eq("name", query.getProcessName().toPrefixString(namespaceService)));
+ }
+
+ return process;
+ }
+
/**
* Gets a jBPM Task Instance
* @param taskSession jBPM task session