Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Write Composite Operation #959

Merged
merged 7 commits into from
Mar 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static org.eclipse.leshan.core.californium.ResponseCodeUtil.toCoapResponseCode;

import java.util.List;
import java.util.Map;

import org.eclipse.californium.core.CoapResource;
import org.eclipse.californium.core.CoapServer;
Expand All @@ -32,16 +33,19 @@
import org.eclipse.leshan.client.resource.LwM2mRootEnabler;
import org.eclipse.leshan.client.servers.ServerIdentity;
import org.eclipse.leshan.core.Link;
import org.eclipse.leshan.core.node.LwM2mNode;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.codec.LwM2mNodeDecoder;
import org.eclipse.leshan.core.node.codec.LwM2mNodeEncoder;
import org.eclipse.leshan.core.request.BootstrapDeleteRequest;
import org.eclipse.leshan.core.request.BootstrapDiscoverRequest;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.request.ReadCompositeRequest;
import org.eclipse.leshan.core.request.WriteCompositeRequest;
import org.eclipse.leshan.core.response.BootstrapDeleteResponse;
import org.eclipse.leshan.core.response.BootstrapDiscoverResponse;
import org.eclipse.leshan.core.response.ReadCompositeResponse;
import org.eclipse.leshan.core.response.WriteCompositeResponse;
import org.eclipse.leshan.core.util.StringUtils;

