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

@ -5,8 +5,8 @@ d_dictionary.model.err.type_not_found=Failed to create anonymous type as specifi
d_dictionary.model.err.aspect_not_found=Failed to create anonymous type as specified aspect {0} not found
d_dictionary.constraint.err.cyclic_ref=Constraint ''{0}'' is part of a cyclic reference of constraints
d_dictionary.constraint.err.type_and_ref=Constraint ''{0}'' cannot have a ''type'' and be a ''reference'' attribute
d_dictionary.constraint.err.type_or_ref=Constraint ''{0}'' cannot have a ''type'' and be a ''reference'' attribute
d_dictionary.constraint.err.type_and_ref=Constraint ''{0}'' cannot have a 'type' and be a 'reference' attribute
d_dictionary.constraint.err.type_or_ref=Constraint ''{0}'' cannot have a 'type' and be a 'reference' attribute
d_dictionary.constraint.err.ref_not_found=Constraint reference ''{0}'' not found on constraint ''{1}''
d_dictionary.constraint.err.anon_needs_property=Anonymous constraints can only be declared within the context of a property
d_dictionary.constraint.err.invalid_type=Constraint type ''{0}'' on constraint ''{1}'' is not a well-known type or a valid Constraint implementation
@ -26,16 +26,22 @@ d_dictionary.property.err.cannot_relax_mandatory_enforcement=Cannot relax mandat
d_dictionary.constraint.regex.no_match=Value ''{0}'' does not match regular expression: {1}
d_dictionary.constraint.regex.match=Value ''{0}'' matches regular expression: {1}
d_dictionary.constraint.numeric_range.invalid_min_value=Invalid ''minValue'' property: {0}
d_dictionary.constraint.numeric_range.invalid_max_value=Invalid ''maxValue'' property: {0}
d_dictionary.constraint.numeric_range.invalid_min_value=Invalid 'minValue' property: {0}
d_dictionary.constraint.numeric_range.invalid_max_value=Invalid 'maxValue' property: {0}
d_dictionary.constraint.numeric_range.non_numeric=Property value could not be converted to a double: {0}
d_dictionary.constraint.numeric_range.out_of_range=Numeric value ''{0}'' is not in range [{1}; {2}]
d_dictionary.constraint.string_length.invalid_min_length=Invalid ''minLength'' property: {0}
d_dictionary.constraint.string_length.invalid_max_length=Invalid ''maxLength'' property: {0}
d_dictionary.constraint.string_length.invalid_min_length=Invalid 'minLength' property: {0}
d_dictionary.constraint.string_length.invalid_max_length=Invalid 'maxLength' property: {0}
d_dictionary.constraint.string_length.non_string=Property value could not be converted to a String: {0}
d_dictionary.constraint.string_length.invalid_length=String length of ''{0}'' is not in range [{1}; {2}]
d_dictionary.constraint.list_of_values.no_values=The list of allowed values is empty
d_dictionary.constraint.list_of_values.non_string=Property value could not be converted to a String: {0}
d_dictionary.constraint.list_of_values.invalid_value=The value is not an allowed value: {0}
d_dictionary.constraint.user_name.invalid_user_name=The value ''{0}'' is not an allowed user name: it is an authority of type: {1}
d_dictionary.constraint.user_name.non_string=Property value could not be converted to a String: {0}
d_dictionary.constraint.authority_name.invalid_authority_name=The value ''{0}'' is not an allowed authority name: it is an authority of type: {1}
d_dictionary.constraint.authority_name.non_string=Property value could not be converted to a String: {0}

View File

@ -137,7 +137,10 @@ patch.userAndPersonUserNamesAsIdentifiers.result=Reindexed user:user and cm:pers
patch.contentFormFolderType.description=Update WCM Content Form folder type.
patch.contentFormFolderType.result=Updated {0} WCM Content Form objects to 'wcm:formfolder' type.
patch.webscripts.description=Adds Web Scripts to Data Dictionary.
patch.groupNamesAsIdentifiers.description=Reindex usr:authorityContainer gids as identifiers
patch.groupNamesAsIdentifiers.result=Reindex usr:authorityContainer gids as identifiers
patch.groupNamesAsIdentifiers.result=Reindex usr:authorityContainer gids as identifiers
patch.invalidUserPersonAndGroup.description=Fix up invalid uids for people and users; and invalid gids for groups
patch.invalidUserPersonAndGroup.result=Fixed ''{0}'' invalid user nodes, ''{1}'' invalid person nodes and ''{2}'' invalid authority nodes.
patch.webscripts.description=Adds Web Scripts to Data Dictionary.

View File

@ -19,6 +19,7 @@
<parameter name="expression"><value><![CDATA[(.*[\"\*\\\>\<\?\/\:\|\xA3\xAC\%\&\+\;]+.*)|(.*[\.]?.*[\.]+$)|(.*[ ]+$)]]></value></parameter>
<parameter name="requiresMatch"><value>false</value></parameter>
</constraint>
<constraint name="cm:userNameConstraint" type="org.alfresco.repo.dictionary.constraint.UserNameConstraint" />
</constraints>
<types>
@ -147,6 +148,9 @@
<property name="cm:userName">
<type>d:text</type>
<mandatory>true</mandatory>
<constraints>
<constraint ref="cm:userNameConstraint" />
</constraints>
</property>
<property name="cm:homeFolder">
<type>d:noderef</type>

View File

@ -684,6 +684,24 @@
<ref bean="indexerAndSearcherFactory" />
</property>
</bean>
<bean id="patch.invalidUserPersonAndGroup" class="org.alfresco.repo.admin.patch.impl.InvalidUserPersonAndGroupPatch" parent="basePatch" >
<property name="id"><value>patch.invalidUserPersonAndGroup</value></property>
<property name="description"><value>patch.invalidUserPersonAndGroup.description</value></property>
<property name="fixesFromSchema"><value>0</value></property>
<property name="fixesToSchema"><value>39</value></property>
<property name="targetSchema"><value>40</value></property>
<!-- bootstrap view -->
<property name="userImporterBootstrap">
<ref bean="userBootstrap" />
</property>
<property name="spacesImporterBootstrap">
<ref bean="spacesBootstrap" />
</property>
<property name="dictionaryService">
<ref bean="dictionaryService" />
</property>
</bean>
<bean id="patch.webscripts" class="org.alfresco.repo.admin.patch.impl.GenericBootstrapPatch" parent="basePatch" >
<property name="id"><value>patch.webscripts</value></property>

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>