package org.ngrinder.operation.cotroller;

import java.io.ByteArrayOutputStream;

import javax.annotation.PostConstruct;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.ngrinder.common.controller.NGrinderBaseController;
import org.ngrinder.infra.config.Config;
import org.ngrinder.perftest.service.AgentManager;
import org.ngrinder.perftest.service.ConsoleManager;
import org.ngrinder.perftest.service.PerfTestService;
import org.ngrinder.script.service.FileEntryService;
import org.ngrinder.user.service.UserService;
import org.python.util.PythonInterpreter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * Script Runner for maintenance.
 * 
 * @author JunHo Yoon
 * @since 3.0
 */
@Controller
@RequestMapping("/operation/scriptConsole")
@PreAuthorize("hasAnyRole('A', 'S')")
public class ScriptConsoleController extends NGrinderBaseController implements ApplicationContextAware {
	@Autowired
	private Config config;

	private ApplicationContext applicationContext;

	@Autowired
	private AgentManager agentManager;

	@Autowired
	private ConsoleManager consoleManager;

	@Autowired
	private PerfTestService perfTestService;

	@Autowired
	private FileEntryService fileEntryService;

	@Autowired
	private UserService userService;
	
	private PythonInterpreter interp;
	@PostConstruct
	public void init() {
		interp = new PythonInterpreter();
		interp.set("applicationContext", this.applicationContext);
		interp.set("agentManager", this.agentManager);
		interp.set("consoleManager", this.consoleManager);
		interp.set("userService", this.userService);
		interp.set("perfTestService", this.perfTestService);
		interp.set("fileEntryService", this.fileEntryService);
		interp.set("config", this.config);
	}

	@RequestMapping("")
	public String runScript(@RequestParam(value = "script", required = false) String script, Model model) {
		if (StringUtils.isNotBlank(script)) {
			String result = processPython(script);
			model.addAttribute("script", script);
			model.addAttribute("result", result);
		}
		return "operation/scriptConsole";
	}

	/**
	 * Run python script.
	 * 
	 * @param script
	 *            script
	 * @return stdout and err
	 */
	public synchronized String processPython(String script) {
		try {
			interp.cleanup();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			interp.setOut(bos);
			interp.setErr(bos);
			interp.exec(script);
			interp.cleanup();
			return bos.toString();
		} catch (Exception e) {
			
			String message = ExceptionUtils.getMessage(e);
			message = message + "\n" + ExceptionUtils.getStackTrace(e);
			return message;
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
}

@@ -1749,17 +1749,16 @@
 ervice;%0A
-%09
 %0A%09privat
@@ -1785,16 +1785,17 @@
 interp;%0A
+%0A
 %09@PostCo
@@ -2674,21 +2674,8 @@
 lic 
-synchronized 
 Stri
@@ -2691,16 +2691,22 @@
 sPython(
+final 
 String s
@@ -2725,37 +2725,22 @@
 ry %7B%0A%09%09%09
+f
 in
-terp.cleanup();%0A%09%09%09
+al 
 ByteArra
@@ -2788,16 +2788,158 @@
 ream();%0A
+%09%09%09synchronized (interp) %7B%0A%09%09%09%09Thread thread = new Thread(new Runnable() %7B%0A%09%09%09%09%09@Override%0A%09%09%09%09%09public void run() %7B%0A%09%09%09%09%09%09interp.cleanup();%0A%09%09%09
 %09%09%09inter
@@ -2949,24 +2949,27 @@
 etOut(bos);%0A
+%09%09%09
 %09%09%09interp.se
@@ -2979,16 +2979,19 @@
 r(bos);%0A
+%09%09%09
 %09%09%09inter
@@ -3006,16 +3006,19 @@
 cript);%0A
+%09%09%09
 %09%09%09inter
@@ -3030,16 +3030,137 @@
 anup();%0A
+%09%09%09%09%09%7D%0A%09%09%09%09%7D);%0A%09%09%09%09thread.run();%0A%09%09%09%09thread.join(30000);%0A%09%09%09%09if (thread.isAlive()) %7B%0A%09%09%09%09%09thread.interrupt();%0A%09%09%09%09%7D%0A%09%09%09%7D%0A
 %09%09%09retur
@@ -3207,12 +3207,8 @@
 ) %7B%0A
-%09%09%09%0A
 %09%09%09S

Enhance script console - Speed up and make it terminatable within 30 sec.