/**
Expand Down Expand Up @@ -129,6 +133,35 @@ public void handleFETCH(CoapExchange exchange) {
return;
}

@Override
public void handleIPATCH(CoapExchange exchange) {
ServerIdentity identity = getServerOrRejectRequest(exchange);
if (identity == null)
return;

// Manage Read Composite request
Request coapRequest = exchange.advanced().getRequest();

// Handle content format
ContentFormat contentFormat = ContentFormat.fromCode(exchange.getRequestOptions().getContentFormat());
if (!decoder.isSupported(contentFormat)) {
exchange.respond(ResponseCode.UNSUPPORTED_CONTENT_FORMAT);
return;
}

Map<LwM2mPath, LwM2mNode> nodes = decoder.decodeNodes(coapRequest.getPayload(), contentFormat, null,
rootEnabler.getModel());

WriteCompositeResponse response = rootEnabler.write(identity,
new WriteCompositeRequest(contentFormat, nodes, coapRequest));
if (response.getCode().isError()) {
exchange.respond(toCoapResponseCode(response.getCode()), response.getErrorMessage());
} else {
exchange.respond(toCoapResponseCode(response.getCode()));
}
return;
}

@Override
public void handleDELETE(CoapExchange exchange) {
String URI = exchange.getRequestOptions().getUriPathString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public ReadResponse read(ServerIdentity identity, int resourceid) {
}

@Override
public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) {
public WriteResponse write(ServerIdentity identity, boolean replace, int resourceid, LwM2mResource value) {

switch (resourceid) {

Expand All @@ -115,7 +115,7 @@ public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResourc
return WriteResponse.success();

default:
return super.write(identity, resourceid, value);
return super.write(identity, replace, resourceid, value);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public static Security x509(String serverUri, int shortServerId, byte[] clientCe
}

@Override
public WriteResponse write(ServerIdentity identity, int resourceId, LwM2mResource value) {
public WriteResponse write(ServerIdentity identity, boolean replace, int resourceId, LwM2mResource value) {
if (!identity.isSystem())
LOG.debug("Write on Security resource /{}/{}/{}", getModel().id, getId(), resourceId);

Expand Down Expand Up @@ -212,7 +212,7 @@ public WriteResponse write(ServerIdentity identity, int resourceId, LwM2mResourc
return WriteResponse.success();

default:
return super.write(identity, resourceId, value);
return super.write(identity, replace, resourceId, value);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public ReadResponse read(ServerIdentity identity, int resourceid) {
}

@Override
public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) {
public WriteResponse write(ServerIdentity identity, boolean replace, int resourceid, LwM2mResource value) {
if (!identity.isSystem())
LOG.debug("Write on Server resource /{}/{}/{}", getModel().id, getId(), resourceid);

Expand Down Expand Up @@ -191,7 +191,7 @@ public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResourc
}

default:
return super.write(identity, resourceid, value);
return super.write(identity, replace, resourceid, value);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public WriteResponse write(ServerIdentity identity, boolean replace, LwM2mObject
if (!identity.isLwm2mServer() || resourceModel.operations.isWritable()) {
LwM2mResource writeResource = resourcesToWrite.remove(resourceModel.id);
if (null != writeResource) {
write(identity, resourceModel.id, writeResource);
write(identity, true, resourceModel.id, writeResource);
} else {
reset(resourceModel.id);
}
Expand All @@ -161,18 +161,18 @@ public WriteResponse write(ServerIdentity identity, boolean replace, LwM2mObject
}
// UPDATE and resources currently not in the model
for (LwM2mResource resource : resourcesToWrite.values()) {
write(identity, resource.getId(), resource);
write(identity, false, resource.getId(), resource);
}
return WriteResponse.success();
}

@Override
public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) {
public WriteResponse write(ServerIdentity identity, boolean replace, int resourceid, LwM2mResource value) {
return WriteResponse.notFound();
}

@Override
public WriteResponse write(ServerIdentity identity, int resourceid, int resourceInstanceId,
public WriteResponse write(ServerIdentity identity, boolean addIfAbsent, int resourceid, int resourceInstanceId,
LwM2mResourceInstance value) {
// this is a sub-optimal default implementation
ReadResponse response = read(ServerIdentity.SYSTEM, resourceid);
Expand All @@ -181,10 +181,10 @@ public WriteResponse write(ServerIdentity identity, int resourceid, int resource
if (content instanceof LwM2mMultipleResource) {
LwM2mMultipleResource multiresource = ((LwM2mMultipleResource) content);
Map<Integer, LwM2mResourceInstance> instances = new HashMap<>(multiresource.getInstances());
if (instances.containsKey(resourceInstanceId)) {
if (addIfAbsent || instances.containsKey(resourceInstanceId)) {
instances.put(resourceInstanceId, value);
return write(identity, resourceid,
new LwM2mMultipleResource(resourceid, value.getType(), instances.values()));
return write(identity, true, resourceid,
new LwM2mMultipleResource(resourceid, value.getType(), instances.values()));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public List<Integer> getAvailableResourceIds(int instanceId) {
@Override
public synchronized CreateResponse create(ServerIdentity identity, CreateRequest request) {
try {
beginTransaction();
beginTransaction(LwM2mPath.OBJECT_DEPTH);

if (!identity.isSystem()) {
if (id == LwM2mId.SECURITY) {
Expand All @@ -133,7 +133,7 @@ public synchronized CreateResponse create(ServerIdentity identity, CreateRequest
return doCreate(identity, request);

} finally {
endTransaction();
endTransaction(LwM2mPath.OBJECT_DEPTH);
}
}

Expand Down Expand Up @@ -183,7 +183,7 @@ protected ReadResponse doRead(ServerIdentity identity, ReadRequest request) {
@Override
public synchronized WriteResponse write(ServerIdentity identity, WriteRequest request) {
try {
beginTransaction();
beginTransaction(LwM2mPath.OBJECT_DEPTH);

LwM2mPath path = request.getPath();

Expand Down Expand Up @@ -234,7 +234,7 @@ public synchronized WriteResponse write(ServerIdentity identity, WriteRequest re

return doWrite(identity, request);
} finally {
endTransaction();
endTransaction(LwM2mPath.OBJECT_DEPTH);
}
}

Expand Down Expand Up @@ -476,12 +476,14 @@ public void removeListener(ObjectListener listener) {
transactionalListener.removeListener(listener);
}

protected void beginTransaction() {
transactionalListener.beginTransaction();
@Override
public synchronized void beginTransaction(byte level) {
transactionalListener.beginTransaction(level);
}

protected void endTransaction() {
transactionalListener.endTransaction();
@Override
public synchronized void endTransaction(byte level) {
transactionalListener.endTransaction(level);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,17 @@ public ReadResponse read(ServerIdentity identity, int resourceid, int resourceIn
}

@Override
public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) {
public WriteResponse write(ServerIdentity identity, boolean replace, int resourceid, LwM2mResource value) {
LOG.info("Write on {} Resource /{}/{}/{} ", getModel().name, getModel().id, getId(), resourceid);
return super.write(identity, resourceid, value);
return super.write(identity, replace, resourceid, value);
}

@Override
public WriteResponse write(ServerIdentity identity, int resourceid, int resourceInstance,
public WriteResponse write(ServerIdentity identity, boolean addIfAbsent, int resourceid, int resourceInstance,
LwM2mResourceInstance value) {
LOG.info("Write on {} Resource Instance/{}/{}/{}/{} ", getModel().name, getModel().id, getId(), resourceid,
resourceInstance);
return super.write(identity, resourceid, resourceInstance, value);
return super.write(identity, addIfAbsent, resourceid, resourceInstance, value);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,27 +153,32 @@ public interface LwM2mInstanceEnabler {
*
* @param identity the identity of the requester. This could be an internal call in this case
* <code> identity == ServerIdentity.SYSTEM</code>.
* @param replace If replace is true that means that the resource value completely replace the previous value. The
* behavior difference is only for Multiple resource. If replace is false the existing array of Resource
* Instances is updated meaning some Instances may be created or overwritten but not deleted.
* @param resourceid the ID of the resource to set the value for
* @param value the value to set the resource to
* @return the response object representing the outcome of the operation. An implementation should set the result's
* {@link WriteResponse#getCode() response code} to either reflect the success or reason for failure to set
* the value.
*/
WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value);
WriteResponse write(ServerIdentity identity, boolean replace, int resourceid, LwM2mResource value);

