| /******************************************************************************* |
| * 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.security.SecureRandom; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.eclipse.om2m.commons.constants.MimeMediaType; |
| import org.eclipse.om2m.commons.constants.Operation; |
| import org.eclipse.om2m.commons.constants.ResultContent; |
| 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.ResourceEntity; |
| import org.eclipse.om2m.commons.exceptions.AccessDeniedException; |
| import org.eclipse.om2m.commons.exceptions.BadRequestException; |
| import org.eclipse.om2m.commons.exceptions.Om2mException; |
| import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException; |
| import org.eclipse.om2m.commons.resource.RequestPrimitive; |
| import org.eclipse.om2m.commons.resource.Resource; |
| import org.eclipse.om2m.commons.resource.ResponsePrimitive; |
| import org.eclipse.om2m.core.datamapper.DataMapperSelector; |
| import org.eclipse.om2m.core.entitymapper.EntityMapper; |
| import org.eclipse.om2m.core.entitymapper.EntityMapperFactory; |
| import org.eclipse.om2m.core.persistence.PersistenceService; |
| import org.eclipse.om2m.persistence.service.DBService; |
| import org.eclipse.om2m.persistence.service.DBTransaction; |
| |
| /** |
| * Controller class contains generic and abstract Create, Retrieve, Update, Delete and Execute |
| * methods to handle generic REST request that will be implemented in extended-to classes. |
| * |
| */ |
| public abstract class Controller { |
| /** Logger */ |
| protected static Log LOGGER = LogFactory.getLog(Controller.class); |
| |
| /** Pointer to Database service */ |
| protected DBService dbs; |
| /** Transaction for the current instance of controller and request */ |
| protected DBTransaction transaction; |
| |
| /** |
| * Perform the request on selected controller |
| * @param request |
| * @return |
| */ |
| public ResponsePrimitive doRequest(RequestPrimitive request) throws Om2mException{ |
| ResponsePrimitive response = new ResponsePrimitive(request); |
| dbs = PersistenceService.getInstance().getDbService(); |
| transaction = dbs.getDbTransaction(); |
| try{ |
| transaction.open(); |
| if(request.getOperation().equals(Operation.CREATE)){ |
| response = doCreate(request); |
| } else if(request.getOperation().equals(Operation.RETRIEVE)){ |
| response = doRetrieve(request); |
| } else if(request.getOperation().equals(Operation.UPDATE)){ |
| response = doUpdate(request); |
| } else if(request.getOperation().equals(Operation.DELETE)){ |
| response = doDelete(request); |
| } else { |
| throw new BadRequestException("Incorrect Operation value (op): " + request.getOperation()); |
| } |
| } catch(Om2mException om2mException){ |
| throw om2mException; |
| } catch(Exception e){ |
| LOGGER.error("Controller internal error", e); |
| throw e; |
| } finally { |
| transaction.close(); |
| } |
| return response; |
| } |
| |
| /** |
| * Abstract Create method to handle generic REST request. |
| * @param request - The generic request to handle. |
| * @return The generic returned response. |
| */ |
| public abstract ResponsePrimitive doCreate (RequestPrimitive request); |
| |
| /** |
| * Abstract Retrieve method to handle generic REST request. |
| * @param request - The generic request to handle. |
| * @return The generic returned response. |
| */ |
| public abstract ResponsePrimitive doRetrieve (RequestPrimitive request); |
| |
| /** |
| * Abstract Update method to handle generic REST request. |
| * @param request - The generic request to handle. |
| * @return The generic returned response. |
| */ |
| public abstract ResponsePrimitive doUpdate (RequestPrimitive request); |
| |
| /** |
| * Abstract Delete method to handle generic REST request. |
| * @param request - The generic request to handle. |
| * @return The generic returned response. |
| */ |
| public abstract ResponsePrimitive doDelete (RequestPrimitive request); |
| |
| /** |
| * Check the access right based on acpId |
| * @param acpID |
| * @param originator |
| * @param method |
| */ |
| public void checkACP(String acpID, String originator, BigInteger method) throws AccessDeniedException{ |
| DBService db = PersistenceService.getInstance().getDbService(); |
| DBTransaction transaction = db.getDbTransaction(); |
| transaction.open(); |
| if (!originatorExists(originator)) { |
| throw new AccessDeniedException("Provided originator not found"); |
| } |
| AccessControlPolicyEntity acp = db.getDAOFactory().getAccessControlPolicyDAO().find(transaction, acpID); |
| if (acp == null){ |
| throw new ResourceNotFoundException(); |
| } |
| List<AccessControlPolicyEntity> acpList = new ArrayList<>(); |
| acpList.add(acp); |
| checkACP(acpList, originator, method); |
| transaction.close(); |
| } |
| |
| /** |
| * Checks the Access Right based on ACP list (Permission) |
| * @param acp - Id of the accessRight |
| * @param originator - requesting entity used by the requester |
| * @param operation - requested method |
| * @return error with a specific status code if the requesting Entity or the method does not exist otherwise null |
| */ |
| public void checkACP(List<AccessControlPolicyEntity> acpList, String originator, BigInteger operation) |
| throws AccessDeniedException{ |
| if(originator == null){ |
| throw new AccessDeniedException(); |
| } |
| if (acpList == null || acpList.isEmpty()) { |
| throw new ResourceNotFoundException("Current resource does not have any ACP attached"); |
| } |
| // Check Resource accessRight existence not found |
| boolean originatorFound = false; |
| boolean operationAllowed = false; |
| for(AccessControlPolicyEntity acp : acpList){ |
| for (AccessControlRuleEntity rule : acp.getPrivileges()){ |
| originatorFound = false ; |
| operationAllowed = false; |
| for (AccessControlOriginatorEntity originatorEntity : rule.getAccessControlOriginators()){ |
| if (originator.matches(originatorEntity.getOriginatorID().replace("*", ".*"))){ |
| originatorFound = true; |
| break; |
| } |
| } |
| if (originatorFound){ |
| if (operation.equals(Operation.CREATE) && rule.isCreate()){ |
| operationAllowed = true; |
| } else if (operation.equals(Operation.RETRIEVE) && rule.isRetrieve()){ |
| operationAllowed = true; |
| } else if (operation.equals(Operation.UPDATE) && rule.isUpdate()){ |
| operationAllowed = true; |
| } else if (operation.equals(Operation.DELETE) && rule.isDelete()){ |
| operationAllowed = true; |
| } else if (operation.equals(Operation.DISCOVERY) && rule.isDiscovery()){ |
| operationAllowed = true; |
| } else if (operation.equals(Operation.NOTIFY) && rule.isNotify()){ |
| operationAllowed = true; |
| } |
| } |
| if (originatorFound && operationAllowed){ |
| break; |
| } |
| } |
| if (originatorFound && operationAllowed){ |
| break; |
| } |
| } |
| |
| if (!originatorFound){ |
| throw new AccessDeniedException(); |
| } |
| if (!operationAllowed){ |
| throw new AccessDeniedException(); |
| } |
| } |
| |
| /** |
| * Check Access Right from Acp Self privileges for ACP modifications |
| * @param acp to check |
| * @param originator to validate |
| * @param operation |
| */ |
| public void checkSelfACP(AccessControlPolicyEntity acp, String originator, BigInteger operation) |
| throws AccessDeniedException{ |
| // Check Resource accessRight existence not found |
| boolean originatorFound = false; |
| boolean operationAllowed = false; |
| |
| for (AccessControlRuleEntity rule : acp.getSelfPrivileges()){ |
| originatorFound = false ; |
| operationAllowed = false ; |
| for (AccessControlOriginatorEntity originatorEntity : rule.getAccessControlOriginators()){ |
| if (originator.matches(originatorEntity.getOriginatorID().replace("*", ".*"))){ |
| originatorFound = true; |
| break; |
| } |
| } |
| if (originatorFound){ |
| if (operation.equals(Operation.CREATE)){ |
| if (rule.isCreate()){ |
| operationAllowed = true; |
| } |
| } else if (operation.equals(Operation.RETRIEVE)){ |
| if (rule.isRetrieve()){ |
| operationAllowed = true; |
| } |
| } else if (operation.equals(Operation.UPDATE)){ |
| if (rule.isUpdate()){ |
| operationAllowed = true; |
| } |
| } else if (operation.equals(Operation.DELETE)){ |
| if (rule.isDelete()){ |
| operationAllowed = true; |
| } |
| } |
| } |
| if (originatorFound && operationAllowed){ |
| break; |
| } |
| } |
| if (!originatorFound){ |
| throw new AccessDeniedException(); |
| } |
| if (!operationAllowed){ |
| throw new AccessDeniedException(); |
| } |
| } |
| |
| |
| /** |
| * Generates an random ID based on SecureRandom library |
| * @param prefix - prefix of the resource ID |
| * @param postfix - postfix of the resource ID |
| * @return generated resource ID |
| */ |
| public static String generateId(String prefix, String postfix) { |
| SecureRandom secureRandom = new SecureRandom(); |
| return prefix+String.valueOf(secureRandom.nextInt(999999999))+postfix; |
| } |
| |
| /** |
| * Generates a random ID based on SecureRandom library |
| * @return generated resource ID |
| */ |
| public static String generateId(){ |
| return generateId("", ""); |
| } |
| |
| protected void setLocationAndCreationContent(RequestPrimitive request, |
| ResponsePrimitive response, ResourceEntity entity){ |
| setLocationAndCreationContent(request, response, entity, EntityMapperFactory. |
| getMapperFromResourceType(entity.getResourceType().intValue())); |
| } |
| |
| @SuppressWarnings("unchecked") |
| protected void setLocationAndCreationContent(RequestPrimitive request, |
| ResponsePrimitive response, ResourceEntity entity, @SuppressWarnings("rawtypes") EntityMapper mapper){ |
| if(request.getResultContent()!= null){ |
| if (request.getResultContent().equals(ResultContent.HIERARCHICAL_ADRESS) |
| || request.getResultContent().equals(ResultContent.HIERARCHICAL_AND_ATTRIBUTES)){ |
| response.setLocation(entity.getHierarchicalURI()); |
| } else { |
| response.setLocation(entity.getResourceID()); |
| } |
| if(request.getResultContent().equals(ResultContent.HIERARCHICAL_AND_ATTRIBUTES) |
| || request.getResultContent().equals(ResultContent.ATTRIBUTES)){ |
| Resource res = mapper.mapEntityToResource(entity, ResultContent.ATTRIBUTES); |
| if(request.getReturnContentType().equals(MimeMediaType.OBJ)){ |
| response.setContent(res); |
| } else { |
| String representation = DataMapperSelector.getDataMapperList(). |
| get(request.getReturnContentType()).objToString(res); |
| response.setContent(representation); |
| } |
| } |
| } else { |
| response.setContent(mapper.mapEntityToResource(entity, ResultContent.ATTRIBUTES)); |
| response.setLocation(entity.getResourceID()); |
| } |
| } |
| |
| |
| /** |
| * Allows to know if the provided originator exists in the system |
| * @param originator |
| * @return true if exists |
| */ |
| protected boolean originatorExists(String originator) { |
| boolean isValid = false; |
| DBService db = PersistenceService.getInstance().getDbService(); |
| DBTransaction transaction = db.getDbTransaction(); |
| transaction.open(); |
| AccessControlOriginatorEntity originatorEntity = db.getDAOFactory().getAccessControlOriginatorDAO().find(transaction, originator); |
| if (originatorEntity != null) { |
| isValid = true; |
| } |
| transaction.close(); |
| return isValid; |
| } |
| |
| /** |
| * Allows to store the originator |
| * @param originator |
| */ |
| protected void registerOriginator(String originator) { |
| DBService db = PersistenceService.getInstance().getDbService(); |
| DBTransaction transaction = db.getDbTransaction(); |
| transaction.open(); |
| // create the new originator |
| AccessControlOriginatorEntity originatorEntity = new AccessControlOriginatorEntity(); |
| originatorEntity.setOriginatorID(originator); |
| // persist the new access control originator |
| db.getDAOFactory().getAccessControlOriginatorDAO().create(transaction, originatorEntity); |
| transaction.commit(); |
| transaction.close(); |
| } |
| |
| } |