IOT-3143
[iotivity.git] / cloud / account / src / main / java / org / iotivity / cloud / accountserver / resources / acl / id / Acl.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.accountserver.resources.acl.id;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.ListIterator;
29 import java.util.UUID;
30
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.iotivity.cloud.accountserver.Constants;
34 import org.iotivity.cloud.accountserver.db.AccountDBManager;
35 import org.iotivity.cloud.accountserver.db.AclTable;
36 import org.iotivity.cloud.accountserver.util.TypeCastingManager;
37 import org.iotivity.cloud.base.device.Device;
38 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
39 import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException;
40 import org.iotivity.cloud.base.exception.ServerException.UnAuthorizedException;
41 import org.iotivity.cloud.base.protocols.IRequest;
42 import org.iotivity.cloud.base.protocols.MessageBuilder;
43 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
44 import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
45 import org.iotivity.cloud.util.Cbor;
46
47 public class Acl {
48     private final static Logger           Log      = LoggerFactory.getLogger(Acl.class);
49     private Cbor<HashMap<String, Object>> mCbor    = new Cbor<>();
50     private String                        mAclid   = null;
51     private String                        mOid     = null;
52     private String                        mDi      = null;
53     private TypeCastingManager<AclTable>  mTypeAcl = new TypeCastingManager<>();
54
55     public Acl(String aclid) {
56         mAclid = aclid;
57     }
58
59     public Acl(String aclid, String oid, String di) {
60         mAclid = aclid;
61         mOid = oid;
62         mDi = di;
63     }
64
65     private static class AclSubscriber {
66         AclSubscriber(Device subscriber, IRequest request) {
67             mSubscriber = subscriber;
68             mRequest = request;
69         }
70
71         public Device   mSubscriber;
72         public IRequest mRequest;
73     }
74
75     private HashMap<String, AclSubscriber> mSubscribers = new HashMap<>();
76
77     public static String valueOf(Object object) {
78         return (object == null) ? "" : object.toString();
79     }
80
81     public static Acl convertMaptoAcl(HashMap<String, Object> aclMap) {
82         return new Acl(
83                 valueOf(aclMap.get(Constants.KEYFIELD_ACLID)),
84                 valueOf(aclMap.get(Constants.REQ_OWNER_ID)),
85                 valueOf(aclMap.get(Constants.KEYFIELD_DI)));
86     }
87
88     @SuppressWarnings("unchecked")
89     public static AclTable convertMaptoAclTable(
90             HashMap<String, Object> aclMap) {
91         AclTable aclTable = new AclTable();
92         try {
93             aclTable.setAclid(valueOf(aclMap.get(Constants.KEYFIELD_ACLID)));
94             aclTable.setDi(valueOf(aclMap.get(Constants.KEYFIELD_DI)));
95             aclTable.setOid(valueOf(aclMap.get(Constants.REQ_OWNER_ID)));
96             aclTable.setRowneruuid(
97                     valueOf(aclMap.get(Constants.REQ_ROWNER_ID)));
98
99             List<Ace> aceList = new ArrayList<Ace>();
100
101             List<HashMap<String, Object>> aclist = (List<HashMap<String, Object>>) aclMap
102                     .get(Constants.REQ_ACL_LIST);
103
104             if (aclist == null) {
105                 return aclTable;
106             }
107
108             for (HashMap<String, Object> eachAce : aclist) {
109
110                 Ace ace = new Ace();
111
112                 ace.setAceid(valueOf(eachAce.get(Constants.REQ_ACE_ID)));
113                 ace.setSubjectuuid(valueOf(
114                         eachAce.get(Constants.KEYFIELD_ACE_SUBJECT_ID)));
115                 ace.setStype(Integer.valueOf(eachAce
116                         .get(Constants.KEYFIELD_ACE_SUBJECT_TYPE).toString()));
117                 ace.setPermission(Integer.valueOf(eachAce
118                         .get(Constants.KEYFIELD_ACE_PERMISSION).toString()));
119
120                 Object validity = eachAce.get(Constants.KEYFIELD_ACE_VALIDITY);
121                 if (validity != null) {
122                     ace.setValidity((List<String>) validity);
123                 }
124
125                 List<AceResource> resourceLst = new ArrayList<AceResource>();
126                 List<HashMap<String, Object>> resourceList = (List<HashMap<String, Object>>) eachAce
127                         .get(Constants.KEYFIELD_ACE_RESOURCE);
128                 for (HashMap<String, Object> resrouce : resourceList) {
129
130                     AceResource aceResource = new AceResource();
131                     aceResource.setHref(valueOf(resrouce
132                             .get(Constants.KEYFIELD_ACE_RESOURCE_HREF)));
133                     List<String> rtList = (List<String>) resrouce
134                             .get(Constants.KEYFIELD_ACE_RESOURCE_RT);
135                     aceResource.setRt(rtList);
136                     List<String> ifList = (List<String>) resrouce
137                             .get(Constants.KEYFIELD_ACE_RESOURCE_IF);
138                     aceResource.setOicif(ifList);
139
140                     resourceLst.add(aceResource);
141                 }
142                 ace.setResources(resourceLst);
143
144                 aceList.add(ace);
145
146             }
147             aclTable.setAclist(aceList);
148         } catch (Exception e) {
149             throw new InternalServerErrorException(
150                     "Map to Acl Object casting error " + e.getMessage());
151         }
152         return aclTable;
153
154     }
155
156     @SuppressWarnings("unchecked")
157
158     public List<HashMap<String, Object>> addACE(
159             List<HashMap<String, Object>> aclist) {
160         Log.trace("IN addACE");
161         HashMap<String, Object> hashmap = AccountDBManager.getInstance()
162                 .selectRecord(Constants.ACL_TABLE, getCondition()).get(0);
163         if (hashmap == null) {
164             throw new BadRequestException("aclid is invalid");
165         }
166         List<HashMap<String, Object>> aclDbList = (List<HashMap<String, Object>>) hashmap
167                 .get(Constants.REQ_ACL_LIST);
168
169         ListIterator<HashMap<String, Object>> iterator = aclist.listIterator();
170         while (iterator.hasNext()) {
171             HashMap<String, Object> aceMap = iterator.next();
172             if (aceMap.get(Constants.KEYFIELD_ACE_SUBJECT_ID)
173                     .equals(hashmap.get(Constants.REQ_OWNER_ID))) {
174                 // remove current iterator
175                 iterator.remove();
176                 continue;
177             }
178             aceMap.put(Constants.REQ_ACE_ID, UUID.randomUUID().toString());
179         }
180
181         List<HashMap<String, Object>> newAcList = new ArrayList<HashMap<String, Object>>(
182                 aclist);
183
184         if (aclDbList != null) {
185             newAcList.addAll(aclDbList);
186         }
187         hashmap.put(Constants.REQ_ACL_LIST, newAcList);
188         AccountDBManager.getInstance().updateRecord(Constants.ACL_TABLE,
189                 hashmap);
190         notifyToSubscriber(getResponsePayload(true));
191         Log.trace("OUT addACE");
192         return aclist;
193     }
194
195     public HashMap<String, Object> getACE(String aceid) {
196         HashMap<String, Object> hashmap = AccountDBManager.getInstance()
197                 .selectRecord(Constants.ACL_TABLE, getCondition()).get(0);
198         if (hashmap == null) {
199             throw new BadRequestException("aclid is invalid");
200         }
201
202         List<HashMap<String, Object>> aclDbList = (List<HashMap<String, Object>>) hashmap
203                 .get(Constants.REQ_ACL_LIST);
204         ListIterator<HashMap<String, Object>> iterator = aclDbList
205                 .listIterator();
206         while (iterator.hasNext()) {
207             HashMap<String, Object> aceMap = iterator.next();
208             if (aceMap.get(Constants.REQ_ACE_ID).equals(aceid)) {
209                 // Return the current element from the iterator
210                 return aceMap;
211             }
212         }
213         throw new BadRequestException("aceid is invalid");
214     }
215
216     public boolean isValidAceId(String aceid) {
217         HashMap<String, Object> hashmap = AccountDBManager.getInstance()
218                 .selectRecord(Constants.ACL_TABLE, getCondition()).get(0);
219         if (hashmap == null) {
220             return false;
221         }
222
223         List<HashMap<String, Object>> aclDbList = (List<HashMap<String, Object>>) hashmap
224                 .get(Constants.REQ_ACL_LIST);
225         ListIterator<HashMap<String, Object>> iterator = aclDbList
226                 .listIterator();
227         while (iterator.hasNext()) {
228             HashMap<String, Object> aceMap = iterator.next();
229             if (aceMap.get(Constants.REQ_ACE_ID).equals(aceid)) {
230                 return true;
231             }
232         }
233         return false;
234     }
235
236     public void updateACE(String aceid, HashMap<String, Object> ace) {
237         Log.trace("IN updateACE");
238
239         HashMap<String, Object> hashmap = AccountDBManager.getInstance()
240                 .selectRecord(Constants.ACL_TABLE, getCondition()).get(0);
241
242         List<HashMap<String, Object>> aclDbList = (List<HashMap<String, Object>>) hashmap
243                 .get(Constants.REQ_ACL_LIST);
244
245         ace.put(Constants.REQ_ACE_ID, aceid);
246
247         ListIterator<HashMap<String, Object>> iterator = aclDbList
248                 .listIterator();
249         while (iterator.hasNext()) {
250             HashMap<String, Object> aceMap = iterator.next();
251             if (aceMap.get(Constants.REQ_ACE_ID).equals(aceid)) {
252                 // replace current iterator with new element
253                 iterator.set(ace);
254                 break;
255             }
256         }
257
258         hashmap.put(Constants.REQ_ACL_LIST, aclDbList);
259         AccountDBManager.getInstance().updateRecord(Constants.ACL_TABLE,
260                 hashmap);
261         notifyToSubscriber(getResponsePayload(true));
262         Log.trace("OUT updateACE");
263
264     }
265
266     public void deleteACE(String aceid) {
267
268         HashMap<String, Object> hashmap = AccountDBManager.getInstance()
269                 .selectRecord(Constants.ACL_TABLE, getCondition()).get(0);
270
271         List<HashMap<String, Object>> aclDbList = (List<HashMap<String, Object>>) hashmap
272                 .get(Constants.REQ_ACL_LIST);
273
274         ListIterator<HashMap<String, Object>> iterator = aclDbList
275                 .listIterator();
276         while (iterator.hasNext()) {
277             HashMap<String, Object> aceMap = iterator.next();
278             if (aceMap.get(Constants.REQ_ACE_ID).equals(aceid)) {
279                 // Remove the current element from the iterator
280                 iterator.remove();
281                 break;
282             }
283         }
284
285         hashmap.put(Constants.REQ_ACL_LIST, aclDbList);
286         AccountDBManager.getInstance().updateRecord(Constants.ACL_TABLE,
287                 hashmap);
288         notifyToSubscriber(getResponsePayload(true));
289     }
290
291     public void deleteAclist() {
292         AclTable aclTable = getAclTable();
293         aclTable.setAclist(null);
294         AccountDBManager.getInstance().updateRecord(Constants.ACL_TABLE,
295                 mTypeAcl.convertObjectToMap(aclTable));
296         notifyToSubscriber(getResponsePayload(true));
297     }
298
299     public HashMap<String, Object> getInfo() {
300         return getResponsePayload(true);
301     }
302
303     public HashMap<String, Object> addSubscriber(String di, Device subscriber,
304             IRequest request) {
305
306         verifyAclTableDi(di);
307         AclSubscriber newSubscriber = new AclSubscriber(subscriber, request);
308         mSubscribers.put(di, newSubscriber);
309         return getInfo();
310     }
311
312     public HashMap<String, Object> removeSubscriber(String di) {
313
314         HashMap<String, Object> responsePayload = getResponsePayload(true);
315         if (mSubscribers.containsKey(di)) {
316             mSubscribers.remove(di);
317         }
318         return responsePayload;
319     }
320
321     private void verifyAclTableDi(String di) {
322         AclTable aclTable = getAclTable();
323         if (aclTable.getDi() == null) {
324             throw new BadRequestException("di is invalid in Acl");
325         }
326         String mDi = aclTable.getDi();
327         if (!mDi.equals(di)) {
328             throw new UnAuthorizedException(
329                     di + "is not Device ID of this ACL");
330         }
331     }
332
333     private void notifyToSubscriber(
334             HashMap<String, Object> notifyBytePayloadData) {
335         synchronized (mSubscribers) {
336
337             Iterator<String> iterator = mSubscribers.keySet().iterator();
338             while (iterator.hasNext()) {
339                 String key = iterator.next();
340                 AclSubscriber aclSubscriber = mSubscribers.get(key);
341                 aclSubscriber.mSubscriber.sendResponse(
342                         MessageBuilder.createResponse(aclSubscriber.mRequest,
343                                 ResponseStatus.CONTENT,
344                                 ContentFormat.APPLICATION_CBOR,
345                                 mCbor.encodingPayloadToCbor(
346                                         notifyBytePayloadData)));
347             }
348         }
349     }
350
351     private AclTable getAclTable() {
352         AclTable getAclTable = new AclTable();
353         getAclTable = convertMaptoAclTable(AccountDBManager.getInstance()
354                 .selectRecord(Constants.ACL_TABLE, getCondition()).get(0));
355         return getAclTable;
356     }
357
358     private HashMap<String, Object> getAclTablePayLoad() {
359         HashMap<String, Object> aclPayload = new HashMap<>();
360         aclPayload = AccountDBManager.getInstance()
361                 .selectRecord(Constants.ACL_TABLE, getCondition()).get(0);
362         return aclPayload;
363     }
364
365     private HashMap<String, Object> getResponsePayload(boolean isAliveAcl) {
366         return isAliveAcl ? getAclTablePayLoad() : null;
367     }
368
369     private HashMap<String, Object> getCondition() {
370         HashMap<String, Object> condition = new HashMap<>();
371         condition.put(Constants.REQ_ACL_ID, mAclid);
372         return condition;
373     }
374
375 }