/**
* http://surenpi.com
*/
package org.suren.autotest.platform.controller;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.poi.util.IOUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.suren.autotest.platform.AutoTestClassloader;
import org.suren.autotest.platform.mapping.AttachmentMapper;
import org.suren.autotest.platform.mapping.DataSourceInfoMapper;
import org.suren.autotest.platform.mapping.PageInfoMapper;
import org.suren.autotest.platform.mapping.ProjectMapper;
import org.suren.autotest.platform.mapping.SuiteRunnerInfoMapper;
import org.suren.autotest.platform.model.Attachment;
import org.suren.autotest.platform.model.DataSourceInfo;
import org.suren.autotest.platform.model.PageInfo;
import org.suren.autotest.platform.model.Project;
import org.suren.autotest.platform.model.SuiteRunnerInfo;
import org.suren.autotest.platform.schemas.autotest.Autotest;
import org.suren.autotest.platform.schemas.datasource.DataSources;
import org.suren.autotest.platform.schemas.suite.Suite;
import org.suren.autotest.platform.security.UserDetail;
import org.suren.autotest.platform.util.JAXBUtils;
import org.suren.autotest.web.framework.code.Generator;
import org.suren.autotest.web.framework.jdt.JDTUtils;
import org.suren.autotest.web.framework.util.StringUtils;
/**
* 项目管理
* @author suren
* @date 2017年1月20日 下午7:43:05
*/
@Controller
@RequestMapping("/project")
public class ProjectController implements ApplicationContextAware
{
@Autowired
private ProjectMapper projectMapper;
@Autowired
private PageInfoMapper pageInfoMapper;
@Autowired
private DataSourceInfoMapper dataSourceInfoMapper;
@Autowired
private SuiteRunnerInfoMapper suiteRunnerInfoMapper;
@Autowired
private AttachmentMapper attachmentMapper;
@Autowired
private ServletContext servletContext;
@Resource(name = "xml_to_java")
private Generator codeGenerator;
@RequestMapping("/list")
public String list(Model model)
{
List<Project> projects = projectMapper.getAll();
model.addAttribute("projects", projects);
return "project_list";
}
@RequestMapping("/edit")
public String edit(Model model, String id)
{
Project proForModel = projectMapper.getById(id);
if(proForModel == null)
{
UserDetail userDetail = (UserDetail) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String ownerId = userDetail.getId();
proForModel = new Project();
proForModel.setOwnerId(ownerId);
}
else
{
List<Attachment> attachList = attachmentMapper.getByBelongId(id);
proForModel.setAttachList(attachList);
}
model.addAttribute("project", proForModel);
return "project_edit";
}
@RequestMapping("/save")
public String save(Model model, Project project)
{
if(StringUtils.isBlank(project.getId()))
{
project.setCreateTime(new Date());
projectMapper.save(project);
}
else
{
projectMapper.update(project);
}
return "redirect:/project/edit.su?id=" + project.getId();
}
@RequestMapping("/del")
public String del(Model model, String id)
{
projectMapper.delById(id);
return "redirect:/project/list.su";
}
@RequestMapping("/deploy")
public String projectDeploy(String id)
{
UserDetail userDetail = (UserDetail) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String ownerId = userDetail.getId();
String projectId = id;
File rootDir = new File(servletContext.getRealPath("/deploy"), id + "/" + ownerId);
rootDir.mkdirs();
File srcOutputDir = new File(rootDir, "src");
JDTUtils jdtUtils = new JDTUtils(srcOutputDir);
//附件拷贝
List<Attachment> attachList = attachmentMapper.getByBelongId(projectId);
if(CollectionUtils.isNotEmpty(attachList))
{
for(Attachment attach : attachList)
{
String name = attach.getFileName();
if(name.endsWith(".java"))
{
String pkgPath = attach.getRemark();
pkgPath = StringUtils.isBlank(pkgPath) ? "" : pkgPath.trim();
pkgPath = pkgPath.replace(".", "/");
try
{
FileUtils.copyFile(new File(attach.getRelativePath(), name),
new File(srcOutputDir, pkgPath + "/" + name));
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
//元素定位文件部署
List<PageInfo> pageInfoList = pageInfoMapper.getAllWithContentByProjectId(projectId);
if(CollectionUtils.isNotEmpty(pageInfoList))
{
for(PageInfo pageInfo : pageInfoList)
{
String content = pageInfo.getContent();
File autotestFile = new File(rootDir, pageInfo.getName() + ".xml");
try
{
FileUtils.writeStringToFile(autotestFile, content, "UTF-8");
//生成Java源码
codeGenerator.generate(autotestFile.toString(), srcOutputDir.toString());
}
catch (IOException e)
{
e.printStackTrace();
}
}
//编译Java源码
List<File> result = jdtUtils.compileAllFile();
try
{
AutoTestClassloader cla = new AutoTestClassloader(new URL[]{srcOutputDir.toURI().toURL()},
Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(cla);
String rootPath = srcOutputDir.getAbsolutePath();
for(File javaSrcFile : result)
{
String absPath = javaSrcFile.getAbsolutePath();
String clsName = absPath.replace(rootPath, "").replace("/", "\\").replace("\\", ".").replace(".java", "");
clsName = clsName.substring(1);
Class<?> target = cla.loadClass(clsName);
BeanDefinitionRegistry reg = (BeanDefinitionRegistry) ((ConfigurableApplicationContext)applicationContext.getParent()).getBeanFactory();
BeanDefinitionBuilder beanDef = BeanDefinitionBuilder.genericBeanDefinition(target);
AbstractBeanDefinition bean = beanDef.getBeanDefinition();
reg.registerBeanDefinition(target.getName(), bean);
Object targetObj = applicationContext.getBean(target.getName());
for(Field field : target.getDeclaredFields())
{
try
{
Object fieldObj = applicationContext.getBean(field.getType());
field.setAccessible(true);
field.set(targetObj, fieldObj);;
}
catch (IllegalAccessException | IllegalArgumentException e)
{
e.printStackTrace();
}
catch(NoSuchBeanDefinitionException e)
{
}
if(field.getAnnotation(Autowired.class) != null)
{
}
}
}
}
catch (MalformedURLException | ClassNotFoundException e)
{
e.printStackTrace();
}
}
//数据源文件部署
List<DataSourceInfo> dataSourceInfoList = dataSourceInfoMapper.getAllWithContentByProjectId(projectId);
if(CollectionUtils.isNotEmpty(dataSourceInfoList))
{
for(DataSourceInfo dataSourceInfo : dataSourceInfoList)
{
String content = dataSourceInfo.getContent();
File dataSourceFile = new File(rootDir, dataSourceInfo.getName() + ".xml");
try
{
FileUtils.writeStringToFile(dataSourceFile, content, "utf-8");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
//测试套件文件部署
List<SuiteRunnerInfo> suiteRunnerInfoList = suiteRunnerInfoMapper.getAllWithContentByProjectId(projectId);
if(CollectionUtils.isNotEmpty(suiteRunnerInfoList))
{
for(SuiteRunnerInfo suiteRunnerInfo : suiteRunnerInfoList)
{
String content = suiteRunnerInfo.getContent();
File suiteFile = new File(rootDir, suiteRunnerInfo.getName() + ".xml");
try
{
FileUtils.writeStringToFile(suiteFile, content, "utf-8");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return "redirect:/project/list.su";
}
@RequestMapping("import.su")
public String projectImport(Model model, MultipartFile file, final String id) throws IOException
{
final File tmpFile = File.createTempFile("autotest", "platform");
try(InputStream input = file.getInputStream();
OutputStream out = new FileOutputStream(tmpFile))
{
IOUtils.copy(input, out);
}
catch (IOException e)
{
e.printStackTrace();
}
new Thread(){
@Override
public void run()
{
try(ZipInputStream zipIn = new ZipInputStream(new FileInputStream(tmpFile)))
{
ZipEntry entry = null;
while((entry = zipIn.getNextEntry()) != null)
{
String entryName = entry.getName();
if(entry.isDirectory() || !entryName.endsWith(".xml"))
{
continue;
}
entryName = entryName.substring(0, entryName.length() - 4);
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
IOUtils.copy(zipIn, byteOut);
SAXReader reader = new SAXReader();
Document doc = reader.read(new ByteArrayInputStream(byteOut.toByteArray()));
Element rootEle = doc.getRootElement();
String rootEleName = rootEle.getName();
if("autotest".equals(rootEleName))
{
PageInfo pageInfo = new PageInfo();
pageInfo.setProjectId(id);
pageInfo.setName(entryName);
pageInfo.setCreateTime(new Date());
pageInfo.setContent(doc.asXML());
try
{
JAXBContext context = JAXBContext.newInstance(Autotest.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Autotest autotest = (Autotest) unmarshaller.unmarshal(
new ByteArrayInputStream(doc.asXML().getBytes()));
JAXBUtils.autotestTransfer(autotest);
ByteArrayOutputStream autoTestByteOut = new ByteArrayOutputStream();
context.createMarshaller().marshal(autotest, autoTestByteOut);
pageInfo.setContent(autoTestByteOut.toString("UTF-8"));
}
catch (JAXBException e)
{
e.printStackTrace();
}
pageInfoMapper.save(pageInfo);
}
else if("dataSources".equals(rootEleName))
{
DataSourceInfo dataSourceInfo = new DataSourceInfo();
dataSourceInfo.setProjectId(id);
dataSourceInfo.setName(entryName);
dataSourceInfo.setCreateTime(new Date());
dataSourceInfo.setContent(doc.asXML());
try
{
JAXBContext context = JAXBContext.newInstance(DataSources.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
DataSources dataSources = (DataSources) unmarshaller.unmarshal(
new ByteArrayInputStream(doc.asXML().getBytes()));
JAXBUtils.dataSourcesTransfer(dataSources);
ByteArrayOutputStream dataSourceByteOut = new ByteArrayOutputStream();
context.createMarshaller().marshal(dataSources, dataSourceByteOut);
dataSourceInfo.setContent(dataSourceByteOut.toString("UTF-8"));
}
catch (JAXBException e)
{
e.printStackTrace();
}
dataSourceInfoMapper.save(dataSourceInfo);
}
else if("suite".equals(rootEleName))
{
SuiteRunnerInfo suiteRunnerInfo = new SuiteRunnerInfo();
suiteRunnerInfo.setProjectId(id);
suiteRunnerInfo.setName(entryName);
suiteRunnerInfo.setCreateTime(new Date());
suiteRunnerInfo.setContent(doc.asXML());
try
{
JAXBContext context = JAXBContext.newInstance(Suite.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Suite suite = (Suite) unmarshaller.unmarshal(
new ByteArrayInputStream(doc.asXML().getBytes()));
JAXBUtils.suiteTransfer(suite);
ByteArrayOutputStream suiteByteOut = new ByteArrayOutputStream();
context.createMarshaller().marshal(suite, suiteByteOut);
suiteRunnerInfo.setContent(suiteByteOut.toString("UTF-8"));
}
catch (JAXBException e)
{
e.printStackTrace();
}
suiteRunnerInfoMapper.save(suiteRunnerInfo);
}
else
{
System.err.println("Unknow type xml, root element name is : " + rootEleName);
}
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (DocumentException e)
{
e.printStackTrace();
}
}
}.start();
return "redirect:/project/edit.su?id=" + id;
}
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException
{
this.applicationContext = applicationContext;
}
}