提交 87bdb420 编写于 作者: O o2null

Merge branch 'fix/datacenter0827#274' into 'develop'

1.修改了上传war,启动判断2.修改了在线编辑服务器json文件中文说明3.修改视图导出日期格式问题

See merge request o2oa/o2oa!1467
{"node_127.0.0.1.json":"节点配置",
"appStyle.json":"应用样式配置",
"appStyle.json":"移动端应用样式配置",
"centerServer.json":"中心服务配置",
"clientInit.json":"客户端初始化配置",
"collect.json":"连接到云平台配置",
......@@ -7,8 +7,7 @@
"components.json":"组件配置",
"dingding.json":"钉钉配置",
"dumpRestoreData.json":"导出导入数据配置",
"dumpRestoreStorage.json":"导出导入文件配置",
"exmail.json":"邮件配置",
"exmail.json":"腾讯企业邮邮件配置",
"externalDataSources.json":"数据库配置",
"externalDataSources_db2.json":"db2数据库配置",
"externalDataSources_dm.json":"达梦数据库配置",
......@@ -28,11 +27,10 @@
"person.json":"个人信息配置",
"portal.json":"门户配置",
"processPlatform.json":"流程平台配置",
"pushConfig.json":"极光推送配置",
"qiyeweixin.json":"微信配置",
"query.json":"定时任务配置",
"token.json":"sso配置",
"vfs.json":"附件上传配置",
"qiyeweixin.json":"企业微信配置",
"query.json":"数据中心配置",
"token.json":"令牌,密钥配置",
"vfs.json":"虚拟文件存储配置",
"welink.json":"华为WeLink配置",
"workTime.json":"工作时间配置",
"zhengwuDingding.json":"政务钉钉配置"
......
......@@ -3,16 +3,32 @@ package com.x.server.console;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import javax.servlet.DispatcherType;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import com.x.base.core.project.tools.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
......@@ -22,7 +38,13 @@ import org.eclipse.jetty.quickstart.QuickStartWebApp;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletHolder;
import org.w3c.dom.Document;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.x.base.core.project.x_base_core_project;
import com.x.base.core.project.annotation.Module;
import com.x.base.core.project.annotation.ModuleType;
import com.x.base.core.project.config.Config;
......@@ -31,6 +53,7 @@ import com.x.base.core.project.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import com.x.server.console.action.ActionCreateEncryptKey;
import com.x.server.console.server.Servers;
import com.x.server.console.server.application.ApplicationServerTools;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ClassInfo;
......@@ -44,7 +67,9 @@ public class NodeAgent extends Thread {
}
public static final Pattern redeploy_pattern = Pattern.compile("^redeploy:(.+)$", Pattern.CASE_INSENSITIVE);
public static final Pattern uninstall_pattern = Pattern.compile("^uninstall:(.+)$", Pattern.CASE_INSENSITIVE);
public static final Pattern syncFile_pattern = Pattern.compile("^syncFile:(.+)$", Pattern.CASE_INSENSITIVE);
public static final Pattern upload_resource_pattern = Pattern.compile("^uploadResource:(.+)$",
......@@ -111,6 +136,34 @@ public class NodeAgent extends Thread {
}
matcher = uninstall_pattern.matcher(commandObject.getCommand());
if (matcher.find()) {
String strCommand = commandObject.getCommand();
strCommand = strCommand.trim();
strCommand = strCommand.substring(strCommand.indexOf(":") + 1, strCommand.length());
logger.info("收接到命令:" + strCommand);
String filename = dis.readUTF();
File tempFile = null;
switch (strCommand) {
case "customWar":
tempFile = Config.dir_custom();
break;
case "customJar":
tempFile = Config.dir_custom_jars();
break;
}
logger.info("文件名path:" + tempFile.getAbsolutePath() + File.separator + filename);
File file = new File(tempFile.getAbsolutePath() + File.separator + filename);
filename = filename.substring(0, filename.lastIndexOf("."));
// uninstall
boolean result = this.customWarUninstall(filename);
logger.info("uninstall:" + result);
continue;
}
matcher = redeploy_pattern.matcher(commandObject.getCommand());
if (matcher.find()) {
String strCommand = commandObject.getCommand();
......@@ -489,10 +542,34 @@ public class NodeAgent extends Thread {
}
}
private boolean customWarUninstall(String simpleName) throws Exception {
boolean stop = false;
File war = new File(Config.dir_custom(true), simpleName + ".war");
//File dir = new File(Config.dir_servers_applicationServer_work(), simpleName);
if (Servers.applicationServerIsRunning()) {
GzipHandler gzipHandler = (GzipHandler) Servers.applicationServer.getHandler();
HandlerList hanlderList = (HandlerList) gzipHandler.getHandler();
for (Handler handler : hanlderList.getHandlers()) {
if (QuickStartWebApp.class.isAssignableFrom(handler.getClass())) {
QuickStartWebApp app = (QuickStartWebApp) handler;
if (StringUtils.equals("/" + simpleName, app.getContextPath())) {
app.stop();
app.destroy();
stop = true;
war.delete();
logger.print("{} need stop.", app.getDisplayName());
}
}
}
}
return stop;
}
private void customWar(String simpleName, byte[] bytes,boolean rebootApp) throws Exception {
File war = new File(Config.dir_custom(true), simpleName + ".war");
File dir = new File(Config.dir_servers_applicationServer_work(), simpleName);
FileUtils.writeByteArrayToFile(war, bytes, false);
boolean isStartApplication = false;//第一次上传
if (Servers.applicationServerIsRunning()) {
GzipHandler gzipHandler = (GzipHandler) Servers.applicationServer.getHandler();
HandlerList hanlderList = (HandlerList) gzipHandler.getHandler();
......@@ -501,17 +578,60 @@ public class NodeAgent extends Thread {
QuickStartWebApp app = (QuickStartWebApp) handler;
if (StringUtils.equals("/" + simpleName, app.getContextPath())) {
app.stop();
logger.print("{} need restart because {} redeployed.", app.getDisplayName(), simpleName);
this.modified(bytes, war, dir);
app.start();
isStartApplication = true;
}
}
}
if(rebootApp) {
Servers.stopApplicationServer();
Thread.sleep(3000);
Servers.startApplicationServer();
if(!isStartApplication) {
customWarPublish(simpleName);
}
}
}
}
private void customWarPublish(String name) throws Exception {
File war = new File(Config.dir_custom(), name + ".war");
File dir = new File(Config.dir_servers_applicationServer_work(), name);
if (war.exists()) {
modified(war, dir);
String className = contextParamProject(dir);
URLClassLoader classLoader = new URLClassLoader(
new URL[] { new File(dir, "WEB-INF/classes").toURI().toURL() });
Class<?> cls = classLoader.loadClass(className);
QuickStartWebApp webApp = new QuickStartWebApp();
webApp.setAutoPreconfigure(false);
webApp.setDisplayName(name);
webApp.setContextPath("/" + name);
webApp.setResourceBase(dir.getAbsolutePath());
webApp.setDescriptor(dir + "/WEB-INF/web.xml");
webApp.setExtraClasspath(calculateExtraClassPath(cls));
webApp.getInitParams().put("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false");
webApp.getInitParams().put("org.eclipse.jetty.jsp.precompiled", "true");
webApp.getInitParams().put("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
/* stat */
if (BooleanUtils.isTrue(Config.currentNode().getApplication().getStatEnable())) {
FilterHolder statFilterHolder = new FilterHolder(new WebStatFilter());
statFilterHolder.setInitParameter("exclusions", Config.currentNode().getApplication().getStatExclusions());
webApp.addFilter(statFilterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
ServletHolder statServletHolder = new ServletHolder(StatViewServlet.class);
statServletHolder.setInitParameter("sessionStatEnable", "false");
webApp.addServlet(statServletHolder, "/druid/*");
}
/* stat end */
logger.print("addHandler {} ", webApp.getDisplayName());
GzipHandler gzipHandler = (GzipHandler) Servers.applicationServer.getHandler();
HandlerList hanlderList = (HandlerList) gzipHandler.getHandler();
hanlderList.addHandler(webApp);
webApp.stop();
logger.print("{} need restart because {} redeployed.", webApp.getDisplayName(), name);
webApp.start();
}
}
......@@ -519,6 +639,7 @@ public class NodeAgent extends Thread {
File jar = new File(Config.dir_custom_jars(true), simpleName + ".jar");
FileUtils.writeByteArrayToFile(jar, bytes, false);
List<String> contexts = new ArrayList<>();
boolean isStartApplication = false;
for (String s : Config.dir_custom().list(new WildcardFileFilter("*.war"))) {
contexts.add("/" + FilenameUtils.getBaseName(s));
}
......@@ -530,16 +651,20 @@ public class NodeAgent extends Thread {
QuickStartWebApp app = (QuickStartWebApp) handler;
if (contexts.contains(app.getContextPath()) ) {
app.stop();
logger.print("{} need restart because {} redeployed.", app.getDisplayName(), simpleName);
Thread.sleep(3000);
app.start();
isStartApplication = true;
}
}
}
if(rebootApp) {
if(!isStartApplication) {
Servers.stopApplicationServer();
Thread.sleep(1000);
Servers.startApplicationServer();
}
}
}
}
......@@ -588,7 +713,88 @@ public class NodeAgent extends Thread {
FileUtils.writeStringToFile(lastModified, war.lastModified() + "", DefaultCharset.charset_utf_8, false);
}
}
private static void modified(File war, File dir) throws IOException {
File lastModified = new File(dir, "WEB-INF/lastModified");
if ((!lastModified.exists()) || lastModified.isDirectory() || (war.lastModified() != NumberUtils
.toLong(FileUtils.readFileToString(lastModified, DefaultCharset.charset_utf_8), 0))) {
if (dir.exists()) {
FileUtils.forceDelete(dir);
}
JarTools.unjar(war, "", dir, true);
FileUtils.writeStringToFile(lastModified, war.lastModified() + "", DefaultCharset.charset_utf_8, false);
}
}
private static String contextParamProject(File dir) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder
.parse(new ByteArrayInputStream(FileUtils.readFileToByteArray(new File(dir, "WEB-INF/web.xml"))));
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("web-app/context-param[param-name='project']/param-value");
String str = expr.evaluate(doc, XPathConstants.STRING).toString();
return StringUtils.trim(str);
}
protected static String calculateExtraClassPath(Class<?> cls, Path... paths) throws Exception {
List<String> jars = new ArrayList<>();
jars.addAll(calculateExtraClassPathDefault());
Module module = cls.getAnnotation(Module.class);
for (String str : module.storeJars()) {
File file = new File(Config.dir_store_jars(), str + ".jar");
if (file.exists()) {
jars.add(file.getAbsolutePath());
}
}
for (String str : module.customJars()) {
File file = new File(Config.dir_custom_jars(), str + ".jar");
if (file.exists()) {
jars.add(file.getAbsolutePath());
}
}
for (String str : module.dynamicJars()) {
File file = new File(Config.dir_dynamic_jars(), str + ".jar");
if (file.exists()) {
jars.add(file.getAbsolutePath());
}
}
for (Path path : paths) {
if (Files.exists(path) && Files.isDirectory(path)) {
try (Stream<Path> stream = Files.walk(path, FileVisitOption.FOLLOW_LINKS)) {
stream.filter(Files::isRegularFile)
.filter(p -> p.toAbsolutePath().toString().toLowerCase().endsWith(".jar"))
.forEach(p -> jars.add(p.toAbsolutePath().toString()));
}
}
}
return StringUtils.join(jars, ";");
}
private static List<String> calculateExtraClassPathDefault() throws Exception {
List<String> jars = new ArrayList<>();
IOFileFilter filter = new WildcardFileFilter(x_base_core_project.class.getSimpleName() + "*.jar");
for (File o : FileUtils.listFiles(Config.dir_store_jars(), filter, null)) {
jars.add(o.getAbsolutePath());
}
filter = new WildcardFileFilter("openjpa-*.jar");
filter = FileFilterUtils.or(filter, new WildcardFileFilter("ehcache-*.jar"));
/* 如果不单独导入会导致java.lang.NoClassDefFoundError: org/eclipse/jetty/http/MimeTypes */
filter = FileFilterUtils.or(filter, new WildcardFileFilter("jetty-all-*.jar"));
filter = FileFilterUtils.or(filter, new WildcardFileFilter("quartz-*.jar"));
if (!com.x.server.console.Main.slf4jOtherImplOn) {
filter = FileFilterUtils.or(filter, new WildcardFileFilter("slf4j-simple-*.jar"));
filter = FileFilterUtils.or(filter, new WildcardFileFilter("jul-to-slf4j-*.jar"));
filter = FileFilterUtils.or(filter, new WildcardFileFilter("log4j-*.jar"));
}
/* jersey从AppClassLoader加载 */
for (File o : FileUtils.listFiles(Config.dir_commons_ext(), filter, null)) {
jars.add(o.getAbsolutePath());
}
return jars;
}
public static class CommandObject {
private String command;
......
package com.x.program.center.jaxrs.command;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import com.hankcs.hanlp.corpus.io.IOUtil;
import com.x.base.core.project.annotation.FieldDescribe;
import com.x.base.core.project.config.Config;
import com.x.base.core.project.config.Nodes;
import com.x.base.core.project.gson.GsonPropertyObject;
import com.x.base.core.project.gson.XGsonBuilder;
import com.x.base.core.project.http.ActionResult;
import com.x.base.core.project.http.EffectivePerson;
import com.x.base.core.project.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import com.x.base.core.project.tools.Crypto;
public class ActionUninstall extends BaseAction {
private static Logger logger = LoggerFactory.getLogger(CommandAction.class);
public ActionResult<Wo> execute(HttpServletRequest request, EffectivePerson effectivePerson, String ctl,
String nodeName, String nodePort, String fileName) throws Exception {
ActionResult<Wo> result = new ActionResult<>();
Wo wo = null;
String curServer = request.getLocalAddr();
if(nodeName.equalsIgnoreCase("*")) {
Nodes nodes = Config.nodes();
logger.info("先其他服务器");
for (String node : nodes.keySet()){
//先其他服务器
if(!node.equalsIgnoreCase(curServer)) {
if(nodes.get(node).getApplication().getEnable() || nodes.get(node).getCenter().getEnable()){
logger.info("node="+node);
wo = executeCommand( ctl, node , nodes.get(node).nodeAgentPort(), fileName);
}
}
}
logger.info("后当前服务器");
for(String node : nodes.keySet()) {
//后当前服务器
if(node.equalsIgnoreCase(curServer)) {
if(nodes.get(curServer).getApplication().getEnable() || nodes.get(curServer).getCenter().getEnable()){
logger.info("node="+node);
wo = executeCommand( ctl, node , nodes.get(curServer).nodeAgentPort(), fileName);
}
}
}
}else {
wo = executeCommand( ctl, nodeName , Integer.parseInt(nodePort), fileName);
}
result.setData(wo);
return result;
}
private Wo executeCommand(String ctl, String nodeName, Integer nodePort, String fileName) {
// TODO Auto-generated method stub
Wo wo = new Wo();
wo.setNode(nodeName);
wo.setStatus("success");
try (Socket socket = new Socket(nodeName, nodePort)) {
socket.setKeepAlive(true);
socket.setSoTimeout(5000);
DataOutputStream dos = null;
DataInputStream dis = null;
try {
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
Map<String, Object> commandObject = new HashMap<>();
commandObject.put("command", "uninstall:"+ ctl);
commandObject.put("credential", Crypto.rsaEncrypt("o2@", Config.publicKey()));
dos.writeUTF(XGsonBuilder.toJson(commandObject));
dos.flush();
dos.writeUTF(fileName);
dos.flush();
}finally {
dos.close();
dis.close();
socket.close();
}
} catch (Exception ex) {
wo.setStatus("fail");
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
wo.setTime(df.format(new Date()));
return wo;
}
public static class Wi extends GsonPropertyObject{
private String ctl;
private String nodeName;
private String nodePort;
public String getCtl() {
return ctl;
}
public void setCtl(String ctl) {
this.ctl = ctl;
}
public String getNodeName() {
return nodeName;
}
public void setNodeName(String nodeName) {
this.nodeName = nodeName;
}
public String getNodePort() {
return nodePort;
}
public void setNodePort(String nodePort) {
this.nodePort = nodePort;
}
}
public static class Wo extends GsonPropertyObject {
@FieldDescribe("执行时间")
private String time;
@FieldDescribe("执行结束")
private String status;
@FieldDescribe("执行服务器")
private String node;
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getNode() {
return node;
}
public void setNode(String node) {
this.node = node;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
}
......@@ -94,5 +94,26 @@ public class CommandAction<Wo> extends StandardJaxrsAction {
}
asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
}
@JaxrsMethodDescribe(value = "uninstall customWar 包并删除", action = ActionUninstall.class)
@POST
@Path("uninstall")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
public void uninstall(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
@JaxrsParameterDescribe("命令名称(customWar)") @FormDataParam("ctl") String ctl,
@JaxrsParameterDescribe("服务器地址(*代表多台应用服务器)") @FormDataParam("nodeName") String nodeName,
@JaxrsParameterDescribe("服务端口") @FormDataParam("nodePort") String nodePort,
@JaxrsParameterDescribe("War名称") @FormDataParam(FILENAME_FIELD) String fileName) {
ActionResult<ActionUninstall.Wo> result = new ActionResult<>();
EffectivePerson effectivePerson = this.effectivePerson(request);
try {
result = new ActionUninstall().execute(request , effectivePerson, ctl, nodeName, nodePort, fileName);
} catch (Exception e) {
logger.error(e, effectivePerson, request, null);
result.error(e);
}
asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
}
}
\ No newline at end of file
package com.x.query.assemble.surface.jaxrs.view;
import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
......@@ -183,7 +185,8 @@ abstract class BaseAction extends StandardJaxrsAction {
i = 0;
for (SelectEntry o : plan.selectList) {
c = r.createCell(i);
c.setCellValue(Objects.toString(row.find(o.column)));
//c.setCellValue(Objects.toString(row.find(o.column)));
c.setCellValue(objectToString(row.find(o.column)));
i++;
}
}
......@@ -200,7 +203,26 @@ abstract class BaseAction extends StandardJaxrsAction {
return flag;
}
}
protected String objectToString(Object object) {
String str = "";
if (object instanceof Integer) {
str = object.toString();
}else if (object instanceof Double) {
str = object.toString();
}else if (object instanceof Float) {
str = object.toString();
}else if (object instanceof Boolean) {
str = String.valueOf(object);
} else if (object instanceof Date) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
str= formatter.format(object);
}else {
str = object.toString();
}
return str;
}
protected Runtime runtime(EffectivePerson effectivePerson, Business business, View view,
List<FilterEntry> filterList, Map<String, String> parameter, Integer count, boolean isBundle) throws Exception {
Runtime runtime = new Runtime();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册