blob: 1781ac71d1e2a1a33f6c4b7b00b97f6c28eb3bc7 [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.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.AccessControlOriginatorEntity;
import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
import org.eclipse.om2m.commons.entities.AccessControlRuleEntity;
import org.eclipse.om2m.commons.entities.CSEBaseEntity;
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.AccessDeniedException;
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.RemoteCSE;
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.persistence.PersistenceService;
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.persistence.service.DAO;
import org.eclipse.om2m.persistence.service.DBService;
import org.eclipse.om2m.persistence.service.DBTransaction;
/**
* Controller for remote CSE
*
*/
public class RemoteCSEController extends Controller {
/**
* Create the resource in the system according to the representation
* @param request
* @return response
*/
@Override
public ResponsePrimitive doCreate(RequestPrimitive request) {
/*
* remoteCSE creation procedure
*
* @resourceName NP
* resourceType NP
* resourceID NP
* parentID NP
* accessControlPolicyIDs O
* creationTime NP
* expirationTime O
* lastModifiedTime NP
* labels O
* announceTo O
* announcedAttribute O
*
* cseType O
* poa O
* CseBase M
* CSE-ID M
* M2M-EXT-ID O
* Trigger-Recipient-ID O
* requestReachability M
* nodeLink NP
*
*/
ResponsePrimitive response = new ResponsePrimitive(request);
// get the database service
DBService dbs = PersistenceService.getInstance().getDbService();
DBTransaction transaction = dbs.getDbTransaction();
transaction.open();
// 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 the parent resource");
}
// get lists to change in the method corresponding to specific object
List<AccessControlPolicyEntity> acpsToCheck = null;
List<RemoteCSEEntity> remoteCSEs = 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();
remoteCSEs = cseB.getRemoteCses();
subscriptions = cseB.getSubscriptions();
}
// check if originator is provided
if (request.getFrom() == null){
throw new AccessDeniedException("No originator provided");
}
boolean newOriginator = false;
if (originatorExists(request.getFrom())) {
// check access control policy of the originator
checkACP(acpsToCheck, request.getFrom(), Operation.CREATE);
} else {
newOriginator = true;
}
// check if content is present
if (request.getContent() == null){
throw new BadRequestException("A content is requiered for RemoteCSE creation");
}
// get the object from the representation
RemoteCSE remoteCse = null;
try{
if(request.getRequestContentType().equals(MimeMediaType.OBJ)){
remoteCse = (RemoteCSE) request.getContent();
} else {
remoteCse = (RemoteCSE)DataMapperSelector.getDataMapperList()
.get(request.getRequestContentType()).stringToObj((String)request.getContent());
}
} catch (ClassCastException e){
throw new BadRequestException("Incorrect resource representation in content");
}
if (remoteCse == null){
throw new BadRequestException("Error in provided content");
}
RemoteCSEEntity remoteCseEntity = new RemoteCSEEntity();
// check attributes
// @resourceName NP
// Resource Type NP
// resourceID NP
// parentID NP
// lastModifiedTime NP
// creationTime NP
// labels O
ControllerUtil.CreateUtil.fillEntityFromGenericResource(remoteCse, remoteCseEntity);
// nodelink NP
if (remoteCse.getNodeLink() != null){
throw new NotPermittedAttrException("NodeLink is Not Permitted");
}
// CseBase M
if (remoteCse.getCSEBase() == null) {
throw new BadRequestException("CseBase is Mandatory");
} else {
remoteCseEntity.setRemoteCseUri(remoteCse.getCSEBase());
}
// CSE-ID M
if (remoteCse.getCSEID() == null) {
throw new BadRequestException("CSE-ID is mandatory");
} else {
remoteCseEntity.setRemoteCseId(remoteCse.getCSEID());
}
// requestReachability M
if (remoteCse.isRequestReachability() == null){
throw new BadRequestException("Request Reachability is mandatory");
} else {
remoteCseEntity.setRequestReachability(remoteCse.isRequestReachability());
}
// accessControlPolicyIDs O
if (!remoteCse.getAccessControlPolicyIDs().isEmpty()){
remoteCseEntity.setAccessControlPolicies(
ControllerUtil.buildAcpEntityList(remoteCse.getAccessControlPolicyIDs(), transaction));
} else {
remoteCseEntity.getAccessControlPolicies().addAll(acpsToCheck);
}
// expiration time O
if (remoteCse.getExpirationTime() != null){
remoteCseEntity.setExpirationTime(remoteCse.getExpirationTime());
}
// labels O
if (!remoteCse.getLabels().isEmpty()){
remoteCseEntity.setLabelsEntitiesFromSring(remoteCse.getLabels());
}
// announceTo O
if (!remoteCse.getAnnounceTo().isEmpty()){
remoteCseEntity.getAnnounceTo().addAll(remoteCse.getAnnounceTo());
}
// announcedAttribute O
if (!remoteCse.getAnnouncedAttribute().isEmpty()){
remoteCseEntity.getAnnouncedAttribute().addAll(remoteCse.getAnnouncedAttribute());
}
// cseType O
if (remoteCse.getCseType() != null) {
remoteCseEntity.setCseType(remoteCse.getCseType());
}
// poa O
if (!remoteCse.getPointOfAccess().isEmpty()){
remoteCseEntity.getPointOfAccess().addAll(remoteCse.getPointOfAccess());
}
// M2M-EXT-ID O
if(remoteCse.getM2MExtID() != null) {
remoteCseEntity.setM2mExtId(remoteCse.getM2MExtID());
}
// Trigger-Recipient-ID O
if (remoteCse.getTriggerRecipientID() != null) {
remoteCseEntity.setTriggerRecipientID(remoteCse.getTriggerRecipientID());
}
// creating the corresponding entity
String generatedId = generateId("", "");
remoteCseEntity.setResourceID("/" + Constants.CSE_ID + "/" + ShortName.REMOTE_CSE + Constants.PREFIX_SEPERATOR + generatedId);
// set name if present and without any conflict
if (remoteCse.getName() != null){
if (!Patterns.checkResourceName(remoteCse.getName())){
throw new BadRequestException("Name provided is incorrect. Must be:" + Patterns.ID_STRING);
}
remoteCseEntity.setName(remoteCse.getName());
} else
if (request.getName() != null){
if (!Patterns.checkResourceName(request.getName())){
throw new BadRequestException("Name provided is incorrect. Must be:" + Patterns.ID_STRING);
}
remoteCseEntity.setName(request.getName());
} else {
remoteCseEntity.setName(ShortName.REMOTE_CSE + "_" + generatedId);
}
remoteCseEntity.setHierarchicalURI(parentEntity.getHierarchicalURI() + "/" + remoteCseEntity.getName());
if (!UriMapper.addNewUri(remoteCseEntity.getHierarchicalURI(), remoteCseEntity.getResourceID(), ResourceType.REMOTE_CSE)){
throw new ConflictException("Name already present in the parent collection.");
}
remoteCseEntity.setCreationTime(DateUtil.now());
remoteCseEntity.setLastModifiedTime(DateUtil.now());
remoteCseEntity.setParentID(parentEntity.getResourceID());
remoteCseEntity.setResourceType(ResourceType.REMOTE_CSE);
if(newOriginator){
AccessControlPolicyEntity acpEntity = new AccessControlPolicyEntity();
acpEntity.setCreationTime(DateUtil.now());
acpEntity.setLastModifiedTime(DateUtil.now());
acpEntity.setParentID("/" + Constants.CSE_ID);
acpEntity.setResourceID("/" + Constants.CSE_ID + "/" + ShortName.ACP + Constants.PREFIX_SEPERATOR + generateId());
acpEntity.setName(ShortName.ACP + ShortName.REMOTE_CSE + Constants.PREFIX_SEPERATOR + generatedId);
AccessControlRuleEntity ruleEntity = new AccessControlRuleEntity();
AccessControlOriginatorEntity originatorEntity = new AccessControlOriginatorEntity(Constants.ADMIN_REQUESTING_ENTITY);
ruleEntity.getAccessControlOriginators().add(originatorEntity);
ruleEntity.setCreate(true);
ruleEntity.setRetrieve(true);
ruleEntity.setUpdate(true);
ruleEntity.setDelete(true);
ruleEntity.setNotify(true);
ruleEntity.setDiscovery(true);
acpEntity.getSelfPrivileges().add(ruleEntity);
// Privileges
ruleEntity = new AccessControlRuleEntity();
ruleEntity.setCreate(true);
ruleEntity.setRetrieve(true);
ruleEntity.setUpdate(true);
ruleEntity.setDelete(true);
ruleEntity.setNotify(true);
ruleEntity.setDiscovery(true);
ruleEntity.getAccessControlOriginators().add(new AccessControlOriginatorEntity(request.getFrom()));
ruleEntity.getAccessControlOriginators().add(new AccessControlOriginatorEntity(Constants.ADMIN_REQUESTING_ENTITY));
acpEntity.getPrivileges().add(ruleEntity);
acpEntity.setHierarchicalURI("/" + Constants.CSE_ID + "/" + acpEntity.getName());
UriMapper.addNewUri(acpEntity.getHierarchicalURI(), acpEntity.getResourceID(), ResourceType.ACCESS_CONTROL_POLICY);
dbs.getDAOFactory().getAccessControlPolicyDAO().create(transaction, acpEntity);
AccessControlPolicyEntity acpDB = dbs.getDAOFactory().getAccessControlPolicyDAO().find(transaction, acpEntity.getResourceID());
CSEBaseEntity cseBase = dbs.getDAOFactory().getCSEBaseDAO().find(transaction, "/" + Constants.CSE_ID);
cseBase.getChildAccessControlPolicies().add(acpDB);
dbs.getDAOFactory().getCSEBaseDAO().update(transaction, cseBase);
remoteCseEntity.getAccessControlPolicies().add(acpDB);
remoteCseEntity.setGeneratedAcp(acpDB);
}
// Create remoteCSE in database
dbs.getDAOFactory().getRemoteCSEDAO().create(transaction, remoteCseEntity);
// Get the managed object from db
RemoteCSEEntity csrDB = dbs.getDAOFactory().getRemoteCSEDAO().find(transaction, remoteCseEntity.getResourceID());
// Add the remoteCSE to the CSEBase list
remoteCSEs.add(csrDB);
dao.update(transaction, parentEntity);
// Commit the DB transaction
transaction.commit();
Notifier.notify(subscriptions, csrDB, ResourceStatus.CHILD_CREATED);
// Create the response
response.setResponseStatusCode(ResponseStatusCode.CREATED);
// Set the location of the resource
setLocationAndCreationContent(request, response, csrDB);
return response;
}
@Override
public ResponsePrimitive doRetrieve(RequestPrimitive request) {
// Creating the response primitive
ResponsePrimitive response = new ResponsePrimitive(request);
// Check existence of the resource
RemoteCSEEntity csrEntity = dbs.getDAOFactory().getRemoteCSEDAO().find(transaction, request.getTargetId());
if (csrEntity == null) {
throw new ResourceNotFoundException();
}
// if resource exists, check authorization
// retrieve
List<AccessControlPolicyEntity> acpList = csrEntity.getAccessControlPolicies();
checkACP(acpList, request.getFrom(), request.getOperation());
// Mapping the entity with the exchange resource
RemoteCSE csr = EntityMapperFactory.getRemoteCseMapper().mapEntityToResource(csrEntity, request);
response.setContent(csr);
response.setResponseStatusCode(ResponseStatusCode.OK);
// return the response
return response;
}
/**
* Implement the full update method for remoteCSE resource
* @param request
* @return response
*/
@Override
public ResponsePrimitive doUpdate(RequestPrimitive request) {
/*
* remoteCSE update procedure
*
* @resourceName NP
* resourceType NP
* resourceID NP
* parentID NP
* accessControlPolicyIDs O
* creationTime NP
* expirationTime O
* lastModifiedTime NP
* labels NP
* announceTo O
* announcedAttribute O
*
* cseType NP
* poa O
* CseBase NP
* CSE-ID NP
* M2M-EXT-ID O
* Trigger-Recipient-ID O
* requestReachability O
* nodeLink NP
*/
// create the response base
ResponsePrimitive response = new ResponsePrimitive(request);
// get the persistence service
DBService dbs = PersistenceService.getInstance().getDbService();
DBTransaction transaction = dbs.getDbTransaction();
transaction.open();
// retrieve the resource from the DB
RemoteCSEEntity csrEntity = dbs.getDAOFactory().getRemoteCSEDAO().find(transaction, request.getTargetId());
if (csrEntity == null) {
throw new ResourceNotFoundException();
}
// check ACP
checkACP(csrEntity.getAccessControlPolicies(), request.getFrom(), Operation.UPDATE);
// check if content is present
if (request.getContent() == null) {
throw new BadRequestException("A content is requiered for RemoteCSE Update");
}
// create the java object from the resource representation
RemoteCSE csr = null;
try{
if (request.getRequestContentType().equals(MimeMediaType.OBJ)){
csr = (RemoteCSE) request.getContent();
} else {
csr = (RemoteCSE)DataMapperSelector.getDataMapperList()
.get(request.getRequestContentType()).stringToObj((String)request.getContent());
}
} catch (ClassCastException e){
throw new BadRequestException("Incorrect resource representation in content", e);
}
if (csr == null){
throw new BadRequestException("Error in provided content");
}
// check attributes, NP attributes are ignored
// @resourceName NP
// resourceType NP
// resourceID NP
// parentID NP
// creationTime NP
// lastModifiedTime NP
// labels NP
// cseType NP
// CseBase NP
// CSE-ID NP
// nodeLink NP
RemoteCSE modifiedAttributes = new RemoteCSE();
// accessControlPolicyIDs O
if (!csr.getAccessControlPolicyIDs().isEmpty()){
csrEntity.setAccessControlPolicies(
ControllerUtil.buildAcpEntityList(csr.getAccessControlPolicyIDs(), transaction));
modifiedAttributes.getAccessControlPolicyIDs().addAll(csr.getAccessControlPolicyIDs());
}
// expirationTime O
if (csr.getExpirationTime() != null){
csrEntity.setExpirationTime(csr.getExpirationTime());
modifiedAttributes.setExpirationTime(csr.getExpirationTime());
}
// announceTo O
if(!csr.getAnnounceTo().isEmpty()){
// TODO Announcement in AE update
csrEntity.getAnnounceTo().clear();
csrEntity.getAnnounceTo().addAll(csr.getAnnounceTo());
modifiedAttributes.getAnnounceTo().addAll(csr.getAnnounceTo());
}
// announcedAttribute O
if(!csr.getAnnouncedAttribute().isEmpty()){
csrEntity.getAnnouncedAttribute().clear();
csrEntity.getAnnouncedAttribute().addAll(csr.getAnnouncedAttribute());
modifiedAttributes.getAnnouncedAttribute().addAll(csr.getAnnouncedAttribute());
}
// poa O
if (!csr.getPointOfAccess().isEmpty()) {
csrEntity.getPointOfAccess().clear();
csrEntity.getPointOfAccess().addAll(csr.getPointOfAccess());
modifiedAttributes.getPointOfAccess().addAll(csr.getPointOfAccess());
}
// M2M-EXT-ID O
if (csr.getM2MExtID() != null) {
csrEntity.setM2mExtId(csr.getM2MExtID());
modifiedAttributes.setM2MExtID(csr.getM2MExtID());
}
// Trigger-Recipient-ID O
if (csr.getTriggerRecipientID() != null) {
csrEntity.setTriggerRecipientID(csr.getTriggerRecipientID());
modifiedAttributes.setTriggerRecipientID(csr.getTriggerRecipientID());
}
// requestReachability O
if (csr.isRequestReachability() != null) {
csrEntity.setRequestReachability(csr.isRequestReachability());
modifiedAttributes.setRequestReachability(csr.isRequestReachability());
}
csrEntity.setLastModifiedTime(DateUtil.now());
modifiedAttributes.setLastModifiedTime(csrEntity.getLastModifiedTime());
response.setContent(modifiedAttributes);
// update the resource in the database
dbs.getDAOFactory().getRemoteCSEDAO().update(transaction, csrEntity);
transaction.commit();
Notifier.notify(csrEntity.getSubscriptions(), csrEntity, ResourceStatus.UPDATED);
// set response status code
response.setResponseStatusCode(ResponseStatusCode.UPDATED);
return response;
}
@Override
/**
* Delete the remoteCSE if access control policies are correct
*/
public ResponsePrimitive doDelete(RequestPrimitive request) {
// Generic delete procedure
ResponsePrimitive response = new ResponsePrimitive(request);
// retrieve the corresponding resource from database
RemoteCSEEntity csrEntity = dbs.getDAOFactory().getRemoteCSEDAO().find(transaction, request.getTargetId());
if (csrEntity == null) {
throw new ResourceNotFoundException();
}
// check access control policies
checkACP(csrEntity.getAccessControlPolicies(), request.getFrom(), Operation.DELETE);
UriMapper.deleteUri(csrEntity.getHierarchicalURI());
Notifier.notifyDeletion(csrEntity.getSubscriptions(), csrEntity);
// delete the resource in the database
dbs.getDAOFactory().getRemoteCSEDAO().delete(transaction, csrEntity);
// commit the transaction
transaction.commit();
// return the response
response.setResponseStatusCode(ResponseStatusCode.DELETED);
return response;
}
}