/** * Create a request for reading an object/instance/resource targeted by a specific path. * * @param format the desired format for the response * @param path the path to the LWM2M node to read * @throws IllegalArgumentException if the target path is not valid */ public ReadRequest(ContentFormat format, String path) { this(format, new LwM2mPath(path)); }
/** * @param path the end of the new path * @return a new path which is the concatenation of this path and the given one in parameter. */ public LwM2mPath append(String path) { LwM2mPath pathToAdd = new LwM2mPath(path); if (isRoot()) { return pathToAdd; } else { return new LwM2mPath(this.toString() + pathToAdd.toString()); } }
/** * Create a Object Link referencing an object instance with the given path. */ public static ObjectLink fromPath(String path) { LwM2mPath lwM2mPath = new LwM2mPath(path); if (lwM2mPath.isRoot()) { return new ObjectLink(); // create null link } else if (lwM2mPath.isObjectInstance()) { return new ObjectLink(lwM2mPath.getObjectId(), lwM2mPath.getObjectInstanceId()); } else { throw new IllegalArgumentException("Invalid path: ObjectLink should reference an object instance"); } }
public static Class<? extends LwM2mNode> nodeClassFromPath(LwM2mPath path) { if (path.isObject()) { return LwM2mObject.class; } else if (path.isObjectInstance()) { return LwM2mObjectInstance.class; } else if (path.isResource()) { return LwM2mResource.class; } throw new IllegalArgumentException("invalid path level: " + path); }
LwM2mPath nodePath = baseName.append(resourceElt.getName()); if (nodePath.isResourceInstance()) { LwM2mPath resourcePath = new LwM2mPath(nodePath.getObjectId(), nodePath.getObjectInstanceId(), nodePath.getResourceId()); Map<Integer, JsonArrayEntry> multiResource = multiResourceMap.get(resourcePath); if (multiResource == null) { JsonArrayEntry previousResInstance = multiResource.put(nodePath.getResourceInstanceId(), resourceElt); if (previousResInstance != null) { throw new CodecException( "2 RESOURCE_INSTANCE nodes (%s,%s) with the same identifier %d for path %s", previousResInstance, resourceElt, nodePath.getResourceInstanceId(), nodePath); } else if (nodePath.isResource()) { LwM2mResource res = LwM2mSingleResource.newResource(nodePath.getResourceId(), parseJsonValue(resourceElt.getResourceValue(), expectedType, nodePath), expectedType); LwM2mResource previousRes = lwM2mResourceMap.put(nodePath.getResourceId(), res); if (previousRes != null) { throw new CodecException("2 RESOURCE nodes (%s,%s) with the same identifier %d for path %s", LwM2mResource resource = LwM2mMultipleResource.newResource(resourcePath.getResourceId(), values, expectedType); LwM2mResource previousRes = lwM2mResourceMap.put(resourcePath.getResourceId(), resource); if (previousRes != null) { throw new CodecException("2 RESOURCE nodes (%s,%s) with the same identifier %d for path %s",
private static LwM2mPath extractAndValidateBaseName(JsonRootObject jsonObject, LwM2mPath requestPath) throws CodecException { // Check baseName is valid if (jsonObject.getBaseName() != null && !jsonObject.getBaseName().isEmpty()) { LwM2mPath bnPath = new LwM2mPath(jsonObject.getBaseName()); // check returned base name path is under requested path if (requestPath.getObjectId() != null && bnPath.getObjectId() != null) { if (!bnPath.getObjectId().equals(requestPath.getObjectId())) { throw new CodecException("Basename path [%s] does not match requested path [%s].", bnPath, requestPath); } if (requestPath.getObjectInstanceId() != null && bnPath.getObjectInstanceId() != null) { if (!bnPath.getObjectInstanceId().equals(requestPath.getObjectInstanceId())) { throw new CodecException("Basename path [%s] does not match requested path [%s].", bnPath, requestPath); } if (requestPath.getResourceId() != null && bnPath.getResourceId() != null) { if (!bnPath.getResourceId().equals(requestPath.getResourceId())) { throw new CodecException("Basename path [%s] does not match requested path [%s].", bnPath, requestPath); } } } } return bnPath; } return null; }
ObjectModel oModel = model.getObjectModel(path.getObjectId()); if (oModel == null) { LOG.warn("No model for object {}. The tlv is decoded assuming this is a single instance object", path.getObjectId()); instances.put(0, parseObjectInstanceTlv(tlvs, path.getObjectId(), 0, model)); } else if (!oModel.multiple) { instances.put(0, parseObjectInstanceTlv(tlvs, path.getObjectId(), 0, model)); } else { throw new CodecException("Object instance TLV is mandatory for multiple instances object [path:%s]", LwM2mObjectInstance objectInstance = parseObjectInstanceTlv(tlv.getChildren(), path.getObjectId(), tlv.getIdentifier(), model); LwM2mObjectInstance previousObjectInstance = instances.put(objectInstance.getId(), objectInstance); return (T) new LwM2mObject(path.getObjectId(), instances.values()); if (path.isObjectInstance() && tlvs[0].getIdentifier() != path.getObjectInstanceId()) { throw new CodecException("Id conflict between path [%s] and instance TLV [object instance id=%d]", path, tlvs[0].getIdentifier()); return (T) parseObjectInstanceTlv(tlvs[0].getChildren(), path.getObjectId(), tlvs[0].getIdentifier(), model); } else { Integer instanceId = path.getObjectInstanceId(); if (instanceId == null) { ObjectModel oModel = model.getObjectModel(path.getObjectId()); if (oModel != null && !oModel.multiple) {
if (path.isObject()) { for (LwM2mObjectInstance instanceNode : ((LwM2mObject) request.getNode()).getInstances().values()) { LwM2mInstanceEnabler instanceEnabler = instances.get(instanceNode.getId()); if (instanceEnabler == null) { doCreate(new CreateRequest(path.getObjectId(), instanceNode)); } else { doWrite(identity, new WriteRequest(Mode.REPLACE, path.getObjectId(), path.getObjectInstanceId(), instanceNode.getResources().values())); if (path.isObjectInstance()) { LwM2mObjectInstance instanceNode = (LwM2mObjectInstance) request.getNode(); LwM2mInstanceEnabler instanceEnabler = instances.get(path.getObjectInstanceId()); if (instanceEnabler == null) { doCreate(new CreateRequest(path.getObjectId(), instanceNode)); } else { doWrite(identity, new WriteRequest(Mode.REPLACE, request.getContentFormat(), path.getObjectId(), path.getObjectInstanceId(), instanceNode.getResources().values())); LwM2mInstanceEnabler instanceEnabler = instances.get(path.getObjectInstanceId()); if (instanceEnabler == null) { doCreate(new CreateRequest(path.getObjectId(), new LwM2mObjectInstance(path.getObjectInstanceId(), resource))); } else { instanceEnabler.write(path.getResourceId(), resource);
protected DiscoverResponse doDiscover(DiscoverRequest request) { LwM2mPath path = request.getPath(); if (path.isObject()) { // Manage discover on object Link[] ObjectLinks = LinkFormatHelper.getObjectDescription(this, null); return DiscoverResponse.success(ObjectLinks); } else if (path.isObjectInstance()) { // Manage discover on instance if (!getAvailableInstanceIds().contains(path.getObjectInstanceId())) return DiscoverResponse.notFound(); Link[] instanceLink = LinkFormatHelper.getInstanceDescription(this, path.getObjectInstanceId(), null); return DiscoverResponse.success(instanceLink); } else if (path.isResource()) { // Manage discover on resource if (!getAvailableInstanceIds().contains(path.getObjectInstanceId())) return DiscoverResponse.notFound(); ResourceModel resourceModel = getObjectModel().resources.get(path.getResourceId()); if (resourceModel == null) return DiscoverResponse.notFound(); if (!getAvailableResourceIds(path.getObjectInstanceId()).contains(path.getResourceId())) return DiscoverResponse.notFound(); Link resourceLink = LinkFormatHelper.getResourceDescription(this, path.getObjectInstanceId(), path.getResourceId(), null); return DiscoverResponse.success(new Link[] { resourceLink }); } return DiscoverResponse.badRequest(null); }
@Override protected CreateResponse doCreate(CreateRequest request) { Integer instanceId = request.getInstanceId(); if (instanceId == null) { // the client is in charge to generate the id of the new instance if (instances.isEmpty()) { instanceId = 0; } else { instanceId = Collections.max(instances.keySet()) + 1; } } LwM2mInstanceEnabler newInstance = instanceFactory.create(getObjectModel()); for (LwM2mResource resource : request.getResources()) { newInstance.write(resource.getId(), resource); } instances.put(instanceId, newInstance); listenInstance(newInstance, instanceId); return CreateResponse.success(new LwM2mPath(request.getPath().getObjectId(), instanceId).toString()); }
String URI = exchange.getRequestOptions().getUriPathString(); LwM2mPath path = new LwM2mPath(URI); if (path.isResource()) { byte[] payload = exchange.getRequestPayload(); ExecuteResponse response = nodeEnabler.execute(identity, if (path.isObjectInstance()) { try { LwM2mNode lwM2mNode = decoder.decode(exchange.getRequestPayload(), contentFormat, path, model); new LwM2mPath(path.getObjectId()), model, LwM2mObjectInstance.class); createRequest = new CreateRequest(contentFormat, path.getObjectId(), newInstance); } else { createRequest = new CreateRequest(contentFormat, path.getObjectId(), newInstance.getResources().values());
public static LwM2mNode decode(byte[] content, LwM2mPath path, LwM2mModel model) throws CodecException { if (!path.isResource()) throw new CodecException("Invalid path %s : TextDecoder decodes resource only", path); ResourceModel rDesc = model.getResourceModel(path.getObjectId(), path.getResourceId()); String strValue = content != null ? new String(content, StandardCharsets.UTF_8) : ""; if (rDesc != null && rDesc.type != null) { return LwM2mSingleResource.newResource(path.getResourceId(), parseTextValue(strValue, rDesc.type, path), rDesc.type); } else { // unknown resource, returning a default string value return LwM2mSingleResource.newStringResource(path.getResourceId(), strValue); } }
private CreateRequest(ContentFormat format, LwM2mPath target, Integer instanceId, LwM2mResource[] resources) { super(target); // accept only object and object instance path if (target.isRoot()) throw new InvalidRequestException("Create request cannot target root path"); if (!target.isObject() && !target.isObjectInstance()) throw new InvalidRequestException( "Invalid path %s: Create request must not target an object or object instance", target); // validate instance id if (instanceId != null && instanceId == LwM2mObjectInstance.UNDEFINED) { instanceId = null; } if (target.isObjectInstance()) { if (instanceId == null) { instanceId = target.getObjectInstanceId(); } else { if (!instanceId.equals(target.getObjectInstanceId())) { throw new InvalidRequestException("Conflict between path instance id %s and node instance id %s", target, instanceId); } } } if (instanceId != null && instanceId < 0) throw new InvalidRequestException("Invalid instance id %s for path %s ", instanceId, target); // store attributes this.instanceId = instanceId; this.resources = Collections.unmodifiableList(Arrays.asList(resources)); this.contentFormat = format != null ? format : ContentFormat.TLV; // default to TLV }
private final void setTarget(Request coapRequest, LwM2mPath path) { EndpointContext context = EndpointContextUtil.extractContext(destination); coapRequest.setDestinationContext(context); // root path if (rootPath != null) { for (String rootPathPart : rootPath.split("/")) { if (!StringUtils.isEmpty(rootPathPart)) { coapRequest.getOptions().addUriPath(rootPathPart); } } } // objectId if (path.getObjectId() != null) { coapRequest.getOptions().addUriPath(Integer.toString(path.getObjectId())); } // objectInstanceId if (path.getObjectInstanceId() == null) { if (path.getResourceId() != null) { coapRequest.getOptions().addUriPath("0"); // default instanceId } } else { coapRequest.getOptions().addUriPath(Integer.toString(path.getObjectInstanceId())); } // resourceId if (path.getResourceId() != null) { coapRequest.getOptions().addUriPath(Integer.toString(path.getResourceId())); } }
public BootstrapWriteRequest(LwM2mPath target, LwM2mNode node, ContentFormat format) throws InvalidRequestException { super(target); if (target.isRoot()) throw new InvalidRequestException("BootstrapWrite request cannot target root path"); if (getPath().isResource()) { if (!(node instanceof LwM2mResource)) { throw new InvalidRequestException("path '%s' and node type '%s' do not match", target, node.getClass().getSimpleName()); } else if (getPath().isObjectInstance()) { if (!(node instanceof LwM2mObjectInstance)) { throw new InvalidRequestException("path '%s' and node type '%s' do not match", target, node.getClass().getSimpleName()); } else if (getPath().isObject()) { if (!(node instanceof LwM2mObject)) { throw new InvalidRequestException("path '%s' and node type '%s' do not match", target, if (!getPath().isResource()) { throw new InvalidRequestException( "Invalid format for path %s: %s format must be used only for single resources", target, format);
/** * The string representation of the path: /{Object ID}/{ObjectInstance ID}/{Resource ID}/{ResourceInstance ID} */ @Override public String toString() { StringBuilder b = new StringBuilder(); b.append("/"); if (getObjectId() != null) { b.append(getObjectId()); if (getObjectInstanceId() != null) { b.append("/").append(getObjectInstanceId()); if (getResourceId() != null) { b.append("/").append(getResourceId()); if (getResourceInstanceId() != null) { b.append("/").append(getResourceInstanceId()); } } } } return b.toString(); }
@Override public void visit(LwM2mObjectInstance instance) { LOG.trace("Encoding object instance {} into TLV", instance); Tlv[] tlvs; if (path.isObjectInstance() || instance.getId() == LwM2mObjectInstance.UNDEFINED) { // the instanceId is part of the request path or is undefined // so the instance TLV layer is not needed. // encoded as an array of resource TLVs tlvs = encodeResources(instance.getResources().values(), new LwM2mPath(path.getObjectId(), instance.getId())); } else { // encoded as an instance TLV Tlv[] resources = encodeResources(instance.getResources().values(), new LwM2mPath(path.getObjectId(), instance.getId())); tlvs = new Tlv[] { new Tlv(TlvType.OBJECT_INSTANCE, resources, null, instance.getId()) }; } try { out.write(TlvEncoder.encode(tlvs).array()); } catch (IOException e) { throw new RuntimeException(e); } }
/** * Create a CoAP observe request context with specific keys needed for internal Leshan working. */ public static Map<String, String> createCoapObserveRequestContext(String endpoint, String registrationId, ObserveRequest request) { Map<String, String> context = new HashMap<>(); context.put(CTX_ENDPOINT, endpoint); context.put(CTX_REGID, registrationId); context.put(CTX_LWM2M_PATH, request.getPath().toString()); for (Entry<String, String> ctx : request.getContext().entrySet()) { context.put(ctx.getKey(), ctx.getValue()); } return context; }
public static byte[] encode(LwM2mNode node, LwM2mPath path, LwM2mModel model, LwM2mValueConverter converter) throws CodecException { Validate.notNull(node); Validate.notNull(path); Validate.notNull(model); InternalEncoder internalEncoder = new InternalEncoder(); internalEncoder.objectId = path.getObjectId(); internalEncoder.model = model; internalEncoder.requestPath = path; internalEncoder.converter = converter; node.accept(internalEncoder); JsonRootObject jsonObject = new JsonRootObject(); jsonObject.setResourceList(internalEncoder.resourceList); jsonObject.setBaseName(path.toString()); return LwM2mJson.toJsonLwM2m(jsonObject).getBytes(); }
@Override protected ReadResponse doRead(ServerIdentity identity, ReadRequest request) { LwM2mPath path = request.getPath(); // Manage Object case if (path.isObject()) { List<LwM2mObjectInstance> lwM2mObjectInstances = new ArrayList<>(); for (Entry<Integer, LwM2mInstanceEnabler> entry : instances.entrySet()) { lwM2mObjectInstances.add(getLwM2mObjectInstance(entry.getKey(), entry.getValue(), identity, false)); } return ReadResponse.success(new LwM2mObject(getId(), lwM2mObjectInstances)); } // Manage Instance case LwM2mInstanceEnabler instance = instances.get(path.getObjectInstanceId()); if (instance == null) return ReadResponse.notFound(); if (path.getResourceId() == null) { return ReadResponse.success(getLwM2mObjectInstance(path.getObjectInstanceId(), instance, identity, false)); } // Manage Resource case return instance.read(path.getResourceId()); }