This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to use the latest version of Californium

Hi, 

I am trying to following the instructions at: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.iotsdk.v0.9.0%2Fiot_sdk_user_guides_java_coaps.html

but the directory paths of Californium has deviated quite a bit since this was published. Do you have some updated instructions on how to use Californium with your IoT examples?

Thanks very much. 

  • Update: I used SecureClient.java and am able to connect to my SecureServer.java instance now, which is cool! I'm going to try and connect my nRF52840-DK to this secure server and see what happens. I'm not sure what to expect.

  • In the current 2.3.0 cf-secure example the PSK store is set in the CredentialsUtil.setupCredentials

    InMemoryPskStore pskStore = new InMemoryPskStore();
    pskStore.setKey(PSK_IDENTITY, PSK_SECRET);
    pskStore.setKey(OPEN_PSK_IDENTITY, OPEN_PSK_SECRET);
    config.setPskStore(pskStore);

    > I think it would be nice if there was some getting started guide with the latest release of californium

    Unfortunately, though not too many are actively working "on" Californium, I will not be able to write such a guide for the next release, 2.4.0 planned for Thursday, 27.8.

  • Hi  and ,

    I have now started on updating the guide, and will hopefully have something for you in the next few days.

    Best regards,

    Didrik

  • Hi Didrik,

    if I can be of any help, just contact me by e-mail (or a github issue in eclipse/californium).

    best regards

    Achim

  • Hi and ,

    I have now been able to get the guide to work with Californium 2.3.0.

    I will do some more testing, update to 2.4.0 and write it down properly, but here are my notes on the changes, and my modified Nrf5xSecureServer/Client.java files (so you don't have to do the modifications to the files listed in the notes under the "Running a secure CoAP server/client):

    nrf5 sdk 16, examples/iot/.....
    californium + californium.tools tag 2.3.0
    newest eclipse version. Seems to have th eplugins already
    
    
    prepare workspace
    1. same
    2. copy to californium/demo-apps/cf-secure/src/main/java/org/eclipse/californium/examples
    3. Do nothing? Everything is in demo-certs?
    
    Import projects
    1. same
    2. same
    3. californium, not californium-core
    4. not needed
    5. same
    
    Change settings
    1. Could not find any
    2. californium\scandium-core\src\main\java\org\eclipse\californium\scandium\config
    3. public static int DEFAULT_RETRANSMISSION_TIMEOUT_MS = 20000, line 123
    4. californium/californium-core/....
    5. line 197, 200000
    6. same
    
    Known limitations
    Should not be any difference
    
    Running a secure CoAP server
    1. californium/demo-apps/cf-secure/......
    2. same/Use address of local interface, line 101
    3. Errors must be fixed, but it seems to be the same otherwise.
    
    30: import org.slfj.Logger;
    34: import org.eclipse.californium.core.network.CoapEndpoint;
    40: remove
    48/53: comment out. I don't think they are needed anymore
    60: 	private static final String KEY_STORE_LOCATION = "../../demo-certs/src/main/resources/keyStore.jks";
    61:	private static final String TRUST_STORE_LOCATION = "../../demo-certs/src/main/resources/trustStore.jks";
    101: 			DtlsConnectorConfig.Builder config = new DtlsConnectorConfig.Builder();
    106/107: 			config.setIdentity((PrivateKey)keyStore.getKey("server", KEY_STORE_PASSWORD.toCharArray()),
    					keyStore.getCertificateChain("server"), CertificateType.RAW_PUBLIC_KEY, CertificateType.X_509);
    111: 			CoapEndpoint.Builder endpointBuilder = new CoapEndpoint.Builder();
    			endpointBuilder.setNetworkConfig(NetworkConfig.getStandard());
    			endpointBuilder.setConnector(connector);
    			server.addEndpoint(endpointBuilder.build());
    
    
    Running a secure CoAP client
    1. same
    2. same/Use address of local interface, line 224
    3. same
    4. same
    
    32: remove
    37: import org.eclipse.californium.core.network.CoapEndpoint;
    44: remove
    71/77: comment out. I don't think they are needed anymore
    79:     private static final String TRUST_STORE_LOCATION = "../../californium/demo-certs/src/main/resources/trustStore.jks";
    82: 	private static final String KEY_STORE_LOCATION = "../../californium/demo-certs/src/main/resources/keyStore.jks";
    226: insert builder.setAddress(myInetSocketAddr);
    230: 								keyStore.getCertificateChain("client"), CertificateType.RAW_PUBLIC_KEY, CertificateType.X_509);
    
    
    
    

    /*******************************************************************************
     * Copyright (c) 2014 Institute for Pervasive Computing, ETH Zurich and others.
     * 
     * All rights reserved. This program and the accompanying materials
     * are made available under the terms of the Eclipse Public License v1.0
     * and Eclipse Distribution License v1.0 which accompany this distribution.
     * 
     * The Eclipse Public License is available at
     *    http://www.eclipse.org/legal/epl-v10.html
     * and the Eclipse Distribution License is available at
     *    http://www.eclipse.org/org/documents/edl-v10.html.
     * 
     * Contributors:
     *    Matthias Kovatsch - creator and main architect
     ******************************************************************************/
    package org.eclipse.californium.examples;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.Inet6Address;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.security.GeneralSecurityException;
    import java.security.KeyStore;
    import java.security.PrivateKey;
    import java.security.cert.Certificate;
    import java.util.logging.Level;
    
    import org.slf4j.Logger;
    import org.eclipse.californium.core.CoapResource;
    import org.eclipse.californium.core.CoapServer;
    import org.eclipse.californium.core.coap.CoAP.ResponseCode;
    import org.eclipse.californium.core.network.CoapEndpoint;
    import org.eclipse.californium.core.network.Endpoint;
    import org.eclipse.californium.core.network.config.NetworkConfig;
    import org.eclipse.californium.core.network.interceptors.MessageTracer;
    import org.eclipse.californium.core.server.resources.CoapExchange;
    import org.eclipse.californium.scandium.DTLSConnector;
    import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
    import org.eclipse.californium.scandium.dtls.CertificateType;
    import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
    import org.eclipse.californium.scandium.dtls.pskstore.InMemoryPskStore;
    
    
    public class Nrf5xSecureServer {
    
    	//static {
    	//	Logger.initialize();
    	//	CaliforniumLogger.setLevel(Level.CONFIG);
    	//	ScandiumLogger.initialize();
    	//	ScandiumLogger.setLevel(Level.FINER);
    	//}
    
    	// allows configuration via Californium.properties
    	public static final int DTLS_PORT = NetworkConfig.getStandard().getInt(NetworkConfig.Keys.COAP_SECURE_PORT);
    
    	private static final String TRUST_STORE_PASSWORD = "rootPass";
    	private final static String KEY_STORE_PASSWORD = "endPass";
    	private static final String KEY_STORE_LOCATION = "../../demo-certs/src/main/resources/keyStore.jks";
    	private static final String TRUST_STORE_LOCATION = "../../demo-certs/src/main/resources/trustStore.jks";
    
    	public static void main(String[] args) {
    
    		CoapServer server = new CoapServer();
    //		server.add(new CoapResource("secure") {
    //			@Override
    //			public void handleGET(CoapExchange exchange) {
    //				exchange.respond(ResponseCode.CONTENT, "hello security");
    //			}
    //		});
            server.add(new CoapResource("lights").add(new DevKitResource("led3"), new DevKitResource("led4")));
    		// ETSI Plugtest environment
    		// server.addEndpoint(new CoAPEndpoint(new DTLSConnector(new InetSocketAddress("::1", DTLS_PORT)), NetworkConfig.getStandard()));
    		// server.addEndpoint(new CoAPEndpoint(new DTLSConnector(new InetSocketAddress("127.0.0.1", DTLS_PORT)), NetworkConfig.getStandard()));
    		// server.addEndpoint(new CoAPEndpoint(new DTLSConnector(new InetSocketAddress("2a01:c911:0:2010::10", DTLS_PORT)), NetworkConfig.getStandard()));
    		// server.addEndpoint(new CoAPEndpoint(new DTLSConnector(new InetSocketAddress("10.200.1.2", DTLS_PORT)), NetworkConfig.getStandard()));
    
    		try {
    			// Pre-shared secrets
    			InMemoryPskStore pskStore = new InMemoryPskStore();
    			pskStore.setKey("Client_identity", "secretPSK".getBytes()); // from ETSI Plugtest test spec
    
    			// load the trust store
    			KeyStore trustStore = KeyStore.getInstance("JKS");
    			InputStream inTrust = new FileInputStream(TRUST_STORE_LOCATION);
    			trustStore.load(inTrust, TRUST_STORE_PASSWORD.toCharArray());
    
    			// You can load multiple certificates if needed
    			Certificate[] trustedCertificates = new Certificate[1];
    			trustedCertificates[0] = trustStore.getCertificate("root");
    
    			// load the key store
    			KeyStore keyStore = KeyStore.getInstance("JKS");
    			InputStream in = new FileInputStream(KEY_STORE_LOCATION);
    			keyStore.load(in, KEY_STORE_PASSWORD.toCharArray());
    			
    			
    			InetAddress myIPv6Addr = Inet6Address.getByName("Your IPv6 address as string.");
    			InetSocketAddress myInetSocketAddr = new InetSocketAddress(myIPv6Addr, DTLS_PORT);
    			DtlsConnectorConfig.Builder config = new DtlsConnectorConfig.Builder();
    			config.setAddress(myInetSocketAddr);
    			config.setSupportedCipherSuites(new CipherSuite[]{CipherSuite.TLS_PSK_WITH_AES_128_CCM_8,
    					CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8});
    			config.setPskStore(pskStore);
    			config.setIdentity((PrivateKey)keyStore.getKey("server", KEY_STORE_PASSWORD.toCharArray()),
    					keyStore.getCertificateChain("server"), CertificateType.RAW_PUBLIC_KEY, CertificateType.X_509);
    			config.setTrustStore(trustedCertificates);
    			
    			DTLSConnector connector = new DTLSConnector(config.build(), null);
    			CoapEndpoint.Builder endpointBuilder = new CoapEndpoint.Builder();
    			endpointBuilder.setNetworkConfig(NetworkConfig.getStandard());
    			endpointBuilder.setConnector(connector);
    			server.addEndpoint(endpointBuilder.build());
    			server.start();
    
    		} catch (GeneralSecurityException | IOException e) {
    			System.err.println("Could not load the keystore");
    			e.printStackTrace();
    		}
    
    		// add special interceptor for message traces
    		for (Endpoint ep : server.getEndpoints()) {
    			ep.addInterceptor(new MessageTracer());
    		}
    
    		System.out.println("Secure CoAP server powered by Scandium (Sc) is listening on port " + DTLS_PORT);
    	}
    
    }
    

    /*******************************************************************************
     * Copyright (c) 2014 Institute for Pervasive Computing, ETH Zurich and others.
     * 
     * All rights reserved. This program and the accompanying materials
     * are made available under the terms of the Eclipse Public License v1.0
     * and Eclipse Distribution License v1.0 which accompany this distribution.
     * 
     * The Eclipse Public License is available at
     *    http://www.eclipse.org/legal/epl-v10.html
     * and the Eclipse Distribution License is available at
     *    http://www.eclipse.org/org/documents/edl-v10.html.
     * 
     * Contributors:
     *    Matthias Kovatsch - creator and main architect
     ******************************************************************************/
    package org.eclipse.californium.tools;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.Inet6Address;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.security.GeneralSecurityException;
    import java.security.KeyStore;
    import java.security.PrivateKey;
    import java.security.cert.Certificate;
    import java.util.logging.Level;
    
    import org.eclipse.californium.core.Utils;
    import org.eclipse.californium.core.coap.CoAP;
    import org.eclipse.californium.core.coap.MediaTypeRegistry;
    import org.eclipse.californium.core.coap.Request;
    import org.eclipse.californium.core.coap.Response;
    import org.eclipse.californium.core.network.CoapEndpoint;
    import org.eclipse.californium.core.network.Endpoint;
    import org.eclipse.californium.core.network.EndpointManager;
    import org.eclipse.californium.core.network.config.NetworkConfig;
    import org.eclipse.californium.elements.RawData;
    import org.eclipse.californium.elements.RawDataChannel;
    import org.eclipse.californium.scandium.DTLSConnector;
    import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
    import org.eclipse.californium.scandium.dtls.CertificateType;
    import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
    import org.eclipse.californium.scandium.dtls.pskstore.InMemoryPskStore;
    import org.eclipse.californium.scandium.dtls.pskstore.StaticPskStore;
    
    /**
     * This class implements a simple CoAP client for testing purposes. Usage:
     * <p>
     * {@code java -jar SampleClient.jar [-l] METHOD URI [PAYLOAD]}
     * <ul>
     * <li>METHOD: {GET, POST, PUT, DELETE, DISCOVER, OBSERVE}
     * <li>URI: The URI to the remote endpoint or resource}
     * <li>PAYLOAD: The data to send with the request}
     * </ul>
     * Options:
     * <ul>
     * <li>-l: Loop for multiple responses}
     * </ul>
     * Examples:
     * <ul>
     * <li>{@code SampleClient DISCOVER coap://localhost}
     * <li>{@code SampleClient POST coap://someServer.org:5683 my data}
     * </ul>
     */
    public class Nrf5xConsoleClient {
    
    	//static {
    	//	CaliforniumLogger.initialize();
    	//	CaliforniumLogger.setLevel(Level.WARNING);
    	//	
    	//	ScandiumLogger.initialize();
    	//	ScandiumLogger.setLevel(Level.FINER);
    	//}
    	
    	// the trust store file used for DTLS server authentication
        private static final String TRUST_STORE_LOCATION = "../../californium/demo-certs/src/main/resources/trustStore.jks";
    	private static final String TRUST_STORE_PASSWORD = "rootPass";
    
    	private static final String KEY_STORE_LOCATION = "../../californium/demo-certs/src/main/resources/keyStore.jks";
    	private static final String KEY_STORE_PASSWORD = "endPass";
    	
    	// resource URI path used for discovery
    	private static final String DISCOVERY_RESOURCE = "/.well-known/core";
    
    	// indices of command line parameters
    	private static final int IDX_METHOD          = 0;
    	private static final int IDX_URI             = 1;
    	private static final int IDX_PAYLOAD         = 2;
    
    	// exit codes for runtime errors
    	private static final int ERR_MISSING_METHOD  = 1;
    	private static final int ERR_UNKNOWN_METHOD  = 2;
    	private static final int ERR_MISSING_URI     = 3;
    	private static final int ERR_BAD_URI         = 4;
    	private static final int ERR_REQUEST_FAILED  = 5;
    	private static final int ERR_RESPONSE_FAILED = 6;
    
    
    	// initialize parameters
    	static String method = null;
    	static URI uri = null;
    	static String payload = "";
    	static boolean loop = false;
    
    	static boolean usePSK = false;
    	static boolean useRaw = true;
    
    	// for coaps
    	private static Endpoint dtlsEndpoint;
    	private static DTLSConnector dtlsConnector;
    	
    	/*
    	 * Main method of this client.
    	 */
    	public static void main(String[] args) throws IOException, GeneralSecurityException {
    		
    		// display help if no parameters specified
    		if (args.length == 0) {
    			printInfo();
    			return;
    		}
    		
    		// input parameters
    		int i_all = 0;
    		int i_rep = -1;
    		int n_rep = 1;
    		int idx = 0;
    		for (String arg : args) {
    			i_all++;
    			if (arg.startsWith("-")) {
    				if (arg.equals("-l")) {
    					loop = true;
    				} else if (arg.equals("-psk")) {
    					usePSK = true;
    				} else if (arg.equals("-cert")) {
    					useRaw = false;
    				} else if (arg.equals("-rep")) {
    					i_rep = i_all;
    				} else {
    					System.out.println("Unrecognized option: " + arg);
    				}
    			} else {
    				if ((i_rep > 0) && (i_all == (i_rep + 1)))
    				{
    					n_rep = Integer.parseInt(arg);
    				}
    				else
    				{
    					switch (idx) {
    						case IDX_METHOD:
    							method = arg.toUpperCase();
    							break;
    						case IDX_URI:
    							try {
    								uri = new URI(arg);
    							} catch (URISyntaxException e) {
    								System.err.println("Failed to parse URI: " + e.getMessage());
    								System.exit(ERR_BAD_URI);
    							}
    							break;
    						case IDX_PAYLOAD:
    							payload = arg;
    							break;
    						default:
    							System.out.println("Unexpected argument: " + arg);
    					}
    					++idx;
    				}
    			}
    		}
    
    		// check if mandatory parameters specified
    		if (method == null) {
    			System.err.println("Method not specified");
    			System.exit(ERR_MISSING_METHOD);
    		}
    		if (uri == null) {
    			System.err.println("URI not specified");
    			System.exit(ERR_MISSING_URI);
    		}
    		
    		for (int i=0; i<n_rep; i++)
    		{
    			// create request according to specified method
    			Request request = newRequest(method);
    	
    			// set request URI
    			if (method.equals("DISCOVER") && (uri.getPath() == null || uri.getPath().isEmpty() || uri.getPath().equals("/"))) {
    				// add discovery resource path to URI
    				try {
    					uri = new URI(uri.getScheme(), uri.getAuthority(), DISCOVERY_RESOURCE, uri.getQuery());
    					
    				} catch (URISyntaxException e) {
    					System.err.println("Failed to parse URI: " + e.getMessage());
    					System.exit(ERR_BAD_URI);
    				}
    			}
    			
    			request.setURI(uri);
    			request.setPayload(payload);
    			request.getOptions().setContentFormat(MediaTypeRegistry.TEXT_PLAIN);
    			
    			if (request.getScheme().equals(CoAP.COAP_SECURE_URI_SCHEME)) {
    				if (i == 0) {
    					try {
    						// load key store
    						KeyStore keyStore = KeyStore.getInstance("JKS");
    						InputStream in = new FileInputStream(KEY_STORE_LOCATION);
    						keyStore.load(in, KEY_STORE_PASSWORD.toCharArray());
    		
    						// load trust store
    						KeyStore trustStore = KeyStore.getInstance("JKS");
    						InputStream inTrust = new FileInputStream(TRUST_STORE_LOCATION);
    						trustStore.load(inTrust, TRUST_STORE_PASSWORD.toCharArray());
    		
    						// You can load multiple certificates if needed
    						Certificate[] trustedCertificates = new Certificate[1];
    						trustedCertificates[0] = trustStore.getCertificate("root");
    		
    						InetAddress myIPv6Addr = Inet6Address.getByName("Your IPv6 address as string.");
    						InetSocketAddress myInetSocketAddr = new InetSocketAddress(myIPv6Addr, 5694);
    						DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder();
    						builder.setAddress(myInetSocketAddr);
    						builder.setPskStore(new StaticPskStore("Client_identity", "secretPSK".getBytes()));
    						builder.setIdentity((PrivateKey)keyStore.getKey("client", KEY_STORE_PASSWORD.toCharArray()),
    								keyStore.getCertificateChain("client"), CertificateType.RAW_PUBLIC_KEY, CertificateType.X_509);
    						builder.setTrustStore(trustedCertificates);
    						dtlsConnector = new DTLSConnector(builder.build(), null);
    						dtlsConnector.setRawDataReceiver(new RawDataChannelImpl());
    		
    					} catch (GeneralSecurityException | IOException e) {
    						System.err.println("Could not load the keystore");
    						e.printStackTrace();
    					}
    			        
    					CoapEndpoint.Builder endpointBuilder = new CoapEndpoint.Builder();
    					endpointBuilder.setNetworkConfig(NetworkConfig.getStandard());
    					endpointBuilder.setConnector(dtlsConnector);
    					dtlsEndpoint = endpointBuilder.build();
    					dtlsEndpoint.start();
    					EndpointManager.getEndpointManager().setDefaultEndpoint(dtlsEndpoint);
    				}
    			}
    			
    			// execute request
    			try {
    				request.send();
    	
    				// loop for receiving multiple responses
    				do {
    		
    					// receive response
    					Response response = null;
    					try {
    						response = request.waitForResponse();
    					} catch (InterruptedException e) {
    						System.err.println("Failed to receive response: " + e.getMessage());
    						System.exit(ERR_RESPONSE_FAILED);
    					}
    		
    					// output response
    		
    					if (response != null) {
    		
    						System.out.println(Utils.prettyPrint(response));
    						System.out.println("Time elapsed (ms): " + response.getRTT());
    		
    						// check of response contains resources
    						if (response.getOptions().isContentFormat(MediaTypeRegistry.APPLICATION_LINK_FORMAT)) {
    		
    							String linkFormat = response.getPayloadString();
    		
    							// output discovered resources
    							System.out.println("\nDiscovered resources:");
    							System.out.println(linkFormat);
    		
    						} else {
    							// check if link format was expected by client
    							if (method.equals("DISCOVER")) {
    								System.out.println("Server error: Link format not specified");
    							}
    						}
    		
    					} else {
    						// no response received	
    						System.err.println("Request timed out");
    						break;
    					}
    		
    				} while (loop);
    				
    			} catch (Exception e) {
    				System.err.println("Failed to execute request: " + e.getMessage());
    				System.exit(ERR_REQUEST_FAILED);
    			}
    
    			try {
    				Thread.sleep(1000);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}
    
    	/*
    	 * Outputs user guide of this program.
    	 */
    	public static void printInfo() {
    		System.out.println("Californium (Cf) Console Client");
    		System.out.println("(c) 2014, Institute for Pervasive Computing, ETH Zurich");
    		System.out.println();
    		System.out.println("Usage: " + Nrf5xConsoleClient.class.getSimpleName() + " [-l] METHOD URI [PAYLOAD]");
    		System.out.println("  METHOD  : {GET, POST, PUT, DELETE, DISCOVER, OBSERVE}");
    		System.out.println("  URI     : The CoAP URI of the remote endpoint or resource");
    		System.out.println("            A coaps URI will automatically use CoAP over DTLS");
    		System.out.println("  PAYLOAD : The data to send with the request");
    		System.out.println("Options:");
    		System.out.println("  -rep N  : Do a request N number of times with the same parameters, with 1 sec delay between requests.");
    		System.out.println("  -l      : Loop for multiple responses");
    		System.out.println("           (automatic for OBSERVE and separate responses)");
    		System.out.println("  -psk    : Use a pre-shared secrest for DTLS (is prompted)");
    		System.out.println("  -cert   : Use full X.509 certificates instead of raw public keys");
    		System.out.println();
    		System.out.println("Examples:");
    		System.out.println("  " + Nrf5xConsoleClient.class.getSimpleName() + " DISCOVER coap://localhost");
    		System.out.println("  " + Nrf5xConsoleClient.class.getSimpleName() + " PUT coap://iot.eclipse.org:5683/large-put my data");
    	}
    
    	private static class RawDataChannelImpl implements RawDataChannel {
    
    		// @Override
    		public void receiveData(final RawData raw) {
    
    			System.out.println("Received response: " + new String(raw.getBytes()));
    
    			dtlsConnector.destroy();
    		}
    	}	
    
    	/*
    	 * Instantiates a new request based on a string describing a method.
    	 * 
    	 * @return A new request object, or null if method not recognized
    	 */
    	private static Request newRequest(String method) {
    		if (method.equals("GET")) {
    			return Request.newGet();
    		} else if (method.equals("POST")) {
    			return Request.newPost();
    		} else if (method.equals("PUT")) {
    			return Request.newPut();
    		} else if (method.equals("DELETE")) {
    			return Request.newDelete();
    		} else if (method.equals("DISCOVER")) {
    			return Request.newGet();
    		} else if (method.equals("OBSERVE")) {
    			Request request = Request.newGet();
    			request.setObserve();
    			loop = true;
    			return request;
    		} else {
    			System.err.println("Unknown method: " + method);
    			System.exit(ERR_UNKNOWN_METHOD);
    			return null;
    		}
    	}
    
    }
    

    Best regards,

    Didrik

Related