blob: 3e55bf86e99c302e4523c439edf00c5780784e42 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013-2015 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
*
* Contributors:
* Thierry Monteil (Project co-founder) - Management and initial specification,
* conception and documentation.
* Mahdi Ben Alaya (Project co-founder) - Management and initial specification,
* conception, implementation, test and documentation.
* Christophe Chassot - Management and initial specification.
* Khalil Drira - Management and initial specification.
* Yassine Banouar - Initial specification, conception, implementation, test
* and documentation.
* Guillaume Garzone - Conception, implementation, test and documentation.
* Francois Aissaoui - Conception, implementation, test and documentation.
******************************************************************************/
package org.eclipse.om2m.core.controller;
import java.util.Date;
import javax.persistence.EntityManager;
import org.eclipse.om2m.commons.resource.Base64Binary;
import org.eclipse.om2m.commons.resource.Container;
import org.eclipse.om2m.commons.resource.ContentInstance;
import org.eclipse.om2m.commons.resource.ContentInstances;
import org.eclipse.om2m.commons.resource.ErrorInfo;
import org.eclipse.om2m.commons.resource.Refs;
import org.eclipse.om2m.commons.resource.StatusCode;
import org.eclipse.om2m.commons.rest.RequestIndication;
import org.eclipse.om2m.commons.rest.ResponseConfirm;
import org.eclipse.om2m.commons.utils.DateConverter;
import org.eclipse.om2m.commons.utils.XmlMapper;
import org.eclipse.om2m.core.constants.Constants;
import org.eclipse.om2m.core.dao.DAOFactory;
import org.eclipse.om2m.core.dao.DBAccess;
import org.eclipse.om2m.core.notifier.Notifier;
import org.eclipse.om2m.core.router.Router;
/**
* Implements Create, Retrieve, Update, Delete and Execute methods to handle
* generic REST request for {@link ContentInstance} resource.
*
* @author <ul>
* <li>Yassine Banouar < ybanouar@laas.fr > < yassine.banouar@gmail.com ></li>
* <li>Mahdi Ben Alaya < ben.alaya@laas.fr > < benalaya.mahdi@gmail.com ></li>
* </ul>
*/
public class ContentInstanceController extends Controller {
public static Object lock = new Object();
/**
* Creates {@link ContentInstance} resource.
* @param requestIndication - The generic request to handle.
* @return The generic returned response.
*/
public ResponseConfirm doCreate (RequestIndication requestIndication) {
// id: (createReq O) (response M*)
// href: (createReq NP) (response O)
// contentTypes: (createReq O) (response O)
// contentSize: (createReq NP) (response M)
// creationTime: (createReq NP) (response M)
// lastModifiedTime: (createReq NP) (response M)
// delayTolerance: (createReq O) (response O)
// content: (createReq M) (response M)
EntityManager em = DBAccess.createEntityManager();
em.getTransaction().begin();
ResponseConfirm errorResponse = new ResponseConfirm();
ContentInstance contentInstance = new ContentInstance();
ContentInstances contentInstances = DAOFactory.getContentInstancesDAO().find(requestIndication.getTargetID(), em);
// Check Resource Parent Existence
if (contentInstances == null) {
em.close();
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_NOT_FOUND,requestIndication.getTargetID()+" does not exist")) ;
}
// Check AccessRight
Container container = DAOFactory.getContainerDAO().find(requestIndication.getTargetID().split(Refs.CONTENTINSTANCES_REF)[0], em);
errorResponse = checkAccessRight(container.getAccessRightID(), requestIndication.getRequestingEntity(), Constants.AR_CREATE);
if (errorResponse != null) {
em.close();
return errorResponse;
}
// Check Resource Representation
if (requestIndication.getRepresentation() == null) {
em.close();
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_BAD_REQUEST,"Resource Representation is EMPTY")) ;
}
// Create a Content if its a direct content Creation with contentInstance
try{
contentInstance = (ContentInstance) XmlMapper.getInstance().xmlToObject(requestIndication.getRepresentation());
} catch (ClassCastException e){
LOGGER.debug("ClassCastException : Incorrect resource type in JAXB unmarshalling.",e);
contentInstance = null ;
}
if (contentInstance == null){
contentInstance = new ContentInstance() ;
Base64Binary content = new Base64Binary();
content.setContentType("application/xml");
content.setValue(requestIndication.getRepresentation().getBytes());
contentInstance.setContent(content);
}
//Check on attributes
// href Must be NP
if (contentInstance.getHref() != null) {
em.close();
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_BAD_REQUEST," Href CREATE is Not Permitted")) ;
}
// ContentSize Must be NP
if (contentInstance.getContentSize() != null) {
em.close();
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_BAD_REQUEST," ContentSize CREATE is Not Permitted")) ;
}
// CreationTime Must be NP
if (contentInstance.getCreationTime() != null) {
em.close();
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_BAD_REQUEST," CreationTime CREATE is Not Permitted")) ;
}
// LastModifiedTime Must be NP
if (contentInstance.getLastModifiedTime() != null) {
em.close();
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_BAD_REQUEST," LastModifiedTime CREATE is Not Permitted")) ;
}
// Content is Mandatory
if (contentInstance.getContent() == null) {
em.close();
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_BAD_REQUEST," Content CREATE is Mandatory")) ;
}
// Check ID Conformity
if (contentInstance.getId() != null && !contentInstance.getId().matches(Constants.ID_REGEXPR)){
em.close();
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_BAD_REQUEST,"Id should match the following regexpr: " + Constants.ID_REGEXPR));
}
// Check uniqueness and Set id if it is not available
if (contentInstance.getId() == null || contentInstance.getId().isEmpty()
|| DAOFactory.getContentInstanceDAO().find(requestIndication.getTargetID()+"/"+contentInstance.getId(), em) != null) {
contentInstance.setId(generateId("CI_",""));
}
// Set URI
contentInstance.setUri(requestIndication.getTargetID()+ "/" +contentInstance.getId());
// Set href
contentInstance.setHref(contentInstance.getUri());
// Set contentSize
contentInstance.setContentSize((long) contentInstance.getContent().getValue().length);
// Set delayTolerance if it's null
if (contentInstance.getDelayTolerance() == null) {
contentInstance.setDelayTolerance(getNewDelayTolerance(12000));
}
// Set CreationTime
contentInstance.setCreationTime(DateConverter.toXMLGregorianCalendar(new Date()).toString());
// Set LastModifiedTime
contentInstance.setLastModifiedTime(DateConverter.toXMLGregorianCalendar(new Date()).toString());
// Notify the subscribers
Notifier.notify(StatusCode.STATUS_CREATED, contentInstance);
//Store contentInstance
DAOFactory.getContentInstanceDAO().create(contentInstance, em);
contentInstances.setCurrentNrOfInstances(contentInstances.getCurrentNrOfInstances() + 1);
contentInstances.setCurrentByteSize(contentInstances.getCurrentByteSize() + contentInstance.getContentSize());
DAOFactory.getContentInstancesDAO().update(contentInstances, em);
// delete the oldest contentInstance if the CurrentNrOfInstances reaches MaxNrOfInstances
if (contentInstances.getCurrentNrOfInstances() > container.getMaxNrOfInstances()) {
final String targetID = requestIndication.getTargetID();
new Thread(){
public void run(){
Router.readWriteLock.readLock().lock();
EntityManager em = DBAccess.createEntityManager();
em.getTransaction().begin();
ContentInstance contentInstanceOldest = DAOFactory.getContentInstanceDAO().find(targetID+"/oldest", em);
//Delete the oldest contentInstance
DAOFactory.getContentInstanceDAO().delete(contentInstanceOldest,em);
ContentInstances contentInstances = DAOFactory.getContentInstancesDAO().find(targetID, em);
contentInstances.setCurrentNrOfInstances(contentInstances.getCurrentNrOfInstances() - 1);
contentInstances.setCurrentByteSize(contentInstances.getCurrentByteSize() - contentInstanceOldest.getContentSize());
DAOFactory.getContentInstancesDAO().update(contentInstances, em);
em.getTransaction().commit();
em.close();
Router.readWriteLock.readLock().unlock();
}
}.start();
}
em.getTransaction().commit();
em.close();
// Response
return new ResponseConfirm(StatusCode.STATUS_CREATED, contentInstance);
}
/**
* Retrieves {@link ContentInstance} resource.
* @param requestIndication - The generic request to handle.
* @return The generic returned response.
*/
public ResponseConfirm doRetrieve (RequestIndication requestIndication) {
// id: (response M*)
// href: (response O)
// contentTypes: (response O)
// contentSize: (response M)
// creationTime: (response M)
// lastModifiedTime: (response M)
// delayTolerance: (response O)
// content: (response M)
ResponseConfirm errorResponse = new ResponseConfirm();
// Check AccessRight
EntityManager em = DBAccess.createEntityManager();
em.getTransaction().begin();
Container container = DAOFactory.getContainerDAO().find(requestIndication.getTargetID().split(Refs.CONTENTINSTANCES_REF)[0], em);
errorResponse = checkAccessRight(container.getAccessRightID(), requestIndication.getRequestingEntity(), Constants.AR_READ);
if (errorResponse != null) {
em.close();
return errorResponse;
}
// Check contentInstance existence
ContentInstance contentInstance = DAOFactory.getContentInstanceDAO().find(requestIndication.getTargetID(), em);
em.close();
if (contentInstance == null) {
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_NOT_FOUND,requestIndication.getTargetID()+" does not exist")) ;
}
// Response
return new ResponseConfirm(StatusCode.STATUS_OK, contentInstance);
}
/**
* Updates {@link ContentInstance} resource.
* @param requestIndication - The generic request to handle.
* @return The generic returned response.
*/
public ResponseConfirm doUpdate (RequestIndication requestIndication) {
// id: (updateReq NA) (response M*)
// href: (updateReq NA) (response O)
// contentTypes: (updateReq NA) (response O)
// contentSize: (updateReq NA) (response M)
// creationTime: (updateReq NA) (response M)
// lastModifiedTime: (updateReq NA) (response M)
// delayTolerance: (updateReq NA) (response O)
// content: (updateReq NA) (response M)
// Response
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_METHOD_NOT_ALLOWED,requestIndication.getMethod()+" Method is not allowed"));
}
/**
* Deletes {@link ContentInstance} resource.
* @param requestIndication - The generic request to handle.
* @return The generic returned response.
*/
public ResponseConfirm doDelete (RequestIndication requestIndication) {
ResponseConfirm errorResponse = new ResponseConfirm();
EntityManager em = DBAccess.createEntityManager();
em.getTransaction().begin();
ContentInstance contentInstance = DAOFactory.getContentInstanceDAO().find(requestIndication.getTargetID(), em);
// Check Resource Existence
if (contentInstance == null) {
em.close();
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_NOT_FOUND,requestIndication.getTargetID()+" does not exist")) ;
}
// Check AccessRight
Container container = DAOFactory.getContainerDAO().find(requestIndication.getTargetID().split(Refs.CONTENTINSTANCES_REF)[0], em);
errorResponse = checkAccessRight(container.getAccessRightID(), requestIndication.getRequestingEntity(), Constants.AR_DELETE);
if (errorResponse != null) {
em.close();
return errorResponse;
}
// Notify the subscribers
Notifier.notify(StatusCode.STATUS_DELETED, contentInstance);
// Delete
DAOFactory.getContentInstanceDAO().delete(contentInstance,em);
em.getTransaction().commit();
em.close();
// Response
return new ResponseConfirm(StatusCode.STATUS_OK);
}
/**
* Executes {@link ContentInstance} resource.
* @param requestIndication - The generic request to handle.
* @return The generic returned response.
*/
public ResponseConfirm doExecute (RequestIndication requestIndication) {
// Response
return new ResponseConfirm(new ErrorInfo(StatusCode.STATUS_NOT_IMPLEMENTED,requestIndication.getMethod()+" Method is not yet Implemented")) ;
}
}