1be0ebf6283e047115d9798dddc99c40e3866446
[iotivity.git] / cloud / interface / src / main / java / org / iotivity / cloud / ciserver / resources / proxy / rd / ResourceDirectory.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.proxy.rd;
23
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27
28 import org.iotivity.cloud.base.connector.ConnectorPool;
29 import org.iotivity.cloud.base.device.Device;
30 import org.iotivity.cloud.base.device.IRequestChannel;
31 import org.iotivity.cloud.base.device.IResponseEventHandler;
32 import org.iotivity.cloud.base.exception.ClientException;
33 import org.iotivity.cloud.base.exception.ServerException;
34 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
35 import org.iotivity.cloud.base.protocols.IRequest;
36 import org.iotivity.cloud.base.protocols.IResponse;
37 import org.iotivity.cloud.base.protocols.MessageBuilder;
38 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
39 import org.iotivity.cloud.base.protocols.enums.RequestMethod;
40 import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
41 import org.iotivity.cloud.base.resource.Resource;
42 import org.iotivity.cloud.ciserver.Constants;
43 import org.iotivity.cloud.util.Cbor;
44
45 /**
46  *
47  * This class provides a set of APIs to send requests about publish resource to
48  * resource directory
49  *
50  */
51
52 public class ResourceDirectory extends Resource {
53     private Cbor<HashMap<String, Object>> mCbor     = new Cbor<>();
54     IRequestChannel                       mRDServer = null;
55     IRequestChannel                       mASServer = null;
56
57     public ResourceDirectory() {
58         super(Arrays.asList(Constants.PREFIX_OIC, Constants.RD_URI));
59         mRDServer = ConnectorPool.getConnection("rd");
60         mASServer = ConnectorPool.getConnection("account");
61     }
62
63     @Override
64     public void onDefaultRequestReceived(Device srcDevice, IRequest request)
65             throws ServerException {
66         switch (request.getMethod()) {
67             case POST:
68                 HashMap<String, Object> payloadData = mCbor
69                         .parsePayloadFromCbor(request.getPayload(),
70                                 HashMap.class);
71                 StringBuffer query = new StringBuffer();
72                 query.append("op=add;");
73                 query.append(Constants.USER_ID + "=" + srcDevice.getUserId());
74
75                 StringBuffer uriPath = new StringBuffer();
76                 uriPath.append(Constants.PREFIX_OIC + "/");
77                 uriPath.append(Constants.ACL_URI + "/");
78                 uriPath.append(Constants.GROUP_URI + "/");
79                 uriPath.append(srcDevice.getUserId());
80
81                 String di = payloadData.get(Constants.REQ_DEVICE_ID).toString();
82                 HashMap<String, Object> requestPayload = new HashMap<>();
83
84                 requestPayload.put(Constants.REQ_GROUP_DEVICES,
85                         Arrays.asList(di));
86                 IRequest requestToAS = MessageBuilder.createRequest(
87                         RequestMethod.POST, uriPath.toString(),
88                         query.toString(), ContentFormat.APPLICATION_CBOR,
89                         mCbor.encodingPayloadToCbor(requestPayload));
90
91                 mASServer.sendRequest(requestToAS,
92                         new AccountReceiveHandler(request, srcDevice));
93                 break;
94
95             case DELETE:
96                 mRDServer.sendRequest(request, srcDevice);
97                 break;
98             default:
99                 throw new BadRequestException(
100                         request.getMethod() + " request type is not support");
101         }
102     }
103
104     class AccountReceiveHandler implements IResponseEventHandler {
105         private Device   mSrcDevice;
106         private IRequest mRequest;
107
108         public AccountReceiveHandler(IRequest request, Device srcDevice) {
109             mSrcDevice = srcDevice;
110             mRequest = request;
111         }
112
113         @Override
114         public void onResponseReceived(IResponse response)
115                 throws ClientException {
116
117             switch (response.getStatus()) {
118                 case CHANGED:
119
120                     byte[] convertedPayload = convertPublishHref(mRequest,
121                             mSrcDevice);
122
123                     if (convertedPayload == null) {
124
125                         mSrcDevice.sendResponse(MessageBuilder.createResponse(
126                                 mRequest, ResponseStatus.PRECONDITION_FAILED));
127                     }
128
129                     mRequest = MessageBuilder.modifyRequest(mRequest, null,
130                             null, ContentFormat.APPLICATION_CBOR,
131                             convertedPayload);
132
133                     mRDServer.sendRequest(mRequest,
134                             new PublishResponseHandler(mSrcDevice));
135                     break;
136
137                 default:
138                     mSrcDevice.sendResponse(MessageBuilder.createResponse(
139                             mRequest, ResponseStatus.BAD_REQUEST));
140             }
141         }
142
143         @SuppressWarnings("unchecked")
144         private byte[] convertPublishHref(IRequest request, Device device) {
145
146             Cbor<HashMap<String, Object>> cbor = new Cbor<>();
147             HashMap<String, Object> payload = cbor
148                     .parsePayloadFromCbor(request.getPayload(), HashMap.class);
149
150             if (verifyPublishPayload(payload) == false) {
151
152                 return null;
153             }
154
155             ArrayList<HashMap<String, Object>> links = (ArrayList<HashMap<String, Object>>) payload
156                     .get(Constants.REQ_LINKS);
157
158             for (HashMap<String, Object> link : links) {
159
160                 String href = (String) link.get(Constants.REQ_HREF);
161                 href = "/di/" + device.getDeviceId() + href;
162
163                 link.put(Constants.REQ_HREF, href);
164             }
165
166             payload.put(Constants.REQ_LINKS, links);
167
168             return cbor.encodingPayloadToCbor(payload);
169         }
170
171         @SuppressWarnings("unchecked")
172         private boolean verifyPublishPayload(HashMap<String, Object> payload) {
173
174             ArrayList<HashMap<String, Object>> links = (ArrayList<HashMap<String, Object>>) payload
175                     .get(Constants.REQ_LINKS);
176
177             if (links == null || links.isEmpty()) {
178                 return false;
179             }
180
181             for (HashMap<String, Object> link : links) {
182
183                 String href = (String) link.get(Constants.REQ_HREF);
184
185                 if (href == null || href.isEmpty()) {
186                     return false;
187                 }
188             }
189
190             return true;
191         }
192     }
193
194     // handles response to convert href in response payload into original href
195     // when resource published or updated
196     class PublishResponseHandler implements IResponseEventHandler {
197
198         private Device mSrcDevice;
199
200         public PublishResponseHandler(Device srcDevice) {
201             mSrcDevice = srcDevice;
202         }
203
204         @Override
205         public void onResponseReceived(IResponse response)
206                 throws ClientException {
207
208             switch (response.getStatus()) {
209                 case CHANGED:
210
211                     response = MessageBuilder.modifyResponse(response,
212                             ContentFormat.APPLICATION_CBOR,
213                             convertResponseHref(response));
214
215                 default:
216
217                     mSrcDevice.sendResponse(response);
218             }
219         }
220
221         @SuppressWarnings("unchecked")
222         private byte[] convertResponseHref(IResponse response) {
223
224             Cbor<HashMap<String, Object>> cbor = new Cbor<>();
225             HashMap<String, Object> payload = cbor
226                     .parsePayloadFromCbor(response.getPayload(), HashMap.class);
227
228             ArrayList<HashMap<String, Object>> links = (ArrayList<HashMap<String, Object>>) payload
229                     .get(Constants.REQ_LINKS);
230
231             for (HashMap<String, Object> link : links) {
232
233                 String href = (String) link.get(Constants.REQ_HREF);
234
235                 // remove prefix
236                 ArrayList<String> hrefSegments = new ArrayList<>(
237                         Arrays.asList(href.split("/")));
238                 for (int i = 0; i < 3; i++) {
239                     hrefSegments.remove(0);
240                 }
241
242                 StringBuilder newHref = new StringBuilder();
243                 for (String path : hrefSegments) {
244                     newHref.append("/" + path);
245                 }
246
247                 link.put(Constants.REQ_HREF, newHref.toString());
248             }
249
250             payload.put(Constants.REQ_LINKS, links);
251
252             return cbor.encodingPayloadToCbor(payload);
253         }
254     }
255
256 }