2 * //******************************************************************
4 * // Copyright 2016 Samsung Electronics All Rights Reserved.
6 * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8 * // Licensed under the Apache License, Version 2.0 (the "License");
9 * // you may not use this file except in compliance with the License.
10 * // You may obtain a copy of the License at
12 * // http://www.apache.org/licenses/LICENSE-2.0
14 * // Unless required by applicable law or agreed to in writing, software
15 * // distributed under the License is distributed on an "AS IS" BASIS,
16 * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * // See the License for the specific language governing permissions and
18 * // limitations under the License.
20 * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 package org.iotivity.cloud.rdserver.resources;
24 import java.nio.ByteBuffer;
25 import java.nio.charset.StandardCharsets;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.LinkedHashMap;
29 import java.util.List;
30 import java.util.StringTokenizer;
32 import org.iotivity.cloud.base.Resource;
33 import org.iotivity.cloud.base.protocols.coap.CoapRequest;
34 import org.iotivity.cloud.base.protocols.coap.CoapResponse;
35 import org.iotivity.cloud.base.protocols.coap.enums.CoapOption;
36 import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
37 import org.iotivity.cloud.rdserver.Constants;
38 import org.iotivity.cloud.rdserver.MongoDB;
39 import org.iotivity.cloud.util.Cbor;
40 import org.iotivity.cloud.util.JSONUtil;
41 import org.iotivity.cloud.util.Logger;
43 import io.netty.channel.ChannelHandlerContext;
47 * This class provides a set of APIs relating Resource Directory
50 public class ResourceDirectoryResource extends Resource {
52 private Cbor<ArrayList<Object>> cbor;
53 private MongoDB mongoDB;
55 public ResourceDirectoryResource() {
56 setUri(Constants.RD_URI);
57 cbor = new Cbor<ArrayList<Object>>();
59 mongoDB = new MongoDB(Constants.RD_DB_NAME);
60 mongoDB.createTable(Constants.RD_TABLE);
61 } catch (Exception e) {
62 // TODO Auto-generated catch block
68 public void onRequestReceived(ChannelHandlerContext ctx,
69 CoapRequest request) {
71 Logger.d("ResourceDirectoryResource IN");
73 if (ctx == null || request == null) {
74 Logger.d("ctx or request msg is null");
78 switch (request.getRequestMethod()) {
80 Logger.d("Request message is GET message");
82 handleGetRequest(ctx, request);
83 } catch (Exception e) {
89 Logger.d("Request message is PUT message");
93 Logger.d("Request message is POST message");
95 handlePostRequest(ctx, request);
96 } catch (Exception e) {
102 Logger.d("Request message is DELETE message");
104 handleDeleteRequest(ctx, request);
105 } catch (Exception e) {
113 private CoapResponse makePublishResponse(CoapRequest request)
115 CoapResponse response = new CoapResponse(CoapStatus.CREATED);
116 response.setToken(request.getToken());
120 private CoapResponse makeDeleteResponse(CoapRequest request)
122 CoapResponse response = new CoapResponse(CoapStatus.DELETED);
123 response.setToken(request.getToken());
127 private CoapResponse makeDiscoveryResponse(CoapRequest request,
128 ArrayList<PublishPayloadFormat> foundResource) throws Exception {
130 CoapResponse response = new CoapResponse(CoapStatus.CONTENT);
131 response.setToken(request.getToken());
134 ArrayList<HashMap<Object, Object>> discoverPayload = new ArrayList<HashMap<Object, Object>>();
136 for (PublishPayloadFormat pubPayload : foundResource) {
138 LinksPayloadFormat links = pubPayload.links.get(0);
139 LinkedHashMap<Object, Object> discoverLinks = new LinkedHashMap<Object, Object>();
140 discoverLinks.put(Constants.RS_HREF, links.getHref());
141 discoverLinks.put(Constants.RS_RESOURCE_TYPE, links.getRt().get(0));
142 discoverLinks.put(Constants.RS_INTERFACE, links.getItf().get(0));
143 HashMap<Object, Object> pres = new HashMap<Object, Object>();
144 pres.put(Constants.RS_BITMAP, pubPayload.getBitmap());
145 discoverLinks.put("p", pres);
147 ArrayList<Object> linksArray = null;
148 for (HashMap<Object, Object> segmentPayload : discoverPayload) {
150 if (segmentPayload.get(Constants.RS_DEVICE_ID)
151 .equals(pubPayload.getDi())) {
152 linksArray = new ArrayList<Object>();
153 linksArray = (ArrayList<Object>) segmentPayload
155 linksArray.add(discoverLinks);
156 segmentPayload.put("links", linksArray);
159 if (linksArray == null) {
160 HashMap<Object, Object> discoverRes = new HashMap<Object, Object>();
161 linksArray = new ArrayList<Object>();
162 discoverRes.put(Constants.RS_DEVICE_ID, pubPayload.getDi());
163 linksArray.add(discoverLinks);
164 discoverRes.put("links", linksArray);
165 discoverPayload.add(discoverRes);
169 // TODO : device id is decoded to byte in IoTivity. So, temporarily we
170 // cast the type of device id to byte.
171 for (HashMap<Object, Object> segmentPayload : discoverPayload) {
172 String stringDi = segmentPayload.get(Constants.RS_DEVICE_ID)
174 segmentPayload.put(Constants.RS_DEVICE_ID,
175 stringDi.getBytes(StandardCharsets.UTF_8));
178 Logger.i("discoverPayload :" + discoverPayload.toString());
180 byte[] bytes = ByteBuffer.allocate(4).putInt(60).array();
181 response.addOption(CoapOption.CONTENT_FORMAT.getvalue(), bytes);
183 byte[] encodedPaylod = cbor.encodingPayloadToCbor(discoverPayload);
184 response.setPayload(encodedPaylod);
190 private HashMap<String, String> extractFiltersFromQuery(List<String> query)
194 throw new IllegalArgumentException("query is null!");
197 HashMap<String, String> filters = new HashMap<String, String>();
198 for (String queryPara : query) {
199 StringTokenizer keyValuePair = new StringTokenizer(queryPara, "=");
200 if (keyValuePair.countTokens() < 2) {
204 String key = keyValuePair.nextToken();
205 String value = keyValuePair.nextToken();
206 if (key.equals(Constants.RS_INTERFACE)) {
207 filters.put(Constants.RS_INTERFACE, value);
208 } else if (key.equals(Constants.RS_RESOURCE_TYPE)) {
209 filters.put(Constants.RS_RESOURCE_TYPE, value);
210 } else if (key.equals(Constants.RS_DEVICE_ID)) {
211 filters.put(Constants.RS_DEVICE_ID, value);
212 } else if (key.equals(Constants.RS_INS)) {
213 filters.put(Constants.RS_INS, value);
214 } else if (key.equals(Constants.RS_SEARCH_TYPE)) {
215 filters.put(Constants.RS_SEARCH_TYPE, value);
224 * API for handling GET message(message to discovery resources)
227 * ChannelHandlerContext of request message
229 * CoAP request message
232 public void handleGetRequest(ChannelHandlerContext ctx, CoapRequest request)
234 HashMap<String, String> filters = extractFiltersFromQuery(
235 request.getUriQuerySegments());
237 ArrayList<PublishPayloadFormat> foundResource = null;
239 if (filters == null) {
240 throw new IllegalArgumentException("filters is null");
241 } else if (filters.get(Constants.RS_SEARCH_TYPE) == null) {
242 Logger.d("st is null, so this is the get msg about public devices");
243 if (filters.get(Constants.RS_INTERFACE) != null) {
244 foundResource = mongoDB.readResource(Constants.RS_INTERFACE,
245 filters.get(Constants.RS_INTERFACE),
247 } else if (filters.get(Constants.RS_RESOURCE_TYPE) != null) {
248 foundResource = mongoDB.readResource(Constants.RS_RESOURCE_TYPE,
249 filters.get(Constants.RS_RESOURCE_TYPE),
252 throw new IllegalArgumentException("rt & if is null");
255 CoapResponse response = makeDiscoveryResponse(request,
257 ctx.writeAndFlush(response);
260 if (filters.get(Constants.RS_SEARCH_TYPE)
261 .equals(Constants.RS_SEARCH_TYPE_DEVICE_LIST)) {
263 "st is not null, so this is the get msg about private devices");
265 byte[] payload = request.getPayload();
266 ArrayList<String> deviceList = JSONUtil.parseJSON(payload,
267 Constants.RS_DEVICE_LIST_KEY);
268 if (deviceList == null) {
269 throw new IllegalArgumentException("deviceList is null");
272 if (filters.get(Constants.RS_INTERFACE) != null) {
273 foundResource = new ArrayList<PublishPayloadFormat>();
274 for (String deviceId : deviceList) {
275 foundResource.addAll(mongoDB.readResourceAboutDid(
276 deviceId, Constants.RS_INTERFACE,
277 filters.get(Constants.RS_INTERFACE),
278 Constants.RD_TABLE));
280 } else if (filters.get(Constants.RS_RESOURCE_TYPE) != null) {
281 foundResource = new ArrayList<PublishPayloadFormat>();
282 for (String deviceId : deviceList) {
283 foundResource.addAll(mongoDB.readResourceAboutDid(
284 deviceId, Constants.RS_RESOURCE_TYPE,
285 filters.get(Constants.RS_RESOURCE_TYPE),
286 Constants.RD_TABLE));
289 throw new IllegalArgumentException("rt & if is null");
292 CoapResponse response = makeDiscoveryResponse(request,
294 ctx.writeAndFlush(response);
296 throw new IllegalArgumentException("value of st is not corret");
302 * API for handling POST message(message to publish or update resources)
305 * ChannelHandlerContext of request message
307 * CoAP request message
310 public void handlePostRequest(ChannelHandlerContext ctx,
311 CoapRequest request) throws Exception {
313 HashMap<String, String> filters = extractFiltersFromQuery(
314 request.getUriQuerySegments());
316 if (filters == null) {
317 throw new IllegalArgumentException("filters is null");
318 } else if (filters.get(Constants.RS_RESOURCE_TYPE) == null) {
319 throw new IllegalArgumentException("rt is null");
320 } else if (filters.get(Constants.RS_RESOURCE_TYPE)
321 .equals(Constants.RS_RESOURCE_TYPE_RDPUBLISH)) {
322 Logger.d("This request is publish msg!");
324 PublishPayloadFormat pubPayload = new PublishPayloadFormat();
326 ArrayList<Object> payloadData = cbor.parsePayloadFromCbor(
327 request.getPayload(), ArrayList.class);
329 if (payloadData == null) {
330 throw new IllegalArgumentException("parsed payload is null");
332 Logger.i("payloadData: " + payloadData.toString());
335 HashMap<Object, Object> tags = (HashMap<Object, Object>) payloadData
339 throw new IllegalArgumentException("tags is null!");
342 Object di = tags.get(Constants.RS_DEVICE_ID);
344 pubPayload.setDi(di.toString());
345 Logger.i("di : " + pubPayload.getDi());
347 throw new IllegalArgumentException("device id is null!");
350 Object deviceName = tags.get(Constants.RS_DEVICE_NAME);
351 if (deviceName != null) {
352 pubPayload.setDeviceName(deviceName.toString());
353 Logger.i("device name : " + pubPayload.getDeviceName());
356 Object baseUri = tags.get(Constants.RS_BASE_URI);
357 if (baseUri != null) {
358 pubPayload.setBaseUri(baseUri.toString());
359 Logger.i("baseURI : " + pubPayload.getBaseUri());
362 Object bitMap = tags.get(Constants.RS_BITMAP);
363 if (bitMap != null) {
364 pubPayload.setBitmap((int) bitMap);
365 Logger.i("bm : " + pubPayload.getBitmap());
368 Object hostingPort = tags.get(Constants.RS_HOSTING_PORT);
369 if (hostingPort != null) {
370 pubPayload.setPort((int) hostingPort);
371 Logger.i("port : " + pubPayload.getPort());
374 Object ins = tags.get(Constants.RS_INS);
376 pubPayload.setIns((int) ins);
377 Logger.i("ins : " + pubPayload.getIns());
380 Object rts = tags.get(Constants.RS_RTS);
382 pubPayload.setRts(rts.toString());
383 Logger.i("rts : " + pubPayload.getRts());
386 Object drel = tags.get(Constants.RS_DREL);
388 pubPayload.setDrel(drel.toString());
389 Logger.i("drel : " + pubPayload.getDrel());
392 // Object ttl = tags.get(Constants.RS_TTL);
393 // if (ttl != null) {
394 // pubPayload.setTtl((int) ttl);
395 // Logger.i("ttl : " + pubPayload.getTtl());
398 ArrayList<LinkedHashMap<Object, Object>> publishLinks = (ArrayList<LinkedHashMap<Object, Object>>) payloadData
401 if (publishLinks == null) {
402 throw new IllegalArgumentException("publishLinks is null!");
405 for (LinkedHashMap<Object, Object> o : publishLinks) {
407 LinksPayloadFormat storeLinks = new LinksPayloadFormat();
409 Object href = o.get(Constants.RS_HREF);
411 String prefix = "/" + pubPayload.getDi();
412 storeLinks.setHref(prefix + href.toString());
413 Logger.i("href : " + storeLinks.getHref());
416 if (o.get(Constants.RS_RESOURCE_TYPE) != null) {
417 Object obj = o.get(Constants.RS_RESOURCE_TYPE);
419 storeLinks.setRt((ArrayList<String>) obj);
421 Object rt = storeLinks.getRt();
423 Logger.i("rt : " + storeLinks.getRt().toString());
427 if (o.get(Constants.RS_INTERFACE) != null) {
429 (ArrayList<String>) o.get(Constants.RS_INTERFACE));
430 Object itf = storeLinks.getItf();
432 Logger.i("if : " + storeLinks.getItf().toString());
436 Object rel = o.get(Constants.RS_REL);
438 storeLinks.setRel(rel.toString());
439 Logger.i("rel : " + storeLinks.getRel());
442 if (o.get(Constants.RS_OBS) != null) {
443 Object obj = o.get(Constants.RS_OBS);
445 storeLinks.setObs((boolean) obj);
447 Logger.i("obs : " + storeLinks.isObs());
450 if (o.get(Constants.RS_TITLE) != null) {
451 Object obj = o.get(Constants.RS_TITLE);
453 storeLinks.setTitle(obj.toString());
455 Logger.i("title : " + storeLinks.getTitle());
458 if (o.get(Constants.RS_URI) != null) {
459 Object obj = o.get(Constants.RS_URI);
461 storeLinks.setUri(obj.toString());
463 Logger.i("uri : " + storeLinks.getUri());
466 if (o.get(Constants.RS_INS) != null) {
467 Object obj = o.get(Constants.RS_INS);
469 storeLinks.setIns((int) obj);
471 Logger.i("ins : " + storeLinks.getIns());
474 if (o.get(Constants.RS_MEDIA_TYPE) != null) {
475 Object obj = o.get(Constants.RS_MEDIA_TYPE);
477 storeLinks.setMt((ArrayList<String>) obj);
479 Object mt = storeLinks.getMt();
481 Logger.i("mt : " + mt.toString());
485 pubPayload.links.add(storeLinks);
488 mongoDB.createResource(pubPayload, Constants.RD_TABLE);
490 CoapResponse response = makePublishResponse(request);
491 ctx.writeAndFlush(response);
494 throw new IllegalArgumentException("rt is not correct");
499 * API for handling Delete message(message to delete published resources)
502 * ChannelHandlerContext of request message
504 * CoAP request message
507 public void handleDeleteRequest(ChannelHandlerContext ctx,
508 CoapRequest request) throws Exception {
509 HashMap<String, String> filters = extractFiltersFromQuery(
510 request.getUriQuerySegments());
512 if (filters == null) {
513 throw new IllegalArgumentException("filters is null");
514 } else if (filters.get(Constants.RS_DEVICE_ID) == null) {
515 throw new IllegalArgumentException("di is null");
517 if (filters.get(Constants.RS_INS) == null) {
518 mongoDB.deleteResourceAboutDid(
519 filters.get(Constants.RS_DEVICE_ID),
522 mongoDB.deleteResourceAboutDidAndIns(
523 filters.get(Constants.RS_DEVICE_ID),
524 filters.get(Constants.RS_INS), Constants.RD_TABLE);
526 CoapResponse response = makeDeleteResponse(request);
527 ctx.writeAndFlush(response);