blob: 675d746a7a606d5f49e90b619e781af62c190333 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013-2016 LAAS-CNRS (www.laas.fr)
* 7 Colonel Roche 31077 Toulouse - France
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Initial Contributors:
* Thierry Monteil : Project manager, technical co-manager
* Mahdi Ben Alaya : Technical co-manager
* Samir Medjiah : Technical co-manager
* Khalil Drira : Strategy expert
* Guillaume Garzone : Developer
* François Aïssaoui : Developer
*
* New contributors :
*******************************************************************************/
package org.eclipse.om2m.core.controller;
import java.math.BigInteger;
import java.util.List;
import org.eclipse.om2m.commons.constants.Constants;
import org.eclipse.om2m.commons.constants.MimeMediaType;
import org.eclipse.om2m.commons.constants.Operation;
import org.eclipse.om2m.commons.constants.ResourceStatus;
import org.eclipse.om2m.commons.constants.ResourceType;
import org.eclipse.om2m.commons.constants.ResponseStatusCode;
import org.eclipse.om2m.commons.constants.ShortName;
import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
import org.eclipse.om2m.commons.entities.AeEntity;
import org.eclipse.om2m.commons.entities.CSEBaseEntity;
import org.eclipse.om2m.commons.entities.ContainerEntity;
import org.eclipse.om2m.commons.entities.RemoteCSEEntity;
import org.eclipse.om2m.commons.entities.ResourceEntity;
import org.eclipse.om2m.commons.entities.SubscriptionEntity;
import org.eclipse.om2m.commons.exceptions.BadRequestException;
import org.eclipse.om2m.commons.exceptions.ConflictException;
import org.eclipse.om2m.commons.exceptions.NotPermittedAttrException;
import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
import org.eclipse.om2m.commons.resource.Container;
import org.eclipse.om2m.commons.resource.RequestPrimitive;
import org.eclipse.om2m.commons.resource.ResponsePrimitive;
import org.eclipse.om2m.commons.utils.Util.DateUtil;
import org.eclipse.om2m.core.datamapper.DataMapperSelector;
import org.eclipse.om2m.core.entitymapper.EntityMapperFactory;
import org.eclipse.om2m.core.notifier.Notifier;
import org.eclipse.om2m.core.router.Patterns;
import org.eclipse.om2m.core.urimapper.UriMapper;
import org.eclipse.om2m.core.util.ControllerUtil;
import org.eclipse.om2m.core.util.ControllerUtil.UpdateUtil;
import org.eclipse.om2m.persistence.service.DAO;
/**
* Controller for the Container Resource
*
*/
public class ContainerController extends Controller {
/**
* Create the resource in the system according to the representation
*/
@Override
public ResponsePrimitive doCreate(RequestPrimitive request) {
/*
* Container creation procedure
*
* @resourceName NP
* resourceType NP
* resourceID NP
* parentID NP
* accessControlPolicyIDs O
* creationTime NP
* expirationTime O
* lastModifiedTime NP
* labels O
* announceTo O
* announcedAttribute O
*
* creator O
* maxNrOfInstances O
* maxByteSize O
* maxInstanceAge O
* currentNrOfInstances NP
* currentByteSize NP
* locationID O
* ontologyRef O
*
*/
ResponsePrimitive response = new ResponsePrimitive(request);
// get the dao of the parent
DAO<ResourceEntity> dao = (DAO<ResourceEntity>) Patterns.getDAO(request.getTargetId(), dbs);
if (dao == null){
throw new ResourceNotFoundException("Cannot find parent resource");
}
// get the parent entity
ResourceEntity parentEntity = (ResourceEntity)dao.find(transaction, request.getTargetId());
// check the parent existence
if (parentEntity == null) {
throw new ResourceNotFoundException("Cannot find parent resource");
}
// get lists to change in the method corresponding to specific object
List<AccessControlPolicyEntity> acpsToCheck = null;
List<ContainerEntity> childContainers = null;
List<SubscriptionEntity> subscriptions = null;
// different cases
// case parent is CSEBase
if (parentEntity.getResourceType().intValue() == (ResourceType.CSE_BASE)) {
CSEBaseEntity cseB = (CSEBaseEntity) parentEntity;
acpsToCheck = cseB.getAccessControlPolicies();
childContainers = cseB.getChildContainers();
subscriptions = cseB.getSubscriptions();
}
// case parent is AE
if (parentEntity.getResourceType().intValue() == (ResourceType.AE)) {
AeEntity ae = (AeEntity) parentEntity;
acpsToCheck = ae.getAccessControlPolicies();
childContainers = ae.getChildContainers();
subscriptions = ae.getSubscriptions();
}
// case parent is a Container
if (parentEntity.getResourceType().intValue() == (ResourceType.CONTAINER)) {
ContainerEntity parentContainer = (ContainerEntity) parentEntity;
acpsToCheck = parentContainer.getAccessControlPolicies();
childContainers = parentContainer.getChildContainers();
subscriptions = parentContainer.getSubscriptions();
}
// case parent is a RemoteCSE
if(parentEntity.getResourceType().intValue() == ResourceType.REMOTE_CSE){
RemoteCSEEntity csr = (RemoteCSEEntity) parentEntity;
acpsToCheck = csr.getAccessControlPolicies();
childContainers = csr.getChildCnt();
subscriptions = csr.getSubscriptions();
}
// check access control policy of the originator
checkACP(acpsToCheck, request.getFrom(), Operation.CREATE);
// check if content is present
if (request.getContent() == null){
throw new BadRequestException("A content is requiered for Container creation");
}
// get the object from the representation
Container container = null;
try{
if (request.getRequestContentType().equals(MimeMediaType.OBJ)){
container = (Container) request.getContent();
} else {
container = (Container)DataMapperSelector.getDataMapperList()
.get(request.getRequestContentType()).stringToObj((String)request.getContent());
}
} catch (ClassCastException e){
LOGGER.debug("ClassCastException: Incorrect resource type in object conversion.",e);
throw new BadRequestException("Incorrect resource representation in content", e);
}
if (container == null){
throw new BadRequestException("Error in provided content");
}
// creating the corresponding entity
ContainerEntity containerEntity = new ContainerEntity();
// check attributes
// @resourceName NP
// Resource Type NP
// resourceID NP
// parentID NP
// lastModifiedTime NP
// creationTime NP
// expiration time O
// labels O
// announceTo O
// announcedAttribute O
ControllerUtil.CreateUtil.fillEntityFromAnnounceableResource(container, containerEntity);
// creator O
if (container.getCreator() != null) {
containerEntity.setCreator(container.getCreator());
}
// currentNrOfInstances NP
if (container.getCurrentNrOfInstances() != null) {
throw new NotPermittedAttrException("Current number of instances is Not Permitted");
}
// currentByteSize NP
if (container.getCurrentByteSize() != null) {
throw new NotPermittedAttrException("Current byte size is Not Permitted");
}
String generatedId = generateId("", "");
// set name if present and without any conflict
if (container.getName() != null){
if (!Patterns.checkResourceName(container.getName())){
throw new BadRequestException("Name provided is incorrect. Must be:" + Patterns.ID_STRING);
}
containerEntity.setName(container.getName());
} else
if (request.getName() != null) {
if(!Patterns.checkResourceName(request.getName())){
throw new BadRequestException("Name provided is incorrect. Must be:" + Patterns.ID_STRING);
}
containerEntity.setName(request.getName());
} else {
containerEntity.setName(ShortName.CNT + "_" + generatedId);
}
containerEntity.setResourceID("/" + Constants.CSE_ID + "/" + ShortName.CNT + Constants.PREFIX_SEPERATOR + generatedId);
containerEntity.setHierarchicalURI(parentEntity.getHierarchicalURI() + "/" + containerEntity.getName());
containerEntity.setParentID(parentEntity.getResourceID());
containerEntity.setResourceType(ResourceType.CONTAINER);
containerEntity.setCurrentNrOfInstances(BigInteger.valueOf(0));
// accessControlPolicyIDs O
if (!container.getAccessControlPolicyIDs().isEmpty()){
containerEntity.setAccessControlPolicies(
ControllerUtil.buildAcpEntityList(container.getAccessControlPolicyIDs(), transaction));
} else {
containerEntity.getAccessControlPolicies().addAll(acpsToCheck);
}
if(!UriMapper.addNewUri(containerEntity.getHierarchicalURI(), containerEntity.getResourceID(), ResourceType.CONTAINER)){
throw new ConflictException("Name already present in the parent collection.");
}
// ontologyRef O
if (container.getOntologyRef() != null){
containerEntity.setOntologyRef(container.getOntologyRef());
}
// maxNrOfInstances O
if (container.getMaxNrOfInstances() != null) {
containerEntity.setMaxNrOfInstances(container.getMaxNrOfInstances());
} else {
containerEntity.setMaxNrOfInstances(Constants.MAX_NBR_OF_INSTANCES);
}
// maxByteSize O
if (container.getMaxByteSize() != null) {
containerEntity.setMaxByteSize(container.getMaxByteSize());
} else {
containerEntity.setMaxByteSize(Constants.MAX_BYTE_SIZE);
}
// maxInstanceAge O
if (container.getMaxInstanceAge() != null) {
containerEntity.setMaxInstanceAge(container.getMaxInstanceAge());
} else {
containerEntity.setMaxInstanceAge(BigInteger.valueOf(0));
}
// locationID O
if (container.getLocationID() != null) {
containerEntity.setLocationID(container.getLocationID());
}
// stateTag init
containerEntity.setStateTag(BigInteger.valueOf(0));
// create the container in the DB
dbs.getDAOFactory().getContainerDAO().create(transaction, containerEntity);
// retrieve the managed object from DB
ContainerEntity containerFromDB = dbs.getDAOFactory().getContainerDAO().find(transaction, containerEntity.getResourceID());
// add the container to the parentEntity child list
childContainers.add(containerFromDB);
dao.update(transaction, parentEntity);
// commit the transaction
transaction.commit();
Notifier.notify(subscriptions, containerFromDB, ResourceStatus.CHILD_CREATED);
// create the response
response.setResponseStatusCode(ResponseStatusCode.CREATED);
// set the location of the resource
setLocationAndCreationContent(request, response, containerFromDB);
return response;
}
/**
* Return the container resource with the normalized representation
* @param request primitive routed
* @return response primitive
*/
@Override
public ResponsePrimitive doRetrieve(RequestPrimitive request) {
// Creating the response primitive
ResponsePrimitive response = new ResponsePrimitive(request);
// Check existence of the resource
ContainerEntity containerEntity = dbs.getDAOFactory().getContainerDAO().find(transaction, request.getTargetId());
if (containerEntity == null) {
throw new ResourceNotFoundException("Resource not found");
}
// if resource exists, check authorization
// retrieve
List<AccessControlPolicyEntity> acpList = containerEntity.getAccessControlPolicies();
checkACP(acpList, request.getFrom(), request.getOperation());
// Mapping the entity with the exchange resource
Container containerResource = EntityMapperFactory.getContainerMapper().mapEntityToResource(containerEntity, request);
response.setContent(containerResource);
response.setResponseStatusCode(ResponseStatusCode.OK);
// return the response
return response;
}
/**
* Implement the full update method for container entity
* @param request
* @return
*/
@Override
public ResponsePrimitive doUpdate(RequestPrimitive request) {
/*
* Container update procedure
*
* @resourceName NP
* resourceType NP
* resourceID NP
* parentID NP
* accessControlPolicyIDs O
* creationTime NP
* expirationTime O
* lastModifiedTime NP
* labels O
* announceTo O
* announcedAttribute O
*
* creator NP
* maxNrOfInstances O
* maxByteSize O
* maxInstanceAge O
* currentNrOfInstances NP
* currentByteSize NP
* locationID O
* ontologyRef O
*
*/
// create the response base
ResponsePrimitive response = new ResponsePrimitive(request);
// retrieve the resource from database
ContainerEntity containerEntity = dbs.getDAOFactory().getContainerDAO().find(transaction, request.getTargetId());
if (containerEntity == null) {
throw new ResourceNotFoundException("Resource not found");
}
// check ACP
checkACP(containerEntity.getAccessControlPolicies(), request.getFrom(), Operation.UPDATE);
// check if content is present
if (request.getContent() == null) {
throw new BadRequestException("A content is requiered for Container update");
}
// create the java object from the resource representation
// get the object from the representation
Container container = null;
try{
if (request.getRequestContentType().equals(MimeMediaType.OBJ)){
container = (Container) request.getContent();
} else {
container = (Container)DataMapperSelector.getDataMapperList()
.get(request.getRequestContentType()).stringToObj((String)request.getContent());
}
} catch (ClassCastException e){
throw new BadRequestException("Incorrect resource representation in content", e);
}
if (container == null){
throw new BadRequestException("Error in provided content");
}
// check attributes, NP attributes are ignored
// @resourceName NP
// resourceType NP
// resourceID NP
// parentID NP
// creationTime NP
// creator NP
// lastModifiedTime NP
UpdateUtil.checkNotPermittedParameters(container);
// currentNrOfInstances NP
if(container.getCurrentNrOfInstances() != null){
throw new BadRequestException("CurrentNrOfInstances is NP");
}
// currentByteSize NP
if(container.getCurrentByteSize() != null){
throw new BadRequestException("CurrentByteSize is NP");
}
Container modifiedAttributes = new Container();
// accessControlPolicyIDs O
if(!container.getAccessControlPolicyIDs().isEmpty()){
for(AccessControlPolicyEntity acpe : containerEntity.getAccessControlPolicies()){
checkSelfACP(acpe, request.getFrom(), Operation.UPDATE);
}
containerEntity.getAccessControlPolicies().clear();
containerEntity.setAccessControlPolicies(ControllerUtil.
buildAcpEntityList(container.getAccessControlPolicyIDs(), transaction));
modifiedAttributes.getAccessControlPolicyIDs().addAll(container.getAccessControlPolicyIDs());
}
// labels O
if (!container.getLabels().isEmpty()) {
containerEntity.setLabelsEntitiesFromSring(container.getLabels());
modifiedAttributes.getLabels().addAll(container.getLabels());
}
// expirationTime O
if (container.getExpirationTime() != null){
containerEntity.setExpirationTime(container.getExpirationTime());
modifiedAttributes.setExpirationTime(container.getExpirationTime());
}
// announceTo O
if(!container.getAnnounceTo().isEmpty()){
// TODO Announcement in AE update
containerEntity.getAnnounceTo().clear();
containerEntity.getAnnounceTo().addAll(container.getAnnounceTo());
modifiedAttributes.getAnnounceTo().addAll(container.getAnnounceTo());
}
// announcedAttribute O
if(!container.getAnnouncedAttribute().isEmpty()){
containerEntity.getAnnouncedAttribute().clear();
containerEntity.getAnnouncedAttribute().addAll(container.getAnnouncedAttribute());
modifiedAttributes.getAnnouncedAttribute().addAll(container.getAnnouncedAttribute());
}
// maxNrOfInstances O
if(container.getMaxNrOfInstances() != null){
containerEntity.setMaxNrOfInstances(container.getMaxNrOfInstances());
modifiedAttributes.setMaxNrOfInstances(container.getMaxNrOfInstances());
}
// maxByteSize O
if(container.getMaxByteSize() != null){
containerEntity.setMaxByteSize(container.getMaxByteSize());
modifiedAttributes.setMaxByteSize(container.getMaxByteSize());
}
// maxInstanceAge O
if(container.getMaxInstanceAge() != null){
containerEntity.setMaxInstanceAge(container.getMaxInstanceAge());
modifiedAttributes.setMaxInstanceAge(container.getMaxInstanceAge());
}
// locationID O
if(container.getLocationID() != null){
containerEntity.setLocationID(container.getLocationID());
modifiedAttributes.setLocationID(container.getLocationID());
}
// ontologyRef O
if(container.getOntologyRef() != null){
containerEntity.setOntologyRef(container.getOntologyRef());
modifiedAttributes.setOntologyRef(container.getOntologyRef());
}
// Update state tag
if(containerEntity.getStateTag() != null){
containerEntity.setStateTag(BigInteger.valueOf(containerEntity.getStateTag().intValue() + 1));
modifiedAttributes.setStateTag(containerEntity.getStateTag());
}
containerEntity.setLastModifiedTime(DateUtil.now());
modifiedAttributes.setLastModifiedTime(containerEntity.getLastModifiedTime());
response.setContent(modifiedAttributes);
// update the resource in the database
dbs.getDAOFactory().getContainerDAO().update(transaction, containerEntity);
transaction.commit();
Notifier.notify(containerEntity.getSubscriptions(), containerEntity, ResourceStatus.UPDATED);
// set response status code
response.setResponseStatusCode(ResponseStatusCode.UPDATED);
return response;
}
/**
* Delete the container if access control policies are correct
*/
@Override
public ResponsePrimitive doDelete(RequestPrimitive request) {
// Generic delete procedure
ResponsePrimitive response = new ResponsePrimitive(request);
// retrieve the corresponding resource from database
ContainerEntity containerEntity = dbs.getDAOFactory().getContainerDAO().find(transaction, request.getTargetId());
if (containerEntity == null) {
throw new ResourceNotFoundException("Resource not found");
}
// check access control policies
checkACP(containerEntity.getAccessControlPolicies(), request.getFrom(), Operation.DELETE);
UriMapper.deleteUri(containerEntity.getHierarchicalURI());
Notifier.notifyDeletion(containerEntity.getSubscriptions(), containerEntity);
// delete the resource in the database
dbs.getDAOFactory().getContainerDAO().delete(transaction, containerEntity);
// commit the transaction
transaction.commit();
// return the response
response.setResponseStatusCode(ResponseStatusCode.DELETED);
return response;
}
}