Merged BRANCHES/DEV/V4.1-BUG-FIX to HEAD

44359: Fix for ALF-15236 - JSF - Edit online of html files does not keep the formatting
   44365: Fix for ALF-14653 - Share - Page link created wrongly in wiki
   44366: Fix for ALF-15435 - Incorrect behavior while managing groups via Explorer
   44370: Completion of existing fix for ALF-14568. Also a build fix.
   44372: Fix for ALF-13192 Rules from first folder move to second when delete first folder.
          This bug was caused because up to now, all rules have been firing for system folders, which they shouldn't have been.
   44381: ALF-17094: Merged V4.1.1  (4.1.1.14) to V4.1-BUG-FIX (4.1.3)
          << Code is actually as suggested by Derek rather than code on V4.1.1 >>
      44291: MNT-222 InvalidNodeRefException on user deletion in Share UI 
   44385: Fix for ALF-16006 - MT: Document Library is absent after upgrade from 3.4.x to 4.1.x (eg. 3.4.10 -> 4.1.1)
          Offshore team identified that patches running outside of a TXN were returning an empty list of tenants for MT upgrades
          - fixed after chat to Derek – added a new "big" TenantAdminService with a TXN wrapper interceptor so the AbstractPatch method that generates the list of tenants will also have a txn support regardless of the config set for a particularly patch
          - merged in fix to AVMToADM store patch to respect tenant named objects in paths
   44395: Fix for ALF-17061 Search is failing with Node does not exist: missing://missing/missing(null)
   44402: Merged DEV to V4.1-BUG-FIX
      44347: ALF-16866 : Failure when trying to login as tenant created on 3.4.0 after the upgrade from 3.4.0 to 4.1.2
         The immutableEntityTransactionalCache was made not tenant aware, and fixUserQNames patch now runs after migrateTenantsFromAttrsToTable to fix tenant users, too.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@44521 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2012-12-09 21:26:09 +00:00
parent a10bd9259f
commit 34cc24aad6
8 changed files with 151 additions and 39 deletions

View File

