net.mingsoft.upgrade.action.UpgraderAction Maven / Gradle / Ivy
package net.mingsoft.upgrade.action;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.hutool.core.util.ObjectUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSONArray;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import net.mingsoft.base.entity.ResultJson;
import net.mingsoft.basic.action.BasicAction;
import net.mingsoft.basic.biz.IModelBiz;
import net.mingsoft.basic.biz.IRoleModelBiz;
import net.mingsoft.basic.entity.ModelEntity;
import net.mingsoft.basic.entity.RoleModelEntity;
import net.mingsoft.basic.util.BasicUtil;
import net.mingsoft.basic.util.SpringUtil;
import net.mingsoft.basic.util.StringUtil;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
@Controller("upgrader")
@RequestMapping("/${ms.manager.path}/upgrader")
public class UpgraderAction extends BasicAction {
private String html = "" + "" + "价值源自分享! " + ""
+ "" + ""
+ " " + " "
+ " {message/}
"
+ " " + " " + "" + "";
/**
* 检测是否有新版本更新请求地址
*/
@Value("${ms.mstore.http:http://store.mingsoft.net}")
private String MS_MSTORE_HTTP;
/**
* 检测是否有新版本更新请求地址
*/
@Value("${ms.mstore.host:store.mingsoft.net}")
private String MS_MSTORE_HOST;
@Autowired
private IModelBiz modelBiz;
@Autowired
private IRoleModelBiz roleModelBiz;
// 第一步检测是否有更新,主页显示图标
/**
* 检测是否有新版本,
*
* @param request
*/
@ResponseBody
@RequestMapping(value = "/sync", method = RequestMethod.GET)
public void sync(HttpServletRequest request, HttpServletResponse response) {
String sync = HttpUtil.createPost(MS_MSTORE_HTTP + "/mstore/sync.do").header("ms", "upgrader").execute().body();
this.outJson(response, sync);
}
/** 菜单新增递归方法
* @param modelParent 菜单实体
* @param parentIds 父级ids
* @param mangerRoleId 管理员id
* @param roleModels 角色mode数组
* @param parentId 父级id
*/
private void reModel(ModelEntity modelParent,String parentIds,int mangerRoleId,List roleModels,int parentId){
//判断是否有子集,有则是菜单没有则是功能
modelParent.setModelIsMenu(ObjectUtil.isNotNull(modelParent.getModelChildList())&&modelParent.getModelChildList().size()>0
? Integer.valueOf(1):Integer.valueOf(0));
//设置父级id,0不会存进数据库
modelParent.setModelModelId(parentId);
modelParent.setModelDatetime(new Timestamp(System.currentTimeMillis()));
ModelEntity modelParentEntity = modelBiz.getEntityByModelCode(modelParent.getModelCode());
if (modelParentEntity == null) {
modelBiz.saveEntity(modelParent);
RoleModelEntity roleModel = new RoleModelEntity();
roleModel.setRoleId(mangerRoleId);
roleModel.setModelId(modelParent.getModelId());
roleModels.add(roleModel);
} else {
modelParent.setModelId(modelParentEntity.getModelId());
modelBiz.updateEntity(modelParent);
}
if(ObjectUtil.isNotNull(modelParent.getModelChildList())&&modelParent.getModelChildList().size()>0){
for (ModelEntity modelEntity : modelParent.getModelChildList()) {
reModel(modelEntity,StringUtils.isBlank(parentIds)?modelParent.getModelId()+"":","+modelParent.getModelId(),mangerRoleId,roleModels,modelParent.getModelId());
}
}
}
/**
* 更新软件
* 更具更新列表文件清单请求资源中心服务器,并将请求文件覆盖本地结果 1版本号 2更新描述 3zip下载地址(服务器) 4数据库地址(服务器)
*
* @throws IOException
* @throws ClientProtocolException
*/
@ResponseBody
@RequestMapping("/setup")
public void setup(HttpServletRequest request, HttpServletResponse response)
throws ClientProtocolException, IOException {
String cookie = BasicUtil.getString("cookie");
String id = BasicUtil.getString("id");
// 生成一个httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
String url = MS_MSTORE_HTTP + "/people/mstore/" + id + "/setup.do";
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Host", MS_MSTORE_HOST);
httpPost.setHeader("ms", "upgrader");
httpPost.setHeader("accept", "");
httpPost.setHeader("method", "setup");
httpPost.setHeader("cookie", cookie);
httpPost.setHeader("Content-Type", "text/html;charset=UTF-8");
HttpResponse httpResponse = null;
try {
httpResponse = httpclient.execute(httpPost);
} catch (HttpHostConnectException e) {
e.printStackTrace();
this.outString(response, html.replace("{result/}", "false").replace("{message/}", "链接MStore失败,请回到主界面重试!"));
return;
}
HttpEntity entity = httpResponse.getEntity();
InputStream in = entity.getContent();
String zipfile = "";
String pack = "";
String source = "";
String menuStr = "";
try {
zipfile = httpResponse.getHeaders("fileName")[0].getValue();
pack = httpResponse.getHeaders("pack")[0].getValue();
source = httpResponse.getHeaders("source")[0].getValue();
} catch (ArrayIndexOutOfBoundsException e) {
this.outString(response, html.replace("{result/}", "false").replace("{message/}", "安装包获取失败,请回到主界面重试!"));
return;
}
// 检查当前系统是拥有代码
if (StringUtils.isNotBlank(pack)) {
ResultJson result = new ResultJson();
if (!this.checkModel(pack)) { // 验证包是否存在
if (source.equals("yes")) {
this.outString(response, html.replace("{result/}", result.isResult() + "").replace("{message/}",
"请先使用源码加载模块到系统!" + " "));
} else {
this.outString(response, html.replace("{result/}", result.isResult() + "").replace("{message/}",
"请先加载源码或Maven依赖到系统!"));
}
return;
}
}
if (StringUtil.isBlank(zipfile)) {
return;
}
File classesFile = new File(ClassUtils.getDefaultClassLoader().getResource("").getPath());
// 判断classes文件是否存在,不存在就创建
if (!FileUtil.exist(classesFile)) {
FileUtil.mkdir(classesFile);
}
File zFile = new File(ClassUtils.getDefaultClassLoader().getResource("").getPath()+ zipfile);
try {
FileOutputStream fout = new FileOutputStream(zFile);
int l = -1;
byte[] tmp = new byte[1024];
while ((l = in.read(tmp)) != -1) {
fout.write(tmp, 0, l);
// 注意这里如果用OutputStream.write(buff)的话,图片会失真,大家可以试试
}
fout.flush();
fout.close();
} finally {
// 关闭低层流。
in.close();
}
httpclient.close();
String entryName = "";
List sqlFiles = new ArrayList();
List files = new ArrayList();
List classFiles = new ArrayList();
File menu = null;
// 更新文件
try {
ZipFile zipFile = new ZipFile(zFile);
// 创建本zip文件解压目录
File unzipFile = new File(ClassUtils.getDefaultClassLoader().getResource("").getPath());
// 得到zip文件条目枚举对象
Enumeration extends ZipEntry> zipEnum = zipFile.getEntries();
// 定义输入输出流对象
// 循环读取条目
while (zipEnum.hasMoreElements()) {
// 得到当前条目
ZipEntry entry = (ZipEntry) zipEnum.nextElement();
try {
entryName = new String(entry.getName().getBytes("utf-8"));
if(entryName.indexOf(".DS_Store") > -1) {
continue;
}
//创建包结构
if(entryName.indexOf(File.separator)> -1) {
FileUtil.mkdir(entryName.substring(0,entryName.indexOf(File.separator)));
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 若当前条目为目录则创建
if (entry.isDirectory()) {
new File(unzipFile.getAbsolutePath() + File.separator + entryName).mkdirs();
} else {
// 若当前条目为文件则解压到相应目录
try {
File temp = new File(unzipFile.getAbsolutePath() + File.separator + entryName);
InputStream input = zipFile.getInputStream(entry);
OutputStream output = new FileOutputStream(temp);
// 纪录sql
if (entryName.indexOf(".sql") > 0) {
sqlFiles.add(new File(unzipFile.getAbsolutePath() + File.separator + entryName));
}
if (entryName.indexOf(".class") > 0) {
classFiles.add(new File(unzipFile.getAbsolutePath() + File.separator + entryName));
}
if (entryName.indexOf(".json") > 0) {
menu = new File(unzipFile.getAbsolutePath() + File.separator + entryName);
}
byte[] buffer = new byte[1024 * 8];
int readLen = 0;
while ((readLen = input.read(buffer, 0, 1024 * 8)) != -1) {
output.write(buffer, 0, readLen);
}
output.flush();
output.close();
input.close();
input = null;
output = null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
zipFile.close();
} catch (ZipException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// 执行sql
if (sqlFiles.size() > 0)
{
try {
DruidDataSource dds = (DruidDataSource) SpringUtil.getBean(request.getServletContext(), "dataSource");
ScriptRunner runner = new ScriptRunner(dds.getConnection());
runner.setErrorLogWriter(null);
runner.setLogWriter(null);
FileReader reader = null;
for (File sql : sqlFiles) {
reader = new FileReader(sql);
runner.runScript(reader);
}
runner.closeConnection();
reader.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 读取菜单
if (menu != null)
{
menuStr = FileUtil.readUtf8String(menu);
}
// 组织菜单数据和权限
int mangerRoleId = this.getManagerBySession(request).getManagerRoleID();
List roleModels = new ArrayList<>();
if (StringUtils.isNotBlank(menuStr))
{
List list = JSONArray.parseArray(menuStr, ModelEntity.class);
for (ModelEntity modelParent : list) {
reModel(modelParent,null,mangerRoleId,roleModels,0);
}
// 添加角色权限
if (roleModels.size() > 0) {
roleModelBiz.saveEntity(roleModels);
}
}
// 执行class
if (classFiles.size() > 0) {
ClassLoader cload = new URLClassLoader(
new URL[] { new File(ClassUtils.getDefaultClassLoader().getResource("").getPath()).toURI().toURL() },
Thread.currentThread().getContextClassLoader());
try {
for (File cls : classFiles) {
String className = cls.getPath().substring(cls.getPath().indexOf("classes") + 8,
cls.getPath().length() - 6);
className = className.replace("/", ".").replace("\\", ".");
Class clzss = Class.forName(className, true, cload);
Object obj = clzss.newInstance();
Method[] method = clzss.getDeclaredMethods();
for (Method m : method) {
if (m.toString().indexOf("public ") > -1) {
try {
Object returnObj = m.invoke(obj, new Object[] {});
if (returnObj instanceof ResultJson) {
ResultJson result = (ResultJson) returnObj;
if (!result.isResult()) {
this.outString(response, html.replace("{result/}", "false")
.replace("{message/}", result.getResultMsg()));
return;
}
}
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InstantiationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalAccessException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
// 清理文件
zFile.delete();
for (File f : files){
f.delete();
}
this.outString(response, html.replace("{result/}", "true").replace("{message/}", "安装升级成功!"));
}
private boolean checkModel(String className) {
try {
Class cls = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return false;
}
return true;
}
}