Merged V2.0 to HEAD

5457: Merge error on copy web project action
   5459: AR-1278
   5461:
   5462: A few deployment fixes
   5469: Dictionary messages
   5470: L2 cache checks
   5478: WCM-374


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5485 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-04-12 02:02:42 +00:00
parent 138d1780cb
commit 0570c77f46
16 changed files with 473 additions and 221 deletions

View File

@@ -1,112 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="java.io.tmpdir"/>
<cacheManagerEventListenerFactory class="" properties=""/>
<defaultCache
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.AVMNodeImpl"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.FileContentImpl"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.RepositoryImpl"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.VersionRootImpl"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.ChildEntryImpl"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="ChildEntry.ByNameParent"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="ChildEntry.ByParent"
maxElementsInMemory="500"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="ChildEntry.ByParentChild"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.DeletedChildImpl"
maxElementsInMemory="2000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="DeletedChild.ByParent"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="Property.Lookup"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="Properties.Lookup"
maxElementsInMemory="2000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="500"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="500"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
<hibernate-configuration>
<session-factory>
<!--
<property name="connection.username">britt</property>
<property name="connection.password"></property>
<property name="connection.url">jdbc:postgresql://127.0.0.1/avm</property>
<property name="connection.driver_class">org.postgresql.Driver</property>
-->
<property name="connection.username">root</property>
<property name="connection.password"></property>
<property name="connection.url">jdbc:mysql://127.0.0.1/avm</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="current_session_context_class">thread</property>
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<!-- <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property> -->
<property name="show_sql">false</property>
<property name="order_updates">false</property>
<property name="connection.isolation">2</property>
<!--
<property name="connection.connection_provider">org.sciencething.cpool.ConnectionProvider</property>
<property name="cpool.size">20</property>
-->
<property name="c3p0.min_size">4</property>
<property name="c3p0.max_size">32</property>
<property name="c3p0.timeout">60</property>
<property name="c3p0.max_statements">0</property>
<property name="c3p0.idle_test_period">60</property>
<property name="default_batch_fetch_size">16</property>
<property name="jdbc.batch_versioned_data">true</property>
<property name="jdbc.batch_size">15</property>
<property name="cach.use_second_level_cache">true</property>
<property name="cache.use_query_cache">true</property>
<mapping resource="org/alfresco/repo/avm/hibernate/AVM.hbm.xml"/>
</session-factory>
</hibernate-configuration>

View File

@@ -0,0 +1,166 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing
*/
package org.alfresco.repo.admin.patch.impl;
import java.io.Serializable;
import java.util.List;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.admin.patch.AbstractPatch;
import org.alfresco.repo.importer.ImporterBootstrap;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.QName;
/**
* Patch usr:user and cm:person objects so that the user name properties are in the index in untokenized form. If not authentication may fail in mixed language use.
*
* @author andyh
*/
public class InvalidUserPersonAndGroupPatch extends AbstractPatch
{
private static final String MSG_SUCCESS = "patch.invalidUserPersonAndGroup.result";
private ImporterBootstrap spacesImporterBootstrap;
private ImporterBootstrap userImporterBootstrap;
private DictionaryService dictionaryService;
public InvalidUserPersonAndGroupPatch()
{
}
public void setSpacesImporterBootstrap(ImporterBootstrap spacesImporterBootstrap)
{
this.spacesImporterBootstrap = spacesImporterBootstrap;
}
public void setUserImporterBootstrap(ImporterBootstrap userImporterBootstrap)
{
this.userImporterBootstrap = userImporterBootstrap;
}
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
@Override
protected String applyInternal() throws Exception
{
int users = deleteInvalid(ContentModel.PROP_USER_USERNAME, userImporterBootstrap.getStoreRef(), "USER_");
int people = deleteInvalid(ContentModel.PROP_USERNAME, spacesImporterBootstrap.getStoreRef(), "USER_");
int authorities = deleteInvalid(ContentModel.PROP_AUTHORITY_NAME, userImporterBootstrap.getStoreRef(), "GROUP_");
return I18NUtil.getMessage(MSG_SUCCESS, users, people, authorities);
}
private int deleteInvalid(QName property, StoreRef store, String prefix)
{
PropertyDefinition propDef = dictionaryService.getProperty(property);
if (propDef == null)
{
return 0;
}
ClassDefinition typeDef = propDef.getContainerClass();
String query;
if (typeDef.isAspect())
{
query = "ASPECT:\"" + typeDef.getName() + "\"";
}
else
{
query = "TYPE:\"" + typeDef.getName() + "\"";
}
List<ConstraintDefinition> conDefs = propDef.getConstraints();
SearchParameters sp = new SearchParameters();
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
sp.setQuery(query);
sp.addStore(store);
ResultSet rs = null;
int invalidCount = 0;
try
{
rs = searchService.query(sp);
for (ResultSetRow row : rs)
{
NodeRef nodeRef = row.getNodeRef();
boolean valid = true;
Serializable value = nodeService.getProperty(nodeRef, property);
String checkValue = null;
try
{
checkValue = DefaultTypeConverter.INSTANCE.convert(String.class, value);
}
catch (TypeConversionException e)
{
continue;
}
for (ConstraintDefinition con : conDefs)
{
try
{
con.getConstraint().evaluate(value);
}
catch (ConstraintException e)
{
valid = false;
}
}
if(!valid)
{
nodeService.setProperty(nodeRef, property, prefix+checkValue);
invalidCount++;
}
}
}
finally
{
if (rs != null)
{
rs.close();
}
}
return invalidCount;
}
}