/**
* Sets the value of one of this LWM2M object instance's resources instance.
*
* @param identity the identity of the requester. This could be an internal call in this case
* <code> identity == ServerIdentity.SYSTEM</code>.
* @param addIfAbsent If resource instance does not already exist it must be addded only if addIfAbsent is True
* @param resourceid the ID of the resource to set the value for
* @param resourceInstance the ID of the resource instance to set the value of
* @param value the value to set the resource instance to
* @return the response object representing the outcome of the operation. An implementation should set the result's
* {@link WriteResponse#getCode() response code} to either reflect the success or reason for failure to set
* the value.
*/
WriteResponse write(ServerIdentity identity, int resourceid, int resourceInstance, LwM2mResourceInstance value);
WriteResponse write(ServerIdentity identity, boolean addIfAbsent, int resourceid, int resourceInstance,
LwM2mResourceInstance value);

/**
* Executes the operation represented by one of this LWM2M object instance's resources.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,9 @@ public interface LwM2mObjectEnabler {

void setLwM2mClient(LwM2mClient client);

void beginTransaction(byte level);

void endTransaction(byte level);

ContentFormat getDefaultEncodingFormat(DownlinkRequest<?> request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.leshan.core.Destroyable;
import org.eclipse.leshan.core.Startable;
import org.eclipse.leshan.core.Stoppable;
import org.eclipse.leshan.core.node.LwM2mPath;

/**
* The LWM2M Object Tree.
Expand Down Expand Up @@ -148,4 +149,17 @@ public void resourceChanged(LwM2mObjectEnabler object, int instanceId, int... re
}
}
}

public void beginTransaction(Map<Integer, LwM2mObjectEnabler> enablers) {
for (LwM2mObjectEnabler enabler : enablers.values()) {
enabler.beginTransaction(LwM2mPath.ROOT_DEPTH);
}
}

public void endTransaction(Map<Integer, LwM2mObjectEnabler> enablers) {
for (LwM2mObjectEnabler enabler : enablers.values()) {
enabler.endTransaction(LwM2mPath.ROOT_DEPTH);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
import org.eclipse.leshan.client.servers.ServerIdentity;
import org.eclipse.leshan.core.model.LwM2mModel;
import org.eclipse.leshan.core.request.ReadCompositeRequest;
import org.eclipse.leshan.core.request.WriteCompositeRequest;
import org.eclipse.leshan.core.response.ReadCompositeResponse;
import org.eclipse.leshan.core.response.WriteCompositeResponse;

/**
* Enable request on root path.
Expand All @@ -27,5 +29,7 @@ public interface LwM2mRootEnabler {

ReadCompositeResponse read(ServerIdentity identity, ReadCompositeRequest request);

WriteCompositeResponse write(ServerIdentity identity, WriteCompositeRequest request);

LwM2mModel getModel();
}
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ protected LwM2mInstanceEnabler createInstance(ServerIdentity identity, Integer i

// add/write resource
for (LwM2mResource resource : resources) {
newInstance.write(identity, resource.getId(), resource);
newInstance.write(identity, true, resource.getId(), resource);
}

return newInstance;
Expand Down Expand Up @@ -268,11 +268,11 @@ protected WriteResponse doWrite(ServerIdentity identity, WriteRequest request) {

// Manage Resource case
if (path.getResourceInstanceId() == null) {
return instance.write(identity, path.getResourceId(), (LwM2mResource) request.getNode());
return instance.write(identity, true, path.getResourceId(), (LwM2mResource) request.getNode());
}

// Manage Resource Instance case
return instance.write(identity, path.getResourceId(), path.getResourceInstanceId(),
return instance.write(identity, false, path.getResourceId(), path.getResourceInstanceId(),
((LwM2mResourceInstance) request.getNode()));
}

Expand Down Expand Up @@ -314,7 +314,7 @@ protected BootstrapWriteResponse doWrite(ServerIdentity identity, BootstrapWrite
doCreate(identity, new CreateRequest(path.getObjectId(),
new LwM2mObjectInstance(path.getObjectInstanceId(), resource)));
} else {
instanceEnabler.write(identity, path.getResourceId(), resource);
instanceEnabler.write(identity, true, path.getResourceId(), resource);
}
return BootstrapWriteResponse.success();
}
Expand Down
Loading