Add SimpleClientServer App.
authorLarry Sachs <larry.j.sachs@intel.com>
Mon, 9 Jan 2017 01:00:38 +0000 (17:00 -0800)
committerRick Bell <richard.s.bell@intel.com>
Mon, 9 Jan 2017 19:29:50 +0000 (19:29 +0000)
Combines SimpleServer and SimpleClient into a single app.
If there are errors, return code is non-zero.

To build:
$ scons TARGET_TRANSPORT=IP SECURED=0 RELEASE=1 BUILD_JAVA=ON

To run:
$ export LD_LIBRARY_PATH="<iotivity>/out/linux/x86_64/release/"
$ java -cp java/examples-java/simpleclientserver/build/libs/simpleclientserver.jar:\
java/iotivity-linux/build/libs/iotivity-linux.jar org.iotivity.base.examples.SimpleClientServer ;\
echo result code = $?

Change-Id: I8f4bcd04ecd41518694b1e9901b7dcc84da4c6fd
Signed-off-by: Larry Sachs <larry.j.sachs@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/16239
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: George Nash <george.nash@intel.com>
Reviewed-by: Rick Bell <richard.s.bell@intel.com>
java/examples-java/settings.gradle
java/examples-java/simpleclientserver/.gitignore [new file with mode: 0644]
java/examples-java/simpleclientserver/build.gradle [new file with mode: 0644]
java/examples-java/simpleclientserver/src/main/assets/oic_svr_db_client.json [new file with mode: 0644]
java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/ServerLight.java [new file with mode: 0644]
java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleClient.java [new file with mode: 0644]
java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleClientServer.java [new file with mode: 0644]
java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleLight.java [new file with mode: 0644]
java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleServer.java [new file with mode: 0644]

