Просмотр исходного кода

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

o2wwx 5 лет назад
Родитель
Сommit
06acdf160c

+ 201 - 5
o2server/x_console/src/main/java/com/x/server/console/NodeAgent.java

@@ -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,6 +542,29 @@ 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);
@@ -512,13 +588,52 @@ public class NodeAgent extends Thread {
 			
 			if(rebootApp) {
 				if(!isStartApplication) {
-				  Servers.stopApplicationServer();
-				  Thread.sleep(3000);
-				  Servers.startApplicationServer();
+				  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();
+		}
+	}
 
 	private void customJar(String simpleName, byte[] bytes,boolean rebootApp) throws Exception {
 		File jar = new File(Config.dir_custom_jars(true), simpleName + ".jar");
@@ -598,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;

+ 168 - 0
o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/command/ActionUninstall.java

@@ -0,0 +1,168 @@
+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;
+		}
+	}
+
+
+}
+

+ 21 - 0
o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/command/CommandAction.java

@@ -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));
+	}
 
 }

+ 24 - 2
o2server/x_query_assemble_surface/src/main/java/com/x/query/assemble/surface/jaxrs/view/BaseAction.java

@@ -1,7 +1,9 @@
 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();