Enhance the core module

[Bug 494090] add wildcard for acp
Update thread handling and policy
Update initialization phase
Reject NP attributes on Update request
Fix some label update

Signed-off-by: Francois Aissaoui <aissaoui@laas.fr>
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/Activator.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/Activator.java
index 0668361..20283c3 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/Activator.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/Activator.java
@@ -30,9 +30,9 @@
 import org.eclipse.om2m.core.persistence.PersistenceService;
 import org.eclipse.om2m.core.router.Router;
 import org.eclipse.om2m.core.service.CseService;
+import org.eclipse.om2m.core.thread.CoreExecutor;
 import org.eclipse.om2m.datamapping.service.DataMapperService;
 import org.eclipse.om2m.interworking.service.InterworkingService;
-import org.eclipse.om2m.persistence.service.DBConstants;
 import org.eclipse.om2m.persistence.service.DBService;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
@@ -64,9 +64,8 @@
 
 			@Override
 			public Object addingService(ServiceReference<Object> reference) {
-				LOGGER.info("DataMapper Service discovered");
 				DataMapperService dataMapper = (DataMapperService) this.context.getService(reference);
-				LOGGER.info("Add Data Mapper Service: " + dataMapper.getServiceDataType());
+				LOGGER.info("Added Data Mapper Service: " + dataMapper.getServiceDataType());
 				DataMapperSelector.getDataMapperList().put(dataMapper.getServiceDataType(), dataMapper);
 				return dataMapper;
 			}
@@ -74,9 +73,8 @@
 			@Override
 			public void removedService(ServiceReference<Object> reference,
 					Object service) {
-				LOGGER.info("DataMapper Service removed");
 				DataMapperService dataMapper = (DataMapperService) service;
-				LOGGER.info("Remove Data Mapper Service: " + dataMapper.getServiceDataType());
+				LOGGER.info("Removed Data Mapper Service: " + dataMapper.getServiceDataType());
 				DataMapperSelector.getDataMapperList().remove(dataMapper.getServiceDataType());
 			}
 
@@ -91,7 +89,22 @@
 				LOGGER.info("DataBase persistence service discovered");
 				DBService dbService = (DBService) this.context.getService(reference);
 				PersistenceService.getInstance().setDbService(dbService);
-				PersistenceService.getInstance().getDbReady().release();
+
+				// Post the start routine in the CoreExecutor
+				CoreExecutor.postThread(new Runnable() {
+					@Override
+					public void run() {
+						try {
+							CSEInitializer.init();
+						} catch (InterruptedException e) {
+							LOGGER.error("Error in CSEInitializer", e);
+						}
+						LOGGER.info("Registering CseService...");
+						context.registerService(CseService.class.getName(), new Router(), null);		
+						LOGGER.info("CSE Started");		
+					}
+				});
+				
 				return dbService;
 			}
 
@@ -100,7 +113,6 @@
 					Object service) {
 				LOGGER.info("Database persistence service removed.");
 				PersistenceService.getInstance().setDbService(null);
-				PersistenceService.getInstance().resetSemaphoreDb();
 			}
 
 		};
@@ -110,9 +122,9 @@
 		restClientServiceTracker = new ServiceTracker<Object,Object>(bundleContext, RestClientService.class.getName(), null){
 
 			public Object addingService(org.osgi.framework.ServiceReference<Object> reference) {
-				LOGGER.info("Rest client service discovered");
 				RestClientService service = (RestClientService) this.context.getService(reference);
 				RestClient.getRestClients().put(service.getProtocol(), service);
+				LOGGER.info("Rest client service discovered. Protocol: " + service.getProtocol());
 				return service;
 			};
 
@@ -145,15 +157,7 @@
 			
 		};
 		ipeServiceTracker.open();
-		
-		if (DBConstants.DB_RESET) {
-			CSEInitializer.init();
-		}
 