index 126def3..2c00535 100755 (executable)
@@ -1 +1 @@
-include ':simpleserver', ':simpleclient'//, ':fridgeserver', ':fridgeclient', ':guiclient', ':provisioningclient', ':presenceserver', ':presenceclient', ':devicediscoveryclient', ':devicediscoveryserver', ':groupclient', ':groupserver', ':fridgegroupclient', ':fridgegroupserver'
+include ':simpleserver', ':simpleclient', ':simpleclientserver'//, ':fridgeserver', ':fridgeclient', ':guiclient', ':provisioningclient', ':presenceserver', ':presenceclient', ':devicediscoveryclient', ':devicediscoveryserver', ':groupclient', ':groupserver', ':fridgegroupclient', ':fridgegroupserver'
diff --git a/java/examples-java/simpleclientserver/.gitignore b/java/examples-java/simpleclientserver/.gitignore
new file mode 100644 (file)
index 0000000..3543521
--- /dev/null
@@ -0,0 +1 @@
+/build\r
diff --git a/java/examples-java/simpleclientserver/build.gradle b/java/examples-java/simpleclientserver/build.gradle
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/java/examples-java/simpleclientserver/src/main/assets/oic_svr_db_client.json b/java/examples-java/simpleclientserver/src/main/assets/oic_svr_db_client.json
new file mode 100644 (file)
index 0000000..c16acb8
--- /dev/null
@@ -0,0 +1,50 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad",
+                "/oic/sec/acl"
+                       ],
+                       "perms": 2,
+                       "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat"
+             ],
+             "perms": 2,
+             "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+        }
+       ],
+       "pstat":        {
+               "isop": true,
+               "deviceid":     "ZGV2aWNlaWQAAAAAABhanw==",
+               "ch": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "sct": 1,
+               "owned": true,
+               "deviceid":     "MjIyMjIyMjIyMjIyMjIyMg==",
+               "ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
+       },
+    "cred":    [{
+               "credid": 1,
+               "sub": "MTExMTExMTExMTExMTExMQ==",
+               "credtyp": 1,
+               "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
+        "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+       }]
+}
diff --git a/java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/ServerLight.java b/java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/ServerLight.java
new file mode 100644 (file)
index 0000000..baef3f6
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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.base.examples;
+
+import org.iotivity.base.EntityHandlerResult;
+import org.iotivity.base.ErrorCode;
+import org.iotivity.base.ObservationInfo;
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.OcRepresentation;
+import org.iotivity.base.OcResource;
+import org.iotivity.base.OcResourceHandle;
+import org.iotivity.base.OcResourceRequest;
+import org.iotivity.base.OcResourceResponse;
+import org.iotivity.base.RequestHandlerFlag;
+import org.iotivity.base.RequestType;
+import org.iotivity.base.ResourceProperty;
+
+import java.util.EnumSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * ServerLight
+ * <p/>
+ * This class represents a server light resource.
+ */
+public class ServerLight extends SimpleLight implements OcPlatform.EntityHandler {
+
+    private static final String TAG = ServerLight.class.getSimpleName();
+
+    public static final String DEFAULT_RESOURCE_URI = "/a/light";
+    public static final String DEFAULT_RESOURCE_NAME = "John's light";
+
+    private SimpleServer mServer; // server
+    private String mResourceUri; // resource URI
+    private String mResourceTypeName; // resource type name
+    private String mResourceInterface; // resource interface
+    private OcResourceHandle mResourceHandle; // resource handle
+
+    private Thread mObserverNotifier;
+
+    public ServerLight(SimpleServer server, String resourceUri, String name, boolean state, int power) {
+        mServer = server;
+        mResourceUri = resourceUri;
+        mResourceTypeName = SimpleLight.RESOURCE_TYPE;
+        mResourceInterface = OcPlatform.DEFAULT_INTERFACE;
+        mResourceHandle = null; // this is set when resource is registered
+
+        setName(name);
+        setState(state);
+        setPower(power);
+    }
+
+    public synchronized void registerResource() throws OcException {
+        if (null == mResourceHandle) {
+            mResourceHandle = OcPlatform.registerResource(mResourceUri, mResourceTypeName, mResourceInterface, this,
+                    EnumSet.of(ResourceProperty.DISCOVERABLE, ResourceProperty.OBSERVABLE));
+        }
+    }
+
+    /**
+     * NOTE: This is just a sample implementation of entity handler. Entity
+     * handler can be implemented in several ways by the manufacturer.
+     */
+    @Override
+    public synchronized EntityHandlerResult handleEntity(final OcResourceRequest request) {
+        EntityHandlerResult ehResult = EntityHandlerResult.ERROR;
+        if (null == request) {
+            msg("Server request is invalid");
+            return ehResult;
+        }
+        // Get the request flags
+        EnumSet<RequestHandlerFlag> requestFlags = request.getRequestHandlerFlagSet();
+        if (requestFlags.contains(RequestHandlerFlag.INIT)) {
+            msg("\t\tRequest Flag: Init");
+            ehResult = EntityHandlerResult.OK;
+        }
+        if (requestFlags.contains(RequestHandlerFlag.REQUEST)) {
+            msg("\t\tRequest Flag: Request");
+            ehResult = handleRequest(request);
+        }
+        if (requestFlags.contains(RequestHandlerFlag.OBSERVER)) {
+            msg("\t\tRequest Flag: Observer");
+            ehResult = handleObserver(request);
+        }
+        return ehResult;
+    }
+
+    private EntityHandlerResult handleRequest(OcResourceRequest request) {
+        EntityHandlerResult ehResult = EntityHandlerResult.ERROR;
+        // Check for query params (if any)
+        Map<String, String> queries = request.getQueryParameters();
+        if (!queries.isEmpty()) {
+            msg("Query processing is up to entityHandler");
+        } else {
+            msg("No query parameters in this request");
+        }
+
+        for (Map.Entry<String, String> entry : queries.entrySet()) {
+            msg("Query key: " + entry.getKey() + " value: " + entry.getValue());
+        }
+
+        // Get the request type
+        RequestType requestType = request.getRequestType();
+        switch (requestType) {
+        case GET:
+            msg("\t\t\tRequest Type is GET");
+            ehResult = handleGetRequest(request);
+            break;
+        case PUT:
+            msg("\t\t\tRequest Type is PUT");
+            ehResult = handlePutRequest(request);
+            break;
+        case POST:
+            msg("\t\t\tRequest Type is POST");
+            ehResult = handlePostRequest(request);
+            break;
+        case DELETE:
+            msg("\t\t\tRequest Type is DELETE");
+            ehResult = handleDeleteRequest();
+            break;
+        }
+        return ehResult;
+    }
+
+    private EntityHandlerResult handleGetRequest(final OcResourceRequest request) {
+        EntityHandlerResult ehResult;
+        OcResourceResponse response = new OcResourceResponse();
+        response.setRequestHandle(request.getRequestHandle());
+        response.setResourceHandle(request.getResourceHandle());
+
+        response.setResponseResult(EntityHandlerResult.OK);
+        response.setResourceRepresentation(getOcRepresentation());
+        ehResult = sendResponse(response);
+        return ehResult;
+    }
+
+    private EntityHandlerResult handlePutRequest(OcResourceRequest request) {
+        OcResourceResponse response = new OcResourceResponse();
+        response.setRequestHandle(request.getRequestHandle());
+        response.setResourceHandle(request.getResourceHandle());
+
+        setOcRepresentation(request.getResourceRepresentation());
+        response.setResourceRepresentation(getOcRepresentation());
+        response.setResponseResult(EntityHandlerResult.OK);
+        return sendResponse(response);
+    }
+
+    private int sUriCounter = 1;
+
+    private EntityHandlerResult handlePostRequest(OcResourceRequest request) {
+        OcResourceResponse response = new OcResourceResponse();
+        response.setRequestHandle(request.getRequestHandle());
+        response.setResourceHandle(request.getResourceHandle());
+        String newUri = DEFAULT_RESOURCE_URI + "/" + (++sUriCounter);
+        mServer.createNewLightResource(newUri, DEFAULT_RESOURCE_NAME + " " + sUriCounter);
+        OcRepresentation rep_post = getOcRepresentation();
+        try {
+            rep_post.setValue(OcResource.CREATED_URI_KEY, newUri);
+        } catch (OcException e) {
+            msgError(TAG, e.toString());
+        }
+        response.setResourceRepresentation(rep_post);
+        response.setNewResourceUri(newUri);
+        response.setResponseResult(EntityHandlerResult.RESOURCE_CREATED);
+        return sendResponse(response);
+    }
+
+    private EntityHandlerResult handleDeleteRequest() {
+        try {
+            unregisterResource();
+            return EntityHandlerResult.RESOURCE_DELETED;
+        } catch (OcException e) {
+            msgError(TAG, e.toString());
+            msg("Failed to unregister a light resource");
+            return EntityHandlerResult.ERROR;
+        }
+    }
+
+    private List<Byte> mObservationIds = new LinkedList<>();
+
+    private EntityHandlerResult handleObserver(final OcResourceRequest request) {
+        ObservationInfo observationInfo = request.getObservationInfo();
+        switch (observationInfo.getObserveAction()) {
+        case REGISTER:
+            mObservationIds.add(observationInfo.getOcObservationId());
+            break;
+        case UNREGISTER:
+            mObservationIds.remove((Byte) observationInfo.getOcObservationId());
+            break;
+        }
+        // Observation happens on a different thread in notifyObservers method.
+        // If we have not created the thread already, we will create one here.
+        if (null == mObserverNotifier) {
+            mObserverNotifier = new Thread(new Runnable() {
+                public void run() {
+                    notifyObservers(request);
+                }
+            });
+            mObserverNotifier.start();
+        }
+        return EntityHandlerResult.OK;
+    }
+
+    private void notifyObservers(OcResourceRequest request) {
+        while (true) {
+            // increment current power value by 10 every 2 seconds
+            setPower(getPower() + 10);
+            sleep(2);
+
+            msg("Notifying observers...");
+            msg(toString());
+            try {
+                OcPlatform.notifyAllObservers(mResourceHandle);
+            } catch (OcException e) {
+                ErrorCode errorCode = e.getErrorCode();
+                if (ErrorCode.NO_OBSERVERS == errorCode) {
+                    msg("No more observers, stopping notifications");
+                }
+                return;
+            }
+        }
+    }
+
+    private EntityHandlerResult sendResponse(OcResourceResponse response) {
+        try {
+            OcPlatform.sendResponse(response);
+            return EntityHandlerResult.OK;
+        } catch (OcException e) {
+            msgError(TAG, e.toString());
+            msg("Failed to send response");
+            return EntityHandlerResult.ERROR;
+        }
+    }
+
+    public synchronized void unregisterResource() throws OcException {
+        if (null != mResourceHandle) {
+            OcPlatform.unregisterResource(mResourceHandle);
+        }
+    }
+
+    public void setOcRepresentation(OcRepresentation rep) {
+        try {
+            if (rep.hasAttribute(NAME_KEY))
+                setName((String) rep.getValue(NAME_KEY));
+            if (rep.hasAttribute(STATE_KEY))
+                setState((boolean) rep.getValue(STATE_KEY));
+            if (rep.hasAttribute(POWER_KEY))
+                setPower((int) rep.getValue(POWER_KEY));
+        } catch (OcException e) {
+            msgError(TAG, e.toString());
+            msg("Failed to get representation values");
+        }
+    }
+
+    public OcRepresentation getOcRepresentation() {
+        OcRepresentation rep = new OcRepresentation();
+        try {
+            rep.setValue(NAME_KEY, getName());
+            rep.setValue(STATE_KEY, getState());
+            rep.setValue(POWER_KEY, getPower());
+        } catch (OcException e) {
+            msgError(TAG, e.toString());
+            msg("Failed to set representation values");
+        }
+        return rep;
+    }
+
+    // ******************************************************************************
+    // End of the OIC specific code
+    // ******************************************************************************
+
+    @Override
+    public String toString() {
+        return "\t" + "URI" + ": " + mResourceUri + "\n\t" + NAME_KEY + ": " + getName() + "\n\t" + STATE_KEY + ": "
+                + getState() + "\n\t" + POWER_KEY + ": " + getPower();
+    }
+
+    private void sleep(int seconds) {
+        try {
+            Thread.sleep(seconds * 1000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+            msgError(TAG, e.toString());
+        }
+    }
+
+    private void msg(String text) {
+        mServer.msg(text);
+    }
+
+    private void msgError(String tag, String text) {
+        mServer.msgError(tag, text);
+    }
+}
diff --git a/java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleClient.java b/java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleClient.java
new file mode 100644 (file)
index 0000000..6ab4517
--- /dev/null
@@ -0,0 +1,536 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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.base.examples;
+
+import org.iotivity.base.ErrorCode;
+import org.iotivity.base.ObserveType;
+import org.iotivity.base.OcConnectivityType;
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcHeaderOption;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.OcRepresentation;
+import org.iotivity.base.OcResource;
+import org.iotivity.base.OcResourceIdentifier;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * SimpleClient
+ * <p/>
+ * SimpleClient is a sample client app which should be started after the
+ * SimpleServer is started. It finds resources advertised by the server and
+ * calls different operations on it (GET, PUT, POST, DELETE and OBSERVE).
+ */
+public class SimpleClient implements OcPlatform.OnResourceFoundListener, OcResource.OnGetListener,
+        OcResource.OnPutListener, OcResource.OnPostListener, OcResource.OnObserveListener {
+
+    private Map<OcResourceIdentifier, OcResource> mFoundResources = new HashMap<>();
+    private OcResource mFoundLightResource;
+    private boolean isDone;
+    private Object mWaitLock;
+    // local representation of a client's light resource
+    private SimpleLight mLight = new SimpleLight();
+
+    public SimpleClient(Object waitLock) {
+        mWaitLock = waitLock;
+
+        try {
+            msg("Finding all resources of type \""+SimpleLight.RESOURCE_TYPE+"\".");
+            String requestUri = OcPlatform.WELL_KNOWN_QUERY + "?rt="+SimpleLight.RESOURCE_TYPE;
+            OcPlatform.findResource("", requestUri, EnumSet.of(OcConnectivityType.CT_DEFAULT), this);
+
+            /*
+             * Find resource is done twice so that we discover the original
+             * resources a second time. These resources will have the same
+             * unique identifier (yet be different objects), so that we can
+             * verify/show the duplicate-checking code in foundResource(above);
+             */
+            msg("Finding all resources of type \""+SimpleLight.RESOURCE_TYPE+"\" for the second time");
+            OcPlatform.findResource("", requestUri, EnumSet.of(OcConnectivityType.CT_DEFAULT), this);
+
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Failed to invoke find resource API");
+        }
+
+        printLine();
+    }
+
+    public boolean isRunning() {
+        return !isDone;
+    }
+
+    /**
+     * An event handler to be executed whenever a "findResource" request
+     * completes successfully
+     *
+     * @param ocResource
+     *            found resource
+     */
+    @Override
+    public synchronized void onResourceFound(OcResource ocResource) {
+        if (null == ocResource) {
+            msg("Found resource is invalid");
+            return;
+        }
+
+        if (mFoundResources.containsKey(ocResource.getUniqueIdentifier())) {
+            msg("Found a previously seen resource again!");
+        } else {
+            msg("Found resource for the first time on server with ID: " + ocResource.getServerId());
+            mFoundResources.put(ocResource.getUniqueIdentifier(), ocResource);
+        }
+
+        if (null != mFoundLightResource) {
+            msg("Found another resource, ignoring");
+            return;
+        }
+
+        // Get the resource URI
+        String resourceUri = ocResource.getUri();
+        // Get the resource host address
+        String hostAddress = ocResource.getHost();
+        msg("\tURI of the resource: " + resourceUri);
+        msg("\tHost address of the resource: " + hostAddress);
+        // Get the resource types
+        msg("\tList of resource types: ");
+        for (String resourceType : ocResource.getResourceTypes()) {
+            msg("\t\t" + resourceType);
+        }
+        msg("\tList of resource interfaces:");
+        for (String resourceInterface : ocResource.getResourceInterfaces()) {
+            msg("\t\t" + resourceInterface);
+        }
+        msg("\tList of resource connectivity types:");
+        for (OcConnectivityType connectivityType : ocResource.getConnectivityTypeSet()) {
+            msg("\t\t" + connectivityType);
+        }
+        printLine();
+
+        // In this example we are only interested in the light resources
+        if (resourceUri.equals(ServerLight.DEFAULT_RESOURCE_URI)) {
+            mFoundLightResource = ocResource;
+
+            // Call a local method which will internally invoke "get" API on the
+            // foundLightResource
+            getLightResourceRepresentation();
+        }
+    }
+
+    @Override
+    public synchronized void onFindResourceFailed(Throwable throwable, String uri) {
+        msg("findResource request has failed");
+        msgError(throwable.toString());
+    }
+
+    /**
+     * Local method to get representation of a found light resource
+     */
+    private void getLightResourceRepresentation() {
+        msg("Getting Light Representation...");
+
+        Map<String, String> queryParams = new HashMap<>();
+        try {
+            // Invoke resource's "get" API with a OcResource.OnGetListener event
+            // listener implementation
+            mFoundLightResource.get(queryParams, this);
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Error occurred while invoking \"get\" API");
+        }
+    }
+
+    /**
+     * An event handler to be executed whenever a "get" request completes
+     * successfully
+     *
+     * @param list
+     *            list of the header options
+     * @param ocRepresentation
+     *            representation of a resource
+     */
+    @Override
+    public synchronized void onGetCompleted(List<OcHeaderOption> list, OcRepresentation ocRepresentation) {
+        msg("GET request was successful");
+        msg("Resource URI: " + ocRepresentation.getUri());
+
+        try {
+            // Read attribute values into local representation of a light
+            mLight.setOcRepresentation(ocRepresentation);
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Failed to read the attributes of a light resource");
+        }
+        msg("Light attributes: ");
+        msg(mLight.toString());
+        printLine();
+
+        // Call a local method which will internally invoke put API on the
+        // foundLightResource
+        putLightRepresentation();
+    }
+
+    /**
+     * An event handler to be executed whenever a "get" request fails
+     *
+     * @param throwable
+     *            exception
+     */
+    @Override
+    public synchronized void onGetFailed(Throwable throwable) {
+        if (throwable instanceof OcException) {
+            OcException ocEx = (OcException) throwable;
+            msgError(ocEx.toString());
+            ErrorCode errCode = ocEx.getErrorCode();
+            // do something based on errorCode
+            msg("Error code: " + errCode);
+        }
+        msg("Failed to get representation of a found light resource");
+    }
+
+    /**
+     * Local method to put a different state for this light resource
+     */
+    private void putLightRepresentation() {
+        // set new values
+        mLight.setState(true);
+        mLight.setPower(15);
+
+        msg("Putting light representation...");
+        OcRepresentation representation = null;
+        try {
+            representation = mLight.getOcRepresentation();
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Failed to get OcRepresentation from a light");
+        }
+
+        Map<String, String> queryParams = new HashMap<>();
+
+        try {
+            // Invoke resource's "put" API with a new representation, query
+            // parameters and OcResource.OnPutListener event listener
+            // implementation
+            mFoundLightResource.put(representation, queryParams, this);
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Error occurred while invoking \"put\" API");
+        }
+    }
+
+    /**
+     * An event handler to be executed whenever a "put" request completes
+     * successfully
+     *
+     * @param list
+     *            list of the header options
+     * @param ocRepresentation
+     *            representation of a resource
+     */
+    @Override
+    public synchronized void onPutCompleted(List<OcHeaderOption> list, OcRepresentation ocRepresentation) {
+        msg("PUT request was successful");
+        try {
+            mLight.setOcRepresentation(ocRepresentation);
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Failed to create Light representation");
+        }
+        msg("Light attributes: ");
+        msg(mLight.toString());
+        printLine();
+
+        // Call a local method which will internally invoke post API on the
+        // foundLightResource
+        postLightRepresentation();
+    }
+
+    /**
+     * An event handler to be executed whenever a "put" request fails
+     *
+     * @param throwable
+     *            exception
+     */
+    @Override
+    public synchronized void onPutFailed(Throwable throwable) {
+        if (throwable instanceof OcException) {
+            OcException ocEx = (OcException) throwable;
+            msgError(ocEx.toString());
+            ErrorCode errCode = ocEx.getErrorCode();
+            // do something based on errorCode
+            msg("Error code: " + errCode);
+        }
+        msg("Failed to \"put\" a new representation");
+    }
+
+    /**
+     * Local method to post a different state for this light resource
+     */
+    private void postLightRepresentation() {
+        // set new values
+        mLight.setState(false);
+        mLight.setPower(105);
+
+        msg("Posting light representation...");
+        OcRepresentation representation = null;
+        try {
+            representation = mLight.getOcRepresentation();
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Failed to get OcRepresentation from a light");
+        }
+
+        Map<String, String> queryParams = new HashMap<>();
+        try {
+            // Invoke resource's "post" API with a new representation, query
+            // parameters and OcResource.OnPostListener event listener
+            // implementation
+            mFoundLightResource.post(representation, queryParams, this);
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Error occurred while invoking \"post\" API");
+        }
+    }
+
+    /**
+     * An event handler to be executed whenever a "post" request completes
+     * successfully
+     *
+     * @param list
+     *            list of the header options
+     * @param ocRepresentation
+     *            representation of a resource
+     */
+    @Override
+    public synchronized void onPostCompleted(List<OcHeaderOption> list, OcRepresentation ocRepresentation) {
+        msg("POST request was successful");
+        try {
+            if (ocRepresentation.hasAttribute(OcResource.CREATED_URI_KEY)) {
+                msg("\tUri of the created resource: " + ocRepresentation.getValue(OcResource.CREATED_URI_KEY));
+            } else {
+                mLight.setOcRepresentation(ocRepresentation);
+                msg(mLight.toString());
+            }
+        } catch (OcException e) {
+            msgError(e.toString());
+        }
+
+        // setting new values
+        mLight.setState(true);
+        mLight.setPower(55);
+        msg("Posting again light representation...");
+        OcRepresentation representation2 = null;
+        try {
+            representation2 = mLight.getOcRepresentation();
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Failed to get OcRepresentation from a light");
+        }
+
+        Map<String, String> queryParams = new HashMap<>();
+        try {
+            // Invoke resource's "post" API with a new representation, query
+            // parameters and OcResource.OnPostListener event listener
+            // implementation
+            mFoundLightResource.post(representation2, queryParams, onPostListener2);
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Error occurred while invoking \"post\" API");
+        }
+    }
+
+    /**
+     * An event handler to be executed whenever a "post" request fails
+     *
+     * @param throwable
+     *            exception
+     */
+    @Override
+    public synchronized void onPostFailed(Throwable throwable) {
+        if (throwable instanceof OcException) {
+            OcException ocEx = (OcException) throwable;
+            msgError(ocEx.toString());
+            ErrorCode errCode = ocEx.getErrorCode();
+            // do something based on errorCode
+            msg("Error code: " + errCode);
+        }
+        msg("Failed to \"post\" a new representation");
+    }
+
+    /**
+     * Declare and implement a second OcResource.OnPostListener
+     */
+    OcResource.OnPostListener onPostListener2 = new OcResource.OnPostListener() {
+        /**
+         * An event handler to be executed whenever a "post" request completes
+         * successfully
+         * 
+         * @param list
+         *            list of the header options
+         * @param ocRepresentation
+         *            representation of a resource
+         */
+        @Override
+        public synchronized void onPostCompleted(List<OcHeaderOption> list, OcRepresentation ocRepresentation) {
+            msg("Second POST request was successful");
+            try {
+                if (ocRepresentation.hasAttribute(OcResource.CREATED_URI_KEY)) {
+                    msg("\tUri of the created resource: " + ocRepresentation.getValue(OcResource.CREATED_URI_KEY));
+                } else {
+                    mLight.setOcRepresentation(ocRepresentation);
+                    msg(mLight.toString());
+                }
+            } catch (OcException e) {
+                msgError(e.toString());
+            }
+
+            // Call a local method which will internally invoke observe API on
+            // the foundLightResource
+            observeFoundLightResource();
+        }
+
+        /**
+         * An event handler to be executed whenever a "post" request fails
+         *
+         * @param throwable
+         *            exception
+         */
+        @Override
+        public synchronized void onPostFailed(Throwable throwable) {
+            if (throwable instanceof OcException) {
+                OcException ocEx = (OcException) throwable;
+                msgError(ocEx.toString());
+                ErrorCode errCode = ocEx.getErrorCode();
+                // do something based on errorCode
+                msg("Error code: " + errCode);
+            }
+            msg("Failed to \"post\" a new representation");
+        }
+    };
+
+    /**
+     * Local method to start observing this light resource
+     */
+    private void observeFoundLightResource() {
+        try {
+            // Invoke resource's "observe" API with a observe type, query
+            // parameters and
+            // OcResource.OnObserveListener event listener implementation
+            mFoundLightResource.observe(ObserveType.OBSERVE, new HashMap<String, String>(), this);
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Error occurred while invoking \"observe\" API");
+        }
+    }
+
+    // holds current number of observations
+    private int mObserveCount = 0;
+
+    /**
+     * An event handler to be executed whenever a "post" request completes
+     * successfully
+     *
+     * @param list
+     *            list of the header options
+     * @param ocRepresentation
+     *            representation of a resource
+     * @param sequenceNumber
+     *            sequence number
+     */
+    @Override
+    public synchronized void onObserveCompleted(List<OcHeaderOption> list, OcRepresentation ocRepresentation,
+            int sequenceNumber) {
+        if (OcResource.OnObserveListener.REGISTER == sequenceNumber) {
+            msg("Observe registration action is successful:");
+        } else if (OcResource.OnObserveListener.DEREGISTER == sequenceNumber) {
+            msg("Observe De-registration action is successful");
+        } else if (OcResource.OnObserveListener.NO_OPTION == sequenceNumber) {
+            msg("Observe registration or de-registration action is failed");
+        }
+
+        msg("OBSERVE Result:");
+        msg("\tSequenceNumber: " + sequenceNumber);
+        try {
+            mLight.setOcRepresentation(ocRepresentation);
+        } catch (OcException e) {
+            msgError(e.toString());
+            msg("Failed to get the attribute values");
+        }
+        msg(mLight.toString());
+
+        if ((++mObserveCount) > 11) {
+            msg("Cancelling Observe...");
+            try {
+                mFoundLightResource.cancelObserve();
+            } catch (OcException e) {
+                msgError(e.toString());
+                msg("Error occurred while invoking \"cancelObserve\" API");
+            }
+            msg("DONE");
+            isDone = true;
+
+            synchronized (mWaitLock) {
+                mWaitLock.notify();
+            }
+        }
+    }
+
+    /**
+     * An event handler to be executed whenever a "observe" request fails
+     *
+     * @param throwable
+     *            exception
+     */
+    @Override
+    public synchronized void onObserveFailed(Throwable throwable) {
+        if (throwable instanceof OcException) {
+            OcException ocEx = (OcException) throwable;
+            msgError(ocEx.toString());
+            ErrorCode errCode = ocEx.getErrorCode();
+            // do something based on errorCode
+            msg("Error code: " + errCode);
+        }
+        msg("Observation of the found light resource has failed");
+    }
+
+    // ******************************************************************************
+    // End of the OIC specific code
+    // ******************************************************************************
+
+    private static final String TAG = SimpleClient.class.getSimpleName();
+
+    private void msg(final String text) {
+        SimpleClientServer.msg(TAG, text);
+    }
+
+    private void msgError(final String text) {
+        SimpleClientServer.msgError(TAG, text);
+    }
+
+    private void printLine() {
+        SimpleClientServer.printLine(TAG);
+    }
+}
diff --git a/java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleClientServer.java b/java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleClientServer.java
new file mode 100644 (file)
index 0000000..e6152dd
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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.base.examples;
+
+import org.iotivity.base.ModeType;
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.PlatformConfig;
+import org.iotivity.base.QualityOfService;
+import org.iotivity.base.ServiceType;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * SimpleClientServer
+ * <p/>
+ * SimpleClientServer is a sample OIC client/server application. Return code is
+ * 0 if no errors detected.
+ */
+public class SimpleClientServer {
+
+    private static final String TAG = SimpleClientServer.class.getSimpleName();
+
+    public static void main(String[] args) {
+
+        PlatformConfig platformConfig = new PlatformConfig(ServiceType.IN_PROC, ModeType.CLIENT_SERVER, "0.0.0.0", 0,
+                QualityOfService.LOW);
+        msg(TAG, "Configuring platform.");
+        OcPlatform.Configure(platformConfig);
+
+        SimpleServer server = new SimpleServer();
+        Object waitLock = new Object();
+        SimpleClient client = new SimpleClient(waitLock);
+
+        int returnCode = -1;
+        synchronized (waitLock) {
+            try {
+                waitLock.wait(60 * 1000);
+                if (client.isRunning()) {
+                    msgError(TAG, "Failed to complete on time!");
+                } else {
+                    returnCode = 0;
+                }
+            } catch (InterruptedException e) {
+                msgError(TAG, e.toString());
+            }
+        }
+
+        server.stopSimpleServer();
+        System.exit(returnCode);
+    }
+
+    private static String getMessage(String tag, String text, boolean isError) {
+        return "[" + (isError ? "E" : "O") + "]" + tag + " | " + text;
+    }
+
+    protected static void msg(final String tag, final String text) {
+        System.out.println(getMessage(tag, text, false));
+    }
+
+    protected static void msgError(final String tag, final String text) {
+        System.out.println(getMessage(tag, text, true));
+    }
+
+    protected static void printLine(final String tag) {
+        msg(tag, "------------------------------------------------------------------------");
+    }
+}
diff --git a/java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleLight.java b/java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleLight.java
new file mode 100644 (file)
index 0000000..9d33f33
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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.base.examples;
+
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcRepresentation;
+
+/**
+ * SimpleLight
+ * <p/>
+ * This class is used by SimpleClient to create an object representation of a
+ * remote light resource and update the values depending on the server response.
+ */
+public class SimpleLight {
+
+    public static final String RESOURCE_TYPE = "core.light";
+
+    public static final String NAME_KEY = "name";
+    public static final String STATE_KEY = "state";
+    public static final String POWER_KEY = "power";
+
+    private String mName;
+    private boolean mState;
+    private int mPower;
+
+    public SimpleLight() {
+        mName = "";
+        mState = false;
+        mPower = 0;
+    }
+
+    public void setOcRepresentation(OcRepresentation rep) throws OcException {
+        mName = rep.getValue(NAME_KEY);
+        mState = rep.getValue(STATE_KEY);
+        mPower = rep.getValue(POWER_KEY);
+    }
+
+    public OcRepresentation getOcRepresentation() throws OcException {
+        OcRepresentation rep = new OcRepresentation();
+        rep.setValue(NAME_KEY, mName);
+        rep.setValue(STATE_KEY, mState);
+        rep.setValue(POWER_KEY, mPower);
+        return rep;
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    public void setName(String name) {
+        mName = name;
+    }
+
+    public boolean getState() {
+        return mState;
+    }
+
+    public void setState(boolean state) {
+        mState = state;
+    }
+
+    public int getPower() {
+        return mPower;
+    }
+
+    public void setPower(int power) {
+        mPower = power;
+    }
+
+    @Override
+    public String toString() {
+        return "\t" + NAME_KEY + ": " + getName() + "\n\t" + STATE_KEY + ": " + getState() + "\n\t" + POWER_KEY + ": "
+                + getPower();
+    }
+}
diff --git a/java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleServer.java b/java/examples-java/simpleclientserver/src/main/java/org/iotivity/base/examples/SimpleServer.java
new file mode 100644 (file)
index 0000000..75fab01
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *******************************************************************
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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.base.examples;
+
+import org.iotivity.base.OcException;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * SimpleServer
+ * <p/>
+ * SimpleServer is a sample OIC server application. It creates a Light and waits
+ * for the incoming client calls to handle various request scenarios.
+ */
+public class SimpleServer {
+
+    private List<ServerLight> lights = new LinkedList<>();
+
+    public SimpleServer() {
+        createNewLightResource(ServerLight.DEFAULT_RESOURCE_URI, ServerLight.DEFAULT_RESOURCE_NAME);
+
+        msg("Waiting for the requests...");
+        printLine();
+    }
+
+    protected void createNewLightResource(String resourceUri, String resourceName) {
+        msg("Creating a light");
+        ServerLight light = new ServerLight(this, resourceUri, resourceName, false, 0);
+        msg(light.toString());
+
+        msg("Registering light as a resource");
+        try {
+            light.registerResource();
+        } catch (OcException e) {
+            msgError(TAG, e.toString());
+            msg("Failed to register a light resource");
+        }
+        lights.add(light);
+    }
+
+    public void stopSimpleServer() {
+        for (ServerLight light : lights) {
+            try {
+                light.unregisterResource();
+            } catch (OcException e) {
+                msgError(TAG, e.toString());
+                msg("Failed to unregister a light resource");
+            }
+        }
+        lights.clear();
+
+        msg("All created resources have been unregistered");
+        printLine();
+    }
+
+    // ******************************************************************************
+    // End of the OIC specific code
+    // ******************************************************************************
+
+    private static final String TAG = SimpleServer.class.getSimpleName();
+
+    protected void msg(final String text) {
+        SimpleClientServer.msg(TAG, text);
+    }
+
+    protected void msgError(final String tag, final String text) {
+        SimpleClientServer.msgError(tag, text);
+    }
+
+    private void printLine() {
+        SimpleClientServer.printLine(TAG);
+    }
+}