diff --git a/LICENSE_HEADER.txt b/LICENSE_HEADER.txt index f363c309..5b1ccb46 100644 --- a/LICENSE_HEADER.txt +++ b/LICENSE_HEADER.txt @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation diff --git a/README.md b/README.md index 6f23838c..afb34b2a 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,7 @@ and other. ## Uses -* [Californium](https://www.eclipse.org/californium/) 2.8.0 -* [Californium](https://www.eclipse.org/californium/) 3.10.0 (development) +* [Californium](https://www.eclipse.org/californium/) 3.11.0 ## Installation @@ -39,21 +38,7 @@ add following dependency to your `pom.xml`: nl.teslanet.mule.connectors.coap mule-coap-connector - 2.1.1 - mule-plugin - - -``` - -To use the latest development milestone, -add following dependency to your `pom.xml`: - -```xml - - - nl.teslanet.mule.connectors.coap - mule-coap-connector - 3.0.0-M2 + 3.0.0-M3 mule-plugin diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 0e2f977d..d5171742 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,8 +1,14 @@ # Mule CoAP Connector Release Notes ![Mule-Coap logo](icon/icon.svg) +## Development milestone 3.0.0-M3 + +* Development phase 3 +* Californium 3.11.0 upgrade + ## Development milestone 3.0.0-M2 +* Development phase 2 * Californium 3.10.0 upgrade ## Release 2.1.1 diff --git a/pom.xml b/pom.xml index 5f537fe9..8dd05743 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -65,7 +65,7 @@ Community LICENSE.md - 3.10.0 + 3.11.0 3.14.0 1.7.36 1.1.3 @@ -195,7 +195,7 @@ Contributors: 1 - + false @@ -293,7 +293,7 @@ Contributors: org.mule.module mule-java-module - 1.2.11 + 1.2.13 mule-plugin provided @@ -307,7 +307,7 @@ Contributors: org.mule.connectors mule-objectstore-connector - 1.2.1 + 1.2.2 mule-plugin test @@ -333,13 +333,13 @@ Contributors: org.awaitility awaitility - 4.2.0 + 4.2.1 test org.apache.logging.log4j log4j-slf4j-impl - 2.22.0 + 2.23.1 test @@ -375,7 +375,7 @@ Contributors: org.jacoco jacoco-maven-plugin - 0.8.8 + 0.8.11 prepare-agent @@ -394,7 +394,7 @@ Contributors: org.sonarsource.scanner.maven sonar-maven-plugin - 3.9.1.2184 + 3.11.0.3922 diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/ExchangeParams.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/ExchangeParams.java index e0747dcf..a8efdf52 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/ExchangeParams.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/ExchangeParams.java @@ -184,7 +184,6 @@ public class ExchangeParams implements VisitableConfig @ParameterDsl( allowReferences= false ) public String maxTransmitWait= null; - //TODO cf3 move to multicast params? /** * The expected maximum response delay over all servers * that the client can send a multicast request to. See @@ -223,7 +222,6 @@ public class ExchangeParams implements VisitableConfig @ParameterDsl( allowReferences= false ) public Integer tokenSizeLimit= null; - //TODO cf3 handle values <= 0, differentiate values in multicast-endpoint and udp-endpoint /** * Base for multicast MID range. Multicast requests use MIDs in the range [base...65536). * A negative or zero value disables multicast requests. @@ -300,7 +298,6 @@ public class ExchangeParams implements VisitableConfig @ParameterDsl( allowReferences= false ) public Deduplicator deduplicator= null; - //TODO cf3 move to udp/multicast /** * Configuration of the congestion control algorithm, if any. */ diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/OptionParams.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/OptionParams.java index 3d399a19..c22d088d 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/OptionParams.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/OptionParams.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -41,13 +41,17 @@ */ public class OptionParams implements VisitableConfig { - //TODO cf3 non critical options need to be understood as well. Not suitable for proxy.. + //TODO non critical options need to be understood as well. Not suitable for proxy.. /** - * The list of critical other options that the endpoint understands. + * The list of other options that the endpoint understands. * Messages containing critical options that are not understood will be refused. + * Elective options that are not understood will be ignored. */ @Parameter - @Summary( value= "The critical other options that the endpoint understands. \nMessages containing critical options that are not understood will be rejected." ) + @Summary( + value= "The other options that the endpoint understands. " + "\nMessages containing critical options that are not understood will be rejected. " + + "\nElective options that are not understood will be ignored." + ) @Expression( ExpressionSupport.NOT_SUPPORTED ) @ParameterDsl( allowInlineDefinition= true, allowReferences= false ) public List< OtherOptionConfig > otherOptionConfigs; diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/SocketParams.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/SocketParams.java index cb2c4c50..80de319a 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/SocketParams.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/SocketParams.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -80,6 +80,16 @@ public class SocketParams implements VisitableConfig @ParameterDsl( allowReferences= false ) public Integer sendBuffer= null; + /** + * Reuse address when true. + */ + @Parameter + @Optional( defaultValue= "false" ) + @Summary( value= "Reuse address when true." ) + @Expression( ExpressionSupport.NOT_SUPPORTED ) + @ParameterDsl( allowReferences= false ) + public boolean reuseAddress= false; + /** * Accept visitor. */ diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/Unused.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/Unused.java index 32d80cf8..4d2fd91f 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/Unused.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/Unused.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -55,7 +55,7 @@ public class Unused implements VisitableConfig @Override public void accept( ConfigVisitor visitor ) { - //visitor.visit( this ); + //no visit } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/endpoint/AbstractEndpoint.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/endpoint/AbstractEndpoint.java index 01a25d52..362322f7 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/endpoint/AbstractEndpoint.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/endpoint/AbstractEndpoint.java @@ -141,7 +141,7 @@ protected AbstractEndpoint() */ protected AbstractEndpoint( String name ) { - configName= name; + this.configName= name; //initialise nullsafe params socketParams= new SocketParams(); blockwiseParams= new BlockwiseParams(); @@ -160,7 +160,6 @@ protected AbstractEndpoint( String name, int port ) { this( name ); socketParams.bindToPort= port; - exchangeParams= new ExchangeParams( new GroupedMidTracker() ); } /** diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/options/OptionType.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/options/OptionFormat.java similarity index 94% rename from src/main/java/nl/teslanet/mule/connectors/coap/api/config/options/OptionType.java rename to src/main/java/nl/teslanet/mule/connectors/coap/api/config/options/OptionFormat.java index 3c4cd746..26eaf468 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/options/OptionType.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/options/OptionFormat.java @@ -22,12 +22,11 @@ */ package nl.teslanet.mule.connectors.coap.api.config.options; - /** - * Enum for CoAP Option types. + * Enum for CoAP Option Formats. * */ -public enum OptionType +public enum OptionFormat { EMPTY, INTEGER, OPAQUE, STRING } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/options/OtherOptionConfig.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/options/OtherOptionConfig.java index 982faa0c..459da273 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/options/OtherOptionConfig.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/options/OtherOptionConfig.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2023 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -58,15 +58,15 @@ public class OtherOptionConfig protected int number; /** - * The type of the other option. + * The format of the other option. */ @Parameter @Optional( defaultValue= "OPAQUE" ) @Expression( ExpressionSupport.NOT_SUPPORTED ) @ParameterDsl( allowReferences= false ) - @Summary( "The type of the other option." ) + @Summary( "The format of the other option." ) @Example( "INTEGER" ) - protected OptionType optionType= OptionType.OPAQUE; + protected OptionFormat format= OptionFormat.OPAQUE; /** * The multiplicity of the other option. @@ -76,7 +76,6 @@ public class OtherOptionConfig @Expression( ExpressionSupport.NOT_SUPPORTED ) @ParameterDsl( allowReferences= false ) @Summary( "The type of the other option." ) - @Example( "INTEGER" ) protected boolean singleValue= true; /** @@ -87,8 +86,8 @@ public class OtherOptionConfig @Expression( ExpressionSupport.NOT_SUPPORTED ) @ParameterDsl( allowReferences= false ) @Summary( "The minimum number of bytes of the option." ) - @Example( "0" ) - protected Integer minBytes= 0; + @Example( "1" ) + protected int minBytes= 0; /** * The value of the other option. @@ -99,7 +98,7 @@ public class OtherOptionConfig @ParameterDsl( allowReferences= false ) @Summary( "The maximum number of bytes of the option." ) @Example( "4" ) - protected Integer maxBytes= Integer.MAX_VALUE; + protected int maxBytes= Integer.MAX_VALUE; /** * @return The alias. @@ -134,19 +133,19 @@ public void setNumber( int number ) } /** - * @return The optionType. + * @return The option format. */ - public OptionType getOptionType() + public OptionFormat getFormat() { - return optionType; + return format; } /** - * @param optionType The optionType to set. + * @param format The option format to set. */ - public void setOptionType( OptionType optionType ) + public void setFormat( OptionFormat format ) { - this.optionType= optionType; + this.format= format; } /** @@ -176,7 +175,7 @@ public Integer getMinBytes() /** * @param minBytes The minBytes to set. */ - public void setMinBytes( Integer minBytes ) + public void setMinBytes( int minBytes ) { this.minBytes= minBytes; } @@ -184,7 +183,7 @@ public void setMinBytes( Integer minBytes ) /** * @return The maxBytes. */ - public Integer getMaxBytes() + public int getMaxBytes() { return maxBytes; } @@ -192,7 +191,7 @@ public Integer getMaxBytes() /** * @param maxBytes The maxBytes to set. */ - public void setMaxBytes( Integer maxBytes ) + public void setMaxBytes( int maxBytes ) { this.maxBytes= maxBytes; } @@ -218,20 +217,20 @@ public OtherOptionConfig( String alias, int number ) } /** - * Constructor with options. - * @param alias - * @param number - * @param optionType - * @param singleValue - * @param minBytes - * @param maxBytes + * Constructor with parameters. + * @param alias The option alias. + * @param number The option number. + * @param format The option format. + * @param singleValue The option alias. + * @param minBytes The minimum length in bytes, may be null. + * @param maxBytes The maximum length in bytes, may be null. */ - public OtherOptionConfig( String alias, int number, OptionType optionType, boolean singleValue, Integer minBytes, Integer maxBytes ) + public OtherOptionConfig( String alias, int number, OptionFormat format, boolean singleValue, int minBytes, int maxBytes ) { super(); this.alias= alias; this.number= number; - this.optionType= optionType; + this.format= format; this.singleValue= singleValue; this.minBytes= minBytes; this.maxBytes= maxBytes; diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/security/PreSharedKey.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/security/PreSharedKey.java index e966c6ad..5826c7a5 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/config/security/PreSharedKey.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/config/security/PreSharedKey.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2023 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -53,6 +53,16 @@ public class PreSharedKey @Summary( "The hostname of the peer that uses the key. \nNeeded for (client) endpoints that connect to multiple servers." ) private String host= null; + /** + * The virtual host to use the key for. + */ + @Parameter + @Optional + @Expression( ExpressionSupport.NOT_SUPPORTED ) + @ParameterDsl( allowReferences= false ) + @Summary( "The virtual host to use the key for." ) + private String virtualHost= null; + /** * The port of the peer that uses the key. * Needed for (client) endpoints that connect to multiple servers." @@ -136,6 +146,22 @@ public void setHost( String host ) this.host= host; } + /** + * @return the virtualHost + */ + public String getVirtualHost() + { + return virtualHost; + } + + /** + * @param virtualHost the virtualHost to set + */ + public void setVirtualHost( String virtualHost ) + { + this.virtualHost= virtualHost; + } + /** * @return the port */ diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/entity/EntityTag.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/entity/EntityTag.java index 0e41e1c8..891c8b13 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/entity/EntityTag.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/entity/EntityTag.java @@ -170,7 +170,7 @@ public String getValueAsString() * Hexadecimal values a-f will be lower case. * @return The string containing the hexadecimal representation or empty string when etag has no value. */ - public String getValueAsHexString() + public String getValueAsHex() { return OptionUtils.toHexString( value ); } @@ -181,7 +181,7 @@ public String getValueAsHexString() @Override public String toString() { - return "ETag { " + getValueAsHexString() + " }"; + return "ETag{ " + getValueAsHex() + " }"; } /** diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/OtherOption.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/OtherOption.java index 858d07c1..2af6024a 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/OtherOption.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/OtherOption.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -33,18 +33,18 @@ /** - * Query Parameter with expression support. + * Other option parameter with expression support. */ public class OtherOption { /** - * The number of the other option. + * The alias of the other option. */ @Parameter @Expression( ExpressionSupport.SUPPORTED ) @Summary( "The number of the other option." ) - @Example( "65001" ) - protected int number; + @Example( "my_option" ) + protected String alias; /** * The value of the other option. @@ -57,19 +57,19 @@ public class OtherOption protected TypedValue< Object > value= null; /** - * @return The number of the option. + * @return The alias of the option. */ - public int getNumber() + public String getAlias() { - return number; + return alias; } /** - * @param optionNumber The optionNumber to set + * @param alias The alias of the option to set */ - public void setNumber( int optionNumber ) + public void setAlias( String alias ) { - this.number= optionNumber; + this.alias= alias; } /** diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/OtherOptionAttribute.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/OtherOptionAttribute.java index d4d87e65..daae6c00 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/OtherOptionAttribute.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/OtherOptionAttribute.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -24,162 +24,85 @@ import java.io.InputStream; -import java.util.Arrays; -import java.util.Objects; + +import nl.teslanet.mule.connectors.coap.api.config.options.OptionFormat; /** - * Other option interface. + * Other option template. */ -public class OtherOptionAttribute +public interface OtherOptionAttribute { /** - * The number of the other option. + * Get the alias of this other option. + * @return The option number. */ - protected final int number; + public String getAlias(); /** - * The value of the other option. + * Get the number of this other option. + * @return The option number. */ - protected final byte[] value; + public int getNumber(); /** - * Default constructor. + * Get the format of this other option. + * @return The option type. */ - public OtherOptionAttribute() - { - super(); - this.number= 0; - this.value= OptionUtils.EMPTY_BYTES; - } + public OptionFormat getFormat(); /** - * Constructor setting members. - * @param number The number of the option. - * @param value The value of the option. + * Get the the length of the other option. + * @return The number of bytes of this option. */ - public OtherOptionAttribute( int number, byte[] value ) - { - super(); - this.number= number; - this.value= ( value == null ? OptionUtils.EMPTY_BYTES : value ); - } - - /** - * Get the number of this other option. - * - * @return The option number. - */ - public int getNumber() - { - return number; - } + public int getLength(); /** * Get the value of this other option. - * * @return The option value if any, otherwise null. */ - public InputStream getValue() - { - return OptionUtils.toInputStream( value ); - } + public InputStream getValue(); /** * Get the value as number. * @return long containing the value. */ - public long getValueAsNumber() - { - return OptionUtils.toLong( value ); - } + public long getValueAsNumber(); /** * Get the option value as hexadecimal string. * Hexadecimal values a-f will be lower case. * @return The string containing the hexadecimal representation or empty string when the value is empty. */ - public String getValueAsHexString() - { - return OptionUtils.toHexString( value ); - } + public String getValueAsHex(); /** * Get value as UTF-8 string. * @return The UTF-8 string interpretation. */ - public String getValueAsString() - { - return OptionUtils.toString( value ); - } + public String getValueAsString(); /** * Checks if option is critical. - * * @return {@code true} if is option critical, otherwise {@code false}. */ - public boolean isCritical() - { - return OptionUtils.isCritical( getNumber() ); - } + public boolean isCritical(); /** * Checks if option with this number is unsafe. - * * @return {@code true} if this is an unsafe option, otherwise {@code false}. */ - public boolean isUnsafe() - { - return OptionUtils.isUnsafe( getNumber() ); - } + public boolean isUnsafe(); /** * Checks if option with this number is a NoCacheKey option. - * * @return {@code true} if this is NoCacheKey option, otherwise {@code false}. */ - public boolean isNoCacheKey() - { - return OptionUtils.isNoCacheKey( getNumber() ); - } - - /** - * Check if the etag is empty. etags whether it contains the etag. - * @return True when the etag is empty, otherwise false. - */ - public boolean isEmpty() - { - return( value.length == 0 ); - } - - /** - * Returns a hash code value for the object. - */ - @Override - public int hashCode() - { - final int prime= 31; - int result= 1; - result= prime * result + Arrays.hashCode( value ); - result= prime * result + Objects.hash( number ); - return result; - } + public boolean isNoCacheKey(); /** - * Indicates whether some other object is "equal to" this one. + * Check if the option is empty. + * @return True when the option is empty, otherwise false. */ - @Override - public boolean equals( Object obj ) - { - if ( this == obj ) - { - return true; - } - if ( !( obj instanceof OtherOptionAttribute ) ) - { - return false; - } - OtherOptionAttribute other= (OtherOptionAttribute) obj; - return getNumber() == other.getNumber() && Arrays.equals( value, other.value ); - } + public boolean isEmpty(); } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/RequestOptions.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/RequestOptions.java index ed559fc3..166cfd7f 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/RequestOptions.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/RequestOptions.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -213,15 +213,14 @@ with the usual response ("size request"). For this usage, the // private String oscore= null; /** - * The CoAP other options to send with the request. + * The other CoAP options to send with the request. */ @Parameter @Optional @NullSafe @Expression( ExpressionSupport.SUPPORTED ) - @Summary( "The CoAP options to send with the request." ) - private List< OtherOption > otherRequestOptions; - // Mule does not seem to convert multimap key to Integer + @Summary( "The other CoAP options to send with the request." ) + private List< OtherOption > otherOptions; /** * @return The ifExists option. @@ -353,19 +352,19 @@ public void setRequestSize( Integer size1 ) } /** - * @return the otherRequestOptions + * @return the other options */ - public List< OtherOption > getOtherRequestOptions() + public List< OtherOption > getOtherOptions() { - return otherRequestOptions; + return otherOptions; } /** - * @param otherRequestOptions the otherRequestOptions to set + * @param otherOptions the other options to set */ - public void setOtherRequestOptions( List< OtherOption > otherRequestOptions ) + public void setOtherRequestOptions( List< OtherOption > otherOptions ) { - this.otherRequestOptions= otherRequestOptions; + this.otherOptions= otherOptions; } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/RequestOptionsAttributes.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/RequestOptionsAttributes.java index 7b5b75ee..11d08370 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/RequestOptionsAttributes.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/RequestOptionsAttributes.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -25,6 +25,8 @@ import java.util.List; +import org.mule.runtime.api.util.MultiMap; + import nl.teslanet.mule.connectors.coap.api.entity.EntityTag; import nl.teslanet.mule.connectors.coap.api.query.QueryParamAttribute; @@ -68,7 +70,7 @@ public class RequestOptionsAttributes protected Integer observe= null; - protected List< OtherOptionAttribute > otherOptions= null; + protected MultiMap< String, OtherOptionAttribute > other= null; /** * @return The ifExists option. @@ -197,8 +199,8 @@ public Integer getObserve() /** * @return the other request options. */ - public List< OtherOptionAttribute > getOtherOptions() + public MultiMap< String, OtherOptionAttribute > getOther() { - return otherOptions; + return other; } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/ResponseOptions.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/ResponseOptions.java index e22e0f7f..9b082183 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/ResponseOptions.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/ResponseOptions.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -195,30 +195,29 @@ public class ResponseOptions // private String oscore= null; /** - * The CoAP other options to send with the request. + * The other CoAP options to send with the response. */ @Parameter @Optional @NullSafe @Expression( ExpressionSupport.SUPPORTED ) - @Summary( "The CoAP options to send with the request." ) - private List< OtherOption > otherResponseOptions; - // Mule does not seem to convert multimap key to Integer + @Summary( "The other CoAP options to send with the response." ) + private List< OtherOption > otherOptions; /** * @return the otherResponseOptions */ - public List< OtherOption > getOtherResponseOptions() + public List< OtherOption > getOtherOptions() { - return otherResponseOptions; + return otherOptions; } /** - * @param otherResponseOptions the otherResponseOptions to set + * @param otherOptions the other options to set */ - public void setOtherResponseOptions( List< OtherOption > otherResponseOptions ) + public void setOtherOptions( List< OtherOption > otherOptions ) { - this.otherResponseOptions= otherResponseOptions; + this.otherOptions= otherOptions; } /** diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/ResponseOptionsAttributes.java b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/ResponseOptionsAttributes.java index 87c6e3dd..ad5bf57b 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/api/options/ResponseOptionsAttributes.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/api/options/ResponseOptionsAttributes.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -25,6 +25,8 @@ import java.util.List; +import org.mule.runtime.api.util.MultiMap; + import nl.teslanet.mule.connectors.coap.api.entity.EntityTag; import nl.teslanet.mule.connectors.coap.api.query.QueryParamAttribute; @@ -51,7 +53,7 @@ public class ResponseOptionsAttributes protected Integer observe= null; - protected List< OtherOptionAttribute > otherOptions= null; + protected MultiMap< String, OtherOptionAttribute > other= null; /** * @return The etag option. @@ -118,10 +120,10 @@ public Integer getObserve() } /** - * Get the other options. + * Get the other response options. */ - public List< OtherOptionAttribute > getOtherOptions() + public MultiMap< String, OtherOptionAttribute > getOther() { - return otherOptions; + return other; } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/CoapConnector.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/CoapConnector.java index e9afe61b..ab6aa9d1 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/CoapConnector.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/CoapConnector.java @@ -23,9 +23,6 @@ package nl.teslanet.mule.connectors.coap.internal; -import org.mule.runtime.api.scheduler.Scheduler; -import org.mule.runtime.api.scheduler.SchedulerConfig; -import org.mule.runtime.api.scheduler.SchedulerService; import org.mule.runtime.extension.api.annotation.Configurations; import org.mule.runtime.extension.api.annotation.Export; import org.mule.runtime.extension.api.annotation.Extension; @@ -34,8 +31,6 @@ import org.mule.runtime.extension.api.annotation.SubTypeMapping; import org.mule.runtime.extension.api.annotation.dsl.xml.Xml; import org.mule.runtime.extension.api.annotation.error.ErrorTypes; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import nl.teslanet.mule.connectors.coap.api.Proxy; import nl.teslanet.mule.connectors.coap.api.ProxyConfig; @@ -43,7 +38,17 @@ import nl.teslanet.mule.connectors.coap.api.RemoteEndpointConfig; import nl.teslanet.mule.connectors.coap.api.SharedServer; import nl.teslanet.mule.connectors.coap.api.SharedServerConfig; -import nl.teslanet.mule.connectors.coap.api.binary.*; +import nl.teslanet.mule.connectors.coap.api.binary.BytesConfig; +import nl.teslanet.mule.connectors.coap.api.binary.BytesValue; +import nl.teslanet.mule.connectors.coap.api.binary.EmptyBytes; +import nl.teslanet.mule.connectors.coap.api.binary.EmptyBytesConfig; +import nl.teslanet.mule.connectors.coap.api.binary.FromBinary; +import nl.teslanet.mule.connectors.coap.api.binary.FromHex; +import nl.teslanet.mule.connectors.coap.api.binary.FromHexConfig; +import nl.teslanet.mule.connectors.coap.api.binary.FromNumber; +import nl.teslanet.mule.connectors.coap.api.binary.FromNumberConfig; +import nl.teslanet.mule.connectors.coap.api.binary.FromString; +import nl.teslanet.mule.connectors.coap.api.binary.FromStringConfig; import nl.teslanet.mule.connectors.coap.api.config.congestion.BasicRto; import nl.teslanet.mule.connectors.coap.api.config.congestion.Cocoa; import nl.teslanet.mule.connectors.coap.api.config.congestion.CocoaStrong; @@ -117,103 +122,8 @@ @ErrorTypes( Errors.class ) public class CoapConnector { - /** - * The logger. - */ - private static final Logger LOGGER= LoggerFactory.getLogger( CoapConnector.class ); - - /** - * The Scheduler service. - */ - private static SchedulerService schedulerService= null; - - /** - * The scheduler configuration. - */ - private static SchedulerConfig schedulerConfig= null; - - /** - * The IO Light scheduler. - */ - private static Scheduler ioScheduler= null; - - /** - * The CPU Light scheduler. - */ - private static Scheduler lightScheduler= null; - - /** - * No instances needed. - */ private CoapConnector() { //NOOP } - - /** - * Set the IO scheduler supplied by Mule. - */ - public static synchronized void setSchedulerService( SchedulerService schedulerServiceCandidate, SchedulerConfig schedulerConfigCandidate ) - { - if ( schedulerService == null && schedulerServiceCandidate != null ) - { - schedulerService= schedulerServiceCandidate; - schedulerConfig= schedulerConfigCandidate; - LOGGER.info( "CoAP schedulerService registered" ); - } - } - - /** - * Get the IO scheduler supplied by Mule. - * @return IO scheduler. - */ - public static synchronized Scheduler getIoScheduler() - { - if ( ioScheduler == null ) - { - ioScheduler= schedulerService.ioScheduler( schedulerConfig.withName( "CoAP IO scheduler" ) ); - LOGGER.info( "CoAP IO scheduler is started" ); - } - return ioScheduler; - } - - /** - * Get the Light scheduler supplied by Mule. - * @return Light scheduler. - */ - public static synchronized Scheduler getLightScheduler() - { - if ( lightScheduler == null ) - { - lightScheduler= schedulerService.cpuLightScheduler( schedulerConfig.withName( "CoAP Light scheduler" ) ); - LOGGER.info( "CoAP CPU Light scheduler is started" ); - } - return lightScheduler; - } - - /** - * Stop the IO scheduler. - */ - public static synchronized void stopIoScheduler() - { - if ( ioScheduler != null ) - { - ioScheduler.stop(); - ioScheduler= null; - LOGGER.info( "CoAP IO scheduler is stopped" ); - } - } - - /** - * Stop the Light scheduler. - */ - public static synchronized void stopLightScheduler() - { - if ( lightScheduler != null ) - { - lightScheduler.stop(); - lightScheduler= null; - LOGGER.info( "CoAP CPU Light scheduler is stopped" ); - } - } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/AttributeUtils.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/AttributeUtils.java index 0a26004d..2446cc98 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/AttributeUtils.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/AttributeUtils.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -25,17 +25,21 @@ import java.util.List; +import org.eclipse.californium.core.coap.Option; import org.eclipse.californium.core.coap.CoAP.Code; import org.eclipse.californium.core.coap.CoAP.ResponseCode; import org.eclipse.californium.core.coap.CoAP.Type; +import org.mule.runtime.api.util.MultiMap; import nl.teslanet.mule.connectors.coap.api.CoapMessageType; import nl.teslanet.mule.connectors.coap.api.CoapRequestCode; import nl.teslanet.mule.connectors.coap.api.CoapResponseCode; +import nl.teslanet.mule.connectors.coap.api.options.OtherOptionAttribute; import nl.teslanet.mule.connectors.coap.api.query.QueryParamAttribute; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalInvalidMessageTypeException; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalInvalidRequestCodeException; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalInvalidResponseCodeException; +import nl.teslanet.mule.connectors.coap.internal.options.DefaultOtherOptionAttribute; /** @@ -341,4 +345,20 @@ public static void addQueryParam( List< QueryParamAttribute > list, String param } list.add( new QueryParamAttribute( key, value ) ); } + + /** + * Create other option attributes. + * @param otherCoapOptions The received other coap options. + * @return The Map containing other options attributes. + */ + public static MultiMap< String, OtherOptionAttribute > createOthers( List< Option > otherCoapOptions ) + { + MultiMap< String, OtherOptionAttribute > others= new MultiMap<>(); + for ( Option other : otherCoapOptions ) + { + DefaultOtherOptionAttribute otherOptionAttribute= new DefaultOtherOptionAttribute( other ); + others.put( otherOptionAttribute.getAlias(), otherOptionAttribute ); + } + return others.toImmutableMultiMap(); + } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/DefaultRequestAttributes.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/DefaultRequestAttributes.java index d1ce2436..58f658c8 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/DefaultRequestAttributes.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/DefaultRequestAttributes.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -23,12 +23,11 @@ package nl.teslanet.mule.connectors.coap.internal.attributes; -import static org.apache.commons.lang3.builder.ToStringStyle.MULTI_LINE_STYLE; - import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import nl.teslanet.mule.connectors.coap.api.CoapRequestAttributes; import nl.teslanet.mule.connectors.coap.api.options.RequestOptionsAttributes; +import nl.teslanet.mule.connectors.coap.internal.options.ToStringStyle; /** @@ -99,6 +98,6 @@ public void setRequestOptionAttributes( RequestOptionsAttributes requestOptionAt @Override public String toString() { - return ReflectionToStringBuilder.toString( this, MULTI_LINE_STYLE ); + return ReflectionToStringBuilder.toString( this, new ToStringStyle() ); } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/DefaultResponseAttributes.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/DefaultResponseAttributes.java index 9b3d2a08..6dba7830 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/DefaultResponseAttributes.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/attributes/DefaultResponseAttributes.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -23,12 +23,11 @@ package nl.teslanet.mule.connectors.coap.internal.attributes; -import static org.apache.commons.lang3.builder.ToStringStyle.MULTI_LINE_STYLE; - import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import nl.teslanet.mule.connectors.coap.api.CoapResponseAttributes; import nl.teslanet.mule.connectors.coap.internal.options.DefaultResponseOptionsAttributes; +import nl.teslanet.mule.connectors.coap.internal.options.ToStringStyle; /** @@ -131,6 +130,6 @@ public void setOptions( DefaultResponseOptionsAttributes responseOptions ) @Override public String toString() { - return ReflectionToStringBuilder.toString( this, MULTI_LINE_STYLE ); + return ReflectionToStringBuilder.toString( this, new ToStringStyle() ); } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/client/Client.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/client/Client.java index 125263c8..361a265a 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/client/Client.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/client/Client.java @@ -42,6 +42,7 @@ import org.eclipse.californium.core.coap.MediaTypeRegistry; import org.eclipse.californium.core.coap.Request; import org.eclipse.californium.core.coap.Token; +import org.eclipse.californium.core.coap.option.OptionDefinition; import org.eclipse.californium.elements.exception.ConnectorException; import org.mule.runtime.api.exception.MuleException; import org.mule.runtime.api.lifecycle.Disposable; @@ -95,7 +96,6 @@ import nl.teslanet.mule.connectors.coap.api.config.endpoint.UDPEndpoint; import nl.teslanet.mule.connectors.coap.api.options.OptionUtils; import nl.teslanet.mule.connectors.coap.api.options.RequestOptions; -import nl.teslanet.mule.connectors.coap.internal.CoapConnector; import nl.teslanet.mule.connectors.coap.internal.attributes.AttributeUtils; import nl.teslanet.mule.connectors.coap.internal.attributes.DefaultResponseAttributes; import nl.teslanet.mule.connectors.coap.internal.endpoint.OperationalEndpoint; @@ -113,6 +113,7 @@ import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalResponseException; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalServerErrorResponseException; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalUnexpectedResponseException; +import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalUnkownOptionException; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalUriException; import nl.teslanet.mule.connectors.coap.internal.options.MediaTypeMediator; import nl.teslanet.mule.connectors.coap.internal.utils.MessageUtils; @@ -213,32 +214,9 @@ public class Client implements Initialisable, Disposable, Startable, Stoppable private static UDPEndpoint defaultEndpoint= null; /** - * Start the client. After starting the client is ready for issuing requests. + * Other options that the client expects. */ - @Override - public void start() throws MuleException - { - coapClient= new CoapClient(); - coapClient.setEndpoint( operationalEndpoint.getCoapEndpoint() ); - LOGGER.info( "{} connected to Endpoint { {} } ", this, operationalEndpoint ); - LOGGER.info( "{} started.", this ); - } - - /** - * Stop the client. When stopped no more requests can be sent using this client. - */ - @Override - public void stop() throws MuleException - { - for ( ObserveRelation relation : observeRelations.values() ) - { - relation.stop(); - } - observeRelations.clear(); - coapClient.shutdown(); - coapClient= null; - LOGGER.info( "{} started.", this ); - } + private ConcurrentHashMap< String, OptionDefinition > otherOptionDefs= new ConcurrentHashMap<>(); /** * Intitialise the client. The client is assigned an endpoint, which is created when needed. @@ -247,7 +225,6 @@ public void stop() throws MuleException public void initialise() throws InitialisationException { AbstractEndpoint abstractEndpoint; - CoapConnector.setSchedulerService( schedulerService, schedulerConfig ); if ( endpoint == null ) { //user wants default endpoint @@ -273,9 +250,39 @@ public void initialise() throws InitialisationException throw new InitialisationException( e, this ); } scheme= operationalEndpoint.getCoapEndpoint().getUri().getScheme(); + operationalEndpoint.getOtherOptionsDefs().forEach( optionDef -> otherOptionDefs.put( optionDef.getName(), optionDef ) ); LOGGER.info( "{} initialised.", this ); } + /** + * Start the client. After starting the client is ready for issuing requests. + */ + @Override + public void start() throws MuleException + { + coapClient= new CoapClient(); + operationalEndpoint.setSchedulersIfNeeded( schedulerService, schedulerConfig ); + coapClient.setEndpoint( operationalEndpoint.getCoapEndpoint() ); + LOGGER.info( "{} connected to Endpoint { {} } ", this, operationalEndpoint ); + LOGGER.info( "{} started.", this ); + } + + /** + * Stop the client. When stopped no more requests can be sent using this client. + */ + @Override + public void stop() throws MuleException + { + for ( ObserveRelation relation : observeRelations.values() ) + { + relation.stop(); + } + observeRelations.clear(); + coapClient.shutdown(); + coapClient= null; + LOGGER.info( "{} started.", this ); + } + /** * The client is disposed of. The client is detached from the endpoint, which will be deleted when not used anymore. */ @@ -284,6 +291,7 @@ public void dispose() { OperationalEndpoint.disposeAll( this ); operationalEndpoint= null; + otherOptionDefs.clear(); LOGGER.info( "{} disposed.", this ); } @@ -295,6 +303,22 @@ public String getClientName() return clientName; } + /** + * @return the schedulerService + */ + public SchedulerService getSchedulerService() + { + return schedulerService; + } + + /** + * @return the schedulerConfig + */ + public SchedulerConfig getSchedulerConfig() + { + return schedulerConfig; + } + /** * @return the coapClient */ @@ -307,11 +331,14 @@ CoapClient getCoapClient() * Get the default client endpoint, lazily initialized. * @return the defaultEndpoint */ - public static synchronized UDPEndpoint getDefaultEndpoint() + private UDPEndpoint getDefaultEndpoint() { - if ( defaultEndpoint == null ) + synchronized ( Client.class ) { - defaultEndpoint= new UDPEndpoint( "default" ); + if ( defaultEndpoint == null ) + { + defaultEndpoint= new UDPEndpoint( "default" ); + } } return defaultEndpoint; } @@ -434,9 +461,9 @@ Result< InputStream, CoapResponseAttributes > doRequest( RequestParams requestPa Request request= builder.build(); try { - MessageUtils.copyOptions( options, request.getOptions(), transformationService ); + MessageUtils.copyOptions( options, request.getOptions(), transformationService, otherOptionDefs ); } - catch ( InternalInvalidOptionValueException e ) + catch ( InternalInvalidOptionValueException | InternalUnkownOptionException e ) { throw new InternalRequestException( this + " cannot process request options", e ); } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/ConfigurationVisitor.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/ConfigurationVisitor.java index ecbcfd38..e83c79c4 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/ConfigurationVisitor.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/ConfigurationVisitor.java @@ -804,8 +804,7 @@ public void visit( DatagramFilter toVisit ) throws ConfigException @Override public void visit( SocketParams toVisit ) { - //TODO cf3 reuse address? - //host and port are configured on endpoint + //reuse address, host and port are configured on endpoint if ( toVisit.receiveBuffer != null ) { config.set( UdpConfig.UDP_RECEIVE_BUFFER_SIZE, toVisit.receiveBuffer ); diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/DtlsEndpointConfigVisitor.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/DtlsEndpointConfigVisitor.java index 0745625a..ff0ac80f 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/DtlsEndpointConfigVisitor.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/DtlsEndpointConfigVisitor.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -39,13 +39,12 @@ import org.eclipse.californium.scandium.dtls.x509.StaticNewAdvancedCertificateVerifier; import nl.teslanet.mule.connectors.coap.api.config.ConfigException; -import nl.teslanet.mule.connectors.coap.api.config.SocketParams; -import nl.teslanet.mule.connectors.coap.api.config.endpoint.AbstractEndpoint; import nl.teslanet.mule.connectors.coap.api.config.security.KeyStore; import nl.teslanet.mule.connectors.coap.api.config.security.PreSharedKey; import nl.teslanet.mule.connectors.coap.api.config.security.SecurityParams; import nl.teslanet.mule.connectors.coap.api.config.security.TrustStore; import nl.teslanet.mule.connectors.coap.api.options.OptionValueException; +import nl.teslanet.mule.connectors.coap.internal.exceptions.EndpointConstructionException; import nl.teslanet.mule.connectors.coap.internal.utils.MuleInputStreamFactory; @@ -53,18 +52,8 @@ * Configuration visitor that collects multi-cast UDP Endpoint configuration * */ -public class DtlsEndpointConfigVisitor extends ConfigurationVisitor +public class DtlsEndpointConfigVisitor extends EndpointConfigVisitor { - /** - * The name of the endpont - */ - private String endpointName; - - /** - * Network interface to use for multicast. - */ - private InetSocketAddress localAddress= null; - /** * The pre-shared keys, if any. */ @@ -115,38 +104,6 @@ public class DtlsEndpointConfigVisitor extends ConfigurationVisitor */ private char[] trustStorePassword= null; - /** - * Visit Endpoint configuration object. - * @param toVisit the object to visit. - * @throws ConfigException When visit is not successful. - */ - @Override - public void visit( AbstractEndpoint toVisit ) throws ConfigException - { - super.visit( toVisit ); - endpointName= toVisit.configName; - } - - /** - * Visit socket parameters. - * @param toVisit The object to visit. - */ - @Override - public void visit( SocketParams toVisit ) - { - super.visit( toVisit ); - int port= ( toVisit.bindToPort != null ? toVisit.bindToPort : 0 ); - - if ( toVisit.bindToHost != null ) - { - localAddress= new InetSocketAddress( toVisit.bindToHost, port ); - } - else - { - localAddress= new InetSocketAddress( port ); - } - } - /** * Visit security parameters. * @param toVisit The object to visit. @@ -191,41 +148,45 @@ public void visit( TrustStore toVisit ) throws ConfigException } /** - * @return The configured endpoint name. - */ - public String getEndpointName() - { - return endpointName; - } - - /** - * Get the Builder that is ready to build the endpoint. - * @return The Endpoint Builder. - * @throws GeneralSecurityException - * @throws IOException - * @throws OptionValueException + * Build the endpoint using the configuration this visitor has collected. + * @return The Endpoint. + * @throws EndpointConstructionException When the configuration cannot be used to create an endpoint. */ - public CoapEndpoint.Builder getEndpointBuilder() throws IOException, GeneralSecurityException, OptionValueException + @Override + public CoapEndpoint getEndpoint() throws EndpointConstructionException { DtlsConnectorConfig.Builder connectBuilder= new DtlsConnectorConfig.Builder( getConfiguration() ); - connectBuilder.setAddress( localAddress ); + connectBuilder.setAddress( getLocalAddress() ); + connectBuilder.setReuseAddress( isReuseAddress() ); // Pre-shared secrets if ( preSharedKeys != null ) { - //TODO cf3 support for virtual host + //TODO cf3 psk file support AdvancedMultiPskStore pskStore= new AdvancedMultiPskStore(); - for ( PreSharedKey key : preSharedKeys ) + try { - if ( key.getHost() == null ) - { - pskStore.setKey( key.getIdentity(), key.getKey().getByteArray() ); - } - else + for ( PreSharedKey key : preSharedKeys ) { - InetSocketAddress address= new InetSocketAddress( key.getHost(), key.getPort() ); - pskStore.addKnownPeer( address, key.getIdentity(), key.getKey().getByteArray() ); + if ( key.getHost() == null ) + { + pskStore.setKey( key.getIdentity(), key.getKey().getByteArray() ); + } + else if ( key.getVirtualHost() != null ) + { + InetSocketAddress address= new InetSocketAddress( key.getHost(), key.getPort() ); + pskStore.addKnownPeer( address, key.getVirtualHost(), key.getIdentity(), key.getKey().getByteArray() ); + } + else + { + InetSocketAddress address= new InetSocketAddress( key.getHost(), key.getPort() ); + pskStore.addKnownPeer( address, key.getIdentity(), key.getKey().getByteArray() ); + } } } + catch ( OptionValueException e ) + { + throw new EndpointConstructionException( String.format( "DTLS Endpoint { %s } preshared key host error.", getEndpointName() ), e ); + } connectBuilder.setAdvancedPskStore( pskStore ); } MuleInputStreamFactory streamFactory= new MuleInputStreamFactory(); @@ -233,32 +194,43 @@ public CoapEndpoint.Builder getEndpointBuilder() throws IOException, GeneralSecu if ( keyStoreAvailable ) { // load the key store - SslContextUtil.Credentials serverCredentials= SslContextUtil.loadCredentials( - streamFactory.getScheme() + keyStoreLocation, - privateKeyAlias, - keyStorePassword, - privateKeyPassword - ); - CertificateProvider identityProvider= new SingleCertificateProvider( serverCredentials.getPrivateKey(), serverCredentials.getPublicKey() ); - connectBuilder.setCertificateIdentityProvider( identityProvider ); + SslContextUtil.Credentials serverCredentials; + + try + { + serverCredentials= SslContextUtil.loadCredentials( streamFactory.getScheme() + keyStoreLocation, privateKeyAlias, keyStorePassword, privateKeyPassword ); + CertificateProvider identityProvider= new SingleCertificateProvider( serverCredentials.getPrivateKey(), serverCredentials.getPublicKey() ); + connectBuilder.setCertificateIdentityProvider( identityProvider ); + } + catch ( IOException | GeneralSecurityException e ) + { + throw new EndpointConstructionException( String.format( "DTLS Endpoint { %s } keystore error.", getEndpointName() ), e ); + } } if ( trustStoreAvailable ) { //load trust store - Certificate[] trustedCertificates= SslContextUtil.loadTrustedCertificates( - streamFactory.getScheme() + trustStoreLocation, - trustedRootCertificateAlias, - trustStorePassword - ); - StaticNewAdvancedCertificateVerifier.Builder verifierBuilder= StaticNewAdvancedCertificateVerifier.builder(); - verifierBuilder.setTrustAllRPKs(); - verifierBuilder.setTrustedCertificates( trustedCertificates ); - connectBuilder.setAdvancedCertificateVerifier( verifierBuilder.build() ); + try + { + Certificate[] trustedCertificates= SslContextUtil.loadTrustedCertificates( + streamFactory.getScheme() + trustStoreLocation, + trustedRootCertificateAlias, + trustStorePassword + ); + StaticNewAdvancedCertificateVerifier.Builder verifierBuilder= StaticNewAdvancedCertificateVerifier.builder(); + verifierBuilder.setTrustAllRPKs(); + verifierBuilder.setTrustedCertificates( trustedCertificates ); + connectBuilder.setAdvancedCertificateVerifier( verifierBuilder.build() ); + } + catch ( IOException | GeneralSecurityException e ) + { + throw new EndpointConstructionException( String.format( "DTLS Endpoint { %s } truststore error.", getEndpointName() ), e ); + } } DTLSConnector dtlsConnector= new DTLSConnector( connectBuilder.build() ); CoapEndpoint.Builder endpointBuilder= new CoapEndpoint.Builder(); endpointBuilder.setConfiguration( getConfiguration() ); endpointBuilder.setConnector( dtlsConnector ); - return endpointBuilder; + return endpointBuilder.build(); } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/EndpointConfigVisitor.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/EndpointConfigVisitor.java index 248fb2c2..f43ff0c9 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/EndpointConfigVisitor.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/EndpointConfigVisitor.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -25,12 +25,9 @@ import java.net.InetSocketAddress; import java.util.ArrayList; +import java.util.List; -import org.eclipse.californium.core.coap.option.EmptyOptionDefinition; -import org.eclipse.californium.core.coap.option.IntegerOptionDefinition; -import org.eclipse.californium.core.coap.option.OpaqueOptionDefinition; import org.eclipse.californium.core.coap.option.OptionDefinition; -import org.eclipse.californium.core.coap.option.StringOptionDefinition; import org.eclipse.californium.core.network.CoapEndpoint; import nl.teslanet.mule.connectors.coap.api.config.ConfigException; @@ -39,23 +36,39 @@ import nl.teslanet.mule.connectors.coap.api.config.endpoint.AbstractEndpoint; import nl.teslanet.mule.connectors.coap.internal.endpoint.EndpointOptionRegistry; import nl.teslanet.mule.connectors.coap.internal.exceptions.EndpointConstructionException; +import nl.teslanet.mule.connectors.coap.internal.utils.MessageUtils; /** * Endpoint configuration visitor. * */ -public class EndpointConfigVisitor extends ConfigurationVisitor +public abstract class EndpointConfigVisitor extends ConfigurationVisitor { /** * The name of the endpont */ private String endpointName; + /** + * Network interface to bind to. + */ + private InetSocketAddress localAddress= null; + /** * The Endpoint Builder that is used to collect endpoint configuration. */ - CoapEndpoint.Builder endPointBuilder= new CoapEndpoint.Builder(); + protected CoapEndpoint.Builder endpointBuilder= new CoapEndpoint.Builder(); + + /** + * Reuse address flag. + */ + private boolean reuseAddress= false; + + /** + * Other options that the endpoint expects. + */ + private ArrayList< OptionDefinition > otherOptionDefs= new ArrayList<>(); /** * Visit option parameters configuration object. @@ -64,49 +77,8 @@ public class EndpointConfigVisitor extends ConfigurationVisitor @Override public void visit( OptionParams toVisit ) { - ArrayList< OptionDefinition > expectedOtherOptions= new ArrayList<>(); - toVisit.otherOptionConfigs.forEach( otherOptionConfig -> { - switch ( otherOptionConfig.getOptionType() ) - { - case EMPTY: - expectedOtherOptions.add( new EmptyOptionDefinition( otherOptionConfig.getNumber(), otherOptionConfig.getAlias() ) ); - break; - case INTEGER: - expectedOtherOptions.add( - new IntegerOptionDefinition( - otherOptionConfig.getNumber(), - otherOptionConfig.getAlias(), - otherOptionConfig.isSingleValue(), - otherOptionConfig.getMinBytes(), - otherOptionConfig.getMaxBytes() - ) - ); - break; - case STRING: - expectedOtherOptions.add( - new StringOptionDefinition( - otherOptionConfig.getNumber(), - otherOptionConfig.getAlias(), - otherOptionConfig.isSingleValue(), - otherOptionConfig.getMinBytes(), - otherOptionConfig.getMaxBytes() - ) - ); - break; - default: - expectedOtherOptions.add( - new OpaqueOptionDefinition( - otherOptionConfig.getNumber(), - otherOptionConfig.getAlias(), - otherOptionConfig.isSingleValue(), - otherOptionConfig.getMinBytes(), - otherOptionConfig.getMaxBytes() - ) - ); - break; - } - } ); - endPointBuilder.setOptionRegistry( new EndpointOptionRegistry( expectedOtherOptions.toArray( new OptionDefinition []{} ) ) ); + toVisit.otherOptionConfigs.forEach( otherOptionConfig -> otherOptionDefs.add( MessageUtils.toCfOptionDefinition( otherOptionConfig ) ) ); + endpointBuilder.setOptionRegistry( new EndpointOptionRegistry( otherOptionDefs.toArray( new OptionDefinition []{} ) ) ); } /** @@ -133,12 +105,13 @@ public void visit( SocketParams toVisit ) if ( toVisit.bindToHost != null ) { - endPointBuilder.setInetSocketAddress( new InetSocketAddress( toVisit.bindToHost, port ) ); + localAddress= new InetSocketAddress( toVisit.bindToHost, port ); } else { - endPointBuilder.setInetSocketAddress( new InetSocketAddress( port ) ); + localAddress= new InetSocketAddress( port ); } + reuseAddress= toVisit.reuseAddress; } /** @@ -150,12 +123,33 @@ public String getEndpointName() } /** - * Get the Builder that is ready to build the endpoint. - * @return The Endpoint Builder. + * @return the localAddress + */ + public InetSocketAddress getLocalAddress() + { + return localAddress; + } + + /** + * @return {@code True} when to reuse address. */ - public CoapEndpoint.Builder getEndpointBuilder() throws EndpointConstructionException + public boolean isReuseAddress() { - endPointBuilder.setConfiguration( this.getConfiguration() ); - return endPointBuilder; + return reuseAddress; } + + /** + * @return The other option definitions. + */ + public List< OptionDefinition > getOtherOptionDefs() + { + return otherOptionDefs; + } + + /** + * Build the endpoint using the configuration this visitor has collected. + * @return The Endpoint. + * @throws EndpointConstructionException When the configuration cannot be used to create an endpoint. + */ + public abstract CoapEndpoint getEndpoint() throws EndpointConstructionException; } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/MulticastUdpEndpointConfigVisitor.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/MulticastUdpEndpointConfigVisitor.java index e49c88a7..3483cd1f 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/MulticastUdpEndpointConfigVisitor.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/MulticastUdpEndpointConfigVisitor.java @@ -24,7 +24,6 @@ import java.net.InetAddress; -import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; @@ -36,7 +35,6 @@ import nl.teslanet.mule.connectors.coap.api.MulticastGroupConfig; import nl.teslanet.mule.connectors.coap.api.config.ConfigException; import nl.teslanet.mule.connectors.coap.api.config.MulticastParams; -import nl.teslanet.mule.connectors.coap.api.config.SocketParams; import nl.teslanet.mule.connectors.coap.internal.exceptions.EndpointConstructionException; @@ -95,33 +93,14 @@ public void visit( MulticastParams toVisit ) throws ConfigException } /** - * Visit socket parameters. - * @param toVisit The object to visit. + * Build the endpoint using the configuration this visitor has collected. + * @return The Endpoint. + * @throws EndpointConstructionException When the configuration cannot be used to create an endpoint. */ @Override - public void visit( SocketParams toVisit ) - { - //Do not call super visit because UDP endpoint bind configuration is not allowed by Cf when connector is set. - int port= ( toVisit.bindToPort != null ? toVisit.bindToPort : 0 ); - - if ( toVisit.bindToHost != null ) - { - connectorBuilder.setLocalAddress( new InetSocketAddress( toVisit.bindToHost, port ) ); - } - else - { - connectorBuilder.setLocalAddress( new InetSocketAddress( port ) ); - } - } - - /** - * Get the Builder that is ready to build the endpoint. - * @return The Endpoint Builder. - * @throws EndpointConstructionException When the configuration cannot be create an endpoint builder. - */ - @Override - public CoapEndpoint.Builder getEndpointBuilder() throws EndpointConstructionException + public CoapEndpoint getEndpoint() throws EndpointConstructionException { + connectorBuilder.setLocalAddress( getLocalAddress() ); if ( outgoingInterface != null ) { try @@ -179,10 +158,10 @@ public CoapEndpoint.Builder getEndpointBuilder() throws EndpointConstructionExce connectorBuilder.addMulticastGroup( groupAddress, networkInterface ); } } - endPointBuilder.setConfiguration( this.getConfiguration() ); + endpointBuilder.setConfiguration( this.getConfiguration() ); UdpMulticastConnector connector= connectorBuilder.build(); connector.setLoopbackMode( disableLoopback ); - endPointBuilder.setConnector( connector ); - return endPointBuilder; + endpointBuilder.setConnector( connector ); + return endpointBuilder.build(); } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/UdpEndpointConfigVisitor.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/UdpEndpointConfigVisitor.java new file mode 100644 index 00000000..efdbeb01 --- /dev/null +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/config/UdpEndpointConfigVisitor.java @@ -0,0 +1,51 @@ +/*- + * #%L + * Mule CoAP Connector + * %% + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben + * + * Contributors: + * (teslanet.nl) Rogier Cobben - initial creation + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + * #L% + */ +package nl.teslanet.mule.connectors.coap.internal.config; + + +import org.eclipse.californium.core.network.CoapEndpoint; +import org.eclipse.californium.elements.UDPConnector; + +import nl.teslanet.mule.connectors.coap.internal.exceptions.EndpointConstructionException; + + +/** + * Configuration visitor that collects UDP Endpoint configuration + * + */ +public class UdpEndpointConfigVisitor extends EndpointConfigVisitor +{ + /** + * Build the endpoint. + * @return The Endpoint. + * @throws EndpointConstructionException When the configuration cannot be used to create an endpoint. + */ + @Override + public CoapEndpoint getEndpoint() throws EndpointConstructionException + { + UDPConnector connector= new UDPConnector( getLocalAddress(), getConfiguration() ); + connector.setReuseAddress( isReuseAddress() ); + endpointBuilder.setConnector( connector ); + return endpointBuilder.build(); + } +} diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/endpoint/OperationalEndpoint.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/endpoint/OperationalEndpoint.java index 880261ce..069a0f8a 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/endpoint/OperationalEndpoint.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/endpoint/OperationalEndpoint.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -30,9 +30,14 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; +import org.eclipse.californium.core.coap.option.OptionDefinition; import org.eclipse.californium.core.network.CoapEndpoint; import org.eclipse.californium.core.network.interceptors.MessageTracer; +import org.mule.runtime.api.scheduler.Scheduler; +import org.mule.runtime.api.scheduler.SchedulerConfig; +import org.mule.runtime.api.scheduler.SchedulerService; import nl.teslanet.mule.connectors.coap.api.config.ConfigException; import nl.teslanet.mule.connectors.coap.api.config.endpoint.AbstractEndpoint; @@ -43,11 +48,10 @@ import nl.teslanet.mule.connectors.coap.api.config.endpoint.TLSClientEndpoint; import nl.teslanet.mule.connectors.coap.api.config.endpoint.TLSServerEndpoint; import nl.teslanet.mule.connectors.coap.api.config.endpoint.UDPEndpoint; -import nl.teslanet.mule.connectors.coap.internal.CoapConnector; import nl.teslanet.mule.connectors.coap.internal.client.Client; import nl.teslanet.mule.connectors.coap.internal.config.DtlsEndpointConfigVisitor; -import nl.teslanet.mule.connectors.coap.internal.config.EndpointConfigVisitor; import nl.teslanet.mule.connectors.coap.internal.config.MulticastUdpEndpointConfigVisitor; +import nl.teslanet.mule.connectors.coap.internal.config.UdpEndpointConfigVisitor; import nl.teslanet.mule.connectors.coap.internal.exceptions.EndpointConstructionException; import nl.teslanet.mule.connectors.coap.internal.server.Server; @@ -81,19 +85,29 @@ public final class OperationalEndpoint /** * The server using the endpoint */ - private Server server= null; + private Optional< Server > server= Optional.empty(); /** * The clients using the endpoint */ private HashSet< Client > clients= new HashSet<>(); + /** + * Flag indicating the schedulers are set. + */ + private boolean schedulerIsSet= false; + + /** + * Other options that the endpoint expects. + */ + private List< OptionDefinition > otherOptionsDefs; + /** * Create an endpoint not attached to a server or return existing when already created * @param config the configuration for the endpoint + * @param lightscheduler * @return the endpoint created from the configuration - * @throws EndpointConstructionException - * @throws Exception + * @throws EndpointConstructionException When the endpoint could not be constructed. */ private static OperationalEndpoint create( AbstractEndpoint config ) throws EndpointConstructionException { @@ -141,29 +155,30 @@ else if ( config instanceof TCPClientEndpoint ) /** * Create an endpoint attached to a server or return existing when already created * @param server the server attached to the endpint - * @param config the endpoint configuration + * @param config The endpoint configuration. * @return the operational endpoint * @throws EndpointConstructionException when endpoint cannot be created or used */ public static synchronized OperationalEndpoint getOrCreate( Server server, AbstractEndpoint config ) throws EndpointConstructionException { OperationalEndpoint operationalEndpoint= null; + Optional< Server > actualServer= Optional.of( server ); if ( registry.containsKey( config.configName ) ) { // endpoint already created operationalEndpoint= registry.get( config.configName ); // endpoint must match, multiple server usage of the endpoint is not allowed - if ( server != null && operationalEndpoint.server != null && server != operationalEndpoint.server ) + if ( operationalEndpoint.server.isPresent() && !operationalEndpoint.server.equals( actualServer ) ) { throw new EndpointConstructionException( ENDPOINT_MSG_PREFIX + config.configName + " }: usage by multiple servers not allowed." ); } - operationalEndpoint.server= server; + operationalEndpoint.server= actualServer; return operationalEndpoint; } // need to create endpoint operationalEndpoint= create( config ); - operationalEndpoint.server= server; + operationalEndpoint.server= actualServer; registry.put( operationalEndpoint.getConfigName(), operationalEndpoint ); return operationalEndpoint; } @@ -173,7 +188,7 @@ public static synchronized OperationalEndpoint getOrCreate( Server server, Abstr * @param client The client using this endpoint. * @param config The endpoint configuration. * @return OperationalEndpoint instance that applies to the endpoint configuration. - * @throws EndpointConstructionException When client parameter is empty + * @throws EndpointConstructionException When the endpoint could not be constructed. */ public static synchronized OperationalEndpoint getOrCreate( Client client, AbstractEndpoint config ) throws EndpointConstructionException { @@ -203,10 +218,11 @@ public static synchronized OperationalEndpoint getOrCreate( Client client, Abstr */ public static List< String > find( Server server ) { + Optional< Server > actualServer= Optional.of( server ); ArrayList< String > found= new ArrayList<>(); for ( Entry< String, OperationalEndpoint > entry : registry.entrySet() ) { - if ( entry.getValue().server == server ) + if ( actualServer.equals( entry.getValue().server ) ) { found.add( entry.getKey() ); } @@ -245,15 +261,14 @@ public static synchronized void disposeAll( Server server ) OperationalEndpoint endpoint= registry.get( endpointName ); if ( endpoint != null ) { - endpoint.server= null; - if ( endpoint.clients.isEmpty() && endpoint.server == null ) + endpoint.server= Optional.empty(); + if ( endpoint.clients.isEmpty() ) { registry.remove( endpointName ); endpoint.coapEndpoint.destroy(); } } } - freeEndpointResoures(); } /** @@ -271,36 +286,30 @@ public static synchronized void disposeAll( Client client ) if ( endpoint != null ) { endpoint.clients.remove( client ); - if ( endpoint.clients.isEmpty() && endpoint.server == null ) + if ( endpoint.clients.isEmpty() && !endpoint.server.isPresent() ) { registry.remove( endpointName ); endpoint.coapEndpoint.destroy(); } } } - freeEndpointResoures(); } /** - * Frees resources that are used by endpoints when possible. + * Get the name of this endpoint. + * @return the configured endpoint name */ - private static void freeEndpointResoures() + private String getConfigName() { - if ( registry.isEmpty() ) - { - //Schedulers are not needed any more, so stop them - CoapConnector.stopIoScheduler(); - CoapConnector.stopLightScheduler(); - } + return configName; } /** - * Get the name of this endpoint. - * @return the configured endpoint name + * @return the otherOptionsConfigs */ - private String getConfigName() + public List< OptionDefinition > getOtherOptionsDefs() { - return configName; + return otherOptionsDefs; } /** @@ -318,7 +327,7 @@ public CoapEndpoint getCoapEndpoint() */ private OperationalEndpoint( UDPEndpoint config ) throws EndpointConstructionException { - EndpointConfigVisitor visitor= new EndpointConfigVisitor(); + UdpEndpointConfigVisitor visitor= new UdpEndpointConfigVisitor(); try { config.accept( visitor ); @@ -328,8 +337,8 @@ private OperationalEndpoint( UDPEndpoint config ) throws EndpointConstructionExc throw new EndpointConstructionException( e ); } this.configName= visitor.getEndpointName(); - this.coapEndpoint= visitor.getEndpointBuilder().build(); - this.coapEndpoint.setExecutors( CoapConnector.getIoScheduler(), CoapConnector.getLightScheduler() ); + this.otherOptionsDefs= visitor.getOtherOptionDefs(); + this.coapEndpoint= visitor.getEndpoint(); } /** @@ -350,14 +359,14 @@ private OperationalEndpoint( MulticastUDPEndpoint config ) throws EndpointConstr throw new EndpointConstructionException( e ); } this.configName= visitor.getEndpointName(); - this.coapEndpoint= visitor.getEndpointBuilder().build(); - this.coapEndpoint.setExecutors( CoapConnector.getIoScheduler(), CoapConnector.getLightScheduler() ); + this.otherOptionsDefs= visitor.getOtherOptionDefs(); + this.coapEndpoint= visitor.getEndpoint(); } /** * Constructor for an operational DTLS endpoint. - * @param config the UDP endpoint configuration - * @throws EndpointConstructionException + * @param config The endpoint configuration. + * @throws EndpointConstructionException When the endpoint could not be constructed. */ private OperationalEndpoint( DTLSEndpoint config ) throws EndpointConstructionException { @@ -371,39 +380,69 @@ private OperationalEndpoint( DTLSEndpoint config ) throws EndpointConstructionEx throw new EndpointConstructionException( e ); } this.configName= visitor.getEndpointName(); - try - { - this.coapEndpoint= visitor.getEndpointBuilder().build(); - this.coapEndpoint.setExecutors( CoapConnector.getIoScheduler(), CoapConnector.getLightScheduler() ); - } - catch ( Exception e ) - { - throw new EndpointConstructionException( ENDPOINT_MSG_PREFIX + config.configName + " } construction DTLS Endpoint failed.", e ); - } + this.otherOptionsDefs= visitor.getOtherOptionDefs(); + this.coapEndpoint= visitor.getEndpoint(); } + /** + * Constructor for an operational TCP server endpoint. + * @param config The endpoint configuration. + * @throws EndpointConstructionException When the endpoint could not be constructed. + */ private OperationalEndpoint( TCPServerEndpoint config ) throws EndpointConstructionException { throw new EndpointConstructionException( ENDPOINT_MSG_PREFIX + config.configName + " } TCP Server Endpoint NIY." ); } + /** + * Constructor for an operational TCP client endpoint. + * @param config The endpoint configuration. + * @throws EndpointConstructionException + */ private OperationalEndpoint( TCPClientEndpoint config ) throws EndpointConstructionException { throw new EndpointConstructionException( ENDPOINT_MSG_PREFIX + config.configName + " } TCP Client Endpoint NIY." ); } + /** + * Constructor for an operational TLS serevr endpoint. + * @param config The endpoint configuration. + * @throws EndpointConstructionException When the endpoint could not be constructed. + */ private OperationalEndpoint( TLSServerEndpoint config ) throws EndpointConstructionException { throw new EndpointConstructionException( ENDPOINT_MSG_PREFIX + config.configName + " } TLS Server Endpoint NIY." ); } + /** + * Constructor for an operational TLS client endpoint. + * @param config The endpoint configuration. + * @throws EndpointConstructionException When the endpoint could not be constructed. + */ private OperationalEndpoint( TLSClientEndpoint config ) throws EndpointConstructionException { throw new EndpointConstructionException( ENDPOINT_MSG_PREFIX + config.configName + " } TLS Client Endpoint NIY." ); } - /* (non-Javadoc) - * @see java.lang.Object#toString() + /** + * Set the schedulers of the endpoint when needed. + * When the endpoint is used by a server the schedulers will be set by the server. + * @param schedulerService The SchedulerService that delivers the schedulers. + * @param schedulerConfig The scheduler configuration to use. + */ + public synchronized void setSchedulersIfNeeded( SchedulerService schedulerService, SchedulerConfig schedulerConfig ) + { + if ( !server.isPresent() && !schedulerIsSet ) + { + Scheduler ioScheduler= schedulerService.ioScheduler( schedulerConfig ); + Scheduler cpuLightScheduler= schedulerService.cpuLightScheduler( schedulerConfig ); + coapEndpoint.setExecutors( ioScheduler, cpuLightScheduler ); + schedulerIsSet= true; + } + } + + /** + * String representation of the object. */ public String toString() { diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/exceptions/InternalInvalidOptionValueException.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/exceptions/InternalInvalidOptionValueException.java index b275efab..53f3a192 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/exceptions/InternalInvalidOptionValueException.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/exceptions/InternalInvalidOptionValueException.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -35,43 +35,29 @@ public class InternalInvalidOptionValueException extends Exception private static final long serialVersionUID= 1L; /** - * Construct exception with given message. - * @param message Description of the exception + * Error message when alias is given. */ - public InternalInvalidOptionValueException( String message ) - { - super( message ); - } - - /** - * Construct exception with given message. - * @param message description of the exception - * @param cause underlying cause - */ - public InternalInvalidOptionValueException( String message, Throwable cause ) - { - super( message, cause ); - } + private static final String MSG_FORMAT_WITH_ALIAS= "Option{ %s } has invalid value: %s"; /** * Construct exception for an option with given message. - * @param optionName name of the option the exception occurred on + * @param alias The name of the option the exception occurred on * @param message description of the exception */ - public InternalInvalidOptionValueException( String optionName, String message ) + public InternalInvalidOptionValueException( String alias, String message ) { - super( "Value of option " + optionName + " is invalid, " + message ); + super( String.format( MSG_FORMAT_WITH_ALIAS, alias, message ) ); } /** * Construct exception for an option with given message. - * @param optionName name of the option the exception occurred on + * @param alias The name of the option the exception occurred on * @param message description of the exception * @param cause underlying cause */ - public InternalInvalidOptionValueException( String optionName, String message, Throwable cause ) + public InternalInvalidOptionValueException( String alias, String message, Throwable cause ) { - super( "Value of option " + optionName + " is invalid, " + message, cause ); + super( String.format( MSG_FORMAT_WITH_ALIAS, alias, message ), cause ); } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/exceptions/InternalUnkownOptionException.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/exceptions/InternalUnkownOptionException.java new file mode 100644 index 00000000..5c70b4a4 --- /dev/null +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/exceptions/InternalUnkownOptionException.java @@ -0,0 +1,83 @@ +/*- + * #%L + * Mule CoAP Connector + * %% + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben + * + * Contributors: + * (teslanet.nl) Rogier Cobben - initial creation + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + * #L% + */ +package nl.teslanet.mule.connectors.coap.internal.exceptions; + + +/** + * Exception that is thrown an option occurs that is not defined. + */ +public class InternalUnkownOptionException extends Exception +{ + /** + * Serial version id. + */ + private static final long serialVersionUID= 1L; + + /** + * Error message when number is given. + */ + private static final String MSG_FORMAT_WITH_NUMBER= "CoAP Option{ %d } is not defined on endpoint."; + + /** + * Error message when alias is given. + */ + private static final String MSG_FORMAT_WITH_ALIAS= "CoAP Option{ %s } is not defined on endpoint."; + + /** + * Construct exception for an option with given message. + * @param number The number of the unrecognized option. + */ + public InternalUnkownOptionException( int number ) + { + super( String.format( MSG_FORMAT_WITH_NUMBER, number ) ); + } + + /** + * Construct exception for an option with given message. + * @param number The number of the unrecognized option. + * @param cause The underlying cause. + */ + public InternalUnkownOptionException( int number, Throwable cause ) + { + super( String.format( MSG_FORMAT_WITH_NUMBER, number ), cause ); + } + + /** + * Construct exception for an option with given message. + * @param alias The name of the option the exception occurred on. + */ + public InternalUnkownOptionException( String alias ) + { + super( String.format( MSG_FORMAT_WITH_ALIAS, alias ) ); + } + + /** + * Construct exception for an option with given message. + * @param alias The name of the option the exception occurred on. + * @param cause The underlying cause. + */ + public InternalUnkownOptionException( String alias, Throwable cause ) + { + super( String.format( MSG_FORMAT_WITH_ALIAS, alias ), cause ); + } +} diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultOtherOptionAttribute.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultOtherOptionAttribute.java index 2bfbdc74..3db61219 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultOtherOptionAttribute.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultOtherOptionAttribute.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -23,26 +23,221 @@ package nl.teslanet.mule.connectors.coap.internal.options; -import static org.apache.commons.lang3.builder.ToStringStyle.DEFAULT_STYLE; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Objects; -import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.eclipse.californium.core.coap.Option; +import org.eclipse.californium.core.coap.option.OptionDefinition; +import nl.teslanet.mule.connectors.coap.api.config.options.OptionFormat; +import nl.teslanet.mule.connectors.coap.api.options.OptionUtils; import nl.teslanet.mule.connectors.coap.api.options.OtherOptionAttribute; +import nl.teslanet.mule.connectors.coap.internal.utils.MessageUtils; /** - * Query Parameter with expression support. + * Default other option attribute. */ -public final class DefaultOtherOptionAttribute extends OtherOptionAttribute +public final class DefaultOtherOptionAttribute implements OtherOptionAttribute { + /** + * Wrong type exception message format. + */ + private static final String FORMAT_WRONG_TYPE= "Option{ %s } is not of type %s."; + + /** + * The definition of the option. + */ + private final Option option; + /** * Constructor - * @param number The number of the option. - * @param value The value of the option. + * @param optionDef The definition of the other option. + * @param value The option value. + */ + public DefaultOtherOptionAttribute( OptionDefinition optionDef, byte[] value ) + { + super(); + this.option= optionDef.create( value ); + } + + /** + * Copy constructor from Cf Option + * @param option The Cf Option to copy from. + */ + public DefaultOtherOptionAttribute( Option option ) + { + super(); + this.option= option; + } + + /** + * Get the alias of this other option. + * @return The option alias. */ - public DefaultOtherOptionAttribute( int number, byte[] value ) + @Override + public String getAlias() + { + return option.getDefinition().getName(); + } + + /** + * Get the number of this other option. + * @return The option number. + */ + @Override + public int getNumber() + { + + return option.getDefinition().getNumber(); + } + + /** + * Get the format of this other option. + * @return The option format. + */ + @Override + public OptionFormat getFormat() + { + return MessageUtils.toOptionFormat( option.getDefinition().getFormat() ); + } + + /** + * Check if the option is empty. options whether it contains the option. + * @return True when the option is empty, otherwise false. + */ + @Override + public boolean isEmpty() + { + return option.getLength() == 0; + } + + /** + * Get the the length of the other option. + * @return The number of bytes of this option. + */ + @Override + public int getLength() + { + return option.getLength(); + } + + /** + * Get the value of this other option as byte array. + * @return The option value if any, otherwise null. + */ + protected byte[] getValueAsBytes() + { + return option.getValue(); + } + + /** + * Get the value of this other option. + * @return The option value if any, otherwise null. + */ + @Override + public InputStream getValue() + { + return OptionUtils.toInputStream( getValueAsBytes() ); + } + + /** + * Get the value as number. + * @return long containing the value. + */ + @Override + public long getValueAsNumber() + { + if ( option.getDefinition().getFormat() != org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat.INTEGER ) + throw new NumberFormatException( String.format( FORMAT_WRONG_TYPE, option.getDefinition().getName(), OptionFormat.INTEGER.toString() ) ); + return OptionUtils.toLong( option.getValue() ); + } + + /** + * Get the option value as hexadecimal string. + * Hexadecimal values a-f will be lower case. + * @return The string containing the hexadecimal representation or empty string when the value is empty. + */ + @Override + public String getValueAsHex() + { + return OptionUtils.toHexString( option.getValue() ); + } + + /** + * Get value as UTF-8 string. + * @return The UTF-8 string interpretation. + */ + @Override + public String getValueAsString() + { + if ( option.getDefinition().getFormat() != org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat.STRING ) + throw new NumberFormatException( String.format( FORMAT_WRONG_TYPE, option.getDefinition().getName(), OptionFormat.STRING.toString() ) ); + return option.getStringValue(); + } + + /** + * Checks if option is critical. + * @return {@code true} if is option critical, otherwise {@code false}. + */ + @Override + public boolean isCritical() + { + return OptionUtils.isCritical( getNumber() ); + } + + /** + * Checks if option with this number is unsafe. + * + * @return {@code true} if this is an unsafe option, otherwise {@code false}. + */ + @Override + public boolean isUnsafe() + { + return OptionUtils.isUnsafe( getNumber() ); + } + + /** + * Checks if option with this number is a NoCacheKey option. + * + * @return {@code true} if this is NoCacheKey option, otherwise {@code false}. + */ + @Override + public boolean isNoCacheKey() + { + return OptionUtils.isNoCacheKey( getNumber() ); + } + + /** + * Returns a hash code value for the object. + */ + @Override + public int hashCode() + { + final int prime= 31; + int result= 1; + result= prime * result + Objects.hash( getNumber() ); + result= prime * result + Arrays.hashCode( getValueAsBytes() ); + return result; + } + + /** + * Indicates whether some other object is "equal to" this. + */ + @Override + public boolean equals( Object obj ) { - super( number, value); + if ( this == obj ) + { + return true; + } + if ( !( obj instanceof DefaultOtherOptionAttribute ) ) + { + return false; + } + DefaultOtherOptionAttribute other= (DefaultOtherOptionAttribute) obj; + return ( getNumber() == other.getNumber() ) && Arrays.equals( getValueAsBytes(), other.getValueAsBytes() ); } /** @@ -51,6 +246,28 @@ public DefaultOtherOptionAttribute( int number, byte[] value ) @Override public String toString() { - return ReflectionToStringBuilder.toString( this, DEFAULT_STYLE ); + StringBuilder builder= new StringBuilder(); + builder.append( "Option{" ); + builder.append( " alias=" ).append( getAlias() ); + builder.append( ", number=" ).append( getNumber() ); + switch ( option.getDefinition().getFormat() ) + { + case EMPTY: + builder.append( ", empty" ); + break; + case INTEGER: + builder.append( ", valueAsNumber=" ).append( option.getLongValue() ); + break; + case STRING: + builder.append( ", valueAsString=" ).append( option.getStringValue() ); + break; + case OPAQUE: + case UNKNOWN: + default: + builder.append( ", valueAsHex=" ).append( OptionUtils.toHexString( option.getValue() ) ); + break; + } + builder.append( " }" ); + return builder.toString(); } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultRequestOptionsAttributes.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultRequestOptionsAttributes.java index ec9074b9..560049f6 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultRequestOptionsAttributes.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultRequestOptionsAttributes.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -23,9 +23,6 @@ package nl.teslanet.mule.connectors.coap.internal.options; -import static org.apache.commons.lang3.builder.ToStringStyle.MULTI_LINE_STYLE; - -import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -35,7 +32,7 @@ import nl.teslanet.mule.connectors.coap.api.entity.EntityTag; import nl.teslanet.mule.connectors.coap.api.entity.EntityTagException; -import nl.teslanet.mule.connectors.coap.api.options.OtherOptionAttribute; +import nl.teslanet.mule.connectors.coap.api.error.InvalidOptionValueException; import nl.teslanet.mule.connectors.coap.api.options.RequestOptionsAttributes; import nl.teslanet.mule.connectors.coap.api.query.QueryParamAttribute; import nl.teslanet.mule.connectors.coap.internal.attributes.AttributeUtils; @@ -48,6 +45,11 @@ */ public class DefaultRequestOptionsAttributes extends RequestOptionsAttributes { + /** + * Constructor that uses options from given optionSet. + * @param optionSet to copy from. + * @throws InvalidOptionValueException when given option value could not be copied successfully. + */ public DefaultRequestOptionsAttributes( OptionSet optionSet ) throws InternalInvalidOptionValueException { super(); @@ -132,9 +134,7 @@ public DefaultRequestOptionsAttributes( OptionSet optionSet ) throws InternalInv { observe= optionSet.getObserve(); } - ArrayList< OtherOptionAttribute > tmpOther= new ArrayList<>(); - optionSet.getOthers().forEach( option -> tmpOther.add( new DefaultOtherOptionAttribute( option.getNumber(), option.getValue() ) ) ); - otherOptions= Collections.unmodifiableList( tmpOther ); + other= AttributeUtils.createOthers( optionSet.getOthers() ); } /** @@ -143,6 +143,6 @@ public DefaultRequestOptionsAttributes( OptionSet optionSet ) throws InternalInv @Override public String toString() { - return ReflectionToStringBuilder.toString( this, MULTI_LINE_STYLE ); + return ReflectionToStringBuilder.toString( this, new ToStringStyle() ); } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultResponseOptionsAttributes.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultResponseOptionsAttributes.java index 53927c13..4b510fb6 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultResponseOptionsAttributes.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/DefaultResponseOptionsAttributes.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -23,9 +23,6 @@ package nl.teslanet.mule.connectors.coap.internal.options; -import static org.apache.commons.lang3.builder.ToStringStyle.MULTI_LINE_STYLE; - -import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; @@ -35,7 +32,6 @@ import nl.teslanet.mule.connectors.coap.api.entity.EntityTag; import nl.teslanet.mule.connectors.coap.api.entity.EntityTagException; import nl.teslanet.mule.connectors.coap.api.error.InvalidOptionValueException; -import nl.teslanet.mule.connectors.coap.api.options.OtherOptionAttribute; import nl.teslanet.mule.connectors.coap.api.options.ResponseOptionsAttributes; import nl.teslanet.mule.connectors.coap.api.query.QueryParamAttribute; import nl.teslanet.mule.connectors.coap.internal.attributes.AttributeUtils; @@ -99,9 +95,7 @@ public DefaultResponseOptionsAttributes( OptionSet optionSet ) throws InternalIn { observe= optionSet.getObserve(); } - ArrayList< OtherOptionAttribute > tmpOther= new ArrayList<>(); - optionSet.getOthers().forEach( option -> tmpOther.add( new DefaultOtherOptionAttribute( option.getNumber(), option.getValue() ) ) ); - otherOptions= Collections.unmodifiableList( tmpOther ); + other= AttributeUtils.createOthers( optionSet.getOthers() ); } /** @@ -110,6 +104,6 @@ public DefaultResponseOptionsAttributes( OptionSet optionSet ) throws InternalIn @Override public String toString() { - return ReflectionToStringBuilder.toString( this, MULTI_LINE_STYLE ); + return ReflectionToStringBuilder.toString( this, new ToStringStyle() ); } } diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/ToStringStyle.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/ToStringStyle.java new file mode 100644 index 00000000..927c0c21 --- /dev/null +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/options/ToStringStyle.java @@ -0,0 +1,48 @@ +/*- + * #%L + * Mule CoAP Connector + * %% + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben + * + * Contributors: + * (teslanet.nl) Rogier Cobben - initial creation + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + * #L% + */ +package nl.teslanet.mule.connectors.coap.internal.options; + + +import org.apache.commons.lang3.builder.MultilineRecursiveToStringStyle; + + +/** + * The to string style for attributes. + * + */ +public class ToStringStyle extends MultilineRecursiveToStringStyle +{ + /** + * Serial version. + */ + private static final long serialVersionUID= 1L; + + /** + * Constructor. + */ + public ToStringStyle() + { + this.setUseClassName( false ); + this.setUseIdentityHashCode( false ); + } +} diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/Listener.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/Listener.java index 87b8c619..932f08bc 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/Listener.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/Listener.java @@ -23,7 +23,6 @@ package nl.teslanet.mule.connectors.coap.internal.server; -import java.io.IOException; import java.io.InputStream; import javax.inject.Inject; @@ -59,7 +58,7 @@ import nl.teslanet.mule.connectors.coap.api.CoapRequestAttributes; import nl.teslanet.mule.connectors.coap.api.CoapResponseCode; import nl.teslanet.mule.connectors.coap.api.ResponseParams; -import nl.teslanet.mule.connectors.coap.api.error.InvalidEntityTagException; +import nl.teslanet.mule.connectors.coap.api.error.InvalidOptionValueException; import nl.teslanet.mule.connectors.coap.api.options.ResponseOptions; import nl.teslanet.mule.connectors.coap.internal.attributes.AttributeUtils; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalExchangeException; @@ -67,6 +66,7 @@ import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalInvalidOptionValueException; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalInvalidResponseCodeException; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalResourceUriException; +import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalUnkownOptionException; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalUriPatternException; import nl.teslanet.mule.connectors.coap.internal.options.MediaTypeMediator; import nl.teslanet.mule.connectors.coap.internal.utils.MessageUtils; @@ -197,10 +197,9 @@ public void onStart( SourceCallback< InputStream, CoapRequestAttributes > source * @param callbackContext * @throws InternalInvalidByteArrayValueException * @throws InternalInvalidResponseCodeException - * @throws IOException - * @throws InvalidEntityTagException - * @throws InternalInvalidOptionValueException * @throws InternalExchangeException + * @throws InternalUnkownOptionException When given option was not defined. + * @throws InvalidOptionValueException When given option value is invalid. */ @OnSuccess @MediaType( value= "*/*", strict= false ) @@ -221,7 +220,8 @@ public void onSuccess( ) throws InternalInvalidByteArrayValueException, InternalInvalidResponseCodeException, InternalInvalidOptionValueException, - InternalExchangeException + InternalExchangeException, + InternalUnkownOptionException { CoapResponseCode defaultCoapResponseCode= (CoapResponseCode) callbackContext.getVariable( Server.VARNAME_DEFAULT_RESPONSE_CODE ).orElseThrow( () -> new InternalInvalidResponseCodeException( "Internal error: no defaultCoAPResponseCode provided" ) @@ -231,7 +231,7 @@ public void onSuccess( coapResponse.getOptions().setContentFormat( MediaTypeMediator.toContentFormat( responsePayload.getDataType().getMediaType() ) ); if ( responseOptions != null ) { - MessageUtils.copyOptions( responseOptions, coapResponse.getOptions(), transformationService ); + MessageUtils.copyOptions( responseOptions, coapResponse.getOptions(), transformationService, server.getOtherOptionDefs() ); } //TODO add streaming & blockwise cooperation try diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/ServedResource.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/ServedResource.java index aa349a68..bfb2101d 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/ServedResource.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/ServedResource.java @@ -139,7 +139,6 @@ public class ServedResource extends CoapResource */ public ServedResource( ResourceConfig resource ) { - //TODO cf3 catch '/' exception super( resource.getResourceName() ); configure( resource ); @@ -410,7 +409,7 @@ private void handleRequest( SourceCallback< InputStream, CoapRequestAttributes > { if ( callback == null ) { - exchange.respond( ResponseCode.INTERNAL_SERVER_ERROR, "NO LISTENER" ); + exchange.respond( ResponseCode.NOT_IMPLEMENTED, "NO LISTENER" ); if ( LOGGER.isWarnEnabled( ERROR_RESPONSE_MARKER ) ) { try diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/Server.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/Server.java index c43d9a4d..7829c14b 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/Server.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/server/Server.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -25,11 +25,14 @@ import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import javax.inject.Inject; import org.eclipse.californium.core.CoapServer; import org.eclipse.californium.core.coap.CoAP; +import org.eclipse.californium.core.coap.option.OptionDefinition; import org.eclipse.californium.core.config.CoapConfig; import org.mule.runtime.api.exception.MuleException; import org.mule.runtime.api.lifecycle.Disposable; @@ -38,6 +41,7 @@ import org.mule.runtime.api.lifecycle.Startable; import org.mule.runtime.api.lifecycle.Stoppable; import org.mule.runtime.api.meta.ExpressionSupport; +import org.mule.runtime.api.scheduler.Scheduler; import org.mule.runtime.api.scheduler.SchedulerConfig; import org.mule.runtime.api.scheduler.SchedulerService; import org.mule.runtime.core.api.lifecycle.StartException; @@ -62,10 +66,10 @@ import nl.teslanet.mule.connectors.coap.api.config.endpoint.AdditionalEndpoint; import nl.teslanet.mule.connectors.coap.api.config.endpoint.Endpoint; import nl.teslanet.mule.connectors.coap.api.config.endpoint.UDPEndpoint; -import nl.teslanet.mule.connectors.coap.internal.CoapConnector; import nl.teslanet.mule.connectors.coap.internal.endpoint.OperationalEndpoint; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalResourceRegistryException; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalUriPatternException; +import nl.teslanet.mule.connectors.coap.internal.utils.MessageUtils; /** @@ -192,13 +196,17 @@ public class Server implements Initialisable, Disposable, Startable, Stoppable */ private ResourceRegistry registry= null; + /** + * Other options that the server expects. + */ + private ConcurrentHashMap< String, OptionDefinition > otherOptionDefs= new ConcurrentHashMap<>(); + /* (non-Javadoc) * @see org.mule.runtime.api.lifecycle.Initialisable#initialise() */ @Override public void initialise() throws InitialisationException { - CoapConnector.setSchedulerService( schedulerService, schedulerConfig ); org.eclipse.californium.elements.config.Configuration config= org.eclipse.californium.elements.config.Configuration.createStandardWithoutFile(); if ( protocolStageThreadCount != null ) { @@ -245,6 +253,21 @@ else if ( additionalEndpoints.isEmpty() ) { OperationalEndpoint operationalEndpoint= OperationalEndpoint.getOrCreate( this, configuredEndpoint ); coapServer.addEndpoint( operationalEndpoint.getCoapEndpoint() ); + for ( OptionDefinition optionDef : operationalEndpoint.getOtherOptionsDefs() ) + { + if ( otherOptionDefs.containsKey( optionDef.getName() ) ) + { + OptionDefinition presentDef= otherOptionDefs.get( optionDef.getName() ); + if ( !MessageUtils.isEqual( presentDef, optionDef ) ) + { + LOGGER.error( "{} receives conflicting other option {} from endpoint {}", this, optionDef.getName(), operationalEndpoint ); + } + } + else + { + otherOptionDefs.put( optionDef.getName(), optionDef ); + } + } LOGGER.info( "{} connected to {}", this, operationalEndpoint ); } catch ( Exception e ) @@ -262,6 +285,7 @@ else if ( additionalEndpoints.isEmpty() ) public void dispose() { coapServer.destroy(); + otherOptionDefs.clear(); OperationalEndpoint.disposeAll( this ); LOGGER.info( "{} disposed.", this ); } @@ -272,6 +296,9 @@ public void dispose() @Override public void start() throws MuleException { + Scheduler ioScheduler= schedulerService.ioScheduler( schedulerConfig ); + Scheduler cpuLightScheduler= schedulerService.cpuLightScheduler( schedulerConfig ); + coapServer.setExecutors( ioScheduler, cpuLightScheduler, true ); try { if ( resources != null ) @@ -280,8 +307,9 @@ public void start() throws MuleException { registry.add( null, resourceConfig ); } - coapServer.start(); } + + coapServer.start(); } catch ( Exception e ) { @@ -363,6 +391,14 @@ public ResourceRegistry getRegistry() return registry; } + /** + * @return the otherOptionDefs + */ + public ConcurrentMap< String, OptionDefinition > getOtherOptionDefs() + { + return otherOptionDefs; + } + /** * @return the resources */ @@ -395,6 +431,22 @@ public void setAdditionalEndpoints( List< AdditionalEndpoint > endpoints ) this.additionalEndpoints= endpoints; } + /** + * @return the schedulerService + */ + public SchedulerService getSchedulerService() + { + return schedulerService; + } + + /** + * @return the schedulerConfig + */ + public SchedulerConfig getSchedulerConfig() + { + return schedulerConfig; + } + /** * Get String repesentation. */ diff --git a/src/main/java/nl/teslanet/mule/connectors/coap/internal/utils/MessageUtils.java b/src/main/java/nl/teslanet/mule/connectors/coap/internal/utils/MessageUtils.java index bdb05c1d..b515c795 100644 --- a/src/main/java/nl/teslanet/mule/connectors/coap/internal/utils/MessageUtils.java +++ b/src/main/java/nl/teslanet/mule/connectors/coap/internal/utils/MessageUtils.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -27,20 +27,28 @@ import java.io.IOException; import java.io.StringWriter; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Map; import org.eclipse.californium.core.coap.BlockOption; import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.Option; import org.eclipse.californium.core.coap.OptionSet; +import org.eclipse.californium.core.coap.option.EmptyOptionDefinition; +import org.eclipse.californium.core.coap.option.IntegerOptionDefinition; import org.eclipse.californium.core.coap.option.OpaqueOptionDefinition; +import org.eclipse.californium.core.coap.option.OptionDefinition; +import org.eclipse.californium.core.coap.option.StringOptionDefinition; import org.eclipse.californium.elements.util.Bytes; import org.mule.runtime.api.metadata.TypedValue; import org.mule.runtime.api.transformation.TransformationService; +import nl.teslanet.mule.connectors.coap.api.config.options.OptionFormat; +import nl.teslanet.mule.connectors.coap.api.config.options.OtherOptionConfig; import nl.teslanet.mule.connectors.coap.api.entity.EntityTag; import nl.teslanet.mule.connectors.coap.api.entity.EntityTagException; import nl.teslanet.mule.connectors.coap.api.error.InvalidEntityTagException; @@ -53,6 +61,7 @@ import nl.teslanet.mule.connectors.coap.api.query.AbstractQueryParam; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalInvalidByteArrayValueException; import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalInvalidOptionValueException; +import nl.teslanet.mule.connectors.coap.internal.exceptions.InternalUnkownOptionException; /** @@ -73,9 +82,16 @@ private MessageUtils() * Copy options from {@link RequestOptions} to {@link OptionSet}. * @param requestOptions to copy from * @param optionSet to copy to - * @throws InvalidOptionValueException when given option value could not be copied + * @throws InternalUnkownOptionException When given option alias was not defined. + * @throws InvalidOptionValueException When given option value could not be copied */ - public static void copyOptions( RequestOptions requestOptions, OptionSet optionSet, TransformationService transformationService ) throws InternalInvalidOptionValueException + public static void copyOptions( + RequestOptions requestOptions, + OptionSet optionSet, + TransformationService transformationService, + Map< String, OptionDefinition > otherOptionDefs + ) throws InternalInvalidOptionValueException, + InternalUnkownOptionException { if ( requestOptions.isIfExists() ) { @@ -94,7 +110,7 @@ public static void copyOptions( RequestOptions requestOptions, OptionSet optionS } catch ( EntityTagException e ) { - throw new InternalInvalidOptionValueException( "If-Match", "", e ); + throw new InternalInvalidOptionValueException( "If-Match", e.getMessage(), e ); } } if ( requestOptions.getEtags() != null ) @@ -134,21 +150,36 @@ public static void copyOptions( RequestOptions requestOptions, OptionSet optionS { optionSet.setSize1( requestOptions.getRequestSize() ); } - for ( OtherOption otherOption : requestOptions.getOtherRequestOptions() ) + for ( OtherOption otherOption : requestOptions.getOtherOptions() ) { - optionSet.addOption( toCfOtherOption( otherOption, transformationService ) ); + OptionDefinition definition= otherOptionDefs.get( otherOption.getAlias() ); + if ( definition != null ) + { + optionSet.addOption( toCfOtherOption( otherOption, definition, transformationService ) ); + } + else + { + throw new InternalUnkownOptionException( "Unknown other option: " + otherOption.getAlias() ); + } } } /** * Copy options from {@link ResponseOptions} to {@link OptionSet}. - * @param responseOptions to copy from - * @param optionSet to copy to - * @throws InternalInvalidOptionValueException - * @throws InvalidEntityTagException when an option containes invalid ETag value - * @throws IOException when an option stream throws an error. + * @param responseOptions The options to copy. + * @param optionSet The set to copy to. + * @throws InternalInvalidOptionValueException When given option value is invalid. + * @throws InternalUnkownOptionException When given option alias was not defined. + * @throws InvalidEntityTagException When an option contains invalid ETag value. + * @throws IOException When an option stream throws an error. */ - public static void copyOptions( ResponseOptions responseOptions, OptionSet optionSet, TransformationService transformationService ) throws InternalInvalidOptionValueException + public static void copyOptions( + ResponseOptions responseOptions, + OptionSet optionSet, + TransformationService transformationService, + Map< String, OptionDefinition > otherOptionDefs + ) throws InternalInvalidOptionValueException, + InternalUnkownOptionException { if ( responseOptions.getEtag() != null ) { @@ -190,36 +221,108 @@ public static void copyOptions( ResponseOptions responseOptions, OptionSet optio { optionSet.setSize1( responseOptions.getAcceptableRequestSize() ); } - for ( OtherOption otherOption : responseOptions.getOtherResponseOptions() ) + for ( OtherOption otherOption : responseOptions.getOtherOptions() ) { - optionSet.addOption( toCfOtherOption( otherOption, transformationService ) ); + OptionDefinition definition= otherOptionDefs.get( otherOption.getAlias() ); + if ( definition != null ) + { + optionSet.addOption( toCfOtherOption( otherOption, definition, transformationService ) ); + } + else + { + throw new InternalUnkownOptionException( "Unknown other option: " + otherOption.getAlias() ); + } } } + /** + * Convert other option configuration to Cf option definition. + * @param config The option config to create definition from. + * @return The created definition. + */ + public static OptionDefinition toCfOptionDefinition( OtherOptionConfig config ) + { + OptionDefinition definition; + switch ( config.getFormat() ) + { + case EMPTY: + definition= new EmptyOptionDefinition( config.getNumber(), config.getAlias() ); + break; + case INTEGER: + definition= new IntegerOptionDefinition( config.getNumber(), config.getAlias(), config.isSingleValue(), config.getMinBytes(), config.getMaxBytes() ); + break; + case STRING: + definition= new StringOptionDefinition( config.getNumber(), config.getAlias(), config.isSingleValue(), config.getMinBytes(), config.getMaxBytes() ); + break; + case OPAQUE: + default: + definition= new OpaqueOptionDefinition( config.getNumber(), config.getAlias(), config.isSingleValue(), config.getMinBytes(), config.getMaxBytes() ); + break; + } + return definition; + } + + /** + * Establish equality of two option definitions based on their properties. + * @param left The first option definition. + * @param right The second option definition. + * @return {@code true} when the definition are equal otherwise {@code false} + */ + //TODO cf need equals method. + @SuppressWarnings( "deprecation" ) + public static boolean isEqual( OptionDefinition left, OptionDefinition right ) + { + if ( left == right ) return true; + if ( left == null || right == null ) return false; + return( left.getName().equals( right.getName() ) && left.getFormat() == right.getFormat() && left.getNumber() == right.getNumber() + && left.isSingleValue() == right.isSingleValue() && Arrays.equals( left.getValueLengths(), right.getValueLengths() ) ); + } + /** * Convert to Cf other option. * @param otherOption The other option to convert. + * @param definition The definition of the option. * @param transformationService The service use for value transformation. * @return The Cf option. * @throws InternalInvalidOptionValueException When the value could not be converted. */ - private static Option toCfOtherOption( OtherOption otherOption, TransformationService transformationService ) throws InternalInvalidOptionValueException + private static Option toCfOtherOption( OtherOption otherOption, OptionDefinition definition, TransformationService transformationService ) + throws InternalInvalidOptionValueException { Option option; try { - option= new Option( - new OpaqueOptionDefinition( otherOption.getNumber(), String.valueOf( otherOption.getNumber() ), false ), - toBytes( otherOption.getValue(), transformationService ) - ); + option= new Option( definition, toBytes( otherOption.getValue(), transformationService ) ); } catch ( Exception e ) { - throw new InternalInvalidOptionValueException( "Other-Option", "Number { " + otherOption.getNumber() + " }", e ); + throw new InternalInvalidOptionValueException( otherOption.getAlias(), e.getMessage(), e ); } return option; } + /** + * Convert Cf format to option format. + * @param format The Cf option format. + * @return The option format. + */ + public static OptionFormat toOptionFormat( org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat format ) + { + switch ( format ) + { + case EMPTY: + return OptionFormat.EMPTY; + case INTEGER: + return OptionFormat.INTEGER; + case STRING: + return OptionFormat.STRING; + case OPAQUE: + case UNKNOWN: + default: + return OptionFormat.OPAQUE; + } + } + /** * Convert an object to byte array. * @param toConvert The object to convert. diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/AbstractOtherOptionInboundPropertyTestCase.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/AbstractOtherOptionInboundPropertyTestCase.java index e9b5f1af..97858622 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/AbstractOtherOptionInboundPropertyTestCase.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/AbstractOtherOptionInboundPropertyTestCase.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -26,8 +26,11 @@ import java.util.Collections; import java.util.LinkedList; +import org.eclipse.californium.core.coap.option.OpaqueOptionDefinition; + import nl.teslanet.mule.connectors.coap.api.CoapResponseAttributes; import nl.teslanet.mule.connectors.coap.api.options.OtherOptionAttribute; +import nl.teslanet.mule.connectors.coap.test.utils.TestOtherOptionAttribute; /** @@ -36,6 +39,8 @@ */ public abstract class AbstractOtherOptionInboundPropertyTestCase extends AbstractInboundPropertyTestCase { + abstract protected String getOptionAlias(); + abstract protected int getOptionNumber(); abstract protected byte[][] getOptionValues(); @@ -46,15 +51,7 @@ public abstract class AbstractOtherOptionInboundPropertyTestCase extends Abstrac @Override protected Object fetchInboundProperty( CoapResponseAttributes attributes ) { - LinkedList< OtherOptionAttribute > found= new LinkedList<>(); - for ( OtherOptionAttribute otherOption : attributes.getOptions().getOtherOptions() ) - { - if ( otherOption.getNumber() == getOptionNumber() ) - { - found.add( otherOption ); - } - } - return Collections.unmodifiableList( found ); + return attributes.getOptions().getOther().getAll( getOptionAlias() ); } /** @@ -66,7 +63,7 @@ protected Object getExpectedInboundPropertyValue() LinkedList< OtherOptionAttribute > list= new LinkedList<>(); for ( int i= 0; i < getOptionValues().length; i++ ) { - OtherOptionAttribute otherOption= new OtherOptionAttribute( getOptionNumber(), getOptionValues()[i] ); + OtherOptionAttribute otherOption= new TestOtherOptionAttribute( new OpaqueOptionDefinition( getOptionNumber(), getOptionAlias() ), getOptionValues()[i] ); list.add( otherOption ); } return Collections.unmodifiableList( list ); @@ -81,7 +78,7 @@ protected PropertyType getPropertyType() { return PropertyType.CollectionOfObject; } - + /* (non-Javadoc) * @see nl.teslanet.mule.transport.coap.client.test.properties.AbstractInboundPropertyTestCase#getStrategy() */ diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/AbstractOutboundPropertiesTestCase.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/AbstractOutboundPropertiesTestCase.java index 88d250c4..a41cda13 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/AbstractOutboundPropertiesTestCase.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/AbstractOutboundPropertiesTestCase.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -101,12 +101,12 @@ protected String getResourcePath() protected abstract String getPropertyName(); /** - * The property nr to set on outbound test - * @return the nr to set + * The alias of the option to set on outbound test + * @return the alias. */ - protected int getOutboundOptionNr() + protected String getOutboundOptionAlias() { - return 0; + return null; } /** @@ -233,6 +233,6 @@ private Event runFlow() throws EntityTagException, Exception return flowRunner( "do_request-" + getFlowNameExtension() ).withPayload( "nothing_important" ).withVariable( "requestCode", requestCode ).withVariable( "host", "127.0.0.1" - ).withVariable( "path", getResourcePath() ).withVariable( "option", getOutboundPropertyValue() ).withVariable( "other", getOutboundOptionNr() ).run(); + ).withVariable( "path", getResourcePath() ).withVariable( "option", getOutboundPropertyValue() ).withVariable( "other", getOutboundOptionAlias() ).run(); } } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/DefaultResponseOptionsAttributesTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/DefaultResponseOptionsAttributesTest.java index 0b8a0946..83d0345c 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/DefaultResponseOptionsAttributesTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/DefaultResponseOptionsAttributesTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -30,11 +30,13 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map.Entry; import org.eclipse.californium.core.coap.Option; import org.eclipse.californium.core.coap.OptionSet; import org.eclipse.californium.core.coap.option.OpaqueOptionDefinition; import org.junit.Test; +import org.mule.runtime.api.util.MultiMap; import org.mule.runtime.core.api.util.IOUtils; import nl.teslanet.mule.connectors.coap.api.entity.EntityTag; @@ -203,18 +205,21 @@ public void testOptionOther() throws EntityTagException, InternalInvalidOptionVa ArrayList< DefaultOtherOptionAttribute > expected= new ArrayList<>(); for ( int i= 0; i < 4; i++ ) { - expected.add( new DefaultOtherOptionAttribute( optionsDefs[i].getNumber(), values[i].clone() ) ); + expected.add( new DefaultOtherOptionAttribute( optionsDefs[i], values[i].clone() ) ); set.addOption( new Option( optionsDefs[i], values[i].clone() ) ); } DefaultResponseOptionsAttributes attributes= new DefaultResponseOptionsAttributes( set ); - List< OtherOptionAttribute > options= attributes.getOtherOptions(); + MultiMap< String, OtherOptionAttribute > options= attributes.getOther(); assertEquals( "coap.opt.other has wrong length", expected.size(), options.size() ); - for ( int i= 0; i < 4; i++ ) + int j= 0; + for ( Entry< String, OtherOptionAttribute > entry : options.entryList() ) { - assertEquals( "coap.opt.other has wrong number", expected.get( i ).getNumber(), options.get( i ).getNumber() ); - assertArrayEquals( "coap.opt.other has wrong value", IOUtils.toByteArray( expected.get( i ).getValue() ), IOUtils.toByteArray( options.get( i ).getValue() ) ); + assertEquals( "coap.opt.other has wrong number", expected.get( j ).getNumber(), entry.getValue().getNumber() ); + assertArrayEquals( "coap.opt.other has wrong value", IOUtils.toByteArray( expected.get( j ).getValue() ), IOUtils.toByteArray( entry.getValue().getValue() ) ); + j++; } + assertEquals( "wrong option count", 4, j ); } } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1CriticalTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1CriticalTest.java index b5b3bbe1..b4343c8c 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1CriticalTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1CriticalTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".critical"; } + @Override + protected String getOptionAlias() + { + return "option-65012"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1NoCacheKeyTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1NoCacheKeyTest.java index 4c0c58b3..7c10fc4c 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1NoCacheKeyTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1NoCacheKeyTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".no_cache_key"; } + @Override + protected String getOptionAlias() + { + return "option-65012"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1Test.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1Test.java index f226b6b3..74bce9f2 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1Test.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1Test.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -22,13 +22,14 @@ */ package nl.teslanet.mule.connectors.coap.test.client.properties; + /** * Test inbound other option property * */ public class OptOtherInbound1Test extends AbstractOtherOptionInboundPropertyTestCase { - byte[][] values= {{ (byte) 0x12, (byte) 0xFF, (byte) 0x45 }}; + byte[][] values= { { (byte) 0x12, (byte) 0xFF, (byte) 0x45 } }; @Override protected String getPropertyName() @@ -36,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber(); } + @Override + protected String getOptionAlias() + { + return "option-65012"; + } + @Override protected int getOptionNumber() { @@ -45,6 +52,6 @@ protected int getOptionNumber() @Override protected byte[][] getOptionValues() { - return values; + return values; } } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1UnsafeTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1UnsafeTest.java index 7b6e848e..bce1e2c2 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1UnsafeTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound1UnsafeTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".unsafe"; } + @Override + protected String getOptionAlias() + { + return "option-65012"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2CriticalTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2CriticalTest.java index c3c565cf..3ab97823 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2CriticalTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2CriticalTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".critical"; } + @Override + protected String getOptionAlias() + { + return "option-65013"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2NoCacheKeyTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2NoCacheKeyTest.java index 211411f2..876f19a2 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2NoCacheKeyTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2NoCacheKeyTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".no_cache_key"; } + @Override + protected String getOptionAlias() + { + return "option-65013"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2Test.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2Test.java index b623aa42..3d5c47a7 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2Test.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2Test.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -22,13 +22,14 @@ */ package nl.teslanet.mule.connectors.coap.test.client.properties; + /** * Test inbound other option property * */ public class OptOtherInbound2Test extends AbstractOtherOptionInboundPropertyTestCase { - byte[][] values= {{ (byte) 0x12, (byte) 0x00, (byte) 0x45, (byte) 0x33 }}; + byte[][] values= { { (byte) 0x12, (byte) 0x00, (byte) 0x45, (byte) 0x33 } }; @Override protected String getPropertyName() @@ -36,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber(); } + @Override + protected String getOptionAlias() + { + return "option-65013"; + } + @Override protected int getOptionNumber() { @@ -45,6 +52,6 @@ protected int getOptionNumber() @Override protected byte[][] getOptionValues() { - return values; + return values; } } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2UnsafeTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2UnsafeTest.java index 10c58152..0b1c8ac7 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2UnsafeTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound2UnsafeTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".unsafe"; } + @Override + protected String getOptionAlias() + { + return "option-65013"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3CriticalTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3CriticalTest.java index e194a6c5..a8beb795 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3CriticalTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3CriticalTest.java @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".critical"; } + @Override + protected String getOptionAlias() + { + return "option-65308"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3NoCacheKeyTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3NoCacheKeyTest.java index ca83c525..3abeeefd 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3NoCacheKeyTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3NoCacheKeyTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".no_cache_key"; } + @Override + protected String getOptionAlias() + { + return "option-65308"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3Test.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3Test.java index 9de1a568..bd05b7e4 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3Test.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3Test.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber(); } + @Override + protected String getOptionAlias() + { + return "option-65308"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3UnsafeTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3UnsafeTest.java index ac700d64..2734111e 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3UnsafeTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound3UnsafeTest.java @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".unsafe"; } + @Override + protected String getOptionAlias() + { + return "option-65308"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4CriticalTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4CriticalTest.java index efc219cc..eb46d075 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4CriticalTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4CriticalTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".unsafe"; } + @Override + protected String getOptionAlias() + { + return "option-65008"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4NoCacheKeyTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4NoCacheKeyTest.java index 4157f96f..d470ef72 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4NoCacheKeyTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4NoCacheKeyTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".no_cache_key"; } + @Override + protected String getOptionAlias() + { + return "option-65008"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4Test.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4Test.java index 5d2eaae7..795c5170 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4Test.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4Test.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber(); } + @Override + protected String getOptionAlias() + { + return "option-65008"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4UnsafeTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4UnsafeTest.java index 789c1e42..fcadfdbb 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4UnsafeTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound4UnsafeTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".unsafe"; } + @Override + protected String getOptionAlias() + { + return "option-65008"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5CriticalTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5CriticalTest.java index d711fbe7..4434a3cc 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5CriticalTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5CriticalTest.java @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".critical"; } + @Override + protected String getOptionAlias() + { + return "option-65010"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5NoCacheKeyTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5NoCacheKeyTest.java index 19740cb8..66cb006c 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5NoCacheKeyTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5NoCacheKeyTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".no_cache_key"; } + @Override + protected String getOptionAlias() + { + return "option-65010"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5Test.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5Test.java index 7c975be9..d13640a0 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5Test.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5Test.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber(); } + @Override + protected String getOptionAlias() + { + return "option-65010"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5UnsafeTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5UnsafeTest.java index 5fe81d52..a6979254 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5UnsafeTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInbound5UnsafeTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -37,6 +37,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber() + ".unsafe"; } + @Override + protected String getOptionAlias() + { + return "option-65010"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedCriticalTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedCriticalTest.java index d6dd8553..dcddc2ac 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedCriticalTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedCriticalTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -47,6 +47,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber(); } + @Override + protected String getOptionAlias() + { + return "option-65009"; + } + @Override protected int getOptionNumber() { diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedNoCacheKeyTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedNoCacheKeyTest.java index 54d681dd..11c16940 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedNoCacheKeyTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedNoCacheKeyTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -41,6 +41,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber(); } + @Override + protected String getOptionAlias() + { + return "option-65020"; + } + @Override protected int getOptionNumber() { @@ -59,7 +65,7 @@ protected byte[][] getOptionValues() @Override protected Object getExpectedInboundPropertyValue() { - //TODO cf3 option in response is ignored silently + //TODO option in response is ignored silently by cf return Collections.unmodifiableList( new LinkedList<>() ); } } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedTest.java index 204ffd76..fb2fd467 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -41,6 +41,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber(); } + @Override + protected String getOptionAlias() + { + return "option-65304"; + } + @Override protected int getOptionNumber() { @@ -59,7 +65,7 @@ protected byte[][] getOptionValues() @Override protected Object getExpectedInboundPropertyValue() { - //TODO cf3 option in response is ignored silently + //TODO option in response is ignored silently by cf return Collections.unmodifiableList( new LinkedList<>() ); } } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedUnsafeTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedUnsafeTest.java index 2c1a4575..6529d83a 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedUnsafeTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherInboundUnsupportedUnsafeTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -41,6 +41,12 @@ protected String getPropertyName() return "coap.opt.other." + getOptionNumber(); } + @Override + protected String getOptionAlias() + { + return "option-65018"; + } + @Override protected int getOptionNumber() { @@ -59,7 +65,7 @@ protected byte[][] getOptionValues() @Override protected Object getExpectedInboundPropertyValue() { - //TODO cf3 option in response is ignored silently + //TODO option in response is ignored silently by cf return Collections.unmodifiableList( new LinkedList<>() ); } } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound1Test.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound1Test.java index a3da9a29..dbc5d2ce 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound1Test.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound1Test.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -51,9 +51,9 @@ protected String getPropertyName() } @Override - protected int getOutboundOptionNr() + protected String getOutboundOptionAlias() { - return getOption().getNumber(); + return getOption().getDefinition().getName(); } @Override diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound2Test.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound2Test.java index 652784ac..be13a267 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound2Test.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound2Test.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -54,9 +54,9 @@ protected String getPropertyName() } @Override - protected int getOutboundOptionNr() + protected String getOutboundOptionAlias() { - return getOption().getNumber(); + return getOption().getDefinition().getName(); } /* (non-Javadoc) diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound3Test.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound3Test.java index 0c1bb7d0..46afa6a9 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound3Test.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutbound3Test.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -51,9 +51,9 @@ protected String getPropertyName() } @Override - protected int getOutboundOptionNr() + protected String getOutboundOptionAlias() { - return getOption().getNumber(); + return getOption().getDefinition().getName(); } @Override diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedCriticalTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedCriticalTest.java index 2416ccd8..91d0c159 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedCriticalTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedCriticalTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -55,9 +55,9 @@ protected String getPropertyName() } @Override - protected int getOutboundOptionNr() + protected String getOutboundOptionAlias() { - return getOption().getNumber(); + return getOption().getDefinition().getName(); } @Override diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedNoCacheKeyTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedNoCacheKeyTest.java index f4bae881..5b1f801e 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedNoCacheKeyTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedNoCacheKeyTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -28,8 +28,7 @@ import org.eclipse.californium.core.coap.Option; import nl.teslanet.mule.connectors.coap.test.utils.TestOptions; - -//TDOD cf3 unsupported option is sent. +import nl.teslanet.mule.connectors.coap.api.error.RequestException; /** @@ -55,9 +54,15 @@ protected String getPropertyName() } @Override - protected int getOutboundOptionNr() + protected Exception getExpectedException() + { + return new RequestException( "CoAP Client { config } failed to execute request." ); + } + + @Override + protected String getOutboundOptionAlias() { - return getOption().getNumber(); + return getOption().getDefinition().getName(); } @Override diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedTest.java index 446972fe..d2239981 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -27,6 +27,7 @@ import org.eclipse.californium.core.coap.Option; +import nl.teslanet.mule.connectors.coap.api.error.RequestException; import nl.teslanet.mule.connectors.coap.test.utils.TestOptions; //TDOD cf3 unsupported option is sent. @@ -55,9 +56,15 @@ protected String getPropertyName() } @Override - protected int getOutboundOptionNr() + protected String getOutboundOptionAlias() { - return getOption().getNumber(); + return getOption().getDefinition().getName(); + } + + @Override + protected Exception getExpectedException() + { + return new RequestException( "CoAP Client { config } failed to execute request." ); } @Override diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedUnsafeTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedUnsafeTest.java index b7223b5b..09facc98 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedUnsafeTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/client/properties/OptOtherOutboundUnsupportedUnsafeTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -27,6 +27,7 @@ import org.eclipse.californium.core.coap.Option; +import nl.teslanet.mule.connectors.coap.api.error.RequestException; import nl.teslanet.mule.connectors.coap.test.utils.TestOptions; //TDOD cf3 unsupported option is sent. @@ -55,9 +56,15 @@ protected String getPropertyName() } @Override - protected int getOutboundOptionNr() + protected String getOutboundOptionAlias() { - return getOption().getNumber(); + return getOption().getDefinition().getName(); + } + + @Override + protected Exception getExpectedException() + { + return new RequestException( "CoAP Client { config } failed to execute request." ); } @Override diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/config/ConfigParam.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/config/ConfigParam.java index cd12d09d..dbcb441c 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/config/ConfigParam.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/config/ConfigParam.java @@ -36,11 +36,18 @@ */ public enum ConfigParam { - // endpoint - logCoapMessages(null), - bindToHost(null), - bindToPort(null), - bindToSecurePort(null), + //endpoint + ENDPOINT_LOGCOAPMESSAGES(null), + ENDPOINT_BINDTOHOST(null), + ENDPOINT_BINDTOPORT(null), + ENDPOINT_BINDTOSECUREPORT(null), + ENDPOINT_REUSEADDRESS(null), + ENDPOINT_OTHEROPTION_ALIAS(null), + ENDPOINT_OTHEROPTION_NUMBER(null), + ENDPOINT_OTHEROPTION_TYPE(null), + ENDPOINT_OTHEROPTION_SINGLEVALUE(null), + ENDPOINT_OTHEROPTION_MINBYTES(null), + ENDPOINT_OTHEROPTION_MAXBYTES(null), // module COAP maxActivePeers(CoapConfig.MAX_ACTIVE_PEERS), @@ -94,6 +101,10 @@ public enum ConfigParam // all deduplicators deduplicationAutoReplace(CoapConfig.DEDUPLICATOR_AUTO_REPLACE), + //coap on endpoint level + responseMatching(CoapConfig.RESPONSE_MATCHING), + strictEmptyMessageFormat(CoapConfig.STRICT_EMPTY_MESSAGE_FORMAT), + //dtls params //DTLS_SESSION_TIMEOUT(DtlsConfig.DTLS_SESSION_TIMEOUT), //not supported by cf @@ -105,7 +116,7 @@ public enum ConfigParam DTLS_RETRANSMISSION_INIT_RANDOM(DtlsConfig.DTLS_RETRANSMISSION_INIT_RANDOM), DTLS_RETRANSMISSION_TIMEOUT_SCALE(DtlsConfig.DTLS_RETRANSMISSION_TIMEOUT_SCALE), DTLS_RETRANSMISSION_BACKOFF(DtlsConfig.DTLS_RETRANSMISSION_BACKOFF), - SUPPORT_CONNECTION_ID(DtlsConfig.DTLS_CONNECTION_ID_LENGTH), + DTLS_SUPPORT_CONNECTION_ID(DtlsConfig.DTLS_CONNECTION_ID_LENGTH), DTLS_SERVER_USE_SESSION_ID(DtlsConfig.DTLS_SERVER_USE_SESSION_ID), DTLS_USE_EARLY_STOP_RETRANSMISSION(DtlsConfig.DTLS_USE_EARLY_STOP_RETRANSMISSION), DTLS_RECORD_SIZE_LIMIT(DtlsConfig.DTLS_RECORD_SIZE_LIMIT), @@ -155,10 +166,6 @@ public enum ConfigParam DTLS_MAC_ERROR_FILTER_QUIET_TIME(DtlsConfig.DTLS_MAC_ERROR_FILTER_QUIET_TIME), DTLS_MAC_ERROR_FILTER_THRESHOLD(DtlsConfig.DTLS_MAC_ERROR_FILTER_THRESHOLD), - //endpoint level. - responseMatching(CoapConfig.RESPONSE_MATCHING), - strictEmptyMessageFormat(CoapConfig.STRICT_EMPTY_MESSAGE_FORMAT), - //secure pskHost(null), pskPort(null), @@ -175,14 +182,6 @@ public enum ConfigParam //server protocolStageThreadCount(CoapConfig.PROTOCOL_STAGE_THREAD_COUNT), - //endpoint - ENDPOINT_OTHEROPTION_ALIAS(null), - ENDPOINT_OTHEROPTION_NUMBER(null), - ENDPOINT_OTHEROPTION_TYPE(null), - ENDPOINT_OTHEROPTION_SINGLEVALUE(null), - ENDPOINT_OTHEROPTION_MINBYTES(null), - ENDPOINT_OTHEROPTION_MAXBYTES(null), - //module udp UDP_RECEIVER_THREAD_COUNT(UdpConfig.UDP_RECEIVER_THREAD_COUNT), UDP_SENDER_THREAD_COUNT(UdpConfig.UDP_SENDER_THREAD_COUNT), diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/config/ConfigParams.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/config/ConfigParams.java index 14341610..564c03fe 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/config/ConfigParams.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/config/ConfigParams.java @@ -171,14 +171,16 @@ static ConfigDescription getConfigDescription( ConfigParam param ) throws Except switch ( param ) { //from EndpointConfig - case logCoapMessages: + case ENDPOINT_LOGCOAPMESSAGES: return new ConfigDescription( param, "false", "false", "true", null, ConfigDescription.TEST_ALL ); - case bindToHost: + case ENDPOINT_BINDTOHOST: return new ConfigDescription( param, null, null, "somehost.org", "somehost.org", ConfigDescription.TEST_ALL ); - case bindToPort: + case ENDPOINT_BINDTOPORT: return new ConfigDescription( param, null, "5683", "9983", "9983", ConfigDescription.TEST_UDP | ConfigDescription.TEST_DTLS ); - case bindToSecurePort: - return new ConfigDescription( param, null, "5684", "9984", "9984", ConfigDescription.TEST_DTLS ); + case ENDPOINT_BINDTOSECUREPORT: + return new ConfigDescription( param, null, "5683", "9983", "9983", ConfigDescription.TEST_UDP | ConfigDescription.TEST_DTLS ); + case ENDPOINT_REUSEADDRESS: + return new ConfigDescription( param, "false", "false", "true", "true", ConfigDescription.TEST_ALL ); case maxActivePeers: return new ConfigDescription( param, null, "150000", "25", "25", ConfigDescription.TEST_ALL ); case maxPeerInactivityPeriod: @@ -334,7 +336,7 @@ static ConfigDescription getConfigDescription( ConfigParam param ) throws Except return new ConfigDescription( param, null, "2.0", "3.3", "3.3", ConfigDescription.TEST_DTLS ); case DTLS_RETRANSMISSION_BACKOFF: return new ConfigDescription( param, null, null, "3", "3", ConfigDescription.TEST_DTLS ); - case SUPPORT_CONNECTION_ID: + case DTLS_SUPPORT_CONNECTION_ID: return new ConfigDescription( param, null, null, "true", "0", ConfigDescription.TEST_DTLS ); case DTLS_CONNECTION_ID_LENGTH: return new ConfigDescription( param, null, null, "5", "5", ConfigDescription.TEST_DTLS ); diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/config/GetValueVisitor.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/config/GetValueVisitor.java index 0e4bc73b..06f25c28 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/config/GetValueVisitor.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/config/GetValueVisitor.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * Contributors: * (teslanet.nl) Rogier Cobben - initial creation * %% @@ -135,7 +135,7 @@ public void visit( AbstractEndpoint toVisit ) { switch ( param ) { - case logCoapMessages: + case ENDPOINT_LOGCOAPMESSAGES: result= Boolean.toString( toVisit.logCoapMessages ); break; case logHealthStatus: @@ -206,7 +206,7 @@ public void visit( OptionParams toVisit ) result= Arrays.toString( toVisit.otherOptionConfigs.stream().map( c -> c.isSingleValue() ).map( Object::toString ).toArray( String[]::new ) ); break; case ENDPOINT_OTHEROPTION_TYPE: - result= Arrays.toString( toVisit.otherOptionConfigs.stream().map( c -> c.getOptionType() ).map( Object::toString ).toArray( String[]::new ) ); + result= Arrays.toString( toVisit.otherOptionConfigs.stream().map( c -> c.getFormat() ).map( Object::toString ).toArray( String[]::new ) ); break; default: break; @@ -705,7 +705,7 @@ public void visit( ConnectionId toVisit ) { switch ( param ) { - case SUPPORT_CONNECTION_ID: + case DTLS_SUPPORT_CONNECTION_ID: result= "true"; break; case DTLS_CONNECTION_ID_LENGTH: @@ -1024,15 +1024,18 @@ public void visit( SocketParams toVisit ) { switch ( param ) { - case bindToHost: + case ENDPOINT_BINDTOHOST: result= toVisit.bindToHost; break; - case bindToPort: + case ENDPOINT_BINDTOPORT: result= ( toVisit.bindToPort != null ? toVisit.bindToPort.toString() : null ); break; - case bindToSecurePort: + case ENDPOINT_BINDTOSECUREPORT: result= ( toVisit.bindToPort != null ? toVisit.bindToPort.toString() : null ); break; + case ENDPOINT_REUSEADDRESS: + result= String.valueOf( toVisit.reuseAddress ); + break; case UDP_RECEIVE_BUFFER_SIZE: case DTLS_RECEIVE_BUFFER_SIZE: result= ( toVisit.receiveBuffer != null ? toVisit.receiveBuffer.toString() : null ); diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/config/SetValueVisitor.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/config/SetValueVisitor.java index 032d7085..8482d7d7 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/config/SetValueVisitor.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/config/SetValueVisitor.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -72,7 +72,7 @@ import nl.teslanet.mule.connectors.coap.api.config.midtracker.GroupedMidTracker; import nl.teslanet.mule.connectors.coap.api.config.midtracker.MapBasedMidTracker; import nl.teslanet.mule.connectors.coap.api.config.midtracker.NullMidTracker; -import nl.teslanet.mule.connectors.coap.api.config.options.OptionType; +import nl.teslanet.mule.connectors.coap.api.config.options.OptionFormat; import nl.teslanet.mule.connectors.coap.api.config.options.OtherOptionConfig; import nl.teslanet.mule.connectors.coap.api.config.security.CertificateKeyAlgorithm; import nl.teslanet.mule.connectors.coap.api.config.security.CertificateKeyAlgorithmName; @@ -191,7 +191,7 @@ public void visit( AbstractEndpoint toVisit ) { switch ( param ) { - case logCoapMessages: + case ENDPOINT_LOGCOAPMESSAGES: toVisit.logCoapMessages= Boolean.valueOf( value ); break; case logHealthStatus: @@ -278,7 +278,7 @@ public void visit( OptionParams toVisit ) { nr++; int val= Integer.valueOf( item.replaceAll( "[\\[\\]\\s]+", "" ) ); - toVisit.otherOptionConfigs.add( new OtherOptionConfig( String.valueOf( nr ), nr, OptionType.OPAQUE, true, 1, val ) ); + toVisit.otherOptionConfigs.add( new OtherOptionConfig( String.valueOf( nr ), nr, OptionFormat.OPAQUE, true, 1, val ) ); } break; case ENDPOINT_OTHEROPTION_MINBYTES: @@ -287,7 +287,7 @@ public void visit( OptionParams toVisit ) { nr++; int val= Integer.valueOf( item.replaceAll( "[\\[\\]\\s]+", "" ) ); - toVisit.otherOptionConfigs.add( new OtherOptionConfig( String.valueOf( nr ), nr, OptionType.OPAQUE, true, val, Integer.MAX_VALUE ) ); + toVisit.otherOptionConfigs.add( new OtherOptionConfig( String.valueOf( nr ), nr, OptionFormat.OPAQUE, true, val, Integer.MAX_VALUE ) ); } break; case ENDPOINT_OTHEROPTION_SINGLEVALUE: @@ -296,7 +296,7 @@ public void visit( OptionParams toVisit ) { nr++; boolean val= Boolean.valueOf( item.replaceAll( "[\\[\\]\\s]+", "" ) ); - toVisit.otherOptionConfigs.add( new OtherOptionConfig( String.valueOf( nr ), nr, OptionType.OPAQUE, val, 0, Integer.MAX_VALUE ) ); + toVisit.otherOptionConfigs.add( new OtherOptionConfig( String.valueOf( nr ), nr, OptionFormat.OPAQUE, val, 0, Integer.MAX_VALUE ) ); } break; case ENDPOINT_OTHEROPTION_TYPE: @@ -304,7 +304,7 @@ public void visit( OptionParams toVisit ) for ( String item : value.split( "," ) ) { nr++; - OptionType val= OptionType.valueOf( item.replaceAll( "[\\[\\]\\s]+", "" ) ); + OptionFormat val= OptionFormat.valueOf( item.replaceAll( "[\\[\\]\\s]+", "" ) ); toVisit.otherOptionConfigs.add( new OtherOptionConfig( String.valueOf( nr ), nr, val, true, 0, Integer.MAX_VALUE ) ); } break; @@ -878,7 +878,7 @@ public void visit( SecurityParams toVisit ) case DTLS_EXTENDED_MASTER_SECRET_MODE: toVisit.extendedMasterSecretMode= ExtendedMasterSecretModeName.valueOf( value ); break; - case SUPPORT_CONNECTION_ID: + case DTLS_SUPPORT_CONNECTION_ID: if ( Boolean.valueOf( value ) ) toVisit.supportConnectionId= new ConnectionId(); break; case DTLS_CONNECTION_ID_LENGTH: @@ -901,7 +901,7 @@ public void visit( ConnectionId toVisit ) { switch ( param ) { - case SUPPORT_CONNECTION_ID: + case DTLS_SUPPORT_CONNECTION_ID: toVisit.connectionIdLength= null; break; case DTLS_CONNECTION_ID_LENGTH: @@ -1148,15 +1148,18 @@ public void visit( SocketParams toVisit ) { switch ( param ) { - case bindToHost: + case ENDPOINT_BINDTOHOST: toVisit.bindToHost= value; break; - case bindToPort: + case ENDPOINT_BINDTOPORT: toVisit.bindToPort= Integer.valueOf( value ); break; - case bindToSecurePort: + case ENDPOINT_BINDTOSECUREPORT: toVisit.bindToPort= Integer.valueOf( value ); break; + case ENDPOINT_REUSEADDRESS: + toVisit.reuseAddress= Boolean.valueOf( value ); + break; case UDP_RECEIVE_BUFFER_SIZE: case DTLS_RECEIVE_BUFFER_SIZE: toVisit.receiveBuffer= Integer.valueOf( value ); diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/entitytag/ETagTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/entitytag/ETagTest.java index 8f501eb7..35bc65f6 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/entitytag/ETagTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/entitytag/ETagTest.java @@ -72,18 +72,18 @@ public void testConstructorNullValue() throws EntityTagException EntityTag etag10= new EntityTag( etagValue1, 16 ); EntityTag etag11= new EntityTag( etagValue6, 16 ); - assertEquals( "ETag contruction from null String failed", "", etag0.getValueAsHexString() ); - assertEquals( "ETag contruction from null String failed", "", etag1.getValueAsHexString() ); - assertEquals( "ETag contruction from null Byte[] failed", "", etag2.getValueAsHexString() ); - assertEquals( "ETag contruction from null Byte[] failed", "", etag3.getValueAsHexString() ); - assertEquals( "ETag contruction from null Long failed", "", etag4.getValueAsHexString() ); - assertEquals( "ETag contruction from empty Byte[] failed", "", etag5.getValueAsHexString() ); - assertEquals( "ETag contruction from empty String failed", "", etag6.getValueAsHexString() ); - assertEquals( "ETag contruction from empty String failed", "", etag7.getValueAsHexString() ); - assertEquals( "ETag contruction from empty String failed", "", etag8.getValueAsHexString() ); - assertEquals( "ETag contruction from empty String failed", "", etag9.getValueAsHexString() ); - assertEquals( "ETag contruction with radix from null String failed", "", etag10.getValueAsHexString() ); - assertEquals( "ETag contruction with radix from empty String failed", "", etag11.getValueAsHexString() ); + assertEquals( "ETag contruction from null String failed", "", etag0.getValueAsHex() ); + assertEquals( "ETag contruction from null String failed", "", etag1.getValueAsHex() ); + assertEquals( "ETag contruction from null Byte[] failed", "", etag2.getValueAsHex() ); + assertEquals( "ETag contruction from null Byte[] failed", "", etag3.getValueAsHex() ); + assertEquals( "ETag contruction from null Long failed", "", etag4.getValueAsHex() ); + assertEquals( "ETag contruction from empty Byte[] failed", "", etag5.getValueAsHex() ); + assertEquals( "ETag contruction from empty String failed", "", etag6.getValueAsHex() ); + assertEquals( "ETag contruction from empty String failed", "", etag7.getValueAsHex() ); + assertEquals( "ETag contruction from empty String failed", "", etag8.getValueAsHex() ); + assertEquals( "ETag contruction from empty String failed", "", etag9.getValueAsHex() ); + assertEquals( "ETag contruction with radix from null String failed", "", etag10.getValueAsHex() ); + assertEquals( "ETag contruction with radix from empty String failed", "", etag11.getValueAsHex() ); } @Test @@ -241,10 +241,10 @@ public void testGetHexString() throws EntityTagException String hexValue2= "afb990"; String hexValue3= "1122334455667788"; - assertEquals( "ETag.toHexString gives wrong value", hexValue0, new EntityTag( etagValue0 ).getValueAsHexString() ); - assertEquals( "ETag.toHexString gives wrong value", hexValue1, new EntityTag( etagValue1 ).getValueAsHexString() ); - assertEquals( "ETag.toHexString gives wrong value", hexValue2, new EntityTag( etagValue2 ).getValueAsHexString() ); - assertEquals( "ETag.toHexString gives wrong value", hexValue3, new EntityTag( etagValue3 ).getValueAsHexString() ); + assertEquals( "ETag.toHexString gives wrong value", hexValue0, new EntityTag( etagValue0 ).getValueAsHex() ); + assertEquals( "ETag.toHexString gives wrong value", hexValue1, new EntityTag( etagValue1 ).getValueAsHex() ); + assertEquals( "ETag.toHexString gives wrong value", hexValue2, new EntityTag( etagValue2 ).getValueAsHex() ); + assertEquals( "ETag.toHexString gives wrong value", hexValue3, new EntityTag( etagValue3 ).getValueAsHex() ); } @Test @@ -254,10 +254,10 @@ public void testToString() throws EntityTagException byte[] etagValue1= { (byte) 0x00 }; byte[] etagValue2= { (byte) 0xAF, (byte) 0xB9, (byte) 0x90 }; byte[] etagValue3= { (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66, (byte) 0x77, (byte) 0x88 }; - String hexValue0= "ETag { }"; - String hexValue1= "ETag { 00 }"; - String hexValue2= "ETag { afb990 }"; - String hexValue3= "ETag { 1122334455667788 }"; + String hexValue0= "ETag{ }"; + String hexValue1= "ETag{ 00 }"; + String hexValue2= "ETag{ afb990 }"; + String hexValue3= "ETag{ 1122334455667788 }"; assertEquals( "ETag.toHexString gives wrong value", hexValue0, new EntityTag( etagValue0 ).toString() ); assertEquals( "ETag.toHexString gives wrong value", hexValue1, new EntityTag( etagValue1 ).toString() ); @@ -285,15 +285,15 @@ public void testValueOf() throws EntityTagException EntityTag etag4= EntityTag.valueOf( etagValue4 ); EntityTag etag5= EntityTag.valueOf( etagValue5 ); - assertEquals( "ETag contruction from null failed", OptionUtils.EMPTY_STRING, etag0.getValueAsHexString() ); - assertEquals( "ETag contruction from null failed", OptionUtils.EMPTY_STRING, etag00.getValueAsHexString() ); - assertEquals( "ETag contruction from null failed", OptionUtils.EMPTY_STRING, etag000.getValueAsHexString() ); - assertEquals( "ETag contruction from null failed", OptionUtils.EMPTY_STRING, etag0000.getValueAsHexString() ); - assertEquals( "ETag contruction from String failed", etagValue2, etag1.getValueAsHexString() ); - assertEquals( "ETag contruction from Byte[] failed", etagValue2, etag2.getValueAsHexString() ); - assertEquals( "ETag contruction from Byte[] failed", etagValue2, etag3.getValueAsHexString() ); - assertEquals( "ETag contruction from Long failed", etagValue2, etag4.getValueAsHexString() ); - assertEquals( "ETag contruction from Long failed", etagValue6, etag5.getValueAsHexString() ); + assertEquals( "ETag contruction from null failed", OptionUtils.EMPTY_STRING, etag0.getValueAsHex() ); + assertEquals( "ETag contruction from null failed", OptionUtils.EMPTY_STRING, etag00.getValueAsHex() ); + assertEquals( "ETag contruction from null failed", OptionUtils.EMPTY_STRING, etag000.getValueAsHex() ); + assertEquals( "ETag contruction from null failed", OptionUtils.EMPTY_STRING, etag0000.getValueAsHex() ); + assertEquals( "ETag contruction from String failed", etagValue2, etag1.getValueAsHex() ); + assertEquals( "ETag contruction from Byte[] failed", etagValue2, etag2.getValueAsHex() ); + assertEquals( "ETag contruction from Byte[] failed", etagValue2, etag3.getValueAsHex() ); + assertEquals( "ETag contruction from Long failed", etagValue2, etag4.getValueAsHex() ); + assertEquals( "ETag contruction from Long failed", etagValue6, etag5.getValueAsHex() ); } @Test @@ -319,16 +319,16 @@ public void testValueOfNull() throws EntityTagException EntityTag etag8= EntityTag.valueOf( etagValue8 ); EntityTag etag9= EntityTag.valueOf( etagValue9 ); - assertEquals( "ETag contruction from null failed", "", etag1.getValueAsHexString() ); - assertEquals( "ETag contruction from String failed", "", etag1.getValueAsHexString() ); - assertEquals( "ETag contruction from Byte[] failed", "", etag2.getValueAsHexString() ); - assertEquals( "ETag contruction from Byte[] failed", "", etag3.getValueAsHexString() ); - assertEquals( "ETag contruction from null Long failed", "", etag4.getValueAsHexString() ); - assertEquals( "ETag contruction from empty Byte[] failed", "", etag5.getValueAsHexString() ); - assertEquals( "ETag contruction from empty String failed", "", etag6.getValueAsHexString() ); - assertEquals( "ETag contruction from 0 long failed", "", etag7.getValueAsHexString() ); - assertEquals( "ETag contruction from null Integer failed", "", etag8.getValueAsHexString() ); - assertEquals( "ETag contruction from 0 int failed", "", etag9.getValueAsHexString() ); + assertEquals( "ETag contruction from null failed", "", etag1.getValueAsHex() ); + assertEquals( "ETag contruction from String failed", "", etag1.getValueAsHex() ); + assertEquals( "ETag contruction from Byte[] failed", "", etag2.getValueAsHex() ); + assertEquals( "ETag contruction from Byte[] failed", "", etag3.getValueAsHex() ); + assertEquals( "ETag contruction from null Long failed", "", etag4.getValueAsHex() ); + assertEquals( "ETag contruction from empty Byte[] failed", "", etag5.getValueAsHex() ); + assertEquals( "ETag contruction from empty String failed", "", etag6.getValueAsHex() ); + assertEquals( "ETag contruction from 0 long failed", "", etag7.getValueAsHex() ); + assertEquals( "ETag contruction from null Integer failed", "", etag8.getValueAsHex() ); + assertEquals( "ETag contruction from 0 int failed", "", etag9.getValueAsHex() ); } @Test diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/options/OptionDefinitionTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/options/OptionDefinitionTest.java new file mode 100644 index 00000000..50d85bb2 --- /dev/null +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/options/OptionDefinitionTest.java @@ -0,0 +1,182 @@ +/*- + * #%L + * Mule CoAP Connector + * %% + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben + * + * Contributors: + * (teslanet.nl) Rogier Cobben - initial creation + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + * #L% + */ +package nl.teslanet.mule.connectors.coap.test.options; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collection; + +import org.eclipse.californium.core.coap.option.OptionDefinition; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import nl.teslanet.mule.connectors.coap.api.config.options.OptionFormat; +import nl.teslanet.mule.connectors.coap.api.config.options.OtherOptionConfig; +import nl.teslanet.mule.connectors.coap.internal.utils.MessageUtils; + + +/** + * Test option definition handling. + * + */ +@RunWith( Parameterized.class ) +public class OptionDefinitionTest +{ + /** + * The option alias. + */ + @Parameter( 0 ) + public String alias; + + /** + * The option number. + */ + @Parameter( 1 ) + public int number; + + /** + * The option format. + */ + @Parameter( 2 ) + public OptionFormat format; + + /** + * The option multiplicity. + */ + @Parameter( 3 ) + public boolean singleValue; + + /** + * The option minimum length. + */ + @Parameter( 4 ) + public Integer minBytes; + + /** + * The option maximum length. + */ + @Parameter( 5 ) + public Integer maxBytes; + + /** + * The expected multiplicity. + */ + @Parameter( 6 ) + public boolean expectedSingleValue; + + /** + * The expected minimum length. + */ + @Parameter( 7 ) + public Integer expectedMinBytes; + + /** + * The expected maximum length. + */ + @Parameter( 8 ) + public Integer expectedMaxBytes; + + /** + * The list of tests with their parameters + * @return Test parameters. + */ + @Parameters( name= "alias= {0}" ) + public static Collection< Object[] > data() + { + return Arrays.asList( + new Object [] [] + { + { "option-empty-single", 65001, OptionFormat.EMPTY, true, 0, 0, true, 0, 0 }, + { "option-empty", 65002, OptionFormat.EMPTY, false, 0, 0, true, 0, 0 }, + { "option-integer-1-4-single", 65003, OptionFormat.INTEGER, true, 1, 4, true, 1, 4 }, + { "option-integer-1-4", 65004, OptionFormat.INTEGER, false, 1, 4, false, 1, 4 }, + { "option-integer-3-3", 65005, OptionFormat.INTEGER, false, 3, 3, false, 3, null }, + { "option-integer-0-max", 65006, OptionFormat.INTEGER, false, 0, Integer.MAX_VALUE, false, 0, Integer.MAX_VALUE }, + { "option-integer-neg", 65007, OptionFormat.INTEGER, false, -3, -4, false, -3, -4 }, + { "option-string-1-4-single", 65003, OptionFormat.STRING, true, 1, 4, true, 1, 4 }, + { "option-string-1-4", 65004, OptionFormat.STRING, false, 1, 4, false, 1, 4 }, + { "option-string-3-3", 65005, OptionFormat.STRING, false, 3, 3, false, 3, null }, + { "option-string-0-max", 65006, OptionFormat.STRING, false, 0, Integer.MAX_VALUE, false, 0, Integer.MAX_VALUE }, + { "option-string-neg", 65007, OptionFormat.STRING, false, -3, -4, false, -3, -4 }, + { "option-opaque-1-4-single", 65003, OptionFormat.OPAQUE, true, 1, 4, true, 1, 4 }, + { "option-opaque-1-4", 65004, OptionFormat.OPAQUE, false, 1, 4, false, 1, 4 }, + { "option-opaque-3-3", 65005, OptionFormat.OPAQUE, false, 3, 3, false, 3, null }, + { "option-opaque-0-max", 65006, OptionFormat.OPAQUE, false, 0, Integer.MAX_VALUE, false, 0, Integer.MAX_VALUE }, + { "option-opaque-neg", 65007, OptionFormat.OPAQUE, false, -3, -4, false, -3, -4 }, + + } + ); + } + + @SuppressWarnings( "deprecation" ) + @Test + public void testToCfOptionDefinition() + { + OtherOptionConfig config= new OtherOptionConfig( alias, number, format, singleValue, minBytes, maxBytes ); + OptionDefinition converted= MessageUtils.toCfOptionDefinition( config ); + + assertEquals( "wrong option definition alias", alias, converted.getName() ); + assertEquals( "wrong option definition number", number, converted.getNumber() ); + assertEquals( "wrong option definition format", format, MessageUtils.toOptionFormat( converted.getFormat() ) ); + assertEquals( "wrong option definition singleValue", expectedSingleValue, converted.isSingleValue() ); + assertEquals( "wrong option definition singleValue", minBytes, Integer.valueOf( converted.getValueLengths()[0] ) ); + assertEquals( "wrong option definition singleValue", maxBytes, Integer.valueOf( converted.getValueLengths().length > 1 ? converted.getValueLengths()[1] : null ) ); + } + + @Test + public void testEquals() + { + OptionDefinition converted1= MessageUtils.toCfOptionDefinition( new OtherOptionConfig( alias, number, format, singleValue, minBytes, maxBytes ) ); + OptionDefinition converted2= MessageUtils.toCfOptionDefinition( new OtherOptionConfig( alias, number, format, singleValue, minBytes, maxBytes ) ); + + assertTrue( "isEqual definition gave wrong result", MessageUtils.isEqual( converted1, converted2 ) ); + } + + @Test + public void testUnEquals() + { + OptionDefinition converted1= MessageUtils.toCfOptionDefinition( new OtherOptionConfig( alias, number, format, singleValue, minBytes, maxBytes ) ); + OptionDefinition converted2= MessageUtils.toCfOptionDefinition( new OtherOptionConfig( "different", number, format, singleValue, minBytes, maxBytes ) ); + OptionDefinition converted3= MessageUtils.toCfOptionDefinition( new OtherOptionConfig( alias, 65000, format, singleValue, minBytes, maxBytes ) ); + OptionDefinition converted4= MessageUtils.toCfOptionDefinition( + new OtherOptionConfig( alias, number, format == OptionFormat.INTEGER ? OptionFormat.OPAQUE : OptionFormat.INTEGER, singleValue, minBytes, maxBytes ) + ); + OptionDefinition converted5= MessageUtils.toCfOptionDefinition( new OtherOptionConfig( alias, number, format, !singleValue, minBytes, maxBytes ) ); + OptionDefinition converted6= MessageUtils.toCfOptionDefinition( new OtherOptionConfig( alias, number, format, singleValue, minBytes + 1, maxBytes ) ); + OptionDefinition converted7= MessageUtils.toCfOptionDefinition( new OtherOptionConfig( alias, number, format, singleValue, minBytes, maxBytes - 1 ) ); + + assertFalse( "isEqual definition gave wrong result", MessageUtils.isEqual( converted1, converted2 ) ); + assertFalse( "isEqual definition gave wrong result", MessageUtils.isEqual( converted1, converted3 ) ); + assertFalse( "isEqual definition gave wrong result", MessageUtils.isEqual( converted1, converted4 ) ); + assertFalse( "isEqual definition gave wrong result", MessageUtils.isEqual( converted1, converted5 ) && format != OptionFormat.EMPTY ); + assertFalse( "isEqual definition gave wrong result", MessageUtils.isEqual( converted1, converted6 ) && format != OptionFormat.EMPTY ); + assertFalse( "isEqual definition gave wrong result", MessageUtils.isEqual( converted1, converted7 ) && format != OptionFormat.EMPTY ); + } +} diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/options/OptionFormatTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/options/OptionFormatTest.java new file mode 100644 index 00000000..556eecea --- /dev/null +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/options/OptionFormatTest.java @@ -0,0 +1,87 @@ +/*- + * #%L + * Mule CoAP Connector + * %% + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben + * + * Contributors: + * (teslanet.nl) Rogier Cobben - initial creation + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + * #L% + */ +package nl.teslanet.mule.connectors.coap.test.options; + + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import nl.teslanet.mule.connectors.coap.api.config.options.OptionFormat; +import nl.teslanet.mule.connectors.coap.internal.utils.MessageUtils; + + +/** + * Test option format handling. + * + */ +@RunWith( Parameterized.class ) +public class OptionFormatTest +{ + /** + * Cf format. + */ + @Parameter( 0 ) + public org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat cfFormat; + + /** + * Format. + */ + @Parameter( 1 ) + public OptionFormat format; + + /** + * The list of tests with their parameters + * @return Test parameters. + */ + @Parameters( name= "format= {0}" ) + public static Collection< Object[] > data() + { + return Arrays.asList( + new Object [] [] + { + { org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat.EMPTY, OptionFormat.EMPTY }, + { org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat.INTEGER, OptionFormat.INTEGER }, + { org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat.STRING, OptionFormat.STRING }, + { org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat.OPAQUE, OptionFormat.OPAQUE }, + { org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat.UNKNOWN, OptionFormat.OPAQUE } } + ); + } + + /** + * Test format conversion. + */ + @Test + public void test2ToOptionFormat() + { + OptionFormat format2= MessageUtils.toOptionFormat( cfFormat ); + assertEquals( "wrong option format conversion", format, format2 ); + } +} diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/options/OptionUtilsTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/options/OptionUtilsTest.java index 4dd97897..1448b384 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/options/OptionUtilsTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/options/OptionUtilsTest.java @@ -40,7 +40,7 @@ /** - * Tests the implementation of the Etag class. + * Tests the option utils. * */ public class OptionUtilsTest diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/basic/DifferentListenersTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/basic/DifferentListenersTest.java index 342b0acc..d9435dcb 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/basic/DifferentListenersTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/basic/DifferentListenersTest.java @@ -217,25 +217,25 @@ public void testNoListeners() throws ConnectorException, IOException CoapResponse response= client.get(); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.post( path, 0 ); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.put( path, 0 ); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.delete(); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); } @@ -254,19 +254,19 @@ public void testNoListenersGetOnly() throws ConnectorException, IOException response= client.post( path, 0 ); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.put( path, 0 ); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.delete(); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); } @@ -279,7 +279,7 @@ public void testNoListenersPostOnly() throws ConnectorException, IOException CoapResponse response= client.get(); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.post( path, 0 ); @@ -291,13 +291,13 @@ public void testNoListenersPostOnly() throws ConnectorException, IOException response= client.put( path, 0 ); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.delete(); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); } @@ -310,13 +310,13 @@ public void testNoListenersPutOnly() throws ConnectorException, IOException CoapResponse response= client.get(); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.post( path, 0 ); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.put( path, 0 ); @@ -328,7 +328,7 @@ public void testNoListenersPutOnly() throws ConnectorException, IOException response= client.delete(); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); } @@ -341,19 +341,19 @@ public void testNoListenersDeleteOnly() throws ConnectorException, IOException CoapResponse response= client.get(); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.post( path, 0 ); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.put( path, 0 ); assertNotNull( "get gave no response", response ); - assertEquals( "response code should be INTERNAL_SERVER_ERROR", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "response code should be NOT_IMPLEMENTED", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "response payload has wrong value", "NO LISTENER", response.getResponseText() ); response= client.delete(); diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/exceptionhandling/ExceptionHandlingTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/exceptionhandling/ExceptionHandlingTest.java index a5591e4b..a37b1c7f 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/exceptionhandling/ExceptionHandlingTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/exceptionhandling/ExceptionHandlingTest.java @@ -149,7 +149,7 @@ public void testException() throws Exception case NO_HANDLER: assertNotNull( "request gave no response", response ); assertFalse( "response does not indicate failure", response.isSuccess() ); - assertEquals( "wrong responsecode", ResponseCode.INTERNAL_SERVER_ERROR, response.getCode() ); + assertEquals( "wrong responsecode", ResponseCode.NOT_IMPLEMENTED, response.getCode() ); assertEquals( "wrong response payload", "NO LISTENER", response.getResponseText() ); break; default: diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/modules/OtherOptionsAttributesTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/modules/OtherOptionsAttributesTest.java index 13dff663..7cf512b4 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/modules/OtherOptionsAttributesTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/modules/OtherOptionsAttributesTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -30,10 +30,17 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; +import org.eclipse.californium.core.coap.option.EmptyOptionDefinition; +import org.eclipse.californium.core.coap.option.IntegerOptionDefinition; +import org.eclipse.californium.core.coap.option.OpaqueOptionDefinition; +import org.eclipse.californium.core.coap.option.OptionDefinition; +import org.eclipse.californium.core.coap.option.StringOptionDefinition; import org.junit.Test; import org.mule.runtime.core.api.util.IOUtils; +import nl.teslanet.mule.connectors.coap.api.config.options.OptionFormat; import nl.teslanet.mule.connectors.coap.api.options.OtherOptionAttribute; +import nl.teslanet.mule.connectors.coap.internal.options.DefaultOtherOptionAttribute; /** @@ -41,91 +48,239 @@ */ public class OtherOptionsAttributesTest { + private void assertAttribute( OtherOptionAttribute attribute, String alias, OptionFormat format, int number, byte[] value, String asHex, Long asNumber, String asString ) + { + assertEquals( "OtherOptionAttribute has wrong alias", alias, attribute.getAlias() ); + assertEquals( "OtherOptionAttribute has wrong format", format, attribute.getFormat() ); + assertEquals( "OtherOptionAttribute has wrong number", number, attribute.getNumber() ); + assertEquals( "OtherOptionAttribute has wrong length", value.length, attribute.getLength() ); + assertArrayEquals( "OtherOptionAttribute has wrong bytes value", value, IOUtils.toByteArray( attribute.getValue() ) ); + assertEquals( "OtherOptionAttribute has wrong Hex value", asHex, attribute.getValueAsHex() ); + if ( asNumber == null ) + { + Exception e= assertThrows( NumberFormatException.class, () -> attribute.getValueAsNumber() ); + assertEquals( "Exception has wrong message", "Option{ " + alias + " } is not of type INTEGER.", e.getMessage() ); + } + else + { + assertEquals( "OtherOptionAttribute has wrong long value", asNumber.longValue(), attribute.getValueAsNumber() ); + } + if ( asString == null ) + { + Exception e= assertThrows( NumberFormatException.class, () -> attribute.getValueAsString() ); + assertEquals( "Exception has wrong message", "Option{ " + alias + " } is not of type STRING.", e.getMessage() ); + } + else + { + assertEquals( "OtherOptionAttribute has wrong string value", asString, attribute.getValueAsString() ); + } + } + @Test - public void defaultConstructorTest() + public void constructorEmpty0Test() { - OtherOptionAttribute attribute= new OtherOptionAttribute(); + String alias= ""; + int number= 0; + byte[] value= {}; + + OptionDefinition def= new EmptyOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); + + assertAttribute( attribute, alias, OptionFormat.EMPTY, number, value, "", null, null ); + } + + @Test + public void constructorOpaque0Test() + { + String alias= ""; + int number= 0; + byte[] value= {}; + + OptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); + + assertAttribute( attribute, alias, OptionFormat.OPAQUE, number, value, "", null, null ); + } + + @Test + public void constructorInteger0Test() + { + String alias= ""; + int number= 0; + byte[] value= {}; - assertEquals( "OtherOptionAttribute has wrong number", 0, attribute.getNumber() ); - assertArrayEquals( "OtherOptionAttribute has wrong bytes value", new byte [0], IOUtils.toByteArray( attribute.getValue() ) ); - assertEquals( "OtherOptionAttribute has wrong Hex value", "", attribute.getValueAsHexString() ); - assertEquals( "OtherOptionAttribute has wrong long value", 0L, attribute.getValueAsNumber() ); - assertEquals( "OtherOptionAttribute has wrong String value", "", attribute.getValueAsString() ); + OptionDefinition def= new IntegerOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); + + assertAttribute( attribute, alias, OptionFormat.INTEGER, number, value, "", 0L, null ); } @Test - public void constructor0Test() + public void constructorString0Test() { + String alias= ""; int number= 0; byte[] value= {}; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OptionDefinition def= new StringOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); - assertEquals( "OtherOptionAttribute has wrong number", 0, attribute.getNumber() ); - assertArrayEquals( "OtherOptionAttribute has wrong bytes value", new byte [0], IOUtils.toByteArray( attribute.getValue() ) ); - assertEquals( "OtherOptionAttribute has wrong Hex value", "", attribute.getValueAsHexString() ); - assertEquals( "OtherOptionAttribute has wrong long value", 0L, attribute.getValueAsNumber() ); - assertEquals( "OtherOptionAttribute has wrong String value", "", attribute.getValueAsString() ); + assertAttribute( attribute, alias, OptionFormat.STRING, number, value, "", null, "" ); } @Test - public void constructorNullTest() + public void constructorEmptyNullTest() { + String alias= null; int number= 0; byte[] value= null; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OptionDefinition def= new EmptyOptionDefinition( number, alias ); + assertThrows( NullPointerException.class, () -> new DefaultOtherOptionAttribute( def, value ) ); + } - assertEquals( "OtherOptionAttribute has wrong number", number, attribute.getNumber() ); - assertArrayEquals( "OtherOptionAttribute has wrong bytes value", new byte [0], IOUtils.toByteArray( attribute.getValue() ) ); - assertEquals( "OtherOptionAttribute has wrong Hex value", "", attribute.getValueAsHexString() ); - assertEquals( "OtherOptionAttribute has wrong long value", 0L, attribute.getValueAsNumber() ); - assertEquals( "OtherOptionAttribute has wrong String value", "", attribute.getValueAsString() ); + @Test + public void constructorOpaqueNullTest() + { + String alias= null; + int number= 0; + byte[] value= null; + + OptionDefinition def= new OpaqueOptionDefinition( number, alias ); + assertThrows( NullPointerException.class, () -> new DefaultOtherOptionAttribute( def, value ) ); + } + + public void constructorIntegerNullTest() + { + String alias= null; + int number= 0; + byte[] value= null; + + OptionDefinition def= new IntegerOptionDefinition( number, alias ); + assertThrows( NullPointerException.class, () -> new DefaultOtherOptionAttribute( def, value ) ); + } + + public void constructorStringNullTest() + { + String alias= null; + int number= 0; + byte[] value= null; + + OptionDefinition def= new StringOptionDefinition( number, alias ); + assertThrows( NullPointerException.class, () -> new DefaultOtherOptionAttribute( def, value ) ); } @Test - public void constructor1Test() + public void constructorEmpty1Test() { + String alias= "option-66123"; int number= 6123; byte[] value= { 0x68, 0x6f, 0x69 }; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OptionDefinition def= new EmptyOptionDefinition( number, alias ); + assertThrows( IllegalArgumentException.class, () -> new DefaultOtherOptionAttribute( def, value ) ); + } - assertEquals( "OtherOptionAttribute has wrong number", number, attribute.getNumber() ); - assertArrayEquals( "OtherOptionAttribute has wrong bytes value", value, IOUtils.toByteArray( attribute.getValue() ) ); - assertEquals( "OtherOptionAttribute has wrong Hex value", "686f69", attribute.getValueAsHexString() ); - assertEquals( "OtherOptionAttribute has wrong long value", 0x686f69L, attribute.getValueAsNumber() ); - assertEquals( "OtherOptionAttribute has wrong String value", "hoi", attribute.getValueAsString() ); + @Test + public void constructorOpaque1Test() + { + String alias= "option-66123"; + int number= 6123; + byte[] value= { 0x68, 0x6f, 0x69 }; + + OptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); + + assertAttribute( attribute, alias, OptionFormat.OPAQUE, number, value, "686f69", null, null ); + } + + @Test + public void constructorInteger1Test() + { + String alias= "option-66123"; + int number= 6123; + byte[] value= { 0x68, 0x6f, 0x69 }; + + OptionDefinition def= new IntegerOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); + + assertAttribute( attribute, alias, OptionFormat.INTEGER, number, value, "686f69", 6844265L, null ); + } + + @Test + public void constructorString1Test() + { + String alias= "option-66123"; + int number= 6123; + byte[] value= { 0x68, 0x6f, 0x69 }; + + OptionDefinition def= new StringOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); + + assertAttribute( attribute, alias, OptionFormat.STRING, number, value, "686f69", null, "hoi" ); + } + + @Test + public void constructorEmpty3Test() + { + String alias= "option-65123"; + int number= 65123; + String text= "This is a rather long option value."; + byte[] value= text.getBytes(); + + OptionDefinition def= new EmptyOptionDefinition( number, alias ); + assertThrows( IllegalArgumentException.class, () -> new DefaultOtherOptionAttribute( def, value ) ); } @Test - public void constructor3Test() + public void constructorOpaque3Test() { - int number= 66123; + String alias= "option-65123"; + int number= 65123; String text= "This is a rather long option value."; byte[] value= text.getBytes(); - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); - assertEquals( "OtherOptionAttribute has wrong number", number, attribute.getNumber() ); - assertArrayEquals( "OtherOptionAttribute has wrong bytes value", value, IOUtils.toByteArray( attribute.getValue() ) ); - assertEquals( "OtherOptionAttribute has wrong Hex value", "54686973206973206120726174686572206c6f6e67206f7074696f6e2076616c75652e", attribute.getValueAsHexString() ); - - NumberFormatException e= assertThrows( NumberFormatException.class, () -> { - @SuppressWarnings( "unused" ) - long longValue= attribute.getValueAsNumber(); - } ); - assertTrue( "Exception has wrong message", e.getMessage().contains( "too large" ) ); - assertEquals( "OtherOptionAttribute has wrong String value", text, attribute.getValueAsString() ); + assertAttribute( attribute, alias, OptionFormat.OPAQUE, number, value, "54686973206973206120726174686572206c6f6e67206f7074696f6e2076616c75652e", null, null ); + } + + @Test + public void constructorInteger3Test() + { + String alias= "option-65123"; + int number= 65123; + String text= "This is a rather long option value."; + byte[] value= text.getBytes(); + + OptionDefinition def= new IntegerOptionDefinition( number, alias ); + assertThrows( IllegalArgumentException.class, () -> new DefaultOtherOptionAttribute( def, value ) ); + } + + @Test + public void constructorString3Test() + { + String alias= "option-65123"; + int number= 65123; + String text= "This is a rather long option value."; + byte[] value= text.getBytes(); + + OptionDefinition def= new StringOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); + + assertAttribute( attribute, alias, OptionFormat.STRING, number, value, "54686973206973206120726174686572206c6f6e67206f7074696f6e2076616c75652e", null, text ); } @Test public void traits000Test() { + String alias= "Location-Path"; int number= 8; //Location-Path byte[] value= { 0x68, 0x6f, 0x69 }; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OpaqueOptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); assertFalse( "OtherOptionAttribute has wrong critical trait", attribute.isCritical() ); assertFalse( "OtherOptionAttribute has wrong unSafe trait", attribute.isUnsafe() ); @@ -135,10 +290,12 @@ public void traits000Test() @Test public void traits001Test() { + String alias= "Size1"; int number= 60; //Size1 byte[] value= { 0x68, 0x6f, 0x69 }; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OpaqueOptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); assertFalse( "OtherOptionAttribute has wrong critical trait", attribute.isCritical() ); assertFalse( "OtherOptionAttribute has wrong unSafe trait", attribute.isUnsafe() ); @@ -148,10 +305,12 @@ public void traits001Test() @Test public void traits010Test() { + String alias= "No-Response"; int number= 258; //No-Response byte[] value= { 0x68, 0x6f, 0x69 }; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OpaqueOptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); assertFalse( "OtherOptionAttribute has wrong critical trait", attribute.isCritical() ); assertTrue( "OtherOptionAttribute has wrong unSafe trait", attribute.isUnsafe() ); @@ -161,10 +320,12 @@ public void traits010Test() @Test public void traits011Test() { + String alias= "Max-Age"; int number= 14; //Max-Age byte[] value= { 0x68, 0x6f, 0x69 }; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OpaqueOptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); assertFalse( "OtherOptionAttribute has wrong critical trait", attribute.isCritical() ); assertTrue( "OtherOptionAttribute has wrong unSafe trait", attribute.isUnsafe() ); @@ -175,10 +336,12 @@ public void traits011Test() @Test public void traits100Test() { + String alias= "If-Match"; int number= 1; //If-Match byte[] value= { 0x68, 0x6f, 0x69 }; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OpaqueOptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); assertTrue( "OtherOptionAttribute has wrong critical trait", attribute.isCritical() ); assertFalse( "OtherOptionAttribute has wrong unSafe trait", attribute.isUnsafe() ); @@ -188,10 +351,12 @@ public void traits100Test() @Test public void traits101Test() { + String alias= "option-65021"; int number= 65021; byte[] value= { 0x68, 0x6f, 0x69 }; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OpaqueOptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); assertTrue( "OtherOptionAttribute has wrong critical trait", attribute.isCritical() ); assertFalse( "OtherOptionAttribute has wrong unSafe trait", attribute.isUnsafe() ); @@ -201,10 +366,12 @@ public void traits101Test() @Test public void traits110Test() { + String alias= "Uri-Host"; int number= 3; //Uri-Host byte[] value= { 0x68, 0x6f, 0x69 }; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OpaqueOptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); assertTrue( "OtherOptionAttribute has wrong critical trait", attribute.isCritical() ); assertTrue( "OtherOptionAttribute has wrong unSafe trait", attribute.isUnsafe() ); @@ -214,10 +381,12 @@ public void traits110Test() @Test public void traits111Test() { + String alias= "option-65023"; int number= 65023; byte[] value= { 0x68, 0x6f, 0x69 }; - OtherOptionAttribute attribute= new OtherOptionAttribute( number, value ); + OpaqueOptionDefinition def= new OpaqueOptionDefinition( number, alias ); + OtherOptionAttribute attribute= new DefaultOtherOptionAttribute( def, value ); assertTrue( "OtherOptionAttribute has wrong critical trait", attribute.isCritical() ); assertTrue( "OtherOptionAttribute has wrong unSafe trait", attribute.isUnsafe() ); @@ -228,16 +397,22 @@ public void traits111Test() @Test public void equalsTest() { + String alias= "option-65023"; int number1= 65023; byte[] value1= { 0x68, 0x6f, 0x69 }; int number2= 65021; byte[] value2= { 0x68, 0x6f, 0x70 }; - OtherOptionAttribute attribute1= new OtherOptionAttribute( number1, value1 ); - OtherOptionAttribute attribute2= new OtherOptionAttribute( number2, value2 ); - OtherOptionAttribute attribute3= new OtherOptionAttribute( number1, value1 ); - OtherOptionAttribute attribute4= new OtherOptionAttribute( number1, value2 ); - OtherOptionAttribute attribute5= new OtherOptionAttribute( number2, value1 ); + OpaqueOptionDefinition def1= new OpaqueOptionDefinition( number1, alias ); + OtherOptionAttribute attribute1= new DefaultOtherOptionAttribute( def1, value1 ); + OpaqueOptionDefinition def2= new OpaqueOptionDefinition( number2, alias ); + OtherOptionAttribute attribute2= new DefaultOtherOptionAttribute( def2, value2 ); + OpaqueOptionDefinition def3= new OpaqueOptionDefinition( number1, alias ); + OtherOptionAttribute attribute3= new DefaultOtherOptionAttribute( def3, value1 ); + OpaqueOptionDefinition def4= new OpaqueOptionDefinition( number1, alias ); + OtherOptionAttribute attribute4= new DefaultOtherOptionAttribute( def4, value2 ); + OpaqueOptionDefinition def5= new OpaqueOptionDefinition( number2, alias ); + OtherOptionAttribute attribute5= new DefaultOtherOptionAttribute( def5, value1 ); assertEquals( "attribute 1 equals attribute 1 returns wrong result", attribute1, attribute1 ); assertNotEquals( "attribute 1 equals null returns wrong result", attribute1, null ); @@ -254,21 +429,27 @@ public void equalsTest() @Test public void hashCodeTest() { + String alias= "option-65023"; int number1= 65023; byte[] value1= { 0x68, 0x6f, 0x69 }; int number2= 65021; byte[] value2= { 0x68, 0x6f, 0x70 }; - OtherOptionAttribute attribute1= new OtherOptionAttribute( number1, value1 ); - OtherOptionAttribute attribute2= new OtherOptionAttribute( number2, value2 ); - OtherOptionAttribute attribute3= new OtherOptionAttribute( number1, value1 ); - OtherOptionAttribute attribute4= new OtherOptionAttribute( number1, value2 ); - OtherOptionAttribute attribute5= new OtherOptionAttribute( number2, value1 ); - - assertEquals( "hashcode flag 1 has wrong value", 4197726, attribute1.hashCode() ); - assertEquals( "hashcode flag 2 has wrong value", 4197941, attribute2.hashCode() ); - assertEquals( "hashcode flag 3 has wrong value", 4197726, attribute3.hashCode() ); - assertEquals( "hashcode flag 4 has wrong value", 4197943, attribute4.hashCode() ); - assertEquals( "hashcode flag 5 has wrong value", 4197724, attribute5.hashCode() ); + OpaqueOptionDefinition def1= new OpaqueOptionDefinition( number1, alias ); + OtherOptionAttribute attribute1= new DefaultOtherOptionAttribute( def1, value1 ); + OpaqueOptionDefinition def2= new OpaqueOptionDefinition( number2, alias ); + OtherOptionAttribute attribute2= new DefaultOtherOptionAttribute( def2, value2 ); + OpaqueOptionDefinition def3= new OpaqueOptionDefinition( number1, alias ); + OtherOptionAttribute attribute3= new DefaultOtherOptionAttribute( def3, value1 ); + OpaqueOptionDefinition def4= new OpaqueOptionDefinition( number1, alias ); + OtherOptionAttribute attribute4= new DefaultOtherOptionAttribute( def4, value2 ); + OpaqueOptionDefinition def5= new OpaqueOptionDefinition( number2, alias ); + OtherOptionAttribute attribute5= new DefaultOtherOptionAttribute( def5, value1 ); + + assertEquals( "hashcode flag 1 has wrong value", 2150916, attribute1.hashCode() ); + assertEquals( "hashcode flag 2 has wrong value", 2150861, attribute2.hashCode() ); + assertEquals( "hashcode flag 3 has wrong value", 2150916, attribute3.hashCode() ); + assertEquals( "hashcode flag 4 has wrong value", 2150923, attribute4.hashCode() ); + assertEquals( "hashcode flag 5 has wrong value", 2150854, attribute5.hashCode() ); } } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/properties/AbstractInboundPropertyTestcase.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/properties/AbstractInboundPropertyTestcase.java index 838a6ca6..1200009e 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/properties/AbstractInboundPropertyTestcase.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/properties/AbstractInboundPropertyTestcase.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -224,7 +224,7 @@ void assertSpy( MuleEventSpy spy, final Object expected ) * Test inbound property * @throws Exception */ - @Test( timeout= 2000000L ) + @Test public void testInbound() throws Exception { MuleEventSpy spy= spyMessage(); @@ -235,8 +235,6 @@ public void testInbound() throws Exception if ( unintendedPayload ) request.setUnintendedPayload(); addOption( request.setPayload( "" ).getOptions() ); - client.setTimeout( 20000L ); - CoapResponse response= client.advanced( request ); assertNotNull( "no response", response ); diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/properties/DefaultRequestOptionsAttributesTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/properties/DefaultRequestOptionsAttributesTest.java index cfb21ff2..06db865e 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/properties/DefaultRequestOptionsAttributesTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/properties/DefaultRequestOptionsAttributesTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -31,11 +31,13 @@ import static org.junit.Assert.assertTrue; import java.util.List; +import java.util.Map.Entry; import org.eclipse.californium.core.coap.Option; import org.eclipse.californium.core.coap.OptionSet; import org.eclipse.californium.core.coap.option.OpaqueOptionDefinition; import org.junit.Test; +import org.mule.runtime.api.util.MultiMap; import org.mule.runtime.core.api.util.IOUtils; import nl.teslanet.mule.connectors.coap.api.entity.EntityTag; @@ -367,13 +369,15 @@ public void testOptionOther() throws InternalInvalidOptionValueException } DefaultRequestOptionsAttributes attributes= new DefaultRequestOptionsAttributes( set ); - List< ? extends OtherOptionAttribute > options= attributes.getOtherOptions(); + MultiMap< String, OtherOptionAttribute > options= attributes.getOther(); assertEquals( "coap.opt.other has wrong length", 4, options.size() ); - for ( int i= 0; i < 4; i++ ) + int i= 0; + for ( Entry< String, OtherOptionAttribute > entry : options.entryList() ) { - assertEquals( "coap.opt.other has wrong number", optionsDefs[i].getNumber(), options.get( i ).getNumber() ); - assertArrayEquals( "coap.opt.other has wrong value", values[i], IOUtils.toByteArray( options.get( i ).getValue() ) ); + assertEquals( "coap.opt.other has wrong number", optionsDefs[i].getNumber(), entry.getValue().getNumber() ); + assertArrayEquals( "coap.opt.other has wrong value", values[i], IOUtils.toByteArray( entry.getValue().getValue() ) ); + i++; } } } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/resources/AddResourceTest.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/resources/AddResourceTest.java index 5cae6891..be253d86 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/server/resources/AddResourceTest.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/server/resources/AddResourceTest.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -120,7 +120,7 @@ protected String getConfigResources() * Test adding a resource on the server * @throws Exception */ - @Test( timeout= 3000000L ) + @Test public void testAddResource() throws Exception { setClientUri( resourcePath ); diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/AbstractServerTestCase.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/AbstractServerTestCase.java index 5736c888..a242c4e0 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/AbstractServerTestCase.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/AbstractServerTestCase.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -56,7 +56,7 @@ public abstract class AbstractServerTestCase extends AbstractTestCase @Before public void setUp() throws Exception { - OpaqueOptionDefinition[] critical= { TestOptions.OTHER_OPTION_65012, TestOptions.OTHER_OPTION_65013, TestOptions.OTHER_OPTION_65308 }; + OpaqueOptionDefinition[] critical= { TestOptions.OTHER_OPTION_65009, TestOptions.OTHER_OPTION_65012, TestOptions.OTHER_OPTION_65013, TestOptions.OTHER_OPTION_65308 }; URI uri= new URI( "coap", "127.0.0.1", null, null ); client= new CoapClient( uri ); @@ -77,6 +77,7 @@ public void tearDown() throws Exception { if ( client != null ) { + client.getEndpoint().destroy(); client.shutdown(); client= null; } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/TestOptions.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/TestOptions.java index c24289a9..566f1917 100644 --- a/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/TestOptions.java +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/TestOptions.java @@ -2,7 +2,7 @@ * #%L * Mule CoAP Connector * %% - * Copyright (C) 2023 (teslanet.nl) Rogier Cobben + * Copyright (C) 2023 - 2024 (teslanet.nl) Rogier Cobben * * Contributors: * (teslanet.nl) Rogier Cobben - initial creation @@ -23,8 +23,14 @@ package nl.teslanet.mule.connectors.coap.test.utils; +import java.util.HashMap; +import java.util.Map; + import org.eclipse.californium.core.coap.option.OpaqueOptionDefinition; +import nl.teslanet.mule.connectors.coap.api.config.options.OptionFormat; +import nl.teslanet.mule.connectors.coap.api.config.options.OtherOptionConfig; + /** * Options for testing. @@ -35,77 +41,97 @@ public class TestOptions /** * Test option 65001. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65001= new OpaqueOptionDefinition( 65001, "Other-Option-65001" ); + public static final OpaqueOptionDefinition OTHER_OPTION_65001= new OpaqueOptionDefinition( 65001, "option-65001", false, 0, 200 ); /** * Test option 65002. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65002= new OpaqueOptionDefinition( 65002, "Other-Option-65002", false ); + public static final OpaqueOptionDefinition OTHER_OPTION_65002= new OpaqueOptionDefinition( 65002, "option-65002", false, 0, 200 ); /** * Test option 65008. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65008= new OpaqueOptionDefinition( 65008, "Other-Option-65008", false ); + public static final OpaqueOptionDefinition OTHER_OPTION_65008= new OpaqueOptionDefinition( 65008, "option-65008", false, 0, 200 ); /** * Test option 65009. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65009= new OpaqueOptionDefinition( 65009, "Other-Option-65009", false ); + public static final OpaqueOptionDefinition OTHER_OPTION_65009= new OpaqueOptionDefinition( 65009, "option-65009", false, 0, 200 ); /** * Test option 65012. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65010= new OpaqueOptionDefinition( 65010, "Other-Option-65010", false ); + public static final OpaqueOptionDefinition OTHER_OPTION_65010= new OpaqueOptionDefinition( 65010, "option-65010", false, 0, 200 ); /** * Test option 65012. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65012= new OpaqueOptionDefinition( 65012, "Other-Option-65012", false ); + public static final OpaqueOptionDefinition OTHER_OPTION_65012= new OpaqueOptionDefinition( 65012, "option-65012", false, 0, 200 ); /** * Test option 65013. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65013= new OpaqueOptionDefinition( 65013, "Other-Option-65013", false ); + public static final OpaqueOptionDefinition OTHER_OPTION_65013= new OpaqueOptionDefinition( 65013, "option-65013", false, 0, 200 ); /** * Test option 65015. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65015= new OpaqueOptionDefinition( 65015, "Other-Option-65015", false ); + public static final OpaqueOptionDefinition OTHER_OPTION_65015= new OpaqueOptionDefinition( 65015, "option-65015", false, 0, 200 ); /** * Test option 65016. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65016= new OpaqueOptionDefinition( 65016, "Other-Option-65016", false ); + public static final OpaqueOptionDefinition OTHER_OPTION_65016= new OpaqueOptionDefinition( 65016, "option-65016", false, 0, 200 ); /** * Test option 65018. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65018= new OpaqueOptionDefinition( 65018, "Other-Option-65018", false ); + public static final OpaqueOptionDefinition OTHER_OPTION_65018= new OpaqueOptionDefinition( 65018, "option-65018", false, 0, 200 ); /** * Test option 65020. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65020= new OpaqueOptionDefinition( 65020, "Other-Option-65020", false ); + public static final OpaqueOptionDefinition OTHER_OPTION_65020= new OpaqueOptionDefinition( 65020, "option-65020", false, 0, 200 ); /** * Test option 65028. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65028= new OpaqueOptionDefinition( 65028, "Other-Option-65028", true ); + public static final OpaqueOptionDefinition OTHER_OPTION_65028= new OpaqueOptionDefinition( 65028, "option-65028", true, 0, 200 ); /** * Test option 65029. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65029= new OpaqueOptionDefinition( 65029, "Other-Option-65029", true ); + public static final OpaqueOptionDefinition OTHER_OPTION_65029= new OpaqueOptionDefinition( 65029, "option-65029", true, 0, 200 ); /** * Test option 65304. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65304= new OpaqueOptionDefinition( 65304, "Other-Option-65304", true ); + public static final OpaqueOptionDefinition OTHER_OPTION_65304= new OpaqueOptionDefinition( 65304, "option-65304", true, 0, 200 ); /** * Test option 65308. */ - public static final OpaqueOptionDefinition OTHER_OPTION_65308= new OpaqueOptionDefinition( 65308, "Other-Option-65308", true ); + public static final OpaqueOptionDefinition OTHER_OPTION_65308= new OpaqueOptionDefinition( 65308, "option-65308", true, 0, 200 ); + + /** + * Test option definitions array. + */ + public static final OpaqueOptionDefinition[] OTHER_OPTION_DEFS= { + OTHER_OPTION_65001, + OTHER_OPTION_65002, + OTHER_OPTION_65008, + OTHER_OPTION_65009, + OTHER_OPTION_65010, + OTHER_OPTION_65012, + OTHER_OPTION_65013, + OTHER_OPTION_65015, + OTHER_OPTION_65016, + OTHER_OPTION_65018, + OTHER_OPTION_65020, + OTHER_OPTION_65028, + OTHER_OPTION_65029, + OTHER_OPTION_65304, + OTHER_OPTION_65308 }; /** * No object are instantiated. @@ -114,4 +140,25 @@ private TestOptions() { //NOOP } + + public static Map< Integer, OtherOptionConfig > getOtherOptionconfigs() + { + + HashMap< Integer, OtherOptionConfig > otherOptionConfigs= new HashMap<>(); + for ( OpaqueOptionDefinition definition : OTHER_OPTION_DEFS ) + { + otherOptionConfigs.put( + definition.getNumber(), + new OtherOptionConfig( + definition.getName(), + definition.getNumber(), + OptionFormat.OPAQUE, + definition.isSingleValue(), + definition.getValueLengths()[0], + definition.getValueLengths()[1] + ) + ); + } + return otherOptionConfigs; + } } diff --git a/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/TestOtherOptionAttribute.java b/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/TestOtherOptionAttribute.java new file mode 100644 index 00000000..415897d7 --- /dev/null +++ b/src/test/java/nl/teslanet/mule/connectors/coap/test/utils/TestOtherOptionAttribute.java @@ -0,0 +1,281 @@ +/*- + * #%L + * Mule CoAP Connector + * %% + * Copyright (C) 2024 (teslanet.nl) Rogier Cobben + * + * Contributors: + * (teslanet.nl) Rogier Cobben - initial creation + * %% + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + * #L% + */ +package nl.teslanet.mule.connectors.coap.test.utils; + + +import java.io.InputStream; +import java.util.Arrays; +import java.util.Objects; + +import org.eclipse.californium.core.coap.Option; +import org.eclipse.californium.core.coap.option.OptionDefinition; +import org.mule.runtime.api.util.IOUtils; + +import nl.teslanet.mule.connectors.coap.api.config.options.OptionFormat; +import nl.teslanet.mule.connectors.coap.api.options.OptionUtils; +import nl.teslanet.mule.connectors.coap.api.options.OtherOptionAttribute; +import nl.teslanet.mule.connectors.coap.internal.utils.MessageUtils; + + +/** + * Test other option attribute. + */ +public final class TestOtherOptionAttribute implements OtherOptionAttribute +{ + /** + * Wrong type exception message format. + */ + private final String FORMAT_WRONG_TYPE= "OtherOption { %s } is not of type %s."; + + /** + * The definition of the option. + */ + private final Option option; + + /** + * Constructor + * @param number The number of the option. + * @param value The value of the option. + * @param optionType + */ + public TestOtherOptionAttribute( OptionDefinition optionDef, byte[] value ) + { + super(); + this.option= optionDef.create( value ); + } + + /** + * Constructor from Cf Option + * @param number The number of the option. + * @param value The value of the option. + * @param optionType + */ + public TestOtherOptionAttribute( Option option ) + { + super(); + this.option= option; + } + + /** + * Get the alias of this other option. + * + * @return The option number. + */ + @Override + public String getAlias() + { + return option.getDefinition().getName(); + } + + /** + * Get the number of this other option. + * + * @return The option number. + */ + @Override + public int getNumber() + { + + return option.getDefinition().getNumber(); + } + + /** + * Get the format of this other option. + * @return The option format. + */ + @Override + public OptionFormat getFormat() + { + return MessageUtils.toOptionFormat( option.getDefinition().getFormat() ); + } + + /** + * Check if the option is empty. options whether it contains the option. + * @return True when the option is empty, otherwise false. + */ + @Override + public boolean isEmpty() + { + return option.getLength() == 0; + } + + /** + * Get the the length of the other option. + * @return The number of bytes of this option. + */ + @Override + public int getLength() + { + return option.getLength(); + } + + /** + * Get the value of this other option as byte array. + * @return The option value if any, otherwise null. + */ + protected byte[] getValueAsBytes() + { + return option.getValue(); + } + + /** + * Get the value of this other option. + * + * @return The option value if any, otherwise null. + */ + @Override + public InputStream getValue() + { + return OptionUtils.toInputStream( getValueAsBytes() ); + } + + /** + * Get the value as number. + * @return long containing the value. + */ + @Override + public long getValueAsNumber() + { + if ( option.getDefinition().getFormat() != org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat.INTEGER ) + throw new NumberFormatException( String.format( FORMAT_WRONG_TYPE, option.getDefinition().getName(), OptionFormat.INTEGER.toString() ) ); + return option.getLongValue(); + } + + /** + * Get the option value as hexadecimal string. + * Hexadecimal values a-f will be lower case. + * @return The string containing the hexadecimal representation or empty string when the value is empty. + */ + @Override + public String getValueAsHex() + { + return OptionUtils.toHexString( option.getValue() ); + } + + /** + * Get value as UTF-8 string. + * @return The UTF-8 string interpretation. + */ + @Override + public String getValueAsString() + { + if ( option.getDefinition().getFormat() != org.eclipse.californium.core.coap.OptionNumberRegistry.OptionFormat.STRING ) + throw new NumberFormatException( String.format( FORMAT_WRONG_TYPE, option.getDefinition().getName(), OptionFormat.STRING.toString() ) ); + return option.getStringValue(); + } + + /** + * Checks if option is critical. + * + * @return {@code true} if is option critical, otherwise {@code false}. + */ + @Override + public boolean isCritical() + { + return OptionUtils.isCritical( getNumber() ); + } + + /** + * Checks if option with this number is unsafe. + * + * @return {@code true} if this is an unsafe option, otherwise {@code false}. + */ + @Override + public boolean isUnsafe() + { + return OptionUtils.isUnsafe( getNumber() ); + } + + /** + * Checks if option with this number is a NoCacheKey option. + * + * @return {@code true} if this is NoCacheKey option, otherwise {@code false}. + */ + @Override + public boolean isNoCacheKey() + { + return OptionUtils.isNoCacheKey( getNumber() ); + } + + /** + * Returns a hash code value for the object. + */ + @Override + public int hashCode() + { + final int prime= 31; + int result= 1; + result= prime * result + Objects.hash( getNumber() ); + result= prime * result + Arrays.hashCode( getValueAsBytes() ); + return result; + } + + /** + * Indicates whether some other object is "equal to" this. + */ + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + { + return true; + } + if ( !( obj instanceof OtherOptionAttribute ) ) + { + return false; + } + OtherOptionAttribute other= (OtherOptionAttribute) obj; + return ( getNumber() == other.getNumber() ) && Arrays.equals( getValueAsBytes(), IOUtils.toByteArray( getValue() ) ); + } + + /** + * Get the string representation. + */ + @Override + public String toString() + { + StringBuilder builder= new StringBuilder(); + builder.append( "TestOption{" ); + builder.append( " alias=" ).append( getAlias() ); + builder.append( ", number=" ).append( getNumber() ); + switch ( option.getDefinition().getFormat() ) + { + case EMPTY: + builder.append( ", empty" ); + break; + case INTEGER: + builder.append( ", valueAsNumber=" ).append( option.getLongValue() ); + break; + case STRING: + builder.append( ", valueAsString=" ).append( option.getStringValue() ); + break; + case OPAQUE: + case UNKNOWN: + default: + builder.append( ", valueAsHex=" ).append( OptionUtils.toHexString( option.getValue() ) ); + break; + } + builder.append( " }" ); + return builder.toString(); + } +} diff --git a/src/test/resources/log4j2-test.xml b/src/test/resources/log4j2-test.xml index 23c9a64a..b40e99a8 100644 --- a/src/test/resources/log4j2-test.xml +++ b/src/test/resources/log4j2-test.xml @@ -3,7 +3,7 @@ #%L Mule CoAP Connector %% - Copyright (C) 2019 - 2022 (teslanet.nl) Rogier Cobben + Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben Contributors: (teslanet.nl) Rogier Cobben - initial creation @@ -44,14 +44,15 @@ - - + + + - - + + - - + + diff --git a/src/test/resources/mule-client-config/properties/testclient1.xml b/src/test/resources/mule-client-config/properties/testclient1.xml index 25721560..d749f430 100644 --- a/src/test/resources/mule-client-config/properties/testclient1.xml +++ b/src/test/resources/mule-client-config/properties/testclient1.xml @@ -42,11 +42,11 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav logCoapMessages="true"> - - - - - + + + + + diff --git a/src/test/resources/mule-client-config/properties/testclient2.xml b/src/test/resources/mule-client-config/properties/testclient2.xml index ff3e7518..81947766 100644 --- a/src/test/resources/mule-client-config/properties/testclient2.xml +++ b/src/test/resources/mule-client-config/properties/testclient2.xml @@ -43,12 +43,12 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - - - - + + + + + + @@ -100,10 +100,10 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav requestCode="#[vars.requestCode]" host="#[vars.host]" path="#[vars.path]"> - - + - + diff --git a/src/test/resources/mule-client-config/secure/testclient-psk.xml b/src/test/resources/mule-client-config/secure/testclient-psk.xml index a0a09612..c626864a 100644 --- a/src/test/resources/mule-client-config/secure/testclient-psk.xml +++ b/src/test/resources/mule-client-config/secure/testclient-psk.xml @@ -3,7 +3,7 @@ #%L Mule CoAP Connector %% - Copyright (C) 2023 (teslanet.nl) Rogier Cobben + Copyright (C) 2023 - 2024 (teslanet.nl) Rogier Cobben Contributors: (teslanet.nl) Rogier Cobben - initial creation @@ -54,6 +54,11 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav + + + + + diff --git a/src/test/resources/mule-config/entitytag/testflow1.xml b/src/test/resources/mule-config/entitytag/testflow1.xml index 3374f447..188c2d44 100644 --- a/src/test/resources/mule-config/entitytag/testflow1.xml +++ b/src/test/resources/mule-config/entitytag/testflow1.xml @@ -83,7 +83,7 @@ - + diff --git a/src/test/resources/mule-server-config/properties/testserver-options-other65008-unsafe-inbound.xml b/src/test/resources/mule-server-config/properties/testserver-options-other65008-unsafe-inbound.xml index 826d9f98..e15af4f7 100644 --- a/src/test/resources/mule-server-config/properties/testserver-options-other65008-unsafe-inbound.xml +++ b/src/test/resources/mule-server-config/properties/testserver-options-other65008-unsafe-inbound.xml @@ -37,6 +37,11 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav + + + + + @@ -56,20 +61,14 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - - - + + + + + - - - - - - - + - - - - - - + + + + + + @@ -61,25 +61,19 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - - - + + + + + - - - - - - - + - + + + + + + @@ -57,19 +62,13 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - + + + - - - - - - - + + + + + + @@ -56,20 +61,14 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - - - + + + + + - - - - - - - + + + + + + @@ -56,20 +61,14 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - - - + + + + + - - - - - - - + + + + + + @@ -56,20 +61,14 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - - - + + + + + - - - - - - - + - - - - - - + + + + + @@ -63,9 +62,9 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - + + + diff --git a/src/test/resources/mule-server-config/properties/testserver-options-other65013-critical-inbound.xml b/src/test/resources/mule-server-config/properties/testserver-options-other65013-critical-inbound.xml index 4533f89f..95afdf94 100644 --- a/src/test/resources/mule-server-config/properties/testserver-options-other65013-critical-inbound.xml +++ b/src/test/resources/mule-server-config/properties/testserver-options-other65013-critical-inbound.xml @@ -39,7 +39,7 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - + @@ -62,19 +62,13 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - + + + - - - - - - - + - + @@ -62,19 +62,13 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - + + + - - - - - - - + Mule CoAP connector test application - - + + + + + + + @@ -57,9 +62,9 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - + + + diff --git a/src/test/resources/mule-server-config/properties/testserver-options-other65308-nocachekey-inbound.xml b/src/test/resources/mule-server-config/properties/testserver-options-other65308-nocachekey-inbound.xml index d5c8d6b8..934372cd 100644 --- a/src/test/resources/mule-server-config/properties/testserver-options-other65308-nocachekey-inbound.xml +++ b/src/test/resources/mule-server-config/properties/testserver-options-other65308-nocachekey-inbound.xml @@ -39,7 +39,7 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - + @@ -63,19 +63,13 @@ http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/jav - - - + + + - - - - - - - + + + + + + diff --git a/src/test/resources/schemata/coap-extension-descriptions.xml b/src/test/resources/schemata/coap-extension-descriptions.xml index b6df45dd..38d94a1d 100644 --- a/src/test/resources/schemata/coap-extension-descriptions.xml +++ b/src/test/resources/schemata/coap-extension-descriptions.xml @@ -3,7 +3,7 @@ #%L Mule CoAP Connector %% - Copyright (C) 2019 - 2023 (teslanet.nl) Rogier Cobben + Copyright (C) 2019 - 2024 (teslanet.nl) Rogier Cobben Contributors: (teslanet.nl) Rogier Cobben - initial creation @@ -1321,7 +1321,7 @@ - + @@ -1359,7 +1359,7 @@ - + @@ -1388,7 +1388,7 @@ - + diff --git a/src/test/resources/schemata/mule-coap.xsd b/src/test/resources/schemata/mule-coap.xsd index 6acf1cfa..f7bb7b75 100644 --- a/src/test/resources/schemata/mule-coap.xsd +++ b/src/test/resources/schemata/mule-coap.xsd @@ -32,6 +32,7 @@ + @@ -64,7 +65,7 @@ - + @@ -638,6 +639,7 @@ + @@ -2031,7 +2033,7 @@ - + @@ -2048,7 +2050,7 @@ - + @@ -2064,7 +2066,7 @@ - + @@ -2440,7 +2442,7 @@ - + @@ -2455,7 +2457,7 @@ - + @@ -2728,7 +2730,7 @@ - +