package org.merka.stubgen.web.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarInputStream;
import javax.servlet.http.HttpServletRequest;
import org.merka.stubgen.MockObjectGenerator;
import org.merka.stubgen.classloader.JarInputStreamClassLoader;
import org.merka.stubgen.exception.MockGenException;
import org.merka.stubgen.web.entity.StubClass;
import org.merka.stubgen.web.entity.UploadedJarFile;
import org.merka.stubgen.web.session.JarManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.RequestContextUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@Controller
@SessionAttributes(value = {"stubClasses"})
public class UploadFormController
{
private static transient Logger logger = LoggerFactory.getLogger(UploadFormController.class);
public static final String JSESSIONIDKEY = "JSESSIONID";
public static final String UPLOAD_FORM_VIEW = "uploadFormView";
public static final String MESSAGE_VIEW = "showMessage";
public static final String ERROR_VIEW = "uncaughtErrorView";
private MultipartFile jarFile;
@Autowired
private JarManager jarManager;
public JarManager getJarManager()
{
return jarManager;
}
public void setJarManager(JarManager jarManager)
{
this.jarManager = jarManager;
}
public MultipartFile getJarFile()
{
return jarFile;
}
public void setJarFile(MultipartFile jarFile)
{
this.jarFile = jarFile;
}
@RequestMapping(value = {"/uploadForm"})
public ModelAndView enter(
@ModelAttribute("uploadedFile")UploadedJarFile file,
@CookieValue(value = JSESSIONIDKEY) String jsessionid,
BindingResult result)
{
Map<String, Object> model = new HashMap<>();
model.put("jsessionid", jsessionid);
return new ModelAndView(UPLOAD_FORM_VIEW, model);
}
@RequestMapping(value = "/submitFile")
public ModelAndView submitFile(
HttpServletRequest request,
@ModelAttribute("uploadedFile") UploadedJarFile file,
@CookieValue(value = JSESSIONIDKEY) String jsessionid,
BindingResult result) throws IOException
{
Map<String, Object> model = new HashMap<>();
model.put("jsessionid", jsessionid);
String title = "Upload OK";
// for each class, this array contains a messages with the corresponding report
ArrayList<StubClass> stubClasses = new ArrayList<>();
model.put("title", title);
JarInputStream jarStream = new JarInputStream(file.getUploadedFile().getInputStream());
JarInputStreamClassLoader classLoader = new JarInputStreamClassLoader(jarStream);
MockObjectGenerator generator = new MockObjectGenerator();
for(String className : classLoader.getAvailableClasses())
{
logger.info("Class found --> " + className + ". ");
Class<?> clazz = null;
boolean loadable = true;
try
{
clazz = classLoader.loadClass(className);
logger.info(clazz.getName());
}
catch(Throwable t)
{
loadable = false;
logger.error("Impossible to load the class", t);
}
boolean instantiable = true;
try
{
Object obj = generator.generate(classLoader.loadClass(className));
}
catch(Throwable e)
{
instantiable = false;
logger.error("Impossible to instantiate the class", e);
}
stubClasses.add(new StubClass(className, loadable, instantiable, clazz));
}
getJarManager().put(jsessionid, classLoader);
model.put("stubClasses", stubClasses);
return new ModelAndView(UPLOAD_FORM_VIEW, model);
}
protected void updateModel(String jsessionid)
{
}
@RequestMapping("/instantiate")
public String instantiate(
HttpServletRequest request,
@CookieValue (value = JSESSIONIDKEY) String jsessionid,
@RequestParam (value = "className") String className,
Model model) throws ClassNotFoundException, MockGenException, JsonProcessingException
{
logger.info(String.format("Trying to instantiate class %s", className));
// This snippet is just to try another way to access the JarManager bean
WebApplicationContext context = RequestContextUtils.getWebApplicationContext(request);
JarManager jarManagerTemp = (JarManager)context.getBean("jarManager");
JarInputStreamClassLoader cached = jarManagerTemp.get(jsessionid);
logger.info(cached.toString());
// end snippet
String json = null;
if(cached != null)
{
Class<?> clazz = cached.loadClass(className);
MockObjectGenerator generator = new MockObjectGenerator();
Object instance = generator.generate(clazz);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
json = mapper.writeValueAsString(instance);
}
if(json != null)
{
model.addAttribute("plainText", json);
}
model.addAttribute("jsessionid", jsessionid);
return UPLOAD_FORM_VIEW;
}
@ExceptionHandler
public String onUncaughtError(Throwable t)
{
logger.error("Uncaught Error: ", t);
return ERROR_VIEW;
}
}