@@ -96,6 +96,8 @@ public class AVMToADMRemoteStorePatch extends AbstractPatch
private static final int MIGRATE_BATCH_THREADS = 4;
private static final int MIGRATE_BATCH_SIZE = 250;
private static final String SEPARATOR = "@";
private Map<String, NodeRef> siteReferenceCache = null;
private SortedMap<String, AVMNodeDescriptor> paths;
private SortedMap<String, AVMNodeDescriptor> retryPaths;
@@ -198,11 +200,14 @@ public class AVMToADMRemoteStorePatch extends AbstractPatch
{
this.retryPaths = new TreeMap<String, AVMNodeDescriptor>();
// get user names that will be used to RunAs and set permissions later
final String systemUser = AuthenticationUtil.getSystemUserName();
// firstly retrieve all AVM paths and descriptors that we need to process
// execute in a single transaction to retrieve the stateless object list
RetryingTransactionCallback<Void> work = new RetryingTransactionCallback<Void>()
RetryingTransactionCallback<String> work = new RetryingTransactionCallback<String>()
{
public Void execute() throws Exception
public String execute() throws Exception
{
long start = System.currentTimeMillis();
paths = retrieveAVMPaths();
@@ -220,21 +225,17 @@ public class AVMToADMRemoteStorePatch extends AbstractPatch
folderPath.add("user");
FileFolderUtil.makeFolders(fileFolderService, surfConfigRef, folderPath, ContentModel.TYPE_FOLDER);
return null;
// return the tenant system user name while in the txn
return tenantAdminService.getDomainUser(systemUser, tenantAdminService.getCurrentUserDomain());
}
};
this.transactionHelper.doInTransaction(work, false, true);
final String tenantSystemUser = this.transactionHelper.doInTransaction(work, false, true);
try
{
// init the siteid to surf-config noderef cache
this.siteReferenceCache = new ConcurrentHashMap<String, NodeRef>(16384);
// get user names that will be used to RunAs and set permissions later
String systemUser = AuthenticationUtil.getSystemUserName();
final String tenantSystemUser = this.tenantAdminService.getDomainUser(
systemUser, this.tenantAdminService.getCurrentUserDomain());
// build a set of unique site names
final Set<String> sites = new HashSet<String>(paths.size());
Matcher matcher;
@@ -421,7 +422,7 @@ public class AVMToADMRemoteStorePatch extends AbstractPatch
if (this.retryPaths.size() != 0)
{
logger.info("Retrying " + this.retryPaths.size() + " paths...");
work = new RetryingTransactionCallback<Void>()
RetryingTransactionCallback<Void> retrywork = new RetryingTransactionCallback<Void>()
{
public Void execute() throws Exception
{
@@ -432,7 +433,7 @@ public class AVMToADMRemoteStorePatch extends AbstractPatch
return null;
}
};
this.transactionHelper.doInTransaction(work, false, true);
this.transactionHelper.doInTransaction(retrywork, false, true);
}
logger.info("Migrated: " + this.paths.size() + " AVM nodes to DM in " + (System.currentTimeMillis()-start) + "ms");
@@ -650,7 +651,16 @@ public class AVMToADMRemoteStorePatch extends AbstractPatch
SortedMap<String, AVMNodeDescriptor> paths = new TreeMap<String, AVMNodeDescriptor>();
String avmPath = this.avmStore + ":" + this.avmRootPath;
String avmPath;
if (this.tenantAdminService.getCurrentUserDomain().isEmpty())
{
avmPath = this.avmStore + ":" + this.avmRootPath;
}
else
{
avmPath = SEPARATOR + this.tenantAdminService.getCurrentUserDomain() + SEPARATOR + this.avmStore + ":" + this.avmRootPath;
}
AVMNodeDescriptor node = this.avmService.lookup(-1, avmPath);
if (node != null)
{

View File

@@ -25,6 +25,7 @@ import static org.junit.Assert.assertNotNull;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -36,6 +37,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.CopyService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@@ -50,6 +52,8 @@ import org.alfresco.util.test.junitrules.ApplicationContextInit;
import org.alfresco.util.test.junitrules.RunAsFullyAuthenticatedRule;
import org.alfresco.util.test.junitrules.TemporaryNodes;
import org.alfresco.util.test.junitrules.TemporarySites;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
@@ -68,6 +72,8 @@ import org.springframework.context.ApplicationContext;
*/
public class MiscellaneousRulesTest
{
private static final Log log = LogFactory.getLog(MiscellaneousRulesTest.class);
// Static JUnit Rules
public static ApplicationContextInit APP_CTXT_INIT = new ApplicationContextInit();
public static AlfrescoPerson TEST_USER = new AlfrescoPerson(APP_CTXT_INIT);
@@ -305,4 +311,74 @@ public class MiscellaneousRulesTest
}
});
}
@Test public void alf13192_rulesFromFirstFolderMoveToSecondWhenDeleteFirstFolder() throws Exception
{
final NodeRef testSiteDocLib = TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<NodeRef>()
{
public NodeRef execute() throws Throwable
{
return SITE_SERVICE.getContainer(testSite.getShortName(), SiteService.DOCUMENT_LIBRARY);
}
});
assertNotNull("Null doclib", testSiteDocLib);
final NodeRef folder1 = testNodes.createFolder(testSiteDocLib, "folder 1", TEST_USER.getUsername());
final NodeRef folder2 = testNodes.createFolder(testSiteDocLib, "folder 2", TEST_USER.getUsername());
// Put a rule on folder1.
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
// Clashes with the JUnit annotation @Rule
org.alfresco.service.cmr.rule.Rule rule = new org.alfresco.service.cmr.rule.Rule();
rule.setRuleType(RuleType.OUTBOUND);
rule.applyToChildren(false);
rule.setRuleDisabled(false);
rule.setTitle("Copy to folder2");
rule.setExecuteAsynchronously(false);
Map<String, Serializable> params = new HashMap<String, Serializable>();
params.put(CopyActionExecuter.PARAM_DESTINATION_FOLDER, folder2);
Action copyAction = ACTION_SERVICE.createAction("copy", params);
rule.setAction(copyAction);
RULE_SERVICE.saveRule(folder1, rule);
// While we're here, let's log some information about the rules.
List<ChildAssociationRef> ruleFolders = NODE_SERVICE.getChildAssocs(folder1, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER);
assertEquals(1, ruleFolders.size());
log.debug("Rule SystemFolder noderef is " + ruleFolders.get(0).getChildRef());
return null;
}
});
// Now delete folder1.
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
log.debug("About to delete the ruled folder: " + folder1);
NODE_SERVICE.deleteNode(folder1);
return null;
}
});
// folder2 should have no rules-related elements
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
assertFalse(RULE_SERVICE.hasRules(folder2));
assertFalse(NODE_SERVICE.hasAspect(folder2, RuleModel.ASPECT_RULES));
return null;
}
});
}
}

View File

@@ -53,6 +53,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
IGNORE_TYPES.add(ContentModel.TYPE_THUMBNAIL);
// Workaround to prevent rules running on cm:rating nodes (which happened for 'liked' folders ALF-8308 & ALF-8382)
IGNORE_TYPES.add(ContentModel.TYPE_RATING);
IGNORE_TYPES.add(ContentModel.TYPE_SYSTEM_FOLDER);
IGNORE_ASPECTS = new HashSet<QName>(13);
IGNORE_ASPECTS.add(ContentModel.ASPECT_TEMPORARY);

View File

@@ -49,6 +49,8 @@ public class SolrJSONResultSet implements ResultSet
private ArrayList<Pair<Long, Float>> page;
private ArrayList<NodeRef> refs;
private ResultSetMetaData rsmd;
private Long status;
@@ -89,18 +91,23 @@ public class SolrJSONResultSet implements ResultSet
int numDocs = docs.length();
page = new ArrayList<Pair<Long, Float>>(numDocs);
refs = new ArrayList<NodeRef>(numDocs);
for(int i = 0; i < numDocs; i++)
{
JSONObject doc = docs.getJSONObject(i);
JSONArray dbids = doc.getJSONArray("DBID");
Long dbid = dbids.getLong(0);
Float score = Float.valueOf(doc.getString("score"));
page.add(new Pair<Long, Float>(dbid, score));
for(Iterator it = doc.keys(); it.hasNext(); /* */)
NodeRef nodeRef = nodeService.getNodeRef(dbid);
if(nodeRef != null)
{
String key = (String)it.next();
page.add(new Pair<Long, Float>(dbid, score));
refs.add(nodeRef);
}
}
if(json.has("facet_counts"))
@@ -212,16 +219,7 @@ public class SolrJSONResultSet implements ResultSet
@Override
public NodeRef getNodeRef(int n)
{
// TODO: lost nodes?
NodeRef nodeRef = nodeService.getNodeRef(page.get(n).getFirst());
if(nodeRef != null)
{
return nodeRef;
}
else
{
return new NodeRef(new StoreRef("missing", "missing"), "missing");
}
return refs.get(n);
}
/*
@@ -231,12 +229,7 @@ public class SolrJSONResultSet implements ResultSet
@Override
public List<NodeRef> getNodeRefs()
{
ArrayList<NodeRef> refs = new ArrayList<NodeRef>(page.size());
for(int i = 0; i < page.size(); i++ )
{
refs.add( getNodeRef(i));
}
return refs;
return Collections.unmodifiableList(refs);
}
/*

View File

@@ -73,6 +73,7 @@ import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.invitation.InvitationException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
@@ -1282,11 +1283,14 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
final List<PersonInfo> personInfos = new ArrayList<PersonInfo>(nodeRefs.size());
for (NodeRef nodeRef : nodeRefs)
{
Map<QName, Serializable> props = nodeService.getProperties(nodeRef);
personInfos.add(new PersonInfo(nodeRef,
(String)props.get(ContentModel.PROP_USERNAME),
(String)props.get(ContentModel.PROP_FIRSTNAME),
(String)props.get(ContentModel.PROP_LASTNAME)));
if (nodeService.exists(nodeRef))
{
Map<QName, Serializable> props = nodeService.getProperties(nodeRef);
personInfos.add(new PersonInfo(nodeRef,
(String)props.get(ContentModel.PROP_USERNAME),
(String)props.get(ContentModel.PROP_FIRSTNAME),
(String)props.get(ContentModel.PROP_LASTNAME)));
}
}
return new PagingResults<PersonInfo>()