Search in sources :

Example 1 with AccessContext

use of org.eclipse.milo.opcua.sdk.server.api.AccessContext in project milo by eclipse.

the class AbstractMethodInvocationHandler method invoke.

@Override
public final CallMethodResult invoke(AccessContext accessContext, CallMethodRequest request) {
    try {
        checkExecutableAttributes(accessContext);
        Variant[] inputArgumentValues = request.getInputArguments();
        if (inputArgumentValues == null)
            inputArgumentValues = new Variant[0];
        if (inputArgumentValues.length != getInputArguments().length) {
            throw new UaException(StatusCodes.Bad_ArgumentsMissing);
        }
        StatusCode[] inputDataTypeCheckResults = new StatusCode[inputArgumentValues.length];
        for (int i = 0; i < inputArgumentValues.length; i++) {
            Argument argument = getInputArguments()[i];
            Variant variant = inputArgumentValues[i];
            Object value = variant.getValue();
            // TODO this needs to be able to match when argument DataType is an alias type
            // extract subtype logic from AttributeWriter...
            boolean dataTypeMatch = value == null || variant.getDataType().flatMap(xni -> xni.toNodeId(node.getNodeContext().getNamespaceTable())).map(type -> {
                if (type.equals(argument.getDataType())) {
                    return true;
                } else {
                    if (Identifiers.Structure.equals(type) && value instanceof ExtensionObject) {
                        SerializationContext serializationContext = getNode().getNodeContext().getServer().getSerializationContext();
                        try {
                            Object decoded = ((ExtensionObject) value).decode(serializationContext);
                            if (decoded instanceof UaStructure) {
                                return ((UaStructure) decoded).getTypeId().toNodeId(node.getNodeContext().getNamespaceTable()).map(argument.getDataType()::equals).orElse(false);
                            }
                        } catch (UaSerializationException e) {
                            LoggerFactory.getLogger(getClass()).warn("Error decoding argument value", e);
                        }
                    }
                    return false;
                }
            }).orElse(false);
            switch(argument.getValueRank()) {
                case ValueRanks.Scalar:
                    if (value != null && value.getClass().isArray()) {
                        dataTypeMatch = false;
                    }
                    break;
                case ValueRanks.OneDimension:
                case ValueRanks.OneOrMoreDimensions:
                    if (value != null && !value.getClass().isArray()) {
                        dataTypeMatch = false;
                    }
                    break;
                default:
                    break;
            }
            if (dataTypeMatch) {
                inputDataTypeCheckResults[i] = StatusCode.GOOD;
            } else {
                inputDataTypeCheckResults[i] = new StatusCode(StatusCodes.Bad_TypeMismatch);
            }
        }
        if (Arrays.stream(inputDataTypeCheckResults).anyMatch(StatusCode::isBad)) {
            throw new InvalidArgumentException(inputDataTypeCheckResults);
        }
        validateInputArgumentValues(inputArgumentValues);
        InvocationContext invocationContext = new InvocationContext() {

            @Override
            public OpcUaServer getServer() {
                return node.getNodeContext().getServer();
            }

            @Override
            public NodeId getObjectId() {
                return request.getObjectId();
            }

            @Override
            public UaMethodNode getMethodNode() {
                return node;
            }

            @Override
            public Optional<Session> getSession() {
                return accessContext.getSession();
            }
        };
        Variant[] outputValues = invoke(invocationContext, inputArgumentValues);
        return new CallMethodResult(StatusCode.GOOD, new StatusCode[0], new DiagnosticInfo[0], outputValues);
    } catch (InvalidArgumentException e) {
        return new CallMethodResult(e.getStatusCode(), e.getInputArgumentResults(), e.getInputArgumentDiagnosticInfos(), new Variant[0]);
    } catch (UaException e) {
        return new CallMethodResult(e.getStatusCode(), new StatusCode[0], new DiagnosticInfo[0], new Variant[0]);
    }
}
Also used : Arrays(java.util.Arrays) ValueRanks(org.eclipse.milo.opcua.sdk.core.ValueRanks) CallMethodRequest(org.eclipse.milo.opcua.stack.core.types.structured.CallMethodRequest) UaStructure(org.eclipse.milo.opcua.stack.core.serialization.UaStructure) LoggerFactory(org.slf4j.LoggerFactory) ExtensionObject(org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject) Session(org.eclipse.milo.opcua.sdk.server.Session) CallMethodResult(org.eclipse.milo.opcua.stack.core.types.structured.CallMethodResult) Argument(org.eclipse.milo.opcua.stack.core.types.structured.Argument) SerializationContext(org.eclipse.milo.opcua.stack.core.serialization.SerializationContext) AttributeId(org.eclipse.milo.opcua.stack.core.AttributeId) UaMethodNode(org.eclipse.milo.opcua.sdk.server.nodes.UaMethodNode) AttributeUtil(org.eclipse.milo.opcua.sdk.server.util.AttributeUtil) StatusCodes(org.eclipse.milo.opcua.stack.core.StatusCodes) NodeId(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId) UaSerializationException(org.eclipse.milo.opcua.stack.core.UaSerializationException) OpcUaServer(org.eclipse.milo.opcua.sdk.server.OpcUaServer) DiagnosticInfo(org.eclipse.milo.opcua.stack.core.types.builtin.DiagnosticInfo) AccessContext(org.eclipse.milo.opcua.sdk.server.api.AccessContext) AttributeContext(org.eclipse.milo.opcua.sdk.server.nodes.AttributeContext) Variant(org.eclipse.milo.opcua.stack.core.types.builtin.Variant) StatusCode(org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode) UaException(org.eclipse.milo.opcua.stack.core.UaException) Optional(java.util.Optional) Identifiers(org.eclipse.milo.opcua.stack.core.Identifiers) SerializationContext(org.eclipse.milo.opcua.stack.core.serialization.SerializationContext) UaSerializationException(org.eclipse.milo.opcua.stack.core.UaSerializationException) Argument(org.eclipse.milo.opcua.stack.core.types.structured.Argument) UaException(org.eclipse.milo.opcua.stack.core.UaException) ExtensionObject(org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject) DiagnosticInfo(org.eclipse.milo.opcua.stack.core.types.builtin.DiagnosticInfo) StatusCode(org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode) Variant(org.eclipse.milo.opcua.stack.core.types.builtin.Variant) UaStructure(org.eclipse.milo.opcua.stack.core.serialization.UaStructure) CallMethodResult(org.eclipse.milo.opcua.stack.core.types.structured.CallMethodResult) ExtensionObject(org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject) Session(org.eclipse.milo.opcua.sdk.server.Session)

Aggregations

Arrays (java.util.Arrays)1 Optional (java.util.Optional)1 ValueRanks (org.eclipse.milo.opcua.sdk.core.ValueRanks)1 OpcUaServer (org.eclipse.milo.opcua.sdk.server.OpcUaServer)1 Session (org.eclipse.milo.opcua.sdk.server.Session)1 AccessContext (org.eclipse.milo.opcua.sdk.server.api.AccessContext)1 AttributeContext (org.eclipse.milo.opcua.sdk.server.nodes.AttributeContext)1 UaMethodNode (org.eclipse.milo.opcua.sdk.server.nodes.UaMethodNode)1 AttributeUtil (org.eclipse.milo.opcua.sdk.server.util.AttributeUtil)1 AttributeId (org.eclipse.milo.opcua.stack.core.AttributeId)1 Identifiers (org.eclipse.milo.opcua.stack.core.Identifiers)1 StatusCodes (org.eclipse.milo.opcua.stack.core.StatusCodes)1 UaException (org.eclipse.milo.opcua.stack.core.UaException)1 UaSerializationException (org.eclipse.milo.opcua.stack.core.UaSerializationException)1 SerializationContext (org.eclipse.milo.opcua.stack.core.serialization.SerializationContext)1 UaStructure (org.eclipse.milo.opcua.stack.core.serialization.UaStructure)1 DiagnosticInfo (org.eclipse.milo.opcua.stack.core.types.builtin.DiagnosticInfo)1 ExtensionObject (org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject)1 NodeId (org.eclipse.milo.opcua.stack.core.types.builtin.NodeId)1 StatusCode (org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode)1