From 90e2231ac9634c6a7478e88e5212c8dd872c2e37 Mon Sep 17 00:00:00 2001 From: Minji Park Date: Thu, 25 Aug 2016 16:01:30 +0900 Subject: [PATCH] Add resouce publish request, response handling in cloud interface - resource publish request and response handling added in CI to append routing info to href Change-Id: I4040d142648cab5a87a5241fc489530c6294ab32 Signed-off-by: Minji Park Reviewed-on: https://gerrit.iotivity.org/gerrit/10897 Tested-by: jenkins-iotivity Reviewed-by: Jee Hyeok Kim --- .../org/iotivity/cloud/ciserver/Constants.java | 3 + .../resources/proxy/rd/ResourceDirectory.java | 193 +++++++++++++++++---- .../resources/proxy/rd/ResourceDirectoryTest.java | 101 ++++++++++- .../directory/rd/ResourceDirectoryResource.java | 26 +-- 4 files changed, 271 insertions(+), 52 deletions(-) diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/Constants.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/Constants.java index 005c700..9ef30d0 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/Constants.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/Constants.java @@ -48,4 +48,7 @@ public class Constants extends OICConstants { public static final String REQ_PING_ARRAY = "inarray"; public static final String REQ_PING = "in"; + public static final String REQ_LINKS = "links"; + public static final String REQ_HREF = "href"; + } diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceDirectory.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceDirectory.java index 97f2f1e..fa024d0 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceDirectory.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceDirectory.java @@ -21,6 +21,7 @@ */ package org.iotivity.cloud.ciserver.resources.proxy.rd; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -52,31 +53,6 @@ public class ResourceDirectory extends Resource { mASServer = ConnectorPool.getConnection("account"); } - class AccountReceiveHandler implements IResponseEventHandler { - private Device mSrcDevice; - private IRequest mRequest; - - public AccountReceiveHandler(IRequest request, Device srcDevice) { - mSrcDevice = srcDevice; - mRequest = request; - } - - @Override - public void onResponseReceived(IResponse response) - throws ClientException { - - switch (response.getStatus()) { - case CHANGED: - mRDServer.sendRequest(mRequest, mSrcDevice); - break; - - default: - mSrcDevice.sendResponse(MessageBuilder.createResponse( - mRequest, ResponseStatus.BAD_REQUEST)); - } - } - } - @Override public void onDefaultRequestReceived(Device srcDevice, IRequest request) throws ServerException { @@ -96,23 +72,176 @@ public class ResourceDirectory extends Resource { HashMap requestPayload = new HashMap<>(); - requestPayload.put(Constants.REQ_DEVICE_LIST, - Arrays.asList(di)); + requestPayload + .put(Constants.REQ_DEVICE_LIST, Arrays.asList(di)); IRequest requestToAS = MessageBuilder.createRequest( RequestMethod.POST, uriPath.toString(), null, ContentFormat.APPLICATION_CBOR, mCbor.encodingPayloadToCbor(requestPayload)); - mASServer.sendRequest(requestToAS, - new AccountReceiveHandler(request, srcDevice)); + mASServer.sendRequest(requestToAS, new AccountReceiveHandler( + request, srcDevice)); break; case DELETE: mRDServer.sendRequest(request, srcDevice); break; default: - throw new BadRequestException( - request.getMethod() + " request type is not support"); + throw new BadRequestException(request.getMethod() + + " request type is not support"); + } + } + + class AccountReceiveHandler implements IResponseEventHandler { + private Device mSrcDevice; + private IRequest mRequest; + + public AccountReceiveHandler(IRequest request, Device srcDevice) { + mSrcDevice = srcDevice; + mRequest = request; + } + + @Override + public void onResponseReceived(IResponse response) + throws ClientException { + + switch (response.getStatus()) { + case CHANGED: + + byte[] convertedPayload = convertPublishHref(mRequest, + mSrcDevice); + + if (convertedPayload == null) { + + mSrcDevice.sendResponse(MessageBuilder.createResponse( + mRequest, ResponseStatus.PRECONDITION_FAILED)); + } + + mRequest = MessageBuilder.modifyRequest(mRequest, null, + null, ContentFormat.APPLICATION_CBOR, + convertedPayload); + + mRDServer.sendRequest(mRequest, new PublishResponseHandler( + mSrcDevice)); + break; + + default: + mSrcDevice.sendResponse(MessageBuilder.createResponse( + mRequest, ResponseStatus.BAD_REQUEST)); + } + } + + @SuppressWarnings("unchecked") + private byte[] convertPublishHref(IRequest request, Device device) { + + Cbor> cbor = new Cbor<>(); + HashMap payload = cbor.parsePayloadFromCbor( + request.getPayload(), HashMap.class); + + if (verifyPublishPayload(payload) == false) { + + return null; + } + + ArrayList> links = (ArrayList>) payload + .get(Constants.REQ_LINKS); + + for (HashMap link : links) { + + String href = (String) link.get(Constants.REQ_HREF); + href = "/di/" + device.getDeviceId() + href; + + link.put(Constants.REQ_HREF, href); + } + + payload.put(Constants.REQ_LINKS, links); + + return cbor.encodingPayloadToCbor(payload); + } + + @SuppressWarnings("unchecked") + private boolean verifyPublishPayload(HashMap payload) { + + ArrayList> links = (ArrayList>) payload + .get(Constants.REQ_LINKS); + + if (links == null || links.isEmpty()) { + return false; + } + + for (HashMap link : links) { + + String href = (String) link.get(Constants.REQ_HREF); + + if (href == null || href.isEmpty()) { + return false; + } + } + + return true; + } + } + + // handles response to convert href in response payload into original href + // when resource published or updated + class PublishResponseHandler implements IResponseEventHandler { + + private Device mSrcDevice; + + public PublishResponseHandler(Device srcDevice) { + mSrcDevice = srcDevice; + } + + @Override + public void onResponseReceived(IResponse response) + throws ClientException { + + switch (response.getStatus()) { + case CHANGED: + + response = MessageBuilder.modifyResponse(response, + ContentFormat.APPLICATION_CBOR, + convertResponseHref(response)); + + default: + + mSrcDevice.sendResponse(response); + } + } + + @SuppressWarnings("unchecked") + private byte[] convertResponseHref(IResponse response) { + + Cbor> cbor = new Cbor<>(); + HashMap payload = cbor.parsePayloadFromCbor( + response.getPayload(), HashMap.class); + + ArrayList> links = (ArrayList>) payload + .get(Constants.REQ_LINKS); + + for (HashMap link : links) { + + String href = (String) link.get(Constants.REQ_HREF); + + // remove prefix + ArrayList hrefSegments = new ArrayList<>( + Arrays.asList(href.split("/"))); + for (int i = 0; i < 3; i++) { + hrefSegments.remove(0); + } + + StringBuilder newHref = new StringBuilder(); + for (String path : hrefSegments) { + newHref.append("/" + path); + } + + link.put(Constants.REQ_HREF, newHref.toString()); + } + + payload.put(Constants.REQ_LINKS, links); + + return cbor.encodingPayloadToCbor(payload); } } -} + +} \ No newline at end of file diff --git a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceDirectoryTest.java b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceDirectoryTest.java index be5b77b..6d46ff0 100644 --- a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceDirectoryTest.java +++ b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceDirectoryTest.java @@ -34,8 +34,10 @@ import java.util.concurrent.CountDownLatch; import org.iotivity.cloud.base.device.CoapDevice; import org.iotivity.cloud.base.device.IRequestChannel; import org.iotivity.cloud.base.protocols.IRequest; +import org.iotivity.cloud.base.protocols.IResponse; import org.iotivity.cloud.base.protocols.MessageBuilder; import org.iotivity.cloud.base.protocols.coap.CoapRequest; +import org.iotivity.cloud.base.protocols.coap.CoapResponse; import org.iotivity.cloud.base.protocols.enums.ContentFormat; import org.iotivity.cloud.base.protocols.enums.RequestMethod; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; @@ -56,7 +58,7 @@ public class ResourceDirectoryTest { public static final String DEVICE_PRS_REQ_URI = Constants.DEVICE_PRESENCE_FULL_URI; public static final String DEVICE_LIST_KEY = "devices"; public static final String RES_PRS_URI = Constants.RESOURCE_PRESENCE_FULL_URI; - // private DeviceServerSystem deviceServerSystem = new DeviceServerSystem(); + private String mDi = "B371C481-38E6-4D47-8320-7688D8A5B58C"; String mUserId = "testuser"; private CoapDevice mMockDevice = null; @@ -78,6 +80,7 @@ public class ResourceDirectoryTest { mDeviceServerSystem.addResource(mRdHandler); mMockDevice = mock(CoapDevice.class); Mockito.doReturn(mUserId).when(mMockDevice).getUserId(); + Mockito.doReturn(mDi).when(mMockDevice).getDeviceId(); Mockito.doAnswer(new Answer() { @Override @@ -140,21 +143,66 @@ public class ResourceDirectoryTest { assertTrue(mReqRDServer.getUriPath().contains(TEST_RD_URI)); } - IRequest rdPublishRequest = makeResourcePublishRequest(); - - @InjectMocks - ResourceDirectory.AccountReceiveHandler accountReceiveHandler = mRdHandler.new AccountReceiveHandler( - rdPublishRequest, mMockDevice); + IRequest rdPublishRequest = makeResourcePublishRequest(); + IResponse rdPublishResponse = makeResourcePublishResponse(); @Test public void testRDResourcePublishOnResponseReceived() throws Exception { + + ResourceDirectory.AccountReceiveHandler accountReceiveHandler = mRdHandler.new AccountReceiveHandler( + rdPublishRequest, mMockDevice); + IRequest request = makeResourcePublishRequest(); - accountReceiveHandler.onResponseReceived( - MessageBuilder.createResponse(request, ResponseStatus.CHANGED)); + accountReceiveHandler.onResponseReceived(MessageBuilder.createResponse( + request, ResponseStatus.CHANGED)); + assertEquals(mReqRDServer, rdPublishRequest); assertTrue(mLatch.await(1L, SECONDS)); } + @Test + public void testRDResourcePublishPayloadConverted() throws Exception { + + ResourceDirectory.AccountReceiveHandler accountReceiveHandler = mRdHandler.new AccountReceiveHandler( + rdPublishRequest, mMockDevice); + + IRequest request = makeResourcePublishRequest(); + accountReceiveHandler.onResponseReceived(MessageBuilder.createResponse( + request, ResponseStatus.CHANGED)); + + assertEquals(getHrefInTestPublishPayload(mReqRDServer.getPayload()), + "/di/" + mDi + "/a/light"); + } + + @Test + public void testRDResourcePublishResponse() throws Exception { + + ResourceDirectory.PublishResponseHandler publishResponseHandler = mRdHandler.new PublishResponseHandler( + mMockDevice); + + CountDownLatch latch = new CountDownLatch(1); + + Mockito.doAnswer(new Answer() { + @Override + public CoapResponse answer(InvocationOnMock invocation) + throws Throwable { + Object[] args = invocation.getArguments(); + CoapResponse resp = (CoapResponse) args[0]; + + assertEquals(getHrefInTestPublishPayload(resp.getPayload()), + "/a/light"); + + latch.countDown(); + return resp; + } + }).when(mMockDevice).sendResponse(Mockito.anyObject()); + + publishResponseHandler + .onResponseReceived(makeResourcePublishResponse()); + + assertTrue(latch.await(1L, SECONDS)); + } + private IRequest makeResourcePublishRequest() { HashMap payload = new HashMap<>(); payload.put(Constants.DEVICE_ID, mDi); @@ -180,6 +228,30 @@ public class ResourceDirectoryTest { return request; } + private IResponse makeResourcePublishResponse() { + HashMap payload = new HashMap<>(); + payload.put(Constants.DEVICE_ID, mDi); + ArrayList> publishLinks = new ArrayList<>(); + HashMap link = new HashMap<>(); + link.put("href", "/di/" + mDi + "/a/light"); + ArrayList rt = new ArrayList(); + rt.add("core.light"); + ArrayList itf = new ArrayList(); + itf.add("oic.if.baseline"); + HashMap policy = new HashMap<>(); + policy.put("bm", 5); + link.put("rt", rt); + link.put("if", itf); + link.put("p", policy); + publishLinks.add(link); + payload.put("links", publishLinks); + + Cbor> cbor = new Cbor<>(); + return MessageBuilder.createResponse(makeResourcePublishRequest(), + ResponseStatus.CHANGED, ContentFormat.APPLICATION_CBOR, + cbor.encodingPayloadToCbor(payload)); + } + private IRequest makeResourceDeleteRequest() { IRequest request = MessageBuilder.createRequest(RequestMethod.DELETE, TEST_RD_URI, "di" + "=" + mDi + ";" + "ins" + "=" + "1234", @@ -187,4 +259,17 @@ public class ResourceDirectoryTest { return request; } + private String getHrefInTestPublishPayload(byte[] payload) { + + Cbor> cbor = new Cbor<>(); + HashMap parsedPayload = cbor.parsePayloadFromCbor( + payload, HashMap.class); + + @SuppressWarnings("unchecked") + ArrayList> links = (ArrayList>) parsedPayload + .get(Constants.REQ_LINKS); + + return (String) links.get(0).get(Constants.REQ_HREF); + } + } diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/ResourceDirectoryResource.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/ResourceDirectoryResource.java index 69eab17..9d465a4 100644 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/ResourceDirectoryResource.java +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/ResourceDirectoryResource.java @@ -73,8 +73,8 @@ public class ResourceDirectoryResource extends Resource { break; default: - throw new BadRequestException( - request.getMethod() + " request type is not supported"); + throw new BadRequestException(request.getMethod() + + " request type is not supported"); } srcDevice.sendResponse(response); @@ -101,18 +101,20 @@ public class ResourceDirectoryResource extends Resource { throw new PreconditionFailedException("rt property is not include"); } else if (listRT.get(0).equals(Constants.RESOURCE_TYPE_RDPUBLISH)) { - PublishPayload pubPayload = parsingPublishPayload( - request.getPayload()); + PublishPayload pubPayload = parsingPublishPayload(request + .getPayload()); mNotiDeviceId = pubPayload.getTags().getDi(); - PublishPayload copyPubPayload = pubPayload.copy(); + // PublishPayload copyPubPayload = pubPayload.copy(); - ArrayList> storeResList = creatDBStoreResource( - changeResourceUri(copyPubPayload)); + // ArrayList> storeResList = + // creatDBStoreResource(changeResourceUri(copyPubPayload)); - mNotiPayloadList = DBManager.getInstance() - .registerResource(storeResList); + ArrayList> storeResList = creatDBStoreResource(pubPayload); + + mNotiPayloadList = DBManager.getInstance().registerResource( + storeResList); encodedPayload = createPublishResponse(pubPayload); @@ -151,8 +153,8 @@ public class ResourceDirectoryResource extends Resource { private PublishPayload parsingPublishPayload(byte[] payload) throws ServerException { - HashMap payloadData = mCbor - .parsePayloadFromCbor(payload, HashMap.class); + HashMap payloadData = mCbor.parsePayloadFromCbor( + payload, HashMap.class); if (payloadData == null) { throw new BadRequestException("payload is null"); @@ -175,7 +177,7 @@ public class ResourceDirectoryResource extends Resource { pubLinks = mPublishLinksTypeManager.convertMaptoObject(links, pubLinks); String href = pubLinks.getHref(); - href = "/di/" + di + href; + // href = "/di/" + di + href; int ins = pubLinks.getIns(); ins = checkResourceIns(di, href, ins); if (ins == 0) { -- 2.7.4