mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-07 18:25:23 +00:00
Merged V4.1-BUG-FIX to HEAD
44765: ALF-17164: Fix failing build in case build is not run in continuous mode 44769: ALF-17097 60k Site Performance: Admin Console | Groups | Browse Groups (include sys groups): Results isn't appeared. - Group page now supports search and browse of large volumes of groups. Tested up to 300,000 sites (60k sites). Previously this would not return. - In order to support large volumes of groups it is not practical to search for all root groups. A functional change has taken place to fix this issue. [Browse] (which initially displayed only root groups) now uses the search value entered by the user and the same query as [Search]. It could be argued that the browse functionality was not very practical anyway if there were a large number of root groups as the user would have to page through all the pages one at a time to get to the required group in order to add a new sub group. As a result of this change it is now possible to get to the required group much faster. As the 'browse' function uses the search value and Include System Groups checkbox (it already used the checkbox value) it made little sense to revert to the Search results when either of these is changed. As this was taking place, this has now been changed too. The [Search] and [Browse] options both now use the authority canned query which has been enhanced to use the sortBy field supplied by the UI. - Uses the authority canned query for [Search] and [Browse] searches on the Groups page. - Canned query may sort on "shortName", "displayName" or "authorityName" - Filter on displayName uses regular expressions to support ? and * wildcards - Canned query returns fewer (unused) columns to speed up fetch time. - Canned query no longer joins to alf_store as none of the values were used. 44772: CIFS Gedit support - rename open files. 44776: ALF-17164: Fix failing build in case build is not run in continuous mode - move generation of version.properties out of continuous mode git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@44790 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
parent
6bb340048a
commit
c21a3d2740
@ -54,7 +54,7 @@
|
||||
<!-- This bean uses the authorityLookupCache configured in cache-context.xml -->
|
||||
<!-- -->
|
||||
|
||||
<bean id="authorityDAO" class="org.alfresco.repo.security.authority.AuthorityDAOBridgeTableImpl" init-method="init">
|
||||
<bean id="authorityDAO" class="org.alfresco.repo.security.authority.AuthorityDAOImpl" init-method="init">
|
||||
<property name="storeUrl">
|
||||
<value>${spaces.store}</value>
|
||||
</property>
|
||||
|
@ -14,7 +14,6 @@
|
||||
<id property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||
<result property="authorityDisplayName" column="authority_display_name" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||
<result property="authorityName" column="authority_name" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||
<association property="node" resultMap="alfresco.node.result_Node"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="result_AuthorityBridgeLink" type="AuthorityBridgeLink">
|
||||
@ -34,15 +33,11 @@
|
||||
<select id="select_GetAuthoritiesCannedQuery" parameterType="AuthorityInfo" resultMap="result_AuthorityInfo">
|
||||
select
|
||||
childNode.id as id,
|
||||
childStore.protocol as protocol,
|
||||
childStore.identifier as identifier,
|
||||
childNode.uuid as uuid,
|
||||
adn.string_value as authority_display_name,
|
||||
assoc.qname_localname as authority_name <!-- see note -->
|
||||
from
|
||||
alf_child_assoc assoc
|
||||
join alf_node childNode on (childNode.id = assoc.child_node_id)
|
||||
join alf_store childStore on (childStore.id = childNode.store_id)
|
||||
left join alf_node_properties adn on (adn.node_id = childNode.id and adn.qname_id = #{authorityDisplayNameQNameId})
|
||||
where
|
||||
assoc.parent_node_id = #{parentNodeId}
|
||||
|
@ -754,6 +754,7 @@
|
||||
org.alfresco.service.cmr.security.AuthorityService.isAdminAuthority=ACL_ALLOW
|
||||
org.alfresco.service.cmr.security.AuthorityService.isGuestAuthority=ACL_ALLOW
|
||||
org.alfresco.service.cmr.security.AuthorityService.getAuthorities=ACL_ALLOW
|
||||
org.alfresco.service.cmr.security.AuthorityService.getAuthoritiesInfo=ACL_ALLOW
|
||||
org.alfresco.service.cmr.security.AuthorityService.getAuthoritiesForUser=ACL_METHOD.ROLE_ADMINISTRATOR
|
||||
org.alfresco.service.cmr.security.AuthorityService.getAllAuthorities=ACL_ALLOW
|
||||
org.alfresco.service.cmr.security.AuthorityService.findAuthorities=ACL_ALLOW
|
||||
|
@ -135,19 +135,13 @@
|
||||
|
||||
<property name="scenarios">
|
||||
<list>
|
||||
<!-- Mac Finder Drag and Drop -->
|
||||
<bean id="deleteRestoreShuffle" class="org.alfresco.filesys.repo.rules.ScenarioDeleteRestore">
|
||||
|
||||
<!-- Mac Mountain Lion Preview / Mac Drag and Drop / Gedit -->
|
||||
<bean id="deleteDeleteRenameOrCreateShuffle" class="org.alfresco.filesys.repo.rules.ScenarioDeleteRenameOrCreate">
|
||||
<property name="pattern"><value>.*</value></property>
|
||||
<property name="timeout"><value>60000</value></property>
|
||||
<property name="ranking"><value>MEDIUM</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- Mac Mountain Lion Preview -->
|
||||
<bean id="deleteDeleteOnCloseRenameShuffle" class="org.alfresco.filesys.repo.rules.ScenarioDeleteOnCloseRename">
|
||||
<property name="pattern"><value>.*</value></property>
|
||||
<property name="timeout"><value>20000</value></property>
|
||||
<property name="ranking"><value>MEDIUM</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- Open/Close reference counting -->
|
||||
<bean id="openFileScenario" class="org.alfresco.filesys.repo.rules.ScenarioOpenFile">
|
||||
|
@ -269,7 +269,7 @@ public class ContentDiskDriverTest extends TestCase
|
||||
int openAction = FileAction.CreateNotExist;
|
||||
|
||||
|
||||
final String FILE_NAME="testCreateFileA.new";
|
||||
final String FILE_NAME="testCreateFile.new";
|
||||
final String FILE_PATH="\\"+FILE_NAME;
|
||||
|
||||
FileOpenParams params = new FileOpenParams(FILE_PATH, openAction, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
|
||||
@ -366,7 +366,7 @@ public class ContentDiskDriverTest extends TestCase
|
||||
* Step 1 : Create a new file in read/write mode and add some content.
|
||||
*/
|
||||
int openAction = FileAction.CreateNotExist;
|
||||
String FILE_PATH="\\testDeleteFileX.new";
|
||||
String FILE_PATH="\\testDeleteFile.new";
|
||||
|
||||
FileOpenParams params = new FileOpenParams(FILE_PATH, openAction, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
|
||||
|
||||
@ -5679,7 +5679,7 @@ public class ContentDiskDriverTest extends TestCase
|
||||
*/
|
||||
public void testMacDragAndDrop() throws Exception
|
||||
{
|
||||
logger.debug("testMacDragAndDrop(");
|
||||
logger.debug("testMacDragAndDrop()");
|
||||
|
||||
final String FILE_NAME = "ALF-15158.diff";
|
||||
|
||||
@ -5843,6 +5843,7 @@ public class ContentDiskDriverTest extends TestCase
|
||||
};
|
||||
|
||||
tran.doInTransaction(validateCB, true, true);
|
||||
logger.debug("end testMacDragAndDrop");
|
||||
|
||||
} // testMacDragAndDrop
|
||||
|
||||
@ -6192,6 +6193,218 @@ public class ContentDiskDriverTest extends TestCase
|
||||
tran.doInTransaction(validateCB, false, true);
|
||||
|
||||
} // testScenarioMountainLionPreview
|
||||
|
||||
/**
|
||||
* Gedit has the nasty behaviour of renaming an open file.
|
||||
* 1) create file (gedit12345678.txt)
|
||||
* 2) create temp file (.goutputStream-IRYDPW) write and flush
|
||||
* 3) rename (fails name collision)
|
||||
* 4) delete target
|
||||
* 5) rename this one succeeds
|
||||
* 6) close temp file
|
||||
*
|
||||
*/
|
||||
public void testGedit() throws Exception
|
||||
{
|
||||
logger.debug("testGEdit");
|
||||
|
||||
final String FILE_NAME = "gedit12345678.txt";
|
||||
final String FILE_TITLE = "Gedit";
|
||||
final String FILE_DESCRIPTION = "This is a test document to test CIFS shuffle";
|
||||
final String TEMP_FILE_NAME = ".goutputStream-IRYDPW";
|
||||
final String UPDATE_TEXT = "Shuffle an open file";
|
||||
|
||||
class TestContext
|
||||
{
|
||||
NetworkFile firstFileHandle;
|
||||
NetworkFile tempFileHandle;
|
||||
NodeRef testNodeRef;
|
||||
};
|
||||
|
||||
final TestContext testContext = new TestContext();
|
||||
|
||||
final String TEST_DIR = TEST_ROOT_DOS_PATH + "\\testGEdit";
|
||||
|
||||
ServerConfiguration scfg = new ServerConfiguration("testServer");
|
||||
TestServer testServer = new TestServer("testServer", scfg);
|
||||
final SrvSession testSession = new TestSrvSession(666, testServer, "test", "remoteName");
|
||||
DiskSharedDevice share = getDiskSharedDevice();
|
||||
final TreeConnection testConnection = testServer.getTreeConnection(share);
|
||||
final RetryingTransactionHelper tran = transactionService.getRetryingTransactionHelper();
|
||||
|
||||
/**
|
||||
* Clean up from a previous run
|
||||
*/
|
||||
RetryingTransactionCallback<Void> deleteGarbageFileCB = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
tran.doInTransaction(deleteGarbageFileCB);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// expect to go here
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a file in the test directory
|
||||
*/
|
||||
RetryingTransactionCallback<Void> createTestFileFirstTime = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
|
||||
/**
|
||||
* Create the test directory we are going to use
|
||||
*/
|
||||
FileOpenParams createRootDirParams = new FileOpenParams(TEST_ROOT_DOS_PATH, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
|
||||
FileOpenParams createDirParams = new FileOpenParams(TEST_DIR, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
|
||||
driver.createDirectory(testSession, testConnection, createRootDirParams);
|
||||
driver.createDirectory(testSession, testConnection, createDirParams);
|
||||
|
||||
/**
|
||||
* Create the file we are going to use
|
||||
*/
|
||||
FileOpenParams createFileParams = new FileOpenParams(TEST_DIR + "\\" + FILE_NAME, 0, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
|
||||
testContext.firstFileHandle = driver.createFile(testSession, testConnection, createFileParams);
|
||||
assertNotNull(testContext.firstFileHandle);
|
||||
|
||||
testContext.testNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
|
||||
|
||||
nodeService.setProperty(testContext.testNodeRef, ContentModel.PROP_TITLE, FILE_TITLE);
|
||||
nodeService.setProperty(testContext.testNodeRef, ContentModel.PROP_DESCRIPTION, FILE_DESCRIPTION);
|
||||
|
||||
String testContent = "Gedit shuffle test";
|
||||
byte[] testContentBytes = testContent.getBytes();
|
||||
testContext.firstFileHandle.writeFile(testContentBytes, testContentBytes.length, 0, 0);
|
||||
|
||||
driver.closeFile(testSession, testConnection, testContext.firstFileHandle);
|
||||
|
||||
nodeService.addAspect(testContext.testNodeRef, ContentModel.ASPECT_VERSIONABLE, null);
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
tran.doInTransaction(createTestFileFirstTime, false, true);
|
||||
|
||||
/**
|
||||
* Create the temp file
|
||||
* add content
|
||||
* leave open
|
||||
*/
|
||||
RetryingTransactionCallback<Void> createTempFile = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
|
||||
FileOpenParams params = new FileOpenParams(TEST_DIR + "\\" + TEMP_FILE_NAME, FileAction.TruncateExisting, AccessMode.ReadWrite, FileAttribute.NTNormal, 0);
|
||||
NetworkFile file = driver.createFile(testSession, testConnection, params);
|
||||
testContext.tempFileHandle = file;
|
||||
String testContent = UPDATE_TEXT;
|
||||
byte[] testContentBytes = testContent.getBytes();
|
||||
testContext.tempFileHandle.writeFile(testContentBytes, testContentBytes.length, 0, 0);
|
||||
/** driver.closeFile(testSession, testConnection, file); **/
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
tran.doInTransaction(createTempFile, false, true);
|
||||
|
||||
/**
|
||||
* rename the test file to the temp
|
||||
*/
|
||||
RetryingTransactionCallback<Void> renameTestFileToTemp = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
driver.renameFile(testSession, testConnection, TEST_DIR + "\\" + TEMP_FILE_NAME, TEST_DIR + "\\" + FILE_NAME);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// expect this one to fail
|
||||
try
|
||||
{
|
||||
tran.doInTransaction(renameTestFileToTemp, false, true);
|
||||
fail("should have failed");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// expect to go here
|
||||
}
|
||||
|
||||
/**
|
||||
* delete the target file
|
||||
*/
|
||||
RetryingTransactionCallback<Void> deleteTargetFile = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
driver.deleteFile(testSession, testConnection, TEST_DIR + "\\" + FILE_NAME);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
tran.doInTransaction(deleteTargetFile, false, true);
|
||||
|
||||
// This one should succeed
|
||||
tran.doInTransaction(renameTestFileToTemp, false, true);
|
||||
|
||||
RetryingTransactionCallback<Void> closeTempFile = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
driver.closeFile(testSession, testConnection, testContext.tempFileHandle);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
tran.doInTransaction(closeTempFile, false, true);
|
||||
|
||||
// Now validate
|
||||
RetryingTransactionCallback<Void> validate = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
NodeRef shuffledNodeRef = getNodeForPath(testConnection, TEST_DIR + "\\" + FILE_NAME);
|
||||
|
||||
ContentReader reader = contentService.getReader(shuffledNodeRef, ContentModel.PROP_CONTENT);
|
||||
String s = reader.getContentString();
|
||||
assertEquals("content not written", UPDATE_TEXT, s);
|
||||
|
||||
assertTrue("node is not versionable", nodeService.hasAspect(shuffledNodeRef, ContentModel.ASPECT_VERSIONABLE));
|
||||
assertEquals("shuffledNode ref is different", shuffledNodeRef, testContext.testNodeRef);
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
tran.doInTransaction(validate, false, true);
|
||||
|
||||
logger.debug("end testGedit");
|
||||
} // testGedit
|
||||
|
||||
|
||||
/**
|
||||
|
@ -595,7 +595,25 @@ public class LegacyFileStateDriver implements ExtendedDiskInterface
|
||||
public void renameFile(SrvSession sess, TreeConnection tree,
|
||||
String oldName, String newName) throws IOException
|
||||
{
|
||||
diskInterface.renameFile(sess, tree, oldName, newName);
|
||||
ContentContext tctx = (ContentContext) tree.getContext();
|
||||
|
||||
diskInterface.renameFile(sess, tree, oldName, newName);
|
||||
|
||||
if(tctx.hasStateCache())
|
||||
{
|
||||
FileStateCache cache = tctx.getStateCache();
|
||||
FileState fstate = cache.findFileState( oldName, false);
|
||||
|
||||
if(fstate != null)
|
||||
{
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("rename file state from:" + oldName + ", to:" + newName);
|
||||
}
|
||||
cache.renameFileState(newName, fstate, fstate.isDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -161,6 +161,8 @@ public class NonTransactionalRuleContentDiskDriver implements ExtendedDiskInterf
|
||||
Command c = ruleEvaluator.evaluate(ctx, o);
|
||||
|
||||
commandExecutor.execute(sess, tree, c);
|
||||
|
||||
releaseEvaluatorContextIfEmpty(driverState, ctx, folder);
|
||||
|
||||
}
|
||||
|
||||
@ -266,6 +268,8 @@ public class NonTransactionalRuleContentDiskDriver implements ExtendedDiskInterf
|
||||
Command c = ruleEvaluator.evaluate(ctx, o);
|
||||
commandExecutor.execute(sess, tree, c);
|
||||
|
||||
releaseEvaluatorContextIfEmpty(driverState, ctx, folder);
|
||||
|
||||
|
||||
} // End of deleteFile
|
||||
|
||||
@ -424,6 +428,11 @@ public class NonTransactionalRuleContentDiskDriver implements ExtendedDiskInterf
|
||||
Operation o = new RenameFileOperation(oldFile, newFile, oldPath, newPath, rootNode);
|
||||
Command c = ruleEvaluator.evaluate(ctx, o);
|
||||
commandExecutor.execute(sess, tree, c);
|
||||
|
||||
ruleEvaluator.notifyRename(ctx, o, c);
|
||||
|
||||
releaseEvaluatorContextIfEmpty(driverState, ctx, oldFolder);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -444,6 +453,8 @@ public class NonTransactionalRuleContentDiskDriver implements ExtendedDiskInterf
|
||||
|
||||
commandExecutor.execute(sess, tree, c);
|
||||
|
||||
releaseEvaluatorContextIfEmpty(driverState, ctx2, newFolder);
|
||||
|
||||
// diskInterface.renameFile(sess, tree, oldPath, newPath);
|
||||
|
||||
}
|
||||
@ -592,6 +603,30 @@ public class NonTransactionalRuleContentDiskDriver implements ExtendedDiskInterf
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the evaluator context if there are no active scenarios.
|
||||
* @param driverState
|
||||
* @param ctx
|
||||
* @param folder
|
||||
*/
|
||||
private void releaseEvaluatorContextIfEmpty(DriverState driverState, EvaluatorContext ctx, String folder)
|
||||
{
|
||||
synchronized(driverState.contextMap)
|
||||
{
|
||||
if(ctx != null)
|
||||
{
|
||||
if(ctx.getScenarioInstances().size() > 0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
driverState.contextMap.remove(folder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -42,6 +42,11 @@ public interface RuleEvaluator
|
||||
* @return Command the command to fulfil the operation
|
||||
*/
|
||||
public Command evaluate(EvaluatorContext context, Operation operation);
|
||||
|
||||
/**
|
||||
* Tell the context of a rename
|
||||
*/
|
||||
public void notifyRename(EvaluatorContext context, Operation operation, Command c);
|
||||
|
||||
|
||||
}
|
||||
|
@ -204,5 +204,31 @@ public class RuleEvaluatorImpl implements RuleEvaluator
|
||||
EvaluatorContextImpl impl = new EvaluatorContextImpl(sessionState);
|
||||
|
||||
return impl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyRename(EvaluatorContext context, Operation operation,
|
||||
Command command)
|
||||
{
|
||||
// currentScenarioInstances needs to be protected for concurrency.
|
||||
synchronized (context.getScenarioInstances())
|
||||
{
|
||||
/**
|
||||
* For each active scenario.
|
||||
*/
|
||||
Iterator<ScenarioInstance> i = context.getScenarioInstances().iterator();
|
||||
|
||||
while(i.hasNext())
|
||||
{
|
||||
ScenarioInstance scenario = i.next();
|
||||
if(scenario instanceof ScenarioInstanceRenameAware)
|
||||
{
|
||||
ScenarioInstanceRenameAware awareScenario = (ScenarioInstanceRenameAware)scenario;
|
||||
awareScenario.notifyRename(operation, command);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -23,12 +23,13 @@ import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.filesys.repo.rules.ScenarioInstance.Ranking;
|
||||
import org.alfresco.filesys.repo.rules.operations.CloseFileOperation;
|
||||
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* The DeleteOnClose rename shuffle is a delete on close of a file resulting in a file being deleted followed by a rename of a file from
|
||||
* somewhere else.
|
||||
* The DeleteOnClose rename shuffle is a delete on close of a file resulting in a file being deleted followed by a
|
||||
* rename or a create
|
||||
*
|
||||
* First case of this is Mac Mountain Lion Preview application.
|
||||
* and then a new copy of the file put into place.
|
||||
@ -36,11 +37,23 @@ import org.apache.commons.logging.LogFactory;
|
||||
* a) DeleteOnClose fileA
|
||||
* b) Close fileA
|
||||
* c) Rename whatever fileA
|
||||
*
|
||||
* Second case First case of this is Mac Drag and drop.
|
||||
* and then a new copy of the file put into place.
|
||||
*
|
||||
* a) Delete fileA
|
||||
* b) Close fileA
|
||||
* c) Create fileA
|
||||
*
|
||||
* Third case Gedit.
|
||||
*
|
||||
* a) Delete fileA
|
||||
* b) Rename .goutputstream fileA
|
||||
*
|
||||
*/
|
||||
public class ScenarioDeleteOnCloseRename implements Scenario
|
||||
public class ScenarioDeleteRenameOrCreate implements Scenario
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(ScenarioDeleteOnCloseRename.class);
|
||||
private static Log logger = LogFactory.getLog(ScenarioDeleteRenameOrCreate.class);
|
||||
|
||||
/**
|
||||
* The regex pattern of a close that will trigger a new instance of
|
||||
@ -67,9 +80,27 @@ public class ScenarioDeleteOnCloseRename implements Scenario
|
||||
{
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("New Scenario ScenarioDeleteOnCloseRename strPattern:" + pattern);
|
||||
logger.debug("New Scenario ScenarioDeleteRenameOrCreate strPattern:" + pattern);
|
||||
}
|
||||
ScenarioDeleteOnCloseRenameInstance instance = new ScenarioDeleteOnCloseRenameInstance();
|
||||
ScenarioDeleteRenameOrCreateInstance instance = new ScenarioDeleteRenameOrCreateInstance();
|
||||
instance.setTimeout(timeout);
|
||||
instance.setRanking(ranking);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
if(operation instanceof DeleteFileOperation)
|
||||
{
|
||||
DeleteFileOperation c = (DeleteFileOperation)operation;
|
||||
|
||||
Matcher m = pattern.matcher(c.getName());
|
||||
if(m.matches())
|
||||
{
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("New Scenario ScenarioDeleteRenameOrCreate strPattern:" + pattern);
|
||||
}
|
||||
ScenarioDeleteRenameOrCreateInstance instance = new ScenarioDeleteRenameOrCreateInstance();
|
||||
instance.setTimeout(timeout);
|
||||
instance.setRanking(ranking);
|
||||
return instance;
|
@ -28,6 +28,8 @@ import org.alfresco.filesys.repo.rules.commands.CopyContentCommand;
|
||||
import org.alfresco.filesys.repo.rules.commands.DeleteFileCommand;
|
||||
import org.alfresco.filesys.repo.rules.commands.RestoreFileCommand;
|
||||
import org.alfresco.filesys.repo.rules.operations.CloseFileOperation;
|
||||
import org.alfresco.filesys.repo.rules.operations.CreateFileOperation;
|
||||
import org.alfresco.filesys.repo.rules.operations.DeleteFileOperation;
|
||||
import org.alfresco.filesys.repo.rules.operations.MoveFileOperation;
|
||||
import org.alfresco.filesys.repo.rules.operations.RenameFileOperation;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
|
||||
@ -46,9 +48,9 @@ import org.apache.commons.logging.LogFactory;
|
||||
* This rule will kick in and ...
|
||||
*
|
||||
*/
|
||||
class ScenarioDeleteOnCloseRenameInstance implements ScenarioInstance
|
||||
class ScenarioDeleteRenameOrCreateInstance implements ScenarioInstance
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(ScenarioDeleteOnCloseRenameInstance.class);
|
||||
private static Log logger = LogFactory.getLog(ScenarioDeleteRenameOrCreateInstance.class);
|
||||
|
||||
private Date startTime = new Date();
|
||||
|
||||
@ -66,7 +68,7 @@ class ScenarioDeleteOnCloseRenameInstance implements ScenarioInstance
|
||||
enum InternalState
|
||||
{
|
||||
NONE,
|
||||
LOOK_FOR_RENAME
|
||||
INITIALISED
|
||||
} ;
|
||||
|
||||
InternalState state = InternalState.NONE;
|
||||
@ -101,7 +103,7 @@ class ScenarioDeleteOnCloseRenameInstance implements ScenarioInstance
|
||||
CloseFileOperation c = (CloseFileOperation)operation;
|
||||
this.name = c.getName();
|
||||
logger.debug("New scenario initialised for file " + name);
|
||||
state = InternalState.LOOK_FOR_RENAME;
|
||||
state = InternalState.INITIALISED;
|
||||
|
||||
ArrayList<Command> commands = new ArrayList<Command>();
|
||||
ArrayList<Command> postCommitCommands = new ArrayList<Command>();
|
||||
@ -110,15 +112,47 @@ class ScenarioDeleteOnCloseRenameInstance implements ScenarioInstance
|
||||
postCommitCommands.add(newDeleteFileCallbackCommand());
|
||||
return new CompoundCommand(commands, postCommitCommands, postErrorCommands);
|
||||
}
|
||||
if(operation instanceof DeleteFileOperation)
|
||||
{
|
||||
DeleteFileOperation c = (DeleteFileOperation)operation;
|
||||
this.name = c.getName();
|
||||
logger.debug("New scenario initialised for file " + name);
|
||||
state = InternalState.INITIALISED;
|
||||
|
||||
ArrayList<Command> commands = new ArrayList<Command>();
|
||||
ArrayList<Command> postCommitCommands = new ArrayList<Command>();
|
||||
ArrayList<Command> postErrorCommands = new ArrayList<Command>();
|
||||
commands.add(new DeleteFileCommand(c.getName(), c.getRootNodeRef(), c.getPath()));
|
||||
postCommitCommands.add(newDeleteFileCallbackCommand());
|
||||
return new CompoundCommand(commands, postCommitCommands, postErrorCommands);
|
||||
}
|
||||
break;
|
||||
|
||||
case LOOK_FOR_RENAME:
|
||||
|
||||
case INITIALISED:
|
||||
|
||||
if(operation instanceof CreateFileOperation)
|
||||
{
|
||||
CreateFileOperation c = (CreateFileOperation)operation;
|
||||
|
||||
if(c.getName().equalsIgnoreCase(name))
|
||||
{
|
||||
isComplete = true;
|
||||
if(originalNodeRef != null)
|
||||
{
|
||||
logger.debug("Delete create shuffle fire!:" + this);
|
||||
return new RestoreFileCommand(c.getName(), c.getRootNodeRef(), c.getPath(), c.getAllocationSize(), originalNodeRef);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if(operation instanceof RenameFileOperation)
|
||||
{
|
||||
RenameFileOperation r = (RenameFileOperation)operation;
|
||||
if(name.equals(r.getTo()))
|
||||
{
|
||||
logger.debug("Delete on close Rename shuffle - fire!");
|
||||
logger.debug("Delete Rename shuffle - fire!");
|
||||
|
||||
if(originalNodeRef != null)
|
||||
{
|
||||
@ -155,7 +189,7 @@ class ScenarioDeleteOnCloseRenameInstance implements ScenarioInstance
|
||||
MoveFileOperation r = (MoveFileOperation)operation;
|
||||
if(name.equals(r.getTo()))
|
||||
{
|
||||
logger.debug("Delete on close Rename shuffle - fire!");
|
||||
logger.debug("Delete Rename shuffle - fire!");
|
||||
|
||||
if(originalNodeRef != null)
|
||||
{
|
||||
@ -198,7 +232,7 @@ class ScenarioDeleteOnCloseRenameInstance implements ScenarioInstance
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "ScenarioDeleteOnCloseRenameShuffleInstance name:" + name ;
|
||||
return "ScenarioDeleteRenameOrCreate name:" + name ;
|
||||
}
|
||||
|
||||
public void setTimeout(long timeout)
|
@ -0,0 +1,19 @@
|
||||
package org.alfresco.filesys.repo.rules;
|
||||
|
||||
/**
|
||||
* The scenario instance wants to be notified about rename.
|
||||
*
|
||||
* @author mrogers
|
||||
*
|
||||
*/
|
||||
public interface ScenarioInstanceRenameAware
|
||||
{
|
||||
/**
|
||||
* Notify the scenario of a successful rename operation.
|
||||
*
|
||||
* @param operation
|
||||
* @param command
|
||||
*/
|
||||
public void notifyRename(Operation operation, Command command);
|
||||
|
||||
}
|
@ -74,7 +74,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
* 4) close
|
||||
*
|
||||
*/
|
||||
class ScenarioOpenFileInstance implements ScenarioInstance, DependentInstance
|
||||
class ScenarioOpenFileInstance implements ScenarioInstance, DependentInstance, ScenarioInstanceRenameAware
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(ScenarioOpenFileInstance.class);
|
||||
|
||||
@ -242,6 +242,20 @@ class ScenarioOpenFileInstance implements ScenarioInstance, DependentInstance
|
||||
|
||||
case OPEN:
|
||||
|
||||
if(operation instanceof RenameFileOperation)
|
||||
{
|
||||
RenameFileOperation r = (RenameFileOperation)operation;
|
||||
if(r.getFrom() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if(name.equalsIgnoreCase(r.getFrom()))
|
||||
{
|
||||
logger.warn("rename of an open file");
|
||||
}
|
||||
}
|
||||
|
||||
if(operation instanceof CloseFileOperation)
|
||||
{
|
||||
CloseFileOperation c = (CloseFileOperation)operation;
|
||||
@ -564,25 +578,70 @@ class ScenarioOpenFileInstance implements ScenarioInstance, DependentInstance
|
||||
}
|
||||
|
||||
|
||||
if(looser.scenario instanceof ScenarioDeleteOnCloseRenameInstance)
|
||||
if(looser.scenario instanceof ScenarioDeleteRenameOrCreateInstance)
|
||||
{
|
||||
CompoundCommand l = (CompoundCommand)looser.command;
|
||||
ArrayList<Command> commands = new ArrayList<Command>();
|
||||
ArrayList<Command> postCommitCommands = new ArrayList<Command>();
|
||||
ArrayList<Command> postErrorCommands = new ArrayList<Command>();
|
||||
commands.addAll(c.getCommands());
|
||||
postCommitCommands.addAll(c.getPostCommitCommands());
|
||||
// Merge in the loosing post commit
|
||||
postCommitCommands.addAll(l.getPostCommitCommands());
|
||||
postErrorCommands.addAll(c.getPostErrorCommands());
|
||||
|
||||
logger.debug("returning merged high priority executor");
|
||||
return new CompoundCommand(commands, postCommitCommands, postErrorCommands);
|
||||
Command x = looser.command;
|
||||
if(x instanceof CompoundCommand)
|
||||
{
|
||||
CompoundCommand l = (CompoundCommand)x;
|
||||
|
||||
ArrayList<Command> commands = new ArrayList<Command>();
|
||||
ArrayList<Command> postCommitCommands = new ArrayList<Command>();
|
||||
ArrayList<Command> postErrorCommands = new ArrayList<Command>();
|
||||
commands.addAll(c.getCommands());
|
||||
postCommitCommands.addAll(c.getPostCommitCommands());
|
||||
// Merge in the loosing post commit
|
||||
postCommitCommands.addAll(l.getPostCommitCommands());
|
||||
postErrorCommands.addAll(c.getPostErrorCommands());
|
||||
|
||||
logger.debug("returning merged high priority executor");
|
||||
return new CompoundCommand(commands, postCommitCommands, postErrorCommands);
|
||||
}
|
||||
else
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No change
|
||||
return command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyRename(Operation operation, Command command)
|
||||
{
|
||||
if(operation instanceof RenameFileOperation)
|
||||
{
|
||||
RenameFileOperation r = (RenameFileOperation)operation;
|
||||
if(r.getFrom() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(name.equalsIgnoreCase(r.getFrom()))
|
||||
{
|
||||
if(logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("rename of this scenario: to " + r.getTo());
|
||||
}
|
||||
|
||||
name = r.getTo();
|
||||
|
||||
if (fileHandleReadWrite != null)
|
||||
{
|
||||
fileHandleReadWrite.setName(r.getTo());
|
||||
fileHandleReadWrite.setFullName(r.getToPath());
|
||||
}
|
||||
|
||||
if (fileHandleReadOnly != null)
|
||||
{
|
||||
fileHandleReadOnly.setName(r.getTo());
|
||||
fileHandleReadOnly.setFullName(r.getToPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@ -95,9 +95,21 @@ public interface AuthorityDAO
|
||||
*/
|
||||
public Set<String> getContainingAuthoritiesInZone(AuthorityType type, String authority, final String zoneName, AuthorityFilter filter, int size);
|
||||
|
||||
|
||||
/**
|
||||
* Get authorities by type and/or zone
|
||||
* Get AuthorityInfo by type and/or zone (both cannot be null).
|
||||
*
|
||||
* @param type
|
||||
* @param zoneName
|
||||
* @param displayNameFilter
|
||||
* @param sortBy either "displayName", "shortName", "authorityName" or null if no sorting.
|
||||
* @param sortAscending
|
||||
* @param pagingRequest
|
||||
* @return
|
||||
*/
|
||||
public PagingResults<AuthorityInfo> getAuthoritiesInfo(AuthorityType type, String zoneName, String displayNameFilter, String sortBy, boolean sortAscending, PagingRequest pagingRequest);
|
||||
|
||||
/**
|
||||
* Get authority names by type and/or zone (both cannot be null).
|
||||
*
|
||||
* @param type
|
||||
* @param zoneName
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@ -69,6 +69,7 @@ import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.util.BridgeTable;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.alfresco.util.ISO9075;
|
||||
import org.alfresco.util.Pair;
|
||||
@ -84,6 +85,8 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
|
||||
private static final String CANNED_QUERY_AUTHS_LIST = "authsGetAuthoritiesCannedQueryFactory"; // see authority-services-context.xml
|
||||
|
||||
private static final String CANNED_QUERY_AUTH_BRIDGE_LINK_LIST = "authsGetAuthorityBridgeCannedQueryFactory"; // see authority-services-context.xml
|
||||
|
||||
private StoreRef storeRef;
|
||||
|
||||
private NodeService nodeService;
|
||||
@ -114,6 +117,8 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
|
||||
private SimpleCache<NodeRef, List<ChildAssociationRef>> childAuthorityCache;
|
||||
|
||||
private SimpleCache<String, BridgeTable<String>> authorityBridgeTableByTenantCache;
|
||||
|
||||
/** System Container ref cache (Tennant aware) */
|
||||
private Map<String, NodeRef> systemContainerRefs = new ConcurrentHashMap<String, NodeRef>(4);
|
||||
|
||||
@ -124,9 +129,14 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
/** The number of authorities in a zone to pre-cache, allowing quick generation of 'first n' results. */
|
||||
private int zoneAuthoritySampleSize = 10000;
|
||||
|
||||
private NamedObjectRegistry<CannedQueryFactory<AuthorityInfo>> cannedQueryRegistry;
|
||||
|
||||
private NamedObjectRegistry<CannedQueryFactory> cannedQueryRegistry;
|
||||
|
||||
private AuthorityBridgeDAO authorityBridgeDAO;
|
||||
|
||||
private boolean useBridgeTable = true;
|
||||
|
||||
private static final Collection<AuthorityType> SEARCHABLE_AUTHORITY_TYPES = new LinkedList<AuthorityType>();
|
||||
|
||||
static
|
||||
{
|
||||
SEARCHABLE_AUTHORITY_TYPES.add(AuthorityType.ROLE);
|
||||
@ -198,6 +208,20 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
{
|
||||
this.childAuthorityCache = childAuthorityCache;
|
||||
}
|
||||
|
||||
public void setAuthorityBridgeTableByTenantCache(SimpleCache<String, BridgeTable<String>> authorityBridgeTableByTenantCache)
|
||||
{
|
||||
this.authorityBridgeTableByTenantCache = authorityBridgeTableByTenantCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useBridgeTable the useBridgeTable to set
|
||||
*/
|
||||
public void setUseBridgeTable(boolean useBridgeTable)
|
||||
{
|
||||
this.useBridgeTable = useBridgeTable;
|
||||
}
|
||||
|
||||
|
||||
public void setPersonService(PersonService personService)
|
||||
{
|
||||
@ -219,12 +243,20 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
public void setCannedQueryRegistry(NamedObjectRegistry<CannedQueryFactory<AuthorityInfo>> cannedQueryRegistry)
|
||||
public void setCannedQueryRegistry(NamedObjectRegistry<CannedQueryFactory> cannedQueryRegistry)
|
||||
{
|
||||
this.cannedQueryRegistry = cannedQueryRegistry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param authorityBridgeDAO the authorityBridgeDAO to set
|
||||
*/
|
||||
public void setAuthorityBridgeDAO(AuthorityBridgeDAO authorityBridgeDAO)
|
||||
{
|
||||
this.authorityBridgeDAO = authorityBridgeDAO;
|
||||
}
|
||||
|
||||
|
||||
public boolean authorityExists(String name)
|
||||
{
|
||||
NodeRef ref = getAuthorityOrNull(name);
|
||||
@ -251,7 +283,7 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
throw new AlfrescoRuntimeException("Authorities of the type " + authorityType
|
||||
+ " may not be added to other authorities");
|
||||
}
|
||||
removeCachedChildAuthorities(parentRef);
|
||||
childAuthorityCache.remove(parentRef);
|
||||
parentRefs.add(parentRef);
|
||||
}
|
||||
NodeRef childRef = getAuthorityOrNull(childName);
|
||||
@ -276,6 +308,7 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
else
|
||||
{
|
||||
userAuthorityCache.clear();
|
||||
authorityBridgeTableByTenantCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,11 +336,6 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
authorityLookupCache.put(cacheKey(name), childRef);
|
||||
}
|
||||
|
||||
private NodeRef cacheKey(NodeRef nodeRef)
|
||||
{
|
||||
return tenantService.getName(nodeRef);
|
||||
}
|
||||
|
||||
private Pair<String, String> cacheKey(String authorityName)
|
||||
{
|
||||
String tenantDomain = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER ? tenantService.getDomain(authorityName) : tenantService.getCurrentUserDomain();
|
||||
@ -330,12 +358,32 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
removeParentsFromChildAuthorityCache(nodeRef);
|
||||
authorityLookupCache.remove(cacheKey(name));
|
||||
userAuthorityCache.clear();
|
||||
authorityBridgeTableByTenantCache.clear();
|
||||
|
||||
nodeService.deleteNode(nodeRef);
|
||||
}
|
||||
|
||||
// Get authorities by type and/or zone (both cannot be null)
|
||||
public PagingResults<AuthorityInfo> getAuthoritiesInfo(AuthorityType type, String zoneName, String displayNameFilter, String sortBy, boolean sortAscending, PagingRequest pagingRequest)
|
||||
{
|
||||
checkGetAuthorityParams(type, zoneName, pagingRequest);
|
||||
|
||||
return getAuthoritiesImpl(type, getContainerRef(zoneName), displayNameFilter, sortBy, sortAscending, pagingRequest, new PagingResultsAuthorityInfo());
|
||||
}
|
||||
|
||||
public PagingResults<String> getAuthorities(AuthorityType type, String zoneName, String displayNameFilter, boolean sortByDisplayName, boolean sortAscending, PagingRequest pagingRequest)
|
||||
{
|
||||
checkGetAuthorityParams(type, zoneName, pagingRequest);
|
||||
|
||||
if ((zoneName == null) && (type.equals(AuthorityType.USER)))
|
||||
{
|
||||
return getUserAuthoritiesImpl(displayNameFilter, sortByDisplayName, sortAscending, pagingRequest);
|
||||
}
|
||||
|
||||
return getAuthoritiesImpl(type, getContainerRef(zoneName), displayNameFilter, (sortByDisplayName ? GetAuthoritiesCannedQuery.DISPLAY_NAME : null), sortAscending, pagingRequest, new PagingResultsString());
|
||||
}
|
||||
|
||||
private void checkGetAuthorityParams(AuthorityType type, String zoneName,
|
||||
PagingRequest pagingRequest)
|
||||
{
|
||||
ParameterCheck.mandatory("pagingRequest", pagingRequest);
|
||||
|
||||
@ -343,12 +391,10 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
{
|
||||
throw new IllegalArgumentException("Type and/or zoneName required - both cannot be null");
|
||||
}
|
||||
|
||||
if ((zoneName == null) && (type.equals(AuthorityType.USER)))
|
||||
{
|
||||
return getUserAuthoritiesImpl(displayNameFilter, sortByDisplayName, sortAscending, pagingRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private NodeRef getContainerRef(String zoneName)
|
||||
{
|
||||
NodeRef containerRef = null;
|
||||
if (zoneName != null)
|
||||
{
|
||||
@ -362,11 +408,10 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
{
|
||||
containerRef = getAuthorityContainer();
|
||||
}
|
||||
|
||||
return getAuthoritiesImpl(type, containerRef, displayNameFilter, sortByDisplayName, sortAscending, pagingRequest);
|
||||
return containerRef;
|
||||
}
|
||||
|
||||
private PagingResults<String> getAuthoritiesImpl(AuthorityType type, NodeRef containerRef, String displayNameFilter, boolean sortByDisplayName, boolean sortAscending, PagingRequest pagingRequest)
|
||||
private <T> PagingResults<T> getAuthoritiesImpl(AuthorityType type, NodeRef containerRef, String displayNameFilter, String sortBy, boolean sortAscending, PagingRequest pagingRequest, AbstractPagingResults<T> finalResults)
|
||||
{
|
||||
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
|
||||
|
||||
@ -386,39 +431,12 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
|
||||
// get canned query
|
||||
GetAuthoritiesCannedQueryFactory getAuthoritiesCannedQueryFactory = (GetAuthoritiesCannedQueryFactory)cannedQueryRegistry.getNamedObject(CANNED_QUERY_AUTHS_LIST);
|
||||
CannedQuery<AuthorityInfo> cq = getAuthoritiesCannedQueryFactory.getCannedQuery(type, containerRef, displayNameFilter, sortByDisplayName, sortAscending, pagingRequest);
|
||||
CannedQuery<AuthorityInfo> cq = getAuthoritiesCannedQueryFactory.getCannedQuery(type, containerRef, displayNameFilter, sortBy, sortAscending, pagingRequest);
|
||||
|
||||
// execute canned query
|
||||
final CannedQueryResults<AuthorityInfo> results = cq.execute();
|
||||
|
||||
PagingResults<String> finalResults = new PagingResults<String>()
|
||||
{
|
||||
@Override
|
||||
public String getQueryExecutionId()
|
||||
{
|
||||
return results.getQueryExecutionId();
|
||||
}
|
||||
@Override
|
||||
public List<String> getPage()
|
||||
{
|
||||
List<String> auths = new ArrayList<String>(results.getPageCount());
|
||||
for (AuthorityInfo authInfo : results.getPage())
|
||||
{
|
||||
auths.add(authInfo.getAuthorityName());
|
||||
}
|
||||
return auths;
|
||||
}
|
||||
@Override
|
||||
public boolean hasMoreItems()
|
||||
{
|
||||
return results.hasMoreItems();
|
||||
}
|
||||
@Override
|
||||
public Pair<Integer, Integer> getTotalResultCount()
|
||||
{
|
||||
return results.getTotalResultCount();
|
||||
}
|
||||
};
|
||||
|
||||
finalResults.setResults(results);
|
||||
|
||||
if (start != null)
|
||||
{
|
||||
@ -704,7 +722,7 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
throw new UnknownAuthorityException("An authority was not found for " + childName);
|
||||
}
|
||||
nodeService.removeChild(parentRef, childRef);
|
||||
removeCachedChildAuthorities(parentRef);
|
||||
childAuthorityCache.remove(parentRef);
|
||||
if (AuthorityType.getAuthorityType(childName) == AuthorityType.USER)
|
||||
{
|
||||
userAuthorityCache.remove(childName);
|
||||
@ -712,11 +730,57 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
else
|
||||
{
|
||||
userAuthorityCache.clear();
|
||||
authorityBridgeTableByTenantCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private BridgeTable<String> getBridgeTable()
|
||||
{
|
||||
String tenant = tenantService.getCurrentUserDomain();
|
||||
BridgeTable<String> bridgeTable = authorityBridgeTableByTenantCache.get(tenant);
|
||||
if(bridgeTable == null)
|
||||
{
|
||||
List<AuthorityBridgeLink> links = authorityBridgeDAO.getAuthorityBridgeLinks();
|
||||
bridgeTable = new BridgeTable<String>();
|
||||
for(AuthorityBridgeLink link : links)
|
||||
{
|
||||
bridgeTable.addLink(link.getParentName(), link.getChildName());
|
||||
}
|
||||
authorityBridgeTableByTenantCache.put(tenant, bridgeTable);
|
||||
}
|
||||
return bridgeTable;
|
||||
}
|
||||
|
||||
private void listAuthoritiesByBridgeTable(Set<String> authorities, String name)
|
||||
{
|
||||
BridgeTable<String> bridgeTable = getBridgeTable();
|
||||
|
||||
AuthorityType type = AuthorityType.getAuthorityType(name);
|
||||
switch(type)
|
||||
{
|
||||
case ADMIN:
|
||||
case GUEST:
|
||||
case USER:
|
||||
case EVERYONE:
|
||||
NodeRef authRef = getAuthorityOrNull(name);
|
||||
List<AuthorityBridgeLink> parents = authorityBridgeDAO.getDirectAuthoritiesForUser(authRef);
|
||||
for(AuthorityBridgeLink parent : parents)
|
||||
{
|
||||
authorities.add(parent.getParentName());
|
||||
authorities.addAll(bridgeTable.getAncestors(parent.getParentName()));
|
||||
}
|
||||
break;
|
||||
case GROUP:
|
||||
case OWNER:
|
||||
case ROLE:
|
||||
authorities.addAll(bridgeTable.getAncestors(name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getContainingAuthorities(AuthorityType type, String name, boolean immediate)
|
||||
{
|
||||
|
||||
// Optimize for the case where we want all the authorities that a user belongs to
|
||||
if (!immediate && AuthorityType.getAuthorityType(name) == AuthorityType.USER)
|
||||
{
|
||||
@ -725,7 +789,14 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
if (authorities == null)
|
||||
{
|
||||
authorities = new TreeSet<String>();
|
||||
listAuthorities(null, name, authorities, true, true);
|
||||
if(useBridgeTable)
|
||||
{
|
||||
listAuthoritiesByBridgeTable(authorities, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
listAuthorities(null, name, authorities, true, true);
|
||||
}
|
||||
userAuthorityCache.put(name, authorities);
|
||||
}
|
||||
// If we wanted the unfiltered set we are done
|
||||
@ -967,14 +1038,14 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ChildAssociationRef> cars = getCachedChildAuthorities(nodeRef);
|
||||
List<ChildAssociationRef> cars = childAuthorityCache.get(nodeRef);
|
||||
if (cars == null)
|
||||
{
|
||||
cars = nodeService.getChildAssocs(nodeRef, RegexQNamePattern.MATCH_ALL,
|
||||
RegexQNamePattern.MATCH_ALL, false);
|
||||
if (!cars.isEmpty() && cars.get(0).getTypeQName().equals(ContentModel.ASSOC_MEMBER))
|
||||
{
|
||||
putCachedChildAuthorities(nodeRef, cars);
|
||||
childAuthorityCache.put(nodeRef, cars);
|
||||
}
|
||||
}
|
||||
|
||||
@ -994,36 +1065,24 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
}
|
||||
|
||||
|
||||
// Take advantage of the fact that the authority name is on the child association
|
||||
public boolean isAuthorityContained(NodeRef authorityNodeRef, String authorityToFind)
|
||||
{
|
||||
// Look up the desired authority using case sensitivity rules appropriate for the authority type
|
||||
NodeRef authorityToFindRef = getAuthorityOrNull(authorityToFind);
|
||||
if (authorityToFindRef == null)
|
||||
{
|
||||
// No such authority so it won't be contained anywhere
|
||||
return false;
|
||||
}
|
||||
// Now we can just search for the NodeRef
|
||||
return isAuthorityContainedImpl(authorityNodeRef, authorityToFindRef);
|
||||
}
|
||||
|
||||
private boolean isAuthorityContainedImpl(NodeRef authorityNodeRef, NodeRef authorityToFindRef)
|
||||
{
|
||||
List<ChildAssociationRef> cars = getCachedChildAuthorities(authorityNodeRef);
|
||||
List<ChildAssociationRef> cars = childAuthorityCache.get(authorityNodeRef);
|
||||
if (cars == null)
|
||||
{
|
||||
cars = nodeService.getChildAssocs(authorityNodeRef, RegexQNamePattern.MATCH_ALL,
|
||||
RegexQNamePattern.MATCH_ALL, false);
|
||||
putCachedChildAuthorities(authorityNodeRef, cars);
|
||||
childAuthorityCache.put(authorityNodeRef, cars);
|
||||
}
|
||||
|
||||
// Loop over children recursively to find authorityToFind
|
||||
for (ChildAssociationRef car : cars)
|
||||
{
|
||||
NodeRef childRef = car.getChildRef();
|
||||
if (authorityToFindRef.equals(childRef)
|
||||
|| AuthorityType.getAuthorityType(car.getQName().getLocalName()) != AuthorityType.USER
|
||||
&& isAuthorityContainedImpl(childRef, authorityToFindRef))
|
||||
String authorityName = car.getQName().getLocalName();
|
||||
if (authorityToFind.equals(authorityName)
|
||||
|| AuthorityType.getAuthorityType(authorityName) != AuthorityType.USER
|
||||
&& isAuthorityContained(car.getChildRef(), authorityToFind))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -1038,12 +1097,12 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
NodeRef parentRef = car.getParentRef();
|
||||
if (dictionaryService.isSubClass(nodeService.getType(parentRef), ContentModel.TYPE_AUTHORITY_CONTAINER))
|
||||
{
|
||||
removeCachedChildAuthorities(parentRef);
|
||||
childAuthorityCache.remove(parentRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private NodeRef getAuthorityOrNull(final String name)
|
||||
private NodeRef getAuthorityOrNull(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -1051,9 +1110,13 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
{
|
||||
return personService.getPerson(name, false);
|
||||
}
|
||||
else if (AuthorityType.getAuthorityType(name).equals(AuthorityType.GUEST) || AuthorityType.getAuthorityType(name).equals(AuthorityType.ADMIN))
|
||||
else if (AuthorityType.getAuthorityType(name).equals(AuthorityType.GUEST))
|
||||
{
|
||||
return null;
|
||||
return personService.getPerson(name, false);
|
||||
}
|
||||
else if (AuthorityType.getAuthorityType(name).equals(AuthorityType.ADMIN))
|
||||
{
|
||||
return personService.getPerson(name, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1244,7 +1307,8 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
{
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return new HashSet<String>(getAuthoritiesImpl(type, zoneRef, null, false, false, new PagingRequest(0, Integer.MAX_VALUE, null)).getPage());
|
||||
return new HashSet<String>(getAuthoritiesImpl(type, zoneRef, null, null, false,
|
||||
new PagingRequest(0, Integer.MAX_VALUE, null), new PagingResultsString()).getPage());
|
||||
}
|
||||
|
||||
public void addAuthorityToZones(String authorityName, Set<String> zones)
|
||||
@ -1360,7 +1424,8 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
}
|
||||
}
|
||||
authorityLookupCache.clear();
|
||||
|
||||
authorityBridgeTableByTenantCache.clear();
|
||||
|
||||
// Cache is out of date
|
||||
userAuthorityCache.clear();
|
||||
}
|
||||
@ -1386,19 +1451,62 @@ public class AuthorityDAOImpl implements AuthorityDAO, NodeServicePolicies.Befor
|
||||
this.policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"), ContentModel.TYPE_AUTHORITY, new JavaBehaviour(
|
||||
this, "onUpdateProperties"));
|
||||
}
|
||||
|
||||
private abstract class AbstractPagingResults<R> implements PagingResults<R>
|
||||
{
|
||||
protected CannedQueryResults<AuthorityInfo> results;
|
||||
|
||||
public void setResults(CannedQueryResults<AuthorityInfo> results)
|
||||
{
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryExecutionId()
|
||||
{
|
||||
return results.getQueryExecutionId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreItems()
|
||||
{
|
||||
return results.hasMoreItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Integer, Integer> getTotalResultCount()
|
||||
{
|
||||
return results.getTotalResultCount();
|
||||
}
|
||||
}
|
||||
|
||||
private List<ChildAssociationRef> getCachedChildAuthorities(NodeRef parentNodeRef)
|
||||
{
|
||||
return childAuthorityCache.get(cacheKey(parentNodeRef));
|
||||
}
|
||||
|
||||
private void removeCachedChildAuthorities(NodeRef parentNodeRef)
|
||||
{
|
||||
childAuthorityCache.remove(cacheKey(parentNodeRef));
|
||||
}
|
||||
|
||||
private void putCachedChildAuthorities(NodeRef parentNodeRef, List<ChildAssociationRef> children)
|
||||
{
|
||||
childAuthorityCache.put(cacheKey(parentNodeRef), children);
|
||||
}
|
||||
private class PagingResultsString extends AbstractPagingResults<String>
|
||||
{
|
||||
@Override
|
||||
public List<String> getPage()
|
||||
{
|
||||
List<String> auths = new ArrayList<String>(results.getPageCount());
|
||||
for (AuthorityInfo authInfo : results.getPage())
|
||||
{
|
||||
auths.add((String) authInfo.getAuthorityName());
|
||||
}
|
||||
return auths;
|
||||
}
|
||||
};
|
||||
|
||||
private class PagingResultsAuthorityInfo extends AbstractPagingResults<AuthorityInfo>
|
||||
{
|
||||
@Override
|
||||
public List<AuthorityInfo> getPage()
|
||||
{
|
||||
List<AuthorityInfo> auths = new ArrayList<AuthorityInfo>(results.getPageCount());
|
||||
for (AuthorityInfo authInfo : results.getPage())
|
||||
{
|
||||
auths.add((AuthorityInfo) authInfo);
|
||||
}
|
||||
return auths;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@ -19,6 +19,7 @@
|
||||
package org.alfresco.repo.security.authority;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.AuthorityType;
|
||||
|
||||
/**
|
||||
* Authority Info - used by GetAuthorities CQ
|
||||
@ -28,21 +29,21 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
||||
*/
|
||||
public class AuthorityInfo
|
||||
{
|
||||
private NodeRef nodeRef;
|
||||
private Long nodeId;
|
||||
|
||||
private String authorityDisplayName; // eg. My Group, My Role
|
||||
private String authorityName; // eg. GROUP_my1, ROLE_myA
|
||||
|
||||
public AuthorityInfo(NodeRef nodeRef, String authorityDisplayName, String authorityName)
|
||||
public AuthorityInfo(Long nodeId, String authorityDisplayName, String authorityName)
|
||||
{
|
||||
this.nodeRef = nodeRef;
|
||||
this.nodeId = nodeId;
|
||||
this.authorityDisplayName = authorityDisplayName;
|
||||
this.authorityName = authorityName;
|
||||
}
|
||||
|
||||
public NodeRef getNodeRef()
|
||||
public Long getNodeId()
|
||||
{
|
||||
return nodeRef;
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
public String getAuthorityDisplayName()
|
||||
@ -54,4 +55,21 @@ public class AuthorityInfo
|
||||
{
|
||||
return authorityName;
|
||||
}
|
||||
|
||||
public String getShortName()
|
||||
{
|
||||
AuthorityType type = AuthorityType.getAuthorityType(authorityName);
|
||||
if (type.isFixedString())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
else if (type.isPrefixed())
|
||||
{
|
||||
return authorityName.substring(type.getPrefixString().length());
|
||||
}
|
||||
else
|
||||
{
|
||||
return authorityName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@ -334,6 +334,21 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
|
||||
return authorities;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public PagingResults<AuthorityInfo> getAuthoritiesInfo(AuthorityType type, String zoneName, String displayNameFilter, String sortBy, boolean sortAscending, PagingRequest pagingRequest)
|
||||
{
|
||||
ParameterCheck.mandatory("pagingRequest", pagingRequest);
|
||||
ParameterCheck.mandatory("type", type);
|
||||
|
||||
if (type != AuthorityType.USER && type != AuthorityType.GROUP && type != AuthorityType.ROLE)
|
||||
{
|
||||
throw new UnsupportedOperationException("Unexpected authority type: "+type);
|
||||
}
|
||||
return authorityDAO.getAuthoritiesInfo(type, zoneName, displayNameFilter, sortBy, sortAscending, pagingRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -700,7 +715,7 @@ public class AuthorityServiceImpl implements AuthorityService, InitializingBean
|
||||
|
||||
/**
|
||||
* Lazy load set of authorities. Try not to iterate or ask for the size. Needed for the case where there
|
||||
* is a large number of sites/groups.
|
||||
* are a large number of sites/groups.
|
||||
*
|
||||
* @author David Ward, Alan Davis
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@ -23,6 +23,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.query.CannedQueryParameters;
|
||||
import org.alfresco.query.CannedQuerySortDetails;
|
||||
@ -49,6 +50,10 @@ public class GetAuthoritiesCannedQuery extends AbstractCannedQueryPermissions<Au
|
||||
private static final String QUERY_NAMESPACE = "alfresco.query.authorities";
|
||||
private static final String QUERY_SELECT_GET_AUTHORITIES = "select_GetAuthoritiesCannedQuery";
|
||||
|
||||
static final String DISPLAY_NAME = "displayName";
|
||||
private static final String SHORT_NAME = "shortName";
|
||||
private static final String AUTHORITY_NAME = "authorityName";
|
||||
|
||||
private CannedQueryDAO cannedQueryDAO;
|
||||
private TenantService tenantService;
|
||||
|
||||
@ -74,7 +79,7 @@ public class GetAuthoritiesCannedQuery extends AbstractCannedQueryPermissions<Au
|
||||
|
||||
// Get filter details
|
||||
final AuthorityType type = params.getType();
|
||||
final String nameFilter = params.getDisplayNameFilter();
|
||||
final Pattern nameFilter = getPattern(params.getDisplayNameFilter());
|
||||
|
||||
// filtered - note: sorting and permissions will be applied post query
|
||||
final List<AuthorityInfo> auths = new ArrayList<AuthorityInfo>(100);
|
||||
@ -106,13 +111,49 @@ public class GetAuthoritiesCannedQuery extends AbstractCannedQueryPermissions<Au
|
||||
return auths;
|
||||
}
|
||||
|
||||
// Gets a regex pattern from the search value
|
||||
private Pattern getPattern(String searchValue)
|
||||
{
|
||||
if (searchValue == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Escapes: \ with \\ and . with \.
|
||||
// Replaces ? with . and * with .*
|
||||
searchValue = "^"+searchValue.replaceAll("\\\\", "\\\\\\\\").replaceAll("\\.", "\\\\.").replaceAll("\\?", ".").replaceAll("\\*", ".*");
|
||||
return Pattern.compile(searchValue, Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
|
||||
private class AuthComparator implements Comparator<AuthorityInfo>
|
||||
{
|
||||
private boolean sortByDisplayName;
|
||||
private boolean sortByShortName;
|
||||
private SortOrder sortOrder;
|
||||
private Collator collator;
|
||||
|
||||
public AuthComparator(SortOrder sortOrder)
|
||||
public AuthComparator(String fieldName, SortOrder sortOrder)
|
||||
{
|
||||
if (DISPLAY_NAME.equals(fieldName))
|
||||
{
|
||||
sortByDisplayName = true;
|
||||
sortByShortName = false;
|
||||
}
|
||||
else if (SHORT_NAME.equals(fieldName))
|
||||
{
|
||||
sortByDisplayName = false;
|
||||
sortByShortName = true;
|
||||
}
|
||||
else if (SHORT_NAME.equals(fieldName))
|
||||
{
|
||||
sortByDisplayName = false;
|
||||
sortByShortName = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Authorities should be sorted by "+DISPLAY_NAME+", "+AUTHORITY_NAME+" or "+SHORT_NAME+". Asked use "+fieldName);
|
||||
}
|
||||
|
||||
this.sortOrder = sortOrder;
|
||||
this.collator = Collator.getInstance(); // note: currently default locale
|
||||
}
|
||||
@ -128,8 +169,19 @@ public class GetAuthoritiesCannedQuery extends AbstractCannedQueryPermissions<Au
|
||||
auth2 = auth1In;
|
||||
}
|
||||
|
||||
String s1 = auth1.getAuthorityDisplayName();
|
||||
String s2 = auth2.getAuthorityDisplayName();
|
||||
String s1 = null;
|
||||
String s2 = null;
|
||||
|
||||
if (sortByDisplayName)
|
||||
{
|
||||
s1 = auth1.getAuthorityDisplayName();
|
||||
s2 = auth2.getAuthorityDisplayName();
|
||||
}
|
||||
else if (sortByShortName)
|
||||
{
|
||||
s1 = auth1.getShortName();
|
||||
s2 = auth2.getShortName();
|
||||
}
|
||||
|
||||
if (s1 == null)
|
||||
{
|
||||
@ -169,14 +221,14 @@ public class GetAuthoritiesCannedQuery extends AbstractCannedQueryPermissions<Au
|
||||
if (sortPairs.size() > 0)
|
||||
{
|
||||
// single sort option - authority display name (else authority name if former is null)
|
||||
Collections.sort(results, new AuthComparator(sortPairs.get(0).getSecond()));
|
||||
Collections.sort(results, new AuthComparator((String) sortPairs.get(0).getFirst(), sortPairs.get(0).getSecond()));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// startsWith / ignoreCase
|
||||
private boolean includeFilter(AuthorityInfo auth, AuthorityType type, String nameFilterLower)
|
||||
private boolean includeFilter(AuthorityInfo auth, AuthorityType type, Pattern nameFilter)
|
||||
{
|
||||
String authName = auth.getAuthorityName();
|
||||
|
||||
@ -187,23 +239,28 @@ public class GetAuthoritiesCannedQuery extends AbstractCannedQueryPermissions<Au
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nameFilterLower == null)
|
||||
if (nameFilter == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
String authDisplayNameLower = (auth.getAuthorityDisplayName() != null ? auth.getAuthorityDisplayName().toLowerCase() : null);
|
||||
if ((authDisplayNameLower != null) && (authDisplayNameLower.startsWith(nameFilterLower)))
|
||||
String displayName = auth.getAuthorityDisplayName();
|
||||
if (displayName != null && nameFilter.matcher(displayName).find())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// To match on just displayName use the following.
|
||||
// if (displayName != null)
|
||||
// {
|
||||
// return nameFilter.matcher(displayName).find();
|
||||
// }
|
||||
|
||||
if (authType.isPrefixed())
|
||||
{
|
||||
authName = authName.substring(authType.getPrefixString().length());
|
||||
}
|
||||
|
||||
return (authName.toLowerCase().startsWith(nameFilterLower));
|
||||
return (nameFilter.matcher(authName).find());
|
||||
}
|
||||
|
||||
private interface QueryCallback
|
||||
@ -230,7 +287,7 @@ public class GetAuthoritiesCannedQuery extends AbstractCannedQueryPermissions<Au
|
||||
}
|
||||
|
||||
// Call back
|
||||
boolean more = resultsCallback.handle(new AuthorityInfo(tenantService.getBaseName(result.getNode().getNodeRef()),
|
||||
boolean more = resultsCallback.handle(new AuthorityInfo(result.getId(),
|
||||
result.getAuthorityDisplayName(),
|
||||
result.getAuthorityName()));
|
||||
if (!more)
|
||||
|
@ -87,7 +87,7 @@ public class GetAuthoritiesCannedQueryFactory extends AbstractCannedQueryFactory
|
||||
return (CannedQuery<AuthorityInfo>) new GetAuthoritiesCannedQuery(cannedQueryDAO, tenantService, methodSecurity, parameters);
|
||||
}
|
||||
|
||||
public CannedQuery<AuthorityInfo> getCannedQuery(AuthorityType type, NodeRef containerRef, String displayNameFilter, boolean sortByDisplayName, boolean sortAscending, PagingRequest pagingRequest)
|
||||
public CannedQuery<AuthorityInfo> getCannedQuery(AuthorityType type, NodeRef containerRef, String displayNameFilter, String sortBy, boolean sortAscending, PagingRequest pagingRequest)
|
||||
{
|
||||
ParameterCheck.mandatory("containerRef", containerRef);
|
||||
ParameterCheck.mandatory("pagingRequest", pagingRequest);
|
||||
@ -120,10 +120,10 @@ public class GetAuthoritiesCannedQueryFactory extends AbstractCannedQueryFactory
|
||||
|
||||
// sort details
|
||||
CannedQuerySortDetails cqsd = null;
|
||||
if (sortByDisplayName)
|
||||
if (sortBy != null)
|
||||
{
|
||||
List<Pair<? extends Object, SortOrder>> sortPairs = new ArrayList<Pair<? extends Object, SortOrder>>(1);
|
||||
sortPairs.add(new Pair<String, SortOrder>("sortByName", (sortAscending ? SortOrder.ASCENDING : SortOrder.DESCENDING))); // note: sortByName is implied
|
||||
sortPairs.add(new Pair<String, SortOrder>(sortBy, (sortAscending ? SortOrder.ASCENDING : SortOrder.DESCENDING)));
|
||||
cqsd = new CannedQuerySortDetails(sortPairs);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
package org.alfresco.repo.security.authority.script;
|
||||
|
||||
import static org.alfresco.repo.security.authority.script.ScriptGroup.makeScriptGroups;
|
||||
import static org.alfresco.repo.security.authority.script.ScriptGroup.makeScriptGroupsInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -28,6 +29,7 @@ import java.util.Set;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
|
||||
import org.alfresco.repo.security.authority.AuthorityInfo;
|
||||
import org.alfresco.repo.security.authority.UnknownAuthorityException;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@ -39,6 +41,9 @@ import org.alfresco.service.cmr.security.PersonService.PersonInfo;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.ScriptPagingDetails;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Script object representing the authority service.
|
||||
@ -52,6 +57,8 @@ public class ScriptAuthorityService extends BaseScopableProcessorExtension
|
||||
/** RegEx to split a String on the first space. */
|
||||
public static final String ON_FIRST_SPACE = " +";
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ScriptAuthorityService.class);
|
||||
|
||||
/** The group/authority service */
|
||||
private AuthorityService authorityService;
|
||||
/** The person service */
|
||||
@ -234,7 +241,7 @@ public class ScriptAuthorityService extends BaseScopableProcessorExtension
|
||||
*
|
||||
* @param filter Pattern to filter groups by
|
||||
* @param paging Paging details
|
||||
* @return Array of mathcing groups
|
||||
* @return Array of matching groups
|
||||
* @since 4.0
|
||||
*/
|
||||
public ScriptGroup[] getGroups(String filter, ScriptPagingDetails paging)
|
||||
@ -252,7 +259,7 @@ public class ScriptAuthorityService extends BaseScopableProcessorExtension
|
||||
* @param paging Paging details
|
||||
* @param sortBy Field to sort by, can be <code>shortName</code> or <code>displayName</code> otherwise
|
||||
* the results are ordered by the authorityName
|
||||
* @return Array of mathcing groups
|
||||
* @return Array of matching groups
|
||||
* @since 4.0
|
||||
*/
|
||||
public ScriptGroup[] getGroups(String filter, ScriptPagingDetails paging, String sortBy)
|
||||
@ -261,54 +268,62 @@ public class ScriptAuthorityService extends BaseScopableProcessorExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives groups matching the given filter from the given zone.
|
||||
* Retrieves groups matching the given filter from the given zone.
|
||||
*
|
||||
* NOTE: If the filter is null, an empty string or * all groups found will be returned.
|
||||
* If the filter starts with * or contains a ? character results returned could be inconsistent.
|
||||
*
|
||||
* @param filter Pattern to filter groups by
|
||||
* @param zone The zone in which to search for groups
|
||||
* @param paging Paging details
|
||||
* @param sortBy Field to sort by, can be <code>shortName</code>, <code>displayName</code> or
|
||||
* <code>authorityName</code>, the default is displayName
|
||||
* @return Array of mathcing groups
|
||||
* @return Array of matching groups
|
||||
* @since 4.0
|
||||
*/
|
||||
public ScriptGroup[] getGroupsInZone(String filter, String zone, ScriptPagingDetails paging, String sortBy)
|
||||
{
|
||||
if (sortBy == null)
|
||||
{
|
||||
sortBy = "displayName";
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Start getGroupsInZone("+(filter == null ? "null" : '"'+filter+'"')+", "+zone+", {"+paging.getMaxItems()+" "+paging.getSkipCount()+"}, "+sortBy+")");
|
||||
}
|
||||
|
||||
// reset filter if necessary
|
||||
if (filter != null && (filter.length() == 0 || filter.equals("*")))
|
||||
{
|
||||
filter = null;
|
||||
}
|
||||
|
||||
if (filter != null && (filter.startsWith("*") || filter.indexOf("?") != -1))
|
||||
ScriptGroup[] scriptGroups = null;
|
||||
try
|
||||
{
|
||||
// contains and ? wildcard queries are not supported by canned queries so use search
|
||||
return searchGroupsInZone(filter, zone, paging, sortBy);
|
||||
// for backwards compatibility request a total count of found items, once the UI can deal with
|
||||
// results that do not specify the total number of results this can be removed
|
||||
paging.setRequestTotalCountMax(10000);
|
||||
|
||||
// get the paged results (NOTE: we can only sort by display name currently)
|
||||
PagingResults<AuthorityInfo> groups = authorityService.getAuthoritiesInfo(AuthorityType.GROUP, zone, filter, sortBy, true, paging);
|
||||
|
||||
// create ScriptGroup array from paged results
|
||||
scriptGroups = makeScriptGroupsInfo(groups, paging, serviceRegistry, this.getScope());
|
||||
}
|
||||
else
|
||||
catch (UnknownAuthorityException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// for backwards compatibility request a total count of found items, once the UI can deal with
|
||||
// results that do not specify the total number of results this can be removed
|
||||
paging.setRequestTotalCountMax(10000);
|
||||
|
||||
// get the paged results (NOTE: we can only sort by display name currently)
|
||||
PagingResults<String> groups = authorityService.getAuthorities(AuthorityType.GROUP, zone, filter, true, true, paging);
|
||||
|
||||
// create ScriptGroup array from paged results
|
||||
return makeScriptGroups(groups, paging, serviceRegistry, this.getScope());
|
||||
}
|
||||
catch (UnknownAuthorityException e)
|
||||
{
|
||||
return new ScriptGroup[] {};
|
||||
}
|
||||
scriptGroups = new ScriptGroup[] {};
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("End getGroupsInZone("+(filter == null ? "null" : '"'+filter+'"')+", "+zone+", {"+paging.getMaxItems()+" "+paging.getSkipCount()+"}, "+sortBy+") returns "+scriptGroups.length+"\n");
|
||||
}
|
||||
return scriptGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Get a group given its short name
|
||||
* @param shortName, the shortName of the group
|
||||
* @return the authority or null if it can't be found
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@ -33,6 +33,7 @@ import java.util.TreeSet;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.jscript.ScriptNode;
|
||||
import org.alfresco.repo.security.authority.AuthorityInfo;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
@ -60,6 +61,16 @@ public class ScriptGroup implements Authority, Serializable
|
||||
private NodeRef groupNodeRef;
|
||||
private Scriptable scope;
|
||||
|
||||
/**
|
||||
* New script group
|
||||
* @param fullName
|
||||
* @param serviceRegistry
|
||||
*/
|
||||
public ScriptGroup(String fullName, String displayName, ServiceRegistry serviceRegistry, Scriptable scope)
|
||||
{
|
||||
this(fullName, displayName, serviceRegistry, serviceRegistry.getAuthorityService(), scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* New script group
|
||||
* @param fullName
|
||||
@ -67,7 +78,7 @@ public class ScriptGroup implements Authority, Serializable
|
||||
*/
|
||||
public ScriptGroup(String fullName, ServiceRegistry serviceRegistry, Scriptable scope)
|
||||
{
|
||||
this(fullName, serviceRegistry, serviceRegistry.getAuthorityService(), scope);
|
||||
this(fullName, null, serviceRegistry, serviceRegistry.getAuthorityService(), scope);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,22 +89,23 @@ public class ScriptGroup implements Authority, Serializable
|
||||
*/
|
||||
public ScriptGroup(String fullName, AuthorityService authorityService)
|
||||
{
|
||||
this(fullName, null, authorityService, null);
|
||||
this(fullName, null, null, authorityService, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* New script group
|
||||
* @param fullName
|
||||
* @param displayName
|
||||
* @param authorityService
|
||||
*/
|
||||
private ScriptGroup(String fullName, ServiceRegistry serviceRegistry, AuthorityService authorityService, Scriptable scope)
|
||||
private ScriptGroup(String fullName, String displayName, ServiceRegistry serviceRegistry, AuthorityService authorityService, Scriptable scope)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
this.fullName = fullName;
|
||||
this.scope = scope;
|
||||
shortName = authorityService.getShortName(fullName);
|
||||
displayName = authorityService.getAuthorityDisplayName(fullName);
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,6 +159,7 @@ public class ScriptGroup implements Authority, Serializable
|
||||
*/
|
||||
public void setDisplayName(String displayName)
|
||||
{
|
||||
getDisplayName();
|
||||
if (this.displayName != null && !this.displayName.equals(displayName))
|
||||
{
|
||||
authorityService.setAuthorityDisplayName(fullName, displayName);
|
||||
@ -156,6 +169,10 @@ public class ScriptGroup implements Authority, Serializable
|
||||
|
||||
public String getDisplayName()
|
||||
{
|
||||
if (displayName == null)
|
||||
{
|
||||
displayName = authorityService.getAuthorityDisplayName(fullName);
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
@ -185,7 +202,7 @@ public class ScriptGroup implements Authority, Serializable
|
||||
Set<ScriptGroup> groups = new LinkedHashSet<ScriptGroup>();
|
||||
for (String authority : children)
|
||||
{
|
||||
ScriptGroup group = new ScriptGroup(authority, serviceRegistry, authorityService, this.scope);
|
||||
ScriptGroup group = new ScriptGroup(authority, null, serviceRegistry, authorityService, this.scope);
|
||||
groups.add(group);
|
||||
}
|
||||
return groups.toArray(new ScriptGroup[groups.size()]);
|
||||
@ -370,7 +387,7 @@ public class ScriptGroup implements Authority, Serializable
|
||||
LinkedHashSet<ScriptGroup> groups = new LinkedHashSet<ScriptGroup>();
|
||||
for (String authority : sortedParents)
|
||||
{
|
||||
ScriptGroup group = new ScriptGroup(authority, serviceRegistry, authorityService, this.scope);
|
||||
ScriptGroup group = new ScriptGroup(authority, null, serviceRegistry, authorityService, this.scope);
|
||||
groups.add(group);
|
||||
|
||||
}
|
||||
@ -437,7 +454,7 @@ public class ScriptGroup implements Authority, Serializable
|
||||
{
|
||||
String authorityName = authorityService.createAuthority(AuthorityType.GROUP, newShortName, newDisplayName, authorityService.getDefaultZones());
|
||||
authorityService.addAuthority(fullName, authorityName);
|
||||
ScriptGroup childGroup = new ScriptGroup(authorityName, serviceRegistry, authorityService, this.scope);
|
||||
ScriptGroup childGroup = new ScriptGroup(authorityName, null, serviceRegistry, authorityService, this.scope);
|
||||
clearCaches();
|
||||
return childGroup;
|
||||
}
|
||||
@ -530,7 +547,7 @@ public class ScriptGroup implements Authority, Serializable
|
||||
}
|
||||
|
||||
public static ScriptGroup[] makeScriptGroups(Collection<String> authorities,
|
||||
ScriptPagingDetails paging, final String sortBy, ServiceRegistry serviceRegistry,
|
||||
ScriptPagingDetails paging, String sortBy, ServiceRegistry serviceRegistry,
|
||||
Scriptable scope)
|
||||
{
|
||||
|
||||
@ -617,6 +634,35 @@ public class ScriptGroup implements Authority, Serializable
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of ScriptGroup objects representing the given paged results.
|
||||
*
|
||||
* @param groups The paged results
|
||||
* @param paging Object representing the paging details
|
||||
* @param serviceRegistry
|
||||
* @param scope
|
||||
* @return Array of ScriptGroup objects
|
||||
*
|
||||
* @since 4.1.3
|
||||
*/
|
||||
public static ScriptGroup[] makeScriptGroupsInfo(PagingResults<AuthorityInfo> pagedGroups, ScriptPagingDetails paging,
|
||||
ServiceRegistry serviceRegistry, Scriptable scope)
|
||||
{
|
||||
// set the total on the paging object
|
||||
paging.setTotalItems(pagedGroups);
|
||||
|
||||
// retrive the page of results and create a ScriptGroup for each one
|
||||
List<AuthorityInfo> groupInfo = pagedGroups.getPage();
|
||||
ScriptGroup[] groups = new ScriptGroup[groupInfo.size()];
|
||||
for (int i=0; i<groups.length; i++)
|
||||
{
|
||||
AuthorityInfo authorityInfo = groupInfo.get(i);
|
||||
groups[i] = new ScriptGroup(authorityInfo.getAuthorityName(), authorityInfo.getAuthorityDisplayName(), serviceRegistry, scope);
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the zones of this group
|
||||
*
|
||||
@ -629,4 +675,4 @@ public class ScriptGroup implements Authority, Serializable
|
||||
{
|
||||
return authorityService.getAuthorityZones(fullName);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@ -23,6 +23,7 @@ import java.util.Set;
|
||||
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.security.authority.AuthorityInfo;
|
||||
import org.alfresco.service.Auditable;
|
||||
import org.alfresco.service.NotAuditable;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@ -138,6 +139,25 @@ public interface AuthorityService
|
||||
@Auditable(parameters = {"type"})
|
||||
public Set<String> getAllAuthorities(AuthorityType type);
|
||||
|
||||
/**
|
||||
* Get authorities by type and/or zone
|
||||
*
|
||||
* @param type the type of authorities (note: mandatory if zoneName is null)
|
||||
* @param zoneName the zoneName (note: mandatory if type is null)
|
||||
* @param displayNameFilter optional filter (startsWith / ignoreCase) for authority display name (note: implied trailing "*")
|
||||
* @param sortBy either "displayName", "shortName", "authorityName" or null if no sorting.
|
||||
* note: for users, displayName/shortName is equivalent to the userName, for groups if the display is null then use the short name
|
||||
* @param sortAscending if true then sort ascending else sort descending (ignore if sortByDisplayName is false)
|
||||
* @param pagingRequest the requested page (skipCount, maxItems, queryExectionId)
|
||||
*
|
||||
* @throws UnknownAuthorityException - if zoneName is not null and does not exist
|
||||
*
|
||||
* @author janv
|
||||
* @since 4.0
|
||||
*/
|
||||
@Auditable(parameters = {"type", "zoneName", "displayNameFilter", "sortByDisplayName", "sortAscending", "pagingRequest"})
|
||||
public PagingResults<AuthorityInfo> getAuthoritiesInfo(AuthorityType type, String zoneName, String displayNameFilter, String sortBy, boolean sortAscending, PagingRequest pagingRequest);
|
||||
|
||||
/**
|
||||
* Get authorities by type and/or zone
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user