Implements OIC/OCF resource models for cloud. 41/9141/15
authorJee Hyeok Kim <jihyeok13.kim@samsung.com>
Mon, 4 Jul 2016 10:46:51 +0000 (19:46 +0900)
committerJee Hyeok Kim <jihyeok13.kim@samsung.com>
Tue, 19 Jul 2016 13:16:31 +0000 (13:16 +0000)
1. Project restructured (API Naming, Callbacks and File location).
2. Add Message Queue implementation (IETF Proposal).
3. OAuth2 authcode, accesstoken, refreshtoken based authentication support.
4. Resource Directory implementation, follows latest OIC Spec.

Change-Id: I036a9d1d54b09dc995f36f8b93029fa149963744
Signed-off-by: Jee Hyeok Kim <jihyeok13.kim@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/9141
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
147 files changed:
cloud/README
cloud/account/.project [deleted file]
cloud/account/Github.jar [new file with mode: 0644]
cloud/account/pom.xml
cloud/account/src/main/java/org/iotivity/cloud/accountserver/AccountServer.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/AccountServerManager.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/Constants.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/AccountDBManager.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/MongoDB.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserDevice.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserSession.java [deleted file]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserToken.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/GitHub.java [deleted file]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/Github.jar [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/OAuthServer.java
cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/OAuthServerFactory.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/AccountResource.java [deleted file]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/AuthResource.java [deleted file]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/ResponseObject.java [deleted file]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountResource.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/device/DeviceResource.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/session/SessionResource.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/tokenrefresh/TokenRefreshResource.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/Token.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenGenerator.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenManager.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenPolicy.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenValidator.java [new file with mode: 0644]
cloud/account/src/main/java/org/iotivity/cloud/accountserver/util/CoapMessageBuilder.java [deleted file]
cloud/account/src/test/java/org/iotivity/cloud/testaccountserver/TestAccountServer.java [deleted file]
cloud/interface/.project [deleted file]
cloud/interface/pom.xml
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/CloudInterfaceServer.java
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/Constants.java
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/DeviceServerSystem.java [new file with mode: 0644]
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/protocols/CoapAuthHandler.java [deleted file]
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/protocols/CoapRelayHandler.java [deleted file]
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/DiResource.java [new file with mode: 0644]
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/KeepAliveResource.java
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/Account.java [new file with mode: 0644]
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/DevicePresence.java [new file with mode: 0644]
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/MessageQueue.java [new file with mode: 0644]
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/ResourceDirectory.java [new file with mode: 0644]
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/ResourceFind.java [new file with mode: 0644]
cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/ResourcePresence.java [new file with mode: 0644]
cloud/interface/src/test/java/org/iotivity/cloud/ciserver/testci/TestCloudInterface.java [deleted file]
cloud/messagequeue/.classpath [new file with mode: 0644]
cloud/messagequeue/.gitignore [new file with mode: 0644]
cloud/messagequeue/pom.xml [new file with mode: 0644]
cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/Constants.java [new file with mode: 0644]
cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/MessageQueueServer.java [new file with mode: 0644]
cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/MessageQueueUtils.java [new file with mode: 0644]
cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaCommonWrapper.java [new file with mode: 0644]
cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaConsumerWrapper.java [new file with mode: 0644]
cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/kafka/KafkaProducerWrapper.java [new file with mode: 0644]
cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/resources/MQBrokerResource.java [new file with mode: 0644]
cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/topic/Topic.java [new file with mode: 0644]
cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/topic/TopicManager.java [new file with mode: 0644]
cloud/resourcedirectory/.project [deleted file]
cloud/resourcedirectory/pom.xml
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/Constants.java
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/MongoDB.java [deleted file]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/ResourceDirectoryServer.java
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/DBManager.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/db/MongoDB.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/LinksPayloadFormat.java [deleted file]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/PublishPayloadFormat.java [deleted file]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/ResourceDirectoryResource.java [deleted file]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/InsManager.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishLinks.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishPayload.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/PublishTags.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/rd/ResourceDirectoryResource.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryLinks.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryPayload.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryResource.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/directory/res/DiscoveryTags.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/ResPresenceManager.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/device/DevicePresenceResource.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/device/DeviceState.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/resource/ResPresencePayload.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/resources/presence/resource/ResPresenceResource.java [new file with mode: 0644]
cloud/resourcedirectory/src/main/java/org/iotivity/cloud/rdserver/util/TypeCastingManager.java [new file with mode: 0644]
cloud/resourcedirectory/src/test/java/org/iotivity/cloud/testrdserver/RDServerTest.java [deleted file]
cloud/stack/.project [deleted file]
cloud/stack/pom.xml
cloud/stack/src/main/java/log4j.properties [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/CoapClient.java [deleted file]
cloud/stack/src/main/java/org/iotivity/cloud/base/CoapServer.java [deleted file]
cloud/stack/src/main/java/org/iotivity/cloud/base/HttpServer.java [deleted file]
cloud/stack/src/main/java/org/iotivity/cloud/base/OCFConstants.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/Resource.java [deleted file]
cloud/stack/src/main/java/org/iotivity/cloud/base/ResourceManager.java [deleted file]
cloud/stack/src/main/java/org/iotivity/cloud/base/ServerSystem.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/SessionManager.java [deleted file]
cloud/stack/src/main/java/org/iotivity/cloud/base/connector/CoapClient.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/connector/CoapConnector.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/connector/ConnectorPool.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/connector/HttpClient.java [moved from cloud/stack/src/main/java/org/iotivity/cloud/base/HttpClient.java with 85% similarity]
cloud/stack/src/main/java/org/iotivity/cloud/base/device/CoapDevice.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/device/Device.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/device/HttpDevice.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/device/IRequestChannel.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/device/IRequestEventHandler.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/device/IResponseEventHandler.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/exception/ClientException.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/exception/ServerException.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/IRequest.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/IResponse.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/Message.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/MessageBuilder.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/coap/CoapDecoder.java
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/coap/CoapEncoder.java
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/coap/CoapLogHandler.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/coap/CoapMessage.java
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/coap/CoapOption.java [moved from cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/coap/enums/CoapOption.java with 65% similarity]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/coap/CoapRequest.java
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/coap/CoapResponse.java
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/coap/enums/CoapMethod.java [deleted file]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/coap/enums/CoapStatus.java [deleted file]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/enums/ContentFormat.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/enums/Observe.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/enums/RequestMethod.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/enums/ResponseStatus.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/http/HttpMessage.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/protocols/proxy/CoapHttpProxyHandler.java [deleted file]
cloud/stack/src/main/java/org/iotivity/cloud/base/resource/Resource.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/resource/ResourceManager.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/resource/URIPathNode.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/server/CoapServer.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/server/HttpServer.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/base/server/Server.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/util/Bytes.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/util/Cbor.java
cloud/stack/src/main/java/org/iotivity/cloud/util/CoapLogHandler.java [deleted file]
cloud/stack/src/main/java/org/iotivity/cloud/util/ErrorLogger.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/util/FileLogger.java [new file with mode: 0644]
cloud/stack/src/main/java/org/iotivity/cloud/util/JSONUtil.java
cloud/stack/src/main/java/org/iotivity/cloud/util/Logger.java
cloud/stack/src/test/java/org/iotivity/cloud/base/CoapClientTest.java [deleted file]
cloud/stack/src/test/java/org/iotivity/cloud/base/CoapServerTest.java [deleted file]
cloud/stack/src/test/java/org/iotivity/cloud/base/ResourceManagerTest.java [deleted file]
cloud/stack/src/test/java/org/iotivity/cloud/base/ResourceTest.java [deleted file]
cloud/stack/src/test/java/org/iotivity/cloud/base/SessionManagerTest.java [deleted file]
cloud/stack/src/test/java/org/iotivity/cloud/base/protocols/coap/CoapRequestTest.java [deleted file]
cloud/stack/src/test/java/org/iotivity/cloud/base/protocols/coap/CoapResponseTest.java [deleted file]
cloud/stack/src/test/java/org/iotivity/cloud/util/UtilTest.java [deleted file]

index 81b45a2..1f2f60b 100644 (file)
@@ -2,11 +2,12 @@ This project contains series of modules for building cloud services.
 
 Modules
 
-1. stack - Java 1.7 based CoAP over TCP implementation.
+1. stack - Java 1.8 based CoAP over TCP implementation.
 2. interface - cloud interface server that accept incoming IoTivity clients connection.
 3. resource_directory - resource directory server that store clients resource models.
 4. account - account server that handle clients credential using OAuth2.
-5. samples - sample IoTivity clients that show how clients working with cloud.
+5. message_queue - message queue server that provides pub/sub feature.
+6. samples - sample IoTivity clients that show how clients working with cloud.
 
 Each cloud modules has README file how to install and run.
 You can run each modules on single computer or PAAS.
@@ -15,4 +16,5 @@ Note. resource_directory should launched before interface and account.
 
 Architecture
 client--------interface_server--------resource_directory_server--------mongo_db
-                      \---------------account_server-------------------mongo_db
\ No newline at end of file
+                      \---------------account_server-------------------mongo_db
+                                         \---------------message_queue_server-------------kafka
\ No newline at end of file
diff --git a/cloud/account/.project b/cloud/account/.project
deleted file mode 100644 (file)
index 336bb80..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-       <name>CloudAccount</name>
-       <comment></comment>
-       <projects>
-       </projects>
-       <buildSpec>
-               <buildCommand>
-                       <name>org.eclipse.jdt.core.javabuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>org.eclipse.m2e.core.maven2Builder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-       </buildSpec>
-       <natures>
-               <nature>org.eclipse.jdt.core.javanature</nature>
-               <nature>org.eclipse.m2e.core.maven2Nature</nature>
-       </natures>
-</projectDescription>
diff --git a/cloud/account/Github.jar b/cloud/account/Github.jar
new file mode 100644 (file)
index 0000000..c7b8f8a
Binary files /dev/null and b/cloud/account/Github.jar differ
index e4d08ab..d066f10 100644 (file)
@@ -6,6 +6,7 @@
   
   <properties>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               <maven.test.skip>true</maven.test.skip>
        </properties>
        
   <dependencies>
                        <artifactId>org.apache.oltu.oauth2.client</artifactId>
                        <version>1.0.1</version>
                </dependency>
+               <dependency>
+                       <groupId>org.apache.oltu.oauth2</groupId>
+                       <artifactId>
+                               org.apache.oltu.oauth2.common
+                       </artifactId>
+                       <version>1.0.1</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.oltu.oauth2</groupId>
+                       <artifactId>
+                               org.apache.oltu.oauth2.authzserver
+                       </artifactId>
+                       <version>1.0.1</version>
+               </dependency>
   </dependencies>
        
   <build>
@@ -38,8 +53,8 @@
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-compiler-plugin</artifactId>
                                <configuration>
-                                       <source>1.7</source>
-                                       <target>1.7</target>
+                                       <source>1.8</source>
+                                       <target>1.8</target>
                                        <encoding>UTF-8</encoding>
                                </configuration>
                        </plugin>
index 5a0e32b..f9c00a9 100644 (file)
@@ -1,33 +1,37 @@
 /*
- *******************************************************************
- *
- * 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.
- *
- *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //******************************************************************
+ * //
+ * // 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.accountserver;
 
 import java.net.InetSocketAddress;
 import java.util.Scanner;
 
-import org.iotivity.cloud.accountserver.resources.AccountResource;
-import org.iotivity.cloud.accountserver.resources.AuthResource;
-import org.iotivity.cloud.base.CoapServer;
-import org.iotivity.cloud.base.ResourceManager;
+import org.iotivity.cloud.accountserver.resources.account.AccountResource;
+import org.iotivity.cloud.accountserver.resources.account.device.DeviceResource;
+import org.iotivity.cloud.accountserver.resources.account.session.SessionResource;
+import org.iotivity.cloud.accountserver.resources.account.tokenrefresh.TokenRefreshResource;
+import org.iotivity.cloud.base.ServerSystem;
+import org.iotivity.cloud.base.server.CoapServer;
+import org.iotivity.cloud.util.ErrorLogger;
+import org.iotivity.cloud.util.FileLogger;
 import org.iotivity.cloud.util.Logger;
 
 /**
@@ -38,28 +42,35 @@ import org.iotivity.cloud.util.Logger;
 public class AccountServer {
 
     public static void main(String[] args) throws Exception {
+        System.setOut(FileLogger.createLoggingProxy(System.out));
 
         System.out.println("-----Account SERVER-----");
 
-        if (args.length != 1) {
-            Logger.e("coap server port required");
+        if (args.length != 2) {
+            Logger.e("coap server port and TLS mode required\n"
+                    + "ex) 5685 0\n");
             return;
         }
 
-        ResourceManager resourceManager = null;
+        ErrorLogger.Init();
+
+        ServerSystem serverSystem = new ServerSystem();
+
+        serverSystem.addResource(new AccountResource());
+
+        serverSystem.addResource(new SessionResource());
 
-        CoapServer coapServer = null;
+        serverSystem.addResource(new TokenRefreshResource());
 
-        coapServer = new CoapServer();
+        // Temporally added
+        serverSystem.addResource(new DeviceResource());
 
-        resourceManager = new ResourceManager();
-        coapServer.addHandler(resourceManager);
+        serverSystem.addServer(new CoapServer(
+                new InetSocketAddress(Integer.parseInt(args[0]))));
 
-        resourceManager.registerResource(new AuthResource());
-        resourceManager.registerResource(new AccountResource());
+        boolean tlsMode = Integer.parseInt(args[1]) == 1;
 
-        coapServer
-                .startServer(new InetSocketAddress(Integer.parseInt(args[0])));
+        serverSystem.startSystem(tlsMode);
 
         Scanner in = new Scanner(System.in, "UTF-8");
 
@@ -71,7 +82,7 @@ public class AccountServer {
 
         System.out.println("Terminating...");
 
-        coapServer.stopServer();
+        serverSystem.stopSystem();
 
         System.out.println("Terminated");
     }
index 5749a7a..2214ebc 100644 (file)
@@ -1,31 +1,32 @@
 /*
- *******************************************************************
- *
- * 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.
- *
- *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //******************************************************************
+ * //
+ * // 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.accountserver;
 
 import java.util.ArrayList;
-import java.util.Random;
 
 import org.iotivity.cloud.accountserver.db.AccountDBManager;
-import org.iotivity.cloud.accountserver.oauth.GitHub;
+import org.iotivity.cloud.accountserver.oauth.OAuthServerFactory;
+import org.iotivity.cloud.accountserver.token.Token;
+import org.iotivity.cloud.accountserver.token.TokenManager;
 import org.iotivity.cloud.util.Logger;
 
 /**
@@ -36,9 +37,11 @@ import org.iotivity.cloud.util.Logger;
  */
 public class AccountServerManager {
 
+    private OAuthServerFactory factory = null;
+
     /**
      * API for requesting user account
-     *
+     * 
      * @param userId
      *            user identifier
      * @param deviceId
@@ -59,63 +62,68 @@ public class AccountServerManager {
     /**
      * API for requesting user account and getting session code for registered
      * user.
-     *
+     * 
      * @param userId
      *            user identifier
      * @return String - session code for registered user
      */
-    public String registerUserAccount(String userId) {
+    public Token registerUserAccount(String userId) {
 
-        String sessionCode = null;
-        sessionCode = generateSessionCode();
+        // String sessionCode = null;
+        // sessionCode = generateSessionCode();
+
+        TokenManager tokenManager = new TokenManager();
+        Token token = tokenManager.generateToken();
 
         // store info to OAuthDBManager
-        AccountDBManager.getInstance().registerUserSessionCode(userId,
-                sessionCode);
+        AccountDBManager.getInstance().registerUserToken(userId,
+                token.getAccessToken(), token.getRefreshToken());
 
-        return sessionCode;
+        // return sessionCode;
+        return token;
     }
 
     /**
      * API for requesting user identifier corresponding with authorization
      * information.
-     *
+     * 
      * @param authCode
      *            authorization code
      * @param authServer
      *            authorization server
      * @return String - user identifier
      */
-    public String requestUserId(String authCode, String authServer) {
+    public String requestUserId(String authCode, String authServer,
+            String authServerUrl, String apiServerUrl) {
 
         String userId = null;
 
-        String accessToken = getAccessToken(authCode, authServer);
-        userId = getUserId(accessToken, authServer);
+        userId = getUserId(authCode, authServer, authServerUrl, apiServerUrl);
 
         return userId;
     }
 
     /**
      * API for requesting user identifier corresponding with session code.
-     *
+     * 
      * @param sessionCode
      *            session code
      * @return String - user identifier
      */
-    public String requestUserId(String sessionCode) {
+    public String requestUserId(String accessToken) {
 
         String userId = null;
 
         // get userId from MongDB
-        userId = AccountDBManager.getInstance().getUserId(sessionCode);
+        userId = AccountDBManager.getInstance()
+                .getUserIdByAccessToken(accessToken);
 
         return userId;
     }
 
     /**
      * API for getting devices corresponding with user identifier.
-     *
+     * 
      * @param userId
      *            user identifier
      * @return ArrayList<String> - list of devices
@@ -130,68 +138,27 @@ public class AccountServerManager {
         return deviceList;
     }
 
-    private String getAccessToken(String authCode, String authServer) {
-
-        String accessToken = null;
-
-        if (authServer.equals(Constants.GITHUB)) {
-
-            GitHub gitHub = new GitHub();
-            accessToken = gitHub.requestAccessToken(authCode);
+    public Boolean loadAuthServer(String authServer) {
+        factory = new OAuthServerFactory();
 
-        } else {
-
-            Logger.e("unsupported auth.server = " + authServer);
-        }
-
-        return accessToken;
+        return factory.create(authServer);
     }
 
-    private String getUserId(String accessToken, String authServer) {
+    private String getUserId(String authCode, String authServer,
+            String authServerUrl, String apiServerUrl) {
 
         String userId = null;
 
-        if (authServer.equals(Constants.GITHUB)) {
-
-            GitHub gitHub = new GitHub();
-            userId = gitHub.requestGetUserInfo(accessToken);
+        String accessToken = factory.requestAccessToken(authCode,
+                authServerUrl);
 
+        if (accessToken == null) {
+            return null;
         } else {
-
-            Logger.e("unsupported auth.server = " + authServer);
+            userId = factory.requestGetUserInfo(accessToken, apiServerUrl);
         }
 
         return userId;
     }
 
-    private String generateSessionCode() {
-
-        StringBuffer sessionCode = new StringBuffer();
-
-        Random random = new Random();
-        int randomNum = random.nextInt(122);
-        char code;
-
-        // generate 16byte key with 0-9, A-Z, a-z
-        for (int k = 0; k < 16; k++) {
-            while (true) {
-                if ((randomNum >= 48 && randomNum <= 57)
-                        || (randomNum >= 65 && randomNum <= 90)
-                        || (randomNum >= 97 && randomNum <= 122)) {
-
-                    code = (char) randomNum;
-                    sessionCode.append(code);
-
-                    randomNum = random.nextInt(122);
-                    break;
-
-                } else {
-
-                    randomNum = random.nextInt(122);
-                }
-            }
-        }
-
-        return sessionCode.toString();
-    }
 }
index c350789..393d4fa 100644 (file)
@@ -1,64 +1,91 @@
 /*
- *******************************************************************
- *
- * 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.
- *
- *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //******************************************************************
+ * //
+ * // 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.accountserver;
 
-public class Constants {
+import org.iotivity.cloud.base.OCFConstants;
+
+public class Constants extends OCFConstants {
 
     // MongoDB
-    public static final String DEVICE_TABLE          = "USER_DEVICE";
-    public static final String SESSION_TABLE         = "USER_SESSION";
-    public static final String DB_NAME               = "ACCOUNTSERVER_DB";
-    public static final String USER_ID               = "userId";
-    public static final String DEVICE_ID             = "deviceId";
-    public static final String SESSION_CODE          = "sessionCode";
-
-    // Resource Uri
-    public static final String AUTH_URI              = "oic/auth";
-    public static final String ACCOUNT_URI           = "oic/account";
-
-    // query parameter
-    public static final String REQ_TYPE              = "reqtype";
-
-    // request type
-    public static final String TYPE_REGISTER         = "register";
-    public static final String TYPE_LOGIN            = "login";
-    public static final String TYPE_PUBLISH          = "publish";
-    public static final String TYPE_FIND             = "find";
-
-    // request payload
-    public static final String REQUEST_AUTH_CODE     = "authcode";
-    public static final String REQUEST_AUTH_SERVER   = "authprovider";
-    public static final String REQUEST_DEVICE_ID     = "deviceid";
-    public static final String REQUEST_USER_ID       = "userid";
-    public static final String REQUEST_SESSION_CODE  = "session";
-
-    // response
-    public static final String RESPONSE_SESSION_CODE = "session";
-    public static final String RESPONSE_USER_ID      = "userid";
-    public static final String RESPONSE_STATE        = "state";
-    public static final String RESPONSE_DEVICES      = "devices";
+
+    public static final String DB_NAME             = "ACCOUNTSERVER_DB";
+
+    public static final String DEVICE_TABLE        = "USER_DEVICE";
+
+    public static final String TOKEN_TABLE         = "USER_TOKEN";
+
+    public static final String KEY_USER_ID         = "userId";
+
+    public static final String KEY_DEVICE_ID       = "deviceId";
+
+    public static final String KEY_ACCESS_TOKEN    = "accesstoken";
+
+    public static final String KEY_REFRESH_TOKEN   = "refreshtoken";
+
+    public static final String KEY_ISSUED_TIME     = "issuedTime";
+
+    // request payload key
+
+    public static final String REQ_DEVICE_ID       = "di";
+
+    public static final String REQ_AUTH_CODE       = "authcode";
+
+    public static final String REQ_AUTH_PROVIDER   = "authprovider";
+
+    public static final String REQ_ACCESS_TOKEN    = "accesstoken";
+
+    public static final String REQ_STATUS          = "status";
+
+    public static final String REQ_REFRESH_TOKEN   = "refreshtoken";
+
+    public static final String REQ_AUTH_OPTIONS    = "options";
+
+    public static final String REQ_AUTH_SERVER_URL = "auth_server_url";
+
+    public static final String REQ_API_SERVER_URL  = "api_server_url";
+
+    // response payload key
+
+    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_DEVICES        = "devices";
+
+    public static final String RESP_USER_ID        = "uid";
 
     // auth servers
-    public static final String GITHUB                = "github";
-    public static final String GOOGLE                = "google";
-    public static final String FACEBOOK              = "facebook";
+
+    public static final String GITHUB              = "Github";
+
+    public static final String SAMSUNG             = "Samsung";
+
+    public static final String KEY_ACCESS_TOKEN_GH = "access_token";
+
+    // etc
+
+    public static final String ERROR_MESSAGE       = "error_message";
 }
index dbb0e20..9f859b6 100644 (file)
@@ -1,23 +1,23 @@
 /*
- *******************************************************************
- *
- * 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.
- *
- *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //******************************************************************
+ * //
+ * // 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.accountserver.db;
 
@@ -42,14 +42,11 @@ public class AccountDBManager {
             mongoDB = new MongoDB(Constants.DB_NAME);
 
             mongoDB.createTable(Constants.DEVICE_TABLE);
-            mongoDB.createTable(Constants.SESSION_TABLE);
-
-            registerAdminAccount();
+            // mongoDB.createTable(Constants.SESSION_TABLE);
+            mongoDB.createTable(Constants.TOKEN_TABLE);
 
         } catch (Exception e) {
-
             e.printStackTrace();
-
         }
     }
 
@@ -58,31 +55,38 @@ public class AccountDBManager {
         return accoutDBManager;
     }
 
-    /**
-     * API for storing session information of authorized user
-     *
-     * @param userId
-     *            user identifier
-     * @param sessionCode
-     *            session code
-     * @return Boolean - true if stored, otherwise false
-     */
-    public Boolean registerUserSessionCode(String userId, String sessionCode) {
-
-        UserSession userSession = new UserSession();
+    public Boolean registerUserToken(String userId, String accessToken,
+            String refreshToken) {
 
-        userSession.setUserId(userId);
-        userSession.setSessionCode(sessionCode);
+        UserToken userToken = new UserToken();
 
-        mongoDB.createResource(userSession);
+        userToken.setUserToken(userId, accessToken, refreshToken);
+        mongoDB.createResource(userToken);
         mongoDB.printResources();
 
         return true;
     }
 
+    public Boolean updateUserToken(String userId, String oldRefreshToken,
+            String newAccessToken, String newRefreshToken) {
+
+        Boolean updateUserToken = false;
+
+        UserToken oldUserToken = new UserToken();
+        oldUserToken.setUserToken(userId, null, oldRefreshToken);
+
+        UserToken newUserToken = new UserToken();
+        newUserToken.setUserToken(userId, newAccessToken, newRefreshToken);
+
+        updateUserToken = mongoDB.updateResource(oldUserToken, newUserToken);
+        mongoDB.printResources();
+
+        return updateUserToken;
+    }
+
     /**
      * API for storing device information of authorized user
-     *
+     * 
      * @param userId
      *            user identifier
      * @param deviceId
@@ -105,47 +109,67 @@ public class AccountDBManager {
     /**
      * API for getting user identifier information corresponding with session
      * code
-     *
+     * 
      * @param userId
      *            identifier of authorized user
      * @param sessionCode
      *            session code
      * @return Boolean - true if stored, otherwise false
      */
-    public String getUserId(String sessionCode) {
+    public String getUserIdByAccessToken(String token) {
+
+        String userId = null;
+
+        userId = mongoDB.getUserIdByAccessToken(token);
+
+        return userId;
+    }
+
+    public String getUserIdByRefreshToken(String token) {
 
         String userId = null;
 
-        userId = mongoDB.getUserId(sessionCode);
+        userId = mongoDB.getUserIdByRefreshToken(token);
 
         return userId;
     }
 
     /**
      * API for getting devices corresponding with user identifier
-     *
+     * 
      * @param userId
      *            user identifier
      * @return ArrayList<String> - list of devices
      */
     public ArrayList<String> getDevices(String userId) {
 
-        ArrayList<String> deviceList = mongoDB.getDevices(userId);
+        ArrayList<String> deviceList = new ArrayList<>();
+
+        deviceList = mongoDB.getDevices(userId);
 
         return deviceList;
     }
 
-    private void registerAdminAccount() {
+    public Boolean hasAccessToken(String token) {
 
-        String adminId = "admin";
-        String adminSessionCode = "00000000";
+        Boolean hasAccessToken = false;
+        hasAccessToken = mongoDB.hasAccessToken(token);
 
-        UserSession userSession = new UserSession();
+        return hasAccessToken;
+    }
 
-        userSession.setUserId(adminId);
-        userSession.setSessionCode(adminSessionCode);
+    public Boolean hasRefreshToken(String token) {
+
+        Boolean hasRefreshToken = false;
+        hasRefreshToken = mongoDB.hasRefreshToken(token);
+
+        return hasRefreshToken;
+    }
+
+    public String getIssuedTime(String accessToken) {
+
+        String issuedTime = mongoDB.getIssuedTime(accessToken);
+        return issuedTime;
 
-        mongoDB.createResource(userSession);
-        mongoDB.printResources();
     }
 }
index 191d17a..b86cc8b 100644 (file)
@@ -1,27 +1,30 @@
 /*
- *******************************************************************
- *
- * 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.
- *
- *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //******************************************************************
+ * //
+ * // 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.accountserver.db;
 
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Date;
 
 import org.bson.Document;
 import org.iotivity.cloud.accountserver.Constants;
@@ -88,23 +91,20 @@ public class MongoDB {
         return db;
     }
 
-    /**
-     * API for storing session information of user
-     * 
-     * @param UserSession
-     *            session information of user
-     */
-    public void createResource(UserSession userSession) {
-
-        Document doc = createDocument(userSession);
+    public void createResource(UserToken userToken) {
+        Document doc = createDocument(userToken);
         MongoCollection<Document> collection = db
-                .getCollection(Constants.SESSION_TABLE);
-
-        if (collection.findOneAndReplace(Filters.and(
-                Filters.eq(Constants.USER_ID, doc.get(Constants.USER_ID)),
-                Filters.eq(Constants.SESSION_CODE, doc.get(Constants.SESSION_CODE))),
+                .getCollection(Constants.TOKEN_TABLE);
+
+        if (collection.findOneAndReplace(
+                Filters.and(
+                        Filters.eq(Constants.KEY_USER_ID,
+                                doc.get(Constants.KEY_USER_ID)),
+                        Filters.eq(Constants.KEY_ACCESS_TOKEN,
+                                doc.get(Constants.KEY_ACCESS_TOKEN)),
+                        Filters.eq(Constants.KEY_REFRESH_TOKEN,
+                                doc.get(Constants.KEY_REFRESH_TOKEN))),
                 doc) == null) {
-
             collection.insertOne(doc);
         }
 
@@ -123,9 +123,13 @@ public class MongoDB {
         MongoCollection<Document> collection = db
                 .getCollection(Constants.DEVICE_TABLE);
 
-        if (collection.findOneAndReplace(Filters.and(
-                Filters.eq(Constants.USER_ID, doc.get(Constants.USER_ID)),
-                Filters.eq(Constants.DEVICE_ID, doc.get(Constants.DEVICE_ID))), doc) == null) {
+        if (collection.findOneAndReplace(
+                Filters.and(
+                        Filters.eq(Constants.KEY_USER_ID,
+                                doc.get(Constants.KEY_USER_ID)),
+                        Filters.eq(Constants.KEY_DEVICE_ID,
+                                doc.get(Constants.KEY_DEVICE_ID))),
+                doc) == null) {
 
             collection.insertOne(doc);
         }
@@ -141,24 +145,54 @@ public class MongoDB {
      *            session code
      * @return String - user identifier
      */
-    public String getUserId(String sessionCode) {
+    public String getUserIdByAccessToken(String token) {
+
+        String userId = null;
+
+        MongoCollection<Document> collection = db
+                .getCollection(Constants.TOKEN_TABLE);
+
+        MongoCursor<Document> cursor = collection
+                .find(Filters.eq(Constants.KEY_ACCESS_TOKEN, token)).iterator();
+
+        try {
+
+            while (cursor.hasNext()) {
+
+                Document doc = cursor.next();
+                UserToken userToken = convertTokenDocToResource(doc);
+
+                userId = userToken.getUserId();
+                break;
+            }
+
+        } finally {
+
+            cursor.close();
+        }
+
+        return userId;
+    }
+
+    public String getUserIdByRefreshToken(String token) {
 
         String userId = null;
 
         MongoCollection<Document> collection = db
-                .getCollection(Constants.SESSION_TABLE);
+                .getCollection(Constants.TOKEN_TABLE);
 
-        MongoCursor<Document> cursor = collection.find(
-                Filters.eq(Constants.SESSION_CODE, sessionCode)).iterator();
+        MongoCursor<Document> cursor = collection
+                .find(Filters.eq(Constants.KEY_REFRESH_TOKEN, token))
+                .iterator();
 
         try {
 
             while (cursor.hasNext()) {
 
                 Document doc = cursor.next();
-                UserSession userSession = convertSessionDocToResource(doc);
+                UserToken userToken = convertTokenDocToResource(doc);
 
-                userId = userSession.getUserId();
+                userId = userToken.getUserId();
                 break;
             }
 
@@ -178,13 +212,13 @@ public class MongoDB {
      */
     public ArrayList<String> getDevices(String userId) {
 
-        ArrayList<String> deviceList = new ArrayList<String>();
+        ArrayList<String> deviceList = new ArrayList<>();
 
         MongoCollection<Document> collection = db
                 .getCollection(Constants.DEVICE_TABLE);
 
-        MongoCursor<Document> cursor = collection.find(
-                Filters.eq(Constants.USER_ID, userId)).iterator();
+        MongoCursor<Document> cursor = collection
+                .find(Filters.eq(Constants.KEY_USER_ID, userId)).iterator();
 
         try {
 
@@ -204,12 +238,108 @@ public class MongoDB {
         return deviceList;
     }
 
+    public Boolean hasAccessToken(String token) {
+
+        Boolean hasAccessToken = false;
+
+        MongoCollection<Document> collection = db
+                .getCollection(Constants.TOKEN_TABLE);
+
+        MongoCursor<Document> cursor = collection
+                .find(Filters.eq(Constants.KEY_ACCESS_TOKEN, token)).iterator();
+
+        if (cursor.hasNext())
+            hasAccessToken = true;
+
+        cursor.close();
+
+        return hasAccessToken;
+    }
+
+    public Boolean hasRefreshToken(String token) {
+
+        Boolean hasRefreshToken = false;
+
+        MongoCollection<Document> collection = db
+                .getCollection(Constants.TOKEN_TABLE);
+
+        MongoCursor<Document> cursor = collection
+                .find(Filters.eq(Constants.KEY_REFRESH_TOKEN, token))
+                .iterator();
+
+        if (cursor.hasNext())
+            hasRefreshToken = true;
+
+        cursor.close();
+
+        return hasRefreshToken;
+    }
+
+    public Boolean updateResource(UserToken oldUserToken,
+            UserToken newUserToken) {
+
+        Boolean updateResource = false;
+        String userId = oldUserToken.getUserId();
+        String oldRefreshToken = oldUserToken.getRefreshToken();
+
+        Document doc = createDocument(newUserToken);
+
+        MongoCollection<Document> collection = db
+                .getCollection(Constants.TOKEN_TABLE);
+
+        // update
+        if (collection.findOneAndReplace(
+                Filters.and(Filters.eq(Constants.KEY_USER_ID, userId), Filters
+                        .eq(Constants.KEY_REFRESH_TOKEN, oldRefreshToken)),
+                doc) != null) {
+
+            // collection.insertOne(doc);
+            updateResource = true;
+
+        } else {
+            Logger.e("UpdateResource failed!");
+        }
+
+        return updateResource;
+    }
+
+    public String getIssuedTime(String accessToken) {
+
+        MongoCollection<Document> collection = db
+                .getCollection(Constants.TOKEN_TABLE);
+
+        MongoCursor<Document> cursor = collection
+                .find(Filters.eq(Constants.KEY_ACCESS_TOKEN, accessToken))
+                .iterator();
+
+        String issuedTime = null;
+
+        try {
+
+            while (cursor.hasNext()) {
+
+                Document doc = cursor.next();
+                UserToken userToken = convertTokenDocToResource(doc);
+
+                issuedTime = userToken.getIssuedTime();
+                break;
+            }
+
+        } finally {
+
+            cursor.close();
+        }
+
+        return issuedTime;
+
+    }
+
     public void printResources() {
 
         ArrayList<UserDevice> dlist = readDeviceResources();
         int size = dlist.size();
-
-        Logger.i("*Table: " + Constants.DEVICE_TABLE);
+        
+        Logger.i("[" + Constants.DEVICE_TABLE + "]Table");
         for (int i = 0; i < size; i++) {
 
             UserDevice item = dlist.get(i);
@@ -218,79 +348,114 @@ public class MongoDB {
                     + item.getDeviceId());
         }
 
-        ArrayList<UserSession> slist = readSessionResources();
-        size = slist.size();
-
-        Logger.i("*Table: " + Constants.SESSION_TABLE);
+        /*
+         * ArrayList<UserSession> slist = readSessionResources(); size =
+         * slist.size();
+         * 
+         * Logger.i("*Table: " + Constants.SESSION_TABLE);
+         * 
+         * for (int i = 0; i < size; i++) {
+         * 
+         * UserSession item = slist.get(i);
+         * 
+         * Logger.i("[" + i + "]" + item.getUserId() + ", " +
+         * item.getSessionCode());
+         * 
+         * }
+         */
+
+        ArrayList<UserToken> tlist = readUserTokenResources();
+        size = tlist.size();
+
+        Logger.i("[" + Constants.TOKEN_TABLE + "]Table");
 
         for (int i = 0; i < size; i++) {
 
-            UserSession item = slist.get(i);
+            UserToken item = tlist.get(i);
 
-            Logger.i("[" + i + "]" + item.getUserId() + ", "
-                    + item.getSessionCode());
+            Logger.i("[" + i + "]" + item.getUserId() + "/"
+                    + item.getAccessToken() + "/" + item.getRefreshToken() + "/"
+                    + item.getIssuedTime());
 
         }
     }
 
-    private Document createDocument(UserSession userSession) {
+    private Document createDocument(UserToken userToken) {
+
+        String userId = userToken.getUserId();
+        String accessToken = userToken.getAccessToken();
+        String refreshToken = userToken.getRefreshToken();
 
-        Document doc = new Document(Constants.USER_ID, userSession.getUserId())
-                .append(Constants.SESSION_CODE, userSession.getSessionCode());
+        DateFormat f = new SimpleDateFormat("yyyyMMddkkmm");
+        Date currentDate = new Date();
+
+        String issuedTime = f.format(currentDate);
+
+        Document doc = new Document(Constants.KEY_USER_ID, userId)
+                .append(Constants.KEY_ACCESS_TOKEN, accessToken)
+                .append(Constants.KEY_REFRESH_TOKEN, refreshToken)
+                .append(Constants.KEY_ISSUED_TIME, issuedTime);
 
         return doc;
     }
 
     private Document createDocument(UserDevice userDevice) {
 
-        Document doc = new Document(Constants.USER_ID, userDevice.getUserId())
-                .append(Constants.DEVICE_ID, userDevice.getDeviceId());
+        Document doc = new Document(Constants.KEY_USER_ID,
+                userDevice.getUserId()).append(Constants.KEY_DEVICE_ID,
+                        userDevice.getDeviceId());
 
         return doc;
     }
 
-    private UserSession convertSessionDocToResource(Document doc) {
+    private UserToken convertTokenDocToResource(Document doc) {
+
+        UserToken userToken = new UserToken();
 
-        UserSession userSession = new UserSession();
+        String userId = doc.getString(Constants.KEY_USER_ID);
+        String accessToken = doc.getString(Constants.KEY_ACCESS_TOKEN);
+        String refreshToken = doc.getString(Constants.KEY_REFRESH_TOKEN);
+        String issuedTime = doc.getString(Constants.KEY_ISSUED_TIME);
 
-        userSession.setUserId(doc.getString(Constants.USER_ID));
-        userSession.setSessionCode(doc.getString(Constants.SESSION_CODE));
+        // Logger.d("issuedTime: " + issuedTime);
+        userToken.setUserToken(userId, accessToken, refreshToken);
+        userToken.setIssuedTime(issuedTime);
 
-        return userSession;
+        return userToken;
     }
 
     private UserDevice convertDeviceDocToResource(Document doc) {
 
         UserDevice userDevice = new UserDevice();
 
-        userDevice.setUserId(doc.getString(Constants.USER_ID));
-        userDevice.setDeviceId(doc.getString(Constants.DEVICE_ID));
+        userDevice.setUserId(doc.getString(Constants.KEY_USER_ID));
+        userDevice.setDeviceId(doc.getString(Constants.KEY_DEVICE_ID));
 
         return userDevice;
     }
 
-    private ArrayList<UserSession> readSessionResources() {
+    private ArrayList<UserToken> readUserTokenResources() {
 
-        ArrayList<UserSession> userSessionList = new ArrayList<UserSession>();
+        ArrayList<UserToken> userTokenList = new ArrayList<>();
 
         MongoCollection<Document> collection = db
-                .getCollection(Constants.SESSION_TABLE);
+                .getCollection(Constants.TOKEN_TABLE);
         MongoCursor<Document> cursor = collection.find().iterator();
 
         while (cursor.hasNext()) {
 
             Document doc = cursor.next();
-            userSessionList.add(convertSessionDocToResource(doc));
+            userTokenList.add(convertTokenDocToResource(doc));
         }
 
         cursor.close();
 
-        return userSessionList;
+        return userTokenList;
     }
 
     private ArrayList<UserDevice> readDeviceResources() {
 
-        ArrayList<UserDevice> userDeviceList = new ArrayList<UserDevice>();
+        ArrayList<UserDevice> userDeviceList = new ArrayList<>();
 
         MongoCollection<Document> collection = db
                 .getCollection(Constants.DEVICE_TABLE);
index f42bc7c..b0cc3c6 100644 (file)
@@ -1,23 +1,23 @@
 /*
- *******************************************************************
- *
- * 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.
- *
- *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //******************************************************************
+ * //
+ * // 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.accountserver.db;
 
@@ -47,4 +47,4 @@ public class UserDevice {
     public String getDeviceId() {
         return this.deviceId;
     }
-}
+}
\ No newline at end of file
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserSession.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserSession.java
deleted file mode 100644 (file)
index 96f6d39..0000000
+++ /dev/null
@@ -1,50 +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.accountserver.db;
-
-/**
- *
- * This class provides a set of APIs storing session information of authorized
- * user.
- *
- */
-public class UserSession {
-
-    private String userId      = null;
-    private String sessionCode = null;
-
-    public void setUserId(String id) {
-        this.userId = id;
-    }
-
-    public void setSessionCode(String code) {
-        this.sessionCode = code;
-    }
-
-    public String getUserId() {
-        return this.userId;
-    }
-
-    public String getSessionCode() {
-        return this.sessionCode;
-    }
-}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserToken.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/db/UserToken.java
new file mode 100644 (file)
index 0000000..ef57486
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.db;
+
+/**
+ *
+ * This class provides a set of APIs storing session information of authorized
+ * user.
+ *
+ */
+public class UserToken {
+
+    private String userId       = null;
+    private String accessToken  = null;
+    private String refreshToken = null;
+    private String issuedTime   = null;
+
+    public void setUserToken(String id, String accessToken,
+            String refreshToken) {
+        this.userId = id;
+        this.accessToken = accessToken;
+        this.refreshToken = refreshToken;
+    }
+
+    public void setUserId(String id) {
+        this.userId = id;
+    }
+
+    public void setToken(String accessToken, String refreshToken) {
+        this.accessToken = accessToken;
+        this.refreshToken = refreshToken;
+    }
+
+    public void setIssuedTime(String time) {
+        this.issuedTime = time;
+    }
+
+    public String getUserId() {
+        return this.userId;
+    }
+
+    public String getAccessToken() {
+        return this.accessToken;
+    }
+
+    public String getRefreshToken() {
+        return this.refreshToken;
+    }
+
+    public String getIssuedTime() {
+        return this.issuedTime;
+    }
+}
\ No newline at end of file
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/GitHub.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/GitHub.java
deleted file mode 100644 (file)
index 8e00566..0000000
+++ /dev/null
@@ -1,109 +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.accountserver.oauth;
-
-import org.apache.oltu.oauth2.client.OAuthClient;
-import org.apache.oltu.oauth2.client.URLConnectionClient;
-import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
-import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
-import org.apache.oltu.oauth2.client.response.GitHubTokenResponse;
-import org.apache.oltu.oauth2.client.response.OAuthResourceResponse;
-import org.apache.oltu.oauth2.common.OAuth;
-import org.apache.oltu.oauth2.common.OAuthProviderType;
-import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
-import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
-import org.apache.oltu.oauth2.common.message.types.GrantType;
-import org.iotivity.cloud.util.JSONUtil;
-import org.iotivity.cloud.util.Logger;
-
-/**
- *
- * This class provides APIs relating authorization for GitHub.
- *
- */
-public class GitHub extends OAuthServer {
-
-    final static private String client_id    = "ea9c18f540323b0213d0";
-    final static private String secret       = "4bc0cd9fe21269507eb8eba3a32664a0f598dbc9";
-    final static private String resource_url = "https://api.github.com/user";
-
-    @Override
-    public String requestAccessToken(String authCode) {
-
-        String accessToken = null;
-
-        try {
-
-            OAuthClientRequest request = OAuthClientRequest
-                    .tokenProvider(OAuthProviderType.GITHUB)
-                    .setGrantType(GrantType.AUTHORIZATION_CODE)
-                    .setClientId(client_id).setClientSecret(secret)
-                    .setCode(authCode).buildBodyMessage();
-
-            OAuthClient oAuthClient = new OAuthClient(
-                    new URLConnectionClient());
-            GitHubTokenResponse oAuthResponse = oAuthClient.accessToken(request,
-                    GitHubTokenResponse.class);
-
-            accessToken = oAuthResponse.getAccessToken();
-
-        } catch (OAuthSystemException | OAuthProblemException e) {
-            e.printStackTrace();
-        }
-
-        return accessToken;
-    }
-
-    @Override
-    public String requestGetUserInfo(String accessToken) {
-
-        String userInfo = null;
-
-        if (accessToken == null) {
-            Logger.w("accessToken is null!");
-            return null;
-        }
-
-        try {
-
-            OAuthClientRequest request = new OAuthBearerClientRequest(
-                    resource_url).setAccessToken(accessToken)
-                    .buildQueryMessage();
-
-            OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
-            
-            OAuthResourceResponse resourceResponse = oAuthClient.resource(
-                    request, OAuth.HttpMethod.GET, OAuthResourceResponse.class);
-
-            userInfo = resourceResponse.getBody();
-            Logger.d("userInfo: " + userInfo);
-
-        } catch (OAuthSystemException | OAuthProblemException e) {
-            e.printStackTrace();
-        }
-
-        String userIdKey = "login";
-        String userId = JSONUtil.parseJSON(userInfo, userIdKey);
-
-        return userId;
-    }
-}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/Github.jar b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/Github.jar
new file mode 100644 (file)
index 0000000..c7b8f8a
Binary files /dev/null and b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/Github.jar differ
index c3c6cc7..3a946ce 100644 (file)
@@ -1,48 +1,56 @@
 /*
- *******************************************************************
- *
- * 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.
- *
- *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //******************************************************************
+ * //
+ * // 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.accountserver.oauth;
 
+import java.util.HashMap;
+
 /**
  *
  * This class provides abstraction of APIs relating authorization for OAuth 2.0
  *
  */
-public abstract class OAuthServer {
+public abstract interface OAuthServer {
 
     /**
      * API for requesting access token
      * 
      * @param authCode
      *            authorization code
-     * @return access token
+     * @param authServerUrl
+     *            authorization server url
+     * @return access token and error message if error occur
      */
-    public abstract String requestAccessToken(String authCode);
+    public abstract HashMap<String, String> requestAccessToken(String authCode,
+            String authServerUrl);
 
     /**
      * API for getting user's information
      * 
      * @param accessToken
      *            access token
-     * @return String - user information of json type
+     * @param apiServerUrl
+     *            api server url
+     * @return access token and error message if error occur
      */
-    public abstract String requestGetUserInfo(String accessToken);
+    public abstract HashMap<String, String> requestGetUserInfo(
+            String accessToken, String apiServerUrl);
 }
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/OAuthServerFactory.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/oauth/OAuthServerFactory.java
new file mode 100644 (file)
index 0000000..4f4977b
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.oauth;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.util.Logger;
+
+/**
+ *
+ * This class provides factory method for OAuth2.0 Servers.
+ *
+ */
+public class OAuthServerFactory {
+
+    private Class<?> authServerClass = null;
+    private Object   authServerObj   = null;
+
+    @SuppressWarnings("unchecked")
+    public String requestAccessToken(String authCode, String authServerUrl) {
+        String accessToken = null;
+        HashMap<String, String> authServerInfo = null;
+
+        try {
+            Method method = authServerClass.getMethod("requestAccessToken",
+                    new Class[] { String.class, String.class });
+            authServerInfo = (HashMap<String, String>) method
+                    .invoke(authServerObj, authCode, authServerUrl);
+            String errorMessage = authServerInfo.get(Constants.ERROR_MESSAGE);
+            if (errorMessage != null) {
+                Logger.d("Exception Error Message from Auth Server : "
+                        + errorMessage);
+            } else {
+                accessToken = authServerInfo.get(Constants.KEY_ACCESS_TOKEN_GH);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return accessToken;
+    }
+
+    @SuppressWarnings("unchecked")
+    public String requestGetUserInfo(String accessToken, String apiServerUrl) {
+        String userId = null;
+        HashMap<String, String> authServerInfo = null;
+
+        try {
+            Method method = authServerClass.getMethod("requestGetUserInfo",
+                    new Class[] { String.class, String.class });
+            authServerInfo = (HashMap<String, String>) method
+                    .invoke(authServerObj, accessToken, apiServerUrl);
+            String errorMessage = authServerInfo.get(Constants.ERROR_MESSAGE);
+            if (errorMessage != null) {
+                Logger.d("Exception Error Message from Auth Server : "
+                        + errorMessage);
+            } else {
+                userId = authServerInfo.get(Constants.KEY_USER_ID);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return userId;
+    }
+
+    /**
+     * API for creating OAuth server object
+     * 
+     * @param authServer
+     *            authorization server
+     * @return OAuthServer - object to handle authorization
+     * @throws Exception
+     */
+    public boolean create(String authServer) {
+
+        // TODO : 3rd-party provider check logic required
+        String authServerName = checkAuthServerName(authServer);
+        String fileName = authServerName + ".jar";
+        File jarFile = new File(fileName);
+        URLClassLoader classLoader = null;
+
+        try {
+            URL urls = new URL("jar:" + jarFile.toURI() + "!/");
+
+            Logger.d("urls: " + urls.toString());
+
+            classLoader = new URLClassLoader(new URL[] { urls });
+            Class<?> gitHubClass = classLoader
+                    .loadClass(this.getClass().getPackage().getName() + "."
+                            + authServerName);
+
+            authServerClass = gitHubClass;
+            Object object = gitHubClass.newInstance();
+            authServerObj = object;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+
+        } finally {
+            try {
+                classLoader.close();
+            } catch (IOException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+
+        return true;
+    }
+
+    private String checkAuthServerName(String authServer) {
+
+        String authServerName = null;
+
+        if (authServer.equalsIgnoreCase(Constants.GITHUB)) {
+            authServerName = Constants.GITHUB;
+        } else if (authServer.equalsIgnoreCase(Constants.SAMSUNG)) {
+            authServerName = Constants.SAMSUNG;
+        }
+
+        return authServerName;
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/AccountResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/AccountResource.java
deleted file mode 100644 (file)
index 72f9226..0000000
+++ /dev/null
@@ -1,253 +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.accountserver.resources;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import org.iotivity.cloud.accountserver.AccountServerManager;
-import org.iotivity.cloud.accountserver.Constants;
-import org.iotivity.cloud.accountserver.util.CoapMessageBuilder;
-import org.iotivity.cloud.base.Resource;
-import org.iotivity.cloud.base.protocols.coap.CoapRequest;
-import org.iotivity.cloud.base.protocols.coap.CoapResponse;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
-import org.iotivity.cloud.util.JSONUtil;
-import org.iotivity.cloud.util.Logger;
-
-import io.netty.channel.ChannelHandlerContext;
-
-/**
- *
- * This class provides a set of APIs to manage resources corresponding with user
- * account
- *
- */
-public class AccountResource extends Resource {
-
-    public AccountResource() {
-        setUri(Constants.ACCOUNT_URI);
-    }
-
-    @Override
-    public void onRequestReceived(ChannelHandlerContext ctx,
-            CoapRequest request) {
-
-        Logger.d("AccountResource IN");
-
-        if (ctx == null || request == null) {
-            Logger.d("ctx or request msg is null");
-        }
-
-        else {
-            CoapMethod method = request.getRequestMethod();
-
-            switch (method) {
-                case GET:
-                    try {
-                        handleGetRequest(ctx, request);
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                    }
-                    break;
-
-                case POST:
-                    try {
-                        handlePostRequest(ctx, request);
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                    }
-                    break;
-
-                default:
-                    Logger.w("method[" + method + "] is not supported");
-                    break;
-            }
-        }
-    }
-
-    private void handleGetRequest(ChannelHandlerContext ctx,
-            CoapRequest request) throws Exception {
-
-        String reqType = extractQuery(request, Constants.REQ_TYPE);
-
-        if (reqType == null)
-            throw new IllegalArgumentException(
-                    "request type is null in query!");
-
-        CoapResponse response = null;
-
-        switch (reqType) {
-            case Constants.TYPE_FIND:
-                response = handleFindRequest(request);
-                break;
-            default:
-                Logger.w("reqType[" + reqType + "] is not supported");
-        }
-        if (response != null) {
-            ctx.writeAndFlush(response);
-        }
-
-    }
-
-    private void handlePostRequest(ChannelHandlerContext ctx,
-            CoapRequest request) throws Exception {
-
-        String reqType = extractQuery(request, Constants.REQ_TYPE);
-
-        if (reqType == null)
-            throw new IllegalArgumentException(
-                    "request type is null in query!");
-
-        CoapResponse response;
-
-        switch (reqType) {
-            case Constants.TYPE_PUBLISH:
-                response = handlePublishRequest(request);
-                break;
-            default:
-                throw new IllegalArgumentException(
-                        "request type is not supported");
-        }
-
-        ctx.writeAndFlush(response);
-    }
-
-    /**
-     * API for handling request for publishing resource corresponding with user
-     * account
-     *
-     * @param requeset
-     *            CoAP request message
-     * @return CoapResponse - CoAP response message with response result
-     *         information
-     */
-    private CoapResponse handlePublishRequest(CoapRequest request) {
-
-        String payload = request.getPayloadString();
-
-        String userId = JSONUtil.parseJSON(payload, Constants.REQUEST_USER_ID);
-        String deviceId = JSONUtil.parseJSON(payload,
-                Constants.REQUEST_DEVICE_ID);
-
-        Logger.d("userId: " + userId + ", deviceId: " + deviceId);
-
-        AccountServerManager oauthServerManager = new AccountServerManager();
-        Boolean status = oauthServerManager.registerUserAccount(userId,
-                deviceId);
-
-        Logger.d("status : " + status);
-
-        CoapMessageBuilder responseMessage = new CoapMessageBuilder();
-        CoapResponse coapResponse;
-
-        if (status) {
-            coapResponse = responseMessage.buildCoapResponse(request.getToken(),
-                    CoapStatus.CREATED);
-        } else {
-            coapResponse = responseMessage.buildCoapResponse(request.getToken(),
-                    CoapStatus.INTERNAL_SERVER_ERROR);
-        }
-
-        return coapResponse;
-    }
-
-    /**
-     * API for handling request for finding resource corresponding with user
-     * account
-     *
-     * @param requeset
-     *            CoAP request message
-     * @return CoapResponse - CoAP response message with response result
-     *         information
-     */
-    private CoapResponse handleFindRequest(CoapRequest request) {
-
-        String payload = request.getPayloadString();
-        // String payload = getPayloadString(request.getPayload());
-
-        JSONUtil util = new JSONUtil();
-        String userId = util.parseJSON(payload, Constants.REQUEST_USER_ID);
-
-        Logger.d("userId: " + userId);
-
-        AccountServerManager oauthServerManager = new AccountServerManager();
-        ArrayList<String> deviceList = oauthServerManager
-                .requestAccountDevices(userId);
-
-        ResponseObject response = new ResponseObject();
-        response.setDeviceList(deviceList);
-
-        String responseJson = convertFindResponseToJson(response);
-        Logger.d("responseJson: " + responseJson);
-
-        CoapMessageBuilder responseMessage = new CoapMessageBuilder();
-        CoapResponse coapResponse = responseMessage.buildCoapResponse(
-                request.getToken(), responseJson, CoapStatus.CONTENT);
-
-        return coapResponse;
-    }
-
-    private String convertFindResponseToJson(ResponseObject response) {
-
-        HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
-
-        ArrayList<String> deviceList = response.getDeviceList();
-        responseMap.put(Constants.RESPONSE_DEVICES, deviceList);
-
-        String responseJson = JSONUtil.writeJSON(responseMap);
-
-        return responseJson;
-    }
-
-    private String extractQuery(CoapRequest request, String key) {
-
-        String value = null;
-
-        List<String> Segments = request.getUriQuerySegments();
-
-        if (Segments != null) {
-            for (String s : Segments) {
-
-                String pair[] = s.split("=");
-
-                if (pair[0].equals(key)) {
-
-                    value = pair[1];
-                }
-            }
-        }
-
-        return value;
-    }
-
-    /*
-     * private static String getPayloadString(byte[] payload) {
-     *
-     * if (payload == null) return "";
-     *
-     * return new String(payload, Charset.forName("UTF-8")); }
-     */
-
-}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/AuthResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/AuthResource.java
deleted file mode 100644 (file)
index 71448e4..0000000
+++ /dev/null
@@ -1,273 +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.accountserver.resources;
-
-import java.util.HashMap;
-import java.util.List;
-
-import org.iotivity.cloud.accountserver.AccountServerManager;
-import org.iotivity.cloud.accountserver.Constants;
-import org.iotivity.cloud.accountserver.util.CoapMessageBuilder;
-import org.iotivity.cloud.base.Resource;
-import org.iotivity.cloud.base.protocols.coap.CoapRequest;
-import org.iotivity.cloud.base.protocols.coap.CoapResponse;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
-import org.iotivity.cloud.util.JSONUtil;
-import org.iotivity.cloud.util.Logger;
-
-import io.netty.channel.ChannelHandlerContext;
-
-/**
- *
- * This class provides a set of APIs to manage user account with authorization
- * process.
- *
- */
-public class AuthResource extends Resource {
-
-    public AuthResource() {
-        setUri(Constants.AUTH_URI);
-    }
-
-    @Override
-    public void onRequestReceived(ChannelHandlerContext ctx,
-            CoapRequest request) {
-
-        Logger.d("AuthResource IN");
-
-        if (ctx == null || request == null) {
-            Logger.d("ctx or request msg is null");
-        }
-
-        else {
-            CoapMethod method = request.getRequestMethod();
-
-            switch (method) {
-                case POST:
-                    try {
-                        handlePostRequest(ctx, request);
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                    }
-                    break;
-
-                default:
-                    Logger.w("method(" + method + ") is not supported");
-                    break;
-            }
-        }
-    }
-
-    private void handlePostRequest(ChannelHandlerContext ctx,
-            CoapRequest request) throws Exception {
-
-        String reqType = extractQuery(request, Constants.REQ_TYPE);
-
-        if (reqType == null)
-            throw new IllegalArgumentException(
-                    "request type is null in query!");
-
-        CoapResponse response;
-
-        switch (reqType) {
-            case Constants.TYPE_REGISTER:
-                response = handleRegisterRequest(request);
-                break;
-            case Constants.TYPE_LOGIN:
-                response = handleLoginRequest(request);
-                break;
-            default:
-                throw new IllegalArgumentException(
-                        "request type is not supported");
-        }
-
-        ctx.writeAndFlush(response);
-    }
-
-    /**
-     * API for handling request for login by user account
-     *
-     * @param request
-     *            CoAP request message
-     * @return CoapResponse - CoAP response message with response result
-     *         information
-     */
-    private CoapResponse handleLoginRequest(CoapRequest request) {
-
-        String payload = request.getPayloadString();
-
-        String sessionCode = JSONUtil.parseJSON(payload,
-                Constants.REQUEST_SESSION_CODE);
-
-        Logger.d("sessionCode: " + sessionCode);
-
-        AccountServerManager oauthServerManager = new AccountServerManager();
-        String userId = oauthServerManager.requestUserId(sessionCode);
-        Logger.d("userId: " + userId);
-
-        CoapMessageBuilder responseMessage = new CoapMessageBuilder();
-        CoapResponse coapResponse;
-
-        if (userId != null) {
-
-            ResponseObject response = new ResponseObject();
-            response.setUserId(userId);
-
-            String responseJson = convertLoginResponseToJson(response);
-            Logger.d("responseJson: " + responseJson);
-
-            coapResponse = responseMessage.buildCoapResponse(request.getToken(),
-                    responseJson, CoapStatus.CREATED);
-
-        } else {
-
-            coapResponse = responseMessage.buildCoapResponse(request.getToken(),
-                    CoapStatus.INTERNAL_SERVER_ERROR);
-
-        }
-
-        return coapResponse;
-    }
-
-    /**
-     * API for handling request for registering user account
-     *
-     * @param request
-     *            CoAP request message
-     * @return CoapResponse - CoAP response message with response result
-     *         information
-     */
-    private CoapResponse handleRegisterRequest(CoapRequest request) {
-
-        String payload = request.getPayloadString();
-
-        String authCode = JSONUtil.parseJSON(payload,
-                Constants.REQUEST_AUTH_CODE);
-        String authServer = JSONUtil.parseJSON(payload,
-                Constants.REQUEST_AUTH_SERVER);
-
-        Logger.d("authCode: " + authCode + ", authServer: " + authServer);
-
-        AccountServerManager oauthServerManager = new AccountServerManager();
-        String userId = null;
-        if (authCode != null && authServer != null) {
-            userId = oauthServerManager.requestUserId(authCode, authServer);
-        }
-        
-        CoapMessageBuilder responseMessage = new CoapMessageBuilder();
-        CoapResponse coapResponse;
-
-        if (userId != null) {
-            
-            String sessionCode = oauthServerManager.registerUserAccount(userId);
-
-            Logger.d("userId: " + userId + ", sessionCode: " + sessionCode);
-
-            if (sessionCode != null) {
-
-                ResponseObject response = new ResponseObject();
-                response.setSessionCode(sessionCode);
-                response.setUserId(userId);
-
-                String responseJson = convertRegisterResponseToJson(response);
-                Logger.d("responseJson: " + responseJson);
-
-                coapResponse = responseMessage.buildCoapResponse(
-                        request.getToken(), responseJson, CoapStatus.CREATED);
-            }
-            else  {
-                coapResponse = responseMessage.buildCoapResponse(request.getToken(),
-                        CoapStatus.UNAUTHORIZED);                
-            }
-
-        } else {
-
-            coapResponse = responseMessage.buildCoapResponse(request.getToken(),
-                    CoapStatus.UNAUTHORIZED);
-        }
-
-        return coapResponse;
-    }
-
-    private String convertRegisterResponseToJson(ResponseObject response) {
-
-        HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
-
-        String sessionCode = response.getSessionCode();
-        String userId = response.getUserId();
-
-        if (userId != null)
-            responseMap.put(Constants.RESPONSE_USER_ID, userId);
-
-        if (sessionCode != null)
-            responseMap.put(Constants.RESPONSE_SESSION_CODE, sessionCode);
-
-        String responseJson = JSONUtil.writeJSON(responseMap);
-
-        return responseJson;
-    }
-
-    private String convertLoginResponseToJson(ResponseObject response) {
-
-        HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
-
-        String userId = response.getUserId();
-
-        if (userId != null)
-            responseMap.put(Constants.RESPONSE_USER_ID, userId);
-
-        String responseJson = JSONUtil.writeJSON(responseMap);
-
-        return responseJson;
-    }
-
-    private String extractQuery(CoapRequest request, String key) {
-
-        String value = null;
-
-        List<String> Segments = request.getUriQuerySegments();
-
-        if (Segments != null) {
-            for (String s : Segments) {
-
-                String pair[] = s.split("=");
-
-                if (pair[0].equals(key)) {
-
-                    value = pair[1];
-                }
-            }
-        }
-
-        return value;
-    }
-
-    /*
-     * private static String getPayloadString(byte[] payload) {
-     *
-     * if (payload == null) return "";
-     *
-     * return new String(payload, Charset.forName("UTF-8")); }
-     */
-
-}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/ResponseObject.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/ResponseObject.java
deleted file mode 100644 (file)
index 4871641..0000000
+++ /dev/null
@@ -1,65 +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.accountserver.resources;
-
-import java.util.ArrayList;
-
-/**
- * 
- * This class provides a set of APIs to manage data for response according to
- * request.
- * 
- */
-public class ResponseObject {
-    // private String channel = null;
-    private String            sessionCode = null;
-    private String            userId      = null;
-    private ArrayList<String> deviceList  = null;
-
-    ResponseObject() {
-        deviceList = new ArrayList<String>();
-    }
-
-    public String getUserId() {
-        return this.userId;
-    }
-
-    public void setUserId(String id) {
-        this.userId = id;
-    }
-
-    public String getSessionCode() {
-        return this.sessionCode;
-    }
-
-    public void setSessionCode(String code) {
-        this.sessionCode = code;
-    }
-
-    public void setDeviceList(ArrayList<String> list) {
-        this.deviceList = list;
-    }
-
-    public ArrayList<String> getDeviceList() {
-        return this.deviceList;
-    }
-}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/AccountResource.java
new file mode 100644 (file)
index 0000000..88d7846
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.resources.account;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.iotivity.cloud.accountserver.AccountServerManager;
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.token.Token;
+import org.iotivity.cloud.accountserver.token.TokenPolicy;
+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.InternalServerErrorException;
+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.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.util.Cbor;
+import org.iotivity.cloud.util.Logger;
+
+/**
+ *
+ * This class provides a set of APIs to manage resources corresponding with user
+ * account
+ *
+ */
+public class AccountResource extends Resource {
+
+    private Cbor<HashMap<String, Object>> mCbor      = new Cbor<>();
+
+    private AccountServerManager          mAsManager = new AccountServerManager();
+
+    public AccountResource() {
+        super(Arrays.asList(Constants.PREFIX_WELL_KNOWN, Constants.PREFIX_OCF,
+                Constants.ACCOUNT_URI));
+
+        // addQueryHandler(Arrays.asList("if=" + Constants.INTERFACE_DEFAULT),
+        // this::onDefaultInterfaceReceived);
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+
+        IResponse response = null;
+
+        switch (request.getMethod()) {
+
+            case POST:
+                // Used for user sign-up
+                response = handlePostSignUp(request);
+                break;
+
+            default:
+                throw new BadRequestException(
+                        request.getMethod() + " request type is not support");
+        }
+
+        srcDevice.sendResponse(response);
+    }
+
+    private IResponse handlePostSignUp(IRequest request)
+            throws ServerException {
+
+        if (request.getPayload() == null) {
+            throw new BadRequestException("payload is null");
+        }
+
+        HashMap<String, Object> payloadData = mCbor
+                .parsePayloadFromCbor(request.getPayload(), HashMap.class);
+
+        exceptionPayloadCheck(payloadData);
+
+        String deviceId = payloadData.get(Constants.REQ_DEVICE_ID).toString();
+        String authCode = payloadData.get(Constants.REQ_AUTH_CODE).toString();
+        String authProvider = payloadData.get(Constants.REQ_AUTH_PROVIDER)
+                .toString();
+
+        Logger.d("authCode: " + authCode);
+
+        @SuppressWarnings("unchecked")
+        HashMap<String, String> options = (HashMap<String, String>) payloadData
+                .get(Constants.REQ_AUTH_OPTIONS);
+
+        String authServerUrl = null;
+        String apiServerUrl = null;
+
+        if (options != null) {
+            authServerUrl = (String) options.get(Constants.REQ_AUTH_SERVER_URL);
+            apiServerUrl = (String) options.get(Constants.REQ_API_SERVER_URL);
+        }
+
+        boolean res = false;
+
+        res = mAsManager.loadAuthServer(authProvider);
+
+        if (!res) {
+            throw new InternalServerErrorException(
+                    authProvider + " library is not loaded");
+        }
+
+        String userId = mAsManager.requestUserId(authCode, authProvider,
+                authServerUrl, apiServerUrl);
+
+        if (userId == null) {
+            throw new BadRequestException("authCode is invalid");
+        }
+
+        Token token = new Token();
+        token = mAsManager.registerUserAccount(userId);
+
+        String accessToken = token.getAccessToken();
+        String refreshToken = token.getRefreshToken();
+
+        if (accessToken == null || refreshToken == null) {
+            throw new InternalServerErrorException("MongoDB is not operating");
+        }
+
+        HashMap<String, Object> responsePayload = null;
+
+        responsePayload = new HashMap<String, Object>();
+
+        responsePayload.put(Constants.RESP_ACCESS_TOKEN, accessToken);
+        responsePayload.put(Constants.RESP_REFRESH_TOKEN, refreshToken);
+        responsePayload.put(Constants.RESP_TOKEN_TYPE,
+                TokenPolicy.BEARER_TOKEN);
+        responsePayload.put(Constants.RESP_EXPIRES_IN, TokenPolicy.EXPIRES_IN);
+        responsePayload.put(Constants.RESP_USER_ID, userId);
+
+        res = mAsManager.registerUserAccount(userId, deviceId);
+
+        if (!res) {
+            throw new InternalServerErrorException("MongoDB is not operating");
+        }
+
+        return MessageBuilder.createResponse(request, ResponseStatus.CREATED,
+                ContentFormat.APPLICATION_CBOR,
+                mCbor.encodingPayloadToCbor(responsePayload));
+    }
+
+    private void exceptionPayloadCheck(HashMap<String, Object> payloadData)
+            throws ServerException {
+        if (payloadData == null) {
+            throw new BadRequestException("payload is null");
+        }
+
+        // check if mandatory properties exist
+        if (!payloadData.containsKey(Constants.REQ_DEVICE_ID)) {
+            throw new PreconditionFailedException("di property is not include");
+        }
+
+        if (!payloadData.containsKey(Constants.REQ_AUTH_CODE)) {
+            throw new PreconditionFailedException(
+                    "authcode property is not include");
+        }
+
+        if (!payloadData.containsKey(Constants.REQ_AUTH_PROVIDER)) {
+            throw new PreconditionFailedException(
+                    "authprovider property is not include");
+        }
+
+        // check if mandatory properties have null values
+        if (payloadData.get(Constants.REQ_DEVICE_ID) == null) {
+            throw new PreconditionFailedException("di param is null");
+        }
+
+        if (payloadData.get(Constants.REQ_AUTH_CODE) == null) {
+            throw new PreconditionFailedException("authcode param is null");
+        }
+
+        if (payloadData.get(Constants.REQ_AUTH_PROVIDER) == null) {
+            throw new PreconditionFailedException("authprovider param is null");
+        }
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/device/DeviceResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/device/DeviceResource.java
new file mode 100644 (file)
index 0000000..8d5a600
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.resources.account.device;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.iotivity.cloud.accountserver.AccountServerManager;
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.token.TokenManager;
+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.UnAuthorizedException;
+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.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.util.Cbor;
+
+public class DeviceResource extends Resource {
+
+    private Cbor<HashMap<String, Object>> mCbor         = new Cbor<>();
+
+    TokenManager                          mTokenManager = new TokenManager();
+
+    private AccountServerManager          mAsManager    = new AccountServerManager();
+
+    public DeviceResource() {
+        super(Arrays.asList(Constants.PREFIX_WELL_KNOWN, Constants.PREFIX_OCF,
+                Constants.ACCOUNT_URI, Constants.DEVICE_URI));
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+
+        IResponse response = null;
+
+        switch (request.getMethod()) {
+            case GET:
+                // Used for getting devices.
+                response = handleGetDevice(request);
+                break;
+
+            default:
+                throw new BadRequestException(
+                        request.getMethod() + " request type is not support");
+        }
+        srcDevice.sendResponse(response);
+    }
+
+    private IResponse handleGetDevice(IRequest request) throws ServerException {
+
+        String accessToken = request.getUriQueryMap().get("accesstoken").get(0);
+
+        if (accessToken == null) {
+            throw new BadRequestException("AccessToken is empty");
+        }
+
+        Boolean res = false;
+
+        res = mTokenManager.verifyAccessToken(accessToken);
+
+        if (!res) {
+            throw new UnAuthorizedException("AccessToken is unauthorized");
+        }
+
+        String userId = mAsManager.requestUserId(accessToken);
+
+        if (userId == null) {
+            throw new BadRequestException("userid is invalid");
+        }
+
+        ArrayList<String> deviceList = mAsManager.requestAccountDevices(userId);
+
+        if (request.getUriQueryMap().get("di") != null) {
+            String di = request.getUriQueryMap().get("di").get(0);
+            if (deviceList.contains(di)) {
+                return MessageBuilder.createResponse(request,
+                        ResponseStatus.VALID);
+            } else {
+                throw new UnAuthorizedException("di is invalid");
+            }
+        } else {
+            HashMap<String, Object> responsePayload = new HashMap<String, Object>();
+            responsePayload.put(Constants.RESP_DEVICES, deviceList);
+
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.CONTENT, ContentFormat.APPLICATION_CBOR,
+                    mCbor.encodingPayloadToCbor(responsePayload));
+        }
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/session/SessionResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/session/SessionResource.java
new file mode 100644 (file)
index 0000000..e53b664
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.resources.account.session;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.token.TokenManager;
+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.UnAuthorizedException;
+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.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.util.Cbor;
+
+public class SessionResource extends Resource {
+
+    private Cbor<HashMap<String, Object>> mCbor         = new Cbor<>();
+
+    TokenManager                          mTokenManager = new TokenManager();
+
+    public SessionResource() {
+        super(Arrays.asList(Constants.PREFIX_WELL_KNOWN, Constants.PREFIX_OCF,
+                Constants.ACCOUNT_URI, Constants.SESSION_URI));
+
+        // addQueryHandler(Arrays.asList("if=" + Constants.INTERFACE_DEFAULT),
+        // this::onDefaultInterfaceReceived);
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+
+        IResponse response = null;
+
+        switch (request.getMethod()) {
+            case POST:
+                // Used for user sign-in & out
+                response = handlePostSigninout(request);
+                break;
+
+            default:
+                throw new BadRequestException(
+                        request.getMethod() + " request type is not support");
+        }
+
+        srcDevice.sendResponse(response);
+    }
+
+    private IResponse handlePostSigninout(IRequest request)
+            throws ServerException {
+
+        // exception handle before getting payload
+        if (request.getPayload() == null) {
+            throw new BadRequestException("payload is empty");
+        }
+
+        HashMap<String, Object> payloadData = mCbor
+                .parsePayloadFromCbor(request.getPayload(), HashMap.class);
+
+        if (payloadData == null) {
+            throw new BadRequestException("CBOR parsing failed");
+        }
+
+        // String deviceId =
+        // payloadData.get(Constants.REQUEST_DEVICE_ID).toString();
+        String accessToken = payloadData.get(Constants.REQ_ACCESS_TOKEN)
+                .toString();
+        boolean signinRequest = (boolean) payloadData.get(Constants.REQ_STATUS);
+
+        Boolean res = false;
+
+        res = mTokenManager.verifyAccessToken(accessToken);
+
+        if (!res) {
+            throw new UnAuthorizedException("AccessToken is unauthorized");
+        }
+
+        if (!signinRequest) {
+            return MessageBuilder.createResponse(request, ResponseStatus.VALID);
+        }
+
+        HashMap<String, Object> responsePayload = null;
+
+        responsePayload = new HashMap<String, Object>();
+
+        responsePayload.put(Constants.RESP_EXPIRES_IN,
+                mTokenManager.getRemainExpiredTime(accessToken));
+
+        return MessageBuilder.createResponse(request, ResponseStatus.VALID,
+                ContentFormat.APPLICATION_CBOR,
+                mCbor.encodingPayloadToCbor(responsePayload));
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/tokenrefresh/TokenRefreshResource.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/resources/account/tokenrefresh/TokenRefreshResource.java
new file mode 100644 (file)
index 0000000..b573a60
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.resources.account.tokenrefresh;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.iotivity.cloud.accountserver.Constants;
+import org.iotivity.cloud.accountserver.token.Token;
+import org.iotivity.cloud.accountserver.token.TokenManager;
+import org.iotivity.cloud.accountserver.token.TokenPolicy;
+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.InternalServerErrorException;
+import org.iotivity.cloud.base.exception.ServerException.UnAuthorizedException;
+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.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.util.Cbor;
+
+public class TokenRefreshResource extends Resource {
+
+    private Cbor<HashMap<String, Object>> mCbor         = new Cbor<>();
+
+    TokenManager                          mTokenManager = new TokenManager();
+
+    public TokenRefreshResource() {
+        super(Arrays.asList(Constants.PREFIX_WELL_KNOWN, Constants.PREFIX_OCF,
+                Constants.ACCOUNT_URI, Constants.TOKEN_REFRESH_URI));
+
+        // addQueryHandler(Arrays.asList("if=" + Constants.INTERFACE_DEFAULT),
+        // this::onDefaultInterfaceReceived);
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+
+        IResponse response = null;
+
+        switch (request.getMethod()) {
+            case POST:
+                // Used for token refresh
+                response = handlePostRefreshToken(request);
+                break;
+
+            default:
+                throw new BadRequestException(
+                        request.getMethod() + " request type is not support");
+        }
+
+        srcDevice.sendResponse(response);
+    }
+
+    private IResponse handlePostRefreshToken(IRequest request)
+            throws ServerException {
+
+        HashMap<String, Object> payloadData = mCbor
+                .parsePayloadFromCbor(request.getPayload(), HashMap.class);
+
+        if (payloadData == null) {
+            throw new BadRequestException("payload is null");
+        }
+
+        // String deviceId =
+        // payloadData.get(Constants.REQUEST_DEVICE_ID).toString();
+        String refreshToken = payloadData.get(Constants.REQ_REFRESH_TOKEN)
+                .toString();
+
+        Boolean res = false;
+
+        res = mTokenManager.verifyRefreshToken(refreshToken);
+
+        if (!res) {
+            throw new UnAuthorizedException("RefreshToken is unauthorized");
+        }
+
+        Token refreshedToken = mTokenManager.refreshToken(refreshToken);
+
+        if (refreshedToken.getAccessToken() == null
+                || refreshedToken.getRefreshToken() == null) {
+            throw new InternalServerErrorException("MongoDB is not operating");
+        }
+
+        HashMap<String, Object> responsePayload = null;
+
+        responsePayload = new HashMap<String, Object>();
+
+        responsePayload.put(Constants.RESP_ACCESS_TOKEN,
+                refreshedToken.getAccessToken());
+        responsePayload.put(Constants.RESP_REFRESH_TOKEN,
+                refreshedToken.getRefreshToken());
+        responsePayload.put(Constants.RESP_TOKEN_TYPE,
+                TokenPolicy.BEARER_TOKEN);
+        responsePayload.put(Constants.RESP_EXPIRES_IN, TokenPolicy.EXPIRES_IN);
+
+        return MessageBuilder.createResponse(request, ResponseStatus.CHANGED,
+                ContentFormat.APPLICATION_CBOR,
+                mCbor.encodingPayloadToCbor(responsePayload));
+
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/Token.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/Token.java
new file mode 100644 (file)
index 0000000..b837423
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.token;
+
+public class Token {
+
+    private String accessToken;
+    private String refreshToken;
+
+    public void setToken(String accessToken, String refreshToken) {
+
+        this.accessToken = accessToken;
+        this.refreshToken = refreshToken;
+    }
+
+    public String getAccessToken() {
+
+        return accessToken;
+    }
+
+    public String getRefreshToken() {
+
+        return refreshToken;
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenGenerator.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenGenerator.java
new file mode 100644 (file)
index 0000000..dcea465
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.token;
+
+import org.apache.oltu.oauth2.as.issuer.MD5Generator;
+import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
+import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
+import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
+import org.iotivity.cloud.util.Logger;
+
+public class TokenGenerator {
+
+    String generateAccessToken() {
+
+        OAuthIssuer oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
+
+        String accessToken = null;
+
+        try {
+
+            accessToken = oauthIssuerImpl.accessToken();
+            Logger.d("accessToken : " + accessToken);
+
+        } catch (OAuthSystemException e) {
+
+            e.printStackTrace();
+        }
+
+        return accessToken;
+    }
+
+    String generateRefreshToken() {
+
+        OAuthIssuer oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
+
+        String refreshToken = null;
+
+        try {
+
+            refreshToken = oauthIssuerImpl.refreshToken();
+            Logger.d("refreshToken : " + refreshToken);
+
+        } catch (OAuthSystemException e) {
+
+            e.printStackTrace();
+        }
+
+        return refreshToken;
+    }
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenManager.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenManager.java
new file mode 100644 (file)
index 0000000..3a1676b
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.token;
+
+import org.iotivity.cloud.accountserver.db.AccountDBManager;
+import org.iotivity.cloud.util.Logger;
+
+public class TokenManager {
+
+    private TokenGenerator tokenGenerator;
+    private TokenValidator tokenValidator;
+
+    public TokenManager() {
+        tokenGenerator = new TokenGenerator();
+        tokenValidator = new TokenValidator();
+    }
+
+    public Token generateToken() {
+
+        String accessToken = tokenGenerator.generateAccessToken();
+        String refreshToken = tokenGenerator.generateRefreshToken();
+
+        Token token = new Token();
+        token.setToken(accessToken, refreshToken);
+
+        return token;
+    }
+
+    public Boolean verifyAccessToken(String token) {
+
+        return tokenValidator.verifyAccessToken(token);
+    }
+
+    public Boolean verifyRefreshToken(String token) {
+
+        return tokenValidator.verifyRefreshToken(token);
+    }
+
+    public long getRemainExpiredTime(String token) {
+
+        return tokenValidator.getRemainedSeconds(token);
+    }
+
+    public Token refreshToken(String token) {
+
+        String userId = null;
+
+        Token refreshedToken = new Token();
+
+        Boolean verifyRefreshToken = false;
+        verifyRefreshToken = tokenValidator.verifyRefreshToken(token);
+
+        if (!verifyRefreshToken) {
+            Logger.w("RefreshToken is not existed!");
+            return null;
+        }
+
+        refreshedToken = generateToken();
+
+        userId = AccountDBManager.getInstance().getUserIdByRefreshToken(token);
+
+        AccountDBManager.getInstance().updateUserToken(userId, token,
+                refreshedToken.getAccessToken(),
+                refreshedToken.getRefreshToken());
+
+        return refreshedToken;
+    }
+
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenPolicy.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenPolicy.java
new file mode 100644 (file)
index 0000000..572bf4d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.token;
+
+public class TokenPolicy {
+
+    /* token type */
+    public final static String BEARER_TOKEN = "bearer";
+
+    /* expired time for accessToken */
+    public final static int    EXPIRES_IN = 3600;    // 1hour
+
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenValidator.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/token/TokenValidator.java
new file mode 100644 (file)
index 0000000..fcc12f7
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.accountserver.token;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.iotivity.cloud.accountserver.db.AccountDBManager;
+import org.iotivity.cloud.util.Logger;
+
+public class TokenValidator {
+
+    Boolean verifyAccessToken(String token) {
+
+        Boolean valid = false;
+
+        // check token existed
+        valid = AccountDBManager.getInstance().hasAccessToken(token);
+        if (!valid) {
+            Logger.w("accessToken is not existed..");
+            return false;
+        }
+
+        // check token expired
+        if (getElaspedSeconds(token) > TokenPolicy.EXPIRES_IN) {
+
+            Logger.w("accessToken is expired..");
+            return false;
+        }
+
+        return true;
+    }
+
+    public long getElaspedSeconds(String token) {
+
+        String time = AccountDBManager.getInstance().getIssuedTime(token);
+
+        DateFormat format = new SimpleDateFormat("yyyyMMddkkmm");
+        Date currentTime = new Date();
+        Date issuedTime = null;
+
+        try {
+            issuedTime = format.parse(time);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+
+        long difference = currentTime.getTime() - issuedTime.getTime();
+        long elaspedSeconds = difference / 1000;
+        // Logger.d("currentTime : " + currentTime.getTime());
+        // Logger.d("issuedTime : " + issuedTime.getTime());
+        // Logger.d("difference : " + difference);
+        Logger.d("accessToken elasped time: " + elaspedSeconds + "s");
+
+        return elaspedSeconds;
+    }
+
+    public long getRemainedSeconds(String token) {
+        return TokenPolicy.EXPIRES_IN - getElaspedSeconds(token);
+    }
+
+    Boolean verifyRefreshToken(String token) {
+
+        Boolean valid = false;
+        // check token existed
+        valid = AccountDBManager.getInstance().hasRefreshToken(token);
+        if (!valid)
+            Logger.w("refreshToken is not existed..");
+
+        return valid;
+    }
+
+}
diff --git a/cloud/account/src/main/java/org/iotivity/cloud/accountserver/util/CoapMessageBuilder.java b/cloud/account/src/main/java/org/iotivity/cloud/accountserver/util/CoapMessageBuilder.java
deleted file mode 100644 (file)
index 30029dc..0000000
+++ /dev/null
@@ -1,136 +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.accountserver.util;
-
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-
-import org.iotivity.cloud.base.protocols.coap.CoapRequest;
-import org.iotivity.cloud.base.protocols.coap.CoapResponse;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapOption;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
-
-/**
- * 
- * This class provides a set of APIs to build build data of CoAP request and
- * response type.
- * 
- */
-public class CoapMessageBuilder {
-
-    public static final int APPLICATION_JSON = 50;
-
-    /**
-     * API for building data of CoAP response type without payload.
-     * 
-     * @param token
-     *            token
-     * @param status
-     *            response status
-     * @return CoapResponse - data of CoAP response type
-     */
-    public CoapResponse buildCoapResponse(byte[] token, CoapStatus status) {
-
-        return buildCoapResponse(token, null, status);
-    }
-
-    /**
-     * API for building data of CoAP response type with payload.
-     * 
-     * @param token
-     *            token
-     * @param jsonString
-     *            payload data
-     * @param status
-     *            response status
-     * @return CoapResponse - data of CoAP response type
-     */
-    public CoapResponse buildCoapResponse(byte[] token, String jsonString,
-            CoapStatus status) {
-
-        CoapResponse coapResponse = new CoapResponse(status);
-
-        coapResponse.setToken(token);
-
-        byte[] bytes = ByteBuffer.allocate(4)
-                .putInt(CoapMessageBuilder.APPLICATION_JSON).array();
-        coapResponse.addOption(CoapOption.CONTENT_FORMAT.getvalue(), bytes);
-
-        if (jsonString != null)
-            coapResponse
-                    .setPayload(jsonString.getBytes(StandardCharsets.UTF_8));
-
-        return coapResponse;
-    }
-
-    /**
-     * API for building data of CoAP requeset type with payload.
-     * 
-     * @param token
-     *            token
-     * @param jsonString
-     *            payload data
-     * @return CoapRequest - data of CoAP request type
-     */
-    public CoapRequest buildCoapRequest(byte[] token, String jsonString) {
-
-        CoapRequest coapRequest = new CoapRequest(CoapMethod.GET);
-
-        coapRequest.setToken(token);
-
-        byte[] bytes = ByteBuffer.allocate(4)
-                .putInt(CoapMessageBuilder.APPLICATION_JSON).array();
-        coapRequest.addOption(CoapOption.CONTENT_FORMAT.getvalue(), bytes);
-
-        coapRequest.setPayload(jsonString.getBytes(StandardCharsets.UTF_8));
-
-        return coapRequest;
-    }
-
-    /*
-     * 
-     * public String getJsonAuthServerResponse() {
-     * 
-     * return "{ \"" + OAuthConstant.AUTH_SERVER + "\" : \"" +
-     * OAuthConstant.AUTH_SERVER_GITHUB + "\" }"; }
-     * 
-     * public String getJsonAuthInfoResponse() {
-     * 
-     * return "\n{\n" + " \"" + OAuthConstant.AUTH_ADDRESS + "\" : \"" +
-     * OAuthConstant.GITHUB_ADDRESS + "\",\n" + " \"" +
-     * OAuthConstant.AUTH_RESPONSE_TYPE + "\" : \"" +
-     * OAuthConstant.AUTH_CODE_VALUE + "\",\n" + " \"" +
-     * OAuthConstant.AUTH_CLIENT_ID + "\" : \"" + OAuthConstant.GITHUB_CLIENT_ID
-     * + "\",\n" + " \"" + OAuthConstant.AUTH_REDIRECT_URI + "\" : \"" +
-     * OAuthConstant.GITHUB_REDIRECT_URL + "\"" + "\n}"; }
-     * 
-     * public String getJsonAuthQueryRequest(String auth_server, String
-     * auth_code, String auth_di) {
-     * 
-     * return "\n{\n" + " \"" + OAuthConstant.AUTH_TYPE + "\" : \"" +
-     * OAuthConstant.AUTH_TYPE_QUERY + "\",\n" + " \"" +
-     * OAuthConstant.AUTH_SERVER + "\" : \"" + auth_server + "\",\n" + " \"" +
-     * OAuthConstant.AUTH_CODE + "\" : \"" + auth_code + "\",\n" + " \"" +
-     * OAuthConstant.AUTH_DEVICE_ID + "\" : \"" + auth_di + "\"" + "\n}"; }
-     */
-}
diff --git a/cloud/account/src/test/java/org/iotivity/cloud/testaccountserver/TestAccountServer.java b/cloud/account/src/test/java/org/iotivity/cloud/testaccountserver/TestAccountServer.java
deleted file mode 100644 (file)
index aebada9..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-package org.iotivity.cloud.testaccountserver;
-
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.SimpleChannelInboundHandler;
-
-import java.net.InetSocketAddress;
-import java.nio.charset.StandardCharsets;
-
-import org.junit.Test;
-import org.iotivity.cloud.accountserver.Constants;
-import org.iotivity.cloud.accountserver.resources.AccountResource;
-import org.iotivity.cloud.accountserver.resources.AuthResource;
-import org.iotivity.cloud.base.CoapClient;
-import org.iotivity.cloud.base.CoapServer;
-import org.iotivity.cloud.base.ResourceManager;
-import org.iotivity.cloud.base.protocols.coap.CoapRequest;
-import org.iotivity.cloud.base.protocols.coap.CoapResponse;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
-import org.iotivity.cloud.util.JSONUtil;
-
-public class TestAccountServer {
-
-    private AuthResource    authResource    = new AuthResource();
-    private AccountResource accountResource = new AccountResource();
-
-    private CoapServer      coapServer      = null;
-    private CoapClient      coapClient      = null;
-    private static String   sessionCode     = null;
-
-    static class CoapClientHandler extends
-            SimpleChannelInboundHandler<CoapResponse> {
-
-        ChannelHandlerContext connectCtx = null;
-
-        @Override
-        public void channelActive(ChannelHandlerContext ctx) throws Exception {
-            connectCtx = ctx;
-        }
-
-        @Override
-        protected void channelRead0(ChannelHandlerContext arg0,
-                CoapResponse arg1) throws Exception {
-
-            if (arg1.getTokenString().equals("1111")) {
-
-                String json = arg1.getPayloadString();
-
-                sessionCode = JSONUtil.parseJSON(json, "session");
-            }
-
-        }
-    }
-
-    public void startServer() throws Exception {
-
-        coapServer = new CoapServer();
-
-        ResourceManager resourceManager = new ResourceManager();
-        coapServer.addHandler(resourceManager);
-
-        resourceManager.registerResource(new AuthResource());
-        resourceManager.registerResource(new AccountResource());
-
-        coapServer.startServer(new InetSocketAddress(5685));
-    }
-
-    public ChannelHandlerContext startClient() throws Exception {
-
-        coapClient = new CoapClient();
-
-        CoapClientHandler coapHandler = new CoapClientHandler();
-        coapClient.addHandler(coapHandler);
-
-        coapClient.startClient(new InetSocketAddress("127.0.0.1", 5685));
-
-        return coapHandler.connectCtx;
-    }
-
-    @Test
-    public void testHandleRegisterRequest() throws Exception {
-
-        System.out.println("Write your authCode before test by following url.");
-        System.out
-                .println("https://github.com/login?return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3Dea9c18f540323b0213d0%26redirect_uri%3Dhttp%253A%252F%252Fwww.example.com%252Foauth_callback%252F");
-
-        String authCode = "7243699de9726d05e74c"; // write your authCode here.
-        String authServer = "github";
-
-        String json = "{\"authcode\":\"" + authCode + "\",\"authprovider\":\""
-                + authServer + "\"}";
-
-        CoapRequest request = new CoapRequest(CoapMethod.POST);
-        request.setUriPath(Constants.AUTH_URI);
-        request.setUriQuery("reqtype=register");
-        request.setToken("1111".getBytes(StandardCharsets.UTF_8));
-        request.setPayload(json.getBytes(StandardCharsets.UTF_8));
-
-        startServer();
-        ChannelHandlerContext ctx = startClient();
-        authResource.onRequestReceived(ctx, request);
-
-        coapClient.stopClient();
-        coapServer.stopServer();
-    }
-
-    @Test
-    public void testHandlerLoginReqeust() throws Exception {
-
-        String json = "{\"session\":\"" + sessionCode + "\"}";
-
-        CoapRequest request = new CoapRequest(CoapMethod.POST);
-        request.setUriPath(Constants.AUTH_URI);
-        request.setUriQuery("reqtype=login");
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-        request.setPayload(json.getBytes(StandardCharsets.UTF_8));
-
-        startServer();
-        ChannelHandlerContext ctx = startClient();
-        authResource.onRequestReceived(ctx, request);
-
-        coapClient.sendRequest(request);
-
-        coapClient.stopClient();
-        coapServer.stopServer();
-    }
-
-    @Test
-    public void testHandlerPublishReqeust() throws Exception {
-
-        String userId = "eyedglen";
-        String deviceId = "d0001";
-        String json = "{\"userid\":\"" + userId + "\",\"deviceId\":\""
-                + deviceId + "\"}";
-
-        CoapRequest request = new CoapRequest(CoapMethod.POST);
-        request.setUriPath(Constants.ACCOUNT_URI);
-        request.setUriQuery("reqtype=publish");
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-        request.setPayload(json.getBytes(StandardCharsets.UTF_8));
-
-        startServer();
-        ChannelHandlerContext ctx = startClient();
-        accountResource.onRequestReceived(ctx, request);
-
-        coapClient.stopClient();
-        coapServer.stopServer();
-    }
-
-    @Test
-    public void testHandlerFindReqeust() throws Exception {
-
-        String userId = "eyedglen";
-        String json = "{\"userid\":\"" + userId + "\"}";
-
-        CoapRequest request = new CoapRequest(CoapMethod.GET);
-        request.setUriPath(Constants.ACCOUNT_URI);
-        request.setUriQuery("reqtype=find");
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-        request.setPayload(json.getBytes(StandardCharsets.UTF_8));
-
-        startServer();
-        ChannelHandlerContext ctx = startClient();
-        accountResource.onRequestReceived(ctx, request);
-
-        coapClient.stopClient();
-        coapServer.stopServer();
-    }
-}
diff --git a/cloud/interface/.project b/cloud/interface/.project
deleted file mode 100644 (file)
index 92dcbdb..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-       <name>CloudInterface</name>
-       <comment></comment>
-       <projects>
-       </projects>
-       <buildSpec>
-               <buildCommand>
-                       <name>org.eclipse.jdt.core.javabuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>org.eclipse.m2e.core.maven2Builder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-       </buildSpec>
-       <natures>
-               <nature>org.eclipse.jdt.core.javanature</nature>
-               <nature>org.eclipse.m2e.core.maven2Nature</nature>
-       </natures>
-</projectDescription>
index 3c29dfd..b8528f6 100644 (file)
@@ -1,30 +1,42 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>org.iotivity.cloud</groupId>
-  <artifactId>CloudInterface</artifactId>
-  <version>0.0.1-SNAPSHOT</version>
-  
-  <properties>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <groupId>org.iotivity.cloud</groupId>
+       <artifactId>CloudInterface</artifactId>
+       <version>0.0.1-SNAPSHOT</version>
+
+       <properties>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               <maven.test.skip>true</maven.test.skip>
        </properties>
-       
-  <dependencies>
-               <dependency>
+
+       <dependencies>
+               <dependency>
                        <groupId>org.iotivity.cloud</groupId>
                        <artifactId>CloudStack</artifactId>
                        <version>0.0.1-SNAPSHOT</version>
-               </dependency>   
+               </dependency>
+               <dependency>
+                       <groupId>org.iotivity.cloud</groupId>
+                       <artifactId>CloudResourceDirectory</artifactId>
+                       <version>0.0.1-SNAPSHOT</version>
+               </dependency>
+               <dependency>
+                       <groupId>log4j</groupId>
+                       <artifactId>log4j</artifactId>
+                       <version>1.2.17</version>
+               </dependency>
        </dependencies>
-       
-  <build>
+
+       <build>
                <plugins>
                        <plugin>
                                <inherited>true</inherited>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-compiler-plugin</artifactId>
                                <configuration>
-                                       <source>1.7</source>
-                                       <target>1.7</target>
+                                       <source>1.8</source>
+                                       <target>1.8</target>
                                        <encoding>UTF-8</encoding>
                                </configuration>
                        </plugin>
@@ -60,5 +72,5 @@
                        </plugin>
                </plugins>
        </build>
-  
+
 </project>
\ No newline at end of file
index a165393..cea7878 100644 (file)
 /*
- *******************************************************************
- *
- * 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.
- *
- *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //******************************************************************
+ * //
+ * // 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.ciserver;
 
 import java.net.InetSocketAddress;
 import java.util.Scanner;
 
-import org.iotivity.cloud.base.CoapServer;
-import org.iotivity.cloud.base.ResourceManager;
-import org.iotivity.cloud.base.SessionManager;
-import org.iotivity.cloud.ciserver.protocols.CoapAuthHandler;
-import org.iotivity.cloud.ciserver.protocols.CoapRelayHandler;
+import org.iotivity.cloud.base.connector.ConnectorPool;
+import org.iotivity.cloud.base.server.CoapServer;
+import org.iotivity.cloud.ciserver.DeviceServerSystem.CoapDevicePool;
+import org.iotivity.cloud.ciserver.resources.DiResource;
 import org.iotivity.cloud.ciserver.resources.KeepAliveResource;
-import org.iotivity.cloud.util.CoapLogHandler;
+import org.iotivity.cloud.ciserver.resources.proxy.Account;
+import org.iotivity.cloud.ciserver.resources.proxy.DevicePresence;
+import org.iotivity.cloud.ciserver.resources.proxy.MessageQueue;
+import org.iotivity.cloud.ciserver.resources.proxy.ResourceDirectory;
+import org.iotivity.cloud.ciserver.resources.proxy.ResourceFind;
+import org.iotivity.cloud.ciserver.resources.proxy.ResourcePresence;
+import org.iotivity.cloud.util.ErrorLogger;
+import org.iotivity.cloud.util.FileLogger;
 import org.iotivity.cloud.util.Logger;
 
 public class CloudInterfaceServer {
 
     public static void main(String[] args) throws Exception {
 
+        System.setOut(FileLogger.createLoggingProxy(System.out));
+
         System.out.println("-----CI SERVER-------");
 
-        if (args.length != 5) {
+        if (args.length != 8) {
             Logger.e(
-                    "coap server port and RDServer_Address port AccountServer_Address Port required\n"
-                            + "ex) 5683 127.0.0.1 5684 127.0.0.1 5685\n");
+                    "coap server port and RDServer_Address port AccountServer_Address Port MQBroker_Address Port and TLS mode required\n"
+                            + "ex) 5683 127.0.0.1 5684 127.0.0.1 5685 127.0.0.1 5686 0\n");
             return;
         }
 
-        ResourceManager resourceManager = null;
-        SessionManager sessionManager = null;
-        CoapServer coapServer = null;
+        boolean tlsMode = Integer.parseInt(args[7]) == 1;
 
-        CoapRelayHandler relayHandler = null;
-        CoapAuthHandler authHandler = null;
+        ConnectorPool.addConnection("rd",
+                new InetSocketAddress(args[1], Integer.parseInt(args[2])),
+                tlsMode);
+        ConnectorPool.addConnection("account",
+                new InetSocketAddress(args[3], Integer.parseInt(args[4])),
+                tlsMode);
+        ConnectorPool.addConnection("mq",
+                new InetSocketAddress(args[5], Integer.parseInt(args[6])),
+                tlsMode);
 
-        KeepAliveResource keepAliveResource = null;
+        ErrorLogger.Init();
 
-        coapServer = new CoapServer();
+        DeviceServerSystem deviceServer = new DeviceServerSystem();
 
-        sessionManager = new SessionManager();
+        Account acHandler = new Account();
+        ResourceDirectory rdHandler = new ResourceDirectory();
+        ResourceFind resHandler = new ResourceFind();
+        ResourcePresence adHandler = new ResourcePresence();
+        DevicePresence prsHandler = new DevicePresence();
+        MessageQueue mqHandler = new MessageQueue();
 
-        resourceManager = new ResourceManager();
+        CoapDevicePool devicePool = deviceServer.getDevicePool();
 
-        relayHandler = new CoapRelayHandler(sessionManager);
+        deviceServer.addResource(acHandler);
 
-        authHandler = new CoapAuthHandler();
+        deviceServer.addResource(rdHandler);
 
-        keepAliveResource = new KeepAliveResource(sessionManager,
-                new int[] { 1, 2, 4, 8 });
+        deviceServer.addResource(resHandler);
+
+        deviceServer.addResource(adHandler);
 
-        coapServer.addHandler(new CoapLogHandler());
+        deviceServer.addResource(prsHandler);
 
-        coapServer.addHandler(authHandler);
+        deviceServer.addResource(mqHandler);
 
-        coapServer.addHandler(relayHandler);
+        KeepAliveResource resKeepAlive = new KeepAliveResource(
+                new int[] { 1, 2, 4, 8 });
 
-        coapServer.addHandler(resourceManager);
+        deviceServer.addResource(resKeepAlive);
 
-        resourceManager.registerResource(keepAliveResource);
+        deviceServer.addResource(new DiResource(devicePool));
 
-        authHandler.startHandler(args[3], Integer.parseInt(args[4]));
+        deviceServer.addServer(new CoapServer(
+                new InetSocketAddress(Integer.parseInt(args[0]))));
 
-        relayHandler.startHandler(args[1], Integer.parseInt(args[2]), args[3],
-                Integer.parseInt(args[4]));
+        // deviceServer.addServer(new HttpServer(new InetSocketAddress(8080)));
 
-        coapServer
-                .startServer(new InetSocketAddress(Integer.parseInt(args[0])));
+        deviceServer.startSystem(tlsMode);
 
-        keepAliveResource.startSessionChecker();
+        resKeepAlive.startSessionChecker();
 
-        Scanner in = new Scanner(System.in, "UTF-8");
+        Scanner in = new Scanner(System.in);
 
         System.out.println("press 'q' to terminate");
 
@@ -98,13 +117,9 @@ public class CloudInterfaceServer {
 
         System.out.println("Terminating...");
 
-        keepAliveResource.stopSessionChecker();
-
-        coapServer.stopServer();
-
-        relayHandler.stopHandler();
+        resKeepAlive.stopSessionChecker();
 
-        authHandler.stopHandler();
+        deviceServer.stopSystem();
 
         System.out.println("Terminated");
     }
index 164c9e8..7c3a2cb 100644 (file)
@@ -1,42 +1,37 @@
 /*
- *******************************************************************
- *
- * 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.
- *
- *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //******************************************************************
+ * //
+ * // 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.ciserver;
 
-import io.netty.util.AttributeKey;
+import org.iotivity.cloud.base.OCFConstants;
 
-public class Constants {
-    public static final String RD_URI         = "oic/rd";   // resource
-                                                            // publish uri
-    public static final String KEEP_ALIVE_URI = "oic/ping"; // keepalive
-                                                            // resource uri
-    public static final String WELL_KNOWN_URI = "oic/res";  // resource
-                                                            // discover uri
+public class Constants extends OCFConstants {
 
-    public static final String DEVICE_LIST = "st=didList"; // oauth device
-                                                           // list riquery
+    public static final int    MIN_TO_LIVE          = 10;
 
-    public static final String AUTH_URI    = "oic/auth";
-    public static final String ACCOUNT_URI = "oic/account";
+    public static final String DEVICE_ID            = "di";
+    public static final String PRESENCE_STATE       = "state";
+
+    public static final String SEARCH_ACCESS_TOKEN  = "accesstoken";
+    public static final Object SEARCH_REFRESH_TOKEN = "refreshtoken";
+    public static final Object EXPIRES_IN           = "expiresin";
 
-    public static final AttributeKey<String> Attribute_UserId = AttributeKey
-            .newInstance("userId");
 }
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
new file mode 100644 (file)
index 0000000..82d7ba7
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.ciserver;
+
+import java.util.HashMap;
+
+import org.iotivity.cloud.base.ServerSystem;
+import org.iotivity.cloud.base.connector.ConnectorPool;
+import org.iotivity.cloud.base.device.CoapDevice;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.device.IRequestChannel;
+import org.iotivity.cloud.base.exception.ServerException;
+import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
+import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException;
+import org.iotivity.cloud.base.exception.ServerException.PreconditionFailedException;
+import org.iotivity.cloud.base.exception.ServerException.UnAuthorizedException;
+import org.iotivity.cloud.base.protocols.MessageBuilder;
+import org.iotivity.cloud.base.protocols.coap.CoapRequest;
+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.base.server.CoapServer;
+import org.iotivity.cloud.base.server.HttpServer;
+import org.iotivity.cloud.base.server.Server;
+import org.iotivity.cloud.util.Cbor;
+import org.iotivity.cloud.util.ErrorLogger;
+
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPromise;
+
+public class DeviceServerSystem extends ServerSystem {
+
+    public class CoapDevicePool {
+        HashMap<String, Device> mMapDevice = new HashMap<>();
+
+        public void addDevice(Device device) {
+            String deviceId = ((CoapDevice) device).getDeviceId();
+            synchronized (mMapDevice) {
+                mMapDevice.put(deviceId, device);
+            }
+        }
+
+        public void removeDevice(Device device) {
+            String deviceId = ((CoapDevice) device).getDeviceId();
+            synchronized (mMapDevice) {
+                if (mMapDevice.get(deviceId) == device) {
+                    mMapDevice.remove(deviceId);
+                }
+            }
+        }
+
+        public Device queryDevice(String deviceId) {
+            Device device = null;
+            synchronized (mMapDevice) {
+                device = mMapDevice.get(deviceId);
+            }
+            return device;
+        }
+    }
+
+    CoapDevicePool mDevicePool = new CoapDevicePool();
+
+    @Sharable
+    class CoapLifecycleHandler extends ChannelDuplexHandler {
+        @Override
+        public void channelRead(ChannelHandlerContext ctx, Object msg) {
+
+            if (msg instanceof CoapRequest) {
+                try {
+                    CoapDevice coapDevice = (CoapDevice) ctx.channel()
+                            .attr(keyDevice).get();
+
+                    if (coapDevice.getIssuedTime() != null
+                            && coapDevice.isExpiredTime()) {
+                        throw new UnAuthorizedException("token is expired");
+                    }
+
+                } catch (Throwable t) {
+                    ResponseStatus responseStatus = t instanceof ServerException
+                            ? ((ServerException) t).getErrorResponse()
+                            : ResponseStatus.BAD_REQUEST;
+                    ctx.channel().writeAndFlush(MessageBuilder
+                            .createResponse((CoapRequest) msg, responseStatus));
+                    ErrorLogger.write(ctx.channel(), t);
+                }
+            }
+
+            ctx.fireChannelRead(msg);
+        }
+
+        @Override
+        public void channelActive(ChannelHandlerContext ctx) {
+
+            // Authenticated device connected
+            Device device = ctx.channel().attr(keyDevice).get();
+            mDevicePool.addDevice(device);
+            device.onConnected();
+
+            sendDevicePresence(device.getDeviceId(), "on");
+        }
+
+        @Override
+        public void channelInactive(ChannelHandlerContext ctx) {
+            Device device = ctx.channel().attr(keyDevice).get();
+            // Some cases, this event occurs after new device connected using
+            // same di.
+            // So compare actual value, and remove if same.
+            if (device != null) {
+                mDevicePool.removeDevice(device);
+                device.onDisconnected();
+                ctx.channel().attr(keyDevice).remove();
+
+                sendDevicePresence(device.getDeviceId(), "off");
+            }
+        }
+
+        private void sendDevicePresence(String deviceId, String state) {
+
+            Cbor<HashMap<String, Object>> cbor = new Cbor<>();
+            IRequestChannel RDServer = ConnectorPool.getConnection("rd");
+            HashMap<String, Object> payload = new HashMap<String, Object>();
+            payload.put(Constants.DEVICE_ID, deviceId);
+            payload.put(Constants.PRESENCE_STATE, state);
+            StringBuffer uriPath = new StringBuffer();
+            uriPath.append("/" + Constants.PREFIX_WELL_KNOWN);
+            uriPath.append("/" + Constants.PREFIX_OCF);
+            uriPath.append("/" + Constants.DEVICE_PRESENCE_URI);
+            RDServer.sendRequest(MessageBuilder.createRequest(
+                    RequestMethod.POST, uriPath.toString(), null,
+                    ContentFormat.APPLICATION_CBOR,
+                    cbor.encodingPayloadToCbor(payload)), null);
+        }
+    }
+
+    @Sharable
+    class CoapAuthHandler extends ChannelDuplexHandler {
+        private Cbor<HashMap<String, Object>> mCbor = new Cbor<HashMap<String, Object>>();
+
+        @Override
+        public void channelActive(ChannelHandlerContext ctx) {
+            // Actual channel active should decided after authentication.
+        }
+
+        @Override
+        public void write(ChannelHandlerContext ctx, Object msg,
+                ChannelPromise promise) {
+
+            try {
+                if (!(msg instanceof CoapResponse)) {
+                    throw new BadRequestException(
+                            "this msg type is not CoapResponse");
+                }
+                // This is CoapResponse
+                // Once the response is valid, add this to deviceList
+                CoapResponse response = (CoapResponse) msg;
+
+                switch (response.getStatus()) {
+                    // TODO: below section is exceptional case for ping from
+                    // clients
+                    case CREATED:
+                    case CONTENT:
+                        break;
+
+                    case VALID:
+                        if (response.getPayload() != null) {
+                            HashMap<String, Object> payloadData = mCbor
+                                    .parsePayloadFromCbor(response.getPayload(),
+                                            HashMap.class);
+                            int remainTime = (int) payloadData
+                                    .get(Constants.EXPIRES_IN);
+
+                            Device device = ctx.channel().attr(keyDevice).get();
+                            ((CoapDevice) device).setExpiredPolicy(remainTime);
+
+                            // Remove current auth handler
+                            ctx.channel().pipeline().remove(this);
+
+                            // Raise event that we have Authenticated device
+                            ctx.fireChannelActive();
+                        }
+                        break;
+
+                    default:
+                }
+
+                ctx.writeAndFlush(msg);
+
+            } catch (Throwable t) {
+                ErrorLogger.write(ctx.channel(), t);
+                ctx.writeAndFlush(msg);
+                ctx.close();
+            }
+        }
+
+        @Override
+        public void channelRead(ChannelHandlerContext ctx, Object msg) {
+
+            try {
+                if (!(msg instanceof CoapRequest)) {
+                    throw new BadRequestException(
+                            "this msg type is not CoapRequest");
+                }
+
+                // And check first response is VALID then add or cut
+                CoapRequest request = (CoapRequest) msg;
+                // Check whether first request is about account
+                if (request.getUriPathSegments().size() < 2) {
+                    throw new UnAuthorizedException(
+                            "first request must be about account or keepAlive");
+                }
+
+                // TODO: device sends ping whether not authorized
+                if (request.getUriPathSegments().get(1)
+                        .equals(Constants.KEEP_ALIVE_URI)) {
+                    // Go upperlayer
+                    ctx.fireChannelRead(msg);
+                    return;
+                }
+
+                if (request.getUriPathSegments().size() < 3
+                        || request.getUriPathSegments().get(2)
+                                .equals(Constants.ACCOUNT_URI) == false) {
+                    throw new UnAuthorizedException(
+                            "authentication required first");
+                }
+
+                HashMap<String, Object> authPayload = mCbor
+                        .parsePayloadFromCbor(request.getPayload(),
+                                HashMap.class);
+
+                if (authPayload.containsKey("di") == false) {
+                    throw new PreconditionFailedException(
+                            "di property is not included");
+                }
+
+                CoapDevice device = new CoapDevice(ctx,
+                        (String) authPayload.get("di"),
+                        (String) authPayload.get("accesstoken"));
+
+                // Create device first and pass to upperlayer
+                ctx.channel().attr(keyDevice).set(device);
+
+                ctx.fireChannelRead(msg);
+
+            } catch (Throwable t) {
+                ResponseStatus responseStatus = t instanceof ServerException
+                        ? ((ServerException) t).getErrorResponse()
+                        : ResponseStatus.UNAUTHORIZED;
+                ctx.channel().writeAndFlush(MessageBuilder
+                        .createResponse((CoapRequest) msg, responseStatus));
+                ErrorLogger.write(ctx.channel(), t);
+            }
+        }
+    }
+
+    @Sharable
+    class HttpAuthHandler extends ChannelDuplexHandler {
+        @Override
+        public void channelActive(ChannelHandlerContext ctx) throws Exception {
+            // After current channel authenticated, raise to upper layer
+        }
+    }
+
+    @Override
+    public void addServer(Server server) {
+        if (server instanceof CoapServer) {
+            server.addHandler(new CoapAuthHandler());
+            server.addHandler(new CoapLifecycleHandler());
+        }
+
+        if (server instanceof HttpServer) {
+            server.addHandler(new HttpAuthHandler());
+        }
+
+        super.addServer(server);
+    }
+
+    public CoapDevicePool getDevicePool() {
+        return mDevicePool;
+    }
+}
diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/protocols/CoapAuthHandler.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/protocols/CoapAuthHandler.java
deleted file mode 100644 (file)
index 3e626e3..0000000
+++ /dev/null
@@ -1,153 +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.ciserver.protocols;
-
-import java.net.InetSocketAddress;
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.iotivity.cloud.base.CoapClient;
-import org.iotivity.cloud.base.protocols.coap.CoapRequest;
-import org.iotivity.cloud.base.protocols.coap.CoapResponse;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
-import org.iotivity.cloud.ciserver.Constants;
-import org.iotivity.cloud.util.Cbor;
-import org.iotivity.cloud.util.JSONUtil;
-import org.iotivity.cloud.util.Logger;
-
-import io.netty.channel.ChannelDuplexHandler;
-import io.netty.channel.ChannelHandler.Sharable;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.SimpleChannelInboundHandler;
-import io.netty.util.AttributeKey;
-
-@Sharable
-public class CoapAuthHandler extends ChannelDuplexHandler {
-
-    private static final AttributeKey<ChannelHandlerContext> keyAuthClient = AttributeKey
-            .newInstance("authCtx");
-
-    private class AccountHandler
-            extends SimpleChannelInboundHandler<CoapResponse> {
-
-        @Override
-        public void channelRead0(ChannelHandlerContext ctx, CoapResponse msg)
-                throws Exception {
-            Logger.d("Receive response from account, forward to client");
-
-            ChannelHandlerContext ctxToDevice = ctx.channel()
-                    .attr(keyAuthClient).get();
-
-            if (msg.getResponseCode() == CoapStatus.CREATED) {
-                Map<String, String> response = JSONUtil.parseJSON(
-                        new String(msg.getPayload(), StandardCharsets.UTF_8));
-
-                if (response != null) {
-                    String userId = response.get("userid");
-                    if (userId != null) {
-                        ctxToDevice.channel().attr(Constants.Attribute_UserId)
-                                .set(userId);
-                    }
-                    msg.setPayload(cbor.encodingPayloadToCbor(response));
-
-                    CoapAuthHandler authHandler = ctxToDevice.channel()
-                            .pipeline().get(CoapAuthHandler.class);
-
-                    ctxToDevice.channel().pipeline().remove(authHandler);
-                }
-            }
-
-            ctxToDevice.writeAndFlush(msg);
-
-            if (msg.getResponseCode() != CoapStatus.CREATED)
-                ctxToDevice.close();
-        }
-
-        @Override
-        public void exceptionCaught(ChannelHandlerContext ctx,
-                Throwable cause) {
-            cause.printStackTrace();
-            ctx.close();
-        }
-    }
-
-    private CoapClient asClient = new CoapClient();
-
-    public CoapAuthHandler() {
-
-        asClient.addHandler(new AccountHandler());
-
-    }
-
-    public void startHandler(String acAddress, int acPort) throws Exception {
-        asClient.startClient(new InetSocketAddress(acAddress, acPort));
-    }
-
-    public void stopHandler() throws Exception {
-        asClient.stopClient();
-    }
-
-    private Cbor<HashMap<Object, Object>> cbor = new Cbor<HashMap<Object, Object>>();
-
-    @Override
-    public void channelRead(ChannelHandlerContext ctx, Object msg)
-            throws Exception {
-
-        if (msg instanceof CoapRequest) {
-            CoapRequest request = (CoapRequest) msg;
-            String uriPath = request.getUriPath();
-            if (uriPath != null) {
-                switch (uriPath) {
-                    // This handler only used for initial handshake
-                    case Constants.AUTH_URI:
-                        HashMap<Object, Object> payloadData = cbor
-                                .parsePayloadFromCbor(request.getPayload(),
-                                        HashMap.class);
-                        String writejson = JSONUtil.writeJSON(payloadData);
-                        if (writejson != null) {
-                            request.setPayload(
-                                    writejson.getBytes(StandardCharsets.UTF_8));
-                            asClient.getChannelFuture().channel()
-                                    .attr(keyAuthClient).set(ctx);
-                            asClient.sendRequest(request);
-                        }
-                        return;
-
-                    case Constants.KEEP_ALIVE_URI:
-                        super.channelRead(ctx, msg);
-                        return;
-
-                    default:
-                        CoapResponse response = new CoapResponse(
-                                CoapStatus.UNAUTHORIZED);
-                        Logger.e("Sending UNAUTHORIZED to client");
-                        ctx.writeAndFlush(response);
-                        break;
-                }
-            }
-        }
-
-        Logger.d("Invalid packet for authenticating");
-        ctx.close();
-    }
-}
diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/protocols/CoapRelayHandler.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/protocols/CoapRelayHandler.java
deleted file mode 100644 (file)
index 533811e..0000000
+++ /dev/null
@@ -1,341 +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.ciserver.protocols;
-
-import java.net.InetSocketAddress;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.iotivity.cloud.base.CoapClient;
-import org.iotivity.cloud.base.SessionManager;
-import org.iotivity.cloud.base.protocols.coap.CoapRequest;
-import org.iotivity.cloud.base.protocols.coap.CoapResponse;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
-import org.iotivity.cloud.ciserver.Constants;
-import org.iotivity.cloud.util.Logger;
-
-import io.netty.channel.ChannelDuplexHandler;
-import io.netty.channel.ChannelHandler.Sharable;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.SimpleChannelInboundHandler;
-import io.netty.util.AttributeKey;
-
-/**
- *
- * This class is relay handler relating Cloud Interface
- *
- */
-@Sharable
-public class CoapRelayHandler extends ChannelDuplexHandler {
-
-    /////////// Handler for Resource Directory
-    private static final AttributeKey<ChannelHandlerContext> keyRDClient = AttributeKey
-            .newInstance("rdCtx");
-
-    private static class RDHandler
-            extends SimpleChannelInboundHandler<CoapResponse> {
-        @Override
-        public void channelRead0(ChannelHandlerContext ctx, CoapResponse msg)
-                throws Exception {
-            Logger.d("Receive response from RD, forward to client");
-
-            ChannelHandlerContext ctxToDevice = ctx.channel().attr(keyRDClient)
-                    .get();
-            ctxToDevice.writeAndFlush(msg);
-        }
-
-        @Override
-        public void exceptionCaught(ChannelHandlerContext ctx,
-                Throwable cause) {
-            cause.printStackTrace();
-            ctx.close();
-        }
-    }
-
-    private CoapClient                                   rdClient         = null;
-                                                                          ///////////
-
-    ////////// Handler for Account Server
-    private static final AttributeKey<List<CoapRequest>> keyAccountClient = AttributeKey
-            .newInstance("accountCtx");
-
-    private class AccountHandler
-            extends SimpleChannelInboundHandler<CoapResponse> {
-        @Override
-        public void channelRead0(ChannelHandlerContext ctx, CoapResponse msg)
-                throws Exception {
-            Logger.d("Receive response from AS, make request to RD");
-
-            CoapRequest rdRequest = null;
-
-            switch (msg.getResponseCode()) {
-                case CREATED:
-                    // response of POST request
-                    rdRequest = ctx.channel().attr(keyAccountClient).get()
-                            .remove(0);
-                    rdClient.sendRequest(rdRequest);
-                    break;
-
-                case CONTENT:
-                    // response of GET request, contains did list
-                    rdRequest = ctx.channel().attr(keyAccountClient).get()
-                            .remove(0);
-                    // change uri to send RD
-                    rdRequest.setUriPath(Constants.RD_URI);
-                    rdRequest.setUriQuery(Constants.DEVICE_LIST);
-                    rdRequest.setPayload(msg.getPayload());
-                    rdClient.sendRequest(rdRequest);
-                    break;
-
-                default:
-                    break;
-            }
-        }
-
-        @Override
-        public void exceptionCaught(ChannelHandlerContext ctx,
-                Throwable cause) {
-            cause.printStackTrace();
-            ctx.close();
-        }
-    }
-
-    private CoapClient     asClient       = null;
-    //////////
-
-    private SessionManager sessionManager = null;
-
-    public CoapRelayHandler(SessionManager sessionManager) {
-        this.sessionManager = sessionManager;
-
-        rdClient = new CoapClient();
-
-        rdClient.addHandler(new RDHandler());
-
-        asClient = new CoapClient();
-
-        asClient.addHandler(new AccountHandler());
-    }
-
-    public void startHandler(String rdAddress, int rdPort, String acAddress,
-            int acPort) throws Exception {
-        rdClient.startClient(new InetSocketAddress(rdAddress, rdPort));
-
-        asClient.startClient(new InetSocketAddress(acAddress, acPort));
-
-        asClient.getChannelFuture().channel().attr(keyAccountClient)
-                .set(new ArrayList<CoapRequest>());
-    }
-
-    public void stopHandler() throws Exception {
-        asClient.stopClient();
-
-        rdClient.stopClient();
-    }
-
-    private static final AttributeKey<ChannelHandlerContext> keyDevice = AttributeKey
-            .newInstance("deviceCtx");
-
-    @Override
-    public void channelRead(ChannelHandlerContext ctx, Object msg)
-            throws Exception {
-
-        if (msg instanceof CoapRequest) {
-            CoapRequest request = (CoapRequest) msg;
-            // Parse uri, send to RD
-            String uriPath = request.getUriPath();
-            CoapRequest accountRequest = null;
-            String userId, deviceId, authPayload;
-            CoapResponse response;
-
-            Logger.d("Request received, URI: " + uriPath);
-            if (uriPath != null) {
-                switch (uriPath) {
-                    case Constants.AUTH_URI:
-                        // This case user wants to logout
-                        String uriQuery = request.getUriQuery();
-                        if (uriQuery != null) {
-                            if (uriQuery.endsWith("logout")) {
-                                ctx.channel().attr(Constants.Attribute_UserId)
-                                        .remove();
-                                response = new CoapResponse(CoapStatus.DELETED);
-                            } else {
-                                response = new CoapResponse(
-                                        CoapStatus.BAD_REQUEST);
-                            }
-                            ctx.writeAndFlush(response);
-                        }
-                        break;
-
-                    case Constants.RD_URI:
-                        // RD POST means publish device to server
-                        switch (request.getRequestMethod()) {
-                            case POST:
-                                userId = ctx.channel()
-                                        .attr(Constants.Attribute_UserId).get();
-                                deviceId = request.decodeDeviceId();
-                                authPayload = String.format(
-                                        "{\"userid\":\"%s\",\"deviceid\":\"%s\"}",
-                                        userId, deviceId);
-                                accountRequest = new CoapRequest(
-                                        CoapMethod.POST);
-                                accountRequest
-                                        .setUriPath(Constants.ACCOUNT_URI);
-                                accountRequest.setUriQuery("reqtype=publish");
-                                accountRequest.setToken(request.getToken());
-                                accountRequest.setPayload(authPayload
-                                        .getBytes(StandardCharsets.UTF_8));
-
-                                // TODO: deviceId must be registered after
-                                // session
-                                // granted
-                                Logger.d("Adding deviceId to session: "
-                                        + deviceId);
-                                sessionManager.addSession(deviceId, ctx);
-                                break;
-
-                            default:
-                                Logger.e("Unsupported request type");
-                                break;
-                        }
-
-                        rdClient.getChannelFuture().channel().attr(keyRDClient)
-                                .set(ctx);
-
-                        // Add original request to list for future use
-                        asClient.getChannelFuture().channel()
-                                .attr(keyAccountClient).get().add(request);
-                        asClient.sendRequest(accountRequest);
-                        return;
-
-                    case Constants.WELL_KNOWN_URI:
-                        switch (request.getRequestMethod()) {
-                            case GET:
-                                userId = ctx.channel()
-                                        .attr(Constants.Attribute_UserId).get();
-                                authPayload = String
-                                        .format("{\"userid\":\"%s\"}", userId);
-                                accountRequest = new CoapRequest(
-                                        CoapMethod.GET);
-                                accountRequest
-                                        .setUriPath(Constants.ACCOUNT_URI);
-                                accountRequest.setUriQuery("reqtype=find");
-                                accountRequest.setToken(request.getToken());
-                                accountRequest.setPayload(authPayload
-                                        .getBytes(StandardCharsets.UTF_8));
-                                break;
-
-                            default:
-                                Logger.e("Unsupported request type");
-                                break;
-                        }
-
-                        rdClient.getChannelFuture().channel().attr(keyRDClient)
-                                .set(ctx);
-
-                        // Add original request to list for future use
-                        asClient.getChannelFuture().channel()
-                                .attr(keyAccountClient).get().add(request);
-                        asClient.sendRequest(accountRequest);
-                        return;
-
-                    case Constants.KEEP_ALIVE_URI:
-                        break;
-
-                    default:
-                        List<String> uriPathList = request.getUriPathSegments();
-                        if (uriPathList != null) {
-                            Logger.i("uriPahtList: " + uriPathList.toString());
-
-                            String did = uriPathList.get(0);
-
-                            Logger.i("did: " + did);
-
-                            // TODO: Clustering algorithm required
-                            // find ctx about did, and send msg
-                            StringBuffer resource = new StringBuffer();
-                            List<String> pathSegments = uriPathList.subList(1,
-                                    uriPathList.size());
-                            for (String path : pathSegments) {
-                                resource.append("/");
-                                resource.append(path);
-                            }
-                            Logger.i("resource: " + resource);
-                            request.setUriPath(resource.toString());
-
-                            ChannelHandlerContext deviceCtx = sessionManager
-                                    .querySession(did);
-                            if (deviceCtx != null) {
-                                deviceCtx.attr(keyDevice).set(ctx);
-                                deviceCtx.writeAndFlush(request);
-                            } else {
-                                Logger.e("deviceCtx is null");
-                                response = new CoapResponse(
-                                        CoapStatus.FORBIDDEN);
-                                response.setToken(request.getToken());
-                                ctx.writeAndFlush(response);
-                            }
-                        }
-                        return;
-                }
-            }
-
-        } else if (msg instanceof CoapResponse) {
-            ChannelHandlerContext resourceClient = ctx.attr(keyDevice).get();
-            if (resourceClient != null) {
-                Logger.i("Forwards message to client");
-
-                CoapResponse response = (CoapResponse) msg;
-
-                // If response contains path, add di
-                String did = sessionManager.queryDid(ctx);
-                if (response.getOption(11) != null && did != null) {
-                    response.getOption(11).add(0,
-                            did.getBytes(StandardCharsets.UTF_8));
-                }
-
-                Logger.i(
-                        "ctx.channel : " + resourceClient.channel().toString());
-                resourceClient.writeAndFlush(response);
-                return;
-            }
-        }
-
-        super.channelRead(ctx, msg);
-    }
-
-    @Override
-    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
-        Logger.d("Channel Inactive");
-        sessionManager.removeSessionByChannel(ctx);
-        super.channelInactive(ctx);
-    }
-
-    @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
-
-        cause.printStackTrace();
-        ctx.close();
-    }
-}
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
new file mode 100644 (file)
index 0000000..84b8675
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.ciserver.resources;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import org.iotivity.cloud.base.device.CoapDevice;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.device.IRequestChannel;
+import org.iotivity.cloud.base.device.IResponseEventHandler;
+import org.iotivity.cloud.base.exception.ServerException;
+import org.iotivity.cloud.base.exception.ServerException.NotFoundException;
+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.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.ciserver.Constants;
+import org.iotivity.cloud.ciserver.DeviceServerSystem.CoapDevicePool;
+import org.iotivity.cloud.util.Cbor;
+
+public class DiResource extends Resource {
+
+    private CoapDevicePool mDevicePool = null;
+
+    public DiResource(CoapDevicePool devicePool) {
+        super(Arrays.asList(Constants.DEVICE_ID));
+        mDevicePool = devicePool;
+
+        addQueryHandler(
+                Arrays.asList(Constants.RS_INTERFACE + "="
+                        + Constants.LINK_INTERFACE),
+                this::onLinkInterfaceRequestReceived);
+    }
+
+    private IRequestChannel getTargetDeviceChannel(IRequest request)
+            throws ServerException {
+        List<String> uriPathSegment = request.getUriPathSegments();
+
+        if (uriPathSegment.size() < 2) {
+            throw new PreconditionFailedException();
+        }
+
+        String deviceId = uriPathSegment.get(1);
+        CoapDevice targetDevice = (CoapDevice) mDevicePool
+                .queryDevice(deviceId);
+
+        if (targetDevice == null) {
+            throw new NotFoundException();
+        }
+
+        // Do request and receive response
+        return targetDevice.getRequestChannel();
+    }
+
+    private String extractTargetUriPath(IRequest request) {
+        List<String> uriPathSegment = request.getUriPathSegments();
+
+        // Remove prefix path
+        uriPathSegment.remove(0);
+        uriPathSegment.remove(0);
+
+        StringBuilder uriPath = new StringBuilder();
+        for (String path : uriPathSegment) {
+            uriPath.append("/" + path);
+        }
+
+        return uriPath.toString();
+    }
+
+    class LinkInterfaceHandler implements IResponseEventHandler {
+        private Cbor<List<HashMap<String, Object>>> mCbor      = new Cbor<>();
+        private String                              mTargetDI  = null;
+        private Device                              mSrcDevice = null;
+
+        public LinkInterfaceHandler(String targetDI, Device srcDevice) {
+            mTargetDI = targetDI;
+            mSrcDevice = srcDevice;
+        }
+
+        private void convertHref(List<HashMap<String, Object>> linkPayload) {
+            for (HashMap<String, Object> link : linkPayload) {
+                link.put("href", "/di/" + mTargetDI + link.get("href"));
+            }
+        }
+
+        @Override
+        public void onResponseReceived(IResponse response) {
+            List<HashMap<String, Object>> linkPayload = null;
+            if (response.getStatus() == ResponseStatus.CONTENT) {
+                linkPayload = mCbor.parsePayloadFromCbor(response.getPayload(),
+                        ArrayList.class);
+                convertHref(linkPayload);
+            }
+
+            mSrcDevice.sendResponse(MessageBuilder.modifyResponse(response,
+                    ContentFormat.APPLICATION_CBOR, linkPayload != null
+                            ? mCbor.encodingPayloadToCbor(linkPayload) : null));
+        }
+    }
+
+    public void onLinkInterfaceRequestReceived(Device srcDevice,
+            IRequest request) throws ServerException {
+        IRequestChannel requestChannel = getTargetDeviceChannel(request);
+
+        if (requestChannel == null) {
+            throw new NotFoundException();
+        }
+
+        String deviceId = request.getUriPathSegments().get(1);
+
+        requestChannel.sendRequest(
+                MessageBuilder.modifyRequest(request,
+                        extractTargetUriPath(request), null, null, null),
+                new LinkInterfaceHandler(deviceId, srcDevice));
+    }
+
+    // This is optional method for packet handling
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+        // Find proper request channel using di in URI path field.
+        IRequestChannel requestChannel = getTargetDeviceChannel(request);
+
+        if (requestChannel == null) {
+            throw new NotFoundException();
+        }
+
+        requestChannel.sendRequest(
+                MessageBuilder.modifyRequest(request,
+                        extractTargetUriPath(request), null, null, null),
+                srcDevice);
+    }
+}
index 804bf81..7f0ccc5 100644 (file)
@@ -1,27 +1,28 @@
 /*
- *******************************************************************
- *
- * 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.
- *
- *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ * //******************************************************************
+ * //
+ * // 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.ciserver.resources;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -30,16 +31,17 @@ import java.util.Set;
 import java.util.Timer;
 import java.util.TimerTask;
 
-import org.iotivity.cloud.base.Resource;
-import org.iotivity.cloud.base.SessionManager;
-import org.iotivity.cloud.base.protocols.coap.CoapRequest;
-import org.iotivity.cloud.base.protocols.coap.CoapResponse;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+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.protocols.IRequest;
+import org.iotivity.cloud.base.protocols.IResponse;
+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.base.resource.Resource;
 import org.iotivity.cloud.ciserver.Constants;
 import org.iotivity.cloud.util.Cbor;
-import org.iotivity.cloud.util.Logger;
-
-import io.netty.channel.ChannelHandlerContext;
 
 /**
  *
@@ -48,149 +50,100 @@ import io.netty.channel.ChannelHandlerContext;
  *
  */
 public class KeepAliveResource extends Resource {
-
-    private int[]                                intervals;
-    private HashMap<ChannelHandlerContext, Long> connectPool;
-    private Timer                                timer;
-    private Cbor<HashMap<String, Integer>>       cbor;
-    private SessionManager                       sessionManager = null;
-
-    public void setIntervals(int[] intervals) {
-        this.intervals = intervals;
-    }
-
-    public int[] getIntervals() {
-        return this.intervals;
+    private int[]                          mIntervals      = null;
+    private Timer                          mTimer          = new Timer();
+    private Cbor<HashMap<String, Integer>> mCbor           = new Cbor<>();
+    private HashMap<Device, Long>          mConnectionPool = new HashMap<>();
+
+    public KeepAliveResource(int[] intervals) {
+        super(Arrays.asList(Constants.PREFIX_OIC, Constants.KEEP_ALIVE_URI));
+        mIntervals = intervals;
     }
 
-    public KeepAliveResource(SessionManager sessionManager, int[] intervals) {
-        setUri(Constants.KEEP_ALIVE_URI);
-        setIntervals(intervals);
-        this.sessionManager = sessionManager;
-        connectPool = new HashMap<ChannelHandlerContext, Long>();
-        timer = new Timer();
-        cbor = new Cbor<HashMap<String, Integer>>();
-    }
-
-    public void startSessionChecker() {
-        timer.schedule(new KeepAliveTask(), 30000, 60000);
-    }
-
-    public void stopSessionChecker() {
-        timer.cancel();
-    }
-
-    /**
-     * API for receiving message(message to keepalive resource)
-     *
-     * @param ctx
-     *            ChannelHandlerContext of request message
-     * @param request
-     *            CoAP request message
-     */
     @Override
-    public void onRequestReceived(ChannelHandlerContext ctx,
-            CoapRequest request) {
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
 
-        CoapResponse response = null;
+        IResponse response = null;
 
-        switch (request.getRequestMethod()) {
-            // First message to KeepAlive from resource
+        switch (request.getMethod()) {
             case GET:
-                if (intervals != null) {
-                    response = makePingConfigMessage(request);
-                    connectPool.put(ctx, System.currentTimeMillis()
-                            + (intervals[0] * (long) 60000));
-                }
+                response = handleGetPingConfig(request);
+                mConnectionPool.put(srcDevice, System.currentTimeMillis()
+                        + (mIntervals[0] * (long) 60000));
                 break;
-            // interval Message to KeepAlive After receiving GET Message
-            case PUT:
-                HashMap<String, Integer> payloadData = null;
-                payloadData = cbor.parsePayloadFromCbor(request.getPayload(),
-                        HashMap.class);
 
-                Logger.d("Receive payloadData : " + payloadData);
-                if (payloadData != null) {
-                    if (payloadData.containsKey("in")) {
-                        Logger.d("interval : " + payloadData.get("in"));
-
-                        connectPool.put(ctx, System.currentTimeMillis()
-                                + (payloadData.get("in") * (long) 60000));
-                    }
-                }
-                response = makeResponse(request);
-                break;
-
-            case POST:
+            case PUT:
+                response = handlePutPingConfig(srcDevice, request);
                 break;
 
-            case DELETE:
-                break;
+            default:
+                throw new BadRequestException(
+                        request.getMethod() + " request type is not support");
         }
 
-        ctx.writeAndFlush(response);
+        srcDevice.sendResponse(response);
     }
 
-    /**
-     * API for making response to Resource
-     *
-     * @param request
-     *            ChannelHandlerContext of request message
-     */
-    private CoapResponse makeResponse(CoapRequest request) {
-        CoapResponse response = new CoapResponse(CoapStatus.VALID);
-        response.setToken(request.getToken());
+    public void startSessionChecker() {
+        mTimer.schedule(new KeepAliveTask(), 30000, 60000);
+    }
 
-        return response;
+    public void stopSessionChecker() {
+        mTimer.cancel();
     }
 
     /**
      * API for making interval and first response to Resource
-     *
+     * 
      * @param request
      *            ChannelHandlerContext of request message
      */
-    private CoapResponse makePingConfigMessage(CoapRequest request) {
-        CoapResponse response = new CoapResponse(CoapStatus.CONTENT);
-        response.setToken(request.getToken());
-
-        HashMap<String, int[]> payloadData = new HashMap<String, int[]>();
-        payloadData.put("inarray", intervals);
+    private IResponse handleGetPingConfig(IRequest request) {
 
-        byte[] cborData = cbor.encodingPayloadToCbor(payloadData);
+        HashMap<String, int[]> payloadData = new HashMap<>();
+        payloadData.put("inarray", mIntervals);
 
-        response.setPayload(cborData);
+        return MessageBuilder.createResponse(request, ResponseStatus.CONTENT,
+                ContentFormat.APPLICATION_CBOR,
+                mCbor.encodingPayloadToCbor(payloadData));
+    }
 
-        Logger.d("Send payloadData : " + payloadData);
+    private IResponse handlePutPingConfig(Device srcDevice, IRequest request) {
 
-        return response;
+        HashMap<String, Integer> payloadData = mCbor
+                .parsePayloadFromCbor(request.getPayload(), HashMap.class);
+        if (payloadData != null) {
+            if (payloadData.containsKey("in")) {
+                mConnectionPool.put(srcDevice, System.currentTimeMillis()
+                        + (payloadData.get("in") * (long) 60000));
+            }
+        }
+        return MessageBuilder.createResponse(request, ResponseStatus.VALID);
     }
 
     /**
      * API for managing session
      */
-    public class KeepAliveTask extends TimerTask {
+    private class KeepAliveTask extends TimerTask {
 
         @Override
         public void run() {
-            Map<ChannelHandlerContext, Long> map = Collections
-                    .synchronizedMap(connectPool);
-            Set<ChannelHandlerContext> keySet = map.keySet();
-            ArrayList<ChannelHandlerContext> deleteList = new ArrayList<ChannelHandlerContext>();
-            Iterator<ChannelHandlerContext> iterator = null;
+            Map<Device, Long> map = Collections
+                    .synchronizedMap(mConnectionPool);
+            Set<Device> keySet = map.keySet();
+            ArrayList<Device> deleteList = new ArrayList<>();
+            Iterator<Device> iterator = null;
             synchronized (map) {
                 iterator = keySet.iterator();
                 Long currentTime = System.currentTimeMillis();
                 // check interval
                 while (iterator.hasNext()) {
-                    ChannelHandlerContext key = iterator.next();
+                    Device key = iterator.next();
                     if (map.containsKey(key)) {
                         if (map.get(key) != null) {
                             Long lifeTime = (Long) map.get(key);
                             if (lifeTime != null) {
-                                Logger.d("KeepAliveTask Operating : "
-                                        + key.channel().toString() + ", Time : "
-                                        + (lifeTime - currentTime));
                                 if (lifeTime < currentTime) {
                                     deleteList.add(key);
                                 }
@@ -203,11 +156,10 @@ public class KeepAliveResource extends Resource {
             iterator = deleteList.iterator();
             // remove session
             while (iterator.hasNext()) {
-                ChannelHandlerContext key = iterator.next();
-                Logger.d("KeepAliveTask Remove");
-                connectPool.remove(key);
-                sessionManager.removeSessionByChannel(key);
-                key.close();
+                Device key = iterator.next();
+                mConnectionPool.remove(key);
+                key.getCtx().fireChannelInactive();
+                key.getCtx().close();
             }
         }
     }
diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/Account.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/Account.java
new file mode 100644 (file)
index 0000000..e89dfc9
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.ciserver.resources.proxy;
+
+import java.util.Arrays;
+
+import org.iotivity.cloud.base.connector.ConnectorPool;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.device.IRequestChannel;
+import org.iotivity.cloud.base.exception.ServerException;
+import org.iotivity.cloud.base.protocols.IRequest;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.ciserver.Constants;
+
+public class Account extends Resource {
+    IRequestChannel mAuthServer = null;
+
+    public Account() {
+        super(Arrays.asList(Constants.PREFIX_WELL_KNOWN, Constants.PREFIX_OCF,
+                Constants.ACCOUNT_URI));
+
+        mAuthServer = ConnectorPool.getConnection("account");
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+        // Token exchange is done by CoapClient
+        mAuthServer.sendRequest(request, srcDevice);
+    }
+}
diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/DevicePresence.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/DevicePresence.java
new file mode 100644 (file)
index 0000000..db39483
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.ciserver.resources.proxy;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.iotivity.cloud.base.connector.ConnectorPool;
+import org.iotivity.cloud.base.device.CoapDevice;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.device.IRequestChannel;
+import org.iotivity.cloud.base.device.IResponseEventHandler;
+import org.iotivity.cloud.base.exception.ClientException;
+import org.iotivity.cloud.base.exception.ClientException.BadResponseException;
+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.enums.RequestMethod;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.ciserver.Constants;
+import org.iotivity.cloud.util.Cbor;
+
+public class DevicePresence extends Resource {
+    IRequestChannel mASServer = null;
+
+    public DevicePresence() {
+        super(Arrays.asList(Constants.PREFIX_WELL_KNOWN, Constants.PREFIX_OCF,
+                Constants.DEVICE_PRESENCE_URI));
+
+        mASServer = ConnectorPool.getConnection("account");
+    }
+
+    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;
+        }
+
+        @Override
+        public void onResponseReceived(IResponse response)
+                throws ClientException {
+
+            switch (response.getStatus()) {
+                case VALID:
+                    mRDServer.sendRequest(mRequest, mSrcDevice);
+                    break;
+
+                case CONTENT:
+                    StringBuilder additionalQuery = new StringBuilder();
+
+                    Cbor<HashMap<String, ArrayList<String>>> responsePayload = new Cbor<>();
+
+                    ArrayList<String> deviceList = responsePayload
+                            .parsePayloadFromCbor(response.getPayload(),
+                                    HashMap.class)
+                            .get("devices");
+
+                    int index = deviceList.size();
+                    for (String deviceId : deviceList) {
+                        if (!deviceId.equals(mSrcDevice.getDeviceId())) {
+                            additionalQuery.append("di=");
+                            additionalQuery.append(deviceId);
+                            if (--index > 0) {
+                                additionalQuery.append("&");
+                            }
+                        }
+                    }
+
+                    String uriQuery = (mRequest.getUriQuery() == null ? ""
+                            : mRequest.getUriQuery() + "&")
+                            + additionalQuery.toString();
+                    IRequest requestToAS = MessageBuilder.modifyRequest(
+                            mRequest, null, uriQuery, null, null);
+
+                    mRDServer.sendRequest(requestToAS, mSrcDevice);
+                    break;
+
+                default:
+                    throw new BadResponseException(
+                            response.getStatus().toString()
+                                    + " response type is not supported");
+            }
+        }
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+        // Token exchange is done by CoapClient
+        CoapDevice coapDevice = (CoapDevice) srcDevice;
+        StringBuffer uriQuery = new StringBuffer();
+        uriQuery.append(Constants.SEARCH_ACCESS_TOKEN + "=");
+        uriQuery.append(coapDevice.getAccessToken());
+
+        if (request.getUriQueryMap() != null) {
+            if (request.getUriQueryMap().get("di") != null) {
+                String di = request.getUriQueryMap().get("di").get(0);
+                if (di != null) {
+                    uriQuery.append("&");
+                    uriQuery.append("di" + "=");
+                    uriQuery.append(di);
+                }
+            }
+        }
+
+        StringBuffer uriPath = new StringBuffer();
+        uriPath.append(Constants.PREFIX_WELL_KNOWN + "/");
+        uriPath.append(Constants.PREFIX_OCF + "/");
+        uriPath.append(Constants.ACCOUNT_URI + "/");
+        uriPath.append(Constants.DEVICE_URI);
+
+        IRequest requestToAS = MessageBuilder.createRequest(RequestMethod.GET,
+                uriPath.toString(), uriQuery.toString());
+
+        mASServer.sendRequest(requestToAS,
+                new AccountReceiveHandler(request, srcDevice));
+    }
+}
diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/MessageQueue.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/MessageQueue.java
new file mode 100644 (file)
index 0000000..a4153f9
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.ciserver.resources.proxy;
+
+import java.util.Arrays;
+
+import org.iotivity.cloud.base.connector.ConnectorPool;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.device.IRequestChannel;
+import org.iotivity.cloud.base.exception.ServerException;
+import org.iotivity.cloud.base.protocols.IRequest;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.ciserver.Constants;
+
+public class MessageQueue extends Resource {
+    IRequestChannel mPSServer = null;
+
+    public MessageQueue() {
+        super(Arrays.asList(Constants.PREFIX_OIC, Constants.MQ_BROKER_URI));
+
+        mPSServer = ConnectorPool.getConnection("mq");
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+
+        // Token exchange is done by CoapClient
+        mPSServer.sendRequest(request, srcDevice);
+    }
+}
diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/ResourceDirectory.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/ResourceDirectory.java
new file mode 100644 (file)
index 0000000..8764ab6
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.ciserver.resources.proxy;
+
+import java.util.Arrays;
+
+import org.iotivity.cloud.base.connector.ConnectorPool;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.device.IRequestChannel;
+import org.iotivity.cloud.base.exception.ServerException;
+import org.iotivity.cloud.base.protocols.IRequest;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.ciserver.Constants;
+
+public class ResourceDirectory extends Resource {
+    IRequestChannel mRDServer = null;
+
+    public ResourceDirectory() {
+        super(Arrays.asList(Constants.PREFIX_OIC, Constants.RD_URI));
+
+        mRDServer = ConnectorPool.getConnection("rd");
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+        // Token exchange is done by CoapClient
+        mRDServer.sendRequest(request, srcDevice);
+    }
+}
diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/ResourceFind.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/ResourceFind.java
new file mode 100644 (file)
index 0000000..dcee4ba
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.ciserver.resources.proxy;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.iotivity.cloud.base.connector.ConnectorPool;
+import org.iotivity.cloud.base.device.CoapDevice;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.device.IRequestChannel;
+import org.iotivity.cloud.base.device.IResponseEventHandler;
+import org.iotivity.cloud.base.exception.ClientException;
+import org.iotivity.cloud.base.exception.ClientException.BadResponseException;
+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.enums.RequestMethod;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.ciserver.Constants;
+import org.iotivity.cloud.util.Cbor;
+
+public class ResourceFind extends Resource {
+    IRequestChannel mASServer = null;
+
+    public ResourceFind() {
+        super(Arrays.asList(Constants.PREFIX_OIC, Constants.WELL_KNOWN_URI));
+
+        mASServer = ConnectorPool.getConnection("account");
+    }
+
+    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;
+        }
+
+        @Override
+        public void onResponseReceived(IResponse response)
+                throws ClientException {
+
+            switch (response.getStatus()) {
+                case VALID:
+                    mRDServer.sendRequest(mRequest, mSrcDevice);
+                    break;
+
+                case CONTENT:
+                    StringBuilder additionalQuery = new StringBuilder();
+
+                    Cbor<HashMap<String, ArrayList<String>>> responsePayload = new Cbor<>();
+
+                    ArrayList<String> deviceList = responsePayload
+                            .parsePayloadFromCbor(response.getPayload(),
+                                    HashMap.class)
+                            .get("devices");
+
+                    int index = deviceList.size();
+
+                    for (String deviceId : deviceList) {
+                        if (!deviceId.equals(mSrcDevice.getDeviceId())) {
+                            additionalQuery.append("di=");
+                            additionalQuery.append(deviceId);
+                            if (--index > 0) {
+                                additionalQuery.append("&");
+                            }
+                        }
+                    }
+                    String uriQuery = (mRequest.getUriQuery() == null ? ""
+                            : mRequest.getUriQuery() + "&")
+                            + additionalQuery.toString();
+                    IRequest requestToAS = MessageBuilder.modifyRequest(
+                            mRequest, null, uriQuery, null, null);
+
+                    mRDServer.sendRequest(requestToAS, mSrcDevice);
+                    break;
+
+                default:
+                    throw new BadResponseException(
+                            response.getStatus().toString()
+                                    + " response type is not supported");
+            }
+        }
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+        // Token exchange is done by CoapClient
+        CoapDevice coapDevice = (CoapDevice) srcDevice;
+        StringBuffer uriQuery = new StringBuffer();
+        uriQuery.append(Constants.SEARCH_ACCESS_TOKEN + "=");
+        uriQuery.append(coapDevice.getAccessToken());
+
+        if (request.getUriQueryMap().get("di") != null) {
+            String di = request.getUriQueryMap().get("di").get(0);
+            if (di != null) {
+                uriQuery.append("&");
+                uriQuery.append("di" + "=");
+                uriQuery.append(di);
+            }
+        }
+
+        StringBuffer uriPath = new StringBuffer();
+        uriPath.append(Constants.PREFIX_WELL_KNOWN + "/");
+        uriPath.append(Constants.PREFIX_OCF + "/");
+        uriPath.append(Constants.ACCOUNT_URI + "/");
+        uriPath.append(Constants.DEVICE_URI);
+
+        IRequest requestToAS = MessageBuilder.createRequest(RequestMethod.GET,
+                uriPath.toString(), uriQuery.toString());
+
+        mASServer.sendRequest(requestToAS,
+                new AccountReceiveHandler(request, srcDevice));
+    }
+}
diff --git a/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/ResourcePresence.java b/cloud/interface/src/main/java/org/iotivity/cloud/ciserver/resources/proxy/ResourcePresence.java
new file mode 100644 (file)
index 0000000..ff22d95
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.ciserver.resources.proxy;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.iotivity.cloud.base.connector.ConnectorPool;
+import org.iotivity.cloud.base.device.CoapDevice;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.device.IRequestChannel;
+import org.iotivity.cloud.base.device.IResponseEventHandler;
+import org.iotivity.cloud.base.exception.ClientException;
+import org.iotivity.cloud.base.exception.ClientException.BadResponseException;
+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.enums.RequestMethod;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.ciserver.Constants;
+import org.iotivity.cloud.util.Cbor;
+
+public class ResourcePresence extends Resource {
+    IRequestChannel mASServer = null;
+
+    public ResourcePresence() {
+        super(Arrays.asList(Constants.PREFIX_OIC, Constants.RES_PRESENCE_URI));
+
+        mASServer = ConnectorPool.getConnection("account");
+    }
+
+    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;
+        }
+
+        @Override
+        public void onResponseReceived(IResponse response)
+                throws ClientException {
+
+            switch (response.getStatus()) {
+                case VALID:
+                    mRDServer.sendRequest(mRequest, mSrcDevice);
+                    break;
+
+                case CONTENT:
+                    StringBuilder additionalQuery = new StringBuilder();
+
+                    Cbor<HashMap<String, ArrayList<String>>> responsePayload = new Cbor<>();
+
+                    ArrayList<String> deviceList = responsePayload
+                            .parsePayloadFromCbor(response.getPayload(),
+                                    HashMap.class)
+                            .get("devices");
+
+                    int index = deviceList.size();
+                    for (String deviceId : deviceList) {
+                        if (!deviceId.equals(mSrcDevice.getDeviceId())) {
+                            additionalQuery.append("di=");
+                            additionalQuery.append(deviceId);
+                            if (--index > 0) {
+                                additionalQuery.append("&");
+                            }
+                        }
+                    }
+
+                    String uriQuery = (mRequest.getUriQuery() == null ? ""
+                            : mRequest.getUriQuery() + "&")
+                            + additionalQuery.toString();
+                    IRequest requestToAS = MessageBuilder.modifyRequest(
+                            mRequest, null, uriQuery, null, null);
+
+                    mRDServer.sendRequest(requestToAS, mSrcDevice);
+                    break;
+
+                default:
+                    throw new BadResponseException(
+                            response.getStatus().toString()
+                                    + " response type is not supported");
+            }
+        }
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+        // Token exchange is done by CoapClient
+        CoapDevice coapDevice = (CoapDevice) srcDevice;
+        StringBuffer uriQuery = new StringBuffer();
+        uriQuery.append(Constants.SEARCH_ACCESS_TOKEN + "=");
+        uriQuery.append(coapDevice.getAccessToken());
+
+        if (request.getUriQueryMap() != null) {
+            String di = request.getUriQueryMap().get("di").get(0);
+            if (di != null) {
+                uriQuery.append("&");
+                uriQuery.append("di" + "=");
+                uriQuery.append(di);
+            }
+        }
+
+        StringBuffer uriPath = new StringBuffer();
+        uriPath.append(Constants.PREFIX_WELL_KNOWN + "/");
+        uriPath.append(Constants.PREFIX_OCF + "/");
+        uriPath.append(Constants.ACCOUNT_URI + "/");
+        uriPath.append(Constants.DEVICE_URI);
+
+        IRequest requestToAS = MessageBuilder.createRequest(RequestMethod.GET,
+                uriPath.toString(), uriQuery.toString());
+
+        mASServer.sendRequest(requestToAS,
+                new AccountReceiveHandler(request, srcDevice));
+    }
+}
diff --git a/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/testci/TestCloudInterface.java b/cloud/interface/src/test/java/org/iotivity/cloud/ciserver/testci/TestCloudInterface.java
deleted file mode 100644 (file)
index 311dec9..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-package org.iotivity.cloud.ciserver.testci;
-
-import java.net.InetSocketAddress;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-
-import org.iotivity.cloud.base.CoapClient;
-import org.iotivity.cloud.base.CoapServer;
-import org.iotivity.cloud.base.ResourceManager;
-import org.iotivity.cloud.base.SessionManager;
-import org.iotivity.cloud.base.protocols.coap.CoapRequest;
-import org.iotivity.cloud.base.protocols.coap.CoapResponse;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
-import org.iotivity.cloud.ciserver.Constants;
-import org.iotivity.cloud.ciserver.protocols.CoapAuthHandler;
-import org.iotivity.cloud.ciserver.protocols.CoapRelayHandler;
-import org.iotivity.cloud.ciserver.resources.KeepAliveResource;
-import org.iotivity.cloud.util.Cbor;
-import org.iotivity.cloud.util.CoapLogHandler;
-import org.junit.Test;
-
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.SimpleChannelInboundHandler;
-
-public class TestCloudInterface {
-
-    private SessionManager  sessionManager  = new SessionManager();
-    private ResourceManager resourceManager = new ResourceManager();
-
-    private CoapServer        coapServer        = null;
-    private CoapClient        coapClient        = null;
-    private CoapRelayHandler  coapRelayHandler  = new CoapRelayHandler(
-            sessionManager);
-    private KeepAliveResource keepAliveResource = new KeepAliveResource(
-            sessionManager, new int[] { 1, 2, 4, 8 });
-
-    static class CoapClientHandler
-            extends SimpleChannelInboundHandler<CoapResponse> {
-
-        ChannelHandlerContext connectCtx = null;
-
-        @Override
-        public void channelActive(ChannelHandlerContext ctx) throws Exception {
-            connectCtx = ctx;
-        }
-
-        @Override
-        protected void channelRead0(ChannelHandlerContext arg0,
-                CoapResponse arg1) throws Exception {
-            // TODO : receive response
-            System.out.println("Get Response");
-        }
-    }
-
-    public void startServer() throws Exception {
-
-        coapServer = new CoapServer();
-
-        coapServer.addHandler(new CoapLogHandler());
-        coapServer.addHandler(coapRelayHandler);
-
-        coapServer.addHandler(resourceManager);
-        resourceManager.registerResource(keepAliveResource);
-
-        coapServer.startServer(new InetSocketAddress(5683));
-    }
-
-    public ChannelHandlerContext startClient() throws Exception {
-
-        coapClient = new CoapClient();
-
-        CoapClientHandler coapHandler = new CoapClientHandler();
-        coapClient.addHandler(coapHandler);
-
-        coapClient.addHandler(new CoapAuthHandler());
-
-        coapClient.startClient(new InetSocketAddress("127.0.0.1", 5683));
-
-        return coapHandler.connectCtx;
-    }
-
-    public CoapRequest makePayload(CoapRequest request) throws Exception {
-        ArrayList<Object> payload = new ArrayList<Object>();
-
-        HashMap<Object, Object> tags = new HashMap<Object, Object>();
-        tags.put("di", "98f7483c-5a31-4161-ba7e-9c13e0d");
-        tags.put("bm", (int) 1);
-        tags.put("ttl", (int) 86400);
-
-        ArrayList<LinkedHashMap<Object, Object>> publishLinks = new ArrayList<LinkedHashMap<Object, Object>>();
-        LinkedHashMap<Object, Object> link = new LinkedHashMap<Object, Object>();
-        link.put("href", "/a/light");
-        ArrayList<String> rt = new ArrayList<String>();
-        ArrayList<String> itf = new ArrayList<String>();
-        ArrayList<String> mt = new ArrayList<String>();
-        rt.add("core.light");
-        link.put("rt", rt);
-
-        itf.add("oic.if.baseline");
-        link.put("if", itf);
-
-        mt.add("application/json");
-        link.put("mt", mt);
-
-        link.put("ins", 1);
-
-        publishLinks.add(link);
-
-        payload.add(tags);
-        payload.add(publishLinks);
-
-        Cbor<ArrayList<Object>> cbor = new Cbor<ArrayList<Object>>();
-
-        request.setPayload(cbor.encodingPayloadToCbor(payload));
-
-        return request;
-    }
-
-    public CoapRequest makeinterval(CoapRequest request) throws Exception {
-
-        HashMap<Object, Object> payload = new HashMap<Object, Object>();
-        payload.put("in", 1);
-
-        Cbor<ArrayList<Object>> cbor = new Cbor<ArrayList<Object>>();
-
-        request.setPayload(cbor.encodingPayloadToCbor(payload));
-
-        return request;
-    }
-
-    @Test
-    public void TestKeepAlivePutInterval() throws Exception {
-
-        CoapRequest request = new CoapRequest(CoapMethod.PUT);
-        request.setUriPath(Constants.KEEP_ALIVE_URI);
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-        makeinterval(request);
-
-        startServer();
-        startClient();
-
-        coapClient.sendRequest(request);
-
-        System.out.println("Waiting for KeepAliveTask..");
-        Thread.sleep(30000);
-
-        coapClient.stopClient();
-        coapServer.stopServer();
-    }
-
-    @Test
-    public void TestKeepAliveGetFirst() throws Exception {
-
-        CoapRequest request = new CoapRequest(CoapMethod.GET);
-        request.setUriPath(Constants.KEEP_ALIVE_URI);
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-
-        startServer();
-        startClient();
-
-        coapClient.sendRequest(request);
-
-        coapClient.stopClient();
-        coapServer.stopServer();
-    }
-
-    @Test
-    public void TestDiscoveryDevice() throws Exception {
-
-        CoapRequest request = new CoapRequest(CoapMethod.GET);
-        request.setUriPath(Constants.WELL_KNOWN_URI);
-        request.setUriQuery("rt=oic.wk.rdpub");
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-
-        startServer();
-        startClient();
-
-        coapClient.sendRequest(request);
-
-        coapClient.stopClient();
-        coapServer.stopServer();
-    }
-
-    @Test
-    public void TestPublishDevice() throws Exception {
-
-        CoapRequest request = new CoapRequest(CoapMethod.POST);
-        request.setUriPath(Constants.RD_URI);
-        request.setUriQuery("rt=oic.wk.rdpub");
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-        makePayload(request);
-
-        startServer();
-        startClient();
-
-        coapClient.sendRequest(request);
-
-        coapClient.stopClient();
-        coapServer.stopServer();
-    }
-
-    @Test
-    public void TestAuthURI() throws Exception {
-
-        CoapRequest request = new CoapRequest(CoapMethod.GET);
-        request.setUriPath(Constants.AUTH_URI);
-        request.setUriQuery("rt=oic.wk.rdpub");
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-        makePayload(request);
-
-        startServer();
-        startClient();
-
-        coapClient.sendRequest(request);
-
-        coapClient.stopClient();
-        coapServer.stopServer();
-    }
-
-    @Test
-    public void TestRequestGetMessageToDeviceCIOwner() throws Exception {
-
-        CoapRequest request = new CoapRequest(CoapMethod.GET);
-        request.setUriPath(
-                "/10.113.64.98/98f7483c-5a31-4161-ba7e-9c13e0d/a/light");
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-        makePayload(request);
-
-        startServer();
-        startClient();
-
-        coapClient.sendRequest(request);
-
-        coapServer.stopServer();
-        coapClient.stopClient();
-    }
-
-    @Test
-    public void TestRequestGetMessageToDeviceNotCIOwner() throws Exception {
-
-        CoapRequest request = new CoapRequest(CoapMethod.GET);
-        request.setUriPath(
-                "/98f7483c-5a31-4161-ba7e-9c13e0d/a/light");
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-        makePayload(request);
-
-        startServer();
-        startClient();
-
-        coapClient.sendRequest(request);
-
-        coapServer.stopServer();
-        coapClient.stopClient();
-    }
-
-    @Test
-    public void TestRequestPutMessageToDevice() throws Exception {
-
-        CoapRequest request = new CoapRequest(CoapMethod.PUT);
-        request.setUriPath(
-                "/98f7483c-5a31-4161-ba7e-9c13e0d/a/light");
-        request.setToken("1234".getBytes(StandardCharsets.UTF_8));
-        makePayload(request);
-
-        startServer();
-        startClient();
-
-        coapClient.sendRequest(request);
-
-        coapServer.stopServer();
-        coapClient.stopClient();
-    }
-}
diff --git a/cloud/messagequeue/.classpath b/cloud/messagequeue/.classpath
new file mode 100644 (file)
index 0000000..af1430b
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" output="target/classes" path="src/main/java">
+               <attributes>
+                       <attribute name="optional" value="true"/>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+               <attributes>
+                       <attribute name="optional" value="true"/>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+               <attributes>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+               <attributes>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/cloud/messagequeue/.gitignore b/cloud/messagequeue/.gitignore
new file mode 100644 (file)
index 0000000..b83d222
--- /dev/null
@@ -0,0 +1 @@
+/target/
diff --git a/cloud/messagequeue/pom.xml b/cloud/messagequeue/pom.xml
new file mode 100644 (file)
index 0000000..5273a5f
--- /dev/null
@@ -0,0 +1,95 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <groupId>org.iotivity.cloud</groupId>
+       <artifactId>CloudMessageQueue</artifactId>
+       <version>0.0.1-SNAPSHOT</version>
+
+       <properties>
+               <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               <maven.test.skip>true</maven.test.skip>
+       </properties>
+
+       <dependencies>
+               <dependency>
+                       <groupId>org.iotivity.cloud</groupId>
+                       <artifactId>CloudStack</artifactId>
+                       <version>0.0.1-SNAPSHOT</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.mongodb</groupId>
+                       <artifactId>mongo-java-driver</artifactId>
+                       <version>3.2.0</version>
+               </dependency>
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <version>4.12</version>
+               </dependency>
+               <dependency>
+            <groupId>org.apache.kafka</groupId>
+            <artifactId>kafka_2.11</artifactId>
+            <version>0.9.0.0</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jmxri</artifactId>
+                    <groupId>com.sun.jmx</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>jmxtools</artifactId>
+                    <groupId>com.sun.jdmk</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>jms</artifactId>
+                    <groupId>javax.jms</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <inherited>true</inherited>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-compiler-plugin</artifactId>
+                               <configuration>
+                                       <source>1.8</source>
+                                       <target>1.8</target>
+                                       <encoding>UTF-8</encoding>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-jar-plugin</artifactId>
+                               <configuration>
+                                       <archive>
+                                               <manifest>
+                                                       <mainClass>org.iotivity.cloud.mqserver.MessageQueueServer</mainClass>
+                                                       <addClasspath>true</addClasspath>
+                                                       <classpathPrefix>lib/</classpathPrefix>
+                                               </manifest>
+                                       </archive>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-dependency-plugin</artifactId>
+                               <executions>
+                                       <execution>
+                                               <id>copy-dependencies</id>
+                                               <phase>package</phase>
+                                               <goals>
+                                                       <goal>copy-dependencies</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                               <configuration>
+                                       <outputDirectory>target/lib</outputDirectory>
+                                       <overWriteIfNewer>true</overWriteIfNewer>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+
+</project>
\ No newline at end of file
diff --git a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/Constants.java b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/Constants.java
new file mode 100644 (file)
index 0000000..23d6318
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.mqserver;
+
+import org.iotivity.cloud.base.OCFConstants;
+
+public class Constants extends OCFConstants {
+
+    public static final String MQ_TOPIC                = "topic";
+    public static final String MQ_LOCATION             = "location";
+    public static final String MQ_TOPICLIST            = "topiclist";
+
+    public static final long   MIN_SEQ_NUM             = 5;
+    public static final long   MAX_SEQ_NUM             = 16777215;
+
+    // For Kafka
+    public static final int    KAFKA_SESSION_TIMEOUT   = 10000;
+    public static final int    KAFKA_CONNECT_TIMEOUT   = 10000;
+
+    public static final int    KAFKA_CONSUMMER_THREADS = 1;
+
+    public static final String KAFKA_COMMIT_INTERVAL   = "6000";
+
+}
\ No newline at end of file
diff --git a/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/MessageQueueServer.java b/cloud/messagequeue/src/main/java/org/iotivity/cloud/mqserver/MessageQueueServer.java
new file mode 100644 (file)
index 0000000..50dda52
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.mqserver;
+
+import java.net.InetSocketAddress;
+import java.util.Scanner;
+
+import org.iotivity.cloud.base.ServerSystem;
+import org.iotivity.cloud.base.server.CoapServer;
+import org.iotivity.cloud.mqserver.resources.MQBrokerResource;
+import org.iotivity.cloud.util.ErrorLogger;
+import org.iotivity.cloud.util.FileLogger;
+import org.iotivity.cloud.util.Logger;
+
+public class MessageQueueServer {
+
+    public static void main(String[] args) throws Exception {
+        System.setOut(FileLogger.createLoggingProxy(System.out));
+
+        System.out.println("-----MQ SERVER-----");
+
+        if (args.length != 6) {
+            Logger.e("coap server port, Kafka_zookeeper_Address port"
+                    + " and Kafka_broker_Address Port and TLS mode required\n"
+                    + "ex) 5686 127.0.0.1 2181 127.0.0.1 9092 0\n");
+
+            return;
+        }
+
+        ErrorLogger.Init();
+
+        ServerSystem serverSystem = new ServerSystem();
+
+        MQBrokerResource MQBroker = new MQBrokerResource();
+
+        String kafka_zookeeper = args[1] + ":" + args[2];
+        String kafka_broker = args[3] + ":" + args[4];
+        MQBroker.setKafkaInformation(kafka_zookeeper, kafka_broker);
+
+        serverSystem.addResource(MQBroker);
+
+        serverSystem.addServer(new CoapServer(
+                new InetSocketAddress(Integer.parseInt(args[0]))));
+
+        boolean tlsMode = Integer.parseInt(args[5]) == 1;
+
+        serverSystem.startSystem(tlsMode);
+
+        Scanner in = new Scanner(System.in, "UTF-8");
+
+        System.out.println("press 'q' to terminate");
+
+        while (!in.nextLine().equals("q"));
+
+        in.close();
+
+        System.out.println("Terminating...");
+
+        serverSystem.stopSystem();
+
+        System.out.println("Terminated");
+    }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..19ba50a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.mqserver;
+
+import java.util.HashMap;
+
+import org.iotivity.cloud.util.Cbor;
+import org.iotivity.cloud.util.Logger;
+
+public class MessageQueueUtils {
+
+    public static <T> T extractDataFromPayload(byte[] payload, String key) {
+
+        if (payload == null || key.isEmpty()) {
+            Logger.e("payload or key is empty");
+            return null;
+        }
+
+        Cbor<HashMap<String, T>> cbor = new Cbor<>();
+        HashMap<String, T> parsedData = null;
+
+        parsedData = cbor.parsePayloadFromCbor(payload, HashMap.class);
+
+        if (parsedData == null || parsedData.containsKey(key) == false) {
+            Logger.e("payload doesn't contain " + key + " information");
+            return null;
+        }
+
+        return parsedData.get(key);
+    }
+
+    public static <T> byte[] buildPayload(String key, T value) {
+
+        Cbor<HashMap<String, T>> cbor = new Cbor<>();
+
+        HashMap<String, T> map = new HashMap<>();
+        map.put(key, value);
+
+        return cbor.encodingPayloadToCbor(map);
+    }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..0e876bf
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.mqserver.kafka;
+
+import java.util.Properties;
+
+import kafka.admin.AdminUtils;
+import kafka.utils.ZKStringSerializer$;
+import kafka.utils.ZkUtils;
+
+import org.I0Itec.zkclient.ZkClient;
+import org.I0Itec.zkclient.ZkConnection;
+import org.iotivity.cloud.mqserver.Constants;
+import org.iotivity.cloud.util.Logger;
+
+public class KafkaCommonWrapper {
+
+    private ZkClient mZkClient = null;
+    private ZkUtils  mZkUtils  = null;
+
+    public KafkaCommonWrapper(String zookeeperAddress, String brokerAddress) {
+
+        mZkClient = new ZkClient(zookeeperAddress,
+                Constants.KAFKA_SESSION_TIMEOUT,
+                Constants.KAFKA_CONNECT_TIMEOUT, ZKStringSerializer$.MODULE$);
+
+        mZkUtils = new ZkUtils(mZkClient, new ZkConnection(zookeeperAddress),
+                false);
+    }
+
+    public boolean createTopic(String topic) {
+
+        Logger.d("kafka createTopic - " + topic);
+
+        topic = topic.replace('/', '.');
+
+        try {
+            // TODO check options - partitions, replicationFactor
+            AdminUtils.createTopic(mZkUtils, topic, 1, 1, new Properties());
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+
+        return true;
+    }
+
+    public boolean deleteTopic(String topic) {
+
+        Logger.d("kafka deleteTopic - " + topic);
+
+        topic = topic.replace('/', '.');
+
+        try {
+            AdminUtils.deleteTopic(mZkUtils, topic);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+
+        return true;
+    }
+
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..8c151c3
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.mqserver.kafka;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import kafka.admin.AdminUtils;
+import kafka.api.FetchRequest;
+import kafka.api.FetchRequestBuilder;
+import kafka.api.PartitionOffsetRequestInfo;
+import kafka.common.TopicAndPartition;
+import kafka.consumer.Consumer;
+import kafka.consumer.ConsumerConfig;
+import kafka.consumer.KafkaStream;
+import kafka.javaapi.FetchResponse;
+import kafka.javaapi.OffsetResponse;
+import kafka.javaapi.consumer.ConsumerConnector;
+import kafka.javaapi.consumer.SimpleConsumer;
+import kafka.javaapi.message.ByteBufferMessageSet;
+import kafka.message.MessageAndMetadata;
+import kafka.message.MessageAndOffset;
+import kafka.utils.ZKStringSerializer$;
+import kafka.utils.ZkUtils;
+
+import org.I0Itec.zkclient.ZkClient;
+import org.I0Itec.zkclient.ZkConnection;
+import org.iotivity.cloud.mqserver.Constants;
+import org.iotivity.cloud.mqserver.topic.Topic;
+import org.iotivity.cloud.util.Logger;
+
+public class KafkaConsumerWrapper {
+
+    private String            mTopicName         = null;
+
+    private String            mZookeeper         = null;
+    private String            mBroker            = null;
+
+    private ZkClient          mZkClient          = null;
+    private ZkUtils           mZkUtils           = null;
+
+    private ConsumerConnector mConsumerConnector = null;
+    private ExecutorService   mConsumerExecutor  = null;
+
+    private Topic             mInternalConsumer  = null;
+
+    private boolean           mConsumerStarted   = false;
+
+    public KafkaConsumerWrapper(String zookeeperAddress, String brokerAddress,
+            Topic consumer) {
+
+        mTopicName = consumer.getName().replace("/", ".");
+
+        mZookeeper = zookeeperAddress;
+        mBroker = brokerAddress;
+        mInternalConsumer = consumer;
+
+        mZkClient = new ZkClient(zookeeperAddress,
+                Constants.KAFKA_SESSION_TIMEOUT,
+                Constants.KAFKA_CONNECT_TIMEOUT, ZKStringSerializer$.MODULE$);
+
+        mZkUtils = new ZkUtils(mZkClient, new ZkConnection(zookeeperAddress),
+                false);
+    }
+
+    public boolean consumerStarted() {
+        return mConsumerStarted;
+    }
+
+    // TODO exception handling
+    public boolean subscribeTopic() {
+
+        Logger.d("kafka subscribeTopic - " + mTopicName);
+
+        if (mConsumerStarted == true) {
+            return true;
+        }
+
+        // remove consumer group info if already exist
+        List<String> subscribers = mZkClient.getChildren(ZkUtils
+                .ConsumersPath());
+
+        if (subscribers.contains(mTopicName)) {
+            AdminUtils.deleteConsumerGroupInZK(mZkUtils, mTopicName);
+        }
+
+        ConsumerConfig consumerConfig = new ConsumerConfig(
+                buildPropertiesForSubscribe());
+
+        mConsumerConnector = Consumer
+                .createJavaConsumerConnector(consumerConfig);
+
+        Map<String, Integer> topicCountMap = new HashMap<>();
+        topicCountMap.put(mTopicName, Constants.KAFKA_CONSUMMER_THREADS);
+
+        Map<String, List<KafkaStream<byte[], byte[]>>> consumerMap = mConsumerConnector
+                .createMessageStreams(topicCountMap);
+
+        List<KafkaStream<byte[], byte[]>> streams = consumerMap.get(mTopicName);
+
+        mConsumerExecutor = Executors
+                .newFixedThreadPool(Constants.KAFKA_CONSUMMER_THREADS);
+
+        for (final KafkaStream<byte[], byte[]> stream : streams) {
+
+            Logger.d("kafka subscribe complete");
+
+            mConsumerExecutor.execute(new Runnable() {
+
+                public void run() {
+
+                    for (final MessageAndMetadata<byte[], byte[]> messageAndMetadata : stream) {
+
+                        mInternalConsumer.onMessagePublished(messageAndMetadata
+                                .message());
+                    }
+                }
+            });
+        }
+
+        mConsumerStarted = true;
+
+        return true;
+    }
+
+    public boolean unsubscribeTopic() {
+
+        Logger.d("kafka unsubscribeTopic - " + mTopicName);
+
+        // remove consumer group info in zookeeper
+        List<String> subscribers = mZkClient.getChildren(ZkUtils
+                .ConsumersPath());
+
+        if (subscribers.contains(mTopicName)) {
+            AdminUtils.deleteConsumerGroupInZK(mZkUtils, mTopicName);
+        }
+
+        mConsumerExecutor.shutdown();
+        mConsumerConnector.shutdown();
+
+        mConsumerStarted = false;
+
+        return true;
+    }
+
+    public ArrayList<byte[]> getMessages() {
+
+        Logger.d("kafka get all messages - " + mTopicName);
+
+        String brokerHost = mBroker.substring(0, mBroker.indexOf(':'));
+        int brokerPort = Integer.parseInt(mBroker.substring(mBroker
+                .indexOf(':') + 1));
+
+        Logger.d("host " + brokerHost + ", port " + brokerPort);
+
+        // TODO check options - Timeout: Int, bufferSize: Int
+        SimpleConsumer simpleConsumer = new SimpleConsumer(brokerHost,
+                brokerPort, 100000, 64 * 1024, mTopicName);
+
+        long lastOffset = getLastOffset(simpleConsumer, mTopicName, 0,
+                kafka.api.OffsetRequest.EarliestTime(), mTopicName);
+
+        // TODO check option - fetch size
+        FetchRequest req = new FetchRequestBuilder().clientId(mTopicName)
+                .addFetch(mTopicName, 0, lastOffset, 100000).build();
+
+        FetchResponse fetchResponse = simpleConsumer.fetch(req);
+
+        if (fetchResponse == null || fetchResponse.hasError()) {
+
+            Logger.e("Error fetching data from the Broker");
+            return null;
+        }
+
+        ArrayList<byte[]> initialData = new ArrayList<>();
+
+        ByteBufferMessageSet messageSet = fetchResponse.messageSet(mTopicName,
+                0);
+
+        if (messageSet != null) {
+            for (MessageAndOffset messageAndOffset : messageSet) {
+
+                long currentOffset = messageAndOffset.offset();
+                if (currentOffset < lastOffset) {
+                    Logger.e("Found an old offset: " + currentOffset
+                            + " Expecting: " + lastOffset);
+                    continue;
+                }
+
+                lastOffset = messageAndOffset.nextOffset();
+                ByteBuffer payload = messageAndOffset.message().payload();
+
+                byte[] bytes = new byte[payload.limit()];
+                payload.get(bytes);
+
+                initialData.add(bytes);
+            }
+        }
+
+        simpleConsumer.close();
+
+        Logger.d("kafka get all messages complete");
+
+        return initialData;
+    }
+
+    private Properties buildPropertiesForSubscribe() {
+
+        // TODO check property settings
+        Properties props = new Properties();
+
+        props.put("group.id", mTopicName);
+        props.put("zookeeper.connect", mZookeeper);
+        props.put("enable.auto.commit", "true");
+        props.put("auto.commit.interval.ms", Constants.KAFKA_COMMIT_INTERVAL);
+
+        return props;
+    }
+
+    private long getLastOffset(SimpleConsumer consumer, String topic,
+            int partition, long whichTime, String clientName) {
+
+        TopicAndPartition topicAndPartition = new TopicAndPartition(topic,
+                partition);
+
+        Map<TopicAndPartition, PartitionOffsetRequestInfo> requestInfo = new HashMap<>();
+        requestInfo.put(topicAndPartition, new PartitionOffsetRequestInfo(
+                whichTime, 1));
+
+        kafka.javaapi.OffsetRequest request = new kafka.javaapi.OffsetRequest(
+                requestInfo, kafka.api.OffsetRequest.CurrentVersion(),
+                clientName);
+
+        OffsetResponse response = consumer.getOffsetsBefore(request);
+
+        if (response == null || response.hasError()) {
+            Logger.e("Error fetching data Offset Data the Broker");
+            return 0;
+        }
+
+        long[] offsets = response.offsets(topic, partition);
+        return offsets[0];
+    }
+
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..903f046
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.mqserver.kafka;
+
+import java.util.Properties;
+
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.Producer;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.iotivity.cloud.util.Logger;
+
+public class KafkaProducerWrapper {
+
+    private String                   mTopicName = null;
+    private String                   mBroker    = null;
+
+    private Producer<byte[], byte[]> mProducer  = null;
+
+    public KafkaProducerWrapper(String brokerAddress, String topic) {
+
+        mTopicName = topic.replace("/", ".");
+
+        mBroker = brokerAddress;
+
+        mProducer = new KafkaProducer<>(buildPropertiesForPublish());
+    }
+
+    // TODO handle exception
+    public boolean publishMessage(byte[] message) {
+
+        Logger.d("kafka publishMessage - " + mTopicName);
+
+        ProducerRecord<byte[], byte[]> record = new ProducerRecord<>(
+                mTopicName, message);
+
+        mProducer.send(record);
+        mProducer.flush();
+
+        return true;
+    }
+
+    private Properties buildPropertiesForPublish() {
+
+        // TODO check property settings
+        Properties props = new Properties();
+
+        props.put("bootstrap.servers", mBroker);
+        props.put("acks", "all");
+        props.put("retries", 0);
+        props.put("batch.size", 16384);
+        props.put("linger.ms", 1);
+        props.put("buffer.memory", 33554432);
+        props.put("key.serializer",
+                "org.apache.kafka.common.serialization.ByteArraySerializer");
+        props.put("value.serializer",
+                "org.apache.kafka.common.serialization.ByteArraySerializer");
+
+        return props;
+    }
+
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..a137f75
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.mqserver.resources;
+
+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;
+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.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.base.resource.Resource;
+import org.iotivity.cloud.mqserver.Constants;
+import org.iotivity.cloud.mqserver.MessageQueueUtils;
+import org.iotivity.cloud.mqserver.topic.Topic;
+import org.iotivity.cloud.mqserver.topic.TopicManager;
+
+public class MQBrokerResource extends Resource {
+
+    private TopicManager mTopicManager = new TopicManager();
+
+    public MQBrokerResource() {
+        super(Arrays.asList(Constants.PREFIX_OIC, Constants.MQ_BROKER_URI));
+
+        // addQueryHandler(Arrays.asList("if=" + Constants.INTERFACE_DEFAULT),
+        // this::onDefaultInterfaceReceived);
+    }
+
+    public void setKafkaInformation(String zookeeper, String broker) {
+        mTopicManager.setKafkaInformation(zookeeper, broker);
+    }
+
+    @Override
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
+
+        IResponse response = null;
+
+        switch (request.getMethod()) {
+            case GET:
+                response = handleGetRequest(srcDevice, request);
+                break;
+            case PUT:
+                response = handlePutRequest(request);
+                break;
+            case POST:
+                response = handlePostRequest(request);
+                break;
+            case DELETE:
+                response = handleDeleteRequest(request);
+                break;
+        }
+
+        srcDevice.sendResponse(response);
+    }
+
+    // DISCOVER, READ, SUBSCRIBE, UNSUBSCRIBE
+    private IResponse handleGetRequest(Device srcDevice, IRequest request) {
+
+        // DISCOVER
+        if (request.getUriPathSegments().size() == getUriPathSegments()
+                .size()) {
+            return discoverTopic(request);
+        }
+
+        switch (request.getObserve()) {
+            case NOTHING:
+                return readMessage(request);
+
+            case SUBSCRIBE:
+                return subscribeTopic(srcDevice, request);
+
+            case UNSUBSCRIBE:
+                return unsubscribeTopic(request);
+
+            default:
+                break;
+        }
+
+        return MessageBuilder.createResponse(request,
+                ResponseStatus.BAD_REQUEST);
+    }
+
+    // PUBLISH
+    private IResponse handlePutRequest(IRequest request) {
+
+        return publishMessage(request);
+    }
+
+    // CREATE topic
+    private IResponse handlePostRequest(IRequest request) {
+
+        return createTopic(request);
+    }
+
+    // REMOVE topic
+    private IResponse handleDeleteRequest(IRequest request) {
+
+        return removeTopic(request);
+    }
+
+    private IResponse createTopic(IRequest request) {
+
+        String uriPath = request.getUriPath();
+
+        // main topic creation request
+        if (request.getUriPathSegments().size() == getUriPathSegments()
+                .size()) {
+            return createMainTopic(request);
+        }
+
+        // subtopic creation request
+        Topic targetTopic = mTopicManager.getTopic(uriPath);
+
+        if (targetTopic == null) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        return targetTopic.handleCreateSubtopic(request);
+    }
+
+    private IResponse removeTopic(IRequest request) {
+
+        String uriPath = request.getUriPath();
+
+        String parentName = uriPath.substring(0, uriPath.lastIndexOf('/'));
+        String targetName = request.getUriPathSegments()
+                .get(request.getUriPathSegments().size() - 1);
+
+        // main topic removal request
+        if (request.getUriPathSegments().size() - 1 == getUriPathSegments()
+                .size()) {
+            return removeMainTopic(request);
+        }
+
+        // subtopic removal request
+        Topic parentTopic = mTopicManager.getTopic(parentName);
+
+        if (parentTopic == null) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        return parentTopic.handleRemoveSubtopic(request, targetName);
+    }
+
+    private IResponse subscribeTopic(Device srcDevice, IRequest request) {
+
+        Topic topic = mTopicManager.getTopic(request.getUriPath());
+
+        if (topic == null) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        return topic.handleSubscribeTopic(srcDevice, request);
+    }
+
+    private IResponse unsubscribeTopic(IRequest request) {
+
+        Topic topic = mTopicManager.getTopic(request.getUriPath());
+
+        if (topic == null) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        return topic.handleUnsubscribeTopic(request);
+    }
+
+    private IResponse publishMessage(IRequest request) {
+
+        Topic topic = mTopicManager.getTopic(request.getUriPath());
+
+        if (topic == null) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        return topic.handlePublishMessage(request);
+    }
+
+    private IResponse readMessage(IRequest request) {
+
+        Topic topic = mTopicManager.getTopic(request.getUriPath());
+
+        if (topic == null) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        return topic.handleReadMessage(request);
+    }
+
+    private IResponse discoverTopic(IRequest request) {
+
+        ArrayList<String> topicList = null;
+
+        HashMap<String, List<String>> query = request.getUriQueryMap();
+
+        if (query != null && query.containsKey("rt")) {
+
+            topicList = mTopicManager
+                    .getTopicListByType(query.get("rt").get(0));
+        } else {
+
+            topicList = mTopicManager.getTopicList();
+        }
+
+        return MessageBuilder.createResponse(request, ResponseStatus.CONTENT,
+                ContentFormat.APPLICATION_CBOR, MessageQueueUtils
+                        .buildPayload(Constants.MQ_TOPICLIST, topicList));
+    }
+
+    private IResponse createMainTopic(IRequest request) {
+
+        String topicName = MessageQueueUtils.extractDataFromPayload(
+                request.getPayload(), Constants.MQ_TOPIC);
+
+        String type = new String();
+
+        if (request.getUriQueryMap() != null) {
+            type = request.getUriQueryMap().get("rt").get(0);
+        }
+
+        if (topicName == null) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        topicName = "/" + Constants.PREFIX_OIC + "/" + Constants.MQ_BROKER_URI
+                + "/" + topicName;
+
+        if (mTopicManager.getTopic(topicName) != null) {
+            // Topic already exists
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        Topic newTopic = new Topic(topicName, type, mTopicManager);
+
+        if (mTopicManager.createTopic(newTopic) == false) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.INTERNAL_SERVER_ERROR);
+        }
+
+        return MessageBuilder.createResponse(request, ResponseStatus.CREATED,
+                ContentFormat.APPLICATION_CBOR, MessageQueueUtils.buildPayload(
+                        Constants.MQ_LOCATION, newTopic.getName()));
+    }
+
+    private IResponse removeMainTopic(IRequest request) {
+
+        String topicName = request.getUriPath();
+
+        Topic targetTopic = mTopicManager.getTopic(topicName);
+
+        // TODO check error
+        if (targetTopic == null) {
+            // Topic doesn't exist
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        if (mTopicManager.removeTopic(targetTopic) == false) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.INTERNAL_SERVER_ERROR);
+        }
+
+        return MessageBuilder.createResponse(request, ResponseStatus.DELETED);
+    }
+}
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
new file mode 100644 (file)
index 0000000..3b004c1
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.mqserver.topic;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.iotivity.cloud.base.device.Device;
+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.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.mqserver.Constants;
+import org.iotivity.cloud.mqserver.MessageQueueUtils;
+import org.iotivity.cloud.mqserver.kafka.KafkaConsumerWrapper;
+import org.iotivity.cloud.mqserver.kafka.KafkaProducerWrapper;
+
+public class Topic {
+
+    private TopicManager           mTopicManager = null;
+
+    private String                 mName         = null;
+    private String                 mType         = null;
+    private HashMap<String, Topic> mSubtopics    = null;
+
+    private byte[]                 mLatestData   = null;
+
+    private class TopicSubscriber {
+        TopicSubscriber(Device subscriber, IRequest request) {
+            mSubscriber = subscriber;
+            mRequest = request;
+        }
+
+        public Device   mSubscriber;
+        public IRequest mRequest;
+    }
+
+    private HashMap<String, TopicSubscriber> mSubscribers           = null;
+
+    private KafkaProducerWrapper             mKafkaProducerOperator = null;
+    private KafkaConsumerWrapper             mKafkaConsumerOperator = null;
+
+    public Topic(String name, String type, TopicManager topicManager) {
+
+        mTopicManager = topicManager;
+        mName = name;
+        mType = type;
+
+        mSubtopics = new HashMap<>();
+        mSubscribers = new HashMap<>();
+
+        String kafka_zookeeper = topicManager.getKafkaZookeeper();
+        String kafka_broker = topicManager.getKafkaBroker();
+
+        mKafkaProducerOperator = new KafkaProducerWrapper(kafka_broker, name);
+        mKafkaConsumerOperator = new KafkaConsumerWrapper(kafka_zookeeper,
+                kafka_broker, this);
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    public String getType() {
+        return mType;
+    }
+
+    public IResponse handleCreateSubtopic(IRequest request) {
+
+        String newTopicName = MessageQueueUtils.extractDataFromPayload(
+                request.getPayload(), Constants.MQ_TOPIC);
+
+        String newTopicType = new String();
+
+        if (request.getUriQueryMap() != null) {
+            newTopicType = request.getUriQueryMap().get("rt").get(0);
+        }
+
+        if (newTopicName == null) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        if (getSubtopic(newTopicName) != null) {
+            // topic already exists
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        Topic newTopic = new Topic(mName + "/" + newTopicName, newTopicType,
+                mTopicManager);
+
+        if (mTopicManager.createTopic(newTopic) == false) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.INTERNAL_SERVER_ERROR);
+        }
+
+        mSubtopics.put(newTopicName, newTopic);
+
+        return MessageBuilder.createResponse(
+                request,
+                ResponseStatus.CREATED,
+                ContentFormat.APPLICATION_CBOR,
+                MessageQueueUtils.buildPayload(Constants.MQ_LOCATION,
+                        newTopic.getName()));
+    }
+
+    public IResponse handleRemoveSubtopic(IRequest request, String topicName) {
+
+        Topic targetTopic = getSubtopic(topicName);
+
+        // TODO check error
+        if (targetTopic == null) {
+            // topic doesn't exist
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.BAD_REQUEST);
+        }
+
+        if (mTopicManager.removeTopic(targetTopic) == false) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.INTERNAL_SERVER_ERROR);
+        }
+
+        mSubtopics.remove(topicName);
+
+        return MessageBuilder.createResponse(request, ResponseStatus.DELETED);
+    }
+
+    public IResponse handleSubscribeTopic(Device srcDevice, IRequest request) {
+
+        // get latest data from kafka if cosumer started for the first time
+        if (mKafkaConsumerOperator.consumerStarted() == false) {
+
+            ArrayList<byte[]> data = mKafkaConsumerOperator.getMessages();
+
+            if (data != null && !data.isEmpty()) {
+                mLatestData = data.get(data.size() - 1);
+            }
+        }
+
+        if (mKafkaConsumerOperator.subscribeTopic() == false) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.INTERNAL_SERVER_ERROR);
+        }
+
+        synchronized (mSubscribers) {
+            mSubscribers.put(request.getRequestId(), new TopicSubscriber(
+                    srcDevice, request));
+        }
+
+        return MessageBuilder.createResponse(request, ResponseStatus.CONTENT,
+                ContentFormat.APPLICATION_CBOR, mLatestData);
+    }
+
+    public IResponse handleUnsubscribeTopic(IRequest request) {
+
+        synchronized (mSubscribers) {
+
+            TopicSubscriber subscriber = mSubscribers.get(request
+                    .getRequestId());
+
+            if (subscriber == null) {
+                // client is not a subscriber
+                return MessageBuilder.createResponse(request,
+                        ResponseStatus.BAD_REQUEST);
+            }
+
+            mSubscribers.remove(subscriber.mRequest.getRequestId());
+
+            // if there's no more subscriber, stop subscribing topic
+            // with kafka consumer
+            if (mSubscribers.isEmpty()) {
+                mKafkaConsumerOperator.unsubscribeTopic();
+            }
+        }
+
+        return MessageBuilder.createResponse(request, ResponseStatus.CONTENT,
+                ContentFormat.APPLICATION_CBOR, mLatestData);
+    }
+
+    public IResponse handlePublishMessage(IRequest request) {
+        byte[] data = request.getPayload();
+
+        if (mKafkaProducerOperator.publishMessage(data) == false) {
+            return MessageBuilder.createResponse(request,
+                    ResponseStatus.INTERNAL_SERVER_ERROR);
+        }
+
+        return MessageBuilder.createResponse(request, ResponseStatus.CHANGED);
+    }
+
+    public IResponse handleReadMessage(IRequest request) {
+        // if consumer is not started, get data from kafka broker
+        if (mKafkaConsumerOperator.consumerStarted() == false) {
+
+            ArrayList<byte[]> data = mKafkaConsumerOperator.getMessages();
+
+            if (data != null && !data.isEmpty()) {
+                mLatestData = data.get(data.size() - 1);
+            }
+        }
+
+        return MessageBuilder.createResponse(request, ResponseStatus.CONTENT,
+                ContentFormat.APPLICATION_CBOR, mLatestData);
+    }
+
+    // callback from Kafka Consumer
+    public void onMessagePublished(byte[] message) {
+
+        mLatestData = message;
+
+        notifyPublishedMessage();
+    }
+
+    // TODO check
+    private Topic getSubtopic(String topicName) {
+
+        if (mSubtopics.containsKey(topicName) == false) {
+            return null;
+        }
+
+        return mSubtopics.get(topicName);
+    }
+
+    private void notifyPublishedMessage() {
+        synchronized (mSubscribers) {
+            for (TopicSubscriber subscriber : mSubscribers.values()) {
+                subscriber.mSubscriber.sendResponse(MessageBuilder
+                        .createResponse(subscriber.mRequest,
+                                ResponseStatus.CONTENT,
+                                ContentFormat.APPLICATION_CBOR, mLatestData));
+            }
+        }
+    }
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..c36a510
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * //******************************************************************
+ * //
+ * // 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.mqserver.topic;
+
+import java.util.ArrayList;
+
+import org.iotivity.cloud.mqserver.kafka.KafkaCommonWrapper;
+
+public class TopicManager {
+
+    private ArrayList<Topic>   mTopics              = new ArrayList<>();
+
+    // for Kafka
+    String                     mKafkaZookeeper      = null;
+    String                     mKafkaBroker         = null;
+
+    private KafkaCommonWrapper mKafkaCommonOperator = null;
+
+    public boolean createTopic(Topic topic) {
+
+        if (mKafkaCommonOperator.createTopic(topic.getName()) == false) {
+            return false;
+        }
+
+        synchronized (mTopics) {
+            mTopics.add(topic);
+        }
+
+        return true;
+    }
+
+    public boolean removeTopic(Topic topic) {
+
+        return removeTopics(topic.getName());
+    }
+
+    public ArrayList<String> getTopicList() {
+
+        ArrayList<String> topicList = new ArrayList<>();
+
+        synchronized (mTopics) {
+            for (Topic topic : mTopics) {
+                topicList.add(topic.getName());
+            }
+        }
+
+        return topicList;
+    }
+
+    public ArrayList<String> getTopicListByType(String type) {
+
+        ArrayList<String> topicList = new ArrayList<>();
+
+        synchronized (mTopics) {
+
+            for (Topic topic : mTopics) {
+                if (type.equals(topic.getType())) {
+                    topicList.add(topic.getName());
+                }
+            }
+        }
+
+        return topicList;
+    }
+
+    public Topic getTopic(String topicName) {
+
+        Topic foundTopic = null;
+
+        synchronized (mTopics) {
+
+            for (Topic topic : mTopics) {
+                if (topicName.equals(topic.getName())) {
+                    foundTopic = topic;
+                    break;
+                }
+            }
+        }
+
+        return foundTopic;
+    }
+
+    public void setKafkaInformation(String zookeeper, String broker) {
+        mKafkaZookeeper = zookeeper;
+        mKafkaBroker = broker;
+
+        mKafkaCommonOperator = new KafkaCommonWrapper(zookeeper, broker);
+    }
+
+    public String getKafkaZookeeper() {
+        return mKafkaZookeeper;
+    }
+
+    public String getKafkaBroker() {
+        return mKafkaBroker;
+    }
+
+    private boolean removeTopics(String topicName) {
+
+        synchronized (mTopics) {
+
+            for (Topic topic : new ArrayList<>(mTopics)) {
+
+                if (topic.getName().startsWith(topicName)) {
+
+                    if (mKafkaCommonOperator.deleteTopic(topic.getName()) == false) {
+                        return false;
+                    }
+
+                    mTopics.remove(topic);
+                }
+ &n