View File

@@ -195,19 +195,21 @@ public class AVMDeploySnapshotAction extends ActionExecuterAbstractBase
DeploymentReport report = null;
try
{
String host = targetServer;
int port = defaultRmiPort;
// check whether there is a port number present, if so, use it
int idx = targetServer.indexOf(":");
if (idx != -1)
{
host = targetServer.substring(0, idx);
String strPort = targetServer.substring(idx+1);
port = Integer.parseInt(strPort);
}
// TODO: we need to capture username/password for the remote server at some
// point, for now we use the admin/admin account, need to externalise this too!
report = this.deployService.deployDifference(version, path, targetServer, port,
// point, for now we use the configured username/password for all servers
report = this.deployService.deployDifference(version, path, host, port,
remoteUsername, remotePassword, targetPath, true, false, false, callback);
}
catch (Throwable err)
@@ -247,8 +249,7 @@ public class AVMDeploySnapshotAction extends ActionExecuterAbstractBase
}
// create the deployment report node
createDeploymentReportNode(report, (String)action.getParameterValue(PARAM_TARGET_SERVER),
version, websiteRef, startDate, deployError);
createDeploymentReportNode(report, targetServer, version, websiteRef, startDate, deployError);
}
/**

View File

@@ -46,40 +46,48 @@ import org.springframework.beans.PropertyAccessException;
*
* @author Derek Hulley
*/
/*package*/ class M2ConstraintDefinition implements ConstraintDefinition
/* package */class M2ConstraintDefinition implements ConstraintDefinition
{
public static final String ERR_CYCLIC_REF = "d_dictionary.constraint.err.cyclic_ref";
public static final String ERR_TYPE_AND_REF = "d_dictionary.constraint.err.type_and_ref";
public static final String ERR_TYPE_OR_REF = "d_dictionary.constraint.err.type_or_ref";
public static final String ERR_REF_NOT_FOUND = "d_dictionary.constraint.err.ref_not_found";
public static final String ERR_ANON_NEEDS_PROPERTY = "d_dictionary.constraint.err.anon_needs_property";
public static final String ERR_INVALID_TYPE = "d_dictionary.constraint.err.invalid_type";
public static final String ERR_SIMPLE_AND_LIST = "d_dictionary.constraint.err.property_simple_and_list";
public static final String ERR_CONSTRUCT_FAILURE = "d_dictionary.constraint.err.construct_failure";
public static final String ERR_PROPERTY_MISMATCH = "d_dictionary.constraint.err.property_mismatch";
private static int anonPropCount = 0;
private ModelDefinition model;
private NamespacePrefixResolver prefixResolver;
private M2Constraint m2Constraint;
private QName name;
private Constraint constraint;
private boolean resolving;
/*package*/ M2ConstraintDefinition(
M2PropertyDefinition m2PropertyDef,
M2Constraint m2Constraint,
/* package */M2ConstraintDefinition(M2PropertyDefinition m2PropertyDef, M2Constraint m2Constraint,
NamespacePrefixResolver prefixResolver)
{
this(m2PropertyDef.getModel(), m2PropertyDef, m2Constraint, prefixResolver);
}
/*package*/ M2ConstraintDefinition(
ModelDefinition modelDefinition,
M2PropertyDefinition m2PropertyDef,
M2Constraint m2Constraint,
NamespacePrefixResolver prefixResolver)
/* package */M2ConstraintDefinition(ModelDefinition modelDefinition, M2PropertyDefinition m2PropertyDef,
M2Constraint m2Constraint, NamespacePrefixResolver prefixResolver)
{
this.model = modelDefinition;
this.m2Constraint = m2Constraint;
@@ -103,8 +111,8 @@ import org.springframework.beans.PropertyAccessException;
this.name = QName.createQName(m2Constraint.getName(), prefixResolver);
}
}
/*package*/ synchronized void resolveDependencies(ModelQuery query)
/* package */synchronized void resolveDependencies(ModelQuery query)
{
if (resolving)
{
@@ -121,7 +129,7 @@ import org.springframework.beans.PropertyAccessException;
resolving = false;
}
}
private synchronized void resolveInternal(ModelQuery query)
{
if (constraint != null)
@@ -187,39 +195,43 @@ import org.springframework.beans.PropertyAccessException;
// property setters
BeanWrapper beanWrapper = new BeanWrapperImpl(constraint);
List<M2NamedValue> constraintNamedValues = m2Constraint.getParameters();
for (M2NamedValue namedValue : constraintNamedValues)
if (constraintNamedValues != null)
{
Object value = null;
if (namedValue.getSimpleValue() != null && namedValue.getListValue() != null)
for (M2NamedValue namedValue : constraintNamedValues)
{
throw new DictionaryException(ERR_SIMPLE_AND_LIST, shortName, namedValue.getName());
}
else if (namedValue.getSimpleValue() != null)
{
value = namedValue.getSimpleValue();
}
else if (namedValue.getListValue() != null)
{
value = namedValue.getListValue();
}
try
{
beanWrapper.setPropertyValue(namedValue.getName(), value);
}
catch (PropertyAccessException e)
{
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValue.getName(), shortName);
}
catch (InvalidPropertyException e)
{
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValue.getName(), shortName);
Object value = null;
if (namedValue.getSimpleValue() != null && namedValue.getListValue() != null)
{
throw new DictionaryException(ERR_SIMPLE_AND_LIST, shortName, namedValue.getName());
}
else if (namedValue.getSimpleValue() != null)
{
value = namedValue.getSimpleValue();
}
else if (namedValue.getListValue() != null)
{
value = namedValue.getListValue();
}
try
{
beanWrapper.setPropertyValue(namedValue.getName(), value);
}
catch (PropertyAccessException e)
{
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValue.getName(), shortName);
}
catch (InvalidPropertyException e)
{
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValue.getName(), shortName);
}
}
}
// now initialize
constraint.initialize();
}
}
/**
* @see #getName()
*/
@@ -228,7 +240,7 @@ import org.springframework.beans.PropertyAccessException;
{
return getName().toString();
}
public ModelDefinition getModel()
{
return model;
@@ -243,7 +255,7 @@ import org.springframework.beans.PropertyAccessException;
{
return constraint;
}
/**
* Well-known constraint types
*/

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing
*/
package org.alfresco.repo.dictionary.constraint;
import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
import org.alfresco.service.cmr.security.AuthorityType;
public class AuthorityNameConstraint extends AbstractConstraint
{
private static final String ERR_INVALID_AUTHORITY_NAME = "d_dictionary.constraint.authority_name.invalid_authority_name";
private static final String ERR_NON_STRING = "d_dictionary.constraint.authority_name.non_string";
@Override
protected void evaluateSingleValue(Object value)
{
// ensure that the value can be converted to a String
String checkValue = null;
try
{
checkValue = DefaultTypeConverter.INSTANCE.convert(String.class, value);
}
catch (TypeConversionException e)
{
throw new ConstraintException(ERR_NON_STRING, value);
}
AuthorityType type = AuthorityType.getAuthorityType(checkValue);
if((type != AuthorityType.GROUP) && (type != AuthorityType.ROLE))
{
throw new ConstraintException(ERR_INVALID_AUTHORITY_NAME, value, type);
}
}
public void initialize()
{
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing
*/
package org.alfresco.repo.dictionary.constraint;
import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
import org.alfresco.service.cmr.security.AuthorityType;
/**
* Apply constraints for user names.
*
* @author andyh
*
*/
public class UserNameConstraint extends AbstractConstraint
{
private static final String ERR_INVALID_USERNAME = "d_dictionary.constraint.user_name.invalid_user_name";
private static final String ERR_NON_STRING = "d_dictionary.constraint.user_name.non_string";
@Override
protected void evaluateSingleValue(Object value)
{
// ensure that the value can be converted to a String
String checkValue = null;
try
{
checkValue = DefaultTypeConverter.INSTANCE.convert(String.class, value);
}
catch (TypeConversionException e)
{
throw new ConstraintException(ERR_NON_STRING, value);
}
AuthorityType type = AuthorityType.getAuthorityType(checkValue);
if((type != AuthorityType.USER) && (type != AuthorityType.GUEST))
{
throw new ConstraintException(ERR_INVALID_USERNAME, value, type);
}
}
public void initialize()
{
}
}

View File

@@ -314,8 +314,15 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
// create the node instance
Node childNode = nodeDaoService.newNode(store, newId, nodeTypeQName);
// get the parent node
// Get the parent node
Node parentNode = getNodeNotNull(parentRef);
// Create the association
ChildAssoc childAssoc = nodeDaoService.newChildAssoc(
parentNode,
childNode,
true,
assocTypeQName,
assocQName);
// Set the default property values
addDefaultPropertyValues(nodeTypeDef, properties);
@@ -331,13 +338,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
propertiesAfter = setPropertiesImpl(childNode, properties);
}
// create the association
ChildAssoc childAssoc = nodeDaoService.newChildAssoc(
parentNode,
childNode,
true,
assocTypeQName,
assocQName);
// Ensure child uniqueness
setChildUniqueName(childNode); // ensure uniqueness
ChildAssociationRef childAssocRef = childAssoc.getChildAssocRef();
@@ -1069,7 +1070,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
{
Node node = getNodeNotNull(nodeRef);
// get the assocs pointing to it
Collection<ChildAssoc> parentAssocs = node.getParentAssocs();
Collection<ChildAssoc> parentAssocs = nodeDaoService.getParentAssocs(node);
// list of results
Collection<NodeRef> results = new ArrayList<NodeRef>(parentAssocs.size());
for (ChildAssoc assoc : parentAssocs)
@@ -1089,7 +1090,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
{
Node node = getNodeNotNull(nodeRef);
// get the assocs pointing to it
Collection<ChildAssoc> parentAssocs = node.getParentAssocs();
Collection<ChildAssoc> parentAssocs = nodeDaoService.getParentAssocs(node);
// shortcut if there are no assocs
if (parentAssocs.size() == 0)
{
@@ -1319,7 +1320,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
{
NodeRef currentNodeRef = currentNode.getNodeRef();
// get the parent associations of the given node
Collection<ChildAssoc> parentAssocs = currentNode.getParentAssocs();
Collection<ChildAssoc> parentAssocs = nodeDaoService.getParentAssocs(currentNode);
// does the node have parents
boolean hasParents = parentAssocs.size() > 0;
// does the current node have a root aspect?
@@ -1651,7 +1652,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
}
// parent associations
ArrayList<ChildAssociationRef> archivedParentAssocRefs = new ArrayList<ChildAssociationRef>(5);
for (ChildAssoc assoc : node.getParentAssocs())
for (ChildAssoc assoc : nodeDaoService.getParentAssocs(node))
{
Long relatedNodeId = assoc.getParent().getId();
if (nodeStatusesById.containsKey(relatedNodeId))
@@ -1952,7 +1953,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
useName = (String) nameValue.getValue(DataTypeDefinition.TEXT);
}
// get all the parent assocs
Collection<ChildAssoc> parentAssocs = childNode.getParentAssocs();
Collection<ChildAssoc> parentAssocs = nodeDaoService.getParentAssocs(childNode);
for (ChildAssoc assoc : parentAssocs)
{
QName assocTypeQName = assoc.getTypeQName();

View File

@@ -223,6 +223,13 @@ public interface NodeDaoService
*/
public ChildAssoc getPrimaryParentAssoc(Node node);
/**
* Get all parent associations for the node. This methods includes a cache safety check.
* @param node the child node
* @return Returns all parent associations for the node.
*/
public Collection<ChildAssoc> getParentAssocs(Node node);
/**
* @return Returns the persisted and filled association
* @see NodeAssoc

View File

@@ -900,6 +900,49 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
getSession().flush();
}
/**
* @inheritDoc
*
* This method includes a check to ensure that the <b>parentAssocs</b> cache
* isn't incorrectly empty.
*/
public Collection<ChildAssoc> getParentAssocs(Node node)
{
Collection<ChildAssoc> parentAssocs = node.getParentAssocs();
if (parentAssocs.size() == 0)
{
// the only condition where this is allowed is if the given node is a root node
Store store = node.getStore();
Node rootNode = store.getRootNode();
if (rootNode == null)
{
// a store without a root node - the entire store is hosed
throw new DataIntegrityViolationException("Store has no root node: \n" +
" store: " + store);
}
if (!rootNode.equals(node))
{
// Reload the node to ensure that it is properly initialized
getSession().refresh(node);
// Check if it has any parents yet.
if (node.getParentAssocs().size() == 0)
{
// It wasn't the root node and definitely has no parent
throw new DataIntegrityViolationException(
"Non-root node has no primary parent: \n" +
" child: " + node);
}
else
{
// Repeat this method with confidence
return getParentAssocs(node);
}
}
}
// Done
return parentAssocs;
}
private Set<NodeRef> warnedDuplicateParents = new HashSet<NodeRef>(3);
/**
* @inheritDoc

View File

@@ -68,7 +68,7 @@ public abstract class AbstractReindexComponent implements IndexRecovery
private static Log logger = LogFactory.getLog(AbstractReindexComponent.class);
/** kept to notify the thread that it should quit */
private static VmShutdownListener vmShutdownListener = new VmShutdownListener("MissingContentReindexComponent");
private static VmShutdownListener vmShutdownListener = new VmShutdownListener("IndexRecovery");
private AuthenticationComponent authenticationComponent;
/** provides transactions to atomically index each missed transaction */

View File

@@ -14,6 +14,10 @@
<namespace uri="http://www.alfresco.org/model/user/1.0" prefix="usr"/>
</namespaces>
<constraints>
<constraint name="usr:userNameConstraint" type="org.alfresco.repo.dictionary.constraint.UserNameConstraint" />
<constraint name="usr:authorityNameConstraint" type="org.alfresco.repo.dictionary.constraint.AuthorityNameConstraint" />
</constraints>
<types>
@@ -30,6 +34,9 @@
<!-- This is so you can not break person lookup -->
<property name="usr:username">
<type>d:text</type>
<constraints>
<constraint ref="usr:userNameConstraint" />
</constraints>
</property>
<property name="usr:password">
<type>d:text</type>
@@ -66,6 +73,9 @@
<!-- This is so you can not break group lookup -->
<property name="usr:authorityName">
<type>d:text</type>
<constraints>
<constraint ref="usr:authorityNameConstraint" />
</constraints>
</property>
<property name="usr:members">
<type>d:text</type>