mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
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:
@@ -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)
|
||||
{
|
||||
|
@@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -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>()
|
||||
|
Reference in New Issue
Block a user