9ba78a8544ef776a9e4e46bcf813aaf2420eaa17
[iotivity.git] / cloud / interface / src / main / java / org / iotivity / cloud / ciserver / resources / RouteResource.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2016 Samsung Electronics All Rights Reserved.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
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
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
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.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.ciserver.resources;
23
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.List;
28
29 import org.iotivity.cloud.base.OICConstants;
30 import org.iotivity.cloud.base.connector.ConnectorPool;
31 import org.iotivity.cloud.base.device.CoapDevice;
32 import org.iotivity.cloud.base.device.Device;
33 import org.iotivity.cloud.base.device.IRequestChannel;
34 import org.iotivity.cloud.base.device.IResponseEventHandler;
35 import org.iotivity.cloud.base.exception.ServerException;
36 import org.iotivity.cloud.base.protocols.IRequest;
37 import org.iotivity.cloud.base.protocols.IResponse;
38 import org.iotivity.cloud.base.protocols.MessageBuilder;
39 import org.iotivity.cloud.base.protocols.coap.CoapResponse;
40 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
41 import org.iotivity.cloud.base.protocols.enums.RequestMethod;
42 import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
43 import org.iotivity.cloud.base.resource.Resource;
44 import org.iotivity.cloud.ciserver.Constants;
45 import org.iotivity.cloud.ciserver.DeviceServerSystem.CoapDevicePool;
46 import org.iotivity.cloud.util.Cbor;
47
48 /**
49  *
50  * This class provides a set of APIs to send requests about message to another
51  * device
52  *
53  */
54 public class RouteResource extends Resource {
55
56     private CoapDevicePool                mDevicePool = null;
57     private IRequestChannel               mASServer   = null;
58     private Cbor<HashMap<String, Object>> mCbor       = new Cbor<>();
59
60     public RouteResource(CoapDevicePool devicePool) {
61         super(Arrays.asList(Constants.PREFIX_OIC, Constants.REQ_DEVICE_ROUTE));
62         mASServer = ConnectorPool.getConnection("account");
63         mDevicePool = devicePool;
64     }
65
66     private IRequestChannel getTargetDeviceChannel(IRequest request)
67             throws ServerException {
68
69         CoapDevice targetDevice = (CoapDevice) mDevicePool
70                 .queryDevice(getDeviceId(request));
71
72         if (targetDevice == null) {
73             return null;
74         }
75
76         // Do request and receive response
77         return targetDevice.getRequestChannel();
78     }
79
80     private String extractTargetUriPath(IRequest request) {
81         List<String> uriPathSegment = request.getUriPathSegments();
82
83         // Remove prefix path
84         for (String path : getUriPathSegments()) {
85             uriPathSegment.remove(path);
86         }
87         uriPathSegment.remove(0);
88
89         StringBuilder uriPath = new StringBuilder();
90         for (String path : uriPathSegment) {
91             uriPath.append("/" + path);
92         }
93
94         return uriPath.toString();
95     }
96
97     private IResponse convertReponseUri(IResponse response, String di) {
98
99         String convertedUri = new String();
100
101         CoapResponse coapResponse = (CoapResponse) response;
102
103         StringBuilder uriPath = new StringBuilder();
104         for (String path : getUriPathSegments()) {
105             uriPath.append("/" + path);
106         }
107
108         if (coapResponse.getUriPath().isEmpty() == false) {
109             convertedUri = uriPath.toString() + "/" + di
110                     + coapResponse.getUriPath();
111         }
112
113         return MessageBuilder.modifyResponse(response, convertedUri, null,
114                 null);
115     }
116
117     private String getDeviceId(IRequest request) {
118         return request.getUriPathSegments().get(getUriPathSegments().size());
119     }
120
121     /**
122      *
123      * This class provides a set of APIs to handling message contains link
124      * interface.
125      *
126      */
127     class LinkInterfaceHandler implements IResponseEventHandler {
128         private Cbor<List<HashMap<String, Object>>> mCbor      = new Cbor<>();
129         private String                              mTargetDI  = null;
130         private Device                              mSrcDevice = null;
131         private IRequest                            mRequest   = null;
132
133         public LinkInterfaceHandler(String targetDI, Device srcDevice,
134                 IRequest request) {
135             mTargetDI = targetDI;
136             mSrcDevice = srcDevice;
137             mRequest = request;
138         }
139
140         private void convertHref(List<HashMap<String, Object>> linkPayload) {
141
142             StringBuilder uriPath = new StringBuilder();
143             for (String path : getUriPathSegments()) {
144                 uriPath.append("/" + path);
145             }
146
147             for (HashMap<String, Object> link : linkPayload) {
148                 link.put("href", uriPath.toString() + "/" + mTargetDI
149                         + link.get("href"));
150             }
151         }
152
153         @Override
154         public void onResponseReceived(IResponse response) {
155             List<HashMap<String, Object>> linkPayload = null;
156             if (response.getStatus().equals(ResponseStatus.CONTENT)) {
157                 linkPayload = mCbor.parsePayloadFromCbor(response.getPayload(),
158                         ArrayList.class);
159                 if (linkPayload == null) {
160                     mSrcDevice.sendResponse(MessageBuilder.createResponse(
161                             mRequest, ResponseStatus.NOT_FOUND));
162                 }
163                 convertHref(linkPayload);
164             }
165             mSrcDevice.sendResponse(MessageBuilder.modifyResponse(
166                     convertReponseUri(response, mTargetDI),
167                     ContentFormat.APPLICATION_CBOR, linkPayload != null
168                             ? mCbor.encodingPayloadToCbor(linkPayload) : null));
169         }
170     }
171
172     class DefaultResponseHandler implements IResponseEventHandler {
173         private String mTargetDI  = null;
174         private Device mSrcDevice = null;
175
176         public DefaultResponseHandler(String targetDI, Device srcDevice) {
177             mTargetDI = targetDI;
178             mSrcDevice = srcDevice;
179         }
180
181         @Override
182         public void onResponseReceived(IResponse response) {
183
184             mSrcDevice.sendResponse(convertReponseUri(response, mTargetDI));
185         }
186     }
187
188     class AccountReceiveHandler implements IResponseEventHandler {
189         private IRequest mRequest   = null;
190         private Device   mSrcDevice = null;
191
192         public AccountReceiveHandler(Device srcDevice, IRequest request) {
193             mRequest = request;
194             mSrcDevice = srcDevice;
195         }
196
197         @Override
198         public void onResponseReceived(IResponse response) {
199             switch (response.getStatus()) {
200                 case CONTENT:
201                     HashMap<String, Object> payloadData = mCbor
202                             .parsePayloadFromCbor(response.getPayload(),
203                                     HashMap.class);
204                     checkPayloadException(Constants.RESP_GRANT_POLICY,
205                             payloadData);
206                     String gp = (String) payloadData
207                             .get(Constants.RESP_GRANT_POLICY);
208                     verifyRequest(mSrcDevice, mRequest, gp);
209                     break;
210
211                 default:
212                     mSrcDevice.sendResponse(response);
213             }
214
215         }
216     }
217
218     private void verifyRequest(Device srcDevice, IRequest request,
219             String grantPermisson) {
220         switch (grantPermisson) {
221             case Constants.RESP_ACL_DENIED:
222                 srcDevice.sendResponse(MessageBuilder.createResponse(request,
223                         ResponseStatus.UNAUTHORIZED));
224                 break;
225
226             case Constants.RESP_ACL_ALLOWED:
227                 IRequestChannel requestChannel = getTargetDeviceChannel(
228                         request);
229
230                 if (requestChannel == null) {
231                     srcDevice.sendResponse(MessageBuilder
232                             .createResponse(request, ResponseStatus.NOT_FOUND));
233                     break;
234                 }
235
236                 IResponseEventHandler responseHandler = new DefaultResponseHandler(
237                         getDeviceId(request), srcDevice);
238                 if (request.getUriQuery() != null && request.getUriQuery()
239                         .contains(Constants.LINK_INTERFACE)) {
240                     responseHandler = new LinkInterfaceHandler(
241                             getDeviceId(request), srcDevice, request);
242                 }
243
244                 String uriPath = extractTargetUriPath(request);
245                 IRequest requestToResource = MessageBuilder
246                         .modifyRequest(request, uriPath, null, null, null);
247
248                 requestChannel.sendRequest(requestToResource, responseHandler);
249                 break;
250         }
251     }
252
253     @Override
254     public void onDefaultRequestReceived(Device srcDevice, IRequest request)
255             throws ServerException {
256         // verify Permission
257         StringBuffer uriQuery = new StringBuffer();
258         uriQuery.append(Constants.REQ_SEARCH_USER_ID + "="
259                 + srcDevice.getUserId() + ";");
260         uriQuery.append(
261                 Constants.REQ_DEVICE_ID + "=" + getDeviceId(request) + ";");
262         uriQuery.append(
263                 Constants.REQ_REQUEST_METHOD + "=" + request.getMethod() + ";");
264         uriQuery.append(Constants.REQ_REQUEST_URI + "="
265                 + extractTargetUriPath(request));
266
267         IRequest verifyRequest = MessageBuilder.createRequest(RequestMethod.GET,
268                 OICConstants.ACL_VERIFY_FULL_URI, uriQuery.toString());
269
270         mASServer.sendRequest(verifyRequest,
271                 new AccountReceiveHandler(srcDevice, request));
272     }
273 }