package org.jolokia.handler;

import static org.jolokia.util.RequestType.EXEC;

import java.io.IOException;
import java.lang.management.ManagementFactory;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import org.jolokia.converter.StringToObjectConverter;
import org.jolokia.request.JmxExecRequest;
import org.jolokia.request.JmxRequestBuilder;
import org.jolokia.restrictor.AllowAllRestrictor;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class OpenExecHandlerTest {
    private ExecHandler handler;

    private ObjectName oName;
	
    @BeforeMethod
    public void createHandler() throws MalformedObjectNameException {
        StringToObjectConverter converter = new StringToObjectConverter();
        handler = new ExecHandler(new AllowAllRestrictor(),converter);
    }

    @BeforeTest
    public void registerMbean() throws MalformedObjectNameException, MBeanException, InstanceAlreadyExistsException, IOException, NotCompliantMBeanException, ReflectionException {
        oName = new ObjectName("jolokia:test=openExec");

        MBeanServerConnection conn = getMBeanServer();
        conn.createMBean(OpenExecData.class.getName(),oName);        
    }
    
    /**
     * If a field in the argument is not set it will be set to its default value
     */
    @Test
    public void missingField() throws InstanceNotFoundException, IOException, ReflectionException, AttributeNotFoundException, MBeanException, MalformedObjectNameException {
    	// set a value just for stringField, leave out intField
        JmxExecRequest request = new JmxRequestBuilder(EXEC, oName).
                operation("compositeData").
                arguments("{ \"stringField\":\"aString\" }").
                build();
        handler.handleRequest(getMBeanServer(),request);
    }

    /**
     * set a non-existing field 
     */
    @Test(expectedExceptions={IllegalArgumentException.class})
    public void invalidField() throws MalformedObjectNameException, InstanceNotFoundException, AttributeNotFoundException, ReflectionException, MBeanException, IOException {
    	// set a value just for stringField, leave out intField
        JmxExecRequest request = new JmxRequestBuilder(EXEC, oName).
                operation("compositeData").
                arguments("{ \"nonExistentField\":\"aString\" }").
                build();
        handler.handleRequest(getMBeanServer(),request);    	
    }    
    
    /**
     * Give an invalid value (wrong type) for the field 
     */
    @Test(expectedExceptions={ NumberFormatException.class })
    public void invalidValueForField() throws MalformedObjectNameException, InstanceNotFoundException, AttributeNotFoundException, ReflectionException, MBeanException, IOException {
        JmxExecRequest request = new JmxRequestBuilder(EXEC, oName).
        		operation("compositeData").
        		arguments("{ \"intField\":\"aString\" }").
        		build();
        handler.handleRequest(getMBeanServer(),request);    	
    }

    /**
     * If a field in the argument is not set it will be set to its default value
     */
    @Test
    public void arrayOfComposites() throws InstanceNotFoundException, IOException, ReflectionException, AttributeNotFoundException, MBeanException, MalformedObjectNameException {
        JmxExecRequest request = new JmxRequestBuilder(EXEC, oName).
                operation("arrayData").
                arguments("[ { \"stringField\":\"aString\" } ]").
                build();
        handler.handleRequest(getMBeanServer(),request);
    }

    /**
     * If a field in the argument is not set it will be set to its default value
     */
    @Test
    public void listOfComposites() throws InstanceNotFoundException, IOException, ReflectionException, AttributeNotFoundException, MBeanException, MalformedObjectNameException {
        JmxExecRequest request = new JmxRequestBuilder(EXEC, oName).
                operation("listData").
                arguments("[ { \"stringField\":\"aString\" } ]").
                build();
        handler.handleRequest(getMBeanServer(),request);
    }
    
    @Test
    public void nested() throws MalformedObjectNameException, InstanceNotFoundException, AttributeNotFoundException, ReflectionException, MBeanException, IOException {
        JmxExecRequest request = new JmxRequestBuilder(EXEC, oName).
				operation("compositeData").
				arguments("{ \"nestedClass\":{\"nestedField\":\"aString\"} }").
				build();
        handler.handleRequest(getMBeanServer(),request);    	    	
    }
    
    @Test
    public void compositeWithArrayField() throws MalformedObjectNameException, InstanceNotFoundException, AttributeNotFoundException, ReflectionException, MBeanException, IOException {
        JmxExecRequest request = new JmxRequestBuilder(EXEC, oName).
        		operation("compositeData").
        		arguments("{ \"array\":[\"one\", \"two\"] }").
        		build();
        handler.handleRequest(getMBeanServer(),request);    	
    }
    


    private MBeanServerConnection getMBeanServer() {
        return ManagementFactory.getPlatformMBeanServer();
    }

}

@@ -5422,16 +5422,468 @@
  %7D%0A    %0A
+    @Test%0A    public void compositeWithListField() throws MalformedObjectNameException, InstanceNotFoundException, AttributeNotFoundException, ReflectionException, MBeanException, IOException %7B%0A        JmxExecRequest request = new JmxRequestBuilder(EXEC, oName).%0A        %09%09operation(%22compositeData%22).%0A        %09%09arguments(%22%7B %5C%22list%5C%22:%5B%5C%22one%5C%22, %5C%22two%5C%22%5D %7D%22).%0A        %09%09build();%0A        handler.handleRequest(getMBeanServer(),request);    %09%0A    %7D%0A        
 %0A%0A    pr

add test from CompositeData with a list field