From: Jee Hyeok Kim Date: Thu, 20 Oct 2016 09:00:19 +0000 (+0900) Subject: Merge 1.2-rel cloud project into master X-Git-Tag: 1.3.0~1054^2~134 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8811eb919e6e92b52c8b646027a709e7d6030f3e;p=platform%2Fupstream%2Fiotivity.git Merge 1.2-rel cloud project into master 1. Overwrite 1.2-rel cloud project into master Change-Id: I9271607595166fce4bda9011f028a40514908fec Signed-off-by: Jee Hyeok Kim Reviewed-on: https://gerrit.iotivity.org/gerrit/13487 Tested-by: jenkins-iotivity Reviewed-by: Yeonghun Nam --- diff --git a/cloud/account/README b/cloud/account/README index 37d1215..c5cd318 100644 --- a/cloud/account/README +++ b/cloud/account/README @@ -18,7 +18,9 @@ Build and Run - The CloudAccount-0.0.1-SNAPSHOT.jar file will be placed in the "target" folder -4) Run .jar file +4) Copy the "properties" folder to inside the "target" folder + +5) Run .jar file go to "target" folder $ java -jar CloudAccount-0.0.1-SNAPSHOT.jar arg1(AccountServer CoAP Server Port) arg2(TLS mode required) @@ -31,3 +33,6 @@ Build and Run - Before you run a Accout server, You need to set up following steps. 1) Install MongoDB 2) Install Github certificates for github.com and *.github.com. +5) Please download: file from http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html: Java Cryptography Extension + 1.Extract files from zip. + 2.Place local_policy.jar and US_export_policy.jar files in/usr/lib/jvm/PATH_TO_JDK/jre/lib/security diff --git a/cloud/account/properties/config.properties b/cloud/account/properties/config.properties index 73d9aaa..9e82e75 100644 --- a/cloud/account/properties/config.properties +++ b/cloud/account/properties/config.properties @@ -1,17 +1,18 @@ #New Serial number -#Wed Sep 07 17:08:34 EEST 2016 +#Tue Sep 27 16:11:46 EEST 2016 keyGeneratorAlgorithm=ECDSA notAfterInterval=20 securityProvider=BC ellipticCurve=secp256r1 +keystoreDir=keystore keyStoreLocation=keystore{0}certificateStorage.jks +keystoreType=BKS nextUpdateInterval=1 signatureAlgorithm=SHA256withECDSA -keystoreType=BKS rootOU=OCF Sub CA -serialNumber=515 +serialNumber=0 rootO=Samsung -caAlias=uuid\:31313131-3131-3131-3131-313131313131 subjectName=uuid\:31313131-3131-3131-3131-313131313131 +caAlias=uuid\:31313131-3131-3131-3131-313131313131 password=PASSWORD rootC=KR diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/AccountServer.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/AccountServer.java index b7fe164..f2830e5 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/AccountServer.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/AccountServer.java @@ -74,10 +74,6 @@ public class AccountServer { serverSystem.addResource(new AclResource()); - serverSystem.addResource(new CrlResource()); - - serverSystem.addResource(new AclResource()); - serverSystem.addResource(new InviteResource()); serverSystem.addServer(new CoapServer( diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/Constants.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/Constants.java index 092de7e..67fac58 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/Constants.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/Constants.java @@ -21,222 +21,232 @@ */ package org.iotivity.cloud.accountserver; -import org.iotivity.cloud.base.OICConstants; - import java.io.File; +import org.iotivity.cloud.base.OICConstants; + public class Constants extends OICConstants { - public static final String PROPERTIES_FILE_NAME = "properties" + public static final String PROPERTIES_FILE_NAME = "properties" + File.separator + "config.properties"; // Database name - public static final String DB_NAME = "ACCOUNTSERVER_DB"; + public static final String DB_NAME = "ACCOUNTSERVER_DB"; // Database table - public static final String CRL_TABLE = "CRL_TABLE"; + public static final String CRL_TABLE = "CRL_TABLE"; - public static final String CERTIFICATE_TABLE = "CERTIFICATE_TABLE"; + public static final String CERTIFICATE_TABLE = "CERTIFICATE_TABLE"; - public static final String USER_TABLE = "USER_TABLE"; + public static final String USER_TABLE = "USER_TABLE"; - public static final String TOKEN_TABLE = "TOKEN_TABLE"; + public static final String TOKEN_TABLE = "TOKEN_TABLE"; - public static final String GROUP_TABLE = "GROUP_TABLE"; + public static final String GROUP_TABLE = "GROUP_TABLE"; - public static final String INVITE_TABLE = "INVITE_TABLE"; + public static final String INVITE_TABLE = "INVITE_TABLE"; - public static final String DEVICE_TABLE = "DEVICE_TABLE"; + public static final String DEVICE_TABLE = "DEVICE_TABLE"; - public static final String ACL_TABLE = "ACL_TABLE"; + public static final String ACL_TABLE = "ACL_TABLE"; - public static final String ACLTEMPLATE_TABLE = "ACLTEMPLATE_TABLE"; + public static final String ACLTEMPLATE_TABLE = "ACLTEMPLATE_TABLE"; // Database table key - public static final String KEYFIELD_SN = "serialNumber"; + public static final String KEYFIELD_SN = "serialNumber"; - public static final String KEYFIELD_NA = "notAfter"; + public static final String KEYFIELD_NA = "notAfter"; - public static final String KEYFIELD_NB = "notBefore"; + public static final String KEYFIELD_NB = "notBefore"; - public static final String KEYFIELD_REVOKED = "revoked"; + public static final String KEYFIELD_REVOKED = "revoked"; - public static final String KEYFIELD_UUID = "uuid"; + public static final String KEYFIELD_UUID = "uuid"; - public static final String KEYFIELD_ACCESSTOKEN = "accesstoken"; + public static final String KEYFIELD_ACCESSTOKEN = "accesstoken"; - public static final String KEYFIELD_GID = "gid"; + public static final String KEYFIELD_GID = "gid"; - public static final String KEYFIELD_DID = "did"; + public static final String KEYFIELD_DID = "did"; - public static final String KEYFIELD_ACLID = "aclid"; + public static final String KEYFIELD_ACLID = "aclid"; - public static final String KEYFIELD_DI = "di"; + public static final String KEYFIELD_DI = "di"; - public static final String KEYFIELD_GTYPE = "gtype"; + public static final String KEYFIELD_GTYPE = "gtype"; - public static final String KEYFIELD_GIDLIST = "gidlist"; + public static final String KEYFIELD_GIDLIST = "gidlist"; - public static final String KEYFIELD_MIDLIST = "midlist"; + public static final String KEYFIELD_MIDLIST = "midlist"; - public static final String KEYFIELD_GACL = "gacl"; + public static final String KEYFIELD_GACL = "gacl"; - public static final String KEYFIELD_USERID = "userid"; + public static final String KEYFIELD_USERID = "userid"; - public static final String KEYFIELD_PROVIDER = "provider"; + public static final String KEYFIELD_PROVIDER = "provider"; - public static final String KEYFIELD_ISSUED_TIME = "issuedtime"; + public static final String KEYFIELD_ISSUED_TIME = "issuedtime"; - public static final String KEYFIELD_EXPIRED_TIME = "expiredtime"; + public static final String KEYFIELD_EXPIRED_TIME = "expiredtime"; - public static final String KEYFIELD_INVITE_USER = "inviteUser"; + public static final String KEYFIELD_INVITE_USER = "inviteUser"; - public static final String KEYFIELD_INVITED_USER = "invitedUser"; + public static final String KEYFIELD_INVITED_USER = "invitedUser"; - public static final String KEYFIELD_ACE_SUBJECT_ID = "subjectuuid"; + public static final String KEYFIELD_ACE_SUBJECT_ID = "subjectuuid"; - public static final String KEYFIELD_ACE_SUBJECT_TYPE = "stype"; + public static final String KEYFIELD_ACE_SUBJECT_TYPE = "stype"; - public static final String KEYFIELD_ACE_RESOURCE= "resources"; + public static final String KEYFIELD_ACE_RESOURCE = "resources"; - public static final String KEYFIELD_ACE_VALIDITY = "validity"; + public static final String KEYFIELD_ACE_VALIDITY = "validity"; - public static final String KEYFIELD_ACE_PERMISSION = "permission"; + public static final String KEYFIELD_ACE_PERMISSION = "permission"; public static final String KEYFIELD_ACE_RESOURCE_HREF = "href"; - public static final String KEYFIELD_ACE_RESOURCE_RT = "rt"; + public static final String KEYFIELD_ACE_RESOURCE_RT = "rt"; - public static final String KEYFIELD_ACE_RESOURCE_IF = "if"; + public static final String KEYFIELD_ACE_RESOURCE_IF = "if"; // Request payload key - public static final String REQ_DEVICE_ID = "di"; + public static final String REQ_DEVICE_ID = "di"; - public static final String REQ_DEVICE_ID_LIST = "dilist"; + public static final String REQ_DEVICE_ID_LIST = "dilist"; - public static final String REQ_UUID_ID = "uid"; + public static final String REQ_UUID_ID = "uid"; - public static final String REQ_ACE_ID = "aceid"; + public static final String REQ_ACE_ID = "aceid"; - public static final String REQ_ACL_ID = "aclid"; + public static final String REQ_ACL_ID = "aclid"; - public static final String REQ_ROWNER_ID = "rowneruuid"; + public static final String REQ_ROWNER_ID = "rowneruuid"; - public static final String REQ_ACL_LIST = "aclist"; + public static final String REQ_ACL_LIST = "aclist"; - public static final String REQ_OWNER_ID = "oid"; + public static final String REQ_OWNER_ID = "oid"; - public static final String REQ_AUTH_CODE = "authcode"; + public static final String REQ_AUTH_CODE = "authcode"; - public static final String REQ_AUTH_PROVIDER = "authprovider"; + public static final String REQ_AUTH_PROVIDER = "authprovider"; - public static final String REQ_ACCESS_TOKEN = "accesstoken"; + public static final String REQ_ACCESS_TOKEN = "accesstoken"; - public static final String REQ_LOGIN = "login"; + public static final String REQ_LOGIN = "login"; - public static final String REQ_REFRESH_TOKEN = "refreshtoken"; + public static final String REQ_REFRESH_TOKEN = "refreshtoken"; - public static final String REQ_GRANT_TYPE = "granttype"; + public static final String REQ_GRANT_TYPE = "granttype"; - public static final String REQ_AUTH_OPTIONS = "options"; + public static final String REQ_AUTH_OPTIONS = "options"; - public static final String REQ_REQUEST_METHOD = "rm"; + public static final String REQ_REQUEST_METHOD = "rm"; - public static final String REQ_REQUEST_URI = "uri"; + public static final String REQ_REQUEST_URI = "uri"; - public static final String REQ_SEARCH_USER_ID = "sid"; + public static final String REQ_SEARCH_USER_ID = "sid"; - public static final String REQ_SEARCH_CRITERIA = "search"; + public static final String REQ_SEARCH_CRITERIA = "search"; - public static final String REQ_GROUP_ID = "gid"; + public static final String REQ_GROUP_ID = "gid"; - public static final String REQ_GROUP_MASTER_ID = "gmid"; + public static final String REQ_GROUP_MASTER_ID = "gmid"; - public static final String REQ_GROUP_TYPE = "gtype"; + public static final String REQ_GROUP_TYPE = "gtype"; - public static final String REQ_MEMBER = "mid"; + public static final String REQ_MEMBER = "mid"; - public static final String REQ_LAST_UPDATE = "lu"; + public static final String REQ_LAST_UPDATE = "lu"; - public static final String REQ_THIS_UPDATE = "tu"; + public static final String REQ_THIS_UPDATE = "tu"; - public static final String REQ_NEXT_UPDATE = "nu"; + public static final String REQ_NEXT_UPDATE = "nu"; - public static final String REQ_CRL = "crl"; + public static final String REQ_CRL = "crl"; - public static final String REQ_SERIAL_NUMBER = "rcsn"; + public static final String REQ_SERIAL_NUMBER = "rcsn"; - public static final String REQ_MEMBER_LIST = "midlist"; + public static final String REQ_MEMBER_LIST = "midlist"; - public static final String REQ_GTYPE_PRIVATE = "Private"; + public static final String REQ_GTYPE_PRIVATE = "Private"; - public static final String REQ_GTYPE_PUBLIC = "Public"; + public static final String REQ_GTYPE_PUBLIC = "Public"; - public static final String REQ_CSR = "csr"; + public static final String REQ_CSR = "csr"; - public static final String REQ_INVITE = "invite"; + public static final String REQ_INVITE = "invite"; // Response payload key - public static final String RESP_ACCESS_TOKEN = "accesstoken"; + public static final String RESP_ACCESS_TOKEN = "accesstoken"; + + public static final String RESP_REFRESH_TOKEN = "refreshtoken"; + + public static final String RESP_TOKEN_TYPE = "tokentype"; + + public static final String RESP_EXPIRES_IN = "expiresin"; + + public static final String RESP_REDIRECT_URI = "redirecturi"; + + public static final String RESP_CERTIFICATE = "certificate"; - public static final String RESP_REFRESH_TOKEN = "refreshtoken"; + public static final String RESP_SERVER_ID = "sid"; - public static final String RESP_TOKEN_TYPE = "tokentype"; + public static final String RESP_DEVICES = "devices"; - public static final String RESP_EXPIRES_IN = "expiresin"; + public static final String RESP_UUID = "uid"; - public static final String RESP_REDIRECT_URI = "redirecturi"; + public static final String RESP_USER_INFO = "uinfo"; - public static final String RESP_CERTIFICATE = "certificate"; + public static final String RESP_USER_LIST = "ulist"; - public static final String RESP_SERVER_ID = "sid"; + public static final String RESP_DEVICE_ID = "di"; - public static final String RESP_DEVICES = "devices"; + public static final String RESP_CERT = "cert"; - public static final String RESP_UUID = "uid"; + public static final String RESP_CACERT = "cacert"; - public static final String RESP_USER_INFO = "uinfo"; + public static final String RESP_INVITE = "invite"; - public static final String RESP_USER_LIST = "ulist"; + public static final String RESP_INVITED = "invited"; - public static final String RESP_DEVICE_ID = "di"; + public static final String RESP_ACL_ALLOWED = "Allowed"; - public static final String RESP_CERT = "cert"; + public static final String RESP_ACL_DENIED = "Denied"; - public static final String RESP_CACERT = "cacert"; + public static final String ENCODING = "encoding"; - public static final String RESP_INVITE = "invite"; + public static final String DATA = "data"; - public static final String RESP_INVITED = "invited"; + public static final String CERT = "cert"; - public static final String ENCODING = "encoding"; + public static final String CERT_CHAIN = "certchain"; - public static final String DATA = "data"; + // query parameter key - public static final String CERT = "cert"; + public static final String REQ_INVITE_ACCEPT = "accept"; - public static final String CERT_CHAIN = "certchain"; + // constants - public static final String RESP_ACL_ALLOWED = "Allowed"; + public static final String INVITE_ACCEPT = "1"; - public static final String RESP_ACL_DENIED = "Denied"; + public static final String INVITE_DENY = "0"; // static token type - public static final String TOKEN_TYPE_BEARER = "bearer"; + public static final String TOKEN_TYPE_BEARER = "bearer"; - public static final int TOKEN_INFINITE = -1; + public static final int TOKEN_INFINITE = -1; // auth servers - public static final String GITHUB = "Github"; + public static final String GITHUB = "Github"; - public static final String SAMSUNG = "Samsung"; + public static final String SAMSUNG = "Samsung"; - public static final String GOOGLE = "Google"; + public static final String GOOGLE = "Google"; } diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/AccountDBManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/AccountDBManager.java index 275d1bb..b88c1a1 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/AccountDBManager.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/AccountDBManager.java @@ -137,6 +137,11 @@ public class AccountDBManager { } + /** + * API to implement singleton pattern based DB manager + * + * @return account DB manager + */ public static AccountDBManager getInstance() { return accoutDBManager; @@ -148,7 +153,7 @@ public class AccountDBManager { * * @param tableName * table name to be inserted - * @param insert + * @param record * record to be inserted */ public void insertRecord(String tableName, HashMap insert) { @@ -219,7 +224,7 @@ public class AccountDBManager { if (!_updateRecord(tableName, replace)) throw new InternalServerErrorException( - "Database record updateX509CRL failed"); + "Database record update failed"); } diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/GroupTable.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/GroupTable.java index 0f89773..8cdc6a5 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/GroupTable.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/GroupTable.java @@ -33,6 +33,22 @@ public class GroupTable { public GroupTable() { } + /** + * API to initialize group table instance + * + * @param gid + * group ID + * @param midlist + * member ID list as a form of array + * @param dilist + * device ID list as a form of array + * @param gmid + * group master ID + * @param gacl + * group ACL + * @param gtype + * group type + */ public GroupTable(String gid, Object midlist, Object dilist, String gmid, String gacl, String gtype) { this.gid = gid; @@ -43,50 +59,116 @@ public class GroupTable { this.gtype = gtype; } + /** + * API to get group ID + * + * @return group ID + */ public String getGid() { return gid; } + /** + * API to set group ID + * + * @param gid + * group ID to be set + */ public void setGid(Object gid) { this.gid = gid.toString(); } + /** + * API to get member ID list of the group + * + * @return member ID list + */ public Object getMidlist() { return midlist; } + /** + * API to set member ID list of the group + * + * @param midlist + * member ID list to be set + */ public void setMidlist(Object midlist) { this.midlist = midlist; } + /** + * API to get device ID list of the group + * + * @return device ID list + */ public Object getDilist() { return dilist; } + /** + * API to set device ID list of the group + * + * @param dilist + * device ID list to be set + */ public void setDilist(Object dilist) { this.dilist = dilist; } + /** + * API to get the group master ID + * + * @return group master ID + */ public String getGmid() { return gmid; } + /** + * API to set the master ID of the group + * + * @param gmid + * group master ID to be set + */ public void setGmid(Object gmid) { this.gmid = gmid.toString(); } + /** + * API to get group ACL + * + * @return group ACL + */ public String getGacl() { return gacl; } + /** + * API to set group ACL of the group + * + * @param gacl + * group ACL to be set + */ public void setGacl(Object gacl) { this.gacl = gacl.toString(); } + /** + * API to get group type + * + * @return group type + */ public String getGtype() { return gtype; } + /** + * API to set group type + * + * @param gtype + * group type to be set + */ public void setGtype(Object gtype) { this.gtype = gtype.toString(); } diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/InviteTable.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/InviteTable.java index 151c56f..b8451d3 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/InviteTable.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/InviteTable.java @@ -30,28 +30,66 @@ public class InviteTable { public InviteTable() { } + /** + * API to initialize an instance of the group invitation table + * + * @param inviteUser + * user ID who requests the group invitation for the + * "invitedUser" + * @param gid + * group ID to be invited + * @param invitedUser + * invited user ID + */ public InviteTable(String inviteUser, String gid, String invitedUser) { this.inviteUser = inviteUser; this.gid = gid; this.invitedUser = invitedUser; } + /** + * API to get the group ID to be invited + * + * @return group ID + */ public String getGid() { return gid; } + /** + * API to set the group ID to invite + * + * @param gid + * group ID + */ public void setGid(String gid) { this.gid = gid; } + /** + * API to get the user ID who requests the group invitation + * + * @return user ID + */ public String getInviteUser() { return inviteUser; } + /** + * API to set the user ID to be invited + * + * @param inviteUser + * user ID to be invited + */ public void setInviteUser(String inviteUser) { this.inviteUser = inviteUser; } + /** + * API to get the user Id to be invited + * + * @return user ID to be invited + */ public String getInvitedUser() { return invitedUser; } diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/TokenTable.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/TokenTable.java index 7ae794f..7cfc6ae 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/TokenTable.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/TokenTable.java @@ -25,11 +25,10 @@ import org.iotivity.cloud.accountserver.Constants; /** * - * This class provides a set of APIs storing session information of authorized - * user. + * This class provides a set of APIs to store session information of authorized + * users. * */ - public class TokenTable { private String uuid = null; @@ -40,62 +39,139 @@ public class TokenTable { private long expiredtime = Constants.TOKEN_INFINITE; private String issuedtime = null; + /** + * API to get user ID + * + * @return user ID + */ public String getUuid() { return uuid; } + /** + * API to set user ID + * + * @param uuid + * user ID to be registered + */ public void setUuid(Object uuid) { this.uuid = uuid.toString(); } + /** + * API to get device ID + * + * @return device ID + */ public String getDid() { return did; } + /** + * API to set device ID + * + * @param did + * device ID to be registered + */ public void setDid(String did) { this.did = did; } + /** + * API to get access token + * + * @return access token + */ public String getAccesstoken() { return accesstoken; } + /** + * API to set the access token to the DB + * + * @param accesstoken + * access token to be registered + */ public void setAccesstoken(Object accesstoken) { if (accesstoken != null) this.accesstoken = accesstoken.toString(); } + /** + * API to get the refresh token from the DB + * + * @return refresh token + */ public String getRefreshtoken() { return refreshtoken; } + /** + * API to set the refresh token to the DB + * + * @param refreshtoken + * refresh token to be registered + */ public void setRefreshtoken(Object refreshtoken) { if (refreshtoken != null) this.refreshtoken = refreshtoken.toString(); } + /** + * API to get the auth provider name + * + * @return auth provider name + */ public String getProvider() { return provider; } + /** + * API to set the auth provider name to the DB + * + * @param provider + * auth provider name to be registered + */ public void setProvider(Object provider) { if (provider != null) this.provider = provider.toString(); } + /** + * API to get the expiration time of the access token + * + * @return time remain + */ public long getExpiredtime() { return expiredtime; } + /** + * API to set the expiration time of the access token + * + * @param expiredtime + * expiration time of the access token + */ public void setExpiredtime(Object expiredtime) { if (expiredtime != null) this.expiredtime = Long.valueOf(expiredtime.toString()); } + /** + * API to get the issued time of the token + * + * @return issued time + */ public String getIssuedtime() { return issuedtime; } + /** + * API to get the issued time of the token + * + * @param issuedtime + * issued time to be registered + */ public void setIssuedtime(Object issuedtime) { if (issuedtime != null) this.issuedtime = issuedtime.toString(); diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserTable.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserTable.java index bdb9f33..b653c29 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserTable.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserTable.java @@ -1,5 +1,10 @@ package org.iotivity.cloud.accountserver.db; +/** + * This class provides a set of APIs to store user information of authorized + * users. + * + */ public class UserTable { private String uuid = null; private String userid = null; @@ -7,46 +12,101 @@ public class UserTable { private String email = null; private String phone = null; + /** + * API to get user ID + * + * @return user ID as a form of UUID + */ public String getUuid() { return uuid; } + /** + * API to set user ID + * + * @param uuid + * user ID to be registered as a form of UUID + */ public void setUuid(Object uuid) { if (uuid != null) this.uuid = uuid.toString(); } + /** + * API to get user ID + * + * @return user ID + */ public String getUserid() { return userid; } + /** + * API to set user ID + * + * @param userid + * user ID to be registered + */ public void setUserid(Object userid) { if (userid != null) this.userid = userid.toString(); } + /** + * API to get the auth provider name + * + * @return auth provider name + */ public String getProvider() { return provider; } + /** + * API to set the auth provider name to the DB + * + * @param provider + * auth provider name to be registered + */ public void setProvider(Object provider) { if (provider != null) this.provider = provider.toString(); } + /** + * API to get the e-mail address of the user + * + * @return e-mail address + */ public String getEmail() { return email; } + /** + * API to set the e-mail address of the user + * + * @param email + * e-mail address to be registered + */ public void setEmail(Object email) { if (email != null) this.email = email.toString(); } + /** + * API to get the phone number of the user + * + * @return phone number + */ public String getPhone() { return phone; } + /** + * API to set the phone number of the user + * + * @param phone + * phone number to be registered + */ public void setPhone(Object phone) { if (phone != null) this.phone = phone.toString(); diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/Acl.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/Acl.java index 1adb63a..62dfc3e 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/Acl.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/Acl.java @@ -148,32 +148,84 @@ public class Acl { @SuppressWarnings("unchecked") - public void addACE(List> aclist) { + public List> addACE(List> aclist) { + Log.v("IN addACE"); + HashMap hashmap = AccountDBManager.getInstance() + .selectRecord(Constants.ACL_TABLE, getCondition()).get(0); + if (hashmap == null) { + throw new BadRequestException("aclid is invalid"); + } + List> aclDbList = (List>) hashmap + .get(Constants.REQ_ACL_LIST); + + + ListIterator> iterator = aclist.listIterator(); + while (iterator.hasNext()) { + HashMap aceMap = iterator.next(); + if (aceMap.get(Constants.KEYFIELD_ACE_SUBJECT_ID) + .equals(hashmap.get(Constants.REQ_OWNER_ID))) { + // remove current iterator + iterator.remove(); + continue; + } + aceMap.put(Constants.REQ_ACE_ID, UUID.randomUUID().toString()); + } + + List> newAcList = new ArrayList>( + aclist); + if (aclDbList != null) { + newAcList.addAll(aclDbList); + } + hashmap.put(Constants.REQ_ACL_LIST, newAcList); + AccountDBManager.getInstance().updateRecord(Constants.ACL_TABLE, + hashmap); + notifyToSubscriber(getResponsePayload(true)); + Log.v("OUT addACE"); + return aclist; + } + + public HashMap getACE(String aceid) { HashMap hashmap = AccountDBManager.getInstance() .selectRecord(Constants.ACL_TABLE, getCondition()).get(0); + if (hashmap == null) { + throw new BadRequestException("aclid is invalid"); + } List> aclDbList = (List>) hashmap .get(Constants.REQ_ACL_LIST); - - - for(HashMap ace : aclist) { - ace.put(Constants.REQ_ACE_ID, UUID.randomUUID().toString()); + ListIterator> iterator = aclDbList + .listIterator(); + while (iterator.hasNext()) { + HashMap aceMap = iterator.next(); + if (aceMap.get(Constants.REQ_ACE_ID).equals(aceid)) { + // Return the current element from the iterator + return aceMap; + } + } + throw new BadRequestException("aceid is invalid"); + } + public boolean isValidAceId(String aceid) { + HashMap hashmap = AccountDBManager.getInstance() + .selectRecord(Constants.ACL_TABLE, getCondition()).get(0); + if (hashmap == null) { + return false; } - List> newAcList = new ArrayList>( - aclist); - - if (aclDbList != null) { - newAcList.addAll(aclDbList); + List> aclDbList = (List>) hashmap + .get(Constants.REQ_ACL_LIST); + ListIterator> iterator = aclDbList + .listIterator(); + while (iterator.hasNext()) { + HashMap aceMap = iterator.next(); + if (aceMap.get(Constants.REQ_ACE_ID).equals(aceid)) { + return true; + } } - hashmap.put(Constants.REQ_ACL_LIST, newAcList); - AccountDBManager.getInstance().updateRecord(Constants.ACL_TABLE, - hashmap); - notifyToSubscriber(getResponsePayload(true)); + return false; } - public void updateACE(String aceid, HashMap ace) { + Log.v("IN updateACE"); HashMap hashmap = AccountDBManager.getInstance() .selectRecord(Constants.ACL_TABLE, getCondition()).get(0); @@ -195,6 +247,8 @@ public class Acl { hashmap.put(Constants.REQ_ACL_LIST, aclDbList); AccountDBManager.getInstance().updateRecord(Constants.ACL_TABLE, hashmap); notifyToSubscriber(getResponsePayload(true)); + Log.v("OUT updateACE"); + } public void deleteACE(String aceid) { diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/AclManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/AclManager.java index f974aaf..081315f 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/AclManager.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/AclManager.java @@ -87,16 +87,34 @@ public class AclManager { mAcls.remove(aclid); } - public void addAclACE(String aclid, List> aclist) { - getAcl(aclid).addACE(aclist); + public List> addAclACE(String aclid, List> aclist) { + return getAcl(aclid).addACE(aclist); + } + + public HashMap getAclACE(String aclid, String aceid) { + return getAcl(aclid).getACE(aceid); } public void updateACE(String aclid, String aceid, HashMap ace) { - getAcl(aclid).updateACE(aceid, ace); + if(getAcl(aclid).isValidAceId(aceid)) + { + getAcl(aclid).updateACE(aceid, ace); + } + else + { + throw new BadRequestException("Invalid parameters"); + } } public void deleteAclACE(String aclid, String aceid) { - getAcl(aclid).deleteACE(aceid); + if(getAcl(aclid).isValidAceId(aceid)) + { + getAcl(aclid).deleteACE(aceid); + } + else + { + throw new BadRequestException("Invalid parameters"); + } } public void deleteAclAclist(String aclid) { getAcl(aclid).deleteAclist(); diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/AclResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/AclResource.java index c9f9c51..7ad3516 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/AclResource.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/AclResource.java @@ -4,7 +4,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; - import org.iotivity.cloud.accountserver.Constants; import org.iotivity.cloud.base.device.Device; import org.iotivity.cloud.base.exception.ServerException; @@ -20,12 +19,12 @@ import org.iotivity.cloud.util.Cbor; public class AclResource extends Resource { - private Cbor> mCbor = new Cbor<>(); - private static AclManager mAclManager = new AclManager(); + private Cbor> mCbor = new Cbor<>(); + private static AclManager mAclManager = new AclManager(); public AclResource() { - super(Arrays.asList(Constants.PREFIX_OIC, - Constants.ACL_URI, Constants.ID_URI)); + super(Arrays.asList(Constants.PREFIX_OIC, Constants.ACL_URI, + Constants.ID_URI)); } public static AclManager getInstance() { @@ -68,15 +67,18 @@ public class AclResource extends Resource { throws ServerException { if (getUriPathSegments().containsAll(request.getUriPathSegments())) { - String oid = request.getUriQueryMap().get(Constants.REQ_OWNER_ID).get(0); - String di = request.getUriQueryMap().get(Constants.REQ_DEVICE_ID).get(0); + String oid = request.getUriQueryMap().get(Constants.REQ_OWNER_ID) + .get(0); + String di = request.getUriQueryMap().get(Constants.REQ_DEVICE_ID) + .get(0); if (mAclManager.getAclid(di) == null) { return MessageBuilder.createResponse(request, - ResponseStatus.CREATED, ContentFormat.APPLICATION_CBOR, - mCbor.encodingPayloadToCbor( - mAclManager.createAcl(oid, di))); + ResponseStatus.CREATED, ContentFormat.APPLICATION_CBOR, + mCbor.encodingPayloadToCbor( + mAclManager.createAcl(oid, di))); } else { - throw new BadRequestException("aclid already exists for the given di"); + throw new BadRequestException( + "aclid already exists for the given di"); } } @@ -84,33 +86,37 @@ public class AclResource extends Resource { } private IResponse handlePostRequest(IRequest request) - throws ServerException { + throws ServerException { - HashMap payloadData = mCbor + HashMap payloadData = mCbor .parsePayloadFromCbor(request.getPayload(), HashMap.class); - if (!getUriPathSegments().containsAll(request.getUriPathSegments())) { - String aclid = request.getUriPathSegments().get(getUriPathSegments().size()); - - List> aclist = null; - if (!payloadData.containsKey(Constants.REQ_ACL_LIST)) { - throw new BadRequestException("aclist not included in payload"); + if (null !=request.getUriQueryMap()) { + String aclid = request.getUriPathSegments().get(getUriPathSegments().size()); + String aceid = request.getUriQueryMap().get(Constants.REQ_ACE_ID).get(0); + List> aclist = (List>) payloadData + .get(Constants.REQ_ACL_LIST); + mAclManager.updateACE(aclid, aceid, aclist.get(0)); + return MessageBuilder.createResponse(request, ResponseStatus.CHANGED); } + else if (!getUriPathSegments().containsAll(request.getUriPathSegments())) { + String aclid = request.getUriPathSegments().get(getUriPathSegments().size()); + + List> aclist = null; + if (!payloadData.containsKey(Constants.REQ_ACL_LIST)) { + throw new BadRequestException("aclist not included in payload"); + } aclist = (List>) payloadData - .get(Constants.REQ_ACL_LIST); - mAclManager.addAclACE(aclid, aclist); - return MessageBuilder.createResponse(request, ResponseStatus.CHANGED); - }else if (getUriPathSegments().containsAll(request.getUriPathSegments())) { - String aclid = request.getUriPathSegments().get(getUriPathSegments().size()); - String aceid = request.getUriQueryMap().get(Constants.REQ_ACE_ID).get(0); - HashMap ace = (HashMap) payloadData.get(Constants.REQ_ACL_LIST); - mAclManager.updateACE(aclid, aceid, ace); - return MessageBuilder.createResponse(request, ResponseStatus.CHANGED); + .get(Constants.REQ_ACL_LIST); + aclist= mAclManager.addAclACE(aclid, aclist); + payloadData.put(Constants.REQ_ACL_LIST, aclist); + return MessageBuilder.createResponse(request, ResponseStatus.CHANGED, + ContentFormat.APPLICATION_CBOR, + mCbor.encodingPayloadToCbor(payloadData)); + } + throw new BadRequestException("uriPath is invalid"); } - throw new BadRequestException("uriPath is invalid"); - - } @SuppressWarnings("unchecked") @@ -127,19 +133,23 @@ public class AclResource extends Resource { } responsePayload = mAclManager.getAclid(di); } else { - String aclid = request.getUriPathSegments().get(getUriPathSegments().size()); - switch(request.getObserve()) { + String aclid = request.getUriPathSegments() + .get(getUriPathSegments().size()); + switch (request.getObserve()) { case NOTHING: responsePayload = mAclManager.getAclInfo(aclid); break; case SUBSCRIBE: - di = request.getUriQueryMap().get(Constants.REQ_DEVICE_ID).get(0); + di = request.getUriQueryMap().get(Constants.REQ_DEVICE_ID) + .get(0); responsePayload = mAclManager.addAclSubscriber(aclid, di, - srcDevice, request); + srcDevice, request); break; case UNSUBSCRIBE: - di = request.getUriQueryMap().get(Constants.REQ_DEVICE_ID).get(0); - responsePayload = mAclManager.removeAclSubscriber(aclid, di); + di = request.getUriQueryMap().get(Constants.REQ_DEVICE_ID) + .get(0); + responsePayload = mAclManager.removeAclSubscriber(aclid, + di); break; default: throw new BadRequestException(request.getObserve() @@ -160,21 +170,28 @@ public class AclResource extends Resource { String aclid = null; if (getUriPathSegments().containsAll(request.getUriPathSegments())) { - aclid = request.getUriQueryMap().get(Constants.REQ_ACL_ID) - .get(0); + aclid = request.getUriQueryMap().get(Constants.REQ_ACL_ID).get(0); if (aclid == null) { - throw new PreconditionFailedException( - "aclid is invalid"); + throw new PreconditionFailedException("aclid is invalid"); } mAclManager.deleteAcl(aclid); } else { - aclid = request.getUriPathSegments().get(getUriPathSegments().size()); - String aceid = request.getUriQueryMap().get(Constants.REQ_ACE_ID).get(0); - if (aceid == null) { + aclid = request.getUriPathSegments() + .get(getUriPathSegments().size()); + + if (request.getUriQueryMap() == null) + { mAclManager.deleteAclAclist(aclid); - } else { + } + else if (request.getUriQueryMap() + .containsKey(Constants.REQ_ACE_ID)) { + String aceid = request.getUriQueryMap().get(Constants.REQ_ACE_ID) + .get(0); mAclManager.deleteAclACE(aclid, aceid); } + else { + throw new BadRequestException("uriPath is invalid"); + } } return MessageBuilder.createResponse(request, ResponseStatus.DELETED); diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteManager.java index ca64b12..27bd56c 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteManager.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteManager.java @@ -23,11 +23,13 @@ package org.iotivity.cloud.accountserver.resources.acl.invite; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import org.iotivity.cloud.accountserver.Constants; import org.iotivity.cloud.accountserver.db.AccountDBManager; import org.iotivity.cloud.accountserver.db.InviteTable; +import org.iotivity.cloud.accountserver.resources.acl.group.GroupManager; import org.iotivity.cloud.accountserver.util.TypeCastingManager; import org.iotivity.cloud.base.device.Device; import org.iotivity.cloud.base.exception.ServerException.BadRequestException; @@ -42,7 +44,6 @@ import org.iotivity.cloud.util.Cbor; * This class provides a set of APIs to invite a user to a group * */ - public class InviteManager { private TypeCastingManager mTypeInvite = new TypeCastingManager<>(); @@ -57,8 +58,19 @@ public class InviteManager { public IRequest mRequest; } - private HashMap mSubscribers = new HashMap<>(); - + // + private HashMap> mSubscribers = new HashMap<>(); + + /** + * API to add invitation + * + * @param uid + * id of user who sent invitation + * @param gid + * id of group to invite member to + * @param mid + * id of invited user + */ public void addInvitation(String uid, String gid, String mid) { // create invitation table @@ -78,7 +90,17 @@ public class InviteManager { } } - public void deleteInvitation(String mid, String gid) { + /** + * API to delete invitation by invited user + * + * @param mid + * id of invited user + * @param gid + * id of group which the user was invited to + * @param accepted + * value of invitation accept or deny + */ + public void deleteInvitation(String mid, String gid, boolean accepted) { HashMap condition = new HashMap<>(); condition.put(Constants.REQ_GROUP_ID, gid); condition.put(Constants.KEYFIELD_INVITED_USER, mid); @@ -98,12 +120,31 @@ public class InviteManager { AccountDBManager.getInstance().deleteRecord(Constants.INVITE_TABLE, condition); + /* add user into group */ + if (accepted) { + + HashSet midlist = new HashSet(); + midlist.add(mid); + + GroupManager.getInstance().addGroupMember(gid, midlist); + } + notifyToSubscriber(mid); for (String uid : uidList) { notifyToSubscriber(uid); } } + /** + * API to cancel invitation by user who invited member + * + * @param uid + * id of user who sent invitation + * @param gid + * id of group to invite member to + * @param mid + * id of invited user + */ public void cancelInvitation(String uid, String gid, String mid) { HashMap condition = new HashMap<>(); @@ -119,6 +160,14 @@ public class InviteManager { notifyToSubscriber(mid); } + /** + * API to get invitation information + * + * @param uid + * user id + * + * @return returns invite and invited information of the user + */ public HashMap getInvitationInfo(String uid) { HashMap responsePayload = new HashMap<>(); @@ -157,20 +206,57 @@ public class InviteManager { return responsePayload; } + /** + * API to add subscriber of invite resource + * + * @param uid + * user id + * @param subscriber + * device that sent request for subscription + * @param request + * received request for subscription + * + * @return returns invite and invited information of the user + */ public HashMap addSubscriber(String uid, Device subscriber, IRequest request) { InviteSubscriber newSubscriber = new InviteSubscriber(subscriber, request); - mSubscribers.put(uid, newSubscriber); + + synchronized (mSubscribers) { + ArrayList subscriberList = mSubscribers.get(uid); + + if (subscriberList == null) { + subscriberList = new ArrayList<>(); + } + + subscriberList.add(newSubscriber); + mSubscribers.put(uid, subscriberList); + } return getInvitationInfo(uid); } - public HashMap removeSubscriber(String uid) { + /** + * API to remove subscriber of invite resource + * + * @param uid + * user id + * @param request + * received request for unsubscription + * + * @return returns invite and invited information of the user + */ + public HashMap removeSubscriber(String uid, + IRequest request) { + + synchronized (mSubscribers) { + if (mSubscribers.containsKey(uid)) { - if (mSubscribers.containsKey(uid)) { - mSubscribers.remove(uid); + mSubscribers.get(uid).removeIf(subscriber -> subscriber.mRequest + .getRequestId().equals(request.getRequestId())); + } } return getInvitationInfo(uid); @@ -182,12 +268,17 @@ public class InviteManager { if (!mSubscribers.containsKey(id)) { return; } + Cbor> cbor = new Cbor<>(); - mSubscribers.get(id).mSubscriber.sendResponse( - MessageBuilder.createResponse(mSubscribers.get(id).mRequest, - ResponseStatus.CONTENT, - ContentFormat.APPLICATION_CBOR, - cbor.encodingPayloadToCbor(getInvitationInfo(id)))); + byte[] payload = cbor.encodingPayloadToCbor(getInvitationInfo(id)); + + for (InviteSubscriber subscriber : mSubscribers.get(id)) { + + subscriber.mSubscriber.sendResponse( + MessageBuilder.createResponse(subscriber.mRequest, + ResponseStatus.CONTENT, + ContentFormat.APPLICATION_CBOR, payload)); + } } } @@ -213,4 +304,4 @@ public class InviteManager { } -} +} \ No newline at end of file diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteResource.java index 080e685..d018924 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteResource.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteResource.java @@ -39,12 +39,21 @@ import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.util.Cbor; +/** + * + * This class provides a set of APIs to handle requests to Invite resource. + * + */ public class InviteResource extends Resource { private InviteManager mInviteManager = new InviteManager(); private Cbor> mCbor = new Cbor<>(); + private enum ReqType { + NONE, CANCEL_INVITATION, DELETE_INVITATION + }; + public InviteResource() { super(Arrays.asList(Constants.PREFIX_OIC, Constants.ACL_URI, Constants.INVITE_URI)); @@ -92,7 +101,7 @@ public class InviteResource extends Resource { request); break; case UNSUBSCRIBE: - responsePayload = mInviteManager.removeSubscriber(uid); + responsePayload = mInviteManager.removeSubscriber(uid, request); break; default: break; @@ -149,11 +158,32 @@ public class InviteResource extends Resource { String gid = queryParams.get(Constants.REQ_GROUP_ID).get(0); String uid = queryParams.get(Constants.REQ_UUID_ID).get(0); + ReqType reqType = ReqType.NONE; if (queryParams.get(Constants.REQ_MEMBER) == null) { - mInviteManager.deleteInvitation(uid, gid); + reqType = ReqType.DELETE_INVITATION; } else { + reqType = ReqType.CANCEL_INVITATION; + } + + if (reqType.equals(ReqType.DELETE_INVITATION)) { + + String acceptStr = queryParams.get(Constants.REQ_INVITE_ACCEPT) + .get(0); + boolean accepted = false; + if (acceptStr.equals(Constants.INVITE_ACCEPT)) { + accepted = true; + } + + mInviteManager.deleteInvitation(uid, gid, accepted); + + } else if (reqType.equals(ReqType.CANCEL_INVITATION)) { + String mid = queryParams.get(Constants.REQ_MEMBER).get(0); mInviteManager.cancelInvitation(uid, gid, mid); + + } else { + + throw new BadRequestException("queryData is not enough"); } return MessageBuilder.createResponse(request, ResponseStatus.DELETED); diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/verify/AclVerifyResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/verify/AclVerifyResource.java index 87cb960..0ad3011 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/verify/AclVerifyResource.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/verify/AclVerifyResource.java @@ -72,7 +72,7 @@ public class AclVerifyResource extends Resource { private boolean checkResourceUri(List aceResources, String uri) throws ServerException { for (AceResource aceResource : aceResources) { - if (aceResource.getHref().equals(uri)) { + if (aceResource.getHref().trim().equals("*") || aceResource.getHref().equals(uri)) { return true; } } @@ -97,12 +97,13 @@ public class AclVerifyResource extends Resource { for (HashMap eachAclMap : aclResult) { AclTable aclTable = Acl.convertMaptoAclObject(eachAclMap); - if (aclTable.getAclist() == null) { - return false; - } if (aclTable.getOid().equals(sid)) { return true; } + if (aclTable.getAclist() == null) { + return false; + } + for (Ace ace : aclTable.getAclist()) { if (ace.getSubjectuuid().equals(sid)) { // check permission matches diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateConstants.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateConstants.java index 68d6fb3..4ba157a 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateConstants.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateConstants.java @@ -45,46 +45,96 @@ import static java.security.cert.CertificateFactory.getInstance; */ public final class CertificateConstants { + /** + * Properties object is used for loading pre-defined configurations: algorithm names and so on. + */ public static final Properties PROPERTIES = new Properties(); /** * Load properties from specified properties file. */ static { - try { - PROPERTIES.load(new FileInputStream(Constants.PROPERTIES_FILE_NAME)); + try (FileInputStream inputStream = new FileInputStream(Constants.PROPERTIES_FILE_NAME)) { + PROPERTIES.load(inputStream); } catch (IOException e) { Log.e(e.getMessage()); } } + /** + * Base 64 encoding constant for comparing request encoding. + */ public static final String BASE_64 = "oic.sec.encoding.base64"; + /** + * Der encoding constant for comparing request encoding. + */ public static final String DER = "oic.sec.encoding.der"; + /** + * Name of security provider, load from properties. + */ public static final String SECURITY_PROVIDER = PROPERTIES.getProperty("securityProvider"); + /** + * Not after interval for X509Certificate generation, load from properties. + */ public static final String NOT_AFTER_INTERVAL = PROPERTIES.getProperty("notAfterInterval"); + /** + * Next Update interval. is used for generation X509CRL, load from properties. + */ public static final String NEXT_UPDATE_INTERVAL = PROPERTIES.getProperty("nextUpdateInterval"); + /** + * Signature algorithm, is used for signing certificates and CRLs, load from properties. + */ public static final String SIGNATURE_ALGORITHM = PROPERTIES.getProperty("signatureAlgorithm"); + /** + * KeyStore type, is used for private key storage and for root certificate storage + */ static final String KEYSTORE_TYPE = PROPERTIES.getProperty("keystoreType"); + /** + * CA Alias name, is used for storing ca certificate to key storage. + */ static final String CA_ALIAS = PROPERTIES.getProperty("caAlias"); + /** + * Curve name, is used in signing algorithm for X509 certificate generation. + */ static final String CURVE = PROPERTIES.getProperty("ellipticCurve"); + /** + * Key generation algorithm is used for generation private and public keys. + */ static final String KEY_GENERATOR_ALGORITHM = PROPERTIES.getProperty("keyGeneratorAlgorithm"); + /** + * Date format, is used to parse date with UTC TIME format for certificate and CRL generation. + */ public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss"); + /** + * String constant is used to create keystore directory. + */ + public static final String KEYSTORE_DIR = PROPERTIES.getProperty("keystoreDir"); + + /** + * X500Name for ca issuer, is used for issuing personal certificates and CRLs. + */ public static final X500Name CA_ISSUER = Utility.getName(PROPERTIES.getProperty("subjectName"), PROPERTIES.getProperty("rootC"), PROPERTIES.getProperty("rootO"), PROPERTIES.getProperty("rootOU")); + /** + * Shared AccountDBManager to get rid of repeatable links on the same object. + */ public static final AccountDBManager ACCOUNT_DB_MANAGER = AccountDBManager.getInstance(); + /** + * Certificate factory is used during certificate generation process. + */ public static CertificateFactory CERTIFICATE_FACTORY; static { @@ -96,25 +146,29 @@ public final class CertificateConstants { } /** - * Path to keystore file + * Path to keystore file, retrieved from properties file. */ public static final File KEYSTORE_FILE = new File(MessageFormat. format(PROPERTIES.getProperty("keyStoreLocation"), File.separator)); /** * Set specified value for specified property. + * * @param property specified property - * @param value specified property value. + * @param value specified property value. */ public static void set(String property, String value) { PROPERTIES.setProperty(property, value); - try { - PROPERTIES.store(new FileOutputStream(Constants.PROPERTIES_FILE_NAME), "New Serial number"); + try (FileOutputStream outputStream = new FileOutputStream(Constants.PROPERTIES_FILE_NAME)) { + PROPERTIES.store(outputStream, "New Serial number"); } catch (IOException e) { Log.e(e.getMessage()); } } + /** + * Private constructor makes class non-instantiable utility class. + */ private CertificateConstants() { throw new AssertionError(); } diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateManager.java index bb36946..8bb7d53 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateManager.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateManager.java @@ -31,17 +31,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import static org.iotivity.cloud.accountserver.Constants.CERTIFICATE_TABLE; -import static org.iotivity.cloud.accountserver.Constants.KEYFIELD_DID; -import static org.iotivity.cloud.accountserver.Constants.KEYFIELD_REVOKED; +import static org.iotivity.cloud.accountserver.Constants.*; import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.ACCOUNT_DB_MANAGER; /** * This class is used as DB manager for CertificateTable. * With help of this class we can save certificate info to DB, - * retrieve it from DB by specified in constructor device id, - * updateX509CRL certificate, also it helps us get user Id from Token + * retrieve it from DB by specified device id, + * update X509 certificate, also it helps us to get user Id from Token * Table by specified device id. */ final class CertificateManager { @@ -63,7 +61,9 @@ final class CertificateManager { private final String deviceId; /** - * Constructs certificateMananger with specified device id. + * Constructs certificateMananger with specified device id. Initialize payload + * as new hash map instance. + * * @param deviceId specified device identifier for this CertificateManager. */ CertificateManager(String deviceId) { @@ -79,33 +79,34 @@ final class CertificateManager { } /** - * Puts for specified key, specified value to - * object payload; - * @param key specified key value - * @param value specified value + * Puts specified value for specified key to payload; + * + * @param key specified String key value + * @param value specified Object value */ public void put(String key, Object value) { payLoad.put(key, value); } /** - * Saves new certificate to DB with specified columns. + * Saves certificate information: serial number, not after, to DB with specified columns. * * @param serialNumber specified certificate serial number - * @param notAfter validation date not after - * @param notBefore validation date not before + * @param notAfter validation date not after + * @param notBefore validation date not before */ void save(BigInteger serialNumber, Date notAfter, Date notBefore) { ACCOUNT_DB_MANAGER.insertRecord(CERTIFICATE_TABLE, CERTIFICATE_TABLE_TYPE_CASTING_MANAGER.convertObjectToMap( new CertificateTable(serialNumber.toString(), notAfter, - notBefore, deviceId, Utility.getUserID(deviceId), false))); + notBefore, deviceId, Utility.getUserID(deviceId), false))); } /** - * Updates certificate table with specified revoked column. + * Updates certificate table by revoked column. + * * @param certificateTable certificate to be updated. - * @param revoked specified value for revoke + * @param revoked specified value for revoke */ void update(CertificateTable certificateTable, boolean revoked) { certificateTable.setRevoked(revoked); @@ -114,8 +115,8 @@ final class CertificateManager { } /** - * Returns certificate from database, according to specified - * device id + * Returns certificate from database for specified in constructor + * device id. */ public CertificateTable getCertificate() { HashMap condition = new HashMap<>(); @@ -123,7 +124,7 @@ final class CertificateManager { condition.put(KEYFIELD_REVOKED, false); List> listMap = ACCOUNT_DB_MANAGER.selectRecord( CERTIFICATE_TABLE, condition); - if (!listMap.isEmpty()) { + if (listMap != null && !listMap.isEmpty()) { return CERTIFICATE_TABLE_TYPE_CASTING_MANAGER .convertMaptoObject( listMap.get(0), @@ -132,4 +133,4 @@ final class CertificateManager { return null; } } -} +} \ No newline at end of file diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateResource.java index e7113d5..13bf1d5 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateResource.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateResource.java @@ -49,6 +49,7 @@ import org.iotivity.cloud.util.Log; import java.io.IOException; import java.security.GeneralSecurityException; +import java.security.PublicKey; import java.security.Security; import java.security.cert.CRLException; import java.security.cert.X509Certificate; @@ -77,15 +78,8 @@ public class CertificateResource extends Resource { private static final Cbor> MAP_CBOR = new Cbor<>(); /** - * Constructs certificate resourcewith specified prefixes - */ - public CertificateResource() { - super(Arrays.asList(PREFIX_OIC, CREDPROV_URI, CERT_URI)); - } - - /** - * Insert BouncyCastleProvider into 0 position in security provider list. - * Init KeyStore, Generate CA certificate and save it to keyStore. + * Inserts BouncyCastleProvider into 0 position in security provider list, + * inits KeyStore, generates CA certificate and saves it to keyStore. */ static { Security.insertProviderAt(new BouncyCastleProvider(), 0); @@ -100,6 +94,13 @@ public class CertificateResource extends Resource { } } + /** + * Constructs certificate resource with specified prefixes. + */ + public CertificateResource() { + super(Arrays.asList(PREFIX_OIC, CREDPROV_URI, CERT_URI)); + } + @Override public void onDefaultRequestReceived(Device srcDevice, IRequest request) throws ServerException { @@ -115,70 +116,106 @@ public class CertificateResource extends Resource { } /** - * Handles post requests to this resource + * Handles post requests to Certificate Resource. + * Request should be with specified format + * POST /oic/credprov/cert + * { + * “di” : “11-22-xx”, + * “csr” : { + * “encoding” : “oic.sec.encoding.base64”, + * “data” : “” + * } + * } + * Method checks encoding, and decodes data by specified encoding if needed. + * + * Method issus a certificate including User UUID in extension field, + * stores issuing information (serial number, validity, device uuid, user uuid) for management (e.g. re-issue). + * Response should be in next format for example: + * 2.04 CHANGED + * { + * “di” : “1111-22-xx”, + * “cert” : { + * “encoding” : “oic.sec.encoding.base64”, + * “data” : “” + * }, + * “certchain” : { + * “encoding” : “oic.sec.encoding.base64”, + * “data” : “” + * } + * } + * or returns BAD_REQUEST: 4.0.1 if any exceptions occured. + * * @param request request with payload information. * @throws ServerException */ private IResponse handlePostRequest(IRequest request) throws ServerException { - Map payloadData = MAP_CBOR - .parsePayloadFromCbor(request.getPayload(), HashMap.class); + byte[] requestPayload = request.getPayload(); IResponse response = MessageBuilder.createResponse(request, ResponseStatus.BAD_REQUEST); - Object csr = payloadData.get(Constants.REQ_CSR); - if (csr != null && csr instanceof Map) { - Object encoding =((Map)csr).get(ENCODING); - Object data = ((Map)csr).get(DATA); - if (encoding != null && encoding instanceof String && data != null && data instanceof byte[]) { - byte[] csrData = (byte[]) data; - if (encoding.equals(BASE_64)) { - csrData = Base64.decode(csrData); - } - try { - CSRParser parser = new CSRParser(csrData); - String commonName = parser.getCommonName(); - String pattern = "^uuid:(.*)$"; - Pattern r = Pattern.compile(pattern); - Matcher m = r.matcher(commonName); - String deviceId = (String) payloadData.get(RESP_DEVICE_ID); - if (m.find() && m.group(1).equals(deviceId) && parser.isSignatureValid()) { - CertificateManager certificateManager = new CertificateManager(deviceId); - CertificateTable certificateTable = certificateManager.getCertificate(); - if (certificateTable != null) { - try { - CrlManager.CRL_MANAGER.revoke(certificateTable.getSerialNumber()); - } catch (CRLException | OperatorCreationException e) { - Log.e(e.getMessage() + e.getClass()); - } - certificateManager.update(certificateTable, true); + if (requestPayload != null) { + Map payloadData = MAP_CBOR + .parsePayloadFromCbor(requestPayload, HashMap.class); + if (payloadData != null) { + Object csr = payloadData.get(Constants.REQ_CSR); + if (csr != null && csr instanceof Map) { + Object encoding = ((Map) csr).get(ENCODING); + Object data = ((Map) csr).get(DATA); + if (encoding != null && encoding instanceof String && data != null && data instanceof byte[]) { + byte[] csrData = (byte[]) data; + if (encoding.equals(BASE_64)) { + csrData = Base64.decode(csrData); } - CertificateExtension extension = new CertificateExtension(Extension.subjectAlternativeName, - false, new DERSequence(new ASN1Encodable[] - {new GeneralName(GeneralName.dNSName, Constants.KEYFIELD_USERID + ":" + - Utility.getUserID(deviceId))})); - CertificateBuilder certBuilder = new CertificateBuilder(parser.getSubject(), - parser.getPublicKey(), extension ); try { - X509Certificate personal = certBuilder.build(); - byte[] encodedCert = personal.getEncoded(); - byte[] encodedCa = CertificateStorage.ROOT_CERTIFICATE.getEncoded(); - if (encoding.equals(CertificateConstants.BASE_64)) { - encodedCert = Base64.encode(encodedCert); - encodedCa = Base64.encode(encodedCa); + CSRParser parser = new CSRParser(csrData); + String commonName = parser.getCommonName(); + String pattern = "^uuid:(.*)$"; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(commonName); + String deviceId = (String) payloadData.get(RESP_DEVICE_ID); + if (m.find() && m.group(1).equals(deviceId) && parser.isSignatureValid()) { + CertificateManager certificateManager = new CertificateManager(deviceId); + CertificateTable certificateTable = certificateManager.getCertificate(); + if (certificateTable != null) { + try { + CrlManager.CRL_MANAGER.revoke(certificateTable.getSerialNumber()); + } catch (CRLException | OperatorCreationException e) { + Log.e(e.getMessage() + e.getClass()); + } + certificateManager.update(certificateTable, true); + } + PublicKey publicKey = parser.getPublicKey(); + if (publicKey != null) { + CertificateExtension extension = new CertificateExtension(Extension.subjectAlternativeName, + false, new DERSequence(new ASN1Encodable[] + {new GeneralName(GeneralName.dNSName, Constants.KEYFIELD_USERID + ":" + + Utility.getUserID(deviceId))})); + CertificateBuilder certBuilder = new CertificateBuilder(parser.getSubject(), + publicKey, extension); + try { + X509Certificate personal = certBuilder.build(); + byte[] encodedCert = personal.getEncoded(); + byte[] encodedCa = CertificateStorage.ROOT_CERTIFICATE.getEncoded(); + if (encoding.equals(CertificateConstants.BASE_64)) { + encodedCert = Base64.encode(encodedCert); + encodedCa = Base64.encode(encodedCa); + } + certificateManager.put(Constants.RESP_DEVICE_ID, deviceId); + certificateManager.put(Constants.CERT, new CSR(encoding.toString(), encodedCert)); + certificateManager.put(Constants.CERT_CHAIN, new CSR(encoding.toString(), encodedCa)); + certificateManager.save(personal.getSerialNumber(), personal.getNotAfter(), + personal.getNotBefore()); + response = MessageBuilder.createResponse(request, ResponseStatus.CHANGED, + ContentFormat.APPLICATION_CBOR, + MAP_CBOR.encodingPayloadToCbor(certificateManager.getPayLoad())); + } catch (GeneralSecurityException | OperatorCreationException | CertIOException e) { + Log.e(e.getMessage()); + } + } } - certificateManager.put(Constants.RESP_DEVICE_ID, deviceId); - certificateManager.put(Constants.CERT, new CSR(encoding.toString(), encodedCert)); - certificateManager.put(Constants.CERT_CHAIN, new CSR(encoding.toString(), encodedCa)); - certificateManager.save(personal.getSerialNumber(), personal.getNotBefore(), - personal.getNotAfter()); - response = MessageBuilder.createResponse(request, ResponseStatus.CHANGED, - ContentFormat.APPLICATION_CBOR, - MAP_CBOR.encodingPayloadToCbor(certificateManager.getPayLoad())); - } catch (GeneralSecurityException | OperatorCreationException | CertIOException e) { + } catch (IOException e) { Log.e(e.getMessage()); } } - } catch (IOException e) { - Log.e(e.getMessage()); } } } @@ -186,7 +223,7 @@ public class CertificateResource extends Resource { } /** - * This class is used for response + * Response utility class. */ private static final class CSR { @@ -199,10 +236,16 @@ public class CertificateResource extends Resource { this.data = data; } + /** + * Return encoding. + */ public String getEncoding() { return encoding; } + /** + * Retrieves data. + */ public byte[] getData() { return data; } diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateStorage.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateStorage.java index f632a20..9363549 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateStorage.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/cert/CertificateStorage.java @@ -23,12 +23,11 @@ package org.iotivity.cloud.accountserver.resources.credprov.cert; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.Extension; -import org.bouncycastle.cert.CertIOException; import org.bouncycastle.jce.ECNamedCurveTable; -import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.OperatorCreationException; import org.iotivity.cloud.accountserver.x509.cert.CertificateBuilder; import org.iotivity.cloud.accountserver.x509.cert.CertificateExtension; +import org.iotivity.cloud.util.Log; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -42,6 +41,10 @@ import java.security.cert.X509Certificate; import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*; +/** + * This class is used for loading and storing key store. + * Also it generates CA certificate and puts it to keystore. + */ public final class CertificateStorage { /** @@ -51,78 +54,62 @@ public final class CertificateStorage { private static final String PASSWORD = PROPERTIES.getProperty("password"); /** - * Keystore object for save, get data from keystore. + * Root private key is used for signing certificates ans CRLs. */ - private static KeyStore keyStore; - public static PrivateKey ROOT_PRIVATE_KEY; - public static X509Certificate ROOT_CERTIFICATE; - - private CertificateStorage() { - throw new AssertionError(); - } - /** - * Init KeyStore. If it does not exists, create it and push to KEYSTORE_FILE. + * Root certificate, is used for isssuing low level certificates. */ - static void init() throws GeneralSecurityException, IOException, OperatorCreationException { - Files.createDirectories(Paths.get("keystore")); - keyStore = load(null, null); - store(); - CertificateStorage.generateCACertificate(); - CertificateStorage.saveCertificatePrivateKey(); - } + public static X509Certificate ROOT_CERTIFICATE; /** - * Load KeyStore with default keystore file and password. - * - * @return KeyStore instance. + * Keystore object to save, retrieve ca private key and ca certificate from keystore. */ - public static void load() throws GeneralSecurityException, IOException { - keyStore = load(new FileInputStream(KEYSTORE_FILE), PASSWORD.toCharArray()); - initRoot(); - } + private static KeyStore keyStore; /** - * Loads KeyStore with defined inputStream object and password. - * - * @param is specified inputStream which contains keystore bytes. - * @param password specified password for opening keystore. - * @return KeyStore instance. + * Private contructor to make this class non-instantiable. */ - private static KeyStore load(InputStream is, char[] password) throws IOException, GeneralSecurityException { - KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE, BouncyCastleProvider.PROVIDER_NAME); - keyStore.load(is, password); - return keyStore; + private CertificateStorage() { + throw new AssertionError(); } - /** - * Stores keyStore to default file KEYSTORE_FILE with default password. + * Loads keystore with null paramaters. + * Stores it empty version. Generates CA certificate and private key and + * saves it to key storage. */ - static void store() throws IOException, GeneralSecurityException { - store(keyStore, new FileOutputStream(KEYSTORE_FILE), PASSWORD.toCharArray()); + static void init() throws GeneralSecurityException, IOException, OperatorCreationException { + Files.createDirectories(Paths.get(KEYSTORE_DIR)); + keyStore = KeyStore.getInstance(KEYSTORE_TYPE, SECURITY_PROVIDER); + keyStore.load(null, null); + generate(); } /** - * Stores KeyStore to file outputstream with specifie password. + * Loads KeyStore intance from created keystore file and with default password. * - * @param keyStore + * @return KeyStore instance. */ - private static void store(KeyStore keyStore, FileOutputStream out, char[] password) throws GeneralSecurityException, - IOException { - keyStore.store(out, password); - out.close(); + static void load() throws GeneralSecurityException, IOException { + keyStore = KeyStore.getInstance(KEYSTORE_TYPE, SECURITY_PROVIDER); + try (InputStream inputStream = new FileInputStream(KEYSTORE_FILE)) { + keyStore.load(inputStream, PASSWORD.toCharArray()); + } catch (IOException ioException) { + Log.e(ioException.getMessage()); + } + ROOT_PRIVATE_KEY = (PrivateKey) keyStore.getKey(CA_ALIAS, PASSWORD.toCharArray()); + ROOT_CERTIFICATE = (X509Certificate) keyStore.getCertificate(CA_ALIAS); } /** - * Generates X509Certificate with PublicKey and PrivateKey + * Generates CA X509Certificate and private key and stores it to key storage. * * @return certificate and private key */ - private static void generateCACertificate() throws GeneralSecurityException, - OperatorCreationException, CertIOException { + private static void generate() throws GeneralSecurityException, + OperatorCreationException, IOException { if (ROOT_PRIVATE_KEY == null) { KeyPairGenerator g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, SECURITY_PROVIDER); g.initialize(ECNamedCurveTable.getParameterSpec(CURVE), new SecureRandom()); @@ -131,21 +118,21 @@ public final class CertificateStorage { ROOT_CERTIFICATE = new CertificateBuilder(CA_ISSUER, pair.getPublic(), new CertificateExtension(Extension.basicConstraints, false, new BasicConstraints(true))).build(); + keyStore.setCertificateEntry(CA_ALIAS, ROOT_CERTIFICATE); + keyStore.setKeyEntry(CA_ALIAS, ROOT_PRIVATE_KEY, PASSWORD.toCharArray(), + new Certificate[]{ROOT_CERTIFICATE}); + store(); } } /** - * Stores certificate and private key to keystore. + * Stores keyStore instance to default keystore file with default password. */ - private static void saveCertificatePrivateKey() throws GeneralSecurityException, IOException { - keyStore.setCertificateEntry(CA_ALIAS, ROOT_CERTIFICATE); - keyStore.setKeyEntry(CA_ALIAS, ROOT_PRIVATE_KEY, PASSWORD.toCharArray(), - new Certificate[]{ROOT_CERTIFICATE}); - store(); - } - - private static void initRoot() throws GeneralSecurityException { - ROOT_PRIVATE_KEY = (PrivateKey) keyStore.getKey(CA_ALIAS, PASSWORD.toCharArray()); - ROOT_CERTIFICATE = (X509Certificate) keyStore.getCertificate(CA_ALIAS); + private static void store() throws IOException, GeneralSecurityException { + try (FileOutputStream out = new FileOutputStream(KEYSTORE_FILE)) { + keyStore.store(out, PASSWORD.toCharArray()); + } catch (IOException ioException) { + Log.e(ioException.getMessage()); + } } } diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlManager.java index d6d0f6a..ca61263 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlManager.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlManager.java @@ -40,55 +40,80 @@ import static org.iotivity.cloud.accountserver.resources.credprov.cert.Certifica import static org.iotivity.cloud.accountserver.x509.crl.CrlIssuer.CRL_ISSUER; /** - * Class is used for managing CRLs(creation, revoke, update) + * Class is used to manage CRLs. It helps to create, + * update CRLS, revoke certificates. */ public final class CrlManager { /** - * Static manager for CRLs. - */ - public static CrlManager CRL_MANAGER; - /** * Casting manager for working with CRLTable in mongo db */ private static TypeCastingManager castingManager = new TypeCastingManager<>(); - static { - try { - CRL_MANAGER = new CrlManager(); - CRL_MANAGER.init(); - } catch (CRLException | IOException | OperatorCreationException e) { - Log.e(e.getMessage()); - } - } - /** * X509 CRL presentation. */ private X509CRL x509CRL; + /** + * Static manager for CRLs. + */ + public static final CrlManager CRL_MANAGER = new CrlManager(); + + /** + * Private constructor to make this class non-instantiable. + */ private CrlManager() { + try { + Calendar calendar = Calendar.getInstance(); + Date thisUpdate = calendar.getTime(); + calendar.add(Calendar.DAY_OF_MONTH, + Integer.parseInt(NEXT_UPDATE_INTERVAL)); + byte[] data = CRL_ISSUER.generate(thisUpdate, calendar.getTime(), Collections.emptyList()); + ACCOUNT_DB_MANAGER.insertRecord(Constants.CRL_TABLE, + castingManager.convertObjectToMap(new CRLTable(thisUpdate, new Binary(data)))); + setX509CRL(data); + } catch (CRLException | IOException | OperatorCreationException e) { + Log.e(e.getMessage()); + } } /** - * Revokes specified serial numbers. + * Revokes specified serial numbers. Puts them to database. * - * @param serialNumber specified var args serial numbers from 0. + * @param serialNumbers specified var args serial numbers from 0. */ - public void revoke(String... serialNumber) throws CRLException, IOException, OperatorCreationException { + public void revoke(String... serialNumbers) throws CRLException, IOException, OperatorCreationException { if (x509CRL != null) { update(x509CRL.getThisUpdate(), CRL_ISSUER.generate(x509CRL.getThisUpdate(), x509CRL.getNextUpdate(), - x509CRL.getRevokedCertificates(), serialNumber)); + x509CRL.getRevokedCertificates(), serialNumbers)); } } /** - * Check if last update is before CRL this update. + * Checks last update less than crl this update and returns response payload, + * including this update, next update, and CRL in DER encoding. + */ + Map getPayload(String lastUpdate) throws ServerException.PreconditionFailedException, CRLException { + if (checkLastUpdate(lastUpdate) && x509CRL != null) { + Map responsePayload = new HashMap<>(); + responsePayload.put(Constants.REQ_THIS_UPDATE, DATE_FORMAT.format(x509CRL.getThisUpdate())); + responsePayload.put(Constants.REQ_NEXT_UPDATE, DATE_FORMAT.format(x509CRL.getNextUpdate())); + responsePayload.put(Constants.REQ_CRL, new CRL(DER, x509CRL.getEncoded())); + return responsePayload; + } + return Collections.emptyMap(); + } + + + /** + * Checks if last update is before CRL this update. + * * @param lastUpdate specified last update; * @return true if before and false - otherwise. */ - boolean checkLastUpdate(String lastUpdate) { + private boolean checkLastUpdate(String lastUpdate) { boolean checkCondition = false; try { if (x509CRL != null) { @@ -100,44 +125,20 @@ public final class CrlManager { return checkCondition; } - /** - * Returns response payload, including this update, next update, and CRL in DER encoding. - */ - Map getPayload() throws ServerException.PreconditionFailedException, CRLException { - if (x509CRL != null) { - Map responsePayload = new HashMap<>(); - responsePayload.put(Constants.REQ_THIS_UPDATE, DATE_FORMAT.format(x509CRL.getThisUpdate())); - responsePayload.put(Constants.REQ_NEXT_UPDATE, DATE_FORMAT.format(x509CRL.getNextUpdate())); - responsePayload.put(Constants.REQ_CRL, new CRL(DER, x509CRL.getEncoded())); - return responsePayload; - } - return Collections.emptyMap(); - } /** * Updates CRLTable with specified this update and binary CRL data. */ void update(Date thisUpdate, byte[] data) throws CRLException { - CRLTable crlTable = castingManager.convertMaptoObject( - ACCOUNT_DB_MANAGER.selectRecord(Constants.CRL_TABLE, new HashMap<>()).get(0), new CRLTable()); - crlTable.setThisUpdate(thisUpdate); - crlTable.setBinaryData(new Binary(data)); - ACCOUNT_DB_MANAGER.updateRecord(Constants.CRL_TABLE, castingManager.convertObjectToMap(crlTable)); - setX509CRL(data); - } - - /** - * Create CRL with default options; - */ - private void init() throws CRLException, IOException, OperatorCreationException { - Calendar calendar = Calendar.getInstance(); - Date thisUpdate = calendar.getTime(); - calendar.add(Calendar.DAY_OF_MONTH, - Integer.parseInt(NEXT_UPDATE_INTERVAL)); - byte[] data = CRL_ISSUER.generate(thisUpdate, calendar.getTime(), Collections.emptyList()); - ACCOUNT_DB_MANAGER.insertRecord(Constants.CRL_TABLE, - castingManager.convertObjectToMap(new CRLTable(thisUpdate, new Binary(data)))); - setX509CRL(data); + ArrayList> crlList = ACCOUNT_DB_MANAGER.selectRecord(Constants.CRL_TABLE, + new HashMap<>()); + if (crlList != null && !crlList.isEmpty()) { + CRLTable crlTable = castingManager.convertMaptoObject(crlList.get(0), new CRLTable()); + crlTable.setThisUpdate(thisUpdate); + crlTable.setBinaryData(new Binary(data)); + ACCOUNT_DB_MANAGER.updateRecord(Constants.CRL_TABLE, castingManager.convertObjectToMap(crlTable)); + setX509CRL(data); + } } /** @@ -148,7 +149,7 @@ public final class CrlManager { } /** - * Static inner class for CBOR Crl presentation. + * Utility class for CBOR Crl presentation. */ private static final class CRL { @@ -156,7 +157,7 @@ public final class CrlManager { private final byte[] data; - public CRL(String encoding, byte[] data) { + CRL(String encoding, byte[] data) { this.encoding = encoding; this.data = data; } @@ -169,5 +170,4 @@ public final class CrlManager { return data; } } - } diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlResource.java index a274784..13a51a2 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlResource.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/credprov/crl/CrlResource.java @@ -47,7 +47,8 @@ import static org.iotivity.cloud.accountserver.resources.credprov.cert.Certifica import static org.iotivity.cloud.accountserver.resources.credprov.crl.CrlManager.CRL_MANAGER; /** - * Class is responsible for handling requests GET and POST for CRL data. + * Class is used working with POST and GET requests and + * handles CRL requests. */ public class CrlResource extends Resource { @@ -83,7 +84,20 @@ public class CrlResource extends Resource { } /** - * Handles GET request and sends response back to the client. + * Method handles GET requests with specified format: + * GET /oic/credprov/crl?lu=20170701000000 + * Checks if “lu” value is not after the latest update. + * If so, response with the latest CRL, otherwise response error (e.g. 4.04 Not Found) + * And response of next format: + * 2.05 CONTENTS + * { + * “tu” : “20160711000000”, + * “nu” : “20161011000000”, + * “crl” : { + * “encoding” : “oic.sec.encoding.base64”, + * “data” : “” + * } + * } */ private IResponse handleGetRequest(IRequest request) throws ServerException { @@ -91,11 +105,13 @@ public class CrlResource extends Resource { IResponse iResponse = MessageBuilder.createResponse(request, ResponseStatus.NOT_FOUND); if (queryData != null) { List lastUpdateList = queryData.get(Constants.REQ_LAST_UPDATE); - if (lastUpdateList != null && !lastUpdateList.isEmpty() && - CRL_MANAGER.checkLastUpdate(lastUpdateList.get(0))) { + if (lastUpdateList != null && !lastUpdateList.isEmpty()) { try { - iResponse = MessageBuilder.createResponse(request, ResponseStatus.CONTENT, - ContentFormat.APPLICATION_CBOR, MAP_CBOR.encodingPayloadToCbor(CRL_MANAGER.getPayload())); + Map payload = CRL_MANAGER.getPayload(lastUpdateList.get(0)); + if (!payload.isEmpty()) { + iResponse = MessageBuilder.createResponse(request, ResponseStatus.CONTENT, + ContentFormat.APPLICATION_CBOR, MAP_CBOR.encodingPayloadToCbor(payload)); + } } catch (CRLException e) { Log.e(e.getMessage()); } @@ -105,42 +121,63 @@ public class CrlResource extends Resource { } /** - * Handles POST requests and sends back CRL data in response. + * Handles POST requests of next formats: + * POST /oic/credprov/crl + * { + * “tu” : “20160727000000”, + * “nu” : “20161027000000”, + * “rcsn” : “123456” + * } + * AND + * POST /oic/credprov/crl + * { + * “tu” : “20160727000000”, + * “nu” : “20161027000000”, + * “crl” : { + * “encoding” : “oic.sec.encoding.base64”, + * “data” : “” + * } + * } + * And responds back with 2.04 CHANGED if everything is ok, and PRECONDITION_FAILED - otherwise */ private IResponse handlePostRequest(IRequest request) throws ServerException { - Map payloadData = MAP_CBOR - .parsePayloadFromCbor(request.getPayload(), HashMap.class); - Object thisUpdate = payloadData.get(Constants.REQ_THIS_UPDATE); - Object nextUpdate = payloadData.get(Constants.REQ_NEXT_UPDATE); + byte[] requestPayload = request.getPayload(); IResponse response = MessageBuilder.createResponse(request, ResponseStatus.PRECONDITION_FAILED); - if (thisUpdate != null && thisUpdate instanceof String && nextUpdate != null && nextUpdate instanceof String) { - Date thisUpdateDate; - try { - thisUpdateDate = DATE_FORMAT.parse(thisUpdate.toString()); - DATE_FORMAT.parse(nextUpdate.toString()); - Object reqSerialNumber = payloadData.get(Constants.REQ_SERIAL_NUMBER); - Object crl = payloadData.get(Constants.REQ_CRL); - if (reqSerialNumber != null && reqSerialNumber instanceof List) { - CRL_MANAGER.revoke(((List) reqSerialNumber).toArray(new String[]{})); - response = MessageBuilder.createResponse(request, ResponseStatus.CHANGED); - } else if (crl != null && crl instanceof Map) { - Object encoding = ((Map) crl).get(Constants.ENCODING); - Object crlData = ((Map) crl).get(Constants.DATA); - if (encoding != null && encoding instanceof String && crlData != null && crlData instanceof byte[]) { - try { - if (encoding.equals(BASE_64)) { - crlData = Base64.decode((byte[]) crlData); - } - CRL_MANAGER.update(thisUpdateDate, (byte[]) crlData); + if (requestPayload != null) { + Map payloadData = MAP_CBOR + .parsePayloadFromCbor(request.getPayload(), HashMap.class); + if (payloadData != null) { + Object thisUpdate = payloadData.get(Constants.REQ_THIS_UPDATE); + Object nextUpdate = payloadData.get(Constants.REQ_NEXT_UPDATE); + if (thisUpdate != null && thisUpdate instanceof String && nextUpdate != null && nextUpdate instanceof String) { + Date thisUpdateDate; + try { + thisUpdateDate = DATE_FORMAT.parse(thisUpdate.toString()); + Object reqSerialNumber = payloadData.get(Constants.REQ_SERIAL_NUMBER); + Object crl = payloadData.get(Constants.REQ_CRL); + if (reqSerialNumber != null && reqSerialNumber instanceof List) { + CRL_MANAGER.revoke(((List) reqSerialNumber).toArray(new String[]{})); response = MessageBuilder.createResponse(request, ResponseStatus.CHANGED); - } catch (DecoderException e) { - Log.e(e.getMessage() + e.getClass()); + } else if (crl != null && crl instanceof Map) { + Object encoding = ((Map) crl).get(Constants.ENCODING); + Object crlData = ((Map) crl).get(Constants.DATA); + if (encoding != null && encoding instanceof String && crlData != null && crlData instanceof byte[]) { + try { + if (encoding.equals(BASE_64)) { + crlData = Base64.decode((byte[]) crlData); + } + CRL_MANAGER.update(thisUpdateDate, (byte[]) crlData); + response = MessageBuilder.createResponse(request, ResponseStatus.CHANGED); + } catch (DecoderException e) { + Log.e(e.getMessage() + e.getClass()); + } + } } + } catch (CRLException | IOException | OperatorCreationException | ParseException e) { + Log.e(e.getMessage() + e.getClass()); } } - } catch (CRLException | IOException | OperatorCreationException | ParseException e) { - Log.e(e.getMessage() + e.getClass()); } } return response; diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CSRParser.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CSRParser.java index 0bf7401..71fb1a0 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CSRParser.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CSRParser.java @@ -21,6 +21,7 @@ */ package org.iotivity.cloud.accountserver.x509.cert; +import org.bouncycastle.asn1.x500.AttributeTypeAndValue; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.openssl.PEMException; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; @@ -95,8 +96,11 @@ public class CSRParser { * Returns common name from csr subject. */ public String getCommonName() { - return subject.getRDNs(CN)[0].getFirst().getValue().toString(); - + AttributeTypeAndValue rdn = subject.getRDNs(CN)[0].getFirst(); + if (rdn != null) { + return rdn.getValue().toString(); + } + return null; } /** diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateBuilder.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateBuilder.java index 041bea7..7aed99f 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateBuilder.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateBuilder.java @@ -58,31 +58,31 @@ public class CertificateBuilder { /** * Attribute for X500Name subject. */ - private X500Name subject; + private final X500Name subject; /** * Attribute for public key. */ - private PublicKey publicKey; + private final PublicKey publicKey; /** * Attribute for certificate extension. */ - private CertificateExtension extension; + private final CertificateExtension extension; /** * Constructs certificate builder with specified subject * public key and certificate extension. */ - public CertificateBuilder(X500Name subject, - PublicKey publicKey, CertificateExtension extension) { + public CertificateBuilder(X500Name subject, PublicKey publicKey, CertificateExtension extension) { this.subject = subject; this.publicKey = publicKey; this.extension = extension; } /** - * Builds X509Certificate with default root key. + * Builds X509Certificate, issued by CA issuer, with specific subject and publick key + * Adds extension during build. */ public X509Certificate build() throws CertIOException, GeneralSecurityException, OperatorCreationException { X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder( @@ -120,6 +120,4 @@ public class CertificateBuilder { Integer.parseInt(NOT_AFTER_INTERVAL)); return calendar.getTime(); } - - } \ No newline at end of file diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateExtension.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateExtension.java index 8172a19..86b9ff8 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateExtension.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/cert/CertificateExtension.java @@ -69,8 +69,6 @@ public class CertificateExtension { /** * Returns ASN1Encodable attribute value. - * - * @return */ ASN1Encodable getValue() { return value; diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlIssuer.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlIssuer.java index 6e4df99..3ea06b2 100644 --- a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlIssuer.java +++ b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/x509/crl/CrlIssuer.java @@ -36,7 +36,7 @@ import java.util.Date; import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.CA_ISSUER; /** - * Class is used for generating CRL with specified parameters. + * Class is used for generating CRLs with specified parameters. */ public final class CrlIssuer { /** @@ -45,7 +45,7 @@ public final class CrlIssuer { public static final CrlIssuer CRL_ISSUER = new CrlIssuer(); /** - * Creates new instance of CRL issuer. + * Private constructor to make class non-instantiable. */ private CrlIssuer() { } @@ -55,7 +55,6 @@ public final class CrlIssuer { */ public byte[] generate(Date thisUpdate, Date nextUpdate, Collection certs, String... serialNumbers) throws IOException, OperatorCreationException { - byte[] crl; X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(CA_ISSUER, thisUpdate); crlBuilder.setNextUpdate(nextUpdate); @@ -67,8 +66,8 @@ public final class CrlIssuer { for (String serialNumber : serialNumbers) { crlBuilder.addCRLEntry(new BigInteger(serialNumber), new Date(), 0); } - crl = crlBuilder.build(CertificateBuilder.SIGNER_BUILDER. + return crlBuilder.build(CertificateBuilder.SIGNER_BUILDER. build(CertificateStorage.ROOT_PRIVATE_KEY)).getEncoded(); - return crl; } + } \ No newline at end of file diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/AccountResourceTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/AccountResourceTest.java index 83800a7..f69d51c 100644 --- a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/AccountResourceTest.java +++ b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/AccountResourceTest.java @@ -49,6 +49,7 @@ import org.iotivity.cloud.base.protocols.enums.ContentFormat; import org.iotivity.cloud.base.protocols.enums.RequestMethod; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.util.Cbor; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -104,7 +105,8 @@ public class AccountResourceTest { }).when(mMockDevice).sendResponse(Mockito.anyObject()); } - public static void resetAccountDatabase() throws Exception { + @After + public void resetAccountDatabase() throws Exception { MongoDB mongoDB = new MongoDB(Constants.DB_NAME); mongoDB.createTable(Constants.USER_TABLE); mongoDB.createTable(Constants.TOKEN_TABLE); @@ -178,6 +180,7 @@ public class AccountResourceTest { .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); HashMap getUserInfo = ((ArrayList>) payloadData .get("ulist")).get(0); + assertTrue(getUserInfo.get("uid").equals(uuid)); } diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/CertificateResourceTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/CertificateResourceTest.java index 62bdca5..552eb7a 100644 --- a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/CertificateResourceTest.java +++ b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/cert/CertificateResourceTest.java @@ -21,15 +21,12 @@ */ package org.iotivity.cloud.accountserver.resources.account.credprov.cert; -import org.bouncycastle.util.encoders.Base64; import org.iotivity.cloud.accountserver.Constants; import org.iotivity.cloud.accountserver.db.AccountDBManager; import org.iotivity.cloud.accountserver.db.TokenTable; -import org.iotivity.cloud.accountserver.resources.account.credprov.crl.CrlResourceTest; import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants; import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateResource; import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage; -import org.iotivity.cloud.accountserver.resources.credprov.crl.CrlResource; import org.iotivity.cloud.accountserver.util.TypeCastingManager; import org.iotivity.cloud.accountserver.x509.cert.Utility; import org.iotivity.cloud.base.OICConstants; @@ -56,38 +53,32 @@ import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.math.BigInteger; -import java.security.cert.*; -import java.util.*; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CountDownLatch; -import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*; -import static org.junit.Assert.*; +import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.CERTIFICATE_FACTORY; +import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.KEYSTORE_FILE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; public class CertificateResourceTest { - private static final String COMMON_NAME = "OU=OCF Device CA, O=Samsung, C=KR, CN=uuid:B371C481-38E6-4D47-8320-7688D8A5B58C"; - + public static final String COMMON_NAME = "OU=OCF Device CA, O=Samsung, C=KR, CN=uuid:B371C481-38E6-4D47-8320-7688D8A5B58C"; + public static final String DEVICE_ID = "B371C481-38E6-4D47-8320-7688D8A5B58C"; private static final String CERTIFICATE_URI = OICConstants.CREDPROV_CERT_FULL_URI; - - private static final String DEVICE_ID = "B371C481-38E6-4D47-8320-7688D8A5B58C"; - + private static CertificateResource certificateResource = new CertificateResource(); + private static TypeCastingManager castingManager = new TypeCastingManager<>(); private CoapDevice mMockDevice = mock(CoapDevice.class); - private Cbor> mCbor = new Cbor<>(); - private IResponse mResponse = null; - private CountDownLatch mLatch = new CountDownLatch( 1); - - private static CertificateResource certificateResource = new CertificateResource(); - private byte[] csr; - private static TypeCastingManager castingManager = new TypeCastingManager<>(); - static void createToken() { TokenTable certificateTable = new TokenTable(); certificateTable.setDid(DEVICE_ID); @@ -99,6 +90,7 @@ public class CertificateResourceTest { @AfterClass public static void after() { KEYSTORE_FILE.delete(); + AccountDBManager.getInstance().deleteRecord(Constants.CERTIFICATE_TABLE, new HashMap<>()); } @BeforeClass @@ -142,8 +134,6 @@ public class CertificateResourceTest { Object[] args = invocation.getArguments(); CoapResponse resp = (CoapResponse) args[0]; mResponse = resp; - - mLatch.countDown(); return null; } @@ -247,67 +237,6 @@ public class CertificateResourceTest { assertTrue(methodCheck(mResponse, ResponseStatus.BAD_REQUEST)); } - Map payloadData; - - Map crlMap; - - byte[] data; - - X509CRL crlX509; - - @Test - public void testReIssueBase64() throws CRLException, CertificateException { - IRequest request = csrRequest(DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true); - certificateResource.onDefaultRequestReceived(mMockDevice, request); - assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); - - Map payloadData = mCbor - .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); - List serialNumbers = new ArrayList<>(); - Map certMap = (Map) payloadData.get(Constants.CERT); - InputStream in = new ByteArrayInputStream(Base64.decode((byte[]) certMap.get(Constants.DATA))); - X509Certificate personaleCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in); - serialNumbers.add(personaleCert.getSerialNumber()); - serialNumbers.add(personaleCert.getSerialNumber().subtract(BigInteger.ONE)); - - request = csrRequest(DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true); - certificateResource.onDefaultRequestReceived(mMockDevice, request); - assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); - payloadData = mCbor - .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); - certMap = (Map) payloadData.get(Constants.CERT); - in = new ByteArrayInputStream(Base64.decode((byte[]) certMap.get(Constants.DATA))); - personaleCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in); - serialNumbers.add(personaleCert.getSerialNumber()); - - - request = csrRequest(DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true); - certificateResource.onDefaultRequestReceived(mMockDevice, request); - assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); - getTestMethodName(); - request = CrlResourceTest.crlRequest(RequestMethod.GET, CrlResourceTest.CRL_URI, CrlResourceTest.CRL_URI_QUERY); - CrlResource crlResource = new CrlResource(); - crlResource.onDefaultRequestReceived(mMockDevice, request); - assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT)); - hashmapCheck(mResponse, Constants.ENCODING); - hashmapCheck(mResponse, Constants.DATA); - if (mResponse.getPayload() != null) { - payloadData = mCbor - .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); - crlMap = (Map) payloadData.get(Constants.REQ_CRL); - data = (byte[]) crlMap.get(Constants.DATA); - crlX509 = (X509CRL) CERTIFICATE_FACTORY.generateCRL(new ByteArrayInputStream(data)); - } - - assertEquals(DER, crlMap.get(Constants.ENCODING)); - assertNotNull(data); - Set entries = crlX509.getRevokedCertificates(); - Iterator iterator = entries.iterator(); - while (iterator.hasNext()) { - assertTrue(serialNumbers.contains(iterator.next().getSerialNumber())); - } - } - @Test public void testMethodNotAllowed() { IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, csr, RequestMethod.GET, true); @@ -364,7 +293,24 @@ public class CertificateResourceTest { return request; } - private static class CSR { + private boolean methodCheck(IResponse response, + ResponseStatus responseStatus) { + if (responseStatus == response.getStatus()) + return true; + else + return false; + } + + private boolean hashmapCheck(IResponse response, String propertyName) { + HashMap payloadData = mCbor + .parsePayloadFromCbor(response.getPayload(), HashMap.class); + if (payloadData.containsKey(propertyName)) + return true; + else + return false; + } + + public static class CSR { String encoding; byte[] data; @@ -394,21 +340,4 @@ public class CertificateResourceTest { } } - private boolean methodCheck(IResponse response, - ResponseStatus responseStatus) { - if (responseStatus == response.getStatus()) - return true; - else - return false; - } - - private boolean hashmapCheck(IResponse response, String propertyName) { - HashMap payloadData = mCbor - .parsePayloadFromCbor(response.getPayload(), HashMap.class); - if (payloadData.containsKey(propertyName)) - return true; - else - return false; - } - } diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/crl/CrlResourceTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/crl/CrlResourceTest.java index 1afb0ef..d548d1f 100644 --- a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/crl/CrlResourceTest.java +++ b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/credprov/crl/CrlResourceTest.java @@ -27,6 +27,8 @@ import org.bouncycastle.util.encoders.Base64; import org.iotivity.cloud.accountserver.Constants; import org.iotivity.cloud.accountserver.db.AccountDBManager; import org.iotivity.cloud.accountserver.db.CRLTable; +import org.iotivity.cloud.accountserver.resources.account.credprov.cert.CertificateResourceTest; +import org.iotivity.cloud.accountserver.resources.account.credprov.cert.GenerateCSR; import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants; import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateResource; import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage; @@ -34,6 +36,7 @@ import org.iotivity.cloud.accountserver.resources.credprov.crl.CrlManager; import org.iotivity.cloud.accountserver.resources.credprov.crl.CrlResource; import org.iotivity.cloud.accountserver.util.TypeCastingManager; import org.iotivity.cloud.accountserver.x509.crl.CrlIssuer; +import org.iotivity.cloud.base.OICConstants; import org.iotivity.cloud.base.device.CoapDevice; import org.iotivity.cloud.base.protocols.IRequest; import org.iotivity.cloud.base.protocols.IResponse; @@ -43,7 +46,9 @@ import org.iotivity.cloud.base.protocols.enums.ContentFormat; import org.iotivity.cloud.base.protocols.enums.RequestMethod; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.util.Cbor; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; @@ -52,6 +57,7 @@ import org.mockito.stubbing.Answer; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -61,6 +67,7 @@ import java.security.Security; import java.security.cert.CertificateFactory; import java.security.cert.X509CRL; import java.security.cert.X509CRLEntry; +import java.security.cert.X509Certificate; import java.text.ParseException; import java.util.*; import java.util.concurrent.CountDownLatch; @@ -84,13 +91,22 @@ public class CrlResourceTest { public static final String CRL_URI_QUERY_CONDITION_FALSE = "lu=21160726210000"; public static final String CRL_URI_QUERY_PARSE_ERROR = "lu=1231212asdzfg4123123123123123"; public static final String[] FOR_FULL_CRL = {Constants.REQ_THIS_UPDATE, Constants.REQ_NEXT_UPDATE, Constants.REQ_CRL}; - public static final PublicKey key = CertificateStorage.ROOT_CERTIFICATE.getPublicKey(); + public static PublicKey key; + static CertificateResource certificateResource; private static TypeCastingManager castingManager = new TypeCastingManager<>(); - static { + @AfterClass + public static void after() { + AccountDBManager.getInstance().deleteRecord(Constants.CERTIFICATE_TABLE, new HashMap<>()); + AccountDBManager.getInstance().deleteRecord(Constants.CRL_TABLE, new HashMap<>()); + } + + @BeforeClass + public static void setUpBefore() { Security.insertProviderAt(new BouncyCastleProvider(), 0); - new CertificateResource(); + certificateResource = new CertificateResource(); + key = CertificateStorage.ROOT_CERTIFICATE.getPublicKey(); } /** @@ -121,11 +137,12 @@ public class CrlResourceTest { payloadData = mCbor .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); crlMap = (Map) payloadData.get(Constants.REQ_CRL); - data = (byte[]) crlMap.get(Constants.DATA); - CertificateFactory factory = CertificateFactory.getInstance("X509"); - crlX509 = (X509CRL) factory.generateCRL(new ByteArrayInputStream(data)); + if (crlMap != null) { + data = (byte[]) crlMap.get(Constants.DATA); + CertificateFactory factory = CertificateFactory.getInstance("X509"); + crlX509 = (X509CRL) factory.generateCRL(new ByteArrayInputStream(data)); + } } - mLatch.countDown(); return null; } @@ -158,6 +175,73 @@ public class CrlResourceTest { return SERIAL_NUMBER; } + + @Test + public void testAeIssueBase64() throws Exception { + byte[] csr = GenerateCSR.generatePKCS10(CertificateResourceTest.COMMON_NAME, false); + IRequest request = csrRequest(CertificateResourceTest.DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true); + certificateResource.onDefaultRequestReceived(mMockDevice, request); + assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); + Map payloadData = mCbor + .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); + List serialNumbers = new ArrayList<>(); + Map certMap = (Map) payloadData.get(Constants.CERT); + InputStream in = new ByteArrayInputStream(Base64.decode((byte[]) certMap.get(Constants.DATA))); + X509Certificate personaleCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in); + serialNumbers.add(personaleCert.getSerialNumber()); + serialNumbers.add(personaleCert.getSerialNumber().subtract(BigInteger.ONE)); + request = csrRequest(CertificateResourceTest.DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true); + certificateResource.onDefaultRequestReceived(mMockDevice, request); + assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); + payloadData = mCbor + .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); + certMap = (Map) payloadData.get(Constants.CERT); + in = new ByteArrayInputStream(Base64.decode((byte[]) certMap.get(Constants.DATA))); + personaleCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in); + serialNumbers.add(personaleCert.getSerialNumber()); + request = csrRequest(CertificateResourceTest.DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true); + certificateResource.onDefaultRequestReceived(mMockDevice, request); + assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); + getTestMethodName(); + request = CrlResourceTest.crlRequest(RequestMethod.GET, CrlResourceTest.CRL_URI, CrlResourceTest.CRL_URI_QUERY); + CrlResource crlResource = new CrlResource(); + crlResource.onDefaultRequestReceived(mMockDevice, request); + assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT)); + hashmapCheck(mResponse, Constants.ENCODING); + hashmapCheck(mResponse, Constants.DATA); + if (mResponse.getPayload() != null) { + payloadData = mCbor + .parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); + crlMap = (Map) payloadData.get(Constants.REQ_CRL); + data = (byte[]) crlMap.get(Constants.DATA); + crlX509 = (X509CRL) CERTIFICATE_FACTORY.generateCRL(new ByteArrayInputStream(data)); + } + assertEquals(DER, crlMap.get(Constants.ENCODING)); + assertNotNull(data); + Set entries = crlX509.getRevokedCertificates(); + Iterator iterator = entries.iterator(); + while (iterator.hasNext()) { + assertTrue(serialNumbers.contains(iterator.next().getSerialNumber())); + } + } + + private IRequest csrRequest(String deviceId, String encoding, byte[] data, RequestMethod method, boolean isEncoded) { + IRequest request; + HashMap payloadData = new HashMap<>(); + payloadData.put(Constants.REQ_DEVICE_ID, deviceId); + CertificateResourceTest.CSR csr = new CertificateResourceTest.CSR(); + if (isEncoded) { + csr.setEncoding(encoding); + csr.setData(data); + payloadData.put("csr", csr); + } + request = MessageBuilder.createRequest(method, OICConstants.CREDPROV_CERT_FULL_URI, + null, ContentFormat.APPLICATION_CBOR, + mCbor.encodingPayloadToCbor(payloadData)); + return request; + } + + @Test public void testCrlGetContent() throws Exception { getTestMethodName(); @@ -208,34 +292,6 @@ public class CrlResourceTest { } @Test - public void testX509CRL() { - Field field; - Method m; - try { - IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY); - crlResource.onDefaultRequestReceived(mMockDevice, request); - assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT)); - field = CrlManager.class.getDeclaredField("x509CRL"); - field.setAccessible(true); - Object value = field.get(CrlManager.CRL_MANAGER); - field.set(CrlManager.CRL_MANAGER, null); - request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY); - crlResource.onDefaultRequestReceived(mMockDevice, request); - assertTrue(methodCheck(mResponse, ResponseStatus.NOT_FOUND)); - m = CrlManager.class.getDeclaredMethod("getPayload"); - m.setAccessible(true); - field.set(CrlManager.CRL_MANAGER, null); - Object o = m.invoke(CrlManager.CRL_MANAGER); - assertEquals(Collections.EMPTY_MAP, o); - field.set(CrlManager.CRL_MANAGER, value); - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { - e.printStackTrace(); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } - } - - @Test public void testCrlPreconditionFailedException() throws ParseException, IOException, OperatorCreationException { getTestMethodName(); getTestMethodName(); @@ -261,6 +317,7 @@ public class CrlResourceTest { getTestMethodName(); IRequest request = crlRequest(RequestMethod.GET, CRL_URI, CRL_URI_QUERY); crlResource.onDefaultRequestReceived(mMockDevice, request); + System.out.println("MRESPONSE" + mResponse.getStatus()); assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT)); String thisUpdate = CertificateConstants.DATE_FORMAT.format(crlX509.getThisUpdate()); String nextUpdate = CertificateConstants.DATE_FORMAT.format(crlX509.getNextUpdate()); diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/session/SessionResourceTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/session/SessionResourceTest.java index ace8a22..a699048 100644 --- a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/session/SessionResourceTest.java +++ b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/session/SessionResourceTest.java @@ -46,6 +46,7 @@ import org.iotivity.cloud.base.protocols.enums.ContentFormat; import org.iotivity.cloud.base.protocols.enums.RequestMethod; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.util.Cbor; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -103,6 +104,14 @@ public class SessionResourceTest { }).when(mMockDevice).sendResponse(Mockito.anyObject()); } + @After + public void resetAccountDatabase() throws Exception { + MongoDB mongoDB = new MongoDB(Constants.DB_NAME); + mongoDB.createTable(Constants.USER_TABLE); + mongoDB.createTable(Constants.TOKEN_TABLE); + mongoDB.createTable(Constants.GROUP_TABLE); + } + @Test public void testSignInOnDefaultRequestReceived() throws Exception { getTestMethodName(); diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/tokenrefresh/TokenRefreshResourceTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/tokenrefresh/TokenRefreshResourceTest.java index ee03ffd..2d1df31 100644 --- a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/tokenrefresh/TokenRefreshResourceTest.java +++ b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/account/tokenrefresh/TokenRefreshResourceTest.java @@ -1,6 +1,5 @@ package org.iotivity.cloud.accountserver.resources.account.tokenrefresh; -import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import java.text.DateFormat; @@ -10,19 +9,19 @@ import java.util.HashMap; import org.iotivity.cloud.accountserver.Constants; import org.iotivity.cloud.accountserver.db.AccountDBManager; +import org.iotivity.cloud.accountserver.db.MongoDB; import org.iotivity.cloud.accountserver.db.TokenTable; import org.iotivity.cloud.accountserver.db.UserTable; import org.iotivity.cloud.accountserver.util.TypeCastingManager; import org.iotivity.cloud.base.device.CoapDevice; import org.iotivity.cloud.base.exception.ServerException; 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.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; import org.iotivity.cloud.util.Cbor; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -33,18 +32,16 @@ import org.mockito.stubbing.Answer; public class TokenRefreshResourceTest { private static final String REFRESH_TOKEN_URI = Constants.ACCOUNT_TOKENREFRESH_FULL_URI; private static final String DEVICE_ID = "B371C481-38E6-4D47-8320-7688D8A5B58C"; - private String mAuthProvider = "Google"; - private String mAccessToken = "ya29.Ci9VA06h_WhVG0lV3nU-kXMPSmisPJ6sM5iqMuoaNz0YYCO2lkXo5TGGy7wiol6Rdw"; - private String mRefreshToken = "1/UKLrjrMWErlq8has8XcpPg_riBcHcehKFUdoPoX9k0E"; - private String mUuid = "3ff62bac-c7cb-46f5-bb9b-c0f2f75f8c1d"; + private String mAuthProvider = "Samsung"; + private String mRefreshToken = "rt0001"; + private String mUuid = "u0001"; private String mUserId = "userId"; - private Cbor> mCbor = new Cbor<>(); - private CoapDevice mMockDevice = mock( + private Cbor> mCbor = new Cbor>(); + private CoapDevice mockDevice = mock( CoapDevice.class); private TypeCastingManager mUserTableCastingManager = new TypeCastingManager<>(); private TypeCastingManager mTokenTableCastingManager = new TypeCastingManager<>(); private TokenRefreshResource mTokenRefreshResource = new TokenRefreshResource(); - private IResponse mResponse = null; @Before public void setUp() throws Exception { @@ -60,22 +57,17 @@ public class TokenRefreshResourceTest { .println("\t----payload : " + resp.getPayloadString()); System.out .println("\t----responsestatus : " + resp.getStatus()); - mResponse = resp; return resp; } - }).when(mMockDevice).sendResponse(Mockito.anyObject()); + }).when(mockDevice).sendResponse(Mockito.anyObject()); } - @Test - public void testRefreshTokenonDefaultRequestReceived() throws Exception { - String uuid = this.mUuid; - RegisterTokenInfo(uuid, mUserId, mAccessToken, mRefreshToken); - TokenRefresh(RequestMethod.POST, mMockDevice, uuid, DEVICE_ID, - mRefreshToken); - assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); - assertTrue(hashmapCheck(mResponse, "accesstoken")); - assertTrue(hashmapCheck(mResponse, "refreshtoken")); - assertTrue(hashmapCheck(mResponse, "expiresin")); + @After + public void resetAccountDatabase() throws Exception { + MongoDB mongoDB = new MongoDB(Constants.DB_NAME); + mongoDB.createTable(Constants.USER_TABLE); + mongoDB.createTable(Constants.TOKEN_TABLE); + mongoDB.createTable(Constants.GROUP_TABLE); } @Test(expected = ServerException.NotFoundException.class) @@ -83,7 +75,7 @@ public class TokenRefreshResourceTest { throws Exception { String uuid = this.mUuid + "WrongRefreshTokenCase"; RegisterTokenInfo(uuid, mUserId, mAuthProvider, mRefreshToken); - TokenRefresh(RequestMethod.POST, mMockDevice, uuid, DEVICE_ID, + TokenRefresh(RequestMethod.POST, mockDevice, uuid, DEVICE_ID, mRefreshToken + "NotExist"); } @@ -92,7 +84,7 @@ public class TokenRefreshResourceTest { throws Exception { String uuid = this.mUuid + "InvalidRequestMethod (GET)"; RegisterTokenInfo(uuid, mUserId, mAuthProvider, mRefreshToken); - TokenRefresh(RequestMethod.GET, mMockDevice, uuid, DEVICE_ID, + TokenRefresh(RequestMethod.GET, mockDevice, uuid, DEVICE_ID, mRefreshToken + "InvalidMethod"); } @@ -100,7 +92,7 @@ public class TokenRefreshResourceTest { public void testRefreshTokenonRequestReceivedNullUuid() throws Exception { String uuid = this.mUuid + "NullUuid"; RegisterTokenInfo(uuid, mUserId, mAuthProvider, mRefreshToken); - TokenRefresh(RequestMethod.POST, mMockDevice, null, DEVICE_ID, + TokenRefresh(RequestMethod.POST, mockDevice, null, DEVICE_ID, mRefreshToken + "InvalidMethod"); } @@ -108,7 +100,7 @@ public class TokenRefreshResourceTest { public void testRefreshTokenonRequestReceivedNullDi() throws Exception { String uuid = this.mUuid + "NullDi"; RegisterTokenInfo(uuid, mUserId, mAuthProvider, mRefreshToken); - TokenRefresh(RequestMethod.POST, mMockDevice, uuid, null, + TokenRefresh(RequestMethod.POST, mockDevice, uuid, null, mRefreshToken + "InvalidMethod"); } @@ -117,7 +109,7 @@ public class TokenRefreshResourceTest { throws Exception { String uuid = this.mUuid + "NullRefreshToken"; RegisterTokenInfo(uuid, mUserId, mAuthProvider, mRefreshToken); - TokenRefresh(RequestMethod.POST, mMockDevice, uuid, DEVICE_ID, null); + TokenRefresh(RequestMethod.POST, mockDevice, uuid, DEVICE_ID, null); } public void TokenRefresh(RequestMethod method, CoapDevice device, @@ -178,21 +170,4 @@ public class TokenRefreshResourceTest { userInfo.setUserid(userId); return userInfo; } - - private boolean methodCheck(IResponse response, - ResponseStatus responseStatus) { - if (responseStatus == response.getStatus()) - return true; - else - return false; - } - - private boolean hashmapCheck(IResponse response, String propertyName) { - HashMap payloadData = mCbor - .parsePayloadFromCbor(response.getPayload(), HashMap.class); - if (payloadData.containsKey(propertyName)) - return true; - else - return false; - } } diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/group/GroupResourceTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/group/GroupResourceTest.java index 70b4e93..61cefac 100644 --- a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/group/GroupResourceTest.java +++ b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/group/GroupResourceTest.java @@ -44,6 +44,7 @@ import org.iotivity.cloud.base.protocols.enums.Observe; import org.iotivity.cloud.base.protocols.enums.RequestMethod; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.util.Cbor; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -93,6 +94,14 @@ public class GroupResourceTest { }).when(mMockDevice).sendResponse(Mockito.anyObject()); } + @After + public void resetAccountDatabase() throws Exception { + MongoDB mongoDB = new MongoDB(Constants.DB_NAME); + mongoDB.createTable(Constants.USER_TABLE); + mongoDB.createTable(Constants.TOKEN_TABLE); + mongoDB.createTable(Constants.GROUP_TABLE); + } + @Test public void testCreateGroup() throws Exception { getTestMethodName(); diff --git a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteResourceTest.java b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteResourceTest.java index 2f7600d..e7f84ce 100644 --- a/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteResourceTest.java +++ b/cloud/account/src/test/java/org/iotivity/cloud/accountserver/resources/acl/invite/InviteResourceTest.java @@ -33,6 +33,7 @@ import java.util.concurrent.CountDownLatch; import org.iotivity.cloud.accountserver.Constants; import org.iotivity.cloud.accountserver.db.MongoDB; +import org.iotivity.cloud.accountserver.resources.acl.group.GroupResource; import org.iotivity.cloud.base.device.CoapDevice; import org.iotivity.cloud.base.exception.ServerException.PreconditionFailedException; import org.iotivity.cloud.base.protocols.IRequest; @@ -53,13 +54,18 @@ import org.mockito.stubbing.Answer; public class InviteResourceTest { private static final String INVITE_URI = Constants.INVITE_FULL_URI; + private static final String GROUP_URI = Constants.GROUP_FULL_URI; private static final String TEST_INVITE_USER = "u0001"; private static final String TEST_INVITED_USER = "u0002"; private static final String TEST_GROUP_ID = "g0001"; + private String mInvitedGroupId = null; + private InviteResource mInviteResource = null; + private GroupResource mGroupResource = new GroupResource(); + private CountDownLatch mLatch = null; private CoapDevice mMockDevice = null; @@ -91,6 +97,18 @@ public class InviteResourceTest { CoapResponse resp = (CoapResponse) args[0]; mResponse = resp; + if (resp.getPayloadSize() != 0) { + + HashMap payloadData = mCbor + .parsePayloadFromCbor(resp.getPayload(), + HashMap.class); + + if (payloadData.containsKey(Constants.REQ_GROUP_ID)) { + mInvitedGroupId = (String) payloadData + .get(Constants.REQ_GROUP_ID); + } + } + mLatch.countDown(); return resp; @@ -247,11 +265,25 @@ public class InviteResourceTest { } @Test - public void testDeleteInvitation() throws Exception { + public void testDeleteInvitationForAccept() throws Exception { - sendInvitation(TEST_GROUP_ID, TEST_INVITED_USER); + createGroup(TEST_INVITE_USER, "Public"); + sendInvitation(mInvitedGroupId, TEST_INVITED_USER); - deleteInvitation(TEST_GROUP_ID, TEST_INVITED_USER, ""); + deleteInvitationWithQuery(mInvitedGroupId, TEST_INVITED_USER, true); + + assertTrue(mLatch.await(1L, SECONDS)); + assertEquals(mResponse.getStatus(), ResponseStatus.DELETED); + + } + + @Test + public void testDeleteInvitationForDeny() throws Exception { + + createGroup(TEST_INVITE_USER, "Public"); + sendInvitation(mInvitedGroupId, TEST_INVITED_USER); + + deleteInvitationWithQuery(mInvitedGroupId, TEST_INVITED_USER, false); assertTrue(mLatch.await(1L, SECONDS)); assertEquals(mResponse.getStatus(), ResponseStatus.DELETED); @@ -347,4 +379,43 @@ public class InviteResourceTest { return false; } + private void deleteInvitationWithQuery(String gid, String uid, + boolean accept) { + + int acceptInt = 0; + + if (accept) + acceptInt = 1; + + String uriQuery = Constants.REQ_GROUP_ID + "=" + gid + ";" + + Constants.REQ_UUID_ID + "=" + uid + ";" + + Constants.REQ_INVITE_ACCEPT + "=" + acceptInt; + + IRequest request = MessageBuilder.createRequest(RequestMethod.DELETE, + INVITE_URI, uriQuery); + + mInviteResource.onDefaultRequestReceived(mMockDevice, request); + } + + private void createGroup(String gmid, String gtype) { + + IRequest request = createGroupRequest(gmid, gtype); + + mGroupResource.onDefaultRequestReceived(mMockDevice, request); + } + + private IRequest createGroupRequest(String uuid, String gtype) { + + IRequest request = null; + + HashMap payloadData = new HashMap(); + payloadData.put("gmid", uuid); + payloadData.put("gtype", gtype); + + request = MessageBuilder.createRequest(RequestMethod.POST, GROUP_URI, + null, ContentFormat.APPLICATION_CBOR, + mCbor.encodingPayloadToCbor(payloadData)); + + return request; + } } \ No newline at end of file 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 766cd3a..8ca99b5 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 @@ -50,5 +50,5 @@ public class Constants extends OICConstants { public static final String REQ_LINKS = "links"; public static final String REQ_HREF = "href"; - public static final String REQ_CRL = "crl"; + public static final String REQ_CRL = "crl"; } diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/DeviceServerSystem.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/DeviceServerSystem.java index 772a051..1fc959c 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/DeviceServerSystem.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/DeviceServerSystem.java @@ -52,6 +52,12 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +/** + * + * This class provides a set of APIs to manage all of request + * + */ + public class DeviceServerSystem extends ServerSystem { IRequestChannel mRDServer = null; @@ -60,9 +66,20 @@ public class DeviceServerSystem extends ServerSystem { mRDServer = ConnectorPool.getConnection("rd"); } + /** + * + * This class provides a set of APIs to manage device pool. + * + */ public class CoapDevicePool { HashMap mMapDevice = new HashMap<>(); + /** + * API for adding device information into pool. + * + * @param device + * device to be added + */ public void addDevice(Device device) { String deviceId = ((CoapDevice) device).getDeviceId(); synchronized (mMapDevice) { @@ -70,6 +87,12 @@ public class DeviceServerSystem extends ServerSystem { } } + /** + * API for removing device information into pool. + * + * @param device + * device to be removed + */ public void removeDevice(Device device) throws ClientException { String deviceId = ((CoapDevice) device).getDeviceId(); synchronized (mMapDevice) { @@ -91,6 +114,12 @@ public class DeviceServerSystem extends ServerSystem { } } + /** + * API for getting device information. + * + * @param deviceId + * device id to get device + */ public Device queryDevice(String deviceId) { Device device = null; synchronized (mMapDevice) { @@ -102,6 +131,11 @@ public class DeviceServerSystem extends ServerSystem { CoapDevicePool mDevicePool = new CoapDevicePool(); + /** + * + * This class provides a set of APIs to manage life cycle of coap message. + * + */ @Sharable class CoapLifecycleHandler extends ChannelDuplexHandler { @Override @@ -184,6 +218,14 @@ public class DeviceServerSystem extends ServerSystem { } } + /** + * API for sending state to resource directory + * + * @param deviceId + * device id to be sent to resource directory + * @param state + * device state to be sent to resource directory + */ public void sendDevicePresence(String deviceId, String state) { Cbor> cbor = new Cbor<>(); diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/DiResource.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/DiResource.java index ae83028..cc029c4 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/DiResource.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/DiResource.java @@ -45,6 +45,12 @@ import org.iotivity.cloud.ciserver.Constants; import org.iotivity.cloud.ciserver.DeviceServerSystem.CoapDevicePool; import org.iotivity.cloud.util.Cbor; +/** + * + * This class provides a set of APIs to send requests about message to another + * device + * + */ public class DiResource extends Resource { private CoapDevicePool mDevicePool = null; @@ -108,6 +114,12 @@ public class DiResource extends Resource { null); } + /** + * + * This class provides a set of APIs to handling message contains link + * interface. + * + */ class LinkInterfaceHandler implements IResponseEventHandler { private Cbor>> mCbor = new Cbor<>(); private String mTargetDI = null; @@ -143,6 +155,15 @@ public class DiResource extends Resource { } } + /** + * API for handling optional method for handling packet contains link + * interface. + * + * @param srcDevice + * device information contains response channel + * @param request + * received request to relay + */ public void onLinkInterfaceRequestReceived(Device srcDevice, IRequest request) throws ServerException { IRequestChannel requestChannel = getTargetDeviceChannel(request); @@ -175,7 +196,6 @@ public class DiResource extends Resource { } } - // This is optional method for packet handling @Override public void onDefaultRequestReceived(Device srcDevice, IRequest request) throws ServerException { diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Account.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Account.java index 572e7ba..4e41179 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Account.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Account.java @@ -37,6 +37,12 @@ import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; +/** + * + * This class provides a set of APIs to send requests about account to account + * + */ + public class Account extends Resource { IRequestChannel mASServer = null; diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AccountSession.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AccountSession.java index 2722bcb..7f3bf84 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AccountSession.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AccountSession.java @@ -35,6 +35,12 @@ import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; import org.iotivity.cloud.util.Cbor; +/** + * + * This class provides a set of APIs to send requests about session to account + * + */ + public class AccountSession extends Resource { IRequestChannel mAuthServer = null; private Cbor> mCbor = new Cbor<>(); diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Acl.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Acl.java index 6adccec..e16aaf5 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Acl.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Acl.java @@ -31,6 +31,12 @@ import org.iotivity.cloud.base.protocols.IRequest; import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; +/** + * + * This class provides a set of APIs to send requests about acl to account + * + */ + public class Acl extends Resource { IRequestChannel mAuthServer = null; diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AclGroup.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AclGroup.java index 8a690d0..e9bed77 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AclGroup.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AclGroup.java @@ -36,6 +36,12 @@ import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; import org.iotivity.cloud.util.Cbor; +/** + * + * This class provides a set of APIs to send requests about group to account + * + */ + public class AclGroup extends Resource { private IRequestChannel mAuthServer = null; diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AclInvite.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AclInvite.java index 54e46af..ff05fab 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AclInvite.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AclInvite.java @@ -35,6 +35,12 @@ import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; import org.iotivity.cloud.util.Cbor; +/** + * + * This class provides a set of APIs to send requests about invite to account + * + */ + public class AclInvite extends Resource { IRequestChannel mAuthServer = null; diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Certificate.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Certificate.java index e0e8e31..0bbf181 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Certificate.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/Certificate.java @@ -31,12 +31,19 @@ import org.iotivity.cloud.base.protocols.IRequest; import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; +/** + * + * This class provides a set of APIs to send requests about certificate to + * account + * + */ + public class Certificate extends Resource { IRequestChannel mAuthServer = null; public Certificate() { - super(Arrays.asList(Constants.PREFIX_OIC, - Constants.CREDPROV_URI, Constants.CERT_URI)); + super(Arrays.asList(Constants.PREFIX_OIC, Constants.CREDPROV_URI, + Constants.CERT_URI)); mAuthServer = ConnectorPool.getConnection("account"); } diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/mq/MessageQueue.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/mq/MessageQueue.java index 687585b..4286902 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/mq/MessageQueue.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/mq/MessageQueue.java @@ -31,6 +31,13 @@ import org.iotivity.cloud.base.protocols.IRequest; import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; +/** + * + * This class provides a set of APIs to send requests about MQ message to + * message queue + * + */ + public class MessageQueue extends Resource { IRequestChannel mPSServer = null; diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/DevicePresence.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/DevicePresence.java index 5f9e0e2..864c755 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/DevicePresence.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/DevicePresence.java @@ -40,6 +40,13 @@ import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; import org.iotivity.cloud.util.Cbor; +/** + * + * This class provides a set of APIs to send requests about device presence to + * resource directory + * + */ + public class DevicePresence extends Resource { IRequestChannel mASServer = null; private Cbor> mCbor = new Cbor<>(); 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 fa024d0..a2fa953 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 @@ -42,6 +42,13 @@ import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; import org.iotivity.cloud.util.Cbor; +/** + * + * This class provides a set of APIs to send requests about publish resource to + * resource directory + * + */ + public class ResourceDirectory extends Resource { private Cbor> mCbor = new Cbor<>(); IRequestChannel mRDServer = null; @@ -72,23 +79,23 @@ 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"); } } @@ -121,8 +128,8 @@ public class ResourceDirectory extends Resource { null, ContentFormat.APPLICATION_CBOR, convertedPayload); - mRDServer.sendRequest(mRequest, new PublishResponseHandler( - mSrcDevice)); + mRDServer.sendRequest(mRequest, + new PublishResponseHandler(mSrcDevice)); break; default: @@ -135,8 +142,8 @@ public class ResourceDirectory extends Resource { private byte[] convertPublishHref(IRequest request, Device device) { Cbor> cbor = new Cbor<>(); - HashMap payload = cbor.parsePayloadFromCbor( - request.getPayload(), HashMap.class); + HashMap payload = cbor + .parsePayloadFromCbor(request.getPayload(), HashMap.class); if (verifyPublishPayload(payload) == false) { @@ -213,8 +220,8 @@ public class ResourceDirectory extends Resource { private byte[] convertResponseHref(IResponse response) { Cbor> cbor = new Cbor<>(); - HashMap payload = cbor.parsePayloadFromCbor( - response.getPayload(), HashMap.class); + HashMap payload = cbor + .parsePayloadFromCbor(response.getPayload(), HashMap.class); ArrayList> links = (ArrayList>) payload .get(Constants.REQ_LINKS); diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceFind.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceFind.java index f5e73ba..320ebf8 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceFind.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceFind.java @@ -40,24 +40,32 @@ import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; import org.iotivity.cloud.util.Cbor; +/** + * + * This class provides a set of APIs to send requests about find resource to + * resource directory + * + */ + public class ResourceFind extends Resource { IRequestChannel mASServer = null; + IRequestChannel mRDServer = null; private Cbor> mCbor = new Cbor<>(); public ResourceFind() { super(Arrays.asList(Constants.PREFIX_OIC, Constants.WELL_KNOWN_URI)); mASServer = ConnectorPool.getConnection("account"); + mRDServer = ConnectorPool.getConnection("rd"); } class AccountReceiveHandler implements IResponseEventHandler { - IRequestChannel mRDServer = null; private Device mSrcDevice; private IRequest mRequest; public AccountReceiveHandler(IRequest request, Device srcDevice) { - mRDServer = ConnectorPool.getConnection("rd"); + mSrcDevice = srcDevice; mRequest = request; } @@ -89,18 +97,12 @@ public class ResourceFind extends Resource { } } else { String additionalQuery = makeAdditionalQuery( - payloadData, mSrcDevice.getDeviceId()); - if (additionalQuery == null) { - mSrcDevice.sendResponse( - MessageBuilder.createResponse(mRequest, - ResponseStatus.BAD_REQUEST)); - return; - } + payloadData); mRequest = MessageBuilder.modifyRequest(mRequest, null, - additionalQuery - + (mRequest.getUriQuery() != null - ? ";" + mRequest.getUriQuery() - : ""), + (mRequest.getUriQuery() != null + ? mRequest.getUriQuery() : "") + + (additionalQuery == null ? "" + : ";" + additionalQuery), null, null); } @@ -112,13 +114,16 @@ public class ResourceFind extends Resource { } } - private String makeAdditionalQuery(HashMap payloadData, - String did) { + private String makeAdditionalQuery( + HashMap payloadData) { StringBuilder additionalQuery = new StringBuilder(); - List deviceList = getResponseDeviceList(payloadData); + if (deviceList == null) { + return null; + } + if (deviceList.isEmpty()) { return null; } @@ -146,19 +151,26 @@ public class ResourceFind extends Resource { @Override public void onDefaultRequestReceived(Device srcDevice, IRequest request) throws ServerException { - StringBuffer uriQuery = new StringBuffer(); - uriQuery.append(Constants.REQ_MEMBER_ID + "=" + srcDevice.getUserId()); - - StringBuffer uriPath = new StringBuffer(); - uriPath.append(Constants.PREFIX_OIC + "/"); - uriPath.append(Constants.ACL_URI + "/"); - uriPath.append(Constants.GROUP_URI + "/"); - uriPath.append(srcDevice.getUserId()); - - IRequest requestToAS = MessageBuilder.createRequest(RequestMethod.GET, - uriPath.toString(), uriQuery.toString()); - - mASServer.sendRequest(requestToAS, - new AccountReceiveHandler(request, srcDevice)); + if (request.getUriQuery() != null && request.getUriQueryMap() + .containsKey(Constants.REQ_DEVICE_ID)) { + + mRDServer.sendRequest(request, srcDevice); + } else { + StringBuffer uriQuery = new StringBuffer(); + uriQuery.append( + Constants.REQ_MEMBER_ID + "=" + srcDevice.getUserId()); + + StringBuffer uriPath = new StringBuffer(); + uriPath.append(Constants.PREFIX_OIC + "/"); + uriPath.append(Constants.ACL_URI + "/"); + uriPath.append(Constants.GROUP_URI + "/"); + uriPath.append(srcDevice.getUserId()); + + IRequest requestToAS = MessageBuilder.createRequest( + RequestMethod.GET, uriPath.toString(), uriQuery.toString()); + + mASServer.sendRequest(requestToAS, + new AccountReceiveHandler(request, srcDevice)); + } } } \ No newline at end of file diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourcePresence.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourcePresence.java index f8e232b..f708115 100644 --- a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourcePresence.java +++ b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourcePresence.java @@ -40,6 +40,13 @@ import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.ciserver.Constants; import org.iotivity.cloud.util.Cbor; +/** + * + * This class provides a set of APIs to send requests about resource presence to + * resource directory + * + */ + public class ResourcePresence extends Resource { IRequestChannel mASServer = null; private Cbor> mCbor = new Cbor<>(); diff --git a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/DevicePresenceTest.java b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/DevicePresenceTest.java index 42943f6..1d58984 100644 --- a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/DevicePresenceTest.java +++ b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/DevicePresenceTest.java @@ -56,18 +56,16 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; public class DevicePresenceTest { - 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 String mDi = "B371C481-38E6-4D47-8320-7688D8A5B58C"; - private CoapDevice mMockDevice = mock(CoapDevice.class); - private IRequest mReq = null; - private DeviceServerSystem mDeviceServerSystem = new DeviceServerSystem(); - final CountDownLatch mLatch = new CountDownLatch(1); + private static final String DEVICE_PRS_REQ_URI = Constants.DEVICE_PRESENCE_FULL_URI; + private String mDi = "B371C481-38E6-4D47-8320-7688D8A5B58C"; + private CoapDevice mMockDevice = mock(CoapDevice.class); + private IRequest mReq = null; + private DeviceServerSystem mDeviceServerSystem = new DeviceServerSystem(); + final CountDownLatch mLatch = new CountDownLatch(1); @Mock - private IRequestChannel mRequestChannel; + private IRequestChannel mRequestChannel; @InjectMocks - private DevicePresence mPrsHandler = new DevicePresence(); + private DevicePresence mPrsHandler = new DevicePresence(); @Before public void setUp() throws Exception { diff --git a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceFindTest.java b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceFindTest.java index 708edd2..109b22a 100644 --- a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceFindTest.java +++ b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceFindTest.java @@ -65,8 +65,10 @@ public class ResourceFindTest { private DeviceServerSystem mDeviceServerSystem = new DeviceServerSystem(); final CountDownLatch mLatch = new CountDownLatch(1); - @Mock - private IRequestChannel mRequestChannel; + @Mock(name = "mRDServer") + IRequestChannel mRequestChannelRDServer; + @Mock(name = "mASServer") + IRequestChannel mRequestChannelASServer; @InjectMocks private ResourceFind mResHandler = new ResourceFind(); @@ -105,8 +107,27 @@ public class ResourceFindTest { mLatch.countDown(); return null; } - }).when(mRequestChannel).sendRequest(Mockito.any(IRequest.class), - Mockito.any(CoapDevice.class)); + }).when(mRequestChannelRDServer).sendRequest( + Mockito.any(IRequest.class), Mockito.any(CoapDevice.class)); + + Mockito.doAnswer(new Answer() { + @Override + public CoapRequest answer(InvocationOnMock invocation) + throws Throwable { + Object[] args = invocation.getArguments(); + CoapRequest request = (CoapRequest) args[0]; + System.out.println( + "\t----------payload : " + request.getPayloadString()); + System.out.println( + "\t----------uripath : " + request.getUriPath()); + System.out.println( + "\t---------uriquery : " + request.getUriQuery()); + mReq = request; + mLatch.countDown(); + return null; + } + }).when(mRequestChannelASServer).sendRequest( + Mockito.any(IRequest.class), Mockito.any(CoapDevice.class)); } // @InjectMocks for testSpecificDeviceonResponseReceived @@ -181,7 +202,7 @@ public class ResourceFindTest { System.out.println( "\t--------------OnRequestReceived(RD) Resource Find (entire deivces) Test------------"); IRequest request = MessageBuilder.createRequest(RequestMethod.GET, - TEST_RESOURCE_FIND_URI, "rt=core.light;di=" + di); + TEST_RESOURCE_FIND_URI, "rt=core.light"); mResHandler.onRequestReceived(mockDevice, request); HashMap> queryMap = mReq.getUriQueryMap(); assertTrue(mLatch.await(1L, SECONDS)); @@ -201,8 +222,8 @@ public class ResourceFindTest { // assertion: if the request packet from the CI contains the query // which includes device ID and the accesstoken assertTrue(mLatch.await(1L, SECONDS)); - assertTrue(queryMap.containsKey("mid")); - assertEquals(mReq.getUriPath(), Constants.GROUP_FULL_URI + "/null"); + assertTrue(queryMap.containsKey("di")); + assertEquals(mReq.getUriPath(), Constants.WELL_KNOWN_FULL_URI); } private IResponse responseFromAccountServer() { diff --git a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourcePresenceTest.java b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourcePresenceTest.java index c28a978..9ed3e0a 100644 --- a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourcePresenceTest.java +++ b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourcePresenceTest.java @@ -56,7 +56,6 @@ import org.mockito.stubbing.Answer; public class ResourcePresenceTest { 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 String mDi = "B371C481-38E6-4D47-8320-7688D8A5B58C"; private CoapDevice mMockDevice = mock(CoapDevice.class); diff --git a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/MessageQueueUtils.java b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/MessageQueueUtils.java index 7947944..052bc14 100644 --- a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/MessageQueueUtils.java +++ b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/MessageQueueUtils.java @@ -26,8 +26,23 @@ import java.util.HashMap; import org.iotivity.cloud.util.Cbor; import org.iotivity.cloud.util.Log; +/** + * + * This class provides a set of APIs of utilities for MessageQueue. + * + */ public class MessageQueueUtils { + /** + * API to get data in the payload with specific property key + * + * @param payload + * payload received + * @param key + * property key to get data + * + * @return extracted data in payload + */ public static T extractDataFromPayload(byte[] payload, String key) { if (payload == null || key.isEmpty()) { @@ -48,6 +63,16 @@ public class MessageQueueUtils { return parsedData.get(key); } + /** + * API to build payload with property key and value + * + * @param key + * property key + * @param value + * property value + * + * @return cbor encoded payload with providing key and value + */ public static byte[] buildPayload(String key, T value) { Cbor> cbor = new Cbor<>(); diff --git a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaCommonWrapper.java b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaCommonWrapper.java index a67f8c1..dfc9458 100644 --- a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaCommonWrapper.java +++ b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaCommonWrapper.java @@ -32,6 +32,11 @@ import org.I0Itec.zkclient.ZkConnection; import org.iotivity.cloud.mqserver.Constants; import org.iotivity.cloud.util.Log; +/** + * + * This class provides a set of APIs to use Kafka APIs for basic operation. + * + */ public class KafkaCommonWrapper { private ZkClient mZkClient = null; @@ -47,6 +52,15 @@ public class KafkaCommonWrapper { false); } + /** + * API to create topic using Kafka utilities + * + * @param topic + * name of topic to create + * + * @return returns true if the topic is successfully created, otherwise + * false + */ public boolean createTopic(String topic) { Log.d("kafka createTopic - " + topic); @@ -64,6 +78,15 @@ public class KafkaCommonWrapper { return true; } + /** + * API to delete topic using Kafka utilities + * + * @param topic + * name of topic to delete + * + * @return returns true if the topic is successfully deleted, otherwise + * false + */ public boolean deleteTopic(String topic) { Log.d("kafka deleteTopic - " + topic); diff --git a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaConsumerWrapper.java b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaConsumerWrapper.java index 3ca503b..73e1e50 100644 --- a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaConsumerWrapper.java +++ b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaConsumerWrapper.java @@ -54,6 +54,12 @@ import org.iotivity.cloud.mqserver.Constants; import org.iotivity.cloud.mqserver.topic.Topic; import org.iotivity.cloud.util.Log; +/** + * + * This class provides a set of APIs to use Kafka consumer APIs for receiving + * messages. + * + */ public class KafkaConsumerWrapper { private String mTopicName = null; @@ -88,11 +94,21 @@ public class KafkaConsumerWrapper { false); } + /** + * API to check if Kafka consumer is started + * + * @return returns true if Kafka consumer started, otherwise false + */ public boolean consumerStarted() { return mConsumerStarted; } - // TODO exception handling + /** + * API to subscribe Kafka topic to receive messages + * + * @return returns true if the topic is successfully subscribed, otherwise + * false + */ public boolean subscribeTopic() { Log.d("kafka subscribeTopic - " + mTopicName); @@ -148,6 +164,12 @@ public class KafkaConsumerWrapper { return true; } + /** + * API to unsubscribe Kafka topic to stop receiving messages + * + * @return returns true if the topic is successfully unsubscribed, otherwise + * false + */ public boolean unsubscribeTopic() { Log.d("kafka unsubscribeTopic - " + mTopicName); @@ -168,6 +190,9 @@ public class KafkaConsumerWrapper { return true; } + /** + * API to close Kafka consumer connection + */ public void closeConnection() { if (mConsumerStarted == true) { @@ -178,6 +203,11 @@ public class KafkaConsumerWrapper { mZkClient.close(); } + /** + * API to get all messages from Kafka topic + * + * @return returns the list of messages published to the topic + */ public ArrayList getMessages() { Log.d("kafka get all messages - " + mTopicName); diff --git a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaProducerWrapper.java b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaProducerWrapper.java index 9b3f2c1..164baf9 100644 --- a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaProducerWrapper.java +++ b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaProducerWrapper.java @@ -28,6 +28,12 @@ import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.ProducerRecord; import org.iotivity.cloud.util.Log; +/** + * + * This class provides a set of APIs to use Kafka producer APIs for publishing + * messages. + * + */ public class KafkaProducerWrapper { private String mTopicName = null; @@ -44,7 +50,15 @@ public class KafkaProducerWrapper { mProducer = new KafkaProducer<>(buildPropertiesForPublish()); } - // TODO handle exception + /** + * API to publish message to Kafka topic + * + * @param message + * message to publish + * + * @return returns true if the message is successfully published, otherwise + * false + */ public boolean publishMessage(byte[] message) { Log.d("kafka publishMessage - " + mTopicName); @@ -58,6 +72,9 @@ public class KafkaProducerWrapper { return true; } + /** + * API to close Kafka producer connection + */ public void closeConnection() { mProducer.close(); diff --git a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/resources/MQBrokerResource.java b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/resources/MQBrokerResource.java index 5b67c3f..4d07cdc 100644 --- a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/resources/MQBrokerResource.java +++ b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/resources/MQBrokerResource.java @@ -43,6 +43,11 @@ import org.iotivity.cloud.mqserver.MessageQueueUtils; import org.iotivity.cloud.mqserver.topic.Topic; import org.iotivity.cloud.mqserver.topic.TopicManager; +/** + * + * This class provides a set of APIs to handle requests to MessageQueue Broker. + * + */ public class MQBrokerResource extends Resource { private TopicManager mTopicManager = new TopicManager(); @@ -51,6 +56,14 @@ public class MQBrokerResource extends Resource { super(Arrays.asList(Constants.PREFIX_OIC, Constants.MQ_BROKER_URI)); } + /** + * API to set Kafka zookeeper and broker information + * + * @param zookeeper + * address and port number of the zookeeper + * @param broker + * address and port number of the Kafka broker + */ public void setKafkaInformation(String zookeeper, String broker) { mTopicManager.setKafkaInformation(zookeeper, broker); } @@ -83,8 +96,7 @@ public class MQBrokerResource extends Resource { private IResponse handleGetRequest(Device srcDevice, IRequest request) { // DISCOVER - if (request.getUriPathSegments().size() == getUriPathSegments() - .size()) { + if (request.getUriPathSegments().size() == getUriPathSegments().size()) { return discoverTopic(request); } @@ -106,8 +118,7 @@ public class MQBrokerResource extends Resource { // CREATE topic private IResponse handlePutRequest(IRequest request) { - if (request.getUriPathSegments().size() == getUriPathSegments() - .size()) { + if (request.getUriPathSegments().size() == getUriPathSegments().size()) { throw new BadRequestException( "topic name is not included in request uri"); @@ -131,8 +142,7 @@ public class MQBrokerResource extends Resource { private IResponse createTopic(IRequest request) { // main topic creation request - if (request.getUriPathSegments().size() == getUriPathSegments().size() - + 1) { + if (request.getUriPathSegments().size() == getUriPathSegments().size() + 1) { return createMainTopic(request); } @@ -161,8 +171,8 @@ public class MQBrokerResource extends Resource { String uriPath = request.getUriPath(); String parentName = uriPath.substring(0, uriPath.lastIndexOf('/')); - String targetName = request.getUriPathSegments() - .get(request.getUriPathSegments().size() - 1); + String targetName = request.getUriPathSegments().get( + request.getUriPathSegments().size() - 1); Topic parentTopic = mTopicManager.getTopic(parentName); @@ -233,14 +243,14 @@ public class MQBrokerResource extends Resource { } return MessageBuilder.createResponse(request, ResponseStatus.CONTENT, - ContentFormat.APPLICATION_CBOR, MessageQueueUtils - .buildPayload(Constants.MQ_TOPICLIST, topicList)); + ContentFormat.APPLICATION_CBOR, MessageQueueUtils.buildPayload( + Constants.MQ_TOPICLIST, topicList)); } private IResponse createMainTopic(IRequest request) { - String topicName = request.getUriPathSegments() - .get(request.getUriPathSegments().size() - 1); + String topicName = request.getUriPathSegments().get( + request.getUriPathSegments().size() - 1); String type = new String(); diff --git a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/topic/Topic.java b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/topic/Topic.java index 4458a35..28dc14e 100644 --- a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/topic/Topic.java +++ b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/topic/Topic.java @@ -39,6 +39,11 @@ import org.iotivity.cloud.mqserver.kafka.KafkaConsumerWrapper; import org.iotivity.cloud.mqserver.kafka.KafkaProducerWrapper; import org.iotivity.cloud.util.Cbor; +/** + * + * This class provides a set of APIs to handle requests to MessageQueue Topic. + * + */ public class Topic { private TopicManager mTopicManager = null; @@ -88,18 +93,36 @@ public class Topic { mLatestData = mCbor.encodingPayloadToCbor(data); } + /** + * API to get name of the topic + * + * @return name of the topic + */ public String getName() { return mName; } + /** + * API to get type of the topic + * + * @return type of the topic + */ public String getType() { return mType; } + /** + * API to handle request to create subtopic + * + * @param request + * received request for subtopic creation + * + * @return response of subtopic creation + */ public IResponse handleCreateSubtopic(IRequest request) { - String newTopicName = request.getUriPathSegments() - .get(request.getUriPathSegments().size() - 1); + String newTopicName = request.getUriPathSegments().get( + request.getUriPathSegments().size() - 1); String newTopicType = new String(); @@ -128,6 +151,16 @@ public class Topic { return response; } + /** + * API to handle request to remove subtopic + * + * @param request + * received request for subtopic removal + * @param topicName + * subtopic name to remove + * + * @return response of subtopic removal + */ public IResponse handleRemoveSubtopic(IRequest request, String topicName) { Topic targetTopic = getSubtopic(topicName); @@ -149,6 +182,16 @@ public class Topic { return MessageBuilder.createResponse(request, ResponseStatus.DELETED); } + /** + * API to handle request to subscribe the topic + * + * @param srcDevice + * device that sent request for topic subscription + * @param request + * received request for topic subscription + * + * @return response of topic subscription + */ public IResponse handleSubscribeTopic(Device srcDevice, IRequest request) { // get latest data from kafka if consumer started for the first time @@ -166,20 +209,28 @@ public class Topic { } synchronized (mSubscribers) { - mSubscribers.put(request.getRequestId(), - new TopicSubscriber(srcDevice, request)); + mSubscribers.put(request.getRequestId(), new TopicSubscriber( + srcDevice, request)); } return MessageBuilder.createResponse(request, ResponseStatus.CONTENT, ContentFormat.APPLICATION_CBOR, mLatestData); } + /** + * API to handle request to unsubscribe the topic + * + * @param request + * received request for topic unsubscription + * + * @return response of topic unsubscription + */ public IResponse handleUnsubscribeTopic(IRequest request) { synchronized (mSubscribers) { - TopicSubscriber subscriber = mSubscribers - .get(request.getRequestId()); + TopicSubscriber subscriber = mSubscribers.get(request + .getRequestId()); mSubscribers.remove(subscriber.mRequest.getRequestId()); @@ -194,6 +245,14 @@ public class Topic { ContentFormat.APPLICATION_CBOR, mLatestData); } + /** + * API to handle request to publish message to the topic + * + * @param request + * received request for message publication + * + * @return response of message publication + */ public IResponse handlePublishMessage(IRequest request) { byte[] payload = request.getPayload(); @@ -217,6 +276,14 @@ public class Topic { return MessageBuilder.createResponse(request, ResponseStatus.CHANGED); } + /** + * API to handle request to read latest message in the topic + * + * @param request + * received request for reading latest message in topic + * + * @return response of reading latest message in topic + */ public IResponse handleReadMessage(IRequest request) { // if consumer is not started, get data from kafka broker if (mKafkaConsumerOperator.consumerStarted() == false) { @@ -232,13 +299,21 @@ public class Topic { ContentFormat.APPLICATION_CBOR, mLatestData); } + /** + * API to close connection of Kafka producer and consumer + */ public void cleanup() { mKafkaProducerOperator.closeConnection(); mKafkaConsumerOperator.closeConnection(); } - // callback from Kafka Consumer + /** + * callback from Kafka Consumer to get published message + * + * @param message + * published message + */ public void onMessagePublished(byte[] message) { mLatestData = message; @@ -261,8 +336,8 @@ public class Topic { synchronized (mSubscribers) { for (TopicSubscriber subscriber : mSubscribers.values()) { - subscriber.mSubscriber.sendResponse( - MessageBuilder.createResponse(subscriber.mRequest, + subscriber.mSubscriber.sendResponse(MessageBuilder + .createResponse(subscriber.mRequest, ResponseStatus.CONTENT, ContentFormat.APPLICATION_CBOR, mLatestData)); } diff --git a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/topic/TopicManager.java b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/topic/TopicManager.java index c36a510..5280915 100644 --- a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/topic/TopicManager.java +++ b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/topic/TopicManager.java @@ -25,6 +25,11 @@ import java.util.ArrayList; import org.iotivity.cloud.mqserver.kafka.KafkaCommonWrapper; +/** + * + * This class provides a set of APIs to manage topics in MessageQueue Broker + * + */ public class TopicManager { private ArrayList mTopics = new ArrayList<>(); @@ -35,6 +40,14 @@ public class TopicManager { private KafkaCommonWrapper mKafkaCommonOperator = null; + /** + * API to create topic + * + * @param topic + * topic to create + * + * @return returns true if the topic successfully created, otherwise false + */ public boolean createTopic(Topic topic) { if (mKafkaCommonOperator.createTopic(topic.getName()) == false) { @@ -48,11 +61,24 @@ public class TopicManager { return true; } + /** + * API to remove topic + * + * @param topic + * topic to remove + * + * @return returns true if the topic successfully removed, otherwise false + */ public boolean removeTopic(Topic topic) { return removeTopics(topic.getName()); } + /** + * API to get list of topics + * + * @return returns list of topic uris + */ public ArrayList getTopicList() { ArrayList topicList = new ArrayList<>(); @@ -66,6 +92,14 @@ public class TopicManager { return topicList; } + /** + * API to get list of topics with specific topic type + * + * @param type + * topic type + * + * @return returns list of topic uris searched with the topic type + */ public ArrayList getTopicListByType(String type) { ArrayList topicList = new ArrayList<>(); @@ -82,6 +116,14 @@ public class TopicManager { return topicList; } + /** + * API to get topic with topic name + * + * @param topicName + * topic name to search + * + * @return topic searched with the topic name + */ public Topic getTopic(String topicName) { Topic foundTopic = null; @@ -99,6 +141,14 @@ public class TopicManager { return foundTopic; } + /** + * API to set Kafka zookeeper and broker information + * + * @param zookeeper + * address and port number of the zookeeper + * @param broker + * address and port number of the Kafka broker + */ public void setKafkaInformation(String zookeeper, String broker) { mKafkaZookeeper = zookeeper; mKafkaBroker = broker; @@ -106,10 +156,20 @@ public class TopicManager { mKafkaCommonOperator = new KafkaCommonWrapper(zookeeper, broker); } + /** + * API to get zookeeper information + * + * @return address and port number of the zookeeper + */ public String getKafkaZookeeper() { return mKafkaZookeeper; } + /** + * API to get Kafka broker information + * + * @return address and port number of the Kafka broker + */ public String getKafkaBroker() { return mKafkaBroker; } diff --git a/cloud/messagequeue/src/test/java/org/iotivity/cloud/mqserver/resources/MQBrokerResourceTest.java b/cloud/messagequeue/src/test/java/org/iotivity/cloud/mqserver/resources/MQBrokerResourceTest.java index 6a3f102..ef8d1f4 100644 --- a/cloud/messagequeue/src/test/java/org/iotivity/cloud/mqserver/resources/MQBrokerResourceTest.java +++ b/cloud/messagequeue/src/test/java/org/iotivity/cloud/mqserver/resources/MQBrokerResourceTest.java @@ -35,6 +35,13 @@ import java.util.HashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; +import kafka.admin.TopicCommand; +import kafka.admin.TopicCommand.TopicCommandOptions; +import kafka.utils.ZKStringSerializer$; +import kafka.utils.ZkUtils; + +import org.I0Itec.zkclient.ZkClient; +import org.I0Itec.zkclient.ZkConnection; import org.iotivity.cloud.base.device.CoapDevice; import org.iotivity.cloud.base.exception.ServerException.ForbiddenException; import org.iotivity.cloud.base.exception.ServerException.NotFoundException; @@ -50,6 +57,7 @@ import org.iotivity.cloud.base.protocols.enums.RequestMethod; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.mqserver.Constants; import org.iotivity.cloud.util.Cbor; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -65,17 +73,17 @@ public class MQBrokerResourceTest { IResponse mResponse = null; CountDownLatch mLatch = null; + // insert user's zookeper and broker addresses + String mZookeeper = "127.0.0.1:2181"; + String mBroker = "127.0.0.1:9092"; + @Before // setup for each test public void setUp() throws Exception { mMqBrokerResource = new MQBrokerResource(); - // insert user's zookeper and broker addresses - String zookeeper = "127.0.0.1:2181"; - String broker = "127.0.0.1:9092"; - mTopicPrefix = "mqtestTopic"; - mMqBrokerResource.setKafkaInformation(zookeeper, broker); + mMqBrokerResource.setKafkaInformation(mZookeeper, mBroker); mLatch = new CountDownLatch(1); mResponse = null; // initialize response packet mMockDevice = mock(CoapDevice.class); @@ -94,6 +102,25 @@ public class MQBrokerResourceTest { }).when(mMockDevice).sendResponse(Mockito.anyObject()); } + @After + public void tearDown() throws Exception { + // delete topics in Kafka broker + ZkClient zkClient = new ZkClient(mZookeeper, 10000, 10000, + ZKStringSerializer$.MODULE$); + ZkUtils zkUtils = new ZkUtils(zkClient, new ZkConnection(mZookeeper), + false); + + String topic = MQ_BROKER_URI + "/*"; + topic = topic.replace('/', '.'); + + String[] arr = { "--topic", topic }; + TopicCommandOptions opts = new TopicCommandOptions(arr); + TopicCommand.deleteTopic(zkUtils, opts); + + zkClient.close(); + zkUtils.close(); + } + @Test // test topic creation public void testTopicCreationOnDefaultRequestReceived() throws Exception { @@ -251,6 +278,8 @@ public class MQBrokerResourceTest { if (latchSubscriber.getCount() == 0) { assertTrue(methodCheck(resp, ResponseStatus.CONTENT)); assertTrue(hashmapCheck(resp, "message")); + + DeleteTopic(mMockDevice, topic); } return resp; } diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/Constants.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/Constants.java index 57ef745..f4789bf 100644 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/Constants.java +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/Constants.java @@ -21,52 +21,61 @@ */ package org.iotivity.cloud.rdserver; -import java.util.Arrays; -import java.util.List; - import org.iotivity.cloud.base.OICConstants; public class Constants extends OICConstants { - public static final String RD_DB_NAME = "RD_DB"; - public static final String RD_TABLE = "RD_TABLE"; - public static final String PRESENCE_TABLE = "PRESENCE_TABLE"; - - public static final String DEVICE_NAME = "n"; - public static final String DEVICE_ID = "di"; - public static final String POLICY = "p"; - public static final String BITMAP = "bm"; - public static final String INS = "ins"; - public static final String DEVICE_TTL = "lt"; - public static final String RESOURCE_TTL = "ttl"; - public static final String HREF = "href"; - public static final String RESOURCE_TYPE = "rt"; - public static final String INTERFACE = "if"; - public static final String REL = "rel"; - public static final String TITLE = "title"; - public static final String ANCHOR = "anchor"; - public static final String MEDIA_TYPE = "type"; - public static final String LINKS = "links"; - public static final String RESOURCE_TYPE_RDPUBLISH = "oic.wk.rdpub"; - public static final List TAGS = Arrays - .asList(DEVICE_NAME, DEVICE_ID, DEVICE_TTL); - - public static final String SEARCH_TYPE = "st"; - public static final String SEARCH_TYPE_DEVICE_LIST = "didList"; - public static final String DEVICE_LIST_KEY = "devices"; - - // for '/oic/prs' resource - public static final String PRESENCE_STATE = "state"; - public static final String PRESENCE_LIST = "prslist"; + /** Database, Table name */ + public static final String RD_DB_NAME = "RD_DB"; + public static final String RD_TABLE = "RD_TABLE"; + public static final String PRESENCE_TABLE = "PRESENCE_TABLE"; - public static final String RS_NON = "non"; - public static final String RS_TRIGGER = "trg"; + /** A human friendly name of device */ + public static final String DEVICE_NAME = "n"; + /** An unique identifier of device */ + public static final String DEVICE_ID = "di"; + /** policies that apply for resource */ + public static final String POLICY = "p"; + /** To represent bitmap. */ + public static final String BITMAP = "bm"; + /** An ordinal number that is not repeated */ + public static final String INS = "ins"; + /** Time (in seconds) to indicate how long RD should publish this item */ + public static final String DEVICE_TTL = "lt"; + /** Time to live for this link */ + public static final String RESOURCE_TTL = "ttl"; + /** URI Reference */ + public static final String HREF = "href"; + /** Resource Types */ + public static final String RESOURCE_TYPE = "rt"; + /** Resource interface */ + public static final String INTERFACE = "if"; + /** Relation between target URI and context URI */ + public static final String REL = "rel"; + /** Title for the link relation */ + public static final String TITLE = "title"; + /** This is used to override the context URI */ + public static final String ANCHOR = "anchor"; + /** Media type. Default : application/json */ + public static final String MEDIA_TYPE = "type"; + /** To represent links. */ + public static final String LINKS = "links"; + /** To represent resource type with Publish RD. */ + public static final String RESOURCE_TYPE_RDPUBLISH = "oic.wk.rdpub"; - public static final long OBSERVE_REGISTER = 0; - public static final long OBSERVE_DEREGISTER = 1; + /** '/oic/prs' resource property */ + public static final String PRESENCE_STATE = "state"; + public static final String PRESENCE_ON = "on"; + public static final String PRESENCE_OFF = "off"; + public static final String PRESENCE_LIST = "prslist"; + public static final String DEVICE_PRESENCE = "device_presence"; - public static final byte RES_CREATE = 0; - public static final byte RES_CHANGE = 1; - public static final byte RES_DELETE = 2; + /** '/oic/ad' resource property */ + public static final String NON = "non"; + public static final String TRIGGER = "trg"; + public static final byte RES_CREATE = 0; + public static final byte RES_CHANGE = 1; + public static final byte RES_DELETE = 2; + public static final String RESOURCE_PRESENCE = "resource_presence"; } diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/ResourceDirectoryServer.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/ResourceDirectoryServer.java index 16fccc3..b5f41c2 100644 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/ResourceDirectoryServer.java +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/ResourceDirectoryServer.java @@ -32,6 +32,11 @@ import org.iotivity.cloud.rdserver.resources.presence.device.DevicePresenceResou import org.iotivity.cloud.rdserver.resources.presence.resource.ResPresenceResource; import org.iotivity.cloud.util.Log; +/** + * + * This class is in charge of running of resource directory server. + * + */ public class ResourceDirectoryServer { public static void main(String[] args) throws Exception { @@ -40,8 +45,7 @@ public class ResourceDirectoryServer { System.out.println("-----RD SERVER-----"); if (args.length != 2) { - Log.e("coap server port and TLS mode required\n" - + "ex) 5684 0\n"); + Log.e("coap server port and TLS mode required\n" + "ex) 5684 0\n"); return; } diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/DBManager.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/DBManager.java index aefb1bb..734c52f 100644 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/DBManager.java +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/DBManager.java @@ -23,65 +23,226 @@ package org.iotivity.cloud.rdserver.db; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import org.bson.Document; +import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException; import org.iotivity.cloud.rdserver.Constants; -import org.iotivity.cloud.rdserver.resources.presence.resource.ResPresencePayload; +/** + * + * This class provides a set of APIs to access a DataBase. + * + */ public class DBManager { - private static DBManager mDBManager = new DBManager(); - private MongoDB mMongoDB = null;; + private static DBManager mDBManager = new DBManager(); + private MongoDB mMongoDB = null; + private HashMap> mKeyField = new HashMap<>(); private DBManager() { + createDatabase(); + createTables(); + createIndexes(); + } + + /** + * API to return DBManager object + * + * @return DBManager DBManager object + */ + public static DBManager getInstance() { + return mDBManager; + } + + private void createDatabase() { + try { + mMongoDB = new MongoDB(Constants.RD_DB_NAME); - mMongoDB.createTable(Constants.RD_TABLE); - mMongoDB.createTable(Constants.PRESENCE_TABLE); } catch (Exception e) { - // TODO Auto-generated catch block e.printStackTrace(); + throw new InternalServerErrorException("Database create failed!"); } } - public static DBManager getInstance() { - return mDBManager; + private void createTables() { + mMongoDB.createTable(Constants.RD_TABLE); + mMongoDB.createTable(Constants.PRESENCE_TABLE); + } + + private void createIndexes() { + + ArrayList keys = new ArrayList<>(); + keys.add(Constants.DEVICE_ID); + keys.add(Constants.INS); + + mMongoDB.createIndex(Constants.RD_TABLE, keys); + mKeyField.put(Constants.RD_TABLE, keys); + + keys = new ArrayList<>(); + keys.add(Constants.DEVICE_ID); + + mMongoDB.createIndex(Constants.PRESENCE_TABLE, keys); + mKeyField.put(Constants.PRESENCE_TABLE, keys); + + } + + /** + * API for inserting a record into DB table. the record will not be inserted + * if duplicated one. + * + * @param tableName + * table name to be inserted + * @param insert + * record to be inserted + */ + public void insertRecord(String tableName, HashMap insert) { + + if (!_insertRecord(tableName, insert)) + throw new InternalServerErrorException( + "Database record insert failed"); + } + + /** + * API for inserting a record into DB table. the record will be replaced if + * duplicated one. + * + * @param tableName + * table name to be inserted + * @param replace + * record to be inserted + */ + public void insertAndReplaceRecord(String tableName, + HashMap replace) { + + if (!_insertAndReplaceRecord(tableName, replace)) + throw new InternalServerErrorException( + "Database record insert failed"); + } + + /** + * API for selecting records from DB table. + * + * @param tableName + * table name to be inserted + * @param condition + * condition record to be selected + * @return selected records + */ + public ArrayList> selectRecord(String tableName, + HashMap condition) { + + return _selectRecord(tableName, condition); } - public ArrayList registerResource( - ArrayList> pubResourceList) { - return mMongoDB.createRDResource(pubResourceList, Constants.RD_TABLE); + /** + * API for deleting records from DB table. + * + * @param tableName + * table name to be inserted + * @param condition + * condition record to be deleted + */ + public void deleteRecord(String tableName, + HashMap condition) { + + if (!_deleteRecord(tableName, condition)) + throw new InternalServerErrorException( + "Database record delete failed"); } - public ArrayList> findResourceAboutDi(String di) { - return mMongoDB.readResourceAboutDid(di, Constants.RD_TABLE); + /** + * API for updating a record into DB table. + * + * @param tableName + * table name to be inserted + * @param replace + * record to be updated + */ + public void updateRecord(String tableName, + HashMap replace) { + + if (!_updateRecord(tableName, replace)) + throw new InternalServerErrorException( + "Database record update failed"); + } - - public ArrayList> findResourceAboutDiAndFilter(String di, - String key, String value) { - return mMongoDB.readResourceAboutDidAndFilter(di, key, value, - Constants.RD_TABLE); + + private Boolean _insertRecord(String tableName, + HashMap record) { + + Document doc = createDocument(record); + + return mMongoDB.insertRecord(tableName, doc); } - public ArrayList deleteResourceAboutDi(String di) { - return mMongoDB.deleteResourceAboutDi(di, Constants.RD_TABLE); + private Boolean _insertAndReplaceRecord(String tableName, + HashMap record) { + + Document doc = createDocument(record); + Document filter = getKeyFilter(tableName, record); + + return mMongoDB.insertAndReplaceRecord(tableName, filter, doc); } - public ArrayList deleteResourceAboutDiAandIns(String di, - String ins) { - return mMongoDB.deleteResourceAboutDiAndIns(di, ins, - Constants.RD_TABLE); + private Boolean _deleteRecord(String tableName, + HashMap condition) { + + Document doc = createDocument(condition); + + return mMongoDB.deleteRecord(tableName, doc); } - public Object findInsAboutDi(String di, String href) { - return mMongoDB.readInsAboutDid(di, href, Constants.RD_TABLE); + private Boolean _updateRecord(String tableName, + HashMap record) { + + Document replace = createDocument(record); + Document filter = getKeyFilter(tableName, record); + + return mMongoDB.updateRecord(tableName, filter, replace); } - public void updateDeviceState(HashMap deviceState) { - mMongoDB.createDevicePresenceResource(deviceState, - Constants.PRESENCE_TABLE); + private ArrayList> _selectRecord(String tableName, + HashMap record) { + + Document doc = createDocument(record); + + return mMongoDB.selectRecord(tableName, doc); } - public String findDeviceState(String deviceId) { - return mMongoDB.readDeviceState(deviceId, Constants.PRESENCE_TABLE); + private Document getKeyFilter(String tableName, + HashMap record) { + + Document filterDoc = new Document(); + + ArrayList keys = mKeyField.get(tableName); + + for (String key : keys) { + + Object value = record.get(key); + filterDoc.append(key, value); + } + + return filterDoc; } -} + + private Document createDocument(HashMap record) { + + Document doc = new Document(); + Set> resEntrySet = record.entrySet(); + Iterator> entryIter = resEntrySet.iterator(); + + while (entryIter.hasNext()) { + Map.Entry entry = (Map.Entry) entryIter + .next(); + doc.append(entry.getKey().toString(), entry.getValue()); + } + + return doc; + } + +} \ No newline at end of file diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/MongoDB.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/MongoDB.java index ff48f63..d15100c 100644 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/MongoDB.java +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/MongoDB.java @@ -29,14 +29,13 @@ import java.util.Map.Entry; import java.util.Set; import org.bson.Document; -import org.iotivity.cloud.rdserver.Constants; -import org.iotivity.cloud.rdserver.resources.presence.resource.ResPresencePayload; +import org.iotivity.cloud.util.Log; import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; -import com.mongodb.client.model.Filters; +import com.mongodb.client.model.IndexOptions; /** * @@ -56,298 +55,232 @@ public class MongoDB { * @throws Exception */ public MongoDB(String dbname) throws Exception { + mongoClient = new MongoClient(); mongoClient.dropDatabase(dbname); db = mongoClient.getDatabase(dbname); } /** - * API creating collection + * API for creating collection * * @param tableName * collection name */ public void createTable(String tableName) { - deleteTable(tableName); + db.createCollection(tableName); } /** - * API deleting collection + * API for creating index * * @param tableName * collection name + * @param keys + * key fields of collection */ - public void deleteTable(String tableName) { - db.getCollection(tableName).drop(); - } - - private Document createDocument(HashMap storeRes) { + public void createIndex(String tablename, ArrayList keys) { Document doc = new Document(); - Set> resEntrySet = storeRes.entrySet(); - Iterator> entryIter = resEntrySet.iterator(); - - while (entryIter.hasNext()) { - Map.Entry entry = (Map.Entry) entryIter - .next(); - doc.append(entry.getKey().toString(), entry.getValue()); - } - - return doc; - } - private ArrayList createDocuments( - ArrayList> storeResList) { + for (String key : keys) { - Iterator> resListIter = storeResList.iterator(); - - ArrayList docList = new ArrayList<>(); + doc.append(key, 1); + } - while (resListIter.hasNext()) { - Document doc = new Document(); + IndexOptions options = new IndexOptions(); + options.unique(true); - HashMap storeRes = resListIter.next(); - Set> resEntrySet = storeRes.entrySet(); - Iterator> entryIter = resEntrySet.iterator(); + db.getCollection(tablename).createIndex(doc, options); + } - while (entryIter.hasNext()) { - Map.Entry entry = (Map.Entry) entryIter - .next(); - doc.append(entry.getKey().toString(), entry.getValue()); - } - docList.add(doc); - } + /** + * API for deleting collection + * + * @param tableName + * collection name + */ + public void deleteTable(String tableName) { - return docList; + db.getCollection(tableName).drop(); } - private HashMap convertDocumentToHashMap(Document doc) { - HashMap resourceMap = new HashMap(); - - Set> entrySet = doc.entrySet(); - Iterator> entryIter = entrySet.iterator(); - while (entryIter.hasNext()) { - Map.Entry entry = (Map.Entry) entryIter - .next(); - if (entry.getValue() != null) { - resourceMap.put(entry.getKey().toString(), entry.getValue()); - } - } + /** + * API for getting database object + * + */ + public MongoDatabase getMongoDatabase() { - return resourceMap; + return db; } /** - * API for storing information of published resources - * - * @param publishPayloadFormat - * information of published resources to store in collection + * API for inserting a record into DB table. the record will not be inserted + * if duplicated one. + * * @param tableName - * collection name + * table name to be inserted + * @param doc + * document to be inserted */ - public ArrayList createRDResource( - ArrayList> storeResList, String tableName) { - ArrayList docList = createDocuments(storeResList); - Iterator docIter = docList.iterator(); + public Boolean insertRecord(String tableName, Document doc) { + + if (tableName == null || doc == null) + return false; MongoCollection collection = db.getCollection(tableName); - ArrayList resPayloadList = new ArrayList<>(); + try { - while (docIter.hasNext()) { - Document doc = docIter.next(); - byte trigger = 0; + if (collection.find(doc).first() == null) { - if (collection.findOneAndReplace( - Filters.and( - Filters.eq(Constants.DEVICE_ID, - doc.get(Constants.DEVICE_ID)), - Filters.eq(Constants.INS, doc.get(Constants.INS))), - doc) == null) { collection.insertOne(doc); - trigger = Constants.RES_CREATE; } else { - trigger = Constants.RES_CHANGE; + Log.w("DB insert failed due to duplecated one."); + return false; } - resPayloadList.add(makeResourcePresencePayload(doc, trigger)); - } - return resPayloadList; - } - - public void createDevicePresenceResource(HashMap storeRes, - String tableName) { - - Document doc = createDocument(storeRes); - MongoCollection collection = db.getCollection(tableName); - - if (collection - .findOneAndReplace( - Filters.and(Filters.eq(Constants.DEVICE_ID, - doc.get(Constants.DEVICE_ID))), - doc) == null) { + } catch (Exception e) { - collection.insertOne(doc); + e.printStackTrace(); + return false; } - return; - } - - private ResPresencePayload makeResourcePresencePayload(Document doc, - byte trigger) { - - ResPresencePayload resPayload = new ResPresencePayload(); - - resPayload.setTrg(trigger); + showRecord(tableName); - Object rt = doc.get(Constants.RESOURCE_TYPE); - if (rt != null) { - resPayload.setRt(rt.toString()); - } - Object href = doc.get(Constants.HREF); - if (href != null) { - Object di = doc.get(Constants.DEVICE_ID); - if (di != null) { - resPayload.setHref(href.toString()); - } - } - Object ttl = doc.get(Constants.RESOURCE_TTL); - if (ttl != null) { - resPayload.setTtl((int) ttl); - } - return resPayload; + return true; } - public String readDeviceState(String deviceId, String tableName) { + /** + * API for inserting a record into DB table. the record will be replaced if + * duplicated one. + * + * @param tableName + * table name to be inserted + * @param filter + * document filter + * @param doc + * document to be inserted + * @return returns true if the record is inserted and replaced successfully, + * or returns false + */ + public Boolean insertAndReplaceRecord(String tableName, Document filter, + Document doc) { - String deviceState = null; + if (tableName == null || filter == null || doc == null) + return false; MongoCollection collection = db.getCollection(tableName); - MongoCursor cursor = collection - .find(Filters.eq(Constants.DEVICE_ID, deviceId)) - .iterator(); - try { - while (cursor.hasNext()) { - Document doc = cursor.next(); - deviceState = doc.getString(Constants.PRESENCE_STATE); - break; + if (collection.findOneAndReplace(filter, doc) == null) { + + collection.insertOne(doc); } - } finally { + } catch (Exception e) { - cursor.close(); + e.printStackTrace(); + return false; } - return deviceState; + showRecord(tableName); + + return true; } - public ArrayList> readResourceAboutDid(String di, String tableName) { + /** + * API for updating a record into DB table. + * + * @param tableName + * table name to be updated + * @param filter + * document filter + * @param record + * record to be updated + * @return returns true if the record is updated successfully, or returns + * false + */ + public Boolean updateRecord(String tableName, Document filter, + Document record) { + + if (tableName == null || filter == null || record == null) + return false; + MongoCollection collection = db.getCollection(tableName); - ArrayList> resList = null; - MongoCursor cursor = collection - .find(Filters.eq(Constants.DEVICE_ID, di)) - .iterator(); - - if (cursor.hasNext()) { - resList = new ArrayList<>(); - try { - while (cursor.hasNext()) { - Document doc = cursor.next(); - resList.add(convertDocumentToHashMap(doc)); - } - } finally { - cursor.close(); - } + + if (collection.findOneAndReplace(filter, record) == null) { + + Log.w("DB update failed due to no matched record!"); + return false; } - return resList; + showRecord(tableName); + + return true; } /** - * API for finding resources matched filterValue of filterKey and a - * particular device ID in collection - * - * @param di - * device id - * @param filterKey - * field name in collection - * @param filterValue - * field value about field name + * API for deleting records from DB table. + * * @param tableName - * collection name - * @return ArrayList - array list of resource - * information + * table name for the record to be deleted + * @param record + * record filter to be deleted + * @return returns true if the record is deleted successfully, or returns + * false */ - public ArrayList> readResourceAboutDidAndFilter(String di, - String filterKey, String filterValue, String tableName) { - MongoCollection collection = db.getCollection(tableName); - ArrayList> resList = null; - MongoCursor cursor = collection - .find(Filters.and(Filters.eq(Constants.DEVICE_ID, di), - Filters.eq(filterKey, filterValue))) - .iterator(); - - if (cursor.hasNext()) { - resList = new ArrayList<>(); - try { - while (cursor.hasNext()) { - Document doc = cursor.next(); - resList.add(convertDocumentToHashMap(doc)); - } - } finally { - cursor.close(); - } - } + public Boolean deleteRecord(String tableName, Document record) { - return resList; - } + if (tableName == null || record == null) + return false; - public Object readInsAboutDid(String di, String href, String tableName) { MongoCollection collection = db.getCollection(tableName); - MongoCursor cursor = collection - .find(Filters.and(Filters.eq(Constants.DEVICE_ID, di), - Filters.eq(Constants.HREF, href))) - .iterator(); + try { - while (cursor.hasNext()) { - Document doc = cursor.next(); - return doc.get(Constants.INS); - } - } finally { - cursor.close(); + + collection.deleteMany(record); + + } catch (Exception e) { + + e.printStackTrace(); + return false; } - return null; + + showRecord(tableName); + + return true; } /** - * API for deleting resources about a particular device ID in collection - * - * @param di - * device id + * API for selecting records from DB table. + * * @param tableName - * collection name + * table name for the record to be selected + * @param doc + * document filter to be selected + * @return record list according to the filter document */ - public ArrayList deleteResourceAboutDi(String di, - String tableName) { + public ArrayList> selectRecord(String tableName, + Document doc) { - MongoCollection collection = db.getCollection(tableName); + if (tableName == null || doc == null) + return null; - MongoCursor cursor = collection - .find(Filters.eq(Constants.DEVICE_ID, di)).iterator(); + MongoCollection collection = db.getCollection(tableName); + MongoCursor cursor = collection.find(doc).iterator(); - ArrayList resPayloadList = new ArrayList<>(); + ArrayList> recordList = new ArrayList<>(); try { + while (cursor.hasNext()) { - Document doc = cursor.next(); - resPayloadList.add( - makeResourcePresencePayload(doc, Constants.RES_DELETE)); + Document selectedDoc = cursor.next(); + recordList.add(convertDocumentToHashMap(selectedDoc)); } } finally { @@ -355,50 +288,50 @@ public class MongoDB { cursor.close(); } - collection.deleteMany(Filters.eq(Constants.DEVICE_ID, di)); - - return resPayloadList; + return recordList; } - /** - * API for deleting resources about a particular device ID and ins in - * collection - * - * @param di - * device id - * @param ins - * ins - * @param tableName - * collection name - */ - public ArrayList deleteResourceAboutDiAndIns(String di, - String ins, String tableName) { + private HashMap convertDocumentToHashMap(Document doc) { + HashMap resourceMap = new HashMap<>(); - MongoCollection collection = db.getCollection(tableName); + Set> entrySet = doc.entrySet(); + Iterator> entryIter = entrySet.iterator(); + + while (entryIter.hasNext()) { + + Map.Entry entry = (Map.Entry) entryIter + .next(); - MongoCursor cursor = collection - .find(Filters.and(Filters.eq(Constants.DEVICE_ID, di), - Filters.eq(Constants.INS, ins))) - .iterator(); + String entryKey = entry.getKey(); - ArrayList resPayloadList = new ArrayList<>(); + // remove a mongoDB index + if (entry.getValue() != null && !entryKey.equals("_id")) { - try { - while (cursor.hasNext()) { - Document doc = cursor.next(); - resPayloadList.add( - makeResourcePresencePayload(doc, Constants.RES_DELETE)); + resourceMap.put(entry.getKey(), entry.getValue()); } + } - } finally { + return resourceMap; + } - cursor.close(); - } + private void showRecord(String tableName) { + + MongoCollection collection = db.getCollection(tableName); + MongoCursor cursor = collection.find().iterator(); - collection.deleteOne(Filters.and(Filters.eq(Constants.DEVICE_ID, di), - Filters.eq(Constants.INS, ins))); + Log.i("<" + tableName + ">"); - return resPayloadList; + HashMap records = null; + int index = 0; + while (cursor.hasNext()) { + + Document doc = cursor.next(); + records = convertDocumentToHashMap(doc); + + Log.i("[" + index + "] " + records.toString()); + index++; + } + cursor.close(); } } diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/PayloadManager.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/PayloadManager.java new file mode 100644 index 0000000..bf1e91f --- /dev/null +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/PayloadManager.java @@ -0,0 +1,103 @@ +/* + * //****************************************************************** + * // + * // Copyright 2016 Samsung Electronics All Rights Reserved. + * // + * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + * // + * // Licensed under the Apache License, Version 2.0 (the "License"); + * // you may not use this file except in compliance with the License. + * // You may obtain a copy of the License at + * // + * // http://www.apache.org/licenses/LICENSE-2.0 + * // + * // Unless required by applicable law or agreed to in writing, software + * // distributed under the License is distributed on an "AS IS" BASIS, + * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * // See the License for the specific language governing permissions and + * // limitations under the License. + * // + * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + */ +package org.iotivity.cloud.rdserver.resources.directory; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import org.iotivity.cloud.rdserver.Constants; + +/** + * + * This class provides a set of APIs handle a payload + * + */ +public class PayloadManager { + + /** tag values of /oic/rd resource payload */ + public List pubTagKey = Arrays.asList("di", "n", "lt"); + + /** links values of /oic/rd resource payload */ + public List pubLinkKey = Arrays.asList("href", "rel", "rt", + "if", "p", "title", "anchor", "ins", "ttl", "type"); + + /** tag values of /oic/res resource payload */ + public List discoverTagKey = Arrays.asList("di", "n"); + + /** links values of /oic/res resource payload */ + public List discoverLinkKey = Arrays.asList("href", "rt", "if", + "p"); + + /** + * API for setting data of payload + * + * @param payload + * payload data + * @param keyType + * key type + * @return data included keys of keyType + */ + public HashMap setPayloadData( + HashMap payload, List keyType) { + + HashMap data = new HashMap(); + + for (String key : keyType) { + Object value = payload.get(key); + if (value != null) { + data.put(key, value); + } + } + return data; + } + + /** + * API for changing type of policy property to store in DB + * + * @param payload + * payload data + */ + public void changePolicyTypeToStore(HashMap payload) { + Object policy = payload.get(Constants.POLICY); + if (policy != null) { + HashMap bm = (HashMap) policy; + payload.put(Constants.POLICY, (int) (bm.get(Constants.BITMAP))); + } + } + + /** + * API for changing type of policy property to make a discovery response + * + * @param payload + * payload data + */ + public void changePolicyTypeToDiscover(HashMap payload) { + Object policy = payload.get(Constants.POLICY); + if (policy != null) { + HashMap bm = new HashMap<>(); + bm.put(Constants.BITMAP, policy); + payload.put(Constants.POLICY, bm); + } + } + +} diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/RDManager.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/RDManager.java new file mode 100644 index 0000000..881eead --- /dev/null +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/RDManager.java @@ -0,0 +1,293 @@ +/* + * //****************************************************************** + * // + * // Copyright 2016 Samsung Electronics All Rights Reserved. + * // + * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + * // + * // Licensed under the Apache License, Version 2.0 (the "License"); + * // you may not use this file except in compliance with the License. + * // You may obtain a copy of the License at + * // + * // http://www.apache.org/licenses/LICENSE-2.0 + * // + * // Unless required by applicable law or agreed to in writing, software + * // distributed under the License is distributed on an "AS IS" BASIS, + * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * // See the License for the specific language governing permissions and + * // limitations under the License. + * // + * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + */ +package org.iotivity.cloud.rdserver.resources.directory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.iotivity.cloud.base.exception.ServerException.BadRequestException; +import org.iotivity.cloud.rdserver.Constants; +import org.iotivity.cloud.rdserver.db.DBManager; +import org.iotivity.cloud.rdserver.resources.directory.rd.InsManager; +import org.iotivity.cloud.util.Log; + +/** + * + * This class provides a set of APIs handle requests about resource information + * + */ +public class RDManager { + + private InsManager mInsManager = new InsManager(); + private PayloadManager mPayloadManager = new PayloadManager(); + + private ArrayList> mResourcePresence = new ArrayList<>(); + + /** + * API for handling resource-publish process + * + * @param requestPayload + * request payload + * @return response payload + */ + public HashMap publishResource( + HashMap requestPayload) { + + HashMap deviceInfo = setResourceDeviceInfo( + requestPayload); + ArrayList> links = getLinks(requestPayload); + + // check ins and set ins + setResourceIns(deviceInfo.get(Constants.DEVICE_ID).toString(), links); + + storeResource(links, deviceInfo); + + return requestPayload; + + } + + // set di, n, lt info + private HashMap setResourceDeviceInfo( + HashMap payload) { + return mPayloadManager.setPayloadData(payload, + mPayloadManager.pubTagKey); + } + + private ArrayList> getLinks( + HashMap requestPayload) { + return (ArrayList>) requestPayload + .get(Constants.LINKS); + + } + + private void storeResource(ArrayList> links, + HashMap deviceInfo) { + + ArrayList> resourcePresence = new ArrayList<>(); + + for (HashMap link : links) { + HashMap storeInfo = new HashMap<>(); + HashMap storeLink = mPayloadManager + .setPayloadData(link, mPayloadManager.pubLinkKey); + mPayloadManager.changePolicyTypeToStore(storeLink); + storeInfo.putAll(storeLink); + storeInfo.putAll(deviceInfo); + storeResourceInDB(storeInfo); + resourcePresence.add(storeInfo); + } + setmResourcePresence(resourcePresence); + + } + + private void storeResourceInDB(HashMap rdInfo) { + HashMap condition = new HashMap<>(); + condition.put(Constants.DEVICE_ID, rdInfo.get(Constants.DEVICE_ID)); + condition.put(Constants.INS, rdInfo.get(Constants.INS)); + if (checkResourceExist(condition).isEmpty()) { + DBManager.getInstance().insertRecord(Constants.RD_TABLE, rdInfo); + // set resource presence + rdInfo.put(Constants.TRIGGER, Constants.RES_CREATE); + } else { + DBManager.getInstance().insertAndReplaceRecord(Constants.RD_TABLE, + rdInfo); + rdInfo.put(Constants.TRIGGER, Constants.RES_CHANGE); + } + + } + + private void setResourceIns(String di, + ArrayList> links) { + + for (HashMap link : links) { + String href = link.get(Constants.HREF).toString(); + int ins = (int) link.get(Constants.INS); + int newIns = checkResourceIns(di, href, ins); + if (newIns == -1) { + throw new BadRequestException("resource ins is not correct"); + } + link.put(Constants.INS, newIns); + } + } + + private int checkResourceIns(String di, String href, int ins) { + int storedIns = mInsManager.getIns(di, href); + if (ins == 0) { + if (storedIns == -1) { + // create ins + ins = mInsManager.createIns(di); + } else { + ins = storedIns; + } + } else { + if (ins != storedIns) { + ins = -1; + } + } + return ins; + } + + /** + * API for handling resource-delete process + * + * @param di + * device id + * @param ins + * unique id of resource + */ + public void deleteResource(String di, List insList) { + + HashMap condition = new HashMap<>(); + condition.put(Constants.DEVICE_ID, di); + + ArrayList> foundRecord = new ArrayList<>(); + + if (insList == null) { + foundRecord = checkResourceExist(condition); + DBManager.getInstance().deleteRecord(Constants.RD_TABLE, condition); + } else { + for (String ins : insList) { + condition.put(Constants.INS, Integer.parseInt(ins)); + if (!checkResourceExist(condition).isEmpty()) { + foundRecord.add(checkResourceExist(condition).get(0)); + DBManager.getInstance().deleteRecord(Constants.RD_TABLE, + condition); + } + } + } + + if (!foundRecord.isEmpty()) { + // set resource presence + for (HashMap record : foundRecord) { + record.put(Constants.TRIGGER, Constants.RES_DELETE); + } + setmResourcePresence(foundRecord); + } + } + + private ArrayList> checkResourceExist( + HashMap condition) { + ArrayList> records = DBManager.getInstance() + .selectRecord(Constants.RD_TABLE, condition); + + return records; + } + + /** + * API for handling resource-discover process + * + * @param diList + * list of device id + * @param rtList + * list of resource type + * @param ifList + * list of resource interface + * @return response payload + */ + public ArrayList discoverResource(List diList, + List rtList, List ifList) { + + HashMap condition = new HashMap<>(); + + ArrayList response = new ArrayList<>(); + + if (diList == null) { + return response; + } + + if (rtList == null && ifList == null) { + readResource(diList, condition, response); + } + + if (rtList != null) { + for (String rt : rtList) { + condition.put(Constants.RESOURCE_TYPE, rt); + readResource(diList, condition, response); + } + } + + if (ifList != null) { + for (String itf : ifList) { + condition.put(Constants.INTERFACE, itf); + readResource(diList, condition, response); + } + } + + Log.d("discovery payload : " + response); + + return response; + } + + private void readResource(List diList, + HashMap condition, ArrayList response) { + + for (String di : diList) { + condition.put(Constants.DEVICE_ID, di); + ArrayList> records = DBManager.getInstance() + .selectRecord(Constants.RD_TABLE, condition); + + if (!records.isEmpty()) { + response.add(makeDiscoverResponseSegment(records)); + } + + } + } + + private HashMap makeDiscoverResponseSegment( + ArrayList> records) { + + HashMap responseSegment = new HashMap<>(); + + // make Tags + HashMap discoverTag = mPayloadManager + .setPayloadData(records.get(0), mPayloadManager.discoverTagKey); + responseSegment.putAll(discoverTag); + + ArrayList links = new ArrayList<>(); + // make links + for (HashMap record : records) { + HashMap link = mPayloadManager + .setPayloadData(record, mPayloadManager.discoverLinkKey); + mPayloadManager.changePolicyTypeToDiscover(link); + links.add(link); + } + responseSegment.put(Constants.LINKS, links); + + return responseSegment; + + } + + private void setmResourcePresence( + ArrayList> resourcePresence) { + this.mResourcePresence = resourcePresence; + } + + /** + * API for getting resource information to notify + * + * @return resource information + */ + public ArrayList> getmResourcePresence() { + return mResourcePresence; + } + +} diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/InsManager.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/InsManager.java index 980e092..f97e2fc 100644 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/InsManager.java +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/InsManager.java @@ -21,26 +21,53 @@ */ package org.iotivity.cloud.rdserver.resources.directory.rd; +import java.util.ArrayList; import java.util.HashMap; +import org.iotivity.cloud.rdserver.Constants; import org.iotivity.cloud.rdserver.db.DBManager; +/** + * + * This class provides a set of APIs to handle ins(unique value of resource) + * + */ public class InsManager { private HashMap mNextIns = new HashMap<>(); private int mInitialValue = 1; + /** + * API for getting ins from DB + * + * @param di + * device id + * @param href + * resource uri + * @return ins + */ public int getIns(String di, String href) { - Object objectIns = DBManager.getInstance().findInsAboutDi(di, href); - if (objectIns == null) { - return 0; - } else { - return (int) objectIns; + HashMap condition = new HashMap<>(); + condition.put(Constants.DEVICE_ID, di); + condition.put(Constants.HREF, href); + ArrayList> records = DBManager.getInstance() + .selectRecord(Constants.RD_TABLE, condition); + if (records.isEmpty()) { + return -1; + } else { + return (int) (records.get(0).get(Constants.INS)); } } + /** + * API for creating ins + * + * @param di + * device id + * @return created ins + */ public int createIns(String di) { Object objectIns; diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishLinks.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishLinks.java deleted file mode 100644 index 6a64e36..0000000 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishLinks.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * //****************************************************************** - * // - * // Copyright 2016 Samsung Electronics All Rights Reserved. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - * // - * // Licensed under the Apache License, Version 2.0 (the "License"); - * // you may not use this file except in compliance with the License. - * // You may obtain a copy of the License at - * // - * // http://www.apache.org/licenses/LICENSE-2.0 - * // - * // Unless required by applicable law or agreed to in writing, software - * // distributed under the License is distributed on an "AS IS" BASIS, - * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * // See the License for the specific language governing permissions and - * // limitations under the License. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - */ -package org.iotivity.cloud.rdserver.resources.directory.rd; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.iotivity.cloud.rdserver.Constants; - -public class PublishLinks { - /** URI Reference */ - private String href; - /** Relation between target URI and context URI */ - private String rel; - /** Resource Types */ - private ArrayList rt = new ArrayList(); - /** Resource interface */ - private ArrayList itf = new ArrayList(); - /** policies that apply for resource */ - private Object p; - /** Title for the link relation */ - private String title; - /** This is used to override the context URI */ - private String anchor; - /** An ordinal number that is not repeated */ - private int ins; - /** Time to live for this link */ - private int ttl; - /** - * A hint of the media type of the representation of the resource referenced - * by the target URI. - */ - ArrayList type = new ArrayList(); - - public PublishLinks copy() { - PublishLinks links = new PublishLinks(); - links.href = this.href; - links.rel = this.rel; - links.rt.addAll(this.rt); - links.itf.addAll(this.itf); - links.p = this.p; - links.title = this.title; - links.anchor = this.anchor; - links.ins = this.ins; - links.ttl = this.ttl; - return links; - } - - public String getHref() { - return href; - } - - public void setHref(Object href) { - this.href = href.toString(); - } - - public String getRel() { - return rel; - } - - public void setRel(Object rel) { - this.rel = rel.toString(); - } - - public ArrayList getRt() { - return rt; - } - - public void setRt(Object rt) { - this.rt = (ArrayList) rt; - } - - public ArrayList getItf() { - return itf; - } - - public void setItf(Object itf) { - this.itf = (ArrayList) itf; - } - - public Object getP() { - return p; - } - - public void setP(Object p) { - HashMap bm = (HashMap) p; - this.p = bm.get(Constants.BITMAP); - } - - public void changePType() { - HashMap bm = new HashMap(); - bm.put(Constants.BITMAP, (int) p); - this.p = bm; - } - - public String getTitle() { - return title; - } - - public void setTitle(Object title) { - this.title = title.toString(); - } - - public String getAnchor() { - return anchor; - } - - public void setAnchor(Object anchor) { - this.anchor = anchor.toString(); - } - - public int getIns() { - return ins; - } - - public void setIns(Object ins) { - this.ins = (int) ins; - } - - public int getTtl() { - return ttl; - } - - public void setTtl(Object ttl) { - this.ttl = (int) ttl; - } - - public ArrayList getType() { - return type; - } - - public void setType(Object type) { - this.type = (ArrayList) type; - } - -} diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishPayload.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishPayload.java deleted file mode 100644 index e02b726..0000000 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishPayload.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * //****************************************************************** - * // - * // Copyright 2016 Samsung Electronics All Rights Reserved. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - * // - * // Licensed under the Apache License, Version 2.0 (the "License"); - * // you may not use this file except in compliance with the License. - * // You may obtain a copy of the License at - * // - * // http://www.apache.org/licenses/LICENSE-2.0 - * // - * // Unless required by applicable law or agreed to in writing, software - * // distributed under the License is distributed on an "AS IS" BASIS, - * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * // See the License for the specific language governing permissions and - * // limitations under the License. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - */ -package org.iotivity.cloud.rdserver.resources.directory.rd; - -import java.util.ArrayList; - -public class PublishPayload { - - private PublishTags tags = new PublishTags(); - - private ArrayList links = new ArrayList<>(); - - public PublishPayload copy() { - PublishPayload pubPayload = new PublishPayload(); - pubPayload.tags = this.tags.copy(); - - pubPayload.links = new ArrayList<>(); - - for (PublishLinks link : this.links) { - pubPayload.links.add(link.copy()); - } - - return pubPayload; - } - - public PublishTags getTags() { - return tags; - } - - public void setTags(PublishTags tags) { - this.tags = tags; - } - - public ArrayList getLinks() { - return links; - } - - public void setLinks(ArrayList links) { - this.links = links; - } -} diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishTags.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishTags.java deleted file mode 100644 index f240ff9..0000000 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishTags.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * //****************************************************************** - * // - * // Copyright 2016 Samsung Electronics All Rights Reserved. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - * // - * // Licensed under the Apache License, Version 2.0 (the "License"); - * // you may not use this file except in compliance with the License. - * // You may obtain a copy of the License at - * // - * // http://www.apache.org/licenses/LICENSE-2.0 - * // - * // Unless required by applicable law or agreed to in writing, software - * // distributed under the License is distributed on an "AS IS" BASIS, - * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * // See the License for the specific language governing permissions and - * // limitations under the License. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - */ -package org.iotivity.cloud.rdserver.resources.directory.rd; - -public class PublishTags { - /** An unique identifier of device */ - private String di; - /** A human friendly name of device */ - private String n; - /** Time (in seconds) to indicate how long RD should publish this item */ - private int lt; - - public PublishTags copy() { - PublishTags tags = new PublishTags(); - tags.di = this.di; - tags.n = this.n; - tags.lt = this.lt; - return tags; - } - - public String getDi() { - return di; - } - - public void setDi(Object di) { - this.di = di.toString(); - } - - public String getN() { - return n; - } - - public void setN(Object n) { - this.n = n.toString(); - } - - public int getLt() { - return lt; - } - - public void setLt(Object lt) { - this.lt = (int) lt; - } -} 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 9d465a4..f56f29d 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 @@ -37,21 +37,20 @@ import org.iotivity.cloud.base.protocols.enums.ContentFormat; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.rdserver.Constants; -import org.iotivity.cloud.rdserver.db.DBManager; -import org.iotivity.cloud.rdserver.resources.presence.ResPresenceManager; -import org.iotivity.cloud.rdserver.resources.presence.resource.ResPresencePayload; -import org.iotivity.cloud.rdserver.util.TypeCastingManager; +import org.iotivity.cloud.rdserver.resources.directory.RDManager; +import org.iotivity.cloud.rdserver.resources.presence.PresenceManager; import org.iotivity.cloud.util.Cbor; import org.iotivity.cloud.util.Log; +/** + * + * This class provides a set of APIs handle requests about resource directory + * + */ public class ResourceDirectoryResource extends Resource { - private Cbor> mCbor = new Cbor<>(); - private TypeCastingManager mPublishTagsTypeManager = new TypeCastingManager<>(); - private TypeCastingManager mPublishLinksTypeManager = new TypeCastingManager<>(); - private InsManager mInsManager = new InsManager(); - private String mNotiDeviceId = null; - private ArrayList mNotiPayloadList = new ArrayList(); + private Cbor> mCbor = new Cbor<>(); + private RDManager mRdManager = new RDManager(); public ResourceDirectoryResource() { super(Arrays.asList(Constants.PREFIX_OIC, Constants.RD_URI)); @@ -73,208 +72,83 @@ 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); - ResPresenceManager.getInstance().notifyToObservers(mNotiDeviceId, - mNotiPayloadList); + PresenceManager.getInstance() + .notifyToObservers(mRdManager.getmResourcePresence()); } - private IResponse handlePostRequest(IRequest request) - throws ServerException { - - HashMap> queryMap = request.getUriQueryMap(); - - byte[] encodedPayload = null; - - if (queryMap == null) { - throw new PreconditionFailedException("query is null"); - } - - List listRT = queryMap.get(Constants.RESOURCE_TYPE); - - if (listRT == null) { - throw new PreconditionFailedException("rt property is not include"); - } else if (listRT.get(0).equals(Constants.RESOURCE_TYPE_RDPUBLISH)) { - - PublishPayload pubPayload = parsingPublishPayload(request - .getPayload()); + private void checkLinksProperty(HashMap payload) { - mNotiDeviceId = pubPayload.getTags().getDi(); - - // PublishPayload copyPubPayload = pubPayload.copy(); - - // ArrayList> storeResList = - // creatDBStoreResource(changeResourceUri(copyPubPayload)); - - ArrayList> storeResList = creatDBStoreResource(pubPayload); - - mNotiPayloadList = DBManager.getInstance().registerResource( - storeResList); - - encodedPayload = createPublishResponse(pubPayload); - - } else { - throw new PreconditionFailedException( - "rt property is not rd publish"); + Object links = payload.get(Constants.LINKS); + if (links == null) { + throw new BadRequestException("links property is null"); } - - return MessageBuilder.createResponse(request, ResponseStatus.CHANGED, - ContentFormat.APPLICATION_CBOR, encodedPayload); - } - - private byte[] createPublishResponse(PublishPayload pubPayload) { - HashMap responseMap = new HashMap(); - - PublishTags tags = pubPayload.getTags(); - responseMap.putAll(mPublishTagsTypeManager.convertObjectToMap(tags)); - - ArrayList pubLinksList = pubPayload.getLinks(); - - ArrayList> links = new ArrayList>(); - - for (PublishLinks pubLinks : pubLinksList) { - mPublishLinksTypeManager.callMethod("changePType", pubLinks); - links.add(mPublishLinksTypeManager.convertObjectToMap(pubLinks)); + ArrayList> linksList = (ArrayList>) links; + for (HashMap link : linksList) { + checkPayloadException( + Arrays.asList(Constants.HREF, Constants.RESOURCE_TYPE, + Constants.INS, Constants.INTERFACE), + link); } - responseMap.put(Constants.LINKS, links); - - Log.i("publish response :" + responseMap.toString()); - - byte[] encodedPaylod = mCbor.encodingPayloadToCbor(responseMap); - - return encodedPaylod; } - private PublishPayload parsingPublishPayload(byte[] payload) + private IResponse handlePostRequest(IRequest request) throws ServerException { - HashMap payloadData = mCbor.parsePayloadFromCbor( - payload, HashMap.class); - - if (payloadData == null) { - throw new BadRequestException("payload is null"); - } else { - Log.i("publish payload: " + payloadData.toString()); - } + HashMap> queryMap = request.getUriQueryMap(); - PublishTags tags = new PublishTags(); - tags = mPublishTagsTypeManager.convertMaptoObject(payloadData, tags); - - String di = tags.getDi(); - - ArrayList> linksList = (ArrayList>) payloadData - .get(Constants.LINKS); - - ArrayList pubLinksList = new ArrayList(); - - for (HashMap links : linksList) { - PublishLinks pubLinks = new PublishLinks(); - pubLinks = mPublishLinksTypeManager.convertMaptoObject(links, - pubLinks); - String href = pubLinks.getHref(); - // href = "/di/" + di + href; - int ins = pubLinks.getIns(); - ins = checkResourceIns(di, href, ins); - if (ins == 0) { - throw new PreconditionFailedException("ins is null"); - } - pubLinks.setIns(ins); - pubLinksList.add(pubLinks); - } + checkQueryException(Arrays.asList(Constants.RESOURCE_TYPE), queryMap); - PublishPayload pubPayload = new PublishPayload(); - pubPayload.setTags(tags); - pubPayload.setLinks(pubLinksList); + List listRT = queryMap.get(Constants.RESOURCE_TYPE); - return pubPayload; - } + // check query "rt=oic.rd.pub" + if (!listRT.get(0).equals(Constants.RESOURCE_TYPE_RDPUBLISH)) { + throw new PreconditionFailedException("rt property is not correct"); + } - private PublishPayload changeResourceUri(PublishPayload pubPayload) { + HashMap payload = mCbor + .parsePayloadFromCbor(request.getPayload(), HashMap.class); - String di = pubPayload.getTags().getDi(); + Log.d("publish payload : " + payload); - for (PublishLinks links : pubPayload.getLinks()) { - String originHref = links.getHref(); - links.setHref("/di/" + di + originHref); - } + checkPayloadException( + Arrays.asList(Constants.DEVICE_ID, Constants.LINKS), payload); - return pubPayload; - } + // check mandatory property + checkLinksProperty(payload); - private int checkResourceIns(String di, String href, int ins) { - int storedIns = mInsManager.getIns(di, href); - if (ins == 0) { - if (storedIns == 0) { - ins = mInsManager.createIns(di); - } else { - ins = storedIns; - } - } else { - if (ins != storedIns) { - ins = 0; - } - } - return ins; - } + HashMap response = mRdManager.publishResource(payload); - private ArrayList> creatDBStoreResource( - PublishPayload pubPayload) { - PublishTags tags = pubPayload.getTags(); - ArrayList linksList = pubPayload.getLinks(); + Log.d("publish response : " + response); - ArrayList> storeResList = new ArrayList>(); - HashMap storeTags = mPublishTagsTypeManager - .convertObjectToMap(tags); + return MessageBuilder.createResponse(request, ResponseStatus.CHANGED, + ContentFormat.APPLICATION_CBOR, + mCbor.encodingPayloadToCbor(response)); - for (PublishLinks links : linksList) { - HashMap storeRes = new HashMap(); - storeRes.putAll(storeTags); - storeRes.putAll(mPublishLinksTypeManager.convertObjectToMap(links)); - storeResList.add(storeRes); - } - return storeResList; } private IResponse handleDeleteRequest(IRequest request) throws ServerException { HashMap> queryMap = request.getUriQueryMap(); - List diList = null; - List insList = null; - - if (queryMap == null) { - throw new PreconditionFailedException("query is null"); - } else { - diList = queryMap.get(Constants.DEVICE_ID); - insList = queryMap.get(Constants.INS); - - if (diList == null) { - throw new PreconditionFailedException( - "di property is not include"); - } else { - String di = diList.get(0); - mNotiDeviceId = di; - - if (insList == null) { - mNotiPayloadList = DBManager.getInstance() - .deleteResourceAboutDi(di); - - } else { - String ins = insList.get(0); - mNotiPayloadList = DBManager.getInstance() - .deleteResourceAboutDiAandIns(di, ins); - } - } - } + + checkQueryException(Arrays.asList(Constants.DEVICE_ID), queryMap); + + List diList = queryMap.get(Constants.DEVICE_ID); + List insList = queryMap.get(Constants.INS); + + mRdManager.deleteResource(diList.get(0), insList); IResponse response = MessageBuilder.createResponse(request, ResponseStatus.DELETED); return response; } + } diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryLinks.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryLinks.java deleted file mode 100644 index e4caa38..0000000 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryLinks.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * //****************************************************************** - * // - * // Copyright 2016 Samsung Electronics All Rights Reserved. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - * // - * // Licensed under the Apache License, Version 2.0 (the "License"); - * // you may not use this file except in compliance with the License. - * // You may obtain a copy of the License at - * // - * // http://www.apache.org/licenses/LICENSE-2.0 - * // - * // Unless required by applicable law or agreed to in writing, software - * // distributed under the License is distributed on an "AS IS" BASIS, - * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * // See the License for the specific language governing permissions and - * // limitations under the License. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - */ -package org.iotivity.cloud.rdserver.resources.directory.res; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.iotivity.cloud.rdserver.Constants; - -public class DiscoveryLinks { - /** URI Reference */ - private String href; - /** Resource Types */ - private ArrayList rt = new ArrayList<>(); - /** Resource interface */ - private ArrayList itf = new ArrayList<>(); - /** policies that apply for resource */ - private HashMap p = new HashMap<>(); - - public DiscoveryLinks() { - - } - - public String getHref() { - return href; - } - - public void setHref(Object href) { - this.href = href.toString(); - } - - public ArrayList getRt() { - return rt; - } - - public void setRt(Object rt) { - this.rt = (ArrayList) rt; - } - - public ArrayList getItf() { - return itf; - } - - public void setItf(Object itf) { - this.itf = (ArrayList) itf; - } - - public Object getP() { - return p; - } - - public void setP(Object p) { - int bm = (int) p; - this.p.put(Constants.BITMAP, bm); - } -} diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryPayload.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryPayload.java deleted file mode 100644 index edae490..0000000 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryPayload.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * //****************************************************************** - * // - * // Copyright 2016 Samsung Electronics All Rights Reserved. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - * // - * // Licensed under the Apache License, Version 2.0 (the "License"); - * // you may not use this file except in compliance with the License. - * // You may obtain a copy of the License at - * // - * // http://www.apache.org/licenses/LICENSE-2.0 - * // - * // Unless required by applicable law or agreed to in writing, software - * // distributed under the License is distributed on an "AS IS" BASIS, - * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * // See the License for the specific language governing permissions and - * // limitations under the License. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - */ -package org.iotivity.cloud.rdserver.resources.directory.res; - -import java.util.ArrayList; - -public class DiscoveryPayload { - - private DiscoveryTags tags = new DiscoveryTags(); - - private ArrayList links = new ArrayList<>(); - - public DiscoveryPayload() { - - } - - public DiscoveryTags getTags() { - return tags; - } - - public void setTags(DiscoveryTags tags) { - this.tags = tags; - } - - public ArrayList getLinks() { - return links; - } - - public void setLinks(ArrayList links) { - this.links = links; - } - -} diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryResource.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryResource.java index 0462ed3..1f7199f 100644 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryResource.java +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryResource.java @@ -29,7 +29,6 @@ import java.util.List; import org.iotivity.cloud.base.device.Device; import org.iotivity.cloud.base.exception.ServerException; import org.iotivity.cloud.base.exception.ServerException.BadRequestException; -import org.iotivity.cloud.base.exception.ServerException.PreconditionFailedException; import org.iotivity.cloud.base.protocols.IRequest; import org.iotivity.cloud.base.protocols.IResponse; import org.iotivity.cloud.base.protocols.MessageBuilder; @@ -37,15 +36,17 @@ import org.iotivity.cloud.base.protocols.enums.ContentFormat; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.rdserver.Constants; -import org.iotivity.cloud.rdserver.db.DBManager; -import org.iotivity.cloud.rdserver.util.TypeCastingManager; +import org.iotivity.cloud.rdserver.resources.directory.RDManager; import org.iotivity.cloud.util.Cbor; -import org.iotivity.cloud.util.Log; +/** + * + * This class provides a set of APIs handle requests about resource discovery + * + */ public class DiscoveryResource extends Resource { - private Cbor> mCbor = new Cbor<>(); - private TypeCastingManager mDiscoveryTagsTypeManager = new TypeCastingManager<>(); - private TypeCastingManager mDiscoveryLinkTypeManager = new TypeCastingManager<>(); + private Cbor> mCbor = new Cbor<>(); + private RDManager mRdManager = new RDManager(); public DiscoveryResource() { super(Arrays.asList(Constants.PREFIX_OIC, Constants.WELL_KNOWN_URI)); @@ -75,105 +76,21 @@ public class DiscoveryResource extends Resource { HashMap> queryMap = request.getUriQueryMap(); - ArrayList resourceList = new ArrayList(); - - if (queryMap == null) { - throw new PreconditionFailedException("query is null"); - } - - List deviceList = queryMap.get(Constants.DEVICE_ID); + List diList = queryMap.get(Constants.DEVICE_ID); + List rtList = queryMap.get(Constants.RESOURCE_TYPE); + List ifList = queryMap.get(Constants.INTERFACE); - if (deviceList == null) { - throw new PreconditionFailedException( - "di property is not included"); - } - - List listRT = queryMap.get(Constants.RESOURCE_TYPE); - List listITF = queryMap.get(Constants.INTERFACE); - String key = null, value = null; - ArrayList> foundResList = null; - - // TODO: Multiple RT or ITF support required - if (listRT != null) { - key = Constants.RESOURCE_TYPE; - value = listRT.get(0); - } else if (listITF != null) { - key = Constants.INTERFACE; - value = listITF.get(0); - } + ArrayList response = mRdManager.discoverResource(diList, rtList, + ifList); - for (String deviceId : deviceList) { - if(key != null && value != null){ - foundResList = DBManager.getInstance().findResourceAboutDiAndFilter(deviceId, - key, value); - } else { - foundResList = DBManager.getInstance().findResourceAboutDi(deviceId); - } - - if (foundResList != null) { - resourceList.add(makeDiscoveryPayloadSegment(foundResList)); - } + if (response.size() == 0) { + return MessageBuilder.createResponse(request, + ResponseStatus.NOT_FOUND); } return MessageBuilder.createResponse(request, ResponseStatus.CONTENT, ContentFormat.APPLICATION_CBOR, - createDiscoveryResponse(resourceList)); + mCbor.encodingPayloadToCbor(response)); } - private DiscoveryPayload makeDiscoveryPayloadSegment( - ArrayList> foundResList) { - - ArrayList discoveryLinksList = new ArrayList(); - - for (HashMap res : foundResList) { - DiscoveryLinks discoveryLinksPayload = new DiscoveryLinks(); - discoveryLinksPayload = mDiscoveryLinkTypeManager - .convertMaptoObject(res, discoveryLinksPayload); - discoveryLinksList.add(discoveryLinksPayload); - } - - DiscoveryPayload discoveryPayload = new DiscoveryPayload(); - - DiscoveryTags tagsPayload = new DiscoveryTags(); - - tagsPayload = mDiscoveryTagsTypeManager - .convertMaptoObject(foundResList.get(0), tagsPayload); - - discoveryPayload.setTags(tagsPayload); - discoveryPayload.setLinks(discoveryLinksList); - - return discoveryPayload; - } - - private byte[] createDiscoveryResponse( - ArrayList discoveryPayloadList) { - ArrayList> responseMapList = new ArrayList>(); - - for (DiscoveryPayload discoveryPayload : discoveryPayloadList) { - - DiscoveryTags tags = discoveryPayload.getTags(); - - HashMap responseSegment = mDiscoveryTagsTypeManager - .convertObjectToMap(tags); - - ArrayList discoveryLinksList = discoveryPayload - .getLinks(); - - ArrayList> links = new ArrayList>(); - - for (DiscoveryLinks discoveryLinks : discoveryLinksList) { - links.add(mDiscoveryLinkTypeManager - .convertObjectToMap(discoveryLinks)); - } - responseSegment.put(Constants.LINKS, links); - - responseMapList.add(responseSegment); - } - - Log.i("discover payload :" + responseMapList.toString()); - - byte[] encodedPaylod = mCbor.encodingPayloadToCbor(responseMapList); - - return encodedPaylod; - } } diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryTags.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryTags.java deleted file mode 100644 index bc1fe35..0000000 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryTags.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * //****************************************************************** - * // - * // Copyright 2016 Samsung Electronics All Rights Reserved. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - * // - * // Licensed under the Apache License, Version 2.0 (the "License"); - * // you may not use this file except in compliance with the License. - * // You may obtain a copy of the License at - * // - * // http://www.apache.org/licenses/LICENSE-2.0 - * // - * // Unless required by applicable law or agreed to in writing, software - * // distributed under the License is distributed on an "AS IS" BASIS, - * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * // See the License for the specific language governing permissions and - * // limitations under the License. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - */ -package org.iotivity.cloud.rdserver.resources.directory.res; - -public class DiscoveryTags { - /** An unique identifier of device */ - private String di; - /** A human friendly name of device */ - private String n; - - public String getDi() { - return di; - } - - public void setDi(Object di) { - this.di = di.toString(); - } - - public String getN() { - return n; - } - - public void setN(Object n) { - this.n = n.toString(); - } -} diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/PresenceManager.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/PresenceManager.java new file mode 100644 index 0000000..1d6f05d --- /dev/null +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/PresenceManager.java @@ -0,0 +1,348 @@ +/* + * //****************************************************************** + * // + * // Copyright 2016 Samsung Electronics All Rights Reserved. + * // + * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + * // + * // Licensed under the Apache License, Version 2.0 (the "License"); + * // you may not use this file except in compliance with the License. + * // You may obtain a copy of the License at + * // + * // http://www.apache.org/licenses/LICENSE-2.0 + * // + * // Unless required by applicable law or agreed to in writing, software + * // distributed under the License is distributed on an "AS IS" BASIS, + * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * // See the License for the specific language governing permissions and + * // limitations under the License. + * // + * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + */ +package org.iotivity.cloud.rdserver.resources.presence; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import org.iotivity.cloud.base.device.Device; +import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException; +import org.iotivity.cloud.base.protocols.IRequest; +import org.iotivity.cloud.base.protocols.MessageBuilder; +import org.iotivity.cloud.base.protocols.enums.ContentFormat; +import org.iotivity.cloud.base.protocols.enums.ResponseStatus; +import org.iotivity.cloud.rdserver.Constants; +import org.iotivity.cloud.rdserver.db.DBManager; +import org.iotivity.cloud.util.Cbor; +import org.iotivity.cloud.util.Log; + +import com.fasterxml.jackson.core.JsonEncoding; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.dataformat.cbor.CBORFactory; +import com.fasterxml.jackson.dataformat.cbor.CBORGenerator; + +/** + * + * This class provides a set of APIs handle requests about presence + * + */ +public class PresenceManager { + private static PresenceManager mPresenceManager = new PresenceManager(); + + private Cbor> mCbor = new Cbor<>(); + + private class PresenceSubscriber { + PresenceSubscriber(Device subscriber, IRequest request) { + mSubscriber = subscriber; + mRequest = request; + } + + public Device mSubscriber; + public IRequest mRequest; + } + + private class PresenceInfo { + + PresenceInfo() { + mSubscriber = new HashMap<>(); + mSubscribedDevices = new HashMap<>(); + mSequenceNumber = new HashMap<>(); + } + + // di , token, Subscriber list + private HashMap> mSubscriber; + // token, di list + private HashMap> mSubscribedDevices; + private HashMap mSequenceNumber; + } + + private PresenceInfo mDevicePresence = null; + private PresenceInfo mResourcePresence = null; + + private PresenceManager() { + mDevicePresence = new PresenceInfo(); + mResourcePresence = new PresenceInfo(); + } + + /** + * API to return PresenceManager object + * + * @return PresenceManager object + */ + public static PresenceManager getInstance() { + return mPresenceManager; + } + + /** + * API to add observer + * + * @param srcDevice + * channel information + * @param request + * request message + * @param deviceIdList + * subscribed device list + * @param presenceType + * device presence or resource presence + */ + public void subscribePresence(Device srcDevice, IRequest request, + List deviceIdList, String presenceType) { + + PresenceInfo presenceInfo = getPresenceInfo(presenceType); + + for (String deviceId : deviceIdList) { + HashMap subscribers = presenceInfo.mSubscriber + .get(deviceId); + + if (subscribers == null) { + subscribers = new HashMap<>(); + presenceInfo.mSubscriber.put(deviceId, subscribers); + } + + subscribers.put(request.getRequestId(), + new PresenceSubscriber(srcDevice, request)); + } + + presenceInfo.mSubscribedDevices.put(request.getRequestId(), + deviceIdList); + presenceInfo.mSequenceNumber.put(request.getRequestId(), (long) 1); + } + + /** + * API to remove observer + * + * @param request + * request message + * @param deviceIdList + * unsubscribed device list + * @param presenceType + * device presence or resource presence + */ + public void unsubscribePresence(IRequest request, List deviceIdList, + String presenceType) { + + PresenceInfo presenceInfo = getPresenceInfo(presenceType); + + for (String deviceId : deviceIdList) { + HashMap subscribers = presenceInfo.mSubscriber + .get(deviceId); + + if (subscribers == null) { + continue; + } + + subscribers.remove(request.getRequestId()); + } + } + + /** + * API for notifying to observers about device presence + * + * @param deviceId + * device id + */ + public void notifyToObservers(String deviceId) { + + HashMap tokenNSubscribers = mDevicePresence.mSubscriber + .get(deviceId); + + if (tokenNSubscribers != null) { + byte[] payload = makeResponsePayload(Arrays.asList(deviceId)); + + for (PresenceSubscriber subscriber : tokenNSubscribers.values()) { + + subscriber.mSubscriber.sendResponse( + MessageBuilder.createResponse(subscriber.mRequest, + ResponseStatus.CONTENT, + ContentFormat.APPLICATION_CBOR, payload)); + } + } + } + + /** + * API to make response payload about device presence + * + * @param deviceList + * device id list + * @return payload data + */ + public byte[] makeResponsePayload(List deviceList) { + + HashMap getPayload = new HashMap<>(); + ArrayList> prsList = new ArrayList<>(); + + for (String deviceId : deviceList) { + HashMap payloadSegment = new HashMap<>(); + + String deviceState = getDeviceState(deviceId); + + payloadSegment.put(Constants.DEVICE_ID, deviceId); + + if (deviceState != null) { + payloadSegment.put(Constants.PRESENCE_STATE, deviceState); + } else { + payloadSegment.put(Constants.PRESENCE_STATE, + Constants.PRESENCE_OFF); + } + prsList.add(payloadSegment); + } + getPayload.put(Constants.PRESENCE_LIST, prsList); + Log.i("Device presence observe response : " + getPayload.toString()); + + return mCbor.encodingPayloadToCbor(getPayload); + + } + + private String getDeviceState(String deviceId) { + + HashMap condition = new HashMap<>(); + condition.put(Constants.DEVICE_ID, deviceId); + + String state = null; + + ArrayList> readRecords = DBManager.getInstance() + .selectRecord(Constants.PRESENCE_TABLE, condition); + + if (!readRecords.isEmpty() + && readRecords.get(0).get(Constants.PRESENCE_STATE) != null) { + state = readRecords.get(0).get(Constants.PRESENCE_STATE).toString(); + } + + return state; + } + + private PresenceInfo getPresenceInfo(String presenceType) { + + PresenceInfo presenceInfo = null; + switch (presenceType) { + case Constants.DEVICE_PRESENCE: + presenceInfo = mDevicePresence; + break; + case Constants.RESOURCE_PRESENCE: + presenceInfo = mResourcePresence; + break; + default: + } + return presenceInfo; + } + + /** + * API for notifying to observers about resource presence + * + * @param resourceInfo + * resource information + */ + public void notifyToObservers( + ArrayList> resourceInfo) { + + if (resourceInfo.isEmpty()) { + return; + } + + Object obj = resourceInfo.get(0).get(Constants.DEVICE_ID); + + if (obj == null) { + return; + } + + String deviceId = obj.toString(); + + HashMap tokenNSubscribers = mResourcePresence.mSubscriber + .get(deviceId); + + if (tokenNSubscribers != null) { + + for (PresenceSubscriber subscriber : tokenNSubscribers.values()) { + + for (HashMap resource : resourceInfo) { + subscriber.mSubscriber.sendResponse( + MessageBuilder.createResponse(subscriber.mRequest, + ResponseStatus.CONTENT, + ContentFormat.APPLICATION_CBOR, + makeResponsePayload( + subscriber.mRequest.getRequestId(), + resource))); + } + } + } + } + + private byte[] makeResponsePayload(String requestId, + HashMap resource) { + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + CBORFactory f = new CBORFactory(); + try { + JsonGenerator gen = f.createGenerator(out, JsonEncoding.UTF8); + gen.writeStartObject(); + long sequenceId = mResourcePresence.mSequenceNumber.get(requestId); + gen.writeNumberField(Constants.NON, sequenceId); + mResourcePresence.mSequenceNumber.put(requestId, sequenceId + 1); + gen.writeNumberField(Constants.RESOURCE_TTL, Long.parseLong( + checkPayload(resource, Constants.RESOURCE_TTL).toString())); + + gen.writeFieldName(Constants.TRIGGER); + + ((CBORGenerator) gen).writeRaw((byte) (224 + + (byte) (checkPayload(resource, Constants.TRIGGER)))); + + gen.writeStringField(Constants.RESOURCE_TYPE, + checkPayload(resource, Constants.RESOURCE_TYPE).toString()); + + gen.writeStringField(Constants.HREF, + checkPayload(resource, Constants.HREF).toString()); + gen.writeEndObject(); + + gen.close(); + } catch (Exception e) { + throw new InternalServerErrorException( + "notification payload cbor encoding error"); + } + + return out.toByteArray(); + } + + private Object checkPayload(HashMap resource, String key) { + Object obj = resource.get(key); + + if (obj == null) { + throw new InternalServerErrorException( + "property (" + key + ") is null"); + } + + return obj; + } + + /** + * API to update device state + * + * @param payload + * payload included device state + */ + public void updateDevicePresence(HashMap payload) { + DBManager.getInstance().insertAndReplaceRecord(Constants.PRESENCE_TABLE, + payload); + } +} diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/ResPresenceManager.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/ResPresenceManager.java deleted file mode 100644 index f0779db..0000000 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/ResPresenceManager.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * //****************************************************************** - * // - * // Copyright 2016 Samsung Electronics All Rights Reserved. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - * // - * // Licensed under the Apache License, Version 2.0 (the "License"); - * // you may not use this file except in compliance with the License. - * // You may obtain a copy of the License at - * // - * // http://www.apache.org/licenses/LICENSE-2.0 - * // - * // Unless required by applicable law or agreed to in writing, software - * // distributed under the License is distributed on an "AS IS" BASIS, - * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * // See the License for the specific language governing permissions and - * // limitations under the License. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - */ -package org.iotivity.cloud.rdserver.resources.presence; - -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import org.iotivity.cloud.base.device.Device; -import org.iotivity.cloud.base.protocols.IRequest; -import org.iotivity.cloud.base.protocols.MessageBuilder; -import org.iotivity.cloud.base.protocols.enums.ContentFormat; -import org.iotivity.cloud.base.protocols.enums.ResponseStatus; -import org.iotivity.cloud.rdserver.Constants; -import org.iotivity.cloud.rdserver.resources.presence.resource.ResPresencePayload; - -import com.fasterxml.jackson.core.JsonEncoding; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.dataformat.cbor.CBORFactory; -import com.fasterxml.jackson.dataformat.cbor.CBORGenerator; - -public class ResPresenceManager { - - public static ResPresenceManager mResPresenceManager = new ResPresenceManager(); - - private class PresenceSubscriber { - PresenceSubscriber(Device subscriber, IRequest request) { - mSubscriber = subscriber; - mRequest = request; - } - - public Device mSubscriber; - public IRequest mRequest; - } - - // di , token, Subscriber list - private HashMap> mDeviceSubscriber = null; - // token, di list - private HashMap> mSubscribedDevices = null; - - private HashMap mSubscriberSequenceNumber = null; - - public ResPresenceManager() { - - mDeviceSubscriber = new HashMap<>(); - mSubscribedDevices = new HashMap<>(); - mSubscriberSequenceNumber = new HashMap<>(); - } - - public static ResPresenceManager getInstance() { - return mResPresenceManager; - } - - public void addObserver(Device srcDevice, IRequest request, - List deviceIdList) { - - for (String deviceId : deviceIdList) { - HashMap subscribers = mDeviceSubscriber - .get(deviceId); - - if (subscribers == null) { - subscribers = new HashMap<>(); - mDeviceSubscriber.put(deviceId, subscribers); - } - - subscribers.put(request.getRequestId(), - new PresenceSubscriber(srcDevice, request)); - } - - mSubscribedDevices.put(request.getRequestId(), deviceIdList); - mSubscriberSequenceNumber.put(request.getRequestId(), (long) 1); - - return; - } - - public void removeObserver(IRequest request) { - - List deviceIdList = mSubscribedDevices - .get(request.getRequestId()); - - if (deviceIdList == null) { - return; - } - - for (String deviceId : deviceIdList) { - HashMap subscribers = mDeviceSubscriber - .get(deviceId); - - if (subscribers == null) { - continue; - } - - subscribers.remove(request.getRequestId()); - } - } - - public void notifyToObservers(String deviceId, - ArrayList resPayloadList) { - - HashMap tokenNSubscribers = mDeviceSubscriber - .get(deviceId); - - if (tokenNSubscribers != null) { - - for (PresenceSubscriber subscriber : tokenNSubscribers.values()) { - - for (ResPresencePayload resPayload : resPayloadList) { - subscriber.mSubscriber.sendResponse( - MessageBuilder.createResponse(subscriber.mRequest, - ResponseStatus.CONTENT, - ContentFormat.APPLICATION_CBOR, - makeResponsePayload( - subscriber.mRequest.getRequestId(), - resPayload))); - } - - } - } - } - - private byte[] makeResponsePayload(String requestId, - ResPresencePayload resPayload) { - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - CBORFactory f = new CBORFactory(); - try { - JsonGenerator gen = f.createGenerator(out, JsonEncoding.UTF8); - gen.writeStartObject(); - long sequenceId = mSubscriberSequenceNumber.get(requestId); - gen.writeNumberField(Constants.RS_NON, sequenceId); - mSubscriberSequenceNumber.put(requestId, sequenceId + 1); - gen.writeNumberField(Constants.RESOURCE_TTL, - (long) resPayload.getTtl()); - - gen.writeFieldName(Constants.RS_TRIGGER); - - ((CBORGenerator) gen).writeRaw((byte) (224 + resPayload.getTrg())); - - gen.writeStringField(Constants.RESOURCE_TYPE, resPayload.getRt()); - - gen.writeStringField(Constants.HREF, resPayload.getHref()); - gen.writeEndObject(); - - gen.close(); - } catch (Exception e) { - e.printStackTrace(); - } - return out.toByteArray(); - } -} diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/device/DevicePresenceResource.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/device/DevicePresenceResource.java index bd8780b..fe4556f 100644 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/device/DevicePresenceResource.java +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/device/DevicePresenceResource.java @@ -21,7 +21,6 @@ */ package org.iotivity.cloud.rdserver.resources.presence.device; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -36,36 +35,22 @@ import org.iotivity.cloud.base.protocols.enums.ContentFormat; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.rdserver.Constants; -import org.iotivity.cloud.rdserver.db.DBManager; -import org.iotivity.cloud.rdserver.util.TypeCastingManager; +import org.iotivity.cloud.rdserver.resources.presence.PresenceManager; import org.iotivity.cloud.util.Cbor; -import org.iotivity.cloud.util.Log; +/** + * + * This class provides a set of APIs handle requests about device presence + * + */ public class DevicePresenceResource extends Resource { private Cbor> mCbor = new Cbor<>(); - private class PresenceSubscriber { - PresenceSubscriber(Device subscriber, IRequest request) { - mSubscriber = subscriber; - mRequest = request; - } - - public Device mSubscriber; - public IRequest mRequest; - } - - // di , token, Subscriber list - private HashMap> mDeviceSubscriber = null; - // token, di list - private HashMap> mSubscribedDevices = null; - public DevicePresenceResource() { super(Arrays.asList(Constants.PREFIX_OIC, Constants.DEVICE_PRESENCE_URI)); - mDeviceSubscriber = new HashMap<>(); - mSubscribedDevices = new HashMap<>(); } @Override @@ -95,30 +80,31 @@ public class DevicePresenceResource extends Resource { throws ServerException { HashMap> queryMap = request.getUriQueryMap(); - byte[] payload = null; + checkQueryException(Arrays.asList(Constants.DEVICE_ID), queryMap); - if (checkQueryException(Arrays.asList(Constants.DEVICE_ID), queryMap)) { + List deviceList = queryMap.get(Constants.DEVICE_ID); - List deviceList = queryMap.get(Constants.DEVICE_ID); - - switch (request.getObserve()) { - case SUBSCRIBE: - addObserver(srcDevice, request, deviceList); - break; - case UNSUBSCRIBE: - removeObserver(request); - break; - default: - } - - payload = makeResponsePayload(deviceList); + switch (request.getObserve()) { + case SUBSCRIBE: + PresenceManager.getInstance().subscribePresence(srcDevice, + request, deviceList, Constants.DEVICE_PRESENCE); + break; + case UNSUBSCRIBE: + PresenceManager.getInstance().unsubscribePresence(request, + deviceList, Constants.DEVICE_PRESENCE); + break; + default: } + byte[] payload = PresenceManager.getInstance() + .makeResponsePayload(deviceList); + return MessageBuilder.createResponse(request, ResponseStatus.CONTENT, ContentFormat.APPLICATION_CBOR, payload); + } - public IResponse handlePostRequest(IRequest request) + private IResponse handlePostRequest(IRequest request) throws ServerException { // check payload byte[] payload = request.getPayload(); @@ -126,104 +112,18 @@ public class DevicePresenceResource extends Resource { HashMap parsedPayload = mCbor .parsePayloadFromCbor(payload, HashMap.class); - if (checkPayloadException( + checkPayloadException( Arrays.asList(Constants.DEVICE_ID, Constants.PRESENCE_STATE), - parsedPayload)) { - - String deviceId = parsedPayload.get(Constants.DEVICE_ID).toString(); - String state = parsedPayload.get(Constants.PRESENCE_STATE) - .toString(); - DeviceState deviceState = new DeviceState(); - deviceState.setDi(deviceId); - deviceState.setState(state); + parsedPayload); - TypeCastingManager deviceStateTypeManager = new TypeCastingManager(); - HashMap storeMap = deviceStateTypeManager - .convertObjectToMap(deviceState); + // store db + PresenceManager.getInstance().updateDevicePresence(parsedPayload); - // store db - DBManager.getInstance().updateDeviceState(storeMap); - - // notification to observers - notifyToObservers(deviceId); - } + // notification to observers + String di = parsedPayload.get(Constants.DEVICE_ID).toString(); + PresenceManager.getInstance().notifyToObservers(di); return MessageBuilder.createResponse(request, ResponseStatus.CHANGED); - } - - private void addObserver(Device srcDevice, IRequest request, - List deviceIdList) { - - for (String deviceId : deviceIdList) { - HashMap subscribers = mDeviceSubscriber - .get(deviceId); - - if (subscribers == null) { - subscribers = new HashMap<>(); - mDeviceSubscriber.put(deviceId, subscribers); - } - - subscribers.put(request.getRequestId(), - new PresenceSubscriber(srcDevice, request)); - } - - mSubscribedDevices.put(request.getRequestId(), deviceIdList); - } - - private void removeObserver(IRequest request) { - - List deviceIdList = mSubscribedDevices - .get(request.getRequestId()); - - if (deviceIdList == null) { - return; - } - - for (String deviceId : deviceIdList) { - HashMap subscribers = mDeviceSubscriber - .get(deviceId); - - if (subscribers == null) { - continue; - } - - subscribers.remove(request.getRequestId()); - } - } - - private void notifyToObservers(String deviceId) { - - HashMap tokenNSubscribers = mDeviceSubscriber - .get(deviceId); - - if (tokenNSubscribers != null) { - byte[] paylod = makeResponsePayload(Arrays.asList(deviceId)); - - for (PresenceSubscriber subscriber : tokenNSubscribers.values()) { - - subscriber.mSubscriber.sendResponse( - MessageBuilder.createResponse(subscriber.mRequest, - ResponseStatus.CONTENT, - ContentFormat.APPLICATION_CBOR, paylod)); - } - } - } - - private byte[] makeResponsePayload(List deviceList) { - - HashMap getPayload = new HashMap<>(); - ArrayList> prsList = new ArrayList>(); - - for (String deviceId : deviceList) { - HashMap payloadSegment = new HashMap(); - payloadSegment.put(Constants.DEVICE_ID, deviceId); - payloadSegment.put(Constants.PRESENCE_STATE, - DBManager.getInstance().findDeviceState(deviceId)); - prsList.add(payloadSegment); - } - getPayload.put(Constants.PRESENCE_LIST, prsList); - Log.i("Get observe response" + getPayload.toString()); - return mCbor.encodingPayloadToCbor(getPayload); } } diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/device/DeviceState.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/device/DeviceState.java deleted file mode 100644 index 72fd80c..0000000 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/device/DeviceState.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * //****************************************************************** - * // - * // Copyright 2016 Samsung Electronics All Rights Reserved. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - * // - * // Licensed under the Apache License, Version 2.0 (the "License"); - * // you may not use this file except in compliance with the License. - * // You may obtain a copy of the License at - * // - * // http://www.apache.org/licenses/LICENSE-2.0 - * // - * // Unless required by applicable law or agreed to in writing, software - * // distributed under the License is distributed on an "AS IS" BASIS, - * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * // See the License for the specific language governing permissions and - * // limitations under the License. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - */ -package org.iotivity.cloud.rdserver.resources.presence.device; - -public class DeviceState { - - private String di; - private String state; - - public String getState() { - return state; - } - - public void setState(String state) { - this.state = state; - } - - public String getDi() { - return di; - } - - public void setDi(String deviceId) { - this.di = deviceId; - } - -} diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/resource/ResPresencePayload.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/resource/ResPresencePayload.java deleted file mode 100644 index 8a9839a..0000000 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/resource/ResPresencePayload.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * //****************************************************************** - * // - * // Copyright 2016 Samsung Electronics All Rights Reserved. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - * // - * // Licensed under the Apache License, Version 2.0 (the "License"); - * // you may not use this file except in compliance with the License. - * // You may obtain a copy of the License at - * // - * // http://www.apache.org/licenses/LICENSE-2.0 - * // - * // Unless required by applicable law or agreed to in writing, software - * // distributed under the License is distributed on an "AS IS" BASIS, - * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * // See the License for the specific language governing permissions and - * // limitations under the License. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - */ -package org.iotivity.cloud.rdserver.resources.presence.resource; - -public class ResPresencePayload { - int non; - int ttl; - byte trg; - String rt; - String href; - - public int getNon() { - return non; - } - - public void setNon(int non) { - this.non = non; - } - - public int getTtl() { - return ttl; - } - - public void setTtl(int ttl) { - this.ttl = ttl; - } - - public byte getTrg() { - return trg; - } - - public void setTrg(byte trg) { - this.trg = trg; - } - - public String getRt() { - return rt; - } - - public void setRt(String rt) { - this.rt = rt; - } - - public String getHref() { - return href; - } - - public void setHref(String href) { - this.href = href; - } -} \ No newline at end of file diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/resource/ResPresenceResource.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/resource/ResPresenceResource.java index 1472463..8ab8640 100644 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/resource/ResPresenceResource.java +++ b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/resource/ResPresenceResource.java @@ -28,15 +28,19 @@ import java.util.List; import org.iotivity.cloud.base.device.Device; import org.iotivity.cloud.base.exception.ServerException; import org.iotivity.cloud.base.exception.ServerException.BadRequestException; -import org.iotivity.cloud.base.exception.ServerException.PreconditionFailedException; 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.enums.ResponseStatus; import org.iotivity.cloud.base.resource.Resource; import org.iotivity.cloud.rdserver.Constants; -import org.iotivity.cloud.rdserver.resources.presence.ResPresenceManager; +import org.iotivity.cloud.rdserver.resources.presence.PresenceManager; +/** + * + * This class provides a set of APIs handle requests about resource presence + * + */ public class ResPresenceResource extends Resource { public ResPresenceResource() { @@ -51,7 +55,7 @@ public class ResPresenceResource extends Resource { switch (request.getMethod()) { case GET: - response = handleRegisterRequest(srcDevice, request); + response = handleGetRequest(srcDevice, request); break; default: @@ -62,23 +66,17 @@ public class ResPresenceResource extends Resource { srcDevice.sendResponse(response); } - public IResponse handleRegisterRequest(Device srcDevice, IRequest request) + private IResponse handleGetRequest(Device srcDevice, IRequest request) throws ServerException { HashMap> queryMap = request.getUriQueryMap(); - if (queryMap == null) { - throw new PreconditionFailedException("query is null"); - } + checkQueryException(Arrays.asList(Constants.DEVICE_ID), queryMap); List deviceList = queryMap.get(Constants.DEVICE_ID); - if (deviceList == null) { - throw new PreconditionFailedException("deviceList is null"); - } - - ResPresenceManager.getInstance().addObserver(srcDevice, request, - deviceList); + PresenceManager.getInstance().subscribePresence(srcDevice, request, + deviceList, Constants.RESOURCE_PRESENCE); return MessageBuilder.createResponse(request, ResponseStatus.CONTENT); } diff --git a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/util/TypeCastingManager.java b/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/util/TypeCastingManager.java deleted file mode 100644 index cc9df99..0000000 --- a/cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/util/TypeCastingManager.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * //****************************************************************** - * // - * // Copyright 2016 Samsung Electronics All Rights Reserved. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - * // - * // Licensed under the Apache License, Version 2.0 (the "License"); - * // you may not use this file except in compliance with the License. - * // You may obtain a copy of the License at - * // - * // http://www.apache.org/licenses/LICENSE-2.0 - * // - * // Unless required by applicable law or agreed to in writing, software - * // distributed under the License is distributed on an "AS IS" BASIS, - * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * // See the License for the specific language governing permissions and - * // limitations under the License. - * // - * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - */ -package org.iotivity.cloud.rdserver.util; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Iterator; - -import org.iotivity.cloud.rdserver.Constants; - -public class TypeCastingManager { - - public TypeCastingManager() { - - } - - public void callMethod(String methodName, T objClass) { - try { - Method method = objClass.getClass().getDeclaredMethod(methodName); - method.invoke(objClass); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - public HashMap convertObjectToMap(T objClass) { - - HashMap map = new HashMap(); - - try { - Field[] fieldList = objClass.getClass().getDeclaredFields(); - - for (Field field : fieldList) { - field.setAccessible(true); - Object value = field.get(objClass); - if (value != null) { - String fieldName = field.getName(); - if (fieldName.equals("itf")) { - fieldName = Constants.INTERFACE; - } - map.put(fieldName, value); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - return map; - } - - public T convertMaptoObject(HashMap map, T objClass) { - - String keyAttribute = null; - String methodName = null; - Iterator iter = map.keySet().iterator(); - String prefixName = "set"; - while (iter.hasNext()) { - keyAttribute = iter.next().toString(); - methodName = makeMethodName(keyAttribute, prefixName); - - Method[] methodList = objClass.getClass().getDeclaredMethods(); - - for (Method method : methodList) { - if (methodName.equals(method.getName())) { - try { - method.invoke(objClass, map.get(keyAttribute)); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - return objClass; - } - - private String makeMethodName(String keyAttribute, String prefixName) { - - // Exception case - if (keyAttribute.equals(Constants.INTERFACE)) { - keyAttribute = "itf"; - } - - String methodName = null; - - methodName = prefixName + keyAttribute.substring(0, 1).toUpperCase() - + keyAttribute.substring(1); - - return methodName; - } -} diff --git a/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/DevicePresenceResourceTest.java b/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/DevicePresenceResourceTest.java index 3e4e851..1e60ce6 100644 --- a/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/DevicePresenceResourceTest.java +++ b/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/DevicePresenceResourceTest.java @@ -22,7 +22,6 @@ package org.iotivity.cloud.testrdserver; import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; @@ -41,7 +40,6 @@ import org.iotivity.cloud.base.protocols.enums.Observe; import org.iotivity.cloud.base.protocols.enums.RequestMethod; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.rdserver.Constants; -import org.iotivity.cloud.rdserver.resources.directory.rd.ResourceDirectoryResource; import org.iotivity.cloud.rdserver.resources.presence.device.DevicePresenceResource; import org.iotivity.cloud.util.Cbor; import org.junit.After; @@ -52,20 +50,18 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; public class DevicePresenceResourceTest { - private Cbor> mCbor = new Cbor<>(); - private ResourceDirectoryResource mRDResource = null; - private DevicePresenceResource mockDevicePresenceResource = null; - private CoapDevice mockDevice = null; - private CountDownLatch mLatch = null; + private Cbor> mCbor = new Cbor<>(); + private DevicePresenceResource mMockDevicePresenceResource = null; + private CoapDevice mMockDevice = null; + private CountDownLatch mLatch = null; private IResponse mResponse; @Before public void setUp() throws Exception { mResponse = null; - mockDevice = mock(CoapDevice.class); + mMockDevice = mock(CoapDevice.class); mLatch = new CountDownLatch(1); - mRDResource = new ResourceDirectoryResource(); - mockDevicePresenceResource = new DevicePresenceResource(); + mMockDevicePresenceResource = new DevicePresenceResource(); // callback mock Mockito.doAnswer(new Answer() { @Override @@ -76,7 +72,7 @@ public class DevicePresenceResourceTest { mResponse = resp; return null; } - }).when(mockDevice).sendResponse(Mockito.anyObject()); + }).when(mMockDevice).sendResponse(Mockito.anyObject()); } @After @@ -91,64 +87,41 @@ public class DevicePresenceResourceTest { request = MessageBuilder.createRequest(RequestMethod.GET, RDServerTestUtils.DEVICE_PRS_REQ_URI, query); } else if (obs.compareTo(Observe.UNSUBSCRIBE) == 0) { - ArrayList devices = new ArrayList<>(); - devices.add(RDServerTestUtils.DI); - HashMap> payload = new HashMap<>(); - payload.put(Constants.DEVICE_LIST_KEY, devices); request = MessageBuilder.createRequest(RequestMethod.GET, - RDServerTestUtils.DEVICE_PRS_REQ_URI, query, - ContentFormat.APPLICATION_CBOR, - mCbor.encodingPayloadToCbor(payload)); + RDServerTestUtils.DEVICE_PRS_REQ_URI, query); } ((CoapRequest) request).setObserve(obs); return request; } - private HashMap parsePayload(IResponse response) { - - HashMap payloadData = mCbor - .parsePayloadFromCbor(response.getPayload(), HashMap.class); - - ArrayList> prsList = (ArrayList>) payloadData - .get(Constants.PRESENCE_LIST); - - HashMap mapData = prsList.get(0); - - return mapData; - } - @Test public void testSubscribeRequest() throws Exception { System.out.println("\t------testHandleGetSubscribeRequest"); - mRDResource.onDefaultRequestReceived(mockDevice, - RDServerTestUtils.makePublishRequest()); IRequest request = makePresenceGetRequest(Observe.SUBSCRIBE); - mockDevicePresenceResource.onDefaultRequestReceived(mockDevice, + mMockDevicePresenceResource.onDefaultRequestReceived(mMockDevice, request); // assertion: if the response status is "CONTENT" assertTrue(mLatch.await(2L, SECONDS)); assertTrue(checkResponseCode(mResponse, ResponseStatus.CONTENT)); - // assertion : if the payload has "di" and "state" - assertTrue(checkPayloadProperty(mResponse, Constants.DEVICE_ID)); - assertTrue(checkPayloadProperty(mResponse, Constants.PRESENCE_STATE)); - assertNull(parsePayload(mResponse).get(Constants.PRESENCE_STATE)); + assertTrue(checkPayloadProperty(mResponse, Constants.DEVICE_ID, + RDServerTestUtils.DI)); + assertTrue(checkPayloadProperty(mResponse, Constants.PRESENCE_STATE, + Constants.PRESENCE_OFF)); } @Test public void testUnsubscribeRequest() throws Exception { System.out.println("\t------testHandleGetUnsubscribeRequest"); IRequest request = makePresenceGetRequest(Observe.UNSUBSCRIBE); - mRDResource.onDefaultRequestReceived(mockDevice, - RDServerTestUtils.makePublishRequest()); - mockDevicePresenceResource.onDefaultRequestReceived(mockDevice, + mMockDevicePresenceResource.onDefaultRequestReceived(mMockDevice, request); // assertion: if the response status is "CONTENT" assertTrue(mLatch.await(2L, SECONDS)); assertTrue(checkResponseCode(mResponse, ResponseStatus.CONTENT)); - // assertion : if the payload has "di" and "state" - assertTrue(checkPayloadProperty(mResponse, Constants.DEVICE_ID)); - assertTrue(checkPayloadProperty(mResponse, Constants.PRESENCE_STATE)); - assertNull(parsePayload(mResponse).get(Constants.PRESENCE_STATE)); + assertTrue(checkPayloadProperty(mResponse, Constants.DEVICE_ID, + RDServerTestUtils.DI)); + assertTrue(checkPayloadProperty(mResponse, Constants.PRESENCE_STATE, + Constants.PRESENCE_OFF)); } @Test @@ -173,11 +146,9 @@ public class DevicePresenceResourceTest { assertTrue(checkResponseCode(response, ResponseStatus.CONTENT)); assertTrue(checkPayloadProperty(response, - Constants.DEVICE_ID)); + Constants.DEVICE_ID, RDServerTestUtils.DI)); assertTrue(checkPayloadProperty(response, - Constants.PRESENCE_STATE)); - assertTrue(parsePayload(response) - .get(Constants.PRESENCE_STATE).equals("on")); + Constants.PRESENCE_STATE, Constants.PRESENCE_ON)); } return null; @@ -186,17 +157,17 @@ public class DevicePresenceResourceTest { }).when(observerDevice).sendResponse(Mockito.anyObject()); // subscribe request (specific device) IRequest subRequest = makePresenceGetRequest(Observe.SUBSCRIBE); - mockDevicePresenceResource.onDefaultRequestReceived(observerDevice, + mMockDevicePresenceResource.onDefaultRequestReceived(observerDevice, subRequest); // POST device presence off HashMap payload = new HashMap<>(); payload.put(Constants.DEVICE_ID, RDServerTestUtils.DI); - payload.put(Constants.PRESENCE_STATE, "on"); + payload.put(Constants.PRESENCE_STATE, Constants.PRESENCE_ON); IRequest request = MessageBuilder.createRequest(RequestMethod.POST, RDServerTestUtils.DEVICE_PRS_REQ_URI, null, ContentFormat.APPLICATION_CBOR, mCbor.encodingPayloadToCbor(payload)); - mockDevicePresenceResource.onDefaultRequestReceived(mockDevice, + mMockDevicePresenceResource.onDefaultRequestReceived(mMockDevice, request); // assertion for resource server device : responseStatus is "CHANGED" assertTrue(mLatch.await(2L, SECONDS)); @@ -221,6 +192,10 @@ public class DevicePresenceResourceTest { if (observerLatch.getCount() == 0) { assertTrue(checkResponseCode(response, ResponseStatus.CONTENT)); + assertTrue(checkPayloadProperty(response, + Constants.DEVICE_ID, RDServerTestUtils.DI)); + assertTrue(checkPayloadProperty(response, + Constants.PRESENCE_STATE, Constants.PRESENCE_OFF)); } return null; @@ -229,16 +204,16 @@ public class DevicePresenceResourceTest { }).when(observerDevice).sendResponse(Mockito.anyObject()); // subscribe request (specific device) IRequest subRequest = makePresenceGetRequest(Observe.UNSUBSCRIBE); - mockDevicePresenceResource.onDefaultRequestReceived(observerDevice, + mMockDevicePresenceResource.onDefaultRequestReceived(observerDevice, subRequest); HashMap payload = new HashMap<>(); payload.put(Constants.DEVICE_ID, RDServerTestUtils.DI); - payload.put(Constants.PRESENCE_STATE, "off"); + payload.put(Constants.PRESENCE_STATE, Constants.PRESENCE_OFF); IRequest request = MessageBuilder.createRequest(RequestMethod.POST, RDServerTestUtils.DEVICE_PRS_REQ_URI, null, ContentFormat.APPLICATION_CBOR, mCbor.encodingPayloadToCbor(payload)); - mockDevicePresenceResource.onDefaultRequestReceived(mockDevice, + mMockDevicePresenceResource.onDefaultRequestReceived(mMockDevice, request); // assertion for resource server device : responseStatus is "CHANGED" assertTrue(mLatch.await(2L, SECONDS)); @@ -247,7 +222,7 @@ public class DevicePresenceResourceTest { } private boolean checkPayloadProperty(IResponse response, - String propertyName) { + String propertyName, String propertyValue) { HashMap payloadData = mCbor .parsePayloadFromCbor(response.getPayload(), HashMap.class); @@ -255,9 +230,10 @@ public class DevicePresenceResourceTest { .get(Constants.PRESENCE_LIST); HashMap mapData = prsList.get(0); - if (mapData.containsKey(propertyName)) + if (mapData.containsKey(propertyName) + && mapData.get(propertyName).equals(propertyValue)) { return true; - else + } else return false; } diff --git a/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/DiscoveryResourceTest.java b/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/DiscoveryResourceTest.java index 193e298..1881f90 100644 --- a/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/DiscoveryResourceTest.java +++ b/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/DiscoveryResourceTest.java @@ -51,14 +51,14 @@ public class DiscoveryResourceTest { private ResourceDirectoryResource mRDResource = null; private DiscoveryResource mDiscoveryResource = null; private CoapDevice mockDevice = null; - CountDownLatch latch = null; - IResponse res; + private CountDownLatch mLatch = null; + private IResponse mResponse; @Before public void setUp() throws Exception { - res = null; + mResponse = null; mockDevice = mock(CoapDevice.class); - latch = new CountDownLatch(1); + mLatch = new CountDownLatch(1); mRDResource = new ResourceDirectoryResource(); mDiscoveryResource = new DiscoveryResource(); // callback mock @@ -67,8 +67,8 @@ public class DiscoveryResourceTest { public CoapResponse answer(InvocationOnMock invocation) throws Throwable { CoapResponse resp = (CoapResponse) invocation.getArguments()[0]; - latch.countDown(); - res = resp; + mLatch.countDown(); + mResponse = resp; return resp; } }).when(mockDevice).sendResponse(Mockito.anyObject()); @@ -85,11 +85,9 @@ public class DiscoveryResourceTest { RDServerTestUtils.DISCOVERY_REQ_URI, "rt=core.light;di=" + RDServerTestUtils.DI); mDiscoveryResource.onDefaultRequestReceived(mockDevice, request); - // assertion: if the response status is "CONTENT" - // assertion : if the payload is null - assertTrue(latch.await(2L, SECONDS)); - assertTrue(methodCheck(res, ResponseStatus.CONTENT)); - assertTrue(nullPayloadCheck(res)); + // assertion: if the response status is "NOT_FOUND" + assertTrue(mLatch.await(2L, SECONDS)); + assertTrue(methodCheck(mResponse, ResponseStatus.NOT_FOUND)); } @Test @@ -102,12 +100,12 @@ public class DiscoveryResourceTest { mDiscoveryResource.onDefaultRequestReceived(mockDevice, request); // assertion: if the response status is "CONTENT" // assertion : if the payload contains resource info - assertTrue(latch.await(2L, SECONDS)); - assertTrue(methodCheck(res, ResponseStatus.CONTENT)); - assertTrue(discoverHashmapCheck(res, "di")); - assertTrue(discoveredResourceCheck(res, "href")); - assertTrue(discoveredResourceCheck(res, "rt")); - assertTrue(discoveredResourceCheck(res, "if")); + assertTrue(mLatch.await(2L, SECONDS)); + assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT)); + assertTrue(discoverHashmapCheck(mResponse, "di")); + assertTrue(discoveredResourceCheck(mResponse, "href")); + assertTrue(discoveredResourceCheck(mResponse, "rt")); + assertTrue(discoveredResourceCheck(mResponse, "if")); } private boolean discoverHashmapCheck(IResponse response, @@ -147,7 +145,7 @@ public class DiscoveryResourceTest { private boolean nullPayloadCheck(IResponse response) { ArrayList payloadData = mCbor - .parsePayloadFromCbor(res.getPayload(), ArrayList.class); + .parsePayloadFromCbor(mResponse.getPayload(), ArrayList.class); return (payloadData.isEmpty()); } } \ No newline at end of file diff --git a/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/RDServerTestUtils.java b/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/RDServerTestUtils.java index 7859888..4b06246 100644 --- a/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/RDServerTestUtils.java +++ b/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/RDServerTestUtils.java @@ -19,6 +19,7 @@ public class RDServerTestUtils { public static final String RES_PRS_URI = Constants.RESOURCE_PRESENCE_FULL_URI; public static IRequest makePublishRequest() throws Exception { + HashMap payload = new HashMap<>(); payload.put(Constants.DEVICE_ID, DI); ArrayList> publishLinks = new ArrayList<>(); @@ -33,6 +34,8 @@ public class RDServerTestUtils { link.put(Constants.RESOURCE_TYPE, rt); link.put(Constants.INTERFACE, itf); link.put(Constants.POLICY, policy); + link.put(Constants.INS, 0); + link.put(Constants.RESOURCE_TTL, 3000); publishLinks.add(link); payload.put(Constants.LINKS, publishLinks); Cbor> cbor = new Cbor<>(); diff --git a/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/ResourceDirectoryResourceTest.java b/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/ResourceDirectoryResourceTest.java index 4d67b08..8acc787 100644 --- a/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/ResourceDirectoryResourceTest.java +++ b/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/ResourceDirectoryResourceTest.java @@ -49,14 +49,14 @@ public class ResourceDirectoryResourceTest { private Cbor> mCbor = new Cbor<>(); private ResourceDirectoryResource mRDResource = null; private CoapDevice mockDevice = null; - CountDownLatch latch = null; - IResponse res; + CountDownLatch mLatch = null; + IResponse mResponse; @Before public void setUp() throws Exception { - res = null; + mResponse = null; mockDevice = mock(CoapDevice.class); - latch = new CountDownLatch(1); + mLatch = new CountDownLatch(1); mRDResource = new ResourceDirectoryResource(); // callback mock Mockito.doAnswer(new Answer() { @@ -64,8 +64,8 @@ public class ResourceDirectoryResourceTest { public CoapResponse answer(InvocationOnMock invocation) throws Throwable { CoapResponse resp = (CoapResponse) invocation.getArguments()[0]; - latch.countDown(); - res = resp; + mLatch.countDown(); + mResponse = resp; return resp; } }).when(mockDevice).sendResponse(Mockito.anyObject()); @@ -83,15 +83,15 @@ public class ResourceDirectoryResourceTest { RDServerTestUtils.makePublishRequest()); // assertion: if the response status is "CHANGED" according to // the resource publication - assertTrue(latch.await(2L, SECONDS)); - assertTrue(methodCheck(res, ResponseStatus.CHANGED)); + assertTrue(mLatch.await(2L, SECONDS)); + assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); // assertion : if the mandatory properties are received in the // response - assertTrue(linkCheck(res, "href")); - assertTrue(linkCheck(res, "rt")); - assertTrue(linkCheck(res, "if")); - assertTrue(linkCheck(res, "ins")); - assertTrue(hashmapCheck(res, "di")); + assertTrue(linkCheck(mResponse, "href")); + assertTrue(linkCheck(mResponse, "rt")); + assertTrue(linkCheck(mResponse, "if")); + assertTrue(linkCheck(mResponse, "ins")); + assertTrue(hashmapCheck(mResponse, "di")); } @Test @@ -102,8 +102,8 @@ public class ResourceDirectoryResourceTest { mRDResource.onDefaultRequestReceived(mockDevice, request); // assertion: if the response status is "DELETED" according to the // resource publication - assertTrue(latch.await(2L, SECONDS)); - assertTrue(methodCheck(res, ResponseStatus.DELETED)); + assertTrue(mLatch.await(2L, SECONDS)); + assertTrue(methodCheck(mResponse, ResponseStatus.DELETED)); } @Test @@ -116,8 +116,8 @@ public class ResourceDirectoryResourceTest { mRDResource.onDefaultRequestReceived(mockDevice, request); // assertion: if the response status is "DELETED" according to the // resource publication - assertTrue(latch.await(2L, SECONDS)); - assertTrue(methodCheck(res, ResponseStatus.DELETED)); + assertTrue(mLatch.await(2L, SECONDS)); + assertTrue(methodCheck(mResponse, ResponseStatus.DELETED)); } @Test @@ -130,8 +130,8 @@ public class ResourceDirectoryResourceTest { mRDResource.onDefaultRequestReceived(mockDevice, request); // assertion: if the response status is "DELETED" according to the // resource publication - assertTrue(latch.await(2L, SECONDS)); - assertTrue(methodCheck(res, ResponseStatus.DELETED)); + assertTrue(mLatch.await(2L, SECONDS)); + assertTrue(methodCheck(mResponse, ResponseStatus.DELETED)); } @Test @@ -145,8 +145,8 @@ public class ResourceDirectoryResourceTest { mRDResource.onDefaultRequestReceived(mockDevice, request); // assertion: if the response status is "DELETED" according to the // resource publication - assertTrue(latch.await(2L, SECONDS)); - assertTrue(methodCheck(res, ResponseStatus.DELETED)); + assertTrue(mLatch.await(2L, SECONDS)); + assertTrue(methodCheck(mResponse, ResponseStatus.DELETED)); } private boolean hashmapCheck(IResponse response, String propertyName) { diff --git a/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/ResourcePresenceResourceTest.java b/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/ResourcePresenceResourceTest.java index 0c647d1..d2773fa 100644 --- a/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/ResourcePresenceResourceTest.java +++ b/cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/ResourcePresenceResourceTest.java @@ -47,24 +47,24 @@ public class ResourcePresenceResourceTest { private ResourceDirectoryResource mRDResource = null; private ResPresenceResource mResPresenceResource = null; private CoapDevice mockDevice = null; - CountDownLatch latch = null; - IResponse res; + private CountDownLatch mLatch = null; + private IResponse mResponse; @Before public void setUp() throws Exception { mRDResource = new ResourceDirectoryResource(); mResPresenceResource = new ResPresenceResource(); - res = null; + mResponse = null; mockDevice = mock(CoapDevice.class); - latch = new CountDownLatch(1); + mLatch = new CountDownLatch(1); // callback mock Mockito.doAnswer(new Answer() { @Override public CoapResponse answer(InvocationOnMock invocation) throws Throwable { CoapResponse resp = (CoapResponse) invocation.getArguments()[0]; - latch.countDown(); - res = resp; + mLatch.countDown(); + mResponse = resp; return resp; } }).when(mockDevice).sendResponse(Mockito.anyObject()); @@ -81,8 +81,8 @@ public class ResourcePresenceResourceTest { IRequest request = MessageBuilder.createRequest(RequestMethod.GET, RDServerTestUtils.RES_PRS_URI, "di=" + RDServerTestUtils.DI); mResPresenceResource.onDefaultRequestReceived(mockDevice, request); - assertTrue(latch.await(2L, SECONDS)); - assertTrue(methodCheck(res, ResponseStatus.CONTENT)); + assertTrue(mLatch.await(2L, SECONDS)); + assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT)); } @Test @@ -125,8 +125,8 @@ public class ResourcePresenceResourceTest { mRDResource.onDefaultRequestReceived(mockDevice, RDServerTestUtils.makePublishRequest()); // assertion: if the response status is "CHANGED" - assertTrue(latch.await(2L, SECONDS)); - assertTrue(methodCheck(res, ResponseStatus.CHANGED)); + assertTrue(mLatch.await(2L, SECONDS)); + assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); } private boolean methodCheck(IResponse response, diff --git a/cloud/samples/client/SConscript b/cloud/samples/client/SConscript index b9335c1..aadd7a4 100644 --- a/cloud/samples/client/SConscript +++ b/cloud/samples/client/SConscript @@ -102,3 +102,8 @@ group_invite_src = [ 'group_invite/group_invite.cpp' ] cc_sample_app_env.Program('group_invite_sample', group_invite_src) + +group_light_share_src = [ + 'group_invite/group_light_share.cpp' + ] +cc_sample_app_env.Program('group_light_share_sample', group_light_share_src) diff --git a/cloud/samples/client/airconditioner/aircon_controller.cpp b/cloud/samples/client/airconditioner/aircon_controller.cpp index 344ac22..bc9a929 100644 --- a/cloud/samples/client/airconditioner/aircon_controller.cpp +++ b/cloud/samples/client/airconditioner/aircon_controller.cpp @@ -217,6 +217,8 @@ void foundAirconditionerResource(shared_ptr resource) void foundDevice(shared_ptr resource) { + cout << "Found device called!" << endl; + vector rt = resource->getResourceTypes(); cout << "Device found: " << resource->uri() << endl; @@ -248,6 +250,12 @@ void foundDevice(shared_ptr resource) } } +void errorFoundDevice(const std::string &uri, const int ecode) +{ + cout << "Found device error on " << uri << " code " << ecode << endl; + g_callbackLock.notify_all(); +} + void presenceDevice(OCStackResult , const unsigned int i, const string &str) { cout << "Presence received, i=" << i << " str=" << str << endl; @@ -325,7 +333,7 @@ int main(int argc, char *argv[]) result = OCPlatform::findResource(g_host, "/oic/res?rt=oic.wk.d", static_cast(CT_ADAPTER_TCP | CT_IP_USE_V4), - &foundDevice); + &foundDevice, &errorFoundDevice); cout << " result: " << result << endl; diff --git a/cloud/samples/client/group_invite/group_invite.cpp b/cloud/samples/client/group_invite/group_invite.cpp index b51789c..ec85e5e 100644 --- a/cloud/samples/client/group_invite/group_invite.cpp +++ b/cloud/samples/client/group_invite/group_invite.cpp @@ -241,143 +241,150 @@ int main(int argc, char *argv[]) { cin >> cmd; - QueryParamsMap query; - OCRepresentation rep; - - switch (atoi(cmd.c_str())) + try { - case 1: - cout << "Put userUUID to search:" << endl; - cin >> cmd; - result = accountMgr->searchUser(cmd, &ocPost); - break; - - case 2: - cout << "Put email to search:" << endl; - cin >> cmd; - query["email"] = cmd; - result = accountMgr->searchUser(query, &ocPost); - break; - - case 3: - cout << "Put phone number to search:" << endl; - cin >> cmd; - query["phone"] = cmd; - result = accountMgr->searchUser(query, &ocPost); - break; - - case 4: - cout << "PUT deviceID to delete:"; - cin >> cmd; - result = accountMgr->deleteDevice(cmd, &onDelete); - break; - - case 5: - result = accountMgr->createGroup(OC::AclGroupType::PUBLIC, &ocPost); - break; - - case 6: - cout << "PUT groupId to observe:"; - cin >> cmd; - result = accountMgr->observeGroup(cmd, &onObserve); - break; - - case 7: - result = accountMgr->getGroupList(&ocPost); - break; - - case 8: - cout << "PUT groupId to delete:"; - cin >> cmd; - result = accountMgr->deleteGroup(cmd, &onDelete); - break; - - case 9: - cout << "PUT groupId to join:"; - cin >> cmd; - result = accountMgr->joinGroup(cmd, &ocPost); - break; - - case 10: - cout << "PUT groupId to add device:"; - cin >> cmd; - cout << "PUT deviceId to add to group:"; - cin >> cmd2; - { - vector deviceIds; - deviceIds.push_back(cmd2); - result = accountMgr->addDeviceToGroup(cmd, deviceIds, &ocPost); - } - break; - - case 11: - cout << "PUT groupId to get info:"; - cin >> cmd; - result = accountMgr->getGroupInfo(cmd, &ocPost); - break; - - case 12: - cout << "PUT groupId to leave:"; - cin >> cmd; - result = accountMgr->leaveGroup(cmd, &onDelete); - break; - - case 13: - cout << "PUT groupId to remove device:"; - cin >> cmd; - cout << "PUT deviceId to remove from group:"; - cin >> cmd2; - { - vector deviceIds; - deviceIds.push_back(cmd2); - result = accountMgr->deleteDeviceFromGroup(cmd, deviceIds, &onDelete); - } - break; - - case 14: - result = accountMgr->observeInvitation(&onObserve); - break; - - case 15: - cout << "PUT groupId to invite:"; - cin >> cmd; - cout << "PUT userUUID to invite:"; - cin >> cmd2; - result = accountMgr->sendInvitation(cmd, cmd2, &ocPost); - break; - - case 16: - cout << "PUT groupId to cancel invitation:"; - cin >> cmd; - cout << "PUT userUUID to cancel invitation:"; - cin >> cmd2; - result = accountMgr->cancelInvitation(cmd, cmd2, &onDelete); - break; - - case 17: - cout << "PUT groupId to delete invitation:"; - cin >> cmd; - result = accountMgr->deleteInvitation(cmd, &onDelete); - break; - - case 18: - cout << "PUT groupId to cancel observe:"; - cin >> cmd; - result = accountMgr->cancelObserveGroup(cmd); - break; - - case 19: - result = accountMgr->cancelObserveInvitation(); - break; - - case 20: - goto exit; - break; - } + QueryParamsMap query; + OCRepresentation rep; + + switch (atoi(cmd.c_str())) + { + case 1: + cout << "Put userUUID to search:" << endl; + cin >> cmd; + result = accountMgr->searchUser(cmd, &ocPost); + break; + + case 2: + cout << "Put email to search:" << endl; + cin >> cmd; + query["email"] = cmd; + result = accountMgr->searchUser(query, &ocPost); + break; + + case 3: + cout << "Put phone number to search:" << endl; + cin >> cmd; + query["phone"] = cmd; + result = accountMgr->searchUser(query, &ocPost); + break; + + case 4: + cout << "PUT deviceID to delete:"; + cin >> cmd; + result = accountMgr->deleteDevice(cmd, &onDelete); + break; + + case 5: + result = accountMgr->createGroup(OC::AclGroupType::PUBLIC, &ocPost); + break; - if (result != OC_STACK_OK) + case 6: + cout << "PUT groupId to observe:"; + cin >> cmd; + result = accountMgr->observeGroup(cmd, &onObserve); + break; + + case 7: + result = accountMgr->getGroupList(&ocPost); + break; + + case 8: + cout << "PUT groupId to delete:"; + cin >> cmd; + result = accountMgr->deleteGroup(cmd, &onDelete); + break; + + case 9: + cout << "PUT groupId to join:"; + cin >> cmd; + result = accountMgr->joinGroup(cmd, &ocPost); + break; + + case 10: + cout << "PUT groupId to add device:"; + cin >> cmd; + cout << "PUT deviceId to add to group:"; + cin >> cmd2; + { + vector deviceIds; + deviceIds.push_back(cmd2); + result = accountMgr->addDeviceToGroup(cmd, deviceIds, &ocPost); + } + break; + + case 11: + cout << "PUT groupId to get info:"; + cin >> cmd; + result = accountMgr->getGroupInfo(cmd, &ocPost); + break; + + case 12: + cout << "PUT groupId to leave:"; + cin >> cmd; + result = accountMgr->leaveGroup(cmd, &onDelete); + break; + + case 13: + cout << "PUT groupId to remove device:"; + cin >> cmd; + cout << "PUT deviceId to remove from group:"; + cin >> cmd2; + { + vector deviceIds; + deviceIds.push_back(cmd2); + result = accountMgr->deleteDeviceFromGroup(cmd, deviceIds, &onDelete); + } + break; + + case 14: + result = accountMgr->observeInvitation(&onObserve); + break; + + case 15: + cout << "PUT groupId to invite:"; + cin >> cmd; + cout << "PUT userUUID to invite:"; + cin >> cmd2; + result = accountMgr->sendInvitation(cmd, cmd2, &ocPost); + break; + + case 16: + cout << "PUT groupId to cancel invitation:"; + cin >> cmd; + cout << "PUT userUUID to cancel invitation:"; + cin >> cmd2; + result = accountMgr->cancelInvitation(cmd, cmd2, &onDelete); + break; + + case 17: + cout << "PUT groupId to delete invitation:"; + cin >> cmd; + result = accountMgr->deleteInvitation(cmd, &onDelete); + break; + + case 18: + cout << "PUT groupId to cancel observe:"; + cin >> cmd; + result = accountMgr->cancelObserveGroup(cmd); + break; + + case 19: + result = accountMgr->cancelObserveInvitation(); + break; + + case 20: + goto exit; + break; + } + + if (result != OC_STACK_OK) + { + cout << "Error, return code: " << result << endl; + } + } + catch (exception e) { - cout << "Error, return code: " << result << endl; + cout << "Precondition failed." << endl; } } diff --git a/cloud/samples/client/group_invite/group_light_share.cpp b/cloud/samples/client/group_invite/group_light_share.cpp new file mode 100644 index 0000000..17aecff --- /dev/null +++ b/cloud/samples/client/group_invite/group_light_share.cpp @@ -0,0 +1,432 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ocstack.h" +#include "ocpayload.h" +#include "rd_client.h" + +#include +#include + +#define maxSequenceNumber 0xFFFFFF + +using namespace OC; +using namespace std; + +string g_host = "coap+tcp://"; +condition_variable g_callbackLock; + +class LightResource +{ +public: + /// Access this property from a TB client + std::string m_power; + std::string m_lightUri; + OCResourceHandle m_resourceHandle; + OCRepresentation m_lightRep; + + /// Constructor + LightResource() : + m_power(""), m_lightUri("/a/light") + { + // Initialize representation + m_lightRep.setUri(m_lightUri); + m_lightRep.setValue("power", m_power); + } + + /// This function internally calls registerResource API. + void createResource() + { + std::string resourceURI = m_lightUri; //URI of the resource + std::string resourceTypeName = "core.light"; //resource type name. In this case, it is light + std::string resourceInterface = DEFAULT_INTERFACE; // resource interface. + + EntityHandler cb = std::bind(&LightResource::entityHandler, this, std::placeholders::_1); + + // This will internally create and register the resource. + OCStackResult result = OCPlatform::registerResource(m_resourceHandle, resourceURI, + resourceTypeName, resourceInterface, cb, OC_DISCOVERABLE | OC_OBSERVABLE); + + if (OC_STACK_OK != result) + { + cout << "Resource creation was unsuccessful\n"; + } + } + + OCRepresentation post(OCRepresentation &rep) + { + m_power = rep.getValueToString("power"); + return get(); + } + + // gets the updated representation. + // Updates the representation with latest internal state before + // sending out. + OCRepresentation get() + { + m_lightRep.setValue("power", m_power); + + return m_lightRep; + } + +private: + // This is just a sample implementation of entity handler. + // Entity handler can be implemented in several ways by the manufacturer + OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request) + { + cout << "\tIn Server CPP entity handler:\n"; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + if (request) + { + // Get the request type and request flag + std::string requestType = request->getRequestType(); + int requestFlag = request->getRequestHandlerFlag(); + + if (requestFlag & RequestHandlerFlag::RequestFlag) + { + cout << "\t\trequestFlag : Request\n"; + auto pResponse = std::make_shared< OC::OCResourceResponse >(); + pResponse->setRequestHandle(request->getRequestHandle()); + pResponse->setResourceHandle(request->getResourceHandle()); + + // If the request type is GET + if (requestType == "GET") + { + cout << "\t\t\trequestType : GET\n"; + pResponse->setErrorCode(200); + pResponse->setResponseResult(OC_EH_OK); + pResponse->setResourceRepresentation(get()); + if (OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else if (requestType == "POST") + { + cout << "\t\t\trequestType : POST\n"; + + OCRepresentation rep = request->getResourceRepresentation(); + + // Do related operations related to POST request + OCRepresentation rep_post = post(rep); + pResponse->setResourceRepresentation(rep_post); + pResponse->setErrorCode(200); + + if (OC_STACK_OK == OCPlatform::sendResponse(pResponse)) + { + ehResult = OC_EH_OK; + } + } + else + { + std::cout << "Unhandled request type" << std::endl; + } + } + } + else + { + std::cout << "Request invalid" << std::endl; + } + + return ehResult; + } +}; + +void printRepresentation(OCRepresentation rep) +{ + for (auto itr = rep.begin(); itr != rep.end(); ++itr) + { + cout << "\t" << itr->attrname() << ":\t" << itr->getValueToString() << endl; + if (itr->type() == AttributeType::Vector) + { + switch (itr->base_type()) + { + case AttributeType::OCRepresentation: + for (auto itr2 : (*itr).getValue< vector< OCRepresentation > >()) + { + printRepresentation(itr2); + } + break; + + case AttributeType::Integer: + for (auto itr2 : (*itr).getValue< vector< int > >()) + { + cout << "\t\t" << itr2 << endl; + } + break; + + case AttributeType::String: + for (auto itr2 : (*itr).getValue< vector< string > >()) + { + cout << "\t\t" << itr2 << endl; + } + break; + + default: + cout << "Unhandled base type " << itr->base_type() << endl; + break; + } + } + else if (itr->type() == AttributeType::OCRepresentation) + { + printRepresentation((*itr).getValue< OCRepresentation >()); + } + } +} + +void getResource(const HeaderOptions &, const OCRepresentation &rep, const int ecode) +{ + cout << "Resource get: " << ecode << endl; + + printRepresentation(rep); +} + +void foundMyDevice(shared_ptr< OC::OCResource > resource) +{ + cout << "Device found: " << resource->uri() << endl; + cout << "DI: " << resource->sid() << endl; + + g_callbackLock.notify_all(); +} + +void foundDevice(shared_ptr< OC::OCResource > resource) +{ + vector < string > rt = resource->getResourceTypes(); + + cout << "Device found: " << resource->uri() << endl; + cout << "DI: " << resource->sid() << endl; + + QueryParamsMap query; + resource->get(query, &getResource); +} + +void onObserveGroup(const HeaderOptions /*headerOptions*/, const OCRepresentation &rep, + const int &eCode, const int /*&sequenceNumber*/) +{ + cout << "onObserveGroup response received code: " << eCode << endl; + + if (eCode == OC_STACK_OK) + { + printRepresentation(rep); + + vector < string > dilist = rep.getValue < vector< string > > ("dilist"); + + for (auto itr = dilist.begin(); itr != dilist.end(); ++itr) + { + cout << (*itr) << " discovered" << endl; + if ((*itr) != OCGetServerInstanceIDString()) + { + cout << "New device joined" << endl; + string query = "/oic/res?di="; + query += (*itr); + OCStackResult result = OC_STACK_ERROR; + + cout << "find my resource : " << *itr << endl; + result = OCPlatform::findResource(g_host, query, + static_cast< OCConnectivityType >(CT_ADAPTER_TCP | CT_IP_USE_V4), + &foundDevice); + cout << " result: " << result << endl; + break; + } + } + } + g_callbackLock.notify_all(); +} + +string g_invitedGroup; +void onInvite(const HeaderOptions /*headerOptions*/, const OCRepresentation &rep, const int &eCode, + const int &sequenceNumber) +{ + cout << "onInvite response received code: " << eCode << endl; + + if (eCode == OC_STACK_OK) + { + printRepresentation(rep); + + if (sequenceNumber != OC_OBSERVE_REGISTER) + { + vector < OCRepresentation > invited = rep.getValue < vector< OCRepresentation > + > ("invited"); + + g_invitedGroup = invited[0].getValueToString("gid"); + } + } + + g_callbackLock.notify_all(); +} + +string g_gid; +void onCreateGroup(const HeaderOptions &, const OCRepresentation &rep, const int ecode) +{ + cout << "onCreateGroup response received code: " << ecode << endl; + + if (ecode == 4) + { + printRepresentation(rep); + g_gid = rep.getValueToString("gid"); + } + + g_callbackLock.notify_all(); +} + +void onPublish(const OCRepresentation &, const int &eCode) +{ + cout << "Publish resource response received, code: " << eCode << endl; + g_callbackLock.notify_all(); +} + +void onPost(const HeaderOptions & /*headerOptions*/, const OCRepresentation &rep, const int eCode) +{ + if (eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CHANGED) + { + cout << "\tRequest was successful: " << eCode << endl; + + printRepresentation(rep); + } + else + { + cout << "\tResponse error: " << eCode << endl; + } + + g_callbackLock.notify_all(); +} + +string g_uid; +string g_accesstoken; + +void handleLoginoutCB(const HeaderOptions &, const OCRepresentation &rep, const int ecode) +{ + cout << "Auth response received code: " << ecode << endl; + + if (rep.getPayload() != NULL) + { + printRepresentation(rep); + } + + if (ecode == 4) + { + g_accesstoken = rep.getValueToString("accesstoken"); + + g_uid = rep.getValueToString("uid"); + } + + g_callbackLock.notify_all(); +} + +string g_option; + +static FILE *client_open(const char * /*path*/, const char *mode) +{ + string option = "./"; + option += g_option; + option += ".dat"; + return fopen(option.c_str(), mode); +} + +int main(int argc, char **argv) +{ + if (argc != 5) + { + cout + << "Put \"[host-ipaddress:port] [authprovider] [authcode] [\'owner\'|\'member\']\" for sign-up and sign-in" + << endl; + cout << "Put \"[host-ipaddress:port] [uid] [accessToken] 1\" for sign-in" << endl; + return 0; + } + + g_option = argv[4]; + + OCPersistentStorage ps + { client_open, fread, fwrite, fclose, unlink }; + + PlatformConfig cfg + { ServiceType::InProc, ModeType::Both, "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces + 0, // Uses randomly available port + QualityOfService::LowQos, &ps }; + + OCPlatform::Configure(cfg); + + OCStackResult result = OC_STACK_ERROR; + + g_host += argv[1]; + + OCAccountManager::Ptr accountMgr = OCPlatform::constructAccountManagerObject(g_host, + CT_ADAPTER_TCP); + + mutex blocker; + unique_lock < mutex > lock(blocker); + + if (g_option == "1") + { + accountMgr->signIn(argv[2], argv[3], &handleLoginoutCB); + g_callbackLock.wait(lock); + } + else + { + accountMgr->signUp(argv[2], argv[3], &handleLoginoutCB); + g_callbackLock.wait(lock); + accountMgr->signIn(g_uid, g_accesstoken, &handleLoginoutCB); + g_callbackLock.wait(lock); + } + + string cmd; + + LightResource lightResource; + lightResource.createResource(); + + ResourceHandles resourceHandles; + resourceHandles.push_back(lightResource.m_resourceHandle); + + OCPlatform::publishResourceToRD(g_host, OCConnectivityType::CT_ADAPTER_TCP, resourceHandles, + &onPublish); + g_callbackLock.wait(lock); + if (g_option == "owner") + { + cout << "Creating group" << endl; + accountMgr->createGroup(AclGroupType::PUBLIC, &onCreateGroup); + g_callbackLock.wait(lock); + cout << "Adding device " << OCGetServerInstanceIDString() << " to group " << g_gid << endl; + accountMgr->addDeviceToGroup(g_gid, + { OCGetServerInstanceIDString() }, &onPost); + g_callbackLock.wait(lock); + + accountMgr->observeGroup(g_gid, &onObserveGroup); + g_callbackLock.wait(lock); + cout << "Put userUUID to send invitation" << endl; + cin >> cmd; + cout << "Group id : " << g_gid << " send invitation to " << cmd << endl; + accountMgr->sendInvitation(g_gid, cmd, &onPost); + g_callbackLock.wait(lock); + + cin >> cmd; + } + else if (g_option == "member") + { + cout << "Observing invitation" << endl; + accountMgr->observeInvitation(&onInvite); + g_callbackLock.wait(lock); + cout << "Waiting invitation" << endl; + g_callbackLock.wait(lock); + cout << "Joining group " << g_invitedGroup << endl; + accountMgr->joinGroup(g_invitedGroup, &onPost); + g_callbackLock.wait(lock); + + cout << "find my resource " << cmd << endl; + result = OCPlatform::findResource(g_host, "/oic/res", + static_cast< OCConnectivityType >(CT_ADAPTER_TCP | CT_IP_USE_V4), &foundMyDevice); + g_callbackLock.wait(lock); + + accountMgr->observeGroup(g_invitedGroup, &onObserveGroup); + g_callbackLock.wait(lock); + + cin >> cmd; + } + + return 0; +} diff --git a/cloud/samples/client/messagequeue/mq_publisher.cpp b/cloud/samples/client/messagequeue/mq_publisher.cpp index f04e037..743b794 100644 --- a/cloud/samples/client/messagequeue/mq_publisher.cpp +++ b/cloud/samples/client/messagequeue/mq_publisher.cpp @@ -216,66 +216,89 @@ int main(int argc, char *argv[]) { cin >> cmd; - QueryParamsMap query; - OCRepresentation rep; - string topicType; - - switch (cmd[0]) + try { - case '0': - gTopicList.clear(); - cout << "Discovering topics" << endl; - result = g_mqBrokerResource->discoveryMQTopics(query, &discoverTopicCB, QualityOfService::LowQos); - break; - - case '1': - gTopicList.clear(); - cout << "Put topic type to discover: "; - cin >> cmd; - query["rt"] = cmd; - result = g_mqBrokerResource->discoveryMQTopics(query, &discoverTopicCB, QualityOfService::LowQos); - break; - - case '2': - cout << "Put discovered topic index to select: "; - cin >> cmd; - g_mqSelectedTopicResource = gTopicList[atoi(cmd.c_str())]; - cout << g_mqSelectedTopicResource->uri() << " selected" << endl; - break; - - case '3': - cout << "Put message to selected topic: "; - cin >> cmd; - rep["message"] = cmd; - result = g_mqSelectedTopicResource->publishMQTopic(rep, query, &publishMessageCB, - QualityOfService::LowQos); - break; - - case '4': - cout << "Put topic uri to create: "; - cin >> cmd; - result = g_mqBrokerResource->createMQTopic(rep, cmd, query, &createTopicCB, - QualityOfService::LowQos); - break; - - case '5': - cout << "Put topic uri to create: "; - cin >> cmd; - cout << "Put topic type: "; - cin >> topicType; - query["rt"] = topicType; - result = g_mqBrokerResource->createMQTopic(rep, cmd, query, &createTopicCB, - QualityOfService::LowQos); - break; - - case 'q': - goto exit; - break; - } - if (result != OC_STACK_OK) + QueryParamsMap query; + OCRepresentation rep; + string topicType; + + switch (cmd[0]) + { + case '0': + gTopicList.clear(); + cout << "Discovering topics" << endl; + result = g_mqBrokerResource->discoveryMQTopics(query, &discoverTopicCB, QualityOfService::LowQos); + break; + + case '1': + gTopicList.clear(); + cout << "Put topic type to discover: "; + cin >> cmd; + query["rt"] = cmd; + result = g_mqBrokerResource->discoveryMQTopics(query, &discoverTopicCB, QualityOfService::LowQos); + break; + + case '2': + cout << "Put discovered topic index to select: "; + cin >> cmd; + { + int index = atoi(cmd.c_str()); + if (index < 0 || (unsigned int) index >= gTopicList.size()) + { + cout << "invalid topic index selected" << endl; + continue; + } + + g_mqSelectedTopicResource = gTopicList[index]; + cout << g_mqSelectedTopicResource->uri() << " selected" << endl; + } + break; + + case '3': + if (g_mqSelectedTopicResource == nullptr) + { + cout << "Topic is not selected." << endl; + continue; + } + + cout << "Put message to selected topic: "; + cin >> cmd; + rep["message"] = cmd; + result = g_mqSelectedTopicResource->publishMQTopic(rep, query, &publishMessageCB, + QualityOfService::LowQos); + break; + + case '4': + cout << "Put topic uri to create: "; + cin >> cmd; + result = g_mqBrokerResource->createMQTopic(rep, cmd, query, &createTopicCB, + QualityOfService::LowQos); + break; + + case '5': + cout << "Put topic uri to create: "; + cin >> cmd; + cout << "Put topic type: "; + cin >> topicType; + query["rt"] = topicType; + result = g_mqBrokerResource->createMQTopic(rep, cmd, query, &createTopicCB, + QualityOfService::LowQos); + break; + + case 'q': + goto exit; + break; + } + + if (result != OC_STACK_OK) + { + cout << "Error, return code: " << result << endl; + } + } + catch (const exception &e) { - cout << "Error, return code: " << result << endl; + cout << "Precondition failed: " << e.what() << endl; } } diff --git a/cloud/samples/client/messagequeue/mq_subscriber.cpp b/cloud/samples/client/messagequeue/mq_subscriber.cpp index bd60726..fbebe6e 100644 --- a/cloud/samples/client/messagequeue/mq_subscriber.cpp +++ b/cloud/samples/client/messagequeue/mq_subscriber.cpp @@ -229,51 +229,78 @@ int main(int argc, char *argv[]) { cin >> cmd; - QueryParamsMap query; - OCRepresentation rep; - - switch (cmd[0]) + try { - case '0': - gTopicList.clear(); - cout << "Discovering topics" << endl; - result = g_mqBrokerResource->discoveryMQTopics(query, &discoverTopicCB, QualityOfService::LowQos); - break; - - case '1': - gTopicList.clear(); - cout << "Put topic type to discover: "; - cin >> cmd; - query["rt"] = cmd; - result = g_mqBrokerResource->discoveryMQTopics(query, &discoverTopicCB, QualityOfService::LowQos); - break; - - case '2': - cout << "Put discovered topic index to select: "; - cin >> cmd; - g_mqSelectedTopicResource = gTopicList[atoi(cmd.c_str())]; - cout << g_mqSelectedTopicResource->uri() << " selected" << endl; - break; - - case '3': - cout << "Subscribe to selected topic" << endl; - result = g_mqSelectedTopicResource->subscribeMQTopic(ObserveType::Observe, query, &subscribeCB, - QualityOfService::LowQos); - break; - - case '4': - cout << "Unsubscribe to selected topic" << endl; - result = g_mqSelectedTopicResource->unsubscribeMQTopic(QualityOfService::LowQos); - break; - - case 'q': - goto exit; - break; - } + QueryParamsMap query; + OCRepresentation rep; + + switch (cmd[0]) + { + case '0': + gTopicList.clear(); + cout << "Discovering topics" << endl; + result = g_mqBrokerResource->discoveryMQTopics(query, &discoverTopicCB, QualityOfService::LowQos); + break; + + case '1': + gTopicList.clear(); + cout << "Put topic type to discover: "; + cin >> cmd; + query["rt"] = cmd; + result = g_mqBrokerResource->discoveryMQTopics(query, &discoverTopicCB, QualityOfService::LowQos); + break; + + case '2': + cout << "Put discovered topic index to select: "; + cin >> cmd; + { + int index = atoi(cmd.c_str()); + if (index < 0 || (unsigned int) index >= gTopicList.size()) + { + cout << "invalid topic index selected" << endl; + continue; + } + + g_mqSelectedTopicResource = gTopicList[index]; + cout << g_mqSelectedTopicResource->uri() << " selected" << endl; + } + break; + + case '3': + if (g_mqSelectedTopicResource == nullptr) + { + cout << "Topic is not selected." << endl; + continue; + } + + cout << "Subscribe to selected topic" << endl; + result = g_mqSelectedTopicResource->subscribeMQTopic(ObserveType::Observe, query, &subscribeCB, + QualityOfService::LowQos); + break; + + case '4': + if (g_mqSelectedTopicResource == nullptr) + { + cout << "Topic is not selected." << endl; + continue; + } + cout << "Unsubscribe to selected topic" << endl; + result = g_mqSelectedTopicResource->unsubscribeMQTopic(QualityOfService::LowQos); + break; - if (result != OC_STACK_OK) + case 'q': + goto exit; + break; + } + + if (result != OC_STACK_OK) + { + cout << "Error, return code: " << result << endl; + } + } + catch (const exception &e) { - cout << "Error, return code: " << result << endl; + cout << "Precondition failed: " << e.what() << endl; } } diff --git a/cloud/samples/client/thin_light/thin_room_light.cpp b/cloud/samples/client/thin_light/thin_room_light.cpp index 9f2104e..17cec71 100644 --- a/cloud/samples/client/thin_light/thin_room_light.cpp +++ b/cloud/samples/client/thin_light/thin_room_light.cpp @@ -43,7 +43,7 @@ using namespace std; #define DEFAULT_AUTH_REFRESH "/oic/account/tokenrefresh" OCStackResult OCCloudSignup(const char *host, const char *deviceId, const char *authprovider, - const char *authcode, OCClientResponseHandler response) + const char *authcode, OCClientResponseHandler response) { char targetUri[MAX_URI_LENGTH * 2] = { 0, }; @@ -66,15 +66,16 @@ OCStackResult OCCloudSignup(const char *host, const char *deviceId, const char * OCRepPayloadSetPropString(registerPayload, "authcode", authcode); return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *) registerPayload, - CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); + CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); - no_memory: OCRepPayloadDestroy(registerPayload); +no_memory: + OCRepPayloadDestroy(registerPayload); return OC_STACK_NO_MEMORY; } OCStackResult OCCloudSession(const char *host, const char *query, const char *uId, - const char *deviceId, const char *accesstoken, bool isLogin, - OCClientResponseHandler response) + const char *deviceId, const char *accesstoken, bool isLogin, + OCClientResponseHandler response) { char targetUri[MAX_URI_LENGTH * 2] = { 0, }; @@ -109,15 +110,16 @@ OCStackResult OCCloudSession(const char *host, const char *query, const char *uI OCRepPayloadSetPropBool(loginoutPayload, "login", isLogin); return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *) loginoutPayload, - CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); + CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); - no_memory: OCRepPayloadDestroy(loginoutPayload); +no_memory: + OCRepPayloadDestroy(loginoutPayload); return OC_STACK_NO_MEMORY; } //Client should call refresh before expiresin or when receive 4.01 during sign-in OCStackResult OCCloudRefresh(const char *host, const char *query, const char *uId, - const char *deviceId, const char *refreshtoken, OCClientResponseHandler response) + const char *deviceId, const char *refreshtoken, OCClientResponseHandler response) { char targetUri[MAX_URI_LENGTH * 2] = { 0, }; @@ -141,14 +143,15 @@ OCStackResult OCCloudRefresh(const char *host, const char *query, const char *uI OCRepPayloadSetPropString(refreshPayload, "refreshtoken", refreshtoken); return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *) refreshPayload, - CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); + CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0); - no_memory: OCRepPayloadDestroy(refreshPayload); +no_memory: + OCRepPayloadDestroy(refreshPayload); return OC_STACK_NO_MEMORY; } OCStackResult OCCloudLogin(const char *host, const char *uId, const char *deviceId, - const char *accesstoken, OCClientResponseHandler response) + const char *accesstoken, OCClientResponseHandler response) { return OCCloudSession(host, DEFAULT_AUTH_SESSION, uId, deviceId, accesstoken, true, response); } @@ -198,10 +201,6 @@ OCRepPayload *constructResponse(OCEntityHandlerRequest *ehRequest) { currLightResource = &gLightInstance[0]; } - else if (ehRequest->resource == gLightInstance[1].handle) - { - currLightResource = &gLightInstance[1]; - } if (OC_REST_PUT == ehRequest->method) { @@ -276,17 +275,13 @@ void *ChangeLightRepresentation(void *param) { sleep(3); gLightInstance[0].power += 1; - gLightInstance[1].power += 3; if (gLightUnderObservation) { cout << " =====> Notifying stack of new power level " << gLightInstance[0].power - << endl; - cout << " =====> Notifying stack of new power level " << gLightInstance[1].power - << endl; + << endl; // Notifying all observers result = OCNotifyAllObservers(gLightInstance[0].handle, OC_NA_QOS); - result = OCNotifyAllObservers(gLightInstance[1].handle, OC_NA_QOS); cout << " =====> Notifying result " << result << endl; } @@ -297,7 +292,7 @@ void *ChangeLightRepresentation(void *param) void ProcessObserveRegister(OCEntityHandlerRequest *ehRequest) { cout << "Received observation registration request with observation Id " - << ehRequest->obsInfo.obsId << endl; + << ehRequest->obsInfo.obsId << endl; if (!observeThreadStarted) { @@ -321,7 +316,7 @@ void ProcessObserveDeregister(OCEntityHandlerRequest *ehRequest) bool clientStillObserving = false; cout << "Received observation deregistration request for observation Id " - << ehRequest->obsInfo.obsId << endl; + << ehRequest->obsInfo.obsId << endl; for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++) { if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId) @@ -339,13 +334,15 @@ void ProcessObserveDeregister(OCEntityHandlerRequest *ehRequest) } OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, - OCEntityHandlerRequest *entityHandlerRequest, void * /*callback*/) + OCEntityHandlerRequest *entityHandlerRequest, void * /*callback*/) { OCEntityHandlerResult ehResult = OC_EH_OK; OCEntityHandlerResponse response = - { 0, 0, OC_EH_ERROR, 0, 0, - { }, - { 0 }, false }; + { + 0, 0, OC_EH_ERROR, 0, 0, + { }, + { 0 }, false + }; // Validate pointer if (!entityHandlerRequest) @@ -357,7 +354,7 @@ OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, // Initialize certain response fields response.numSendVendorSpecificHeaderOptions = 0; memset(response.sendVendorSpecificHeaderOptions, 0, - sizeof response.sendVendorSpecificHeaderOptions); + sizeof response.sendVendorSpecificHeaderOptions); memset(response.resourceUri, 0, sizeof response.resourceUri); OCRepPayload *payload = nullptr; @@ -378,7 +375,7 @@ OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, else { cout << "Received unsupported method %d from client " << entityHandlerRequest->method - << endl; + << endl; ehResult = OC_EH_ERROR; } // If the result isn't an error or forbidden, send response @@ -431,7 +428,7 @@ int createLightResource(char *uri, LightResource *lightResource) lightResource->state = false; lightResource->power = 0; OCStackResult res = OCCreateResource(&(lightResource->handle), "core.light", "oc.mi.def", uri, - OCEntityHandlerCb, NULL, OC_DISCOVERABLE | OC_OBSERVABLE); + OCEntityHandlerCb, NULL, OC_DISCOVERABLE | OC_OBSERVABLE); cout << "Created Light resource with result:" << res << endl; return res; @@ -550,7 +547,7 @@ OCStackApplicationResult handleLoginoutCB(void *ctx, OCDoHandle /*handle*/, cout << "Login/out response received code: " << clientResponse->result << endl; if (clientResponse->payload != NULL - && clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION) + && clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION) { cout << "PAYLOAD_TYPE_REPRESENTATION received" << endl; @@ -578,7 +575,7 @@ OCStackApplicationResult handleRegisterCB(void *ctx, OCDoHandle /*handle*/, cout << "Register response received code: " << clientResponse->result << endl; if (clientResponse->payload != NULL - && clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION) + && clientResponse->payload->type == PAYLOAD_TYPE_REPRESENTATION) { cout << "PAYLOAD_TYPE_REPRESENTATION received" << endl; cout << "You can Sign-In using retrieved accesstoken when disconnected or reboot" << endl; @@ -675,21 +672,21 @@ int main(int argc, char *argv[]) case 2: cout << "Sign-Up to cloud using " << authProvider << " " << authCode << endl; res = OCCloudSignup(g_host.c_str(), OCGetServerInstanceIDString(), authProvider.c_str(), - authCode.c_str(), handleRegisterCB); + authCode.c_str(), handleRegisterCB); cout << "OCCloudSignup return " << res << endl; break; case 4: cout << "Sign-In to cloud using " << accessToken << endl; res = OCCloudLogin(g_host.c_str(), uId.c_str(), OCGetServerInstanceIDString(), - accessToken.c_str(), handleLoginoutCB); + accessToken.c_str(), handleLoginoutCB); cout << "OCCloudLogin return " << res << endl; break; case 5: cout << "Token refresh to cloud using the refresh token " << refreshToken << endl; res = OCCloudRefresh(g_host.c_str(), DEFAULT_AUTH_REFRESH, uId.c_str(), - OCGetServerInstanceIDString(), refreshToken.c_str(), handleRegisterCB); + OCGetServerInstanceIDString(), refreshToken.c_str(), handleRegisterCB); cout << "OCCloudRefresh return " << res << endl; break; diff --git a/cloud/stack/src/main/java/org/iotivity/cloud/base/connector/CoapClient.java b/cloud/stack/src/main/java/org/iotivity/cloud/base/connector/CoapClient.java index 369e268..d98b531 100644 --- a/cloud/stack/src/main/java/org/iotivity/cloud/base/connector/CoapClient.java +++ b/cloud/stack/src/main/java/org/iotivity/cloud/base/connector/CoapClient.java @@ -131,16 +131,17 @@ public class CoapClient implements IRequestChannel, IResponseEventHandler { } // Subscription response should stored - if (reqInfo.observe != Observe.SUBSCRIBE) { + if (reqInfo.observe != Observe.SUBSCRIBE + || coapResponse.getSequenceNumber() == -1) { mTokenExchanger.remove(Bytes.bytesToLong(coapResponse.getToken())); - if (reqInfo.observe == Observe.UNSUBSCRIBE && mSubscription + if (mSubscription .containsKey(Bytes.bytesToLong(reqInfo.originToken))) { mSubscription.remove(Bytes.bytesToLong(reqInfo.originToken)); } } coapResponse.setToken(reqInfo.originToken); - reqInfo.responseHandler.onResponseReceived(response); + reqInfo.responseHandler.onResponseReceived(coapResponse); } private void addObserve(long token, long newtoken) { diff --git a/cloud/stack/src/main/java/org/iotivity/cloud/base/device/CoapDevice.java b/cloud/stack/src/main/java/org/iotivity/cloud/base/device/CoapDevice.java index 196ecca..7ab584e 100644 --- a/cloud/stack/src/main/java/org/iotivity/cloud/base/device/CoapDevice.java +++ b/cloud/stack/src/main/java/org/iotivity/cloud/base/device/CoapDevice.java @@ -142,14 +142,14 @@ public class CoapDevice extends Device { @Override public void sendResponse(IResponse response) { // This message must converted to CoapResponse - CoapResponse coapResp = (CoapResponse) response; + CoapResponse coapResponse = (CoapResponse) response; Iterator iterator = mObserveRequestList.keySet().iterator(); while (iterator.hasNext()) { Long token = iterator.next(); - Long respToken = Bytes.bytesToLong(coapResp.getToken()); + Long respToken = Bytes.bytesToLong(coapResponse.getToken()); if (respToken.equals(token) - && coapResp.getObserve().equals(Observe.UNSUBSCRIBE)) { + && coapResponse.getSequenceNumber() == -1) { iterator.remove(); } }