-		LOGGER.info("Registering CseService...");
-		bundleContext.registerService(CseService.class.getName(), new Router(), null);
-
-		LOGGER.info("CSE Started");
 	}
 
 	public void stop(BundleContext bundleContext) throws Exception {
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/CSEInitializer.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/CSEInitializer.java
index 94b55cd..67fc229 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/CSEInitializer.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/CSEInitializer.java
@@ -70,29 +70,36 @@
 	 * Initialize the current launching CSE.
 	 */
 	public static void init() throws InterruptedException{
-		LOGGER.info("Waiting for the database service");
-		PersistenceService.getInstance().getDbReady().acquire();
+		LOGGER.info("Initializating the cseBase");
+		// Check the existence of the cseBase in the database
+		DBService dbs = PersistenceService.getInstance().getDbService();
+		DBTransaction transaction = dbs.getDbTransaction();
+		transaction.open();
+		CSEBaseEntity cseBase = dbs.getDAOFactory().getCSEBaseDAO().find(transaction, "/" + Constants.CSE_ID);
+		// if the cseBase is not initialized, then create the base resources
+		if(cseBase == null){
+			// Create AccessRight resource
+			LOGGER.info("Create AccessControlPolicy resource");
+			initACP();
+			
+			// Create CSEBase resource
+			LOGGER.info("Create CSEBase resource");
+			initCSEBase();			
 
-		// Create AccessRight resource
-		LOGGER.info("Create AccessControlPolicy resource");
-		initACP();
-
-		// Create CSEBase resource
-		LOGGER.info("Create CSEBase resource");
-		initCSEBase();
-
-		if(!Constants.CSE_TYPE.equalsIgnoreCase(CSEType.IN) && Constants.CSE_AUTHENTICATION){
-			LOGGER.info("Register CSE to another CSE.");
-			new Thread(new Runnable() {
-
-				@Override
-				public void run() {
-					registerCSE();					
-				}
-			}).start();
+			if(!Constants.CSE_TYPE.equalsIgnoreCase(CSEType.IN) && Constants.CSE_AUTHENTICATION){
+				LOGGER.info("Register CSE to another CSE.");
+				new Thread(new Runnable() {
+					
+					@Override
+					public void run() {
+						registerCSE();
+					}
+				}).start();
+			}
+		} else {
+			LOGGER.info("cseBase already initialized");
 		}
 
-		PersistenceService.getInstance().getDbReady().release();
 	}
 
 	/**
@@ -170,7 +177,8 @@
 		remoteCSE.setCSEID("/" + Constants.CSE_ID);
 		remoteCSE.setCSEBase("//" + Constants.M2M_SP_ID + remoteCSE.getCSEID());
 		remoteCSE.setRequestReachability(new Boolean(true));
-
+		remoteCSE.setName(Constants.CSE_ID);
+		
 		String representation = DataMapperSelector.getDataMapperList().get(contentFormat).objToString(remoteCSE);
 
 		RequestPrimitive request = new RequestPrimitive();
@@ -182,7 +190,6 @@
 		remotePoa += Constants.REMOTE_CSE_ID;
 		request.setTo(remotePoa);
 		request.setContent(representation);
-		request.setName(Constants.CSE_ID);
 		request.setOperation(Operation.CREATE);
 		request.setResourceType(BigInteger.valueOf(ResourceType.REMOTE_CSE));
 		request.setRequestContentType(contentFormat);
@@ -278,6 +285,7 @@
 		ruleEntity.setNotify(true);
 		ruleEntity.setDiscovery(true);
 		ruleEntity.getAccessControlOriginators().add(new AccessControlOriginatorEntity(Constants.ADMIN_REQUESTING_ENTITY));
+		ruleEntity.getAccessControlOriginators().add(new AccessControlOriginatorEntity("/" + Constants.CSE_ID));
 		acp.getPrivileges().add(ruleEntity);
 		
 		// privileges for ALL originators (read + discovery)
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/comm/RestClient.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/comm/RestClient.java
index 6d5a24e..1b84b6a 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/comm/RestClient.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/comm/RestClient.java
@@ -25,7 +25,8 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.eclipse.om2m.binding.service.RestClientService;
-import org.eclipse.om2m.commons.constants.ResponseStatusCode;
+import org.eclipse.om2m.commons.exceptions.InternalServerErrorException;
+import org.eclipse.om2m.commons.exceptions.NotImplementedException;
 import org.eclipse.om2m.commons.resource.RequestPrimitive;
 import org.eclipse.om2m.commons.resource.ResponsePrimitive;
 
@@ -63,17 +64,14 @@
 				}
 			}catch(Exception e){
 				LOGGER.error("RestClient error",e);
-				response.setResponseStatusCode(ResponseStatusCode.INTERNAL_SERVER_ERROR);
-				response.setErrorMessage("RestClient error");
+				throw new InternalServerErrorException("RestClient Error", e);
 			}
 		}else{
-			response.setResponseStatusCode(ResponseStatusCode.NOT_IMPLEMENTED);
-			response.setErrorMessage("No RestClient service found for protocol: " + protocol);
+			throw new NotImplementedException("No RestClient service found for protocol: " + protocol);
 		}
 
 		LOGGER.info(response);
 		return response;
-		
 	}
 
 	/**
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/AEController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/AEController.java
index b156a9c..813dfe1 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/AEController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/AEController.java
@@ -52,6 +52,7 @@
 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;
 
 /**
@@ -129,17 +130,14 @@
 
 		if (request.getFrom() != null){
 			if (request.getFrom().startsWith("S")) {
-				response.setResponseStatusCode(ResponseStatusCode.NOT_IMPLEMENTED);
-				response.setErrorMessage("originator starting with S not implemented yet");
-				transaction.close();
-				return response;
+				throw new NotImplementedException("originator starting with S not implemented yet");
 			} else if (request.getFrom().startsWith("C")) {
 				assignAeiC = false;
-			} else {
+			} else if(!request.getFrom().equals("")){
 				// Check access control policy of the originator
 				checkACP(acpsToCheck, request.getFrom(), Operation.CREATE);
 			}
-		} 
+		}
 
 		// Check if content is present
 		if (request.getContent() == null){
@@ -183,7 +181,7 @@
 		}
 		// nodeLink					NP
 		if (ae.getNodeLink() != null){
-			throw new NotPermittedAttrException("NodeLink is Not Permitted");
+			aeEntity.setNodeLink(ae.getNodeLink());
 		}
 
 		// app-ID					M
@@ -208,60 +206,62 @@
 			aeEntity.setAeid(request.getFrom());
 		}
 		// Set other parameters
-		aeEntity.setResourceID("/" + Constants.CSE_ID + "/" + ShortName.AE + Constants.PREFIX_SEPERATOR + aeEntity.getAeid());
+		aeEntity.setResourceID("/" + Constants.CSE_ID + "/" + aeEntity.getAeid());
 		if (dbs.getDAOFactory().getAeDAO().find(transaction, aeEntity.getResourceID()) != null) {
-			transaction.close();
-			response.setResponseStatusCode(ResponseStatusCode.CONFLICT);
-			response.setErrorMessage("Already registered");
-			return response;
+			throw new ConflictException("Already registered");
 		}
 
 		// accessControlPolicyIDs	O
 		if (!ae.getAccessControlPolicyIDs().isEmpty()){
 			aeEntity.setAccessControlPolicies(
 					ControllerUtil.buildAcpEntityList(ae.getAccessControlPolicyIDs(), transaction));
-		} else {
-			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.AE + 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(aeEntity.getAeid()));
-			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);
-			// adding new acp to the acp list
-			aeEntity.getAccessControlPolicies().add(acpDB);
-			// direct link to the generated acp
-			aeEntity.setGeneratedAcp(acpDB);
 		}
 
+		// FIXME [0001] Creation of AE with an acpi provided
+		//		} else {
+		// Create the acp corresponding to the AE_ID 
+		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.AE + 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(aeEntity.getAeid()));
+		ruleEntity.getAccessControlOriginators().add(new AccessControlOriginatorEntity(Constants.ADMIN_REQUESTING_ENTITY));
+		acpEntity.getPrivileges().add(ruleEntity);
+		acpEntity.setHierarchicalURI("/" + Constants.CSE_ID + "/" + Constants.CSE_NAME + "/" + acpEntity.getName());
+		// Add the acp in the UriMapper table
+		UriMapper.addNewUri(acpEntity.getHierarchicalURI(), acpEntity.getResourceID(), ResourceType.ACCESS_CONTROL_POLICY);
+		dbs.getDAOFactory().getAccessControlPolicyDAO().create(transaction, acpEntity);
+		// Retrieve the acp in the database to make the link with the CSEBase resource
+		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);
+		// adding new acp to the acp list
+		aeEntity.getAccessControlPolicies().add(acpDB);
+		// direct link to the generated acp
+		aeEntity.setGeneratedAcp(acpDB);
+		//		}
+
 		// appName					O
 		if (ae.getAppName() != null){
 			aeEntity.setAppName(ae.getAppName());
@@ -283,14 +283,14 @@
 			}
 			aeEntity.setName(ae.getName());
 		} else
-		if (request.getName() != null){
-			if (!Patterns.checkResourceName(request.getName())){
-				throw new BadRequestException("Name provided is incorrect. Must be:" + Patterns.ID_STRING);
+			if (request.getName() != null){
+				if (!Patterns.checkResourceName(request.getName())){
+					throw new BadRequestException("Name provided is incorrect. Must be:" + Patterns.ID_STRING);
+				}
+				aeEntity.setName(request.getName());
+			} else {
+				aeEntity.setName(ShortName.AE + "_" + generatedId);
 			}
-			aeEntity.setName(request.getName());
-		} else {
-			aeEntity.setName(ShortName.AE + "_" + generatedId);
-		}
 		aeEntity.setHierarchicalURI(parentEntity.getHierarchicalURI() + "/" + aeEntity.getName());
 		if (!UriMapper.addNewUri(aeEntity.getHierarchicalURI(), aeEntity.getResourceID(), ResourceType.AE)){
 			throw new ConflictException("Name already present in the parent collection.");
@@ -411,14 +411,31 @@
 		// parentID					NP
 		// creationTime				NP
 		// lastModifiedTime			NP
-		// labels					NP
+		UpdateUtil.checkNotPermittedParameters(ae);
 		// app-ID					NP
+		if(ae.getAppID() != null){
+			throw new BadRequestException("AppID is NP");
+		}
 		// ae-ID					NP
+		if(ae.getAEID() != null){
+			throw new BadRequestException("AE ID is NP");
+		}
 		// nodeLink					NP
+		if(ae.getNodeLink() != null){
+			throw new BadRequestException("NodeLink is NP");
+		}
 
 		AE modifiedAttributes = new AE();
+		// labels					O
+		if(!ae.getLabels().isEmpty()){
+			aeEntity.setLabelsEntitiesFromSring(ae.getLabels());
+			modifiedAttributes.getLabels().addAll(ae.getLabels());
+		}
 		// accessControlPolicyIDs	O
 		if(!ae.getAccessControlPolicyIDs().isEmpty()){
+			for(AccessControlPolicyEntity acpe : aeEntity.getAccessControlPolicies()){
+				checkSelfACP(acpe, request.getFrom(), Operation.UPDATE);
+			}
 			aeEntity.getAccessControlPolicies().clear();
 			aeEntity.setAccessControlPolicies(ControllerUtil.buildAcpEntityList(ae.getAccessControlPolicyIDs(), transaction));
 			modifiedAttributes.getAccessControlPolicyIDs().addAll(ae.getAccessControlPolicyIDs());
@@ -462,7 +479,7 @@
 			aeEntity.setRequestReachability(ae.getRequestReachability());
 			modifiedAttributes.setRequestReachability(ae.getRequestReachability());
 		}
-		
+
 		// Last Time Modified update
 		aeEntity.setLastModifiedTime(DateUtil.now());
 		modifiedAttributes.setLastModifiedTime(aeEntity.getLastModifiedTime());
@@ -496,7 +513,11 @@
 				Operation.DELETE);
 
 		UriMapper.deleteUri(aeEntity.getHierarchicalURI());
-
+		
+		if(aeEntity.getGeneratedAcp() != null){
+			UriMapper.deleteUri(aeEntity.getGeneratedAcp().getHierarchicalURI());
+		}
+		
 		Notifier.notifyDeletion(aeEntity.getSubscriptions(), aeEntity);
 
 		// Delete the resource
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/AccessControlPolicyController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/AccessControlPolicyController.java
index 7514fb0..8d4c252 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/AccessControlPolicyController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/AccessControlPolicyController.java
@@ -50,6 +50,7 @@
 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;
 import org.eclipse.om2m.persistence.service.DBService;
 import org.eclipse.om2m.persistence.service.DBTransaction;
@@ -311,14 +312,14 @@
 		
 		AccessControlPolicy modifiedAttributes = new AccessControlPolicy();
 
-		// NP attributes are ignored
+		// NP attributes 
 		// @resourceName 		NP 
 		// resourceType 		NP 
 		// resourceID 			NP 
 		// parentID 			NP
 		// creationTime 		NP 
 		// lastModifiedTime 	NP 
-
+		UpdateUtil.checkNotPermittedParameters(acp);
 		// expirationTime 		O
 		if(acp.getExpirationTime() != null){
 			acpEntity.setExpirationTime(acp.getExpirationTime());
@@ -388,6 +389,14 @@
 		if (acpEntity == null){
 			throw new ResourceNotFoundException("Resource not found");
 		}
+		
+		// Check this acp is not a generated acp for an AE to avoid inconsistency
+		for(AeEntity ae : acpEntity.getLinkedAes()){
+			if(ae.getGeneratedAcp().getResourceID().equals(acpEntity.getResourceID())){
+				throw new BadRequestException("Delete the linked ae(s) to avoid acp inconsistency.");
+			}
+		}
+		
 		// Check self access control policy
 		checkSelfACP(acpEntity, request.getFrom(), Operation.DELETE);
 
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/CSEBaseController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/CSEBaseController.java
index 913b0a7..2c69f73 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/CSEBaseController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/CSEBaseController.java
@@ -24,6 +24,7 @@
 import org.eclipse.om2m.commons.constants.ResponseStatusCode;
 import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
 import org.eclipse.om2m.commons.entities.CSEBaseEntity;
+import org.eclipse.om2m.commons.exceptions.OperationNotAllowed;
 import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
 import org.eclipse.om2m.commons.resource.CSEBase;
 import org.eclipse.om2m.commons.resource.RequestPrimitive;
@@ -39,9 +40,7 @@
 	// OPERATION_NOT_ALLOWED
 	@Override
 	public ResponsePrimitive doCreate(RequestPrimitive requestIndication) {
-		ResponsePrimitive response = new ResponsePrimitive(requestIndication);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Create of CSEBase is not allowed");
 	}
 
 	// Generic  retrieve operation
@@ -69,17 +68,13 @@
 	// OPERATION_NOT_ALLOWED
 	@Override
 	public ResponsePrimitive doUpdate(RequestPrimitive requestIndication) {
-		ResponsePrimitive response = new ResponsePrimitive(requestIndication);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Update of CSEBase is not allowed");
 	}
 
 	// OPERATION_NOT_ALLOWED
 	@Override
 	public ResponsePrimitive doDelete(RequestPrimitive requestIndication) {
-		ResponsePrimitive response = new ResponsePrimitive(requestIndication);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Delete of CSEBase is not allowed");
 	}
 
 }
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/ContainerController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/ContainerController.java
index d40df35..0d4b614 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/ContainerController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/ContainerController.java
@@ -19,6 +19,7 @@
  *******************************************************************************/
 package org.eclipse.om2m.core.controller;
 
+import java.math.BigInteger;
 import java.util.List;
 
 import org.eclipse.om2m.commons.constants.Constants;
@@ -49,6 +50,7 @@
 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;
 
 /**
@@ -232,19 +234,28 @@
 		// 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);
@@ -370,13 +381,22 @@
 		// 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();
-		// labels						O
 		// 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));
@@ -430,7 +450,13 @@
 			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);
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/ContentInstanceController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/ContentInstanceController.java
index 645c745..d30eef1 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/ContentInstanceController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/ContentInstanceController.java
@@ -36,6 +36,7 @@
 import org.eclipse.om2m.commons.exceptions.BadRequestException;
 import org.eclipse.om2m.commons.exceptions.ConflictException;
 import org.eclipse.om2m.commons.exceptions.NotImplementedException;
+import org.eclipse.om2m.commons.exceptions.OperationNotAllowed;
 import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
 import org.eclipse.om2m.commons.resource.ContentInstance;
 import org.eclipse.om2m.commons.resource.RequestPrimitive;
@@ -222,6 +223,10 @@
 				dbs.getDAOFactory().getContentInstanceDAO().delete(transaction, container.getChildContentInstances().get(0));
 			}
 			cinEntity.setParentContainer(container);
+			if(container.getStateTag() != null){
+				container.setStateTag(BigInteger.valueOf(container.getStateTag().intValue() + 1));
+				dbs.getDAOFactory().getContainerDAO().update(transaction, container);
+			}
 		}
 		// case parent is ContainerAnnc
 		if (parentEntity.getResourceType().intValue() == (ResourceType.CONTAINER_ANNC)) {
@@ -280,10 +285,7 @@
 	@Override
 	public ResponsePrimitive doUpdate(RequestPrimitive request) {
 		// this operation is not allowed for content instance resource
-		// create the response primitive
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Update on ContentInstance is not Allowed");
 	}
 
 	/**
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/Controller.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/Controller.java
index 3fc3e2c..7307475 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/Controller.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/Controller.java
@@ -26,7 +26,6 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.eclipse.om2m.commons.constants.AccessControl;
 import org.eclipse.om2m.commons.constants.MimeMediaType;
 import org.eclipse.om2m.commons.constants.Operation;
 import org.eclipse.om2m.commons.constants.ResultContent;
@@ -42,6 +41,7 @@
 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;
@@ -155,14 +155,11 @@
 	public void checkACP(List<AccessControlPolicyEntity> acpList, String originator, BigInteger operation)
 			throws AccessDeniedException{
 		if(originator == null){
-			throw new AccessDeniedException("No originator privded");
+			throw new AccessDeniedException();
 		}
 		if (acpList == null || acpList.isEmpty()) {
 			throw new ResourceNotFoundException("Current resource does not have any ACP attached");
 		}
-		if (!originatorExists(originator)) {
-			throw new AccessDeniedException("Provided originator not found");
-		}
 		// Check Resource accessRight existence not found
 		boolean originatorFound = false;
 		boolean operationAllowed = false;
@@ -171,7 +168,7 @@
 				originatorFound = false ; 
 				operationAllowed = false;
 				for (AccessControlOriginatorEntity originatorEntity : rule.getAccessControlOriginators()){
-					if (originatorEntity.getOriginatorID().equalsIgnoreCase(AccessControl.ORIGINATOR_ALL) || originatorEntity.getOriginatorID().equalsIgnoreCase(originator)){
+					if (originator.matches(originatorEntity.getOriginatorID().replace("*", ".*"))){
 						originatorFound = true;
 						break;
 					}
@@ -187,7 +184,7 @@
 						operationAllowed = true; 
 					} else if (operation.equals(Operation.DISCOVERY) && rule.isDiscovery()){
 						operationAllowed = true;
-					}else if(operation.equals(Operation.NOTIFY) && rule.isNotify()){
+					} else if (operation.equals(Operation.NOTIFY) && rule.isNotify()){
 						operationAllowed = true;
 					}
 				}
@@ -201,7 +198,7 @@
 		}
 
 		if (!originatorFound){
-			throw new AccessDeniedException("Given originator is not found");
+			throw new AccessDeniedException();
 		}
 		if (!operationAllowed){
 			throw new AccessDeniedException();
@@ -224,7 +221,7 @@
 			originatorFound = false ; 
 			operationAllowed = false ;
 			for (AccessControlOriginatorEntity originatorEntity : rule.getAccessControlOriginators()){
-				if (originatorEntity.getOriginatorID().equalsIgnoreCase(AccessControl.ORIGINATOR_ALL) || originatorEntity.getOriginatorID().equalsIgnoreCase(originator)){
+				if (originator.matches(originatorEntity.getOriginatorID().replace("*", ".*"))){
 					originatorFound = true;
 					break;
 				}
@@ -253,7 +250,7 @@
 			}
 		}
 		if (!originatorFound){
-			throw new AccessDeniedException("Given originator is not found");
+			throw new AccessDeniedException();
 		}
 		if (!operationAllowed){
 			throw new AccessDeniedException();
@@ -280,9 +277,15 @@
 		return generateId("", "");
 	}
 
-	@SuppressWarnings("unchecked")
 	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)){
@@ -292,9 +295,7 @@
 			}
 			if(request.getResultContent().equals(ResultContent.HIERARCHICAL_AND_ATTRIBUTES)
 					|| request.getResultContent().equals(ResultContent.ATTRIBUTES)){
-				Resource res = EntityMapperFactory.
-						getMapperFromResourceType(entity.getResourceType().intValue()).
-						mapEntityToResource(entity, ResultContent.ATTRIBUTES);
+				Resource res = mapper.mapEntityToResource(entity, ResultContent.ATTRIBUTES);
 				if(request.getReturnContentType().equals(MimeMediaType.OBJ)){
 					response.setContent(res);
 				} else {
@@ -304,13 +305,12 @@
 				}
 			}
 		} else {
-			response.setContent(EntityMapperFactory.
-					getMapperFromResourceType(entity.getResourceType().intValue()).
-					mapEntityToResource(entity, ResultContent.ATTRIBUTES));
+			response.setContent(mapper.mapEntityToResource(entity, ResultContent.ATTRIBUTES));
 			response.setLocation(entity.getResourceID());			
 		}
 	}
-
+	
+	
 	/**
 	 * Allows to know if the provided originator exists in the system
 	 * @param originator
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/DiscoveryController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/DiscoveryController.java
index 00c76f3..d878030 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/DiscoveryController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/DiscoveryController.java
@@ -31,23 +31,26 @@
 import org.eclipse.om2m.commons.constants.ResponseStatusCode;
 import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
 import org.eclipse.om2m.commons.entities.AeEntity;
+import org.eclipse.om2m.commons.entities.AreaNwkDeviceInfoEntity;
+import org.eclipse.om2m.commons.entities.AreaNwkInfoEntity;
 import org.eclipse.om2m.commons.entities.CSEBaseEntity;
 import org.eclipse.om2m.commons.entities.ContainerEntity;
 import org.eclipse.om2m.commons.entities.ContentInstanceEntity;
 import org.eclipse.om2m.commons.entities.GroupEntity;
 import org.eclipse.om2m.commons.entities.LabelEntity;
+import org.eclipse.om2m.commons.entities.NodeEntity;
 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.entities.UriMapperEntity;
 import org.eclipse.om2m.commons.exceptions.BadRequestException;
 import org.eclipse.om2m.commons.exceptions.NotImplementedException;
+import org.eclipse.om2m.commons.exceptions.OperationNotAllowed;
 import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
-import org.eclipse.om2m.commons.resource.DiscoveryResult;
-import org.eclipse.om2m.commons.resource.DiscoveryResult.ResourceRef;
 import org.eclipse.om2m.commons.resource.FilterCriteria;
 import org.eclipse.om2m.commons.resource.RequestPrimitive;
 import org.eclipse.om2m.commons.resource.ResponsePrimitive;
+import org.eclipse.om2m.commons.resource.URIList;
 import org.eclipse.om2m.core.persistence.PersistenceService;
 import org.eclipse.om2m.core.router.Patterns;
 import org.eclipse.om2m.persistence.service.DAO;
@@ -62,9 +65,7 @@
 
 	@Override
 	public ResponsePrimitive doCreate(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Delete of Discovery is not allowed");
 	}
 
 	@Override
@@ -157,43 +158,36 @@
 			childUris = dbs.getDBUtilManager().getComplexFindUtil().
 					getChildUrisDis(request.getTargetId(), filter);
 		}
-
-		// Create the result object that will be serialized
-		DiscoveryResult result = new DiscoveryResult();
-		for (UriMapperEntity uriEntity : childUris){
-			if(filter.getLimit() != null && result.getReferences().size() == filter.getLimit().intValue()){
-				System.out.println("Limit reached");
+		
+		URIList uriList = new URIList();
+		for(UriMapperEntity uriEntity : childUris){
+			if(filter.getLimit() != null && uriList.getListOfUri().size() == filter.getLimit().intValue()){
 				break;
 			}
-			ResourceRef ref = new ResourceRef();
-			ref.setResourceType(uriEntity.getResourceType());
 			if(request.getDiscoveryResultType().equals(DiscoveryResultType.HIERARCHICAL)){
-				ref.setUri(uriEntity.getHierarchicalUri());
+				if(!uriList.getListOfUri().contains(uriEntity.getHierarchicalUri())){
+					uriList.getListOfUri().add(uriEntity.getHierarchicalUri());
+				}
 			} else {
-				ref.setUri(uriEntity.getNonHierarchicalUri());
-			}
-			if(!result.getReferences().contains(ref)){
-				result.getReferences().add(ref);
+				if(!uriList.getListOfUri().contains(uriEntity.getNonHierarchicalUri())){
+					uriList.getListOfUri().add(uriEntity.getNonHierarchicalUri());
+				}
 			}
 		}
 
-		response.setContent(result);
+		response.setContent(uriList);
 		response.setResponseStatusCode(ResponseStatusCode.OK);
 		return response;
 	}
 
 	@Override
 	public ResponsePrimitive doUpdate(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Update of Discovery is not allowed");
 	}
 
 	@Override
 	public ResponsePrimitive doDelete(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Delete of Discovery is not allowed");
 	}
 
 	private List<AccessControlPolicyEntity> getAcpsFromEntity(
@@ -216,6 +210,16 @@
 			return ((CSEBaseEntity) resourceEntity).getAccessControlPolicies();
 		case ResourceType.SUBSCRIPTION:
 			return ((SubscriptionEntity) resourceEntity).getAcpList();
+		case ResourceType.NODE:
+			return ((NodeEntity) resourceEntity).getAccessControlPolicies();
+		case ResourceType.MGMT_OBJ:
+			if (resourceEntity instanceof AreaNwkInfoEntity) {
+				return ((AreaNwkInfoEntity) resourceEntity).getAcps();
+			}
+			if (resourceEntity instanceof AreaNwkDeviceInfoEntity) {
+				return ((AreaNwkDeviceInfoEntity) resourceEntity).getAcps();
+			}
+			return null;
 		default:
 			// TODO On implementing resource, add the reference here
 			return null;
@@ -245,6 +249,14 @@
 			case(ResourceType.CSE_BASE):
 				result.addAll(labelEntity.getLinkedCsb());
 			break;
+			case(ResourceType.NODE): {
+				result.addAll(labelEntity.getLinkedNodes());
+			}
+			break;
+			case(ResourceType.MGMT_OBJ): {
+				result.addAll(labelEntity.getLinkedAni());
+				result.addAll(labelEntity.getLinkedAndi());
+			}
 			default:
 				break;
 			}
@@ -255,6 +267,9 @@
 			result.addAll(labelEntity.getLinkedGroup());
 			result.addAll(labelEntity.getLinkedCsr());
 			result.addAll(labelEntity.getLinkedCsb());
+			result.addAll(labelEntity.getLinkedNodes());
+			result.addAll(labelEntity.getLinkedAni());
+			result.addAll(labelEntity.getLinkedAndi());
 		}
 		return result;
 	}
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/FanOutPointController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/FanOutPointController.java
index 76b9945..1fc142a 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/FanOutPointController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/FanOutPointController.java
@@ -21,6 +21,9 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
 import org.eclipse.om2m.commons.constants.MimeMediaType;
 import org.eclipse.om2m.commons.constants.ResponseStatusCode;
@@ -31,12 +34,23 @@
 import org.eclipse.om2m.commons.resource.RequestPrimitive;
 import org.eclipse.om2m.commons.resource.ResponsePrimitive;
 import org.eclipse.om2m.core.router.Router;
+import org.eclipse.om2m.core.thread.CoreExecutor;
 
 /**
  * Controller for fan out point handling (virtual resource)
  *
  */
 public class FanOutPointController extends Controller {
+	
+	private String foptSuffix;
+	
+	public FanOutPointController(){
+		super();
+	}
+	
+	public FanOutPointController(String foptSuffix){
+		this.foptSuffix = foptSuffix;
+	}
 
 	/**
 	 * Fan out the request verifying access rights etc
@@ -46,9 +60,10 @@
 	protected ResponsePrimitive fanOutRequest(RequestPrimitive request) {
 		String targetGroup = request.getTargetId();
 		AggregatedResponse aggResp = new AggregatedResponse();
-		ArrayList<RequestPrimitive> requests = new ArrayList<>();
+//		ArrayList<RequestPrimitive> requests = new ArrayList<>();
 		ResponsePrimitive resp = new ResponsePrimitive(request);
-
+		List<Future<ResponsePrimitive>> listOfResponse = new ArrayList<Future<ResponsePrimitive>>();
+		
 		// retrieve the parent group
 		GroupEntity group = dbs.getDAOFactory().getGroupDAO().find(transaction, targetGroup);
 		// check authorization of the originator 
@@ -57,29 +72,34 @@
 		
 		// TODO validate member types if not retrieve
 
-		ArrayList<FanOutSender> threads = new ArrayList<>();
+//		ArrayList<FanOutSender> threads = new ArrayList<>();
 		// fanout request to each member
 		for (String to : group.getMemberIDs()){
 			RequestPrimitive fanRequest = request.cloneParameters();
-			fanRequest.setTo(to);
-			fanRequest.setTargetId(to);
+			// if a suffix is provided add it to the request uri
+			LOGGER.info("Suffix in FanOutController " + this.foptSuffix);
+			if(this.foptSuffix != null){
+				fanRequest.setTo(to + foptSuffix);				
+			} else {
+				fanRequest.setTo(to);
+			}
+			LOGGER.info(fanRequest.getTo());
 			fanRequest.setReturnContentType(MimeMediaType.OBJ);
-			requests.add(fanRequest);
-			FanOutSender t = new FanOutSender(fanRequest);
-			threads.add(t);
-			t.start();
+			listOfResponse.add(CoreExecutor.submit(new FanOutWorker(fanRequest)));
 		}
 
-		// aggregate responses
-		for (FanOutSender t : threads) {
+		for(Future<ResponsePrimitive> response : listOfResponse){
 			try {
-				t.join();
-				aggResp.getResponsePrimitive().add(t.getResp());
-			} catch (InterruptedException e) {
-				LOGGER.debug("Fan out thread interrupted", e);
+				aggResp.getResponsePrimitive().add(response.get());
+			} catch (InterruptedException | ExecutionException e) {
+				LOGGER.error("FanOutCallable exception", e);
+				ResponsePrimitive responsePrimitive = new ResponsePrimitive();
+				PrimitiveContent content = new PrimitiveContent();
+				content.getAny().add(e.getMessage());
+				responsePrimitive.setContent(content);
+				responsePrimitive.setResponseStatusCode(ResponseStatusCode.INTERNAL_SERVER_ERROR);
 			}
 		}
-
 		// sub group creation?
 
 		resp.setResponseStatusCode(ResponseStatusCode.OK);
@@ -110,64 +130,38 @@
 		// fan out the request
 		return fanOutRequest(request);
 	}
-
-
+	
 	/**
-	 * Thread to fan out request
+	 * This inner class defines the Callable that will return the 
+	 * response of a request for the FanOutPoint broadcast.
 	 *
 	 */
-	class FanOutSender extends Thread {
-		/** Request to fan out */
-		private RequestPrimitive reqToFanOut;
-		/** Response primitive returned by the router */
-		private ResponsePrimitive resp ;
+	private static class FanOutWorker implements Callable<ResponsePrimitive>{
+		
+		/** The request that will be fan out to the router. */
+		private RequestPrimitive request;
+		
 		/**
-		 * Constructor
-		 * @param req to fan out
+		 * Main constructor with the request to be fan out.
+		 * @param request request to fan out
 		 */
-		public FanOutSender(RequestPrimitive req) {
-			this.reqToFanOut = req;
+		public FanOutWorker(RequestPrimitive request){
+			this.request = request;
 		}
-
+		
 		/**
-		 * Send the request
+		 * Implementation of the call() method from Callable<T>. 
+		 * It sends the request to the router and retrieve the result
+		 * that will be send to the caller of the class.
 		 */
 		@Override
-		public void run() {
-			resp = new Router().doRequest(reqToFanOut);
+		public ResponsePrimitive call() throws Exception {
+			ResponsePrimitive resp = new Router().doRequest(request);
 			resp.setPrimitiveContent(new PrimitiveContent());
 			resp.getPritimitiveContent().getAny().add(resp.getContent());
-		}
-
-		/**
-		 * @return the reqToFanOut
-		 */
-		public RequestPrimitive getReqToFanOut() {
-			return reqToFanOut;
-		}
-
-		/**
-		 * @param reqToFanOut the reqToFanOut to set
-		 */
-		public void setReqToFanOut(RequestPrimitive reqToFanOut) {
-			this.reqToFanOut = reqToFanOut;
-		}
-
-		/**
-		 * @return the resp
-		 */
-		public ResponsePrimitive getResp() {
 			return resp;
 		}
-
-		/**
-		 * @param resp the resp to set
-		 */
-		public void setResp(ResponsePrimitive resp) {
-			this.resp = resp;
-		}
-
-
+		
 	}
 
 }
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/GroupController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/GroupController.java
index e2c85d1..d20ec6c 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/GroupController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/GroupController.java
@@ -23,6 +23,7 @@
 
 import org.eclipse.om2m.commons.constants.ConsistencyStrategy;
 import org.eclipse.om2m.commons.constants.Constants;
+import org.eclipse.om2m.commons.constants.MemberType;
 import org.eclipse.om2m.commons.constants.MimeMediaType;
 import org.eclipse.om2m.commons.constants.Operation;
 import org.eclipse.om2m.commons.constants.ResourceStatus;
@@ -53,6 +54,7 @@
 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.core.util.GroupUtil;
 import org.eclipse.om2m.persistence.service.DAO;
 import org.eclipse.om2m.persistence.service.DBService;
@@ -194,11 +196,12 @@
 		}
 		groupEntity.setMaxNrOfMembers(group.getMaxNrOfMembers());
 
-		// memberType				M
+		// memberType				O
 		if(group.getMemberType() == null){
-			throw new BadRequestException("MemberType is Mandatory");
+			groupEntity.setMemberType(MemberType.MIXED);
+		} else {
+			groupEntity.setMemberType(group.getMemberType());			
 		}
-		groupEntity.setMemberType(group.getMemberType());
 		// memberID					M
 		if (group.getMemberIDs().isEmpty()){
 			throw new BadRequestException("MemberIDs is Mandatory");
@@ -381,10 +384,23 @@
 		// accessControlPolicyIDs	NP
 		// creationTime				NP
 		// lastModifiedTime			NP
+		UpdateUtil.checkNotPermittedParameters(group);
 		// creator					NP
+		if(group.getCreator() != null){
+			throw new BadRequestException("Creator is NP");
+		}
 		// currentNrOdMembers		NP
+		if(group.getCurrentNrOfMembers() != null){
+			throw new BadRequestException("CurrentNrOfMembers is NP");
+		}
 		// memberTypeValidated		NP
+		if(group.getMemberTypeValidated() != null){
+			throw new BadRequestException("MemberTypeValidated is NP");
+		}
 		// consistencyStrategy		NP
+		if(group.getConsistencyStrategy() != null){
+			throw new BadRequestException("ConsistencyStrategy is NP");
+		}
 
 		Group modifiedAttributes = new Group();
 		
@@ -430,6 +446,9 @@
 		}
 		// membersACPIDs			O
 		if(!group.getMembersAccessControlPolicyIDs().isEmpty()){
+			for(AccessControlPolicyEntity acpe : groupEntity.getAccessControlPolicies()){
+				checkSelfACP(acpe, request.getFrom(), Operation.UPDATE);
+			}
 			groupEntity.getMemberAcpIds().clear();
 			groupEntity.getMemberAcpIds().addAll(group.getMembersAccessControlPolicyIDs());
 			modifiedAttributes.getMembersAccessControlPolicyIDs().addAll(group.getMembersAccessControlPolicyIDs());
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/LatestOldestController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/LatestOldestController.java
index 20a7f7b..2aa5012 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/LatestOldestController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/LatestOldestController.java
@@ -25,6 +25,7 @@
 import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
 import org.eclipse.om2m.commons.entities.ContainerEntity;
 import org.eclipse.om2m.commons.entities.ContentInstanceEntity;
+import org.eclipse.om2m.commons.exceptions.OperationNotAllowed;
 import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
 import org.eclipse.om2m.commons.resource.ContentInstance;
 import org.eclipse.om2m.commons.resource.RequestPrimitive;
@@ -52,9 +53,7 @@
 
 	@Override
 	public ResponsePrimitive doCreate(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Create on " + policy.toString() +" is not allowed");
 	}
 
 	@Override
@@ -98,9 +97,7 @@
 
 	@Override
 	public ResponsePrimitive doUpdate(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Update on " + policy + " is not allowed");
 	}
 
 	@Override
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/NodeController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/NodeController.java
index 04c1003..8b21332 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/NodeController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/NodeController.java
@@ -47,6 +47,7 @@
 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;
 
 
@@ -271,14 +272,23 @@
 		// creationTime					NP
 		// creator						NP
 		// lastModifiedTime				NP
-		// currentNrOfInstances			NP
-		// currentByteSize				NP
-		// labels						NP
+		UpdateUtil.checkNotPermittedParameters(node);
+		// hostedCseLink				NP
+		if(node.getHostedCSELink() != null){
+			throw new BadRequestException("HostedCSELink is NP");
+		}
 
 		Node modifiedAttributes = new Node();
-		
+		// labels						O
+		if(!node.getLabels().isEmpty()){
+			nodeEntity.setLabelsEntitiesFromSring(node.getLabels());
+			modifiedAttributes.getLabels().addAll(node.getLabels());
+		}
 		// accessControlPolicyIDs		O
 		if(!node.getAccessControlPolicyIDs().isEmpty()){
+			for(AccessControlPolicyEntity acpe : nodeEntity.getAccessControlPolicies()){
+				checkSelfACP(acpe, request.getFrom(), Operation.UPDATE);
+			}
 			nodeEntity.getAccessControlPolicies().clear();
 			nodeEntity.setAccessControlPolicies(ControllerUtil.buildAcpEntityList(node.getAccessControlPolicyIDs(), transaction));
 			modifiedAttributes.getAccessControlPolicyIDs().addAll(node.getAccessControlPolicyIDs());
@@ -307,10 +317,6 @@
 			nodeEntity.setNodeID(node.getNodeID());
 			modifiedAttributes.setNodeID(node.getNodeID());
 		}
-		// hostedCSELink			NP
-		if (node.getHostedCSELink() != null) {
-			response.setErrorMessage("WARNING: update of hosted CSE link is not permitted and has not been updated");
-		}
 		
 		nodeEntity.setLastModifiedTime(DateUtil.now());
 		modifiedAttributes.setLastModifiedTime(nodeEntity.getLastModifiedTime());
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/PollingChannelController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/PollingChannelController.java
index ea53daf..f90ec52 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/PollingChannelController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/PollingChannelController.java
@@ -34,7 +34,6 @@
 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.ResourceNotFoundException;
@@ -48,6 +47,7 @@
 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;
 
 /**
@@ -99,10 +99,8 @@
 			return response;
 		}
 		
-		if(!request.getFrom().equals(originatorToCheck)){
-			throw new AccessDeniedException("Only the creator of the parent resource can create a polling channel.");
-		}
-
+		checkACP(acpsToCheck, request.getFrom(), Operation.CREATE);
+		
 		// Check if content is present
 		if (request.getContent() == null){
 			throw new BadRequestException("A content is requiered for PollingChannel creation");
@@ -250,8 +248,9 @@
 			throw new BadRequestException("Error in provided content");
 		}
 		
-		PollingChannel modifiedAttributes = new PollingChannel();
+		UpdateUtil.checkNotPermittedParameters(pollingChannel);
 		
+		PollingChannel modifiedAttributes = new PollingChannel();
 		// expirationTime O
 		if(pollingChannel.getExpirationTime() != null){
 			pollingChannelEntity.setExpirationTime(pollingChannel.getExpirationTime());
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/PollingChannelUriController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/PollingChannelUriController.java
index 6b24930..c94c98f 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/PollingChannelUriController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/PollingChannelUriController.java
@@ -19,42 +19,35 @@
  *******************************************************************************/
 package org.eclipse.om2m.core.controller;
 
-import org.eclipse.om2m.commons.constants.ResponseStatusCode;
+import org.eclipse.om2m.commons.exceptions.NotImplementedException;
+import org.eclipse.om2m.commons.exceptions.OperationNotAllowed;
 import org.eclipse.om2m.commons.resource.RequestPrimitive;
 import org.eclipse.om2m.commons.resource.ResponsePrimitive;
 
 /**
- * Controller for polling channel uri
+ * Controller for polling channel URI
  *
  */
 public class PollingChannelUriController extends Controller {
 
 	@Override
 	public ResponsePrimitive doCreate(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Create on PollingChannelUri is not allowed");
 	}
 
 	@Override
 	public ResponsePrimitive doRetrieve(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.NOT_IMPLEMENTED);
-		return response;
+		throw new NotImplementedException("Retrieve operation on PollingChannelURI is not implemented");
 	}
 
 	@Override
 	public ResponsePrimitive doUpdate(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Update on PollingChannelUri is not allowed");
 	}
 
 	@Override
 	public ResponsePrimitive doDelete(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Delete on PollingChannelUri is not allowed");
 	}
 
 }
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/RemoteCSEController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/RemoteCSEController.java
index 1781ac7..e26a89e 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/RemoteCSEController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/RemoteCSEController.java
@@ -51,6 +51,7 @@
 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;
 import org.eclipse.om2m.persistence.service.DBService;
 import org.eclipse.om2m.persistence.service.DBTransaction;
@@ -428,16 +429,36 @@
 		// parentID					NP
 		// creationTime				NP
 		// lastModifiedTime			NP
-		// labels					NP
+		UpdateUtil.checkNotPermittedParameters(csr);
 		// cseType					NP
+		if(csr.getCseType() != null){
+			throw new BadRequestException("CseType is NP");
+		}
 		// CseBase					NP
+		if(csr.getCSEBase() != null){
+			throw new BadRequestException("CseBase is NP");
+		}
 		// CSE-ID					NP
+		if(csr.getCSEID() != null){
+			throw new BadRequestException("CseID is NP");
+		}
 		// nodeLink					NP
+		if(csr.getNodeLink() != null){
+			throw new BadRequestException("NodeLink is NP");
+		}
 
 		RemoteCSE modifiedAttributes = new RemoteCSE();
-
+		// labels					O
+		if(!csr.getLabels().isEmpty()){
+			csrEntity.setLabelsEntitiesFromSring(csr.getLabels());
+			modifiedAttributes.getLabels().addAll(csr.getLabels());
+		}
+		
 		// accessControlPolicyIDs		O
 		if (!csr.getAccessControlPolicyIDs().isEmpty()){		
+			for(AccessControlPolicyEntity acpe : csrEntity.getAccessControlPolicies()){
+				checkSelfACP(acpe, request.getFrom(), Operation.UPDATE);
+			}
 			csrEntity.setAccessControlPolicies(
 					ControllerUtil.buildAcpEntityList(csr.getAccessControlPolicyIDs(), transaction));
 			modifiedAttributes.getAccessControlPolicyIDs().addAll(csr.getAccessControlPolicyIDs());
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/RequestController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/RequestController.java
index 7e4f6ce..bb77183 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/RequestController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/RequestController.java
@@ -23,6 +23,7 @@
 import org.eclipse.om2m.commons.constants.ResponseStatusCode;
 import org.eclipse.om2m.commons.entities.RequestEntity;
 import org.eclipse.om2m.commons.exceptions.AccessDeniedException;
+import org.eclipse.om2m.commons.exceptions.OperationNotAllowed;
 import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
 import org.eclipse.om2m.commons.resource.Request;
 import org.eclipse.om2m.commons.resource.RequestPrimitive;
@@ -34,9 +35,7 @@
 
 	@Override
 	public ResponsePrimitive doCreate(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Create on Request is not allowed");
 	}
 
 	@Override
@@ -64,9 +63,7 @@
 
 	@Override
 	public ResponsePrimitive doUpdate(RequestPrimitive request) {
-		ResponsePrimitive response = new ResponsePrimitive(request);
-		response.setResponseStatusCode(ResponseStatusCode.OPERATION_NOT_ALLOWED);
-		return response;
+		throw new OperationNotAllowed("Update on Request is not allowed");
 	}
 
 	@Override
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/SubscriptionController.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/SubscriptionController.java
index a2a2962..50173a1 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/SubscriptionController.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/controller/SubscriptionController.java
@@ -52,6 +52,7 @@
 import org.eclipse.om2m.core.urimapper.UriMapper;
 import org.eclipse.om2m.core.util.ControllerUtil;
 import org.eclipse.om2m.core.util.ControllerUtil.CreateUtil;
+import org.eclipse.om2m.core.util.ControllerUtil.UpdateUtil;
 import org.eclipse.om2m.persistence.service.DAO;
 import org.eclipse.om2m.persistence.service.DBService;
 import org.eclipse.om2m.persistence.service.DBTransaction;
@@ -120,7 +121,7 @@
 			acpsToCheck = csr.getAccessControlPolicies();
 		}
 
-		if(acpsToCheck.isEmpty()){
+		if(acpsToCheck == null){
 			throw new NotImplementedException("Subscription is not yet supported on this resource");
 		}
 
@@ -358,22 +359,37 @@
 		// parentID NP
 		// creationTime NP
 		// lastTimeModified NP
+		UpdateUtil.checkNotPermittedParameters(subscription);
 		// preSubscriptionNotify NP
+		if(subscription.getPreSubscriptionNotify() != null){
+			throw new BadRequestException("PreSubscriptionNotify is NP");
+		}
 		// subscriberURI NP
+		if(subscription.getSubscriberURI() != null){
+			throw new BadRequestException("SubscripberURI is NP");
+		}
+		
+		Subscription modifiedAttributes = new Subscription();
 
 		// ACPIDs O
 		if(!subscription.getAccessControlPolicyIDs().isEmpty()){
+			for(AccessControlPolicyEntity acpe : subscriptionEntity.getAcpList()){
+				checkSelfACP(acpe, request.getFrom(), Operation.UPDATE);
+			}
 			subscriptionEntity.getAcpList().clear();
 			subscriptionEntity.setAcpList(ControllerUtil.buildAcpEntityList(subscription.getAccessControlPolicyIDs(), transaction));
+			modifiedAttributes.getAccessControlPolicyIDs().addAll(subscription.getAccessControlPolicyIDs());
 		}
 		// expirationTime O
 		if(subscription.getExpirationTime() != null){
 			subscriptionEntity.setExpirationTime(subscription.getExpirationTime());
+			modifiedAttributes.setExpirationTime(subscription.getExpirationTime());
 		}
 		// labels O
 		if(!subscription.getLabels().isEmpty()){
 			subscriptionEntity.getLabelsEntities().clear();
 			subscriptionEntity.setLabelsEntitiesFromSring(subscription.getLabels());
+			modifiedAttributes.getLabels().addAll(subscription.getLabels());
 		}
 		// eventNotificationCriteria O
 		if(subscription.getEventNotificationCriteria() != null){
@@ -382,19 +398,23 @@
 		// expirationCounter O
 		if(subscription.getExpirationCounter() != null){
 			subscriptionEntity.setExpirationCounter(subscription.getExpirationCounter());
+			modifiedAttributes.setExpirationCounter(subscription.getExpirationCounter());
 		}
 		// notificationUri O
 		if(!subscription.getNotificationURI().isEmpty()){
 			subscriptionEntity.getNotificationURI().clear();
 			subscriptionEntity.getNotificationURI().addAll(subscription.getNotificationURI());
+			modifiedAttributes.getNotificationURI().addAll(subscription.getNotificationURI());
 		}
 		// groupID O
 		if(subscription.getGroupID() != null){
 			subscriptionEntity.setGroupID(subscription.getGroupID());
+			modifiedAttributes.setGroupID(subscription.getGroupID());
 		}
 		// notificationForwardingUri O
 		if(subscription.getNotificationForwardingURI() != null){
 			subscriptionEntity.setNotificationForwardingURI(subscription.getNotificationForwardingURI());
+			modifiedAttributes.setNotificationForwardingURI(subscription.getNotificationForwardingURI());
 		}
 		// batchNotify O
 		if(subscription.getBatchNotify() != null){
@@ -407,31 +427,39 @@
 		// pendingNotification O
 		if(subscription.getPendingNotification() != null){
 			subscriptionEntity.setPendingNotification(subscription.getPendingNotification());
+			modifiedAttributes.setPendingNotification(subscription.getPendingNotification());
 		}
 		// notificationStorePriority O 
 		if(subscription.getNotificationStoragePriority() != null){
 			subscriptionEntity.setNotificationStoragePriority(subscription.getNotificationStoragePriority());
+			modifiedAttributes.setNotificationStoragePriority(subscription.getNotificationStoragePriority());
 		}
 		// latestNotify O
 		if(subscription.isLatestNotify() != null){
 			subscriptionEntity.setLatestNotify(subscription.isLatestNotify());
+			modifiedAttributes.setLatestNotify(subscription.isLatestNotify());
 		}
 		// notificationContentType O
 		if(subscription.getNotificationContentType() != null){
 			subscriptionEntity.setNotificationContentType(subscription.getNotificationContentType());
+			modifiedAttributes.setNotificationContentType(subscription.getNotificationContentType());
 		}
 		// notificationEventCat O
 		if(subscription.getNotificationEventCat() != null){
 			subscriptionEntity.setNotificationEventCat(subscription.getNotificationEventCat());
+			modifiedAttributes.setNotificationEventCat(subscription.getNotificationEventCat());
 		}
 		// creator O
 		if(subscription.getCreator() != null){
 			subscriptionEntity.setCreator(subscription.getCreator());
+			modifiedAttributes.setCreator(subscription.getCreator());
 		}
 
 		// Update last time modified
 		subscriptionEntity.setLastModifiedTime(DateUtil.now());
-
+		modifiedAttributes.setLastModifiedTime(subscriptionEntity.getLastModifiedTime());
+		response.setContent(modifiedAttributes);
+		
 		dbs.getDAOFactory().getSubsciptionDAO().update(transaction, subscriptionEntity);
 		transaction.commit();
 
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/AreaNwkDeviceInfoMapper.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/AreaNwkDeviceInfoMapper.java
new file mode 100644
index 0000000..3f07125
--- /dev/null
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/AreaNwkDeviceInfoMapper.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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.entitymapper;
+
+import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
+import org.eclipse.om2m.commons.entities.AreaNwkDeviceInfoEntity;
+import org.eclipse.om2m.commons.resource.AreaNwkDeviceInfo;
+
+/**
+ * Mapper for AreaNwkDeviceInfo
+ *
+ */
+public class AreaNwkDeviceInfoMapper extends EntityMapper<AreaNwkDeviceInfoEntity, AreaNwkDeviceInfo> {
+
+	@Override
+	protected void mapAttributes(AreaNwkDeviceInfoEntity entity,
+			AreaNwkDeviceInfo resource) {
+		resource.setAreaNwkId(entity.getAreaNwkId());
+		resource.setDescription(entity.getDescription());
+		resource.setDevID(entity.getDevID());
+		resource.setExpirationTime(entity.getExpirationTime());
+		resource.setMgmtDefinition(entity.getMgmtDefinition());
+		resource.setName(entity.getName());
+		resource.setSleepDuration(entity.getSleepDuration());
+		resource.setSleepInterval(entity.getSleepInterval());
+		resource.setStatus(entity.getStatus());
+
+		for (AccessControlPolicyEntity acp : entity.getAcps()) {
+			resource.getAccessControlPolicyIDs().add(acp.getResourceID());
+		}
+		
+		if (!entity.getAnnouncedAttribute().isEmpty()) {
+			resource.getAnnouncedAttribute().addAll(entity.getAnnouncedAttribute());
+		}
+		if (!entity.getAnnounceTo().isEmpty()) {
+			resource.getAnnounceTo().addAll(entity.getAnnounceTo());
+		}
+		
+	}
+
+	@Override
+	protected void mapChildResourceRef(AreaNwkDeviceInfoEntity entity,
+			AreaNwkDeviceInfo resource) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	protected void mapChildResources(AreaNwkDeviceInfoEntity entity,
+			AreaNwkDeviceInfo resource) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	protected AreaNwkDeviceInfo createResource() {
+		return new AreaNwkDeviceInfo();
+	}
+
+
+
+}
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/AreaNwkInfoMapper.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/AreaNwkInfoMapper.java
new file mode 100644
index 0000000..bec4633
--- /dev/null
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/AreaNwkInfoMapper.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * 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.entitymapper;
+
+import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
+import org.eclipse.om2m.commons.entities.AreaNwkInfoEntity;
+import org.eclipse.om2m.commons.entities.LabelEntity;
+import org.eclipse.om2m.commons.resource.AreaNwkInfo;
+
+public class AreaNwkInfoMapper extends EntityMapper<AreaNwkInfoEntity, AreaNwkInfo> {
+
+	@Override
+	protected void mapAttributes(AreaNwkInfoEntity entity, AreaNwkInfo resource) {
+		resource.setAreaNwkType(entity.getAreaNwkType());
+		resource.setCreationTime(entity.getCreationTime());
+		resource.setDescription(entity.getDescription());
+		resource.setExpirationTime(entity.getExpirationTime());
+		resource.setLastModifiedTime(entity.getLastModifiedTime());
+		resource.setMgmtDefinition(entity.getMgmtDefinition());
+		resource.setName(entity.getName());
+		resource.setParentID(entity.getParentID());
+		resource.setResourceID(entity.getResourceID());
+		resource.setResourceType(entity.getResourceType());
+		if (!entity.getAnnouncedAttribute().isEmpty()) {
+			resource.getAnnouncedAttribute().addAll(entity.getAnnouncedAttribute());
+		}
+		if (!entity.getAnnounceTo().isEmpty()) {
+			resource.getAnnounceTo().addAll(entity.getAnnounceTo());
+		}
+		for (AccessControlPolicyEntity acp : entity.getAcps()) {
+			resource.getAccessControlPolicyIDs().add(acp.getResourceID());
+		}
+		for (LabelEntity lbl : entity.getLabelsEntities()) {
+			resource.getLabels().add(lbl.getLabel());
+		}
+		if (!entity.getListOfDevices().isEmpty()) {
+			resource.getListOfDevices().addAll(entity.getListOfDevices());
+		}
+	}
+
+	@Override
+	protected void mapChildResourceRef(AreaNwkInfoEntity entity,
+			AreaNwkInfo resource) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	protected void mapChildResources(AreaNwkInfoEntity entity,
+			AreaNwkInfo resource) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	protected AreaNwkInfo createResource() {
+		return new AreaNwkInfo();
+	}
+
+}
+
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/ContainerMapper.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/ContainerMapper.java
index 8ab93d6..0401feb 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/ContainerMapper.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/ContainerMapper.java
@@ -23,6 +23,7 @@
 
 import org.eclipse.om2m.commons.constants.ResourceType;
 import org.eclipse.om2m.commons.constants.ResultContent;
+import org.eclipse.om2m.commons.constants.ShortName;
 import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
 import org.eclipse.om2m.commons.entities.ContainerEntity;
 import org.eclipse.om2m.commons.entities.ContentInstanceEntity;
@@ -61,6 +62,8 @@
 		for (AccessControlPolicyEntity acp : entity.getAccessControlPolicies()) {
 			resource.getAccessControlPolicyIDs().add(acp.getResourceID());
 		}
+		resource.setOldest(entity.getHierarchicalURI() + "/" + ShortName.OLDEST);
+		resource.setLatest(entity.getHierarchicalURI() + "/" + ShortName.LATEST);
 	}
 
 	@Override
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/EntityMapper.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/EntityMapper.java
index 1cebf36..a202f77 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/EntityMapper.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/EntityMapper.java
@@ -27,7 +27,6 @@
 import org.eclipse.om2m.commons.entities.ResourceEntity;
 import org.eclipse.om2m.commons.resource.RequestPrimitive;
 import org.eclipse.om2m.commons.resource.Resource;
-import org.eclipse.om2m.commons.utils.UriUtil;
 
 /**
  * Generic entity mapper
@@ -47,7 +46,7 @@
 		resource.setLastModifiedTime(entity.getLastModifiedTime());
 		resource.setName(entity.getName());
 		resource.setParentID(entity.getParentID());
-		resource.setResourceID(UriUtil.toCseRelativeUri(entity.getResourceID()));
+		resource.setResourceID(entity.getResourceID());
 		resource.setResourceType(entity.getResourceType());
 		for (LabelEntity lbl : entity.getLabelsEntities()){
 			resource.getLabels().add(lbl.getLabel());
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/EntityMapperFactory.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/EntityMapperFactory.java
index 2f710aa..dc12cab 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/EntityMapperFactory.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/EntityMapperFactory.java
@@ -22,10 +22,13 @@
 import org.eclipse.om2m.commons.constants.ResourceType;
 import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
 import org.eclipse.om2m.commons.entities.AeEntity;
+import org.eclipse.om2m.commons.entities.AreaNwkDeviceInfoEntity;
+import org.eclipse.om2m.commons.entities.AreaNwkInfoEntity;
 import org.eclipse.om2m.commons.entities.CSEBaseEntity;
 import org.eclipse.om2m.commons.entities.ContainerEntity;
 import org.eclipse.om2m.commons.entities.ContentInstanceEntity;
 import org.eclipse.om2m.commons.entities.GroupEntity;
+import org.eclipse.om2m.commons.entities.MgmtObjEntity;
 import org.eclipse.om2m.commons.entities.NodeEntity;
 import org.eclipse.om2m.commons.entities.PollingChannelEntity;
 import org.eclipse.om2m.commons.entities.RemoteCSEEntity;
@@ -33,6 +36,8 @@
 import org.eclipse.om2m.commons.entities.SubscriptionEntity;
 import org.eclipse.om2m.commons.resource.AE;
 import org.eclipse.om2m.commons.resource.AccessControlPolicy;
+import org.eclipse.om2m.commons.resource.AreaNwkDeviceInfo;
+import org.eclipse.om2m.commons.resource.AreaNwkInfo;
 import org.eclipse.om2m.commons.resource.CSEBase;
 import org.eclipse.om2m.commons.resource.Container;
 import org.eclipse.om2m.commons.resource.ContentInstance;
@@ -95,6 +100,16 @@
 		return new RequestMapper();
 	}
 
+	/** Get the Area Nwk info mapper */
+	public static EntityMapper<AreaNwkInfoEntity, AreaNwkInfo> getAreaNwkInfoMapper(){
+		return new AreaNwkInfoMapper();
+	}
+
+	/** Get the Area Nwk device info mapper */
+	public static EntityMapper<AreaNwkDeviceInfoEntity, AreaNwkDeviceInfo> getAreaNwkDeviceInfoMapper(){
+		return new AreaNwkDeviceInfoMapper();
+	}
+	
 	/**
 	 * Get entity mapper from resource type
 	 * @param resourceType (integer)
@@ -126,9 +141,27 @@
 			return new PollingChannelMapper();
 		case ResourceType.REQUEST:
 			return new RequestMapper();
+		case ResourceType.MGMT_OBJ:
+			throw new IllegalArgumentException("Cannot get Mapper for MGMT OBJ");
 		default:
 			return null;
 		}
 	}
+	
+	/**
+	 * Get the entity mapper for specific mgmtObj entity
+	 * @param mgmtObj
+	 * @return entity mapper
+	 */
+	@SuppressWarnings("rawtypes")
+	public static EntityMapper getMapperForMgmtObj(MgmtObjEntity mgmtObj) {
+		if (mgmtObj instanceof AreaNwkInfoEntity) {
+			return new AreaNwkInfoMapper();
+		}
+		if (mgmtObj instanceof AreaNwkDeviceInfoEntity) {
+			return new AreaNwkDeviceInfoMapper();
+		}
+		return null;
+	}
 
 }
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/NodeMapper.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/NodeMapper.java
index 5c2811c..113b3a4 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/NodeMapper.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/entitymapper/NodeMapper.java
@@ -19,7 +19,15 @@
  *******************************************************************************/
 package org.eclipse.om2m.core.entitymapper;
 
+import org.eclipse.om2m.commons.constants.ResourceType;
+import org.eclipse.om2m.commons.constants.ResultContent;
+import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
+import org.eclipse.om2m.commons.entities.AreaNwkDeviceInfoEntity;
+import org.eclipse.om2m.commons.entities.AreaNwkInfoEntity;
 import org.eclipse.om2m.commons.entities.NodeEntity;
+import org.eclipse.om2m.commons.resource.AreaNwkDeviceInfo;
+import org.eclipse.om2m.commons.resource.AreaNwkInfo;
+import org.eclipse.om2m.commons.resource.ChildResourceRef;
 import org.eclipse.om2m.commons.resource.Node;
 
 /**
@@ -32,16 +40,52 @@
 	protected void mapAttributes(NodeEntity entity, Node resource) {
 		resource.setNodeID(entity.getNodeID());
 		resource.setHostedCSELink(entity.getHostedCSELink());
+		resource.setExpirationTime(entity.getExpirationTime());
+
+		if (!entity.getAnnouncedAttribute().isEmpty()) {
+			resource.getAnnouncedAttribute().addAll(entity.getAnnouncedAttribute());
+		}
+		if (!entity.getAnnounceTo().isEmpty()) {
+			resource.getAnnounceTo().addAll(entity.getAnnounceTo());
+		}
+
+		for (AccessControlPolicyEntity acp : entity.getAccessControlPolicies()) {
+			resource.getAccessControlPolicyIDs().add(acp.getResourceID());
+		}
 	}
 
 	@Override
 	protected void mapChildResourceRef(NodeEntity entity, Node resource) {
-		// TODO Auto-generated method stub	
+		// add child area nwk info entities
+		for (AreaNwkInfoEntity aniEntity : entity.getChildAreaNwkInfoEntities()) {
+			ChildResourceRef chref = new ChildResourceRef();
+			chref.setResourceName(aniEntity.getName());
+			chref.setType(ResourceType.MGMT_OBJ);
+			chref.setValue(aniEntity.getResourceID());
+			resource.getChildResource().add(chref);
+		}
+		// add child area nwk device info entities
+		for (AreaNwkDeviceInfoEntity andiEntity : entity.getChildAreaNwkDeviceInfoEntities()) {
+			ChildResourceRef chref = new ChildResourceRef();
+			chref.setResourceName(andiEntity.getName());
+			chref.setType(ResourceType.MGMT_OBJ);
+			chref.setValue(andiEntity.getResourceID());
+			resource.getChildResource().add(chref);
+		}
 	}
 
 	@Override
 	protected void mapChildResources(NodeEntity entity, Node resource) {
-		// TODO Auto-generated method stub
+		// add child area nwk info entities
+		for (AreaNwkInfoEntity aniEntity : entity.getChildAreaNwkInfoEntities()) {
+			AreaNwkInfo aniRes = new AreaNwkInfoMapper().mapEntityToResource(aniEntity, ResultContent.ATTRIBUTES);
+			resource.getMemoryOrBatteryOrAreaNwkInfo().add(aniRes);
+		}
+		// add child area nwk device info entities
+		for (AreaNwkDeviceInfoEntity andiEntity : entity.getChildAreaNwkDeviceInfoEntities()) {
+			AreaNwkDeviceInfo andiRes = new AreaNwkDeviceInfoMapper().mapEntityToResource(andiEntity, ResultContent.ATTRIBUTES);
+			resource.getMemoryOrBatteryOrAreaNwkInfo().add(andiRes);
+		}
 	}
 
 	@Override
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/nblocking/NonBlockingHandler.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/nblocking/NonBlockingHandler.java
index fbb9513..818ae60 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/nblocking/NonBlockingHandler.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/nblocking/NonBlockingHandler.java
@@ -71,18 +71,22 @@
 				if(request.getRequestContentType().equals(MimeMediaType.OBJ)){
 					requestEntity.setContent(DataMapperSelector.getDataMapperList().get(MimeMediaType.JSON).objToString(request.getContent()));
 					requestEntity.setRequestContentType(MimeMediaType.JSON);
-				} else if(!request.getRequestContentType().equals(MimeMediaType.JSON)){
-					Object resource = DataMapperSelector.getDataMapperList().
-							get(request.getReturnContentType()).stringToObj((String)request.getContent());
-					requestEntity.setContent(DataMapperSelector.getDataMapperList().get(MimeMediaType.JSON).objToString(resource));
-					requestEntity.setRequestContentType(request.getRequestContentType());
 				} else {
-					requestEntity.setContent((String) request.getContent());
-					requestEntity.setRequestContentType(request.getRequestContentType());
+					if(request.getContent() instanceof String && !((String)request.getContent()).isEmpty()){
+						if(!request.getRequestContentType().equals(MimeMediaType.JSON)){
+							Object resource = DataMapperSelector.getDataMapperList().
+									get(request.getReturnContentType()).stringToObj((String)request.getContent());
+							requestEntity.setContent(DataMapperSelector.getDataMapperList().get(MimeMediaType.JSON).objToString(resource));
+							requestEntity.setRequestContentType(request.getRequestContentType());
+						} else {
+							requestEntity.setContent((String) request.getContent());
+							requestEntity.setRequestContentType(request.getRequestContentType());
+						}						
+					}
 				}
 			}
 		} catch (Exception e){
-			throw new BadRequestException("Error in provided content");
+			throw new BadRequestException("Error in provided content", e);
 		}
 		requestEntity.setCreationTime(DateUtil.now());
 		
@@ -129,6 +133,7 @@
 		
 		Request requestResource = EntityMapperFactory.getRequestMapper().mapEntityToResource(requestEntity, ResultContent.ATTRIBUTES);
 		response.setContent(requestResource.getResourceID());
+		response.setContentType(MimeMediaType.TEXT_PLAIN);
 		
 		response.setResponseStatusCode(ResponseStatusCode.ACCEPTED);
 		response.setLocation(requestDb.getResourceID());
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/nblocking/NonBlockingWorker.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/nblocking/NonBlockingWorker.java
index 81c6db6..5473266 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/nblocking/NonBlockingWorker.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/nblocking/NonBlockingWorker.java
@@ -96,7 +96,13 @@
 			if(request.getReturnContentType().equals(MimeMediaType.OBJ)){
 				managedRequest.setOperationResultContent(DataMapperSelector.
 						getDataMapperList().get(MimeMediaType.JSON).objToString(response.getContent()));
-			} else {
+			} else if(request.getReturnContentType().equals(MimeMediaType.XML)){
+				Object objReseult = DataMapperSelector.getDataMapperList().
+						get(MimeMediaType.XML).stringToObj((String)response.getContent());
+				String jsonResult = DataMapperSelector.getDataMapperList().get(MimeMediaType.JSON).objToString(objReseult);
+				managedRequest.setOperationResultContent(jsonResult);
+			}
+			else {
 				managedRequest.setOperationResultContent((String) response.getContent());				
 			}
 		}
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/notifier/Notifier.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/notifier/Notifier.java
index 362de0b..3744af3 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/notifier/Notifier.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/notifier/Notifier.java
@@ -1,278 +1,276 @@
-/*******************************************************************************
- * 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.notifier;
-
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.eclipse.om2m.commons.constants.Constants;
-import org.eclipse.om2m.commons.constants.MimeMediaType;
-import org.eclipse.om2m.commons.constants.NotificationContentType;
-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.ResultContent;
-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.GroupEntity;
-import org.eclipse.om2m.commons.entities.RemoteCSEEntity;
-import org.eclipse.om2m.commons.entities.ResourceEntity;
-import org.eclipse.om2m.commons.entities.ScheduleEntity;
-import org.eclipse.om2m.commons.entities.SubscriptionEntity;
-import org.eclipse.om2m.commons.exceptions.Om2mException;
-import org.eclipse.om2m.commons.resource.Notification;
-import org.eclipse.om2m.commons.resource.Notification.NotificationEvent;
-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.comm.RestClient;
-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.core.router.Patterns;
-import org.eclipse.om2m.core.router.Router;
-import org.eclipse.om2m.core.urimapper.UriMapper;
-import org.eclipse.om2m.persistence.service.DAO;
-import org.eclipse.om2m.persistence.service.DBService;
-import org.eclipse.om2m.persistence.service.DBTransaction;
-
-/**
- * Notifies subscribers when a change occurs on a resource according to their subscriptions.
- */
-public class Notifier {
-	/** Logger */
-	private static Log LOGGER = LogFactory.getLog(Notifier.class);
-
-	private static final int NOTIFICATION_NTHREADS = Integer.parseInt(System.getProperty("org.eclipse.om2m.notification.nthreads", "20"));
-	private static final ExecutorService threadPool = Executors.newFixedThreadPool(NOTIFICATION_NTHREADS);
-
-	/**
-	 * Finds all resource subscribers and notifies them.
-	 * @param statusCode - Notification status code
-	 * @param resource - Notification resource
-	 */
-	public static void notify(List<SubscriptionEntity> listSubscription, ResourceEntity resource, int resourceStatus) {
-		if (listSubscription != null){
-			for(SubscriptionEntity sub : listSubscription){
-				NotificationWorker worker = new NotificationWorker(sub, resourceStatus, resource);
-				threadPool.execute(worker);
-			}
-		}
-	}
-
-	/**
-	 * Used in DELETE procedure when a resource is deleted. It notifies the subscribed resource
-	 * and the parent resource subscribed entities.
-	 * @param listSubs
-	 * @param resourceDeleted
-	 */
-	public static void notifyDeletion(List<SubscriptionEntity> listSubs, ResourceEntity resourceDeleted){
-		List<SubscriptionEntity> parentSubscriptions = getParentSubscriptions(resourceDeleted);
-		if(parentSubscriptions != null){
-			notify(parentSubscriptions, resourceDeleted, ResourceStatus.CHILD_DELETED);
-		}
-		if(listSubs != null){
-			notify(listSubs, resourceDeleted, ResourceStatus.DELETED);
-		}
-	}
-
-	public static void performVerificationRequest(RequestPrimitive request,
-			SubscriptionEntity subscriptionEntity) {
-		for(String uri : subscriptionEntity.getNotificationURI()){
-			if(!uri.equals(request.getFrom())){
-				Notification notification = new Notification();
-				notification.setCreator(subscriptionEntity.getCreator());
-				notification.setVerificationRequest(true);
-				notification.setSubscriptionReference(subscriptionEntity.getHierarchicalURI());
-				notification.setSubscriptionDeletion(false);
-				RequestPrimitive notifRequest = new RequestPrimitive();
-				notifRequest.setContent(DataMapperSelector.getDataMapperList().get(MimeMediaType.XML).objToString(notification));
-				notifRequest.setFrom("/" + Constants.CSE_ID);
-				notifRequest.setTo(uri);
-				notifRequest.setOperation(Operation.NOTIFY);
-				notifRequest.setRequestContentType(MimeMediaType.XML);
-				notifRequest.setReturnContentType(MimeMediaType.XML);
-				ResponsePrimitive resp = notify(notifRequest, uri);
-				if(resp.getResponseStatusCode().equals(ResponseStatusCode.TARGET_NOT_REACHABLE)){
-					throw new Om2mException("Error during the verification request", 
-							ResponseStatusCode.SUBSCRIPTION_VERIFICATION_INITIATION_FAILED);
-				}
-				if(resp.getResponseStatusCode().equals(ResponseStatusCode.SUBSCRIPTION_CREATOR_HAS_NO_PRIVILEGE)
-						|| resp.getResponseStatusCode().equals(ResponseStatusCode.SUBSCRIPTION_HOST_HAS_NO_PRIVILEGE)){
-					throw new Om2mException(resp.getResponseStatusCode());
-				}
-			}
-		}
-	}
-
-	public static ResponsePrimitive notify(RequestPrimitive request, String contact){
-		// Check whether the subscription contact is protocol-dependent or not.
-		LOGGER.info("Sending notify request to: " + contact);
-		if(contact.matches(".*://.*")){
-			// Contact = protocol-dependent -> direct notification using the rest client.
-			request.setTo(contact);
-			return RestClient.sendRequest(request);
-		}else{
-			request.setTargetId(contact);
-			LOGGER.info("Sending notify request...");
-			return new Router().doRequest(request);
-		}
-	}
-
-	/**
-	 * Used to retrieve the subscription list of the parent resource
-	 * @param resource
-	 * @return
-	 */
-	private static List<SubscriptionEntity> getParentSubscriptions(
-			ResourceEntity resourceDeleted) {
-		List<SubscriptionEntity> result;
-		// Get parent id
-		String[] ids = resourceDeleted.getHierarchicalURI().split("/");
-		String parentHierarchicalId = resourceDeleted.getHierarchicalURI().replace("/" + ids[ids.length - 1], "");
-		String parentId = UriMapper.getNonHierarchicalUri(parentHierarchicalId);
-		// get parent entity
-		DBService dbs = PersistenceService.getInstance().getDbService();
-
-		DAO<?> dao = Patterns.getDAO(parentId, dbs);
-		DBTransaction transaction = dbs.getDbTransaction();
-		transaction.open();
-		ResourceEntity parentEntity = (ResourceEntity) dao.find(transaction, parentId);
-		// get the sub list from parent
-		switch(parentEntity.getResourceType().intValue()){
-		case ResourceType.ACCESS_CONTROL_POLICY:
-			AccessControlPolicyEntity acp = (AccessControlPolicyEntity) parentEntity;
-			result = acp.getChildSubscriptions();
-			break;
-		case ResourceType.AE:
-			AeEntity ae = (AeEntity) parentEntity;
-			result = ae.getSubscriptions();
-			break;
-		case ResourceType.CONTAINER:
-			ContainerEntity cnt = (ContainerEntity) parentEntity;
-			result = cnt.getSubscriptions();
-			break;
-		case ResourceType.CSE_BASE:
-			CSEBaseEntity csb = (CSEBaseEntity) parentEntity;
-			result = csb.getSubscriptions();
-			break;
-		case ResourceType.GROUP:
-			GroupEntity group = (GroupEntity) parentEntity;
-			result = group.getSubscriptions();
-			break;
-		case ResourceType.REMOTE_CSE:
-			RemoteCSEEntity csr = (RemoteCSEEntity) parentEntity;
-			result = csr.getSubscriptions();
-			break;
-		case ResourceType.SCHEDULE:
-			ScheduleEntity schedule = (ScheduleEntity) parentEntity;
-			result = schedule.getSubscriptions();
-			break;
-		default:
-			result = new ArrayList<SubscriptionEntity>();
-		}
-		transaction.close();
-		return result;
-	}
-
-	/**
-	 * Worker that perform the notification task for a subscription
-	 *
-	 */
-	static class NotificationWorker extends Thread {
-		/** resource status of the notification */
-		private int resourceStatus;
-		/** the subscription to handle */
-		private SubscriptionEntity sub;
-		/** the resource to be sent */
-		private ResourceEntity resource;
-
-		public NotificationWorker(SubscriptionEntity sub, int resourceStatus, ResourceEntity resource) {
-			this.resourceStatus = resourceStatus;
-			this.sub = sub;
-			this.resource = resource;
-		}
-
-		@SuppressWarnings("unchecked")
-		@Override
-		public void run() {
-			final RequestPrimitive request = new RequestPrimitive();
-			Notification notification = new Notification();
-			NotificationEvent notifEvent = new NotificationEvent();
-			notification.setNotificationEvent(notifEvent);
-
-			// Set attributes of notification object
-			notifEvent.setResourceStatus(BigInteger.valueOf(resourceStatus));
-			notification.setCreator(sub.getCreator());
-
-			// Set request parameters
-			request.setOperation(Operation.NOTIFY);
-			request.setFrom("/" + Constants.CSE_ID);
-
-			if(resourceStatus == ResourceStatus.DELETED){
-				notification.setSubscriptionDeletion(true);
-			} else {
-				notification.setSubscriptionDeletion(false);
-			}
-
-			notification.setSubscriptionReference(sub.getHierarchicalURI());
-
-			// Get the representation of the content
-			if (sub.getNotificationContentType() != null){
-				if(sub.getNotificationContentType().equals(NotificationContentType.MODIFIED_ATTRIBUTES)){
-					Resource serializableResource = (Resource) EntityMapperFactory.
-							getMapperFromResourceType(resource.getResourceType().intValue()).
-							mapEntityToResource(resource, ResultContent.ATTRIBUTES);
-					notification.getNotificationEvent().setRepresentation(serializableResource);
-					request.setRequestContentType(MimeMediaType.XML);
-				} else if(sub.getNotificationContentType().equals(NotificationContentType.WHOLE_RESOURCE)){
-					Resource serializableResource = (Resource) EntityMapperFactory.
-							getMapperFromResourceType(resource.getResourceType().intValue()).
-							mapEntityToResource(resource, ResultContent.ATTRIBUTES);
-					notification.getNotificationEvent().setRepresentation(serializableResource);
-					request.setRequestContentType(MimeMediaType.XML);
-				}
-			}
-
-			// Set the content
-			request.setContent(DataMapperSelector.getDataMapperList().get(MimeMediaType.XML).objToString(notification));
-			// For each notification URI: send the notify request
-			for(final String uri : sub.getNotificationURI()){
-				ExecutorService senderThreadPool = Executors.newFixedThreadPool(5);
-				senderThreadPool.execute(new Thread(){
-					public void run() {
-						Notifier.notify(request, uri);
-					};
-				});
-				senderThreadPool.shutdown();
-			}
-		}
-	}
-
-}
+/*******************************************************************************

+ * 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.notifier;

+

+import java.math.BigInteger;

+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.Constants;

+import org.eclipse.om2m.commons.constants.MimeMediaType;

+import org.eclipse.om2m.commons.constants.NotificationContentType;

+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.ResultContent;

+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.GroupEntity;

+import org.eclipse.om2m.commons.entities.MgmtObjEntity;

+import org.eclipse.om2m.commons.entities.RemoteCSEEntity;

+import org.eclipse.om2m.commons.entities.ResourceEntity;

+import org.eclipse.om2m.commons.entities.ScheduleEntity;

+import org.eclipse.om2m.commons.entities.SubscriptionEntity;

+import org.eclipse.om2m.commons.exceptions.Om2mException;

+import org.eclipse.om2m.commons.resource.Notification;

+import org.eclipse.om2m.commons.resource.Notification.NotificationEvent;

+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.comm.RestClient;

+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.core.router.Patterns;

+import org.eclipse.om2m.core.router.Router;

+import org.eclipse.om2m.core.thread.CoreExecutor;

+import org.eclipse.om2m.core.urimapper.UriMapper;

+import org.eclipse.om2m.persistence.service.DAO;

+import org.eclipse.om2m.persistence.service.DBService;

+import org.eclipse.om2m.persistence.service.DBTransaction;

+

+/**

+ * Notifies subscribers when a change occurs on a resource according to their subscriptions.

+ */

+public class Notifier {

+	/** Logger */

+	private static Log LOGGER = LogFactory.getLog(Notifier.class);

+

+	/**

+	 * Finds all resource subscribers and notifies them.

+	 * @param statusCode - Notification status code

+	 * @param resource - Notification resource

+	 */

+	public static void notify(List<SubscriptionEntity> listSubscription, ResourceEntity resource, int resourceStatus) {

+		if (listSubscription != null){

+			for(SubscriptionEntity sub : listSubscription){

+				NotificationWorker worker = new NotificationWorker(sub, resourceStatus, resource);

+				CoreExecutor.postThread(worker);

+			}

+		}

+	}

+

+	/**

+	 * Used in DELETE procedure when a resource is deleted. It notifies the subscribed resource

+	 * and the parent resource subscribed entities. 

+	 * @param listSubs

+	 * @param resourceDeleted

+	 */

+	public static void notifyDeletion(List<SubscriptionEntity> listSubs, ResourceEntity resourceDeleted){

+		List<SubscriptionEntity> parentSubscriptions = getParentSubscriptions(resourceDeleted);

+		if(parentSubscriptions != null){

+			notify(parentSubscriptions, resourceDeleted, ResourceStatus.CHILD_DELETED);			

+		}

+		if(listSubs != null){

+			notify(listSubs, resourceDeleted, ResourceStatus.DELETED);			

+		}

+	}

+

+	public static void performVerificationRequest(RequestPrimitive request,

+			SubscriptionEntity subscriptionEntity) {

+		for(String uri : subscriptionEntity.getNotificationURI()){

+			if(!uri.equals(request.getFrom())){

+				Notification notification = new Notification();

+				notification.setCreator(subscriptionEntity.getCreator());

+				notification.setVerificationRequest(true);

+				notification.setSubscriptionReference(subscriptionEntity.getHierarchicalURI());

+				notification.setSubscriptionDeletion(false);

+				RequestPrimitive notifRequest = new RequestPrimitive();

+				notifRequest.setContent(DataMapperSelector.getDataMapperList().get(MimeMediaType.XML).objToString(notification));

+				notifRequest.setFrom("/" + Constants.CSE_ID);

+				notifRequest.setTo(uri);

+				notifRequest.setOperation(Operation.NOTIFY);

+				notifRequest.setRequestContentType(MimeMediaType.XML);

+				notifRequest.setReturnContentType(MimeMediaType.XML);

+				ResponsePrimitive resp = notify(notifRequest, uri);

+				if(resp.getResponseStatusCode().equals(ResponseStatusCode.TARGET_NOT_REACHABLE)){

+					throw new Om2mException("Error during the verification request", 

+							ResponseStatusCode.SUBSCRIPTION_VERIFICATION_INITIATION_FAILED);

+				}

+				if(resp.getResponseStatusCode().equals(ResponseStatusCode.SUBSCRIPTION_CREATOR_HAS_NO_PRIVILEGE)

+						|| resp.getResponseStatusCode().equals(ResponseStatusCode.SUBSCRIPTION_HOST_HAS_NO_PRIVILEGE)){

+					throw new Om2mException(resp.getResponseStatusCode());

+				}

+			}

+		}

+	}

+

+	public static ResponsePrimitive notify(RequestPrimitive request, String contact){

+		// Check whether the subscription contact is protocol-dependent or not.

+		LOGGER.info("Sending notify request to: " + contact);

+		if(contact.matches(".*://.*")){ 

+			// Contact = protocol-dependent -> direct notification using the rest client.

+			request.setTo(contact);

+			return RestClient.sendRequest(request);

+		}else{

+			request.setTargetId(contact);

+			LOGGER.info("Sending notify request...");

+			return new Router().doRequest(request);

+		}

+	}

+

+	/**

+	 * Used to retrieve the subscription list of the parent resource

+	 * @param resource 

+	 * @return

+	 */

+	private static List<SubscriptionEntity> getParentSubscriptions(

+			ResourceEntity resourceDeleted) {

+		List<SubscriptionEntity> result;

+		// Get parent id

+		String[] ids = resourceDeleted.getHierarchicalURI().split("/");

+		String parentHierarchicalId = resourceDeleted.getHierarchicalURI().replace("/" + ids[ids.length - 1], "");

+		String parentId = UriMapper.getNonHierarchicalUri(parentHierarchicalId);

+		// get parent entity

+		DBService dbs = PersistenceService.getInstance().getDbService();

+

+		DAO<?> dao = Patterns.getDAO(parentId, dbs);

+		DBTransaction transaction = dbs.getDbTransaction();

+		transaction.open();

+		ResourceEntity parentEntity = (ResourceEntity) dao.find(transaction, parentId);

+		// get the sub list from parent

+		switch(parentEntity.getResourceType().intValue()){

+		case ResourceType.ACCESS_CONTROL_POLICY:

+			AccessControlPolicyEntity acp = (AccessControlPolicyEntity) parentEntity;

+			result = acp.getChildSubscriptions();

+			break;

+		case ResourceType.AE:

+			AeEntity ae = (AeEntity) parentEntity;

+			result = ae.getSubscriptions();

+			break;

+		case ResourceType.CONTAINER:

+			ContainerEntity cnt = (ContainerEntity) parentEntity;

+			result = cnt.getSubscriptions();

+			break;

+		case ResourceType.CSE_BASE:

+			CSEBaseEntity csb = (CSEBaseEntity) parentEntity;

+			result = csb.getSubscriptions();

+			break;

+		case ResourceType.GROUP:

+			GroupEntity group = (GroupEntity) parentEntity;

+			result = group.getSubscriptions();

+			break;

+		case ResourceType.REMOTE_CSE:

+			RemoteCSEEntity csr = (RemoteCSEEntity) parentEntity;

+			result = csr.getSubscriptions();

+			break;

+		case ResourceType.SCHEDULE:

+			ScheduleEntity schedule = (ScheduleEntity) parentEntity;

+			result = schedule.getSubscriptions();

+			break;

+		default:

+			result = new ArrayList<SubscriptionEntity>();

+		}

+		transaction.close();

+		return result;

+	}

+

+	/**

+	 * Worker that perform the notification task for a subscription

+	 *

+	 */

+	static class NotificationWorker implements Runnable {

+		/** resource status of the notification */

+		private int resourceStatus;

+		/** the subscription to handle */

+		private SubscriptionEntity sub;

+		/** the resource to be sent */

+		private ResourceEntity resource;

+

+		public NotificationWorker(SubscriptionEntity sub, int resourceStatus, ResourceEntity resource) {

+			this.resourceStatus = resourceStatus;

+			this.sub = sub;

+			this.resource = resource;

+		}

+

+		@SuppressWarnings("unchecked")

+		@Override

+		public void run() {

+			final RequestPrimitive request = new RequestPrimitive();

+			Notification notification = new Notification();

+			NotificationEvent notifEvent = new NotificationEvent();

+			notification.setNotificationEvent(notifEvent);

+

+			// Set attributes of notification object

+			notifEvent.setResourceStatus(BigInteger.valueOf(resourceStatus));

+			notification.setCreator(sub.getCreator());

+

+			// Set request parameters

+			request.setOperation(Operation.NOTIFY);

+			request.setFrom("/" + Constants.CSE_ID);

+

+			if(resourceStatus == ResourceStatus.DELETED){

+				notification.setSubscriptionDeletion(true);

+			} else {

+				notification.setSubscriptionDeletion(false);

+			}

+

+			notification.setSubscriptionReference(sub.getHierarchicalURI());

+

+			// Get the representation of the content

+			Resource serializableResource;

+			EntityMapper mapper ;

+			if (sub.getNotificationContentType() != null){

+				if (resource.getResourceType().equals(ResourceType.MGMT_OBJ)) {

+					mapper = EntityMapperFactory.getMapperForMgmtObj((MgmtObjEntity) resource);

+				} else {

+					mapper = EntityMapperFactory.

+							getMapperFromResourceType(resource.getResourceType().intValue());

+				}

+				if(sub.getNotificationContentType().equals(NotificationContentType.MODIFIED_ATTRIBUTES)){

+					serializableResource = (Resource)mapper.mapEntityToResource(resource, ResultContent.ATTRIBUTES);

+					notification.getNotificationEvent().setRepresentation(serializableResource);

+					request.setRequestContentType(MimeMediaType.XML);

+				} else if(sub.getNotificationContentType().equals(NotificationContentType.WHOLE_RESOURCE)){

+					serializableResource = (Resource) mapper.mapEntityToResource(resource, ResultContent.ATTRIBUTES);

+					notification.getNotificationEvent().setRepresentation(serializableResource);

+					request.setRequestContentType(MimeMediaType.XML);

+				} 

+			} 

+			// Set the content

+			request.setContent(DataMapperSelector.getDataMapperList().get(MimeMediaType.XML).objToString(notification));

+			// For each notification URI: send the notify request

+			for(final String uri : sub.getNotificationURI()){

+				CoreExecutor.postThread(new Runnable(){

+					public void run() {

+						Notifier.notify(request, uri);    					

+					};

+				});

+			}

+		}

+	}

+

+}

diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/persistence/PersistenceService.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/persistence/PersistenceService.java
index c9a6f56..a5d9596 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/persistence/PersistenceService.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/persistence/PersistenceService.java
@@ -19,8 +19,6 @@
  *******************************************************************************/
 package org.eclipse.om2m.core.persistence;
 
-import java.util.concurrent.Semaphore;
-
 import org.eclipse.om2m.persistence.service.DBService;
 
 /**
@@ -30,7 +28,6 @@
 public class PersistenceService {
 	
 	private DBService dbService ;
-	private Semaphore dbReady = new Semaphore(0);
 	
 	private static PersistenceService service = new PersistenceService();
 	
@@ -49,15 +46,4 @@
 		this.dbService = dbService;
 	}
 
-	/**
-	 * @return the dbReady
-	 */
-	public Semaphore getDbReady() {
-		return dbReady;
-	}
-	
-	public void resetSemaphoreDb(){
-		dbReady = new Semaphore(0);
-	}
-
 }
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/redirector/Redirector.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/redirector/Redirector.java
index fbf20a1..fd20c05 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/redirector/Redirector.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/redirector/Redirector.java
@@ -23,6 +23,7 @@
 import org.apache.commons.logging.LogFactory;

 import org.eclipse.om2m.commons.constants.CSEType;

 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.ResponseStatusCode;

 import org.eclipse.om2m.commons.entities.AeEntity;

@@ -76,69 +77,79 @@
 		DAO<RemoteCSEEntity> dao = dbs.getDAOFactory().getRemoteCSEbyCseIdDAO();

 		RemoteCSEEntity csrEntity = dao.find(transaction, remoteCseId);

 		if (csrEntity != null) {

-			// test if remote cse is reachable

-			if (!csrEntity.isRequestReachability()) {

-				throw new Om2mException("Remote Cse is not request reachable", 

-						ResponseStatusCode.TARGET_NOT_REACHABLE);

-			}

-			// get Point of Access

-			String url = "";

-			if (!csrEntity.getPointOfAccess().isEmpty()) {

-				boolean done = false;

-				int i = 0;

-				// iterating on points of access while target are not reachable

-				while (!done & i < csrEntity.getPointOfAccess().size()) {

-					url = csrEntity.getPointOfAccess().get(i);

-					if(!url.endsWith("/")){

-						url += "/";

-					}

-					String cseId = (csrEntity.getRemoteCseId().startsWith("/")? 

-							csrEntity.getRemoteCseId().replace("/", ""):

-								csrEntity.getRemoteCseId());

-					if (request.getTargetId().startsWith("/" + cseId)){

-						url += "~" + request.getTargetId();

-					} else {

-						url += request.getTargetId();

-					}

-					request.setTo(url);

-					response = RestClient.sendRequest(request);

-					if(!(response.getResponseStatusCode()

-							.equals(ResponseStatusCode.TARGET_NOT_REACHABLE))){

-						done = true;

-						if(i > 0){

-							String poa = csrEntity.getPointOfAccess().get(i);

-							csrEntity.getPointOfAccess().remove(i);

-							csrEntity.getPointOfAccess().add(0, poa);

-							dbs.getDAOFactory().getRemoteCSEDAO().update(transaction, csrEntity);

-							transaction.commit();

-						}

-					}

-					i++;

-				}

-			} else {

-				// TODO to improve w/ polling channel policy

-				throw new Om2mException("The point of access parameter is missing", ResponseStatusCode.TARGET_NOT_REACHABLE);

-			}

+			LOGGER.info("RemoteCSE found: " + csrEntity.getRemoteCseId());

+			response = sendRedirectorRequest(request, csrEntity, transaction);

 		} else {

 			if (!Constants.CSE_TYPE.equalsIgnoreCase(CSEType.IN)) {

-				String url = "http://" + Constants.REMOTE_CSE_IP + ":"

-						+ Constants.REMOTE_CSE_PORT

-						+ Constants.REMOTE_CSE_CONTEXT;

-				if (Constants.REMOTE_CSE_CONTEXT.length() > 1) {

-					url += "/";

-				}

-				url += request.getTargetId();

-				request.setTo(url);

+				LOGGER.info("Unknow CSE, sending request to registrar CSE: " + Constants.REMOTE_CSE_ID);

+				csrEntity = dao.find(transaction, "/" + Constants.REMOTE_CSE_ID);

 				// transfer the request and get the response

-				response = RestClient.sendRequest(request);

+				response =sendRedirectorRequest(request, csrEntity, transaction);

 			} else {

 				// case nothing found

-				response.setResponseStatusCode(ResponseStatusCode.NOT_FOUND);

+				throw new ResourceNotFoundException("RemoteCse with cseId " + remoteCseId + " has not been found");

 			}

 		}

 		transaction.close();

 		return response;

 	}

+	

+	private static ResponsePrimitive sendRedirectorRequest(RequestPrimitive request, RemoteCSEEntity csrEntity, DBTransaction transaction){

+		// test if the remoteCse is reachable

+		if (!csrEntity.isRequestReachability()) {

+			throw new Om2mException("Remote Cse is not request reachable", 

+					ResponseStatusCode.TARGET_NOT_REACHABLE);

+		}

+		DBService dbs = PersistenceService.getInstance().getDbService();

+		// get Point of Access

+		String url = "";

+		if (!csrEntity.getPointOfAccess().isEmpty()) {

+			boolean done = false;

+			int i = 0;

+			// iterating on points of access while target are not reachable

+			while (!done & i < csrEntity.getPointOfAccess().size()) {

+				url = csrEntity.getPointOfAccess().get(i);

+				// Remove a potential / added at the end of the poa

+				if(url.endsWith("/")){

+					LOGGER.debug("Removing / at the end of poa: " + url);

+					url = url.substring(0, url.length() - 1);

+				}

+				

+				if(request.getTo().startsWith("//")){

+					url += request.getTo().replaceFirst("//", "/_/");

+				} else if(request.getTo().startsWith("/")){

+					url += request.getTo().replaceFirst("/", "/~/");

+				} else {

+					url+= "/" + request.getTo();

+				}

+				

+				request.setTo(url);

+				ResponsePrimitive response = RestClient.sendRequest(request);

+				if(!(response.getResponseStatusCode()

+						.equals(ResponseStatusCode.TARGET_NOT_REACHABLE))){

+					done = true;

+					if(i > 0){

+						String poa = csrEntity.getPointOfAccess().get(i);

+						csrEntity.getPointOfAccess().remove(i);

+						csrEntity.getPointOfAccess().add(0, poa);

+						dbs.getDAOFactory().getRemoteCSEDAO().update(transaction, csrEntity);

+						transaction.commit();

+					}

+					return response;

+				}

+				i++;

+			}

+			// if we reach this point, there is no poa working

+			ResponsePrimitive response = new ResponsePrimitive(request);

+			response.setResponseStatusCode(ResponseStatusCode.TARGET_NOT_REACHABLE);

+			response.setContent("Target is not reachable");

+			response.setContentType(MimeMediaType.TEXT_PLAIN);

+			return response;

+		} else {

+			// TODO to improve w/ polling channel policy

+			throw new Om2mException("The point of access parameter is missing", ResponseStatusCode.TARGET_NOT_REACHABLE);

+		}

+	}

 

 	public static ResponsePrimitive retargetNotify(RequestPrimitive request){

 		ResponsePrimitive response = new ResponsePrimitive(request);

@@ -151,13 +162,15 @@
 			dbt.close();

 			throw new ResourceNotFoundException("AE resource " + request.getTargetId() + " not found.");

 		}

-

-		new AEController().checkACP(ae.getAccessControlPolicies(), request.getFrom(), Operation.NOTIFY);

-

+	

+		// FIXME use the correct originator when a notification is generated

+		if(!request.getFrom().equals("/" + Constants.CSE_ID)){

+			new AEController().checkACP(ae.getAccessControlPolicies(), request.getFrom(), Operation.NOTIFY);			

+		}

+		

 		// Get point of access

 		if(ae.getPointOfAccess().isEmpty() || !(ae.isRequestReachable())){

-			response.setResponseStatusCode(ResponseStatusCode.TARGET_NOT_REACHABLE);

-			response.setErrorMessage("AE has no Point of Access");

+			throw new Om2mException("AE has no point of access", ResponseStatusCode.TARGET_NOT_REACHABLE);

 		} else {

 			boolean done = false ;

 			int i = 0;

@@ -173,7 +186,7 @@
 						LOGGER.info("Om2m exception caught in Redirector: " + om2mE.getMessage() );

 						throw om2mE;

 					} catch (Exception e){

-						LOGGER.error("Exception caught in IPE execution");

+						LOGGER.error("Exception caught in IPE execution",e);

 						throw new Om2mException("IPE Internal Error", e, ResponseStatusCode.INTERNAL_SERVER_ERROR);

 					}

 					done = true;

diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/router/Patterns.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/router/Patterns.java
index 862c19e..4b14183 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/router/Patterns.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/router/Patterns.java
@@ -38,7 +38,7 @@
 	private static final String ALL_SHORT_NAMES = ShortName.ACP+"|"+ShortName.AE+"|"+ShortName.CNT+
 			"|"+ShortName.CIN + "|" + ShortName.REMOTE_CSE + "|" + ShortName.LATEST + "|" + ShortName.OLDEST +
 			"|" + ShortName.GROUP + "|" + ShortName.FANOUTPOINT + "|" + ShortName.SUB + "|" + ShortName.PCH + 
-			"|" + ShortName.POLLING_CHANNEL_URI + "|" + ShortName.REQ + "|" + ShortName.NODE;
+			"|" + ShortName.POLLING_CHANNEL_URI + "|" + ShortName.REQ + "|" + ShortName.NODE + "|" + ShortName.ANI + "|" + ShortName.ANDI;
 	
 	private static final String NON_HIERARCHICAL_ID = "(" + Constants.PREFIX_SEPERATOR +"(\\b\\w+\\b)?)" ;
 	
@@ -59,15 +59,10 @@
     /** CseBase resource uri pattern. */
     public static final Pattern CSE_BASE_PATTERN= Pattern.compile("/" + Constants.CSE_ID);
     
-    /** Non-hierarchical URI pattern */
-    public static final Pattern NON_HIERARCHICAL_PATTERN = Pattern.compile(
-    		"(" + CSE_BASE_PATTERN + "/(" + ALL_SHORT_NAMES + ")" + Constants.PREFIX_SEPERATOR + ID_STRING + ")|(" + CSE_BASE_PATTERN+ ")"
-    		); 
-    
     /** AccessControlPolicy uri pattern MAY BE NOT COMPLETE */
     public static final Pattern ACP_PATTERN = Pattern.compile(CSE_BASE_PATTERN + "/" + ShortName.ACP + Constants.PREFIX_SEPERATOR + ID_STRING );
     
-    public static final Pattern AE_PATTERN = Pattern.compile(CSE_BASE_PATTERN + "/" + ShortName.AE + Constants.PREFIX_SEPERATOR + ID_STRING);
+    public static final Pattern AE_PATTERN = Pattern.compile(CSE_BASE_PATTERN + "/" + "(C|S)" + ID_STRING);
     
     public static final Pattern CONTAINER_PATTERN = Pattern.compile(CSE_BASE_PATTERN + "/" + ShortName.CNT + Constants.PREFIX_SEPERATOR + ID_STRING);
 
@@ -91,6 +86,20 @@
     
     public static final Pattern NODE_PATTERN = Pattern.compile(CSE_BASE_PATTERN + "/" + ShortName.NODE + Constants.PREFIX_SEPERATOR + ID_STRING);
 
+    public static final Pattern AREA_NW_INFO_PATTERN = Pattern.compile(CSE_BASE_PATTERN + "/" + ShortName.ANI + Constants.PREFIX_SEPERATOR + ID_STRING);
+
+	public static final Pattern AREA_NWK_DEVICE_INFO_PATTERN = Pattern.compile(CSE_BASE_PATTERN + "/" + ShortName.ANDI + Constants.PREFIX_SEPERATOR + ID_STRING);
+
+    /** Non-hierarchical URI pattern */
+    public static final Pattern NON_HIERARCHICAL_PATTERN = Pattern.compile(
+    		"(" + CSE_BASE_PATTERN + "/(" + ALL_SHORT_NAMES + ")" + Constants.PREFIX_SEPERATOR + ID_STRING + ")|(" + CSE_BASE_PATTERN+ ")|" +
+    		AE_PATTERN.pattern()); 
+    
+    /** Hierarchical URI Pattern */
+    public static final Pattern HIERARCHICAL_PATTERN = Pattern.compile(
+    		CSE_BASE_PATTERN + "(/" + Constants.CSE_NAME + "(/"+ ID_PATTERN +")*)?"
+    		);
+    
 	/**
 	 * match uri with a pattern.
 	 * @param pattern - pattern
@@ -143,6 +152,9 @@
 		if(match(REQUEST_PATTERN, uri)){
 			return db.getDAOFactory().getRequestEntityDAO();
 		}
+		if (match(NODE_PATTERN, uri)) {
+			return db.getDAOFactory().getNodeEntityDAO();
+		}
 		return null;
 	}
 	
@@ -152,6 +164,6 @@
 	 * @return
 	 */
 	public static boolean checkResourceName(String resourceName){
-		return (!match(UNAUTHORIZED_NAMES, resourceName) && match(ID_PATTERN, resourceName));
+		return match(ID_PATTERN, resourceName);
 	}
 }
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/router/Router.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/router/Router.java
index 0bfc16f..44f4f5c 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/router/Router.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/router/Router.java
@@ -20,6 +20,10 @@
 package org.eclipse.om2m.core.router;
 
 import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -32,6 +36,7 @@
 import org.eclipse.om2m.commons.constants.ResultContent;
 import org.eclipse.om2m.commons.constants.ShortName;
 import org.eclipse.om2m.commons.exceptions.BadRequestException;
+import org.eclipse.om2m.commons.exceptions.NotImplementedException;
 import org.eclipse.om2m.commons.exceptions.Om2mException;
 import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
 import org.eclipse.om2m.commons.resource.RequestPrimitive;
@@ -74,9 +79,9 @@
 	public ResponsePrimitive doRequest(RequestPrimitive request) {
 		LOGGER.info("Received request in Router: " + request.toString());
 		ResponsePrimitive response = new ResponsePrimitive(request);
-		
+
 		try{
-			
+
 			// Non blocking request handling
 			if (request.getResponseTypeInfo() != null 
 					&& request.getResponseTypeInfo().getResponseType() != null){
@@ -86,8 +91,9 @@
 						return NonBlockingHandler.handle(request);					
 					} else {
 						response.setResponseStatusCode(ResponseStatusCode.NON_BLOCKING_REQUEST_NOT_SUPPORTED);
-						response.setErrorMessage("Non blocking request is not supported");
-						return response;					
+						response.setContent("Non blocking request is not supported");
+						response.setContentType(MimeMediaType.TEXT_PLAIN);
+						return response;
 					}
 				}
 			}
@@ -95,37 +101,35 @@
 			// Check if the data type has been set
 			if (request.getRequestContentType() == null){
 				request.setRequestContentType(MimeMediaType.XML);
+				LOGGER.info("No Content-Type parameter set, setting to default: " + request.getRequestContentType());
 			}
 			if (request.getReturnContentType() == null){
 				request.setReturnContentType(MimeMediaType.XML);
+				LOGGER.info("No Accept parameter set, setting to default: " + request.getReturnContentType());
 			}
 
 			// Check if the data type requested is supported
 			if (request.getRequestContentType() != MimeMediaType.OBJ && request.getRequestContentType()!=null){
 				if (!DataMapperSelector.getDataMapperList().containsKey(request.getRequestContentType())){
-					response.setResponseStatusCode(ResponseStatusCode.NOT_IMPLEMENTED);
-					response.setErrorMessage(request.getRequestContentType()+" is not supported.");
-					return response;
+					throw new NotImplementedException(request.getRequestContentType()+" is not supported.");
 				}
 			}
 			if (request.getReturnContentType() != MimeMediaType.OBJ && request.getReturnContentType()!=null){
 				if (!DataMapperSelector.getDataMapperList().containsKey(request.getReturnContentType())){
-					response.setResponseStatusCode(ResponseStatusCode.NOT_IMPLEMENTED);
-					response.setErrorMessage(request.getReturnContentType()+" is not supported.");
-					return response;
+					throw new NotImplementedException(request.getReturnContentType()+" is not supported.");
 				}
 			}
-			
+
 			// Check if the operation has been provided
 			if(request.getOperation() == null){
 				throw new BadRequestException("No Operation provided");
 			}
-			
+
 			// URI Handling
 			if(request.getTargetId() == null){
 				request.setTargetId(request.getTo());
 			}
-			
+
 			if(request.getTargetId().startsWith("~")){
 				request.setTargetId(request.getTargetId().substring(1));
 			} 
@@ -135,7 +139,7 @@
 				String uri = request.getTargetId().substring(2);
 				String spId = uri.split("/")[0];
 				if (!spId.equals(Constants.M2M_SP_ID)){
-					throw new ResourceNotFoundException("Not the current SP Domain.");
+					throw new ResourceNotFoundException("Not the current SP Domain (" + spId + ")");
 				} else {
 					request.setTargetId(uri.replace(spId, ""));
 				}
@@ -148,14 +152,34 @@
 				request.setTargetId(request.getTargetId().substring(0,request.getTargetId().length()-1));
 			}
 
+			getQueryStringFromTargetId(request);
+
 			// Redirection case
 			if (!Patterns.match(Patterns.NON_RETARGETING_PATTERN, request.getTargetId())){
+				LOGGER.info("Request targeting another CSE, forwarding to Redirector: " + request.getTo());
 				return Redirector.retarget(request);
 			}
+			LOGGER.info("Request handling in the current CSE: " + request.getTo());
 
 			Controller controller = null ; 
 			// Case of hierarchical URI, retrieve the non-hierarchical URI of the resource
-			if (!Patterns.match(Patterns.NON_HIERARCHICAL_PATTERN, request.getTargetId())){
+			if (Patterns.match(Patterns.HIERARCHICAL_PATTERN, request.getTargetId())){
+				if(request.getTargetId().contains(Patterns.FANOUT_POINT_MATCH + "/")){
+					int foptIndex = request.getTargetId().indexOf(Patterns.FANOUT_POINT_MATCH);
+					String uri = request.getTargetId().substring(0, foptIndex);
+					String suffix = request.getTargetId()
+							.substring(
+									foptIndex + Patterns.FANOUT_POINT_MATCH.length(), 
+									request.getTargetId().length()
+									);
+					controller = new FanOutPointController(suffix);
+					request.setTargetId(uri);
+					LOGGER.info("Fan Out request received: [grp uri: " + uri + ", suffix: " + suffix + "]");
+				} if (request.getTargetId().endsWith(Patterns.FANOUT_POINT_MATCH)) {
+					controller = new FanOutPointController();
+					request.setTargetId(request.getTargetId().replaceAll(Patterns.FANOUT_POINT_MATCH, ""));
+					LOGGER.info("Fan Out request received: [grp uri: " + request.getTargetId()+ "]");
+				} 
 				if(request.getTargetId().endsWith("/" + ShortName.LATEST)){
 					controller = new LatestOldestController(SortingPolicy.LATEST);
 					request.setTargetId(request.getTargetId() + "/");
@@ -166,15 +190,12 @@
 					request.setTargetId(request.getTargetId() + "/");
 					request.setTargetId(request.getTargetId().replace("/"+ShortName.OLDEST+"/", ""));
 				}
-				if (request.getTargetId().endsWith(Patterns.FANOUT_POINT_MATCH)) {
-					controller = new FanOutPointController();
-					request.setTargetId(request.getTargetId().replaceAll(Patterns.FANOUT_POINT_MATCH, ""));
-				}
 				String nonHierarchicalUri = UriMapper.getNonHierarchicalUri(request.getTargetId());
 				if (nonHierarchicalUri == null){
 					throw new ResourceNotFoundException("Resource not found");
 				}
 				request.setTargetId(nonHierarchicalUri);
+				LOGGER.debug("Changing to unstructured uri for routing to: " + request.getTargetId());
 			}
 
 			// Notify case
@@ -198,7 +219,7 @@
 			}
 
 			if (controller!=null){
-				LOGGER.info("ResourceController ["+ controller.getClass().getSimpleName()+"]");
+				LOGGER.info("ResourceController to be used ["+ controller.getClass().getSimpleName()+"]");
 				// Perform the request in the specific controller
 				response = controller.doRequest(request);
 				if(request.getResultContent() != null && request.getResultContent().equals(ResultContent.NOTHING)){
@@ -209,20 +230,23 @@
 						String representation = DataMapperSelector.getDataMapperList().
 								get(request.getReturnContentType()).objToString(response.getContent());
 						response.setContent(representation);
+						response.setContentType(request.getReturnContentType());
 					}
 				}
 			} else {
-				response.setResponseStatusCode(ResponseStatusCode.BAD_REQUEST);
-				response.setErrorMessage("Malformed URI");
+				throw new BadRequestException("Malformed URI");
 			}
 		} catch (Om2mException om2mException){
 			response.setResponseStatusCode(om2mException.getErrorStatusCode());
-			response.setErrorMessage(om2mException.getMessage());
-			LOGGER.debug("Om2m exception catched in Controller", om2mException);
+			response.setContent(om2mException.getMessage());
+			response.setContentType(MimeMediaType.TEXT_PLAIN);
+			LOGGER.info("OM2M exception caught in Router: " + om2mException.getMessage());
+			LOGGER.debug("OM2M exception caught in Router", om2mException);
 		} catch(Exception e){
-			response.setResponseStatusCode(ResponseStatusCode.INTERNAL_SERVER_ERROR);
-			response.setErrorMessage("Router internal error");
 			LOGGER.error("Router internal error", e);
+			response.setResponseStatusCode(ResponseStatusCode.INTERNAL_SERVER_ERROR);
+			response.setContent("Router internal error");
+			response.setContentType(MimeMediaType.TEXT_PLAIN);
 		}
 
 		LOGGER.info("Response in Router= " + response);
@@ -286,7 +310,7 @@
 	protected Controller getResourceControllerFromRT(BigInteger resourceType){
 		// test in case resourceType is null
 		if (resourceType == null) {
-			throw new BadRequestException("Resource type is missing");
+			throw new BadRequestException("Resource type is missing for creation request");
 		}
 		// switch case
 		switch(resourceType.intValue()){
@@ -311,7 +335,43 @@
 		case ResourceType.POLLING_CHANNEL:
 			return new PollingChannelController();
 		default : 
-			return null;
+			throw new NotImplementedException("ResourceType: " + resourceType + " is not implemented");
 		}
 	}
+
+	private static void getQueryStringFromTargetId(RequestPrimitive request){
+		if(request.getTargetId().contains("?")){
+			String query = request.getTargetId().split("\\?")[1];
+			Map<String, List<String>> parameters = new HashMap<String, List<String>>();
+			if (query != null) {
+				String[] pairs = query.split("[&]");
+				for (String pair : pairs) {
+					String[] param = pair.split("[=]");
+
+					String key = null;
+					String value = null;
+					if (param.length > 0) {
+						key = param[0];
+					}
+					if (param.length > 1) {
+						value = param[1];
+					}
+					if (parameters.containsKey(key)) {
+						parameters.get(key).add(value);
+					} else {
+						List<String> values = new ArrayList<String>();
+						values.add(value);
+						parameters.put(key,values);
+					}
+				}
+			}
+			request.getQueryStrings().putAll(parameters);
+			if(request.getTo() == null){
+				request.setTo(request.getTargetId().split("\\?")[0]);
+				request.setTargetId(request.getTo());
+			}
+		}
+
+	}
+
 }
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/thread/CoreExecutor.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/thread/CoreExecutor.java
new file mode 100644
index 0000000..de56423
--- /dev/null
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/thread/CoreExecutor.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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.thread;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.om2m.commons.constants.Constants;
+
+/**
+ * This class provides a management of thread policies. It is initialized using 
+ * the Constants.MAX_THREAD_POOL_SIZE and avoid creating too much thread and overload 
+ * an instance. 
+ * 
+ */
+public class CoreExecutor {
+	
+	/** Default logger */
+	private static final Log LOGGER = LogFactory.getLog(CoreExecutor.class.getName());
+	/** The ExecutorService with the applied thread policy */
+	private static final ExecutorService threadPool;
+
+	/**
+	 * Initialize the threadPool with the specific policy
+	 */
+	static {
+		// Use minimum 2 threads
+		int maximumPoolSize = Constants.MAX_THREAD_POOL_SIZE > 2 ? Constants.MAX_THREAD_POOL_SIZE: 2; 
+		// Provide 10% of thread kept alive for better performance
+		int corePoolSize = maximumPoolSize / 10;
+		LOGGER.info("Creating thread pool with corePoolSize=" + corePoolSize + 
+				" & maximumSize=" + maximumPoolSize);
+		// Keep alive the threads for a minute in the pool
+		threadPool = new ThreadPoolExecutor(
+				corePoolSize, maximumPoolSize, 
+				60L, TimeUnit.SECONDS, 
+				new SynchronousQueue<Runnable>()
+		);
+	}
+	
+	/**
+	 * Submit the operation to the executor service. 
+	 * It will return a Future<T> object. To access the result of the
+	 * operation, use the get() method of the Future<T> object that will
+	 * block until the result is not available. Then, it will provide the 
+	 * result of the operation of type <T>.
+	 * @param callable the operation to perform with the specific type
+	 * @return the Future<T> object, use the get() method to retrieve the result
+	 */
+	public static <T> Future<T> submit(Callable<T> callable){
+		return threadPool.submit(callable);
+	}
+	
+	/** 
+	 * Post the runnable into the executor service.
+	 * @param runnable the operation to be performed
+	 */
+	public static void postThread(Runnable runnable){
+		threadPool.execute(runnable);
+	}
+	
+}
diff --git a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/util/ControllerUtil.java b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/util/ControllerUtil.java
index fef9741..b4081b2 100644
--- a/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/util/ControllerUtil.java
+++ b/org.eclipse.om2m.core/src/main/java/org/eclipse/om2m/core/util/ControllerUtil.java
@@ -26,6 +26,7 @@
 import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
 import org.eclipse.om2m.commons.entities.AnnounceableSubordinateEntity;
 import org.eclipse.om2m.commons.entities.ResourceEntity;
+import org.eclipse.om2m.commons.exceptions.BadRequestException;
 import org.eclipse.om2m.commons.exceptions.NotPermittedAttrException;
 import org.eclipse.om2m.commons.exceptions.Om2mException;
 import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
@@ -86,9 +87,6 @@
 		
 		public static void fillEntityFromGenericResource(Resource resource, ResourceEntity entity) 
 				throws NotPermittedAttrException{
-			/*if(resource.getName() != null){
-				throw new NotPermittedAttrException("Name is Not Permitted");
-			}*/
 			if(resource.getResourceType() != null){
 				throw new NotPermittedAttrException("ResourceType is Not Permitted");
 			}
@@ -122,9 +120,38 @@
 			}
 			if(resource.getExpirationTime() != null){
 				entity.setExpirationTime(resource.getExpirationTime());
+			} else {
+				entity.setExpirationTime(DateUtil.getDefaultExpirationTime());
 			}
 		}
 	}
+	
+	public static class UpdateUtil{
+		
+		private UpdateUtil(){}
+		
+		public static void checkNotPermittedParameters(Resource resource){
+			if(resource.getName() != null){
+				throw new BadRequestException("ResourceName is NP");
+			}
+			if(resource.getResourceType() != null){
+				throw new BadRequestException("ResourceType is NP");
+			}
+			if(resource.getResourceID() != null){
+				throw new BadRequestException("ResourceID is NP");
+			}
+			if(resource.getParentID() != null){
+				throw new BadRequestException("ParentID is NP");
+			}
+			if(resource.getCreationTime() != null){
+				throw new BadRequestException("CreationTime is NP");
+			}
+			if(resource.getLastModifiedTime() != null){
+				throw new BadRequestException("LastModifiedTime is NP");
+			}
+		}
+		
+	}
 
 
 }