Merged V2.0 to HEAD

5448: (From V1.4)
      5281 (V1.4): Patches not executed in read-only mode
      5284 (V1.4): Integrity messages
      5308 (V1.4): Category selector performance
      5331 (V1.4): Category performance
      5402 (V1.4): AR-1315
      5410 (V1.4): 
      5417 (V1.4): Upgrade script performance
      5435 (V1.4): Lucene test text encoding


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5482 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley 2007-04-11 23:24:00 +00:00
parent d3e08db677
commit 4ea83f7f2b
15 changed files with 183 additions and 22 deletions

View File

@ -282,6 +282,9 @@
<!-- This component ensures that patches get applied on startup -->
<bean id="patchExecuter" class="org.alfresco.repo.admin.patch.PatchExecuter">
<property name="transactionService">
<ref bean="transactionComponent" />
</property>
<property name="patchService">
<ref bean="PatchService" />
</property>

View File

@ -27,6 +27,8 @@ CREATE TABLE alf_transaction (
KEY FKB8761A3A9AE340B7 (server_id),
CONSTRAINT FKB8761A3A9AE340B7 FOREIGN KEY (server_id) REFERENCES alf_server (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- add index for perfromance
create index ug_index_142_1 on alf_transaction (change_txn_id);
insert into alf_transaction
(
server_id, change_txn_id
@ -41,6 +43,8 @@ UPDATE alf_node_status ns SET ns.transaction_id =
(
select t.id from alf_transaction t where t.change_txn_id = ns.change_txn_id
);
-- remove index added for performance
ALTER TABLE alf_node_status
DROP COLUMN change_txn_id,
ADD CONSTRAINT FK71C2002B9E57C13D FOREIGN KEY (transaction_id) REFERENCES alf_transaction (id),
@ -48,7 +52,7 @@ ALTER TABLE alf_node_status
ALTER TABLE alf_node_status
DROP COLUMN deleted
;(optional)
drop index ug_index_142_1 on alf_transaction;
--
-- Record script finish
--

View File

@ -2,6 +2,7 @@
patch.service.not_relevant=Not relevant to schema {0}
patch.executer.checking=Checking for patches to apply ...
patch.executer.no_patches_required=No patches were required.
patch.executer.system_readonly=Patches cannot be applied to a read-only system. Possible incompatibilities may exist between the application code and the existing data.
patch.executer.not_executed =\n=== Recorded patch (not executed) === \nID: {0}\nRESULT: \n{1}\n=====================================
patch.executer.executed =\n=== Applied patch === \nID: {0}\nRESULT: \n{1}\n=====================================
patch.executer.failed =\n=== Failed to apply patch === \nID: {0}\nRESULT: \n{1}\n=====================================

View File

@ -308,9 +308,6 @@
<!-- owner permissions. -->
<includePermissionGroup permissionGroup="Consumer" type="cm:cmobject"/>
<includePermissionGroup permissionGroup="AddChildren" type="sys:base"/>
<!-- Check out requires write permissions so this will not apply to all -->
<!-- documents. -->
<includePermissionGroup type="cm:lockable" permissionGroup="CheckOut"/>
</permissionGroup>
<!-- An editor can read and write to the object; they can not create -->

View File

@ -29,6 +29,7 @@ import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.AbstractLifecycleBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -44,6 +45,7 @@ public class PatchExecuter extends AbstractLifecycleBean
{
private static final String MSG_CHECKING = "patch.executer.checking";
private static final String MSG_NO_PATCHES_REQUIRED = "patch.executer.no_patches_required";
private static final String MSG_SYSTEM_READ_ONLY = "patch.executer.system_readonly";
private static final String MSG_NOT_EXECUTED = "patch.executer.not_executed";
private static final String MSG_EXECUTED = "patch.executer.executed";
private static final String MSG_FAILED = "patch.executer.failed";
@ -51,6 +53,7 @@ public class PatchExecuter extends AbstractLifecycleBean
private static Log logger = LogFactory.getLog(PatchExecuter.class);
private PatchService patchService;
private TransactionService transactionService;
/**
* @param patchService the server that actually executes the patches
@ -59,12 +62,27 @@ public class PatchExecuter extends AbstractLifecycleBean
{
this.patchService = patchService;
}
/**
* @param transactionService provides the system read-only state
*/
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/**
* Ensures that all outstanding patches are applied.
*/
public void applyOutstandingPatches()
{
// Avoid read-only systems
if (transactionService.isReadOnly())
{
logger.warn(I18NUtil.getMessage(MSG_SYSTEM_READ_ONLY));
return;
}
logger.info(I18NUtil.getMessage(MSG_CHECKING));
Date before = new Date(System.currentTimeMillis() - 60000L); // 60 seconds ago

View File

@ -101,6 +101,7 @@ public class AssocSourceMultiplicityIntegrityEvent extends AbstractIntegrityEven
{
IntegrityRecord result = new IntegrityRecord(
"Association type does not exist: \n" +
" Target Node: " + targetNodeRef + "\n" +
" Target Node Type: " + targetNodeTypeQName + "\n" +
" Association Type: " + assocTypeQName);
eventResults.add(result);
@ -156,6 +157,7 @@ public class AssocSourceMultiplicityIntegrityEvent extends AbstractIntegrityEven
String parentOrSourceStr = (assocDef.isChild() ? "parent" : "source");
IntegrityRecord result = new IntegrityRecord(
"The association " + parentOrSourceStr + " multiplicity has been violated: \n" +
" Target Node: " + targetNodeRef + "\n" +
" Association: " + assocDef + "\n" +
" Required " + parentOrSourceStr + " Multiplicity: " + getMultiplicityString(mandatory, allowMany) + "\n" +
" Actual " + parentOrSourceStr + " Multiplicity: " + actualSize);

View File

@ -82,6 +82,7 @@ public class AssocSourceTypeIntegrityEvent extends AbstractIntegrityEvent
{
IntegrityRecord result = new IntegrityRecord(
"Association type does not exist: \n" +
" Source Node: " + sourceNodeRef + "\n" +
" Source Node Type: " + sourceNodeTypeQName + "\n" +
" Association Type: " + assocTypeQName);
eventResults.add(result);
@ -110,6 +111,7 @@ public class AssocSourceTypeIntegrityEvent extends AbstractIntegrityEvent
{
IntegrityRecord result = new IntegrityRecord(
"The association source type is incorrect: \n" +
" Source Node: " + sourceNodeRef + "\n" +
" Association: " + assocDef + "\n" +
" Required Source Type: " + sourceDef.getName() + "\n" +
" Actual Source Type: " + sourceNodeTypeQName);
@ -133,6 +135,7 @@ public class AssocSourceTypeIntegrityEvent extends AbstractIntegrityEvent
{
IntegrityRecord result = new IntegrityRecord(
"The association source is missing the aspect required for this association: \n" +
" Source Node: " + sourceNodeRef + "\n" +
" Association: " + assocDef + "\n" +
" Required Source Aspect: " + sourceDef.getName() + "\n" +
" Actual Source Aspects: " + sourceAspects);
@ -143,6 +146,7 @@ public class AssocSourceTypeIntegrityEvent extends AbstractIntegrityEvent
{
IntegrityRecord result = new IntegrityRecord(
"Unknown ClassDefinition subclass on the source definition: \n" +
" Source Node: " + sourceNodeRef + "\n" +
" Association: " + assocDef + "\n" +
" Source Definition: " + sourceDef.getName());
eventResults.add(result);

View File

@ -101,6 +101,7 @@ public class AssocTargetMultiplicityIntegrityEvent extends AbstractIntegrityEven
{
IntegrityRecord result = new IntegrityRecord(
"Association type does not exist: \n" +
" Source Node: " + sourceNodeRef + "\n" +
" Source Node Type: " + sourceNodeTypeQName + "\n" +
" Association Type: " + assocTypeQName);
eventResults.add(result);
@ -156,6 +157,7 @@ public class AssocTargetMultiplicityIntegrityEvent extends AbstractIntegrityEven
String childOrTargetStr = (assocDef.isChild() ? "child" : "target");
IntegrityRecord result = new IntegrityRecord(
"The association " + childOrTargetStr + " multiplicity has been violated: \n" +
" Source Node: " + sourceNodeRef + "\n" +
" Association: " + assocDef + "\n" +
" Required " + childOrTargetStr + " Multiplicity: " + getMultiplicityString(mandatory, allowMany) + "\n" +
" Actual " + childOrTargetStr + " Multiplicity: " + actualSize);

View File

@ -55,6 +55,7 @@ public class AssocTargetRoleIntegrityEvent extends AbstractIntegrityEvent
{
QName assocTypeQName = getTypeQName();
QName assocQName = getQName();
NodeRef sourceNodeRef = getNodeRef();
// get the association def
AssociationDefinition assocDef = getAssocDef(eventResults, assocTypeQName);
@ -80,7 +81,7 @@ public class AssocTargetRoleIntegrityEvent extends AbstractIntegrityEvent
ChildAssociationDefinition childAssocDef = (ChildAssociationDefinition) assocDef;
// perform required checks
checkAssocQNameRegex(eventResults, childAssocDef, assocQName);
checkAssocQNameRegex(eventResults, childAssocDef, assocQName, sourceNodeRef);
}
/**
@ -89,7 +90,8 @@ public class AssocTargetRoleIntegrityEvent extends AbstractIntegrityEvent
protected void checkAssocQNameRegex(
List<IntegrityRecord> eventResults,
ChildAssociationDefinition assocDef,
QName assocQName)
QName assocQName,
NodeRef sourceNodeRef)
{
// check the association name
QName assocRoleQName = assocDef.getTargetRoleName();
@ -101,6 +103,7 @@ public class AssocTargetRoleIntegrityEvent extends AbstractIntegrityEvent
{
IntegrityRecord result = new IntegrityRecord(
"The association name does not match the allowed role names: \n" +
" Source Node: " + sourceNodeRef + "\n" +
" Association: " + assocDef + "\n" +
" Allowed roles: " + rolePattern + "\n" +
" Name assigned: " + assocRoleQName);

View File

@ -82,6 +82,7 @@ public class AssocTargetTypeIntegrityEvent extends AbstractIntegrityEvent
{
IntegrityRecord result = new IntegrityRecord(
"Association type does not exist: \n" +
" Target Node: " + targetNodeRef + "\n" +
" Target Node Type: " + targetNodeTypeQName + "\n" +
" Association Type: " + assocTypeQName);
eventResults.add(result);
@ -110,6 +111,7 @@ public class AssocTargetTypeIntegrityEvent extends AbstractIntegrityEvent
{
IntegrityRecord result = new IntegrityRecord(
"The association target type is incorrect: \n" +
" Target Node: " + targetNodeRef + "\n" +
" Association: " + assocDef + "\n" +
" Required Target Type: " + targetDef.getName() + "\n" +
" Actual Target Type: " + targetNodeTypeQName);
@ -133,6 +135,7 @@ public class AssocTargetTypeIntegrityEvent extends AbstractIntegrityEvent
{
IntegrityRecord result = new IntegrityRecord(
"The association target is missing the aspect required for this association: \n" +
" Target Node: " + targetNodeRef + "\n" +
" Association: " + assocDef + "\n" +
" Required Target Aspect: " + targetDef.getName() + "\n" +
" Actual Target Aspects: " + targetAspects);
@ -143,6 +146,7 @@ public class AssocTargetTypeIntegrityEvent extends AbstractIntegrityEvent
{
IntegrityRecord result = new IntegrityRecord(
"Unknown ClassDefinition subclass on the target definition: \n" +
" Target Node: " + targetNodeRef + "\n" +
" Association: " + assocDef + "\n" +
" Source Definition: " + targetDef.getName());
eventResults.add(result);

View File

@ -97,19 +97,9 @@ public class LuceneCategoryServiceImpl implements CategoryService
{
StringBuilder luceneQuery = new StringBuilder(64);
if (!mode.equals(Mode.ALL))
{
luceneQuery.append(mode.equals(Mode.SUB_CATEGORIES) ? "-" : "").append("PATH:\"");
luceneQuery.append(buildXPath(nodeService.getPath(categoryRef))).append("/");
if (depth.equals(Depth.ANY))
{
luceneQuery.append("/");
}
luceneQuery.append("member").append("\" ");
}
if (!mode.equals(Mode.MEMBERS))
switch(mode)
{
case ALL:
luceneQuery.append("PATH:\"");
luceneQuery.append(buildXPath(nodeService.getPath(categoryRef))).append("/");
if (depth.equals(Depth.ANY))
@ -117,6 +107,26 @@ public class LuceneCategoryServiceImpl implements CategoryService
luceneQuery.append("/");
}
luceneQuery.append("*").append("\" ");
break;
case MEMBERS:
luceneQuery.append("PATH:\"");
luceneQuery.append(buildXPath(nodeService.getPath(categoryRef))).append("/");
if (depth.equals(Depth.ANY))
{
luceneQuery.append("/");
}
luceneQuery.append("member").append("\" ");
break;
case SUB_CATEGORIES:
luceneQuery.append("+PATH:\"");
luceneQuery.append(buildXPath(nodeService.getPath(categoryRef))).append("/");
if (depth.equals(Depth.ANY))
{
luceneQuery.append("/");
}
luceneQuery.append("*").append("\" ");
luceneQuery.append("+TYPE:\"" + ContentModel.TYPE_CATEGORY.toString() + "\"");
break;
}
resultSet = indexerAndSearcher.getSearcher(categoryRef.getStoreRef(), false).query(categoryRef.getStoreRef(), "lucene", luceneQuery.toString(), null, null);

View File

@ -664,7 +664,96 @@ public class LuceneCategoryTest2 extends TestCase
tx.rollback();
}
public void xtestManyCategories() throws Exception
{
TransactionService transactionService = serviceRegistry.getTransactionService();
UserTransaction tx = transactionService.getUserTransaction();
tx.begin();
long start = System.nanoTime();
int startCount = categoryService.getRootCategories(serviceRegistry.getPersonService().getPeopleContainer().getStoreRef(),
ContentModel.ASPECT_GEN_CLASSIFIABLE).size();
System.out.println("1 Query complete in "+(System.nanoTime()-start)/1e9f);
tx.commit();
tx = transactionService.getUserTransaction();
tx.begin();
start = System.nanoTime();
startCount = categoryService.getRootCategories(serviceRegistry.getPersonService().getPeopleContainer().getStoreRef(),
ContentModel.ASPECT_GEN_CLASSIFIABLE).size();
System.out.println("2 Query complete in "+(System.nanoTime()-start)/1e9f);
tx.commit();
for (int i = 0; i < 0; i++)
{
tx = transactionService.getUserTransaction();
tx.begin();
categoryService.createRootCategory(serviceRegistry.getPersonService().getPeopleContainer().getStoreRef(), ContentModel.ASPECT_GEN_CLASSIFIABLE, "first" + i);
tx.commit();
}
for (int j = 0; j < 10; j++)
{
tx = transactionService.getUserTransaction();
tx.begin();
for (int i = 0; i < 1; i++)
{
NodeRef topref = categoryService.createRootCategory(serviceRegistry.getPersonService().getPeopleContainer().getStoreRef(),ContentModel.ASPECT_GEN_CLASSIFIABLE, "third" + (j*100)+ i);
for(int k = 0; k < 5; k++)
{
NodeRef oneRef = categoryService.createCategory(topref, "child_"+i+"_"+j+"_"+k);
for(int l = 0; l < 5; l++)
{
NodeRef twoRef = categoryService.createCategory(oneRef, "child_"+i+"_"+j+"_"+k+"_"+l);
for(int m = 0; m < 5; m++)
{
NodeRef threeRef = categoryService.createCategory(twoRef, "child_"+i+"_"+j+"_"+k+"_"+l+"_"+m);
for(int n = 0; n < 5; n++)
{
NodeRef fourRef = categoryService.createCategory(threeRef, "child_"+i+"_"+j+"_"+k+"_"+l+"_"+m+"_"+n);
for(int o = 0; o < 5; o++)
{
NodeRef fiveRef = categoryService.createCategory(fourRef, "child_"+i+"_"+j+"_"+k+"_"+l+"_"+m+"_"+n+"_"+o);
for(int p = 0; p < 5; p++)
{
NodeRef sixRef = categoryService.createCategory(fiveRef, "child_"+i+"_"+j+"_"+k+"_"+l+"_"+m+"_"+n+"_"+o+"_"+p);
}
}
}
}
}
}
}
tx.commit();
}
tx = transactionService.getUserTransaction();
tx.begin();
start = System.nanoTime();
assertEquals(startCount + 10, categoryService.getRootCategories(serviceRegistry.getPersonService().getPeopleContainer().getStoreRef(),
ContentModel.ASPECT_GEN_CLASSIFIABLE).size());
System.out.println("3 Query complete in "+(System.nanoTime()-start)/1e9f);
tx.commit();
tx = transactionService.getUserTransaction();
tx.begin();
start = System.nanoTime();
assertEquals(startCount + 10, categoryService.getRootCategories(serviceRegistry.getPersonService().getPeopleContainer().getStoreRef(),
ContentModel.ASPECT_GEN_CLASSIFIABLE).size());
System.out.println("4 Query complete in "+(System.nanoTime()-start)/1e9f);
tx.commit();
tx = transactionService.getUserTransaction();
tx.begin();
start = System.nanoTime();
ResultSet set = searcher.query(serviceRegistry.getPersonService().getPeopleContainer().getStoreRef(), "lucene", "@"+LuceneQueryParser.escape(ContentModel.ASPECT_GEN_CLASSIFIABLE.toString())+":second*");
System.out.println("Query complete in "+(System.nanoTime()-start)/1e9f);
tx.commit();
}
private int getTotalScore(ResultSet results)
{
int totalScore = 0;

View File

@ -373,13 +373,14 @@ public class LuceneTest2 extends TestCase
getOrderProperties()).getChildRef();
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
properties.put(ContentModel.PROP_CONTENT, new ContentData(null, "text/plain", 0L, "UTF-16"));
properties.put(ContentModel.PROP_CONTENT, new ContentData(null, "text/plain", 0L, "UTF-8"));
n14 = nodeService.createNode(n13, ASSOC_TYPE_QNAME, QName.createQName("{namespace}fourteen"),
ContentModel.TYPE_CONTENT, properties).getChildRef();
// nodeService.addAspect(n14, DictionaryBootstrap.ASPECT_QNAME_CONTENT,
// properties);
ContentWriter writer = contentService.getWriter(n14, ContentModel.PROP_CONTENT, true);
writer.setEncoding("UTF-8");
// InputStream is =
// this.getClass().getClassLoader().getResourceAsStream("test.doc");
// writer.putContent(is);

View File

@ -93,6 +93,27 @@ public class PermissionServiceTest extends AbstractPermissionTest
"andy", AccessStatus.ALLOWED);
}
public void testDefaultModelPermissions()
{
runAs("admin");
NodeRef n1 = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN,
QName.createQName("{namespace}one"), ContentModel.TYPE_FOLDER).getChildRef();
runAs("andy");
assertTrue(permissionService.hasPermission(n1, getPermission(PermissionService.CONTRIBUTOR)) == AccessStatus.DENIED);
runAs("admin");
permissionService.setPermission(new SimplePermissionEntry(n1, getPermission(PermissionService.CONTRIBUTOR),
"andy", AccessStatus.ALLOWED));
runAs("andy");
assertTrue(permissionService.hasPermission(n1, getPermission(PermissionService.CONTRIBUTOR)) == AccessStatus.ALLOWED);
}
public void testSystemUserPermissions()
{
AuthenticationUtil.setSystemUserAsCurrentUser();
@ -1883,6 +1904,8 @@ public class PermissionServiceTest extends AbstractPermissionTest
}
// TODO: Test permissions on missing nodes
}

View File

@ -63,7 +63,7 @@ public class PermissionModelTest extends AbstractPermissionTest
Set<PermissionReference> grantees = permissionModelDAO.getGranteePermissions(new SimplePermissionReference(QName.createQName("cm", "cmobject",
namespacePrefixResolver), "Contributor"));
assertEquals(17, grantees.size());
assertEquals(14, grantees.size());
}
public void testIncludePermissionGroups3()