Fix Build: Reverse Merged

<< Think issue is just from 55012, but not taking the chance. Left the wrong commit r54935 on HEAD-BUG-FIX. I misread 54935 as 54635 >>
   55006: Merged HEAD-BUG-FIX to HEAD (4.2)
      54919: MNT-9571: Merged V4.1-BUG-FIX (4.1.7) to HEAD-BUG-FIX (4.2)
         54377: MNT-9090 "CMIS: Integer overflow in properties": checks for overflow + tests
   55012: Merged HEAD-BUG-FIX to HEAD (4.2)
      54933: MNT-9574: Merged V4.1-BUG-FIX (4.1.7) to HEAD-BUG-FIX (4.2)
         54635: Merged DEV to HEAD-QA (4.1.N)
            MNT-9089 : CMIS: Missing boundaries for integer and long values
               - Adding default constrains for Integer and Long CMIS PropertyDefinitions. Adding Test.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@55059 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Alan Davis
2013-09-06 15:21:04 +00:00
parent 60d9622559
commit 5a6bee26b8
3 changed files with 15 additions and 344 deletions

View File

@@ -93,7 +93,6 @@ import org.alfresco.service.cmr.audit.AuditQueryParameters;
import org.alfresco.service.cmr.audit.AuditService; import org.alfresco.service.cmr.audit.AuditService;
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback; import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.InvalidAspectException; import org.alfresco.service.cmr.dictionary.InvalidAspectException;
import org.alfresco.service.cmr.lock.LockService; import org.alfresco.service.cmr.lock.LockService;
@@ -273,11 +272,6 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
private static final String CMIS_USER = "cmis:user"; private static final String CMIS_USER = "cmis:user";
private static final BigInteger maxInt = BigInteger.valueOf(Integer.MAX_VALUE);
private static final BigInteger minInt = BigInteger.valueOf(Integer.MIN_VALUE);
private static final BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE);
private static final BigInteger minLong = BigInteger.valueOf(Long.MIN_VALUE);
// lifecycle // lifecycle
private ProcessorLifecycle lifecycle = new ProcessorLifecycle(); private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
@@ -2954,8 +2948,8 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
ArrayList<Serializable> values = new ArrayList<Serializable>(); ArrayList<Serializable> values = new ArrayList<Serializable>();
if (property.getChildren() != null) if (property.getChildren() != null)
{ {
// try try
// { {
for (CmisExtensionElement valueElement : property.getChildren()) for (CmisExtensionElement valueElement : property.getChildren())
{ {
if ("value".equals(valueElement.getName())) if ("value".equals(valueElement.getName()))
@@ -2963,80 +2957,28 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
switch (propertyType) switch (propertyType)
{ {
case BOOLEAN: case BOOLEAN:
try values.add(Boolean.parseBoolean(valueElement.getValue()));
{
values.add(Boolean.parseBoolean(valueElement.getValue()));
}
catch (Exception e)
{
throw new CmisInvalidArgumentException("Invalid property aspect value: " + propertyId, e);
}
break; break;
case DATETIME: case DATETIME:
try values.add(df.newXMLGregorianCalendar(valueElement.getValue())
{ .toGregorianCalendar());
values.add(df.newXMLGregorianCalendar(valueElement.getValue())
.toGregorianCalendar());
}
catch (Exception e)
{
throw new CmisInvalidArgumentException("Invalid property aspect value: " + propertyId, e);
}
break; break;
case INTEGER: case INTEGER:
BigInteger value = null; values.add(new BigInteger(valueElement.getValue()));
try
{
value = new BigInteger(valueElement.getValue());
}
catch (Exception e)
{
throw new CmisInvalidArgumentException("Invalid property aspect value: " + propertyId, e);
}
// overflow check
PropertyDefinitionWrapper propDef = cmisDictionaryService.findProperty(propertyId);
if(propDef == null)
{
throw new CmisInvalidArgumentException("Property " + propertyId + " is unknown!");
}
QName propertyQName = propDef.getPropertyAccessor().getMappedProperty();
if (propertyQName == null)
{
throw new CmisConstraintException("Unable to set property " + propertyId + "!");
}
org.alfresco.service.cmr.dictionary.PropertyDefinition def = dictionaryService.getProperty(propertyQName);
QName dataDef = def.getDataType().getName();
if (dataDef.equals(DataTypeDefinition.INT) && (value.compareTo(maxInt) > 0 || value.compareTo(minInt) < 0))
{
throw new CmisConstraintException("Value is out of range for property " + propertyId);
}
if (dataDef.equals(DataTypeDefinition.LONG) && (value.compareTo(maxLong) > 0 || value.compareTo(minLong) < 0 ))
{
throw new CmisConstraintException("Value is out of range for property " + propertyId);
}
values.add(value);
break; break;
case DECIMAL: case DECIMAL:
try values.add(new BigDecimal(valueElement.getValue()));
{
values.add(new BigDecimal(valueElement.getValue()));
}
catch (Exception e)
{
throw new CmisInvalidArgumentException("Invalid property aspect value: " + propertyId, e);
}
break; break;
default: default:
values.add(valueElement.getValue()); values.add(valueElement.getValue());
} }
} }
} }
}
catch (Exception e)
{
throw new CmisInvalidArgumentException("Invalid property aspect value: " + propertyId, e);
}
} }
aspectProperties.put(QName.createQName(propertyId, namespaceService), values); aspectProperties.put(QName.createQName(propertyId, namespaceService), values);
@@ -3127,8 +3069,6 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
// set property // set property
for (Map.Entry<QName, List<Serializable>> property : aspectProperties.entrySet()) for (Map.Entry<QName, List<Serializable>> property : aspectProperties.entrySet())
{ {
QName propertyQName = property.getKey();
if (property.getValue().isEmpty()) if (property.getValue().isEmpty())
{ {
if(HiddenAspect.HIDDEN_PROPERTIES.contains(property.getKey())) if(HiddenAspect.HIDDEN_PROPERTIES.contains(property.getKey()))
@@ -3136,7 +3076,7 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
if(hiddenAspect.isClientControlled(nodeRef) || aspectProperties.containsKey(ContentModel.PROP_CLIENT_CONTROLLED)) if(hiddenAspect.isClientControlled(nodeRef) || aspectProperties.containsKey(ContentModel.PROP_CLIENT_CONTROLLED))
{ {
// manipulate hidden aspect property only if client controlled // manipulate hidden aspect property only if client controlled
nodeService.removeProperty(nodeRef, propertyQName); nodeService.removeProperty(nodeRef, property.getKey());
} }
} }
else else
@@ -3157,9 +3097,8 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
} }
else else
{ {
Serializable value = (Serializable)property.getValue();
nodeService.setProperty(nodeRef, property.getKey(), property.getValue().size() == 1 ? property nodeService.setProperty(nodeRef, property.getKey(), property.getValue().size() == 1 ? property
.getValue().get(0) : value); .getValue().get(0) : (Serializable) property.getValue());
} }
} }
} }
@@ -3222,7 +3161,6 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
throw new CmisConstraintException("Unable to set property " + property.getId() + "!"); throw new CmisConstraintException("Unable to set property " + property.getId() + "!");
} }
if (property.getId().equals(PropertyIds.NAME)) if (property.getId().equals(PropertyIds.NAME))
{ {
if (!(value instanceof String)) if (!(value instanceof String))
@@ -3251,24 +3189,6 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
} }
else else
{ {
// overflow check
if(propDef.getPropertyDefinition().getPropertyType() == PropertyType.INTEGER && value instanceof BigInteger)
{
org.alfresco.service.cmr.dictionary.PropertyDefinition def = dictionaryService.getProperty(propertyQName);
QName dataDef = def.getDataType().getName();
BigInteger bigValue = (BigInteger)value;
if ((bigValue.compareTo(maxInt) > 0 || bigValue.compareTo(minInt) < 0 ) && dataDef.equals(DataTypeDefinition.INT))
{
throw new CmisConstraintException("Value is out of range for property " + propertyQName.getLocalName());
}
if ((bigValue.compareTo(maxLong) > 0 || bigValue.compareTo(minLong) < 0 ) && dataDef.equals(DataTypeDefinition.LONG))
{
throw new CmisConstraintException("Value is out of range for property " + propertyQName.getLocalName());
}
}
nodeService.setProperty(nodeRef, propertyQName, value); nodeService.setProperty(nodeRef, propertyQName, value);
} }
} }

View File

@@ -10,7 +10,6 @@ import java.io.File;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -34,32 +33,24 @@ import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.rule.Rule; import org.alfresco.service.cmr.rule.Rule;
import org.alfresco.service.cmr.rule.RuleService; import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.rule.RuleType; import org.alfresco.service.cmr.rule.RuleType;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.cmr.version.VersionService; import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.ApplicationContextHelper;
import org.apache.chemistry.opencmis.commons.PropertyIds; import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.AllowableActions; import org.apache.chemistry.opencmis.commons.data.AllowableActions;
import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
import org.apache.chemistry.opencmis.commons.data.ObjectData; import org.apache.chemistry.opencmis.commons.data.ObjectData;
import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData; import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList; import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
import org.apache.chemistry.opencmis.commons.data.Properties;
import org.apache.chemistry.opencmis.commons.data.PropertyData; import org.apache.chemistry.opencmis.commons.data.PropertyData;
import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.enums.Action; import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion; import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships; import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.enums.VersioningState; import org.apache.chemistry.opencmis.commons.enums.VersioningState;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException; import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.CmisExtensionElementImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerDefinitionImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl;
import org.apache.chemistry.opencmis.commons.impl.server.AbstractServiceFactory; import org.apache.chemistry.opencmis.commons.impl.server.AbstractServiceFactory;
import org.apache.chemistry.opencmis.commons.server.CallContext; import org.apache.chemistry.opencmis.commons.server.CallContext;
@@ -78,7 +69,7 @@ import org.springframework.extensions.webscripts.GUID;
*/ */
public class CMISTest public class CMISTest
{ {
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(new String[]{ApplicationContextHelper.CONFIG_LOCATIONS[0],"classpath:test-cmisinteger_modell-context.xml"}); private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private FileFolderService fileFolderService; private FileFolderService fileFolderService;
private TransactionService transactionService; private TransactionService transactionService;
@@ -897,231 +888,4 @@ public class CMISTest
} }
} }
/**
* Test for MNT-9089
*/
@Test
public void testIntegerBoudaries() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
CmisService cmisService = factory.getService(context);
try
{
FileInfo fileInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
QName testIntTypeQName = QName.createQName("http://testCMISIntegersModel/1.0/", "testintegerstype");
String folderName = GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
String docName = GUID.generate();
FileInfo fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, testIntTypeQName);
assertNotNull(fileInfo);
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_NAME, docName);
return fileInfo;
}
});
// get repository id
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
String objectIdStr = fileInfo.getNodeRef().toString();
TypeDefinition typeDef = cmisService.getTypeDefinition(repositoryId, "D:tcim:testintegerstype", null);
PropertyIntegerDefinitionImpl intNoBoundsTypeDef =
(PropertyIntegerDefinitionImpl)typeDef.getPropertyDefinitions().get("tcim:int");
PropertyIntegerDefinitionImpl longNoBoundsTypeDef =
(PropertyIntegerDefinitionImpl)typeDef.getPropertyDefinitions().get("tcim:long");
PropertyIntegerDefinitionImpl intWithBoundsTypeDef =
(PropertyIntegerDefinitionImpl)typeDef.getPropertyDefinitions().get("tcim:intwithbounds");
PropertyIntegerDefinitionImpl longWithBoundsTypeDef =
(PropertyIntegerDefinitionImpl)typeDef.getPropertyDefinitions().get("tcim:longwithbounds");
BigInteger minInteger = BigInteger.valueOf(Integer.MIN_VALUE);
BigInteger maxInteger = BigInteger.valueOf(Integer.MAX_VALUE);
BigInteger minLong = BigInteger.valueOf(Long.MIN_VALUE);
BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE);
// test for default boundaries
assertTrue(intNoBoundsTypeDef.getMinValue().equals(minInteger));
assertTrue(intNoBoundsTypeDef.getMaxValue().equals(maxInteger));
assertTrue(longNoBoundsTypeDef.getMinValue().equals(minLong));
assertTrue(longNoBoundsTypeDef.getMaxValue().equals(maxLong));
// test for pre-defined boundaries
assertTrue(intWithBoundsTypeDef.getMinValue().equals(BigInteger.valueOf(-10L)));
assertTrue(intWithBoundsTypeDef.getMaxValue().equals(BigInteger.valueOf(10L)));
assertTrue(longWithBoundsTypeDef.getMinValue().equals(BigInteger.valueOf(-10L)));
assertTrue(longWithBoundsTypeDef.getMaxValue().equals(BigInteger.valueOf(10L)));
try // try to overfloat long without boundaries
{
BigInteger aValue = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.valueOf(1L));
setProperiesToObject(cmisService, repositoryId, objectIdStr, "tcim:long", aValue);
fail();
}
catch(Exception e)
{
assertTrue(e instanceof CmisConstraintException);
}
try // try to overfloat int without boundaries
{
BigInteger aValue = BigInteger.valueOf(Integer.MAX_VALUE).add(BigInteger.valueOf(1L));
setProperiesToObject(cmisService, repositoryId, objectIdStr, "tcim:int", aValue);
fail();
}
catch(Exception e)
{
assertTrue(e instanceof CmisConstraintException);
}
try // try to overfloat int with boundaries
{
BigInteger aValue = BigInteger.valueOf( 11l );
setProperiesToObject(cmisService, repositoryId, objectIdStr, "tcim:intwithbounds", aValue);
fail();
}
catch(Exception e)
{
assertTrue(e instanceof CmisConstraintException);
}
try // try to overfloat long with boundaries
{
BigInteger aValue = BigInteger.valueOf( 11l );
setProperiesToObject(cmisService, repositoryId, objectIdStr, "tcim:longwithbounds", aValue);
fail();
}
catch(Exception e)
{
assertTrue(e instanceof CmisConstraintException);
}
}
catch(Exception e)
{
fail(e.getMessage());
}
finally
{
cmisService.close();
AuthenticationUtil.popAuthentication();
}
}
private void setProperiesToObject(CmisService cmisService, String repositoryId, String objectIdStr, String propertyStr, BigInteger bigIntValue) throws CmisConstraintException{
Properties properties = cmisService.getProperties(repositoryId, objectIdStr, null, null);
PropertyIntegerImpl pd = (PropertyIntegerImpl)properties.getProperties().get(propertyStr);
pd.setValue(bigIntValue);
Collection<PropertyData<?>> propsList = new ArrayList<PropertyData<?>>();
propsList.add(pd);
Properties newProps = new PropertiesImpl(propsList);
cmisService.updateProperties(repositoryId, new Holder<String>(objectIdStr), null, newProps, null);
}
@Test
public void testMNT9090() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
CmisService cmisService = factory.getService(context);
try
{
FileInfo fileInfo = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
String folderName = GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
String docName = GUID.generate();
FileInfo fileInfo = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
assertNotNull(fileInfo);
nodeService.setProperty(fileInfo.getNodeRef(), ContentModel.PROP_NAME, docName);
QName ASPECT_AUDIO = QName.createQName(NamespaceService.AUDIO_MODEL_1_0_URI, "audio");
Map<QName, Serializable> aspectProperties = new HashMap<QName, Serializable>();
nodeService.addAspect(fileInfo.getNodeRef(), ASPECT_AUDIO, aspectProperties);
return fileInfo;
}
});
// get repository id
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.get(0);
String repositoryId = repo.getId();
String objectIdStr = fileInfo.getNodeRef().toString();
Holder<String> objectId = new Holder<String>(objectIdStr);
// try to overflow the value
Object value = BigInteger.valueOf(Integer.MAX_VALUE + 1l);
Properties properties = new PropertiesImpl();
List<CmisExtensionElement> extensions = new ArrayList<CmisExtensionElement>();
CmisExtensionElement valueElem = new CmisExtensionElementImpl(CMISConnector.ALFRESCO_EXTENSION_NAMESPACE, "value", null, value.toString());
List<CmisExtensionElement> valueElems = new ArrayList<CmisExtensionElement>();
valueElems.add(valueElem);
List<CmisExtensionElement> children = new ArrayList<CmisExtensionElement>();
Map<String, String> attributes = new HashMap<String, String>();
attributes.put("propertyDefinitionId", "audio:trackNumber");
children.add(new CmisExtensionElementImpl(CMISConnector.ALFRESCO_EXTENSION_NAMESPACE, "propertyInteger", attributes, valueElems));
List<CmisExtensionElement> propertyValuesExtension = new ArrayList<CmisExtensionElement>();
propertyValuesExtension.add(new CmisExtensionElementImpl(CMISConnector.ALFRESCO_EXTENSION_NAMESPACE, CMISConnector.PROPERTIES, null, children));
CmisExtensionElement setAspectsExtension = new CmisExtensionElementImpl(CMISConnector.ALFRESCO_EXTENSION_NAMESPACE, CMISConnector.SET_ASPECTS, null, propertyValuesExtension);
extensions.add(setAspectsExtension);
properties.setExtensions(extensions);
// should throw a CMISConstraintException
cmisService.updateProperties(repositoryId, objectId, null, properties, null);
fail();
}
catch(CmisConstraintException e)
{
assertTrue(e.getMessage().startsWith("Value is out of range for property"));
// ok
}
finally
{
cmisService.close();
AuthenticationUtil.popAuthentication();
}
}
} }

View File

@@ -1,13 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- Registration of new models -->
<bean id="testcmisintegermodelDictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
<property name="models">
<list>
<value>opencmis/testcmisinteger_model.xml</value>
</list>
</property>
</bean>
</beans>