Merged V3.1 to HEAD

13424: ETHREEOH-1242: Sample LDAP authentication config breaks site invites in Share
   13427: Fixes for ETHREEOH-1157: Propagate exceptions using ReportedException
   13428: Fix ETHREEOH-1493: Upgrade from 2.1-A to 3.1 uses incorrect patch id and fixes_to_schema
   13429: Specific fix for ETHREEOH-1157: duplicate/triplicate users not properly prohibited
   13436: Merged V2.2 to V3.1
      13435: Merged V2.1 to V2.2  
         12307: Merged DEV/V2.1SP7 to 2.1 
            11927: ETWOONE-396 
            12112: ETWOONE-396
   13437: Fixed ETHREEOH-1498: Mismatched closing XML tag in ehcache-custom.xml.sample.cluster
   13439: Fix for ETHREEOH-1157: JSF Dialogs Absorbing Exceptions
   13456: Fixed ETHREEOH-1472: Changes to systemBootstrap cause bootstrapping ACP's not to work
   13469: Upgrade patch to update internal version2Store counter (follow-on fix for ETHREEOH-1540)
   13491: Chaining example for DOC-84
   13492: Fixed paths in zip file
   13494: Fixed GenericBootstrapPatch when overriding bootstrap views
   13495: Added @version javadoc
   13496: Minor logging updates
   13497: Fixed ETHREEOH-1431: Authentication case sensitivity switch doesn't work
   13500: Temporary fix for Sharepoint issue raised last week
   13502: ETHREEOH-1575: It's impossible to create Change Request task
   13511: Fix for ETHREEOH-1549: Impossible to create HTML web content
   13529: Fix for ETHREEOH-1595
   13531: Fix for ETHREEOH-1607: Error on chaining example xml - malformed comment
   13537: Build fix ... exclude the system user from auto creation
   13538: Build Fix - further contraints to aviod auto-creation of guest
   ___________________________________________________________________
   Modified: svn:mergeinfo
      Merged /alfresco/BRANCHES/V2.1:r12307
      Merged /alfresco/BRANCHES/V2.2:r13435
      Merged /alfresco/BRANCHES/V3.1:r
                   13424,13427-13429,13436-13437,13439,13442-13450,13452,13454-13456,
                   13469-13473,13475-13476,13479-13480,13491-13500,13502,13511,13529-13538


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13619 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2009-03-13 01:52:39 +00:00
parent fec1149d8c
commit 65b8cd4a8b
27 changed files with 1829 additions and 1548 deletions

View File

@@ -24,7 +24,7 @@
*/
package org.alfresco.repo.admin.patch.impl;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@@ -118,7 +118,8 @@ public class GenericBootstrapPatch extends AbstractPatch
}
}
String path = bootstrapView.getProperty("path");
List<Properties> bootstrapViews = Collections.singletonList(bootstrapView);
List<Properties> bootstrapViews = new ArrayList<Properties>(1);
bootstrapViews.add(bootstrapView);
// modify the bootstrapper
importerBootstrap.setBootstrapViews(bootstrapViews);
importerBootstrap.setUseExistingStore(true); // allow import into existing store

View File

@@ -0,0 +1,63 @@
/*
* 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
* 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.admin.patch.impl;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.admin.patch.AbstractPatch;
import org.alfresco.repo.version.Version2Model;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.repo.version.common.counter.VersionCounterService;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* Update internal version2Store counter if needed (eg. affects upgrades from 2.x to 3.0.1, will not affect upgrades from 2.x to 3.1.0)
*/
public class MigrateVersionStoreUpdateCounterPatch extends AbstractPatch
{
private static final String MSG_SUCCESS = "patch.migrateVersionStoreUpdateCounter.result";
private VersionCounterService versionCounterService;
public void setVersionCounterService(VersionCounterService versionCounterService)
{
this.versionCounterService = versionCounterService;
}
@Override
protected String applyInternal() throws Exception
{
int oldV1count = versionCounterService.currentVersionNumber(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID));
int oldV2count = versionCounterService.currentVersionNumber(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, Version2Model.STORE_ID));
int newV2count = (oldV1count+oldV2count);
versionCounterService.setVersionNumber(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, Version2Model.STORE_ID), newV2count);
// build the result message
String msg = I18NUtil.getMessage(MSG_SUCCESS, "oldV1count="+oldV1count+",oldV2count="+oldV2count+",newV2count="+newV2count);
// done
return msg;
}
}

View File

@@ -200,7 +200,7 @@ public class AVMExpiredContentProcessor
};
// perform the work as the system user
AuthenticationUtil.runAs(authorisedWork, AuthenticationUtil.getAdminRoleName());
AuthenticationUtil.runAs(authorisedWork, AuthenticationUtil.getAdminUserName());
// now we know everything worked ok, let the virtualisation server
// know about all the new workflow sandboxes created (just the main stores)

View File

@@ -461,7 +461,8 @@
]]>
</query>
<sql-query name="person.getPerson">
<!-- Lowercase: ETHREEOH-1431 and ETWOTWO-1012 -->
<sql-query name="person.getPersonIgnoreCase">
<return alias="n" class="org.alfresco.repo.domain.hibernate.NodeImpl"/>
SELECT
{n.*}
@@ -471,15 +472,14 @@
JOIN alf_child_assoc c on c.child_node_id = n.id
JOIN alf_store s on s.id = n.store_id
WHERE
c.qname_localname = :userName1 AND
c.qname_localname = :userNameLowerCase AND
p.qname_id = :qnamePropId AND
p.string_value = :userName2 AND
n.type_qname_id = :qnameTypeId AND
n.node_deleted = :False AND
s.protocol = :storeProtocol AND
s.identifier = :storeIdentifier
</sql-query>
<sql-query name="person.getAllPeople">
<return alias="n" class="org.alfresco.repo.domain.hibernate.NodeImpl"/>
SELECT

View File

@@ -40,6 +40,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
@@ -56,7 +57,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
* The abstract class keeps track of support for guest login
*/
private Boolean allowGuestLogin = null;
private TenantService tenantService;
private PersonService personService;
@@ -65,6 +66,8 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
private TransactionService transactionService;
private boolean autoCreatePeopleOnLogin = true;
public AbstractAuthenticationComponent()
{
super();
@@ -79,10 +82,10 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
{
this.allowGuestLogin = allowGuestLogin;
}
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
this.tenantService = tenantService;
}
public void setPersonService(PersonService personService)
@@ -120,6 +123,16 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
return personService;
}
public boolean isAutoCreatePeopleOnLogin()
{
return autoCreatePeopleOnLogin;
}
public void setAutoCreatePeopleOnLogin(boolean autoCreatePeopleOnLogin)
{
this.autoCreatePeopleOnLogin = autoCreatePeopleOnLogin;
}
public void authenticate(String userName, char[] password) throws AuthenticationException
{
// Support guest login from the login screen
@@ -148,7 +161,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
public Authentication setCurrentUser(String userName, UserNameValidationMode validationMode)
{
switch(validationMode)
switch (validationMode)
{
case NONE:
return setCurrentUserImpl(userName);
@@ -157,7 +170,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
return setCurrentUser(userName);
}
}
public Authentication setCurrentUser(final String userName) throws AuthenticationException
{
if (isSystemUserName(userName))
@@ -232,8 +245,8 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
throw new AuthenticationException(ae.getMessage(), ae);
}
finally
{
// Support for logging tenantdomain / username (via log4j NDC)
{
// Support for logging tenantdomain / username (via log4j NDC)
AuthenticationUtil.logNDC(userName);
}
}
@@ -283,8 +296,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
}
/**
* Set the system user as the current user
* note: for MT, will set to default domain only
* Set the system user as the current user note: for MT, will set to default domain only
*
* @return Authentication
*/
@@ -294,8 +306,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
}
/**
* Get the name of the system user
* note: for MT, will get system for default domain only
* Get the name of the system user note: for MT, will get system for default domain only
*
* @return String
*/
@@ -303,20 +314,19 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
{
return AuthenticationUtil.SYSTEM_USER_NAME;
}
/**
* Is this the system user ?
*
*
* @return boolean
*/
*/
public boolean isSystemUserName(String userName)
{
return (getSystemUserName().equals(tenantService.getBaseNameUser(userName)));
return (getSystemUserName().equals(tenantService.getBaseNameUser(userName)));
}
/**
* Get the name of the Guest User
* note: for MT, will get guest for default domain only
* Get the name of the Guest User note: for MT, will get guest for default domain only
*
* @return String
*/
@@ -327,18 +337,17 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
private String getGuestUserName(String tenantDomain)
{
return tenantService.getDomainUser(getGuestUserName(), tenantDomain);
return tenantService.getDomainUser(getGuestUserName(), tenantDomain);
}
/**
* Set the guest user as the current user.
* note: for MT, will set to default domain only
* Set the guest user as the current user. note: for MT, will set to default domain only
*/
public Authentication setGuestUserAsCurrentUser() throws AuthenticationException
{
return setGuestUserAsCurrentUser(TenantService.DEFAULT_DOMAIN);
return setGuestUserAsCurrentUser(TenantService.DEFAULT_DOMAIN);
}
/**
* Set the guest user as the current user.
*/
@@ -359,7 +368,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
{
if (allowGuestLogin.booleanValue())
{
return setCurrentUser(getGuestUserName(tenantDomain));
return setCurrentUser(getGuestUserName(tenantDomain));
}
else
{
@@ -368,10 +377,10 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
}
}
private boolean isGuestUserName(String userName)
{
return (PermissionService.GUEST_AUTHORITY.equalsIgnoreCase(tenantService.getBaseNameUser(userName)));
return (PermissionService.GUEST_AUTHORITY.equalsIgnoreCase(tenantService.getBaseNameUser(userName)));
}
protected abstract boolean implementationAllowsGuestLogin();
@@ -447,7 +456,8 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
NodeRef userNode = personService.getPerson(userName);
if (userNode != null)
{
// Get the person name and use that as the current user to line up with permission checks
// Get the person name and use that as the current user to line up with permission
// checks
return (String) nodeService.getProperty(userNode, ContentModel.PROP_USERNAME);
}
else
@@ -458,12 +468,23 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
}
else
{
if (autoCreatePeopleOnLogin && (userName != null) && !userName.equals(AuthenticationUtil.getSystemUserName()))
{
if (personService.createMissingPeople())
{
AuthorityType authorityType = AuthorityType.getAuthorityType(userName);
if (authorityType == AuthorityType.USER)
{
personService.getPerson(userName);
}
}
}
// Get user name
return userName;
}
}
}
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantService.getUserDomain(userName)));
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantService.getUserDomain(userName)));
return setCurrentUserImpl(name);
}
catch (AuthenticationException ae)

View File

@@ -245,7 +245,7 @@ public class AuthenticationTest extends TestCase
userName = pubAuthenticationService.getCurrentUserName();
assertEquals("andy", userName);
// get Person
assertFalse(pubPersonService.personExists(userName));
assertTrue(pubPersonService.personExists(userName));
AuthenticationUtil.runAs(new RunAsWork() {

View File

@@ -51,7 +51,7 @@ import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao
{
private static final String QUERY_PERSON_GET_PERSON = "person.getPerson";
private static final String QUERY_PERSON_GET_PERSON_IGNORE_CASE = "person.getPersonIgnoreCase";
private static final String QUERY_PERSON_GET_ALL_PEOPLE = "person.getAllPeople";
@@ -75,9 +75,32 @@ public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao
this.tenantService = tenantService;
}
public void init()
{
qNamePropId = qnameDAO.getOrCreateQName(ContentModel.PROP_USERNAME).getFirst();
qNameTypeId = qnameDAO.getOrCreateQName(ContentModel.TYPE_PERSON).getFirst();
}
@SuppressWarnings("unchecked")
public List<NodeRef> getPersonOrNull(final String searchUserName, UserNameMatcher matcher)
{
/*
* Related JIRA:
* https://issues.alfresco.com/jira/browse/MOB-387
* https://issues.alfresco.com/jira/browse/ETHREEOH-1431
* https://issues.alfresco.com/jira/browse/ETWOTWO-1012
*
* When usernames are case-insensitive, it could happen that the DB is NOT.
* DB queries should therefore return values regardless of the DB collation.
* The original, case-preserving username is stored with the node properties.
* To solve the query issue, a LOWERCASE version of the username is stored on
* the path (alf_child_assoc.qname_localname). This is queried for using the
* lowercase version of the searched-for username. The case results pruning
* is done (as it always was) as a post-search task.
*
* Note that the upgrade scripts had to change to force lowercase names as well.
*/
final StoreRef personStoreRef = tenantService.getName(storeRef);
List<NodeRef> answer = new ArrayList<NodeRef>();
@@ -86,11 +109,10 @@ public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao
{
public Object doInHibernate(Session session)
{
SQLQuery query = (SQLQuery) session.getNamedQuery(QUERY_PERSON_GET_PERSON);
SQLQuery query = (SQLQuery) session.getNamedQuery(QUERY_PERSON_GET_PERSON_IGNORE_CASE);
query.setParameter("qnamePropId", qNamePropId);
query.setParameter("qnameTypeId", qNameTypeId);
query.setParameter("userName1", searchUserName);
query.setParameter("userName2", searchUserName);
query.setParameter("userNameLowerCase", searchUserName.toLowerCase()); // Lowercase: ETHREEOH-1431
query.setParameter("False", Boolean.FALSE);
query.setParameter("storeProtocol", personStoreRef.getProtocol());
query.setParameter("storeIdentifier", personStoreRef.getIdentifier());
@@ -121,12 +143,6 @@ public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao
}
public void init()
{
qNamePropId = qnameDAO.getOrCreateQName(ContentModel.PROP_USERNAME).getFirst();
qNameTypeId = qnameDAO.getOrCreateQName(ContentModel.TYPE_PERSON).getFirst();
}
@SuppressWarnings("unchecked")
public Set<NodeRef> getAllPeople()
{

View File

@@ -68,7 +68,6 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.GUID;
import org.alfresco.util.Pair;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -596,7 +595,11 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
properties.put(ContentModel.PROP_USERNAME, userName);
properties.put(ContentModel.PROP_SIZE_CURRENT, 0L);
NodeRef personRef = nodeService.createNode(getPeopleContainer(), ContentModel.ASSOC_CHILDREN, QName.createQName("cm", userName, namespacePrefixResolver), ContentModel.TYPE_PERSON,
NodeRef personRef = nodeService.createNode(
getPeopleContainer(),
ContentModel.ASSOC_CHILDREN,
QName.createQName("cm", userName.toLowerCase(), namespacePrefixResolver), // Lowercase: ETHREEOH-1431
ContentModel.TYPE_PERSON,
properties).getChildRef();
return personRef;
}

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
@@ -27,16 +27,12 @@ package org.alfresco.repo.security.person;
/**
* Check if userNames match
* @author andyh
*
* @since 3.1
*/
public interface UserNameMatcher
{
/**
* Do the two user names match?
*
* @param userName1
* @param userName2
* @return
*/
public boolean matches(String userName1, String userName2);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 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
@@ -27,12 +27,13 @@ package org.alfresco.repo.version;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
@@ -40,6 +41,7 @@ import org.alfresco.repo.policy.PolicyScope;
import org.alfresco.repo.version.common.VersionHistoryImpl;
import org.alfresco.repo.version.common.VersionImpl;
import org.alfresco.repo.version.common.VersionUtil;
import org.alfresco.repo.version.common.VersionHistoryImpl.VersionComparatorAsc;
import org.alfresco.service.cmr.repository.AspectMissingException;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -67,6 +69,8 @@ public class Version2ServiceImpl extends VersionServiceImpl implements VersionSe
private PermissionService permissionService;
private static Comparator<Version> versionComparatorAsc = new VersionComparatorAsc();
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
@@ -607,27 +611,25 @@ public class Version2ServiceImpl extends VersionServiceImpl implements VersionSe
VersionHistory versionHistory = null;
List<ChildAssociationRef> versionsAssoc = this.dbNodeService.getChildAssocs(versionHistoryRef, Version2Model.CHILD_QNAME_VERSIONS, RegexQNamePattern.MATCH_ALL);
Map<Integer,NodeRef> versionHistoryMap = new HashMap<Integer,NodeRef>(versionsAssoc.size());
for (ChildAssociationRef versionAssoc : versionsAssoc)
{
String localName = versionAssoc.getQName().getLocalName();
if (localName.indexOf(Version2Model.CHILD_VERSIONS+"-") != -1) // TODO - could remove this belts-and-braces, should match correctly above !
{
int versionNumber = Integer.parseInt(localName.substring((Version2Model.CHILD_VERSIONS+"-").length()));
versionHistoryMap.put(versionNumber, versionAssoc.getChildRef());
}
}
Map<Integer,NodeRef> sortedMap = new TreeMap<Integer,NodeRef>(versionHistoryMap);
List<Version> versions = new ArrayList<Version>(versionsAssoc.size());
for (ChildAssociationRef versionAssoc : versionsAssoc)
{
String localName = versionAssoc.getQName().getLocalName();
if (localName.indexOf(Version2Model.CHILD_VERSIONS+"-") != -1) // TODO - could remove this belts-and-braces, should match correctly above !
{
versions.add(getVersion(versionAssoc.getChildRef()));
}
}
Collections.sort(versions, versionComparatorAsc);
// Build the version history object
boolean isRoot = true;
Version preceeding = null;
for (NodeRef versionRef : sortedMap.values())
for (Version version : versions)
{
Version version = getVersion(versionRef);
if (isRoot == true)
{
versionHistory = new VersionHistoryImpl(version);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 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

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
@@ -26,14 +26,19 @@ package org.alfresco.repo.version;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.version.common.counter.VersionCounterService;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.namespace.QName;
@@ -55,6 +60,8 @@ public class VersionMigratorTest extends BaseVersionStoreTest
protected VersionMigrator versionMigrator;
protected PolicyComponent policyComponent;
protected DictionaryService dictionaryService;
protected CheckOutCheckInService cociService;
protected VersionCounterService versionCounterService;
public VersionMigratorTest()
{
@@ -71,6 +78,9 @@ public class VersionMigratorTest extends BaseVersionStoreTest
this.version2Service = (Version2ServiceImpl)applicationContext.getBean("versionService");
this.versionNodeService = (NodeService)applicationContext.getBean("versionNodeService"); // note: auto-switches between V1 and V2
this.cociService = (CheckOutCheckInService)applicationContext.getBean("CheckoutCheckinService");
this.versionCounterService = (VersionCounterService)applicationContext.getBean("versionCounterService");
// Version1Service is used to create the version nodes in Version1Store (workspace://lightWeightVersionStore)
version1Service.setDbNodeService(dbNodeService);
version1Service.setNodeService(dbNodeService);
@@ -243,4 +253,100 @@ public class VersionMigratorTest extends BaseVersionStoreTest
logger.info("testMigrateMultipleVersions: Migrated from oldVHNodeRef = " + oldVHNodeRef + " to newVHNodeRef = " + newVHNodeRef);
}
public void test_ETHREEOH_1540() throws Exception
{
// Create the node used for tests
NodeRef nodeRef = nodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("{test}MyVersionableNode"),
TEST_TYPE_QNAME,
this.nodeProperties).getChildRef();
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TITLED, null);
nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, "name");
// Add the initial content to the node
ContentWriter contentWriter = this.contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
contentWriter.setMimetype("text/plain");
contentWriter.setEncoding("UTF-8");
contentWriter.putContent("my content");
VersionHistory vh1 = version1Service.getVersionHistory(nodeRef);
assertNull(vh1);
version2Service.useDeprecatedV1 = true;
// note: for testing only - not recommended !!!
versionCounterService.setVersionNumber(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID), 100);
// Add the version aspect to the created node
nodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, null);
vh1 = version1Service.getVersionHistory(nodeRef);
assertNull(vh1);
NodeRef workingCopyNodeRef = cociService.checkout(nodeRef);
vh1 = version1Service.getVersionHistory(nodeRef);
assertNull(vh1);
int v1count = 3;
for (int i = 1; i <= v1count; i++)
{
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>();
versionProperties.put(Version.PROP_DESCRIPTION, "This is a test checkin - " + i);
cociService.checkin(workingCopyNodeRef, versionProperties);
vh1 = version1Service.getVersionHistory(nodeRef);
assertEquals(i, vh1.getAllVersions().size());
workingCopyNodeRef = cociService.checkout(nodeRef);
vh1 = version1Service.getVersionHistory(nodeRef);
assertEquals(i, vh1.getAllVersions().size());
}
NodeRef oldVHNodeRef = version1Service.getVersionHistoryNodeRef(nodeRef);
version2Service.useDeprecatedV1 = false;
// Migrate and delete old version history !
NodeRef versionedNodeRef = versionMigrator.v1GetVersionedNodeRef(oldVHNodeRef);
//int nextVersionNumber = versionCounterService.nextVersionNumber(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID));
//versionCounterService.setVersionNumber(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, Version2Model.STORE_ID), nextVersionNumber);
// to force the error: https://issues.alfresco.com/jira/browse/ETHREEOH-1540
versionCounterService.setVersionNumber(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, Version2Model.STORE_ID), 0);
NodeRef newVHNodeRef = versionMigrator.migrateVersionHistory(oldVHNodeRef, versionedNodeRef);
versionMigrator.v1DeleteVersionHistory(oldVHNodeRef);
VersionHistory vh2 = version2Service.getVersionHistory(nodeRef);
assertEquals(v1count, vh2.getAllVersions().size());
int v2count = 3;
for (int i = 1; i <= v2count; i++)
{
versionProperties = new HashMap<String, Serializable>();
versionProperties.put(Version.PROP_DESCRIPTION, "This is a test checkin - " + (v1count + i));
cociService.checkin(workingCopyNodeRef, versionProperties);
vh2 = version2Service.getVersionHistory(nodeRef);
assertEquals((v1count + i), vh2.getAllVersions().size());
workingCopyNodeRef = cociService.checkout(nodeRef);
vh2 = version2Service.getVersionHistory(nodeRef);
assertEquals((v1count + i), vh2.getAllVersions().size());
}
logger.info("testMigrateOneCheckoutVersion: Migrated from oldVHNodeRef = " + oldVHNodeRef + " to newVHNodeRef = " + newVHNodeRef);
}
}

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
@@ -36,6 +36,7 @@ import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionDoesNotExistException;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionServiceException;
import org.alfresco.util.VersionNumber;
/**
* Version History implementation.
@@ -72,7 +73,7 @@ public class VersionHistoryImpl implements VersionHistory
/*
* Versions ordered by creation date (descending)
*/
private static VersionComparator versionComparator = new VersionComparator();
private static Comparator<Version> versionComparatorDesc = new VersionComparatorDesc();
private List<Version> versions = new ArrayList<Version>();
/**
@@ -124,7 +125,7 @@ public class VersionHistoryImpl implements VersionHistory
*/
public Collection<Version> getAllVersions()
{
Collections.sort(versions, versionComparator);
Collections.sort(versions, versionComparatorDesc);
return versions;
}
@@ -223,13 +224,38 @@ public class VersionHistoryImpl implements VersionHistory
*
* Note: Descending create date order
*/
public static class VersionComparator implements Comparator<Version>, Serializable
public static class VersionComparatorDesc implements Comparator<Version>, Serializable
{
private static final long serialVersionUID = 6227528170880231770L;
public int compare(Version v1, Version v2)
{
return v2.getCreatedDate().compareTo(v1.getCreatedDate());
int result = v2.getCreatedDate().compareTo(v1.getCreatedDate());
if (result == 0)
{
result = new VersionNumber(v2.getVersionLabel()).compareTo(new VersionNumber(v1.getVersionLabel()));
}
return result;
}
}
/**
* Version Comparator
*
* Note: Ascending create date order
*/
public static class VersionComparatorAsc implements Comparator<Version>, Serializable
{
private static final long serialVersionUID = 6227528170880231770L;
public int compare(Version v1, Version v2)
{
int result = v1.getCreatedDate().compareTo(v2.getCreatedDate());
if (result == 0)
{
result = new VersionNumber(v1.getVersionLabel()).compareTo(new VersionNumber(v2.getVersionLabel()));
}
return result;
}
}