IOT-3143 63/26763/2
authorOndrej Tomcik <ondrej.tomcik@kistler.com>
Tue, 20 Feb 2018 16:30:28 +0000 (17:30 +0100)
committerPeter Rafaj <peter.rafaj@kistler.com>
Mon, 13 Aug 2018 10:18:22 +0000 (12:18 +0200)
Change-Id: I14790c66e51b3f7ef955085a91db525d6107460b
Signed-off-by: Peter Rafaj <peter.rafaj@kistler.com>
14 files changed:
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/MongoDB.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/Acl.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/id/AclManager.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/acl/verify/AclVerifyResource.java
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/DeviceServerSystem.java
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/account/AccountSession.java
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/rd/ResourceDirectory.java
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/DBManager.java
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/MongoDB.java
cloud/stack/src/main/java/org/iotivity/cloud/base/ServerSystem.java
cloud/stack/src/main/java/org/iotivity/cloud/base/connector/CoapConnector.java
cloud/stack/src/main/java/org/iotivity/cloud/base/connector/ConnectorPool.java
cloud/stack/src/main/java/org/iotivity/cloud/base/exception/ServerException.java
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/enums/ResponseStatus.java

index f54dca9..d91a19b 100644 (file)
@@ -61,7 +61,6 @@ public class MongoDB {
      */
     public MongoDB(String host, String dbname) throws Exception {
         mongoClient = new MongoClient(host);
-        mongoClient.dropDatabase(dbname);
         db = mongoClient.getDatabase(dbname);
     }
 
@@ -72,8 +71,23 @@ public class MongoDB {
      *            collection name
      */
     public void createTable(String tableName) {
+        if (!collectionExists(tableName))
+            db.createCollection(tableName);
+    }
+
+    private boolean collectionExists(String tableName ) {
+        return db.listCollectionNames().into(new ArrayList<>()).contains(tableName);
+    }
 
-        db.createCollection(tableName);
+    /**
+     * API for dropping collection
+     *
+     * @param tableName
+     *            collection name
+     */
+    public void dropTable(String tableName) {
+        if (collectionExists(tableName))
+            db.getCollection(tableName).drop();
     }
 
     /**
index 9aa8119..4732d2a 100644 (file)
@@ -78,8 +78,15 @@ public class Acl {
         return (object == null) ? "" : object.toString();
     }
 
+    public static Acl convertMaptoAcl(HashMap<String, Object> aclMap) {
+        return new Acl(
+                valueOf(aclMap.get(Constants.KEYFIELD_ACLID)),
+                valueOf(aclMap.get(Constants.REQ_OWNER_ID)),
+                valueOf(aclMap.get(Constants.KEYFIELD_DI)));
+    }
+
     @SuppressWarnings("unchecked")
-    public static AclTable convertMaptoAclObject(
+    public static AclTable convertMaptoAclTable(
             HashMap<String, Object> aclMap) {
         AclTable aclTable = new AclTable();
         try {
@@ -343,7 +350,7 @@ public class Acl {
 
     private AclTable getAclTable() {
         AclTable getAclTable = new AclTable();
-        getAclTable = convertMaptoAclObject(AccountDBManager.getInstance()
+        getAclTable = convertMaptoAclTable(AccountDBManager.getInstance()
                 .selectRecord(Constants.ACL_TABLE, getCondition()).get(0));
         return getAclTable;
     }
index c5df3ce..62accb5 100644 (file)
@@ -36,7 +36,6 @@ import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
 import org.iotivity.cloud.base.protocols.IRequest;
 
 public class AclManager {
-    public HashMap<String, Acl>          mAcls    = new HashMap<>();
     private TypeCastingManager<AclTable> mTypeAcl = new TypeCastingManager<AclTable>();
 
     public HashMap<String, Object> createAcl(String oid, String di) {
@@ -48,13 +47,15 @@ public class AclManager {
 
         AccountDBManager.getInstance().insertRecord(Constants.ACL_TABLE,
                 mTypeAcl.convertObjectToMap(newAclTable));
-        mAcls.put(aclid, new Acl(aclid));
         responsePayload.put(Constants.REQ_ACL_ID, aclid);
         return responsePayload;
     }
 
     public Acl getAcl(String aclid) {
-        return mAcls.get(aclid);
+        HashMap<String, Object> condition = new HashMap<>();
+        condition.put(Constants.REQ_ACL_ID, aclid);
+        HashMap<String, Object> result = AccountDBManager.getInstance().selectOneRecord(Constants.ACL_TABLE, condition);
+        return Acl.convertMaptoAcl(result);
     }
 
     public HashMap<String, Object> getAclid(String di) {
@@ -68,7 +69,7 @@ public class AclManager {
         {
             for (HashMap<String, Object> element : result) {
                 AclTable getAclTable = new AclTable();
-                getAclTable = Acl.convertMaptoAclObject(element);
+                getAclTable = Acl.convertMaptoAclTable(element);
                 aclid = getAclTable.getAclid();
                 responsePayload.put(Constants.KEYFIELD_ACLID, aclid);
                 return responsePayload;
@@ -82,7 +83,6 @@ public class AclManager {
         condition.put(Constants.REQ_ACL_ID, aclid);
         AccountDBManager.getInstance().deleteRecord(Constants.ACL_TABLE,
             condition);
-        mAcls.remove(aclid);
     }
 
     public List<HashMap<String, Object>> addAclACE(String aclid, List<HashMap<String, Object>> aclist) {
index bc83ef3..5a7a72f 100644 (file)
@@ -116,7 +116,7 @@ public class AclVerifyResource extends Resource {
 
         for (HashMap<String, Object> eachAclMap : aclResult) {
 
-            AclTable aclTable = Acl.convertMaptoAclObject(eachAclMap);
+            AclTable aclTable = Acl.convertMaptoAclTable(eachAclMap);
             if (aclTable.getOid().equals(sid)) {
                 return true;
             }
index b59331a..47995cd 100644 (file)
@@ -217,9 +217,12 @@ public class DeviceServerSystem extends ServerSystem {
                 // This is CoapResponse
                 // Once the response is valid, add this to deviceList
                 CoapResponse response = (CoapResponse) msg;
+                if (!response.getStatus().isSuccess()) {
+                    ctx.writeAndFlush(msg);
+                    return;
+                }
 
                 String urlPath = response.getUriPath();
-
                 if (urlPath == null) {
                     throw new InternalServerErrorException(
                             "request uriPath is null");
@@ -250,10 +253,14 @@ public class DeviceServerSystem extends ServerSystem {
         public void channelActive(ChannelHandlerContext ctx) {
             Device device = ctx.channel().attr(keyDevice).get();
             // Authenticated device connected
-
-            sendDevicePresence(device.getDeviceId(), "on");
+            Log.debug("Device: {} online", device.getDeviceId());
+            try {
+                sendDevicePresence(device.getDeviceId(), "on");
+            } catch (ServerException.ServiceUnavailableException e) {
+                Log.warn(e.getMessage());
+                ctx.close();
+            }
             mDevicePool.addDevice(device);
-
             device.onConnected();
         }
 
@@ -266,13 +273,17 @@ public class DeviceServerSystem extends ServerSystem {
             // same di.
             // So compare actual value, and remove if same.
             if (device != null) {
-                sendDevicePresence(device.getDeviceId(), "off");
-
-                device.onDisconnected();
-
-                mDevicePool.removeDevice(device);
-                ctx.channel().attr(keyDevice).remove();
-
+                Log.debug("Device: {} offline ", device.getDeviceId());
+                try {
+                    sendDevicePresence(device.getDeviceId(), "off");
+                } catch (ServerException.ServiceUnavailableException e) {
+                    Log.warn(e.getMessage());
+                    ctx.close();
+                } finally {
+                    device.onDisconnected();
+                    mDevicePool.removeDevice(device);
+                    ctx.channel().attr(keyDevice).remove();
+                }
             }
         }
 
@@ -328,14 +339,16 @@ public class DeviceServerSystem extends ServerSystem {
                 // Once the response is valid, add this to deviceList
 
                 CoapResponse response = (CoapResponse) msg;
+                if (!response.getStatus().isSuccess()) {
+                    ctx.writeAndFlush(msg);
+                    return;
+                }
 
                 String urlPath = response.getUriPath();
-
                 if (urlPath == null) {
                     throw new InternalServerErrorException(
                             "request uriPath is null");
                 }
-
                 switch (urlPath) {
                     /*
                      * case OICConstants.ACCOUNT_FULL_URI:
index f3d36bb..f4ad6f7 100644 (file)
@@ -68,6 +68,10 @@ public class AccountSession extends Resource {
                     ContentFormat.APPLICATION_CBOR,
                     mCbor.encodingPayloadToCbor(payloadData));
         }
+        if (!ConnectorPool.containConnection("rd")) {
+            // connection is required for proper presence state configuration
+            throw new ServerException.ServiceUnavailableException("Required connection to resource directory is not available");
+        }
         ConnectorPool.getConnection("account").sendRequest(request, srcDevice);
     }
 }
\ No newline at end of file
index 2f066c7..9cdd239 100644 (file)
@@ -40,6 +40,7 @@ import org.iotivity.cloud.base.protocols.enums.RequestMethod;
 import org.iotivity.cloud.base.resource.Resource;
 import org.iotivity.cloud.ciserver.Constants;
 import org.iotivity.cloud.util.Cbor;
+import org.slf4j.LoggerFactory;
 
 /**
  *
@@ -50,6 +51,7 @@ import org.iotivity.cloud.util.Cbor;
 
 public class ResourceDirectory extends Resource {
     private Cbor<HashMap<String, Object>> mCbor     = new Cbor<>();
+    private final static org.slf4j.Logger Log       = LoggerFactory.getLogger(ResourceDirectory.class);
 
     public ResourceDirectory() {
         super(Arrays.asList(Constants.PREFIX_OIC, Constants.RD_URI));
@@ -83,8 +85,9 @@ public class ResourceDirectory extends Resource {
                         query.toString(), ContentFormat.APPLICATION_CBOR,
                         mCbor.encodingPayloadToCbor(requestPayload));
 
+                IRequestChannel resourceDirectoryConnection = ConnectorPool.getConnection("rd");
                 ConnectorPool.getConnection("account").sendRequest(requestToAS,
-                        new AccountReceiveHandler(request, srcDevice));
+                        new AccountReceiveHandler(resourceDirectoryConnection, request, srcDevice));
                 break;
 
             case DELETE:
@@ -98,10 +101,12 @@ public class ResourceDirectory extends Resource {
     }
 
     class AccountReceiveHandler implements IResponseEventHandler {
+        private IRequestChannel resourceDirectoryConnection;
         private Device   mSrcDevice;
         private IRequest mRequest;
 
-        public AccountReceiveHandler(IRequest request, Device srcDevice) {
+        public AccountReceiveHandler(IRequestChannel resourceDirectoryConnection, IRequest request, Device srcDevice) {
+            this.resourceDirectoryConnection = resourceDirectoryConnection;
             mSrcDevice = srcDevice;
             mRequest = request;
         }
@@ -119,7 +124,7 @@ public class ResourceDirectory extends Resource {
                             null, ContentFormat.APPLICATION_CBOR,
                             convertedPayload);
 
-                    ConnectorPool.getConnection("rd").sendRequest(mRequest,
+                    resourceDirectoryConnection.sendRequest(mRequest,
                             new PublishResponseHandler(mSrcDevice));
                     break;
 
index a28f519..1180078 100644 (file)
@@ -82,6 +82,9 @@ public class DBManager {
 
     private void createTables() {
         mMongoDB.createTable(Constants.RD_TABLE);
+
+        // TODO cannot be drop in case of component scaling
+        mMongoDB.dropTable(Constants.PRESENCE_TABLE);
         mMongoDB.createTable(Constants.PRESENCE_TABLE);
     }
 
index f7cc46f..fc14645 100644 (file)
@@ -58,9 +58,7 @@ public class MongoDB {
      * @throws Exception
      */
     public MongoDB(String host, String dbname) throws Exception {
-
         mongoClient = new MongoClient(host);
-        mongoClient.dropDatabase(dbname);
         db = mongoClient.getDatabase(dbname);
     }
 
@@ -71,8 +69,23 @@ public class MongoDB {
      *            collection name
      */
     public void createTable(String tableName) {
+        if (!collectionExists(tableName))
+            db.createCollection(tableName);
+    }
 
-        db.createCollection(tableName);
+    private boolean collectionExists(String tableName ) {
+        return db.listCollectionNames().into(new ArrayList<>()).contains(tableName);
+    }
+
+    /**
+     * API for dropping collection
+     *
+     * @param tableName
+     *            collection name
+     */
+    public void dropTable(String tableName) {
+        if (collectionExists(tableName))
+            db.getCollection(tableName).drop();
     }
 
     /**
index ed1ea16..68caf19 100644 (file)
@@ -98,16 +98,17 @@ public class ServerSystem extends ResourceManager {
                 }
 
             } catch (ServerException e) {
-                ctx.writeAndFlush(MessageBuilder.createResponse(msg,
-                        e.getErrorResponse()));
-                Log.error("[{}] channel error", ctx.channel().id().asLongText().substring(26), e);
+                ctx.writeAndFlush(MessageBuilder.createResponse(msg, e.getErrorResponse()));
+                if (e instanceof ServerException.ServiceUnavailableException)
+                    Log.warn(e.getMessage());
+                else
+                    Log.error("[{}] channel error", ctx.channel().id().asLongText().substring(26), e);
             } catch (ClientException e) {
                 Log.error("[{}] channel error", ctx.channel().id().asLongText().substring(26), e);
             } catch (Throwable t) {
                 Log.error("[{}] channel error", ctx.channel().id().asLongText().substring(26), t);
                 if (msg instanceof CoapRequest) {
-                    ctx.writeAndFlush(MessageBuilder.createResponse(msg,
-                            ResponseStatus.INTERNAL_SERVER_ERROR));
+                    ctx.writeAndFlush(MessageBuilder.createResponse(msg, ResponseStatus.INTERNAL_SERVER_ERROR));
                 }
             }
         }
index 09ebc43..64b76c5 100644 (file)
@@ -43,6 +43,8 @@ import javax.net.ssl.SSLException;
 import java.io.File;
 import java.net.InetSocketAddress;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 public class CoapConnector {
     private final static Logger Log             = LoggerFactory.getLogger(CoapConnector.class);
@@ -152,7 +154,7 @@ public class CoapConnector {
         }
     }
 
-    private static Map<Channel, CoapClient> mChannelMap     = new HashMap<>();
+    private static ConcurrentMap<Channel, CoapClient> mChannelMap     = new ConcurrentHashMap<>();
     Bootstrap                    mBootstrap      = new Bootstrap();
     EventLoopGroup               mConnectorGroup = new NioEventLoopGroup();
     Timer                        mTimer          = new Timer();
@@ -189,6 +191,7 @@ public class CoapConnector {
 
             private void addCloseDetectListener(Channel channel) {
                 channel.closeFuture().addListener((ChannelFutureListener) future -> {
+                    ConnectorPool.removeConnection(connectionName);
                     Log.debug("Connection to " + inetSocketAddress.getHostString() + " was lost. Retrying...");
                     scheduleConnect(connectionName, inetSocketAddress, tlsMode, 5);
                 });
index 84f4eac..bf7047c 100644 (file)
@@ -26,6 +26,7 @@ import java.util.ArrayList;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.iotivity.cloud.base.device.IRequestChannel;
+import org.iotivity.cloud.base.exception.ServerException;
 
 public class ConnectorPool {
 
@@ -43,7 +44,17 @@ public class ConnectorPool {
     }
 
     public static IRequestChannel getConnection(String name) {
-        return mConnection.get(name);
+        if (mConnection.containsKey(name))
+            return mConnection.get(name);
+        throw new ServerException.ServiceUnavailableException("Requested connection to service " + name + " is not available");
+    }
+
+    public static void removeConnection(String name) {
+        mConnection.remove(name);
+    }
+
+    public static boolean containConnection(String name) {
+        return mConnection.containsKey(name);
     }
 
     public static ArrayList<IRequestChannel> getConnectionList() {
index fb33b1e..e7c01f1 100644 (file)
@@ -116,15 +116,15 @@ public class ServerException extends RuntimeException {
         }
     }
 
-    public static class NotImplementedException extends ServerException {
-        private static final long serialVersionUID = 5699911106834702025L;
+    public static class ServiceUnavailableException extends ServerException {
+        private static final long serialVersionUID = -112373218973982719L;
 
-        public NotImplementedException() {
-            super(ResponseStatus.NOT_IMPLEMENTED);
+        public ServiceUnavailableException() {
+            super(ResponseStatus.SERVICE_UNAVAILABLE);
         }
 
-        public NotImplementedException(String msg) {
-            super(ResponseStatus.NOT_IMPLEMENTED, msg);
+        public ServiceUnavailableException(String msg) {
+            super(ResponseStatus.SERVICE_UNAVAILABLE, msg);
         }
     }
 }
index 602c005..38e354f 100644 (file)
@@ -21,6 +21,9 @@
  */
 package org.iotivity.cloud.base.protocols.enums;
 
+import java.util.Arrays;
+import java.util.List;
+
 public enum ResponseStatus {
     // Success 2.xx
     CREATED, DELETED, VALID, CHANGED, CONTENT,
@@ -36,4 +39,10 @@ public enum ResponseStatus {
     INTERNAL_SERVER_ERROR, NOT_IMPLEMENTED, BAD_GATEWAY,
     //
     SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, PROXY_NOT_SUPPORTED;
+
+    private static final List<ResponseStatus> successResponseStatuses = Arrays.asList(ResponseStatus.CREATED, ResponseStatus.DELETED, ResponseStatus.VALID, ResponseStatus.CHANGED, ResponseStatus.CONTENT);
+
+    public boolean isSuccess() {
+        return successResponseStatuses.contains(this);
+    }
 }