zhourui 5 лет назад
Родитель
Сommit
bbf5278f78

+ 95 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/ClassLoaderTools.java

@@ -0,0 +1,95 @@
+package com.x.base.core.project.tools;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.x.base.core.project.config.Config;
+
+public class ClassLoaderTools {
+
+	private ClassLoaderTools() {
+		// nothing
+	}
+
+	private static final String CFG = "manifest.cfg";
+	private static final String GIT = ".gitignore";
+	private static final String JAR = ".jar";
+	private static final String ZIP = ".zip";
+
+	public static URLClassLoader urlClassLoader(boolean systemParent, boolean ext, boolean store, boolean custom,
+			boolean dynamic, Path... paths) throws Exception {
+		return urlClassLoader(systemParent, ext, store, custom, dynamic, ListTools.toList(paths));
+	}
+
+	public static URLClassLoader urlClassLoader(boolean systemParent, boolean ext, boolean store, boolean custom,
+			boolean dynamic, List<Path> paths) throws Exception {
+		Set<Path> set = new HashSet<>();
+		if (ext) {
+			set.addAll(dirCfg(Config.dir_commons_ext().toPath()));
+		}
+		if (store) {
+			set.addAll(dirCfg(Config.dir_store_jars().toPath()));
+		}
+		if (custom) {
+			set.addAll(dir(Config.dir_custom_jars().toPath()));
+		}
+		if (dynamic) {
+			set.addAll(dir(Config.dir_dynamic_jars().toPath()));
+		}
+		set.addAll(paths);
+		if (systemParent) {
+			return URLClassLoader.newInstance(toURL(set), ClassLoader.getSystemClassLoader());
+		} else {
+			return URLClassLoader.newInstance(toURL(set));
+		}
+	}
+
+	private static URL[] toURL(Set<Path> set) throws MalformedURLException {
+		URL[] urls = new URL[set.size()];
+		int idx = 0;
+		for (Path p : set) {
+			urls[idx++] = p.toUri().toURL();
+		}
+		return urls;
+	}
+
+	private static List<Path> dirCfg(Path dir) throws IOException {
+		List<Path> paths = new ArrayList<>();
+		Path cfg = dir.resolve(CFG);
+		if (Files.exists(dir) && Files.isDirectory(dir) && Files.exists(cfg) && Files.isRegularFile(cfg)) {
+			List<String> names = Files.readAllLines(cfg);
+			try (Stream<Path> stream = Files.list(dir)) {
+				stream.filter(o -> !(o.getFileName().toString().equalsIgnoreCase(CFG)
+						|| o.getFileName().toString().equalsIgnoreCase(GIT))).forEach(o -> {
+							if (names.remove(o.getFileName().toString())) {
+								paths.add(o);
+							}
+						});
+			}
+		}
+		return paths;
+	}
+
+	private static List<Path> dir(Path dir) throws IOException {
+		List<Path> paths = new ArrayList<>();
+		if (Files.exists(dir) && Files.isDirectory(dir)) {
+			try (Stream<Path> stream = Files.list(dir)) {
+				stream.filter(o -> StringUtils.endsWithAny(StringUtils.lowerCase(o.getFileName().toString()), JAR, ZIP))
+						.forEach(paths::add);
+			}
+		}
+		return paths;
+	}
+
+}

+ 116 - 0
o2server/x_console/src/main/java/com/x/server/console/InstrumentationAgent.java

@@ -0,0 +1,116 @@
+package com.x.server.console;
+
+import java.io.IOException;
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.stream.Stream;
+
+public class InstrumentationAgent {
+
+	private static Instrumentation INST;
+
+	private static final String CFG = "manifest.cfg";
+	private static final String GIT = ".gitignore";
+
+	public static void agentmain(String args, Instrumentation inst) {
+		INST = inst;
+		try {
+			Path base = getBasePath();
+			if (Files.exists(base.resolve("custom/jars"))) {
+				load(base, "custom/jars");
+			}
+			if (Files.exists(base.resolve("dynamic/jars"))) {
+				load(base, "dynamic/jars");
+			}
+			load(base, "store/jars");
+			load(base, "commons/ext");
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	public static void premain(String args, Instrumentation inst) {
+		INST = inst;
+		try {
+			Path base = getBasePath();
+			if (Files.exists(base.resolve("custom/jars"))) {
+				load(base, "custom/jars");
+			}
+			if (Files.exists(base.resolve("dynamic/jars"))) {
+				load(base, "dynamic/jars");
+			}
+			load(base, "store/jars");
+			load(base, "commons/ext");
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	private static void load(Path base, String sub) throws Exception {
+		Path dir = base.resolve(sub);
+		Path cfg = dir.resolve(CFG);
+		if (Files.exists(dir) && Files.isDirectory(dir) && Files.exists(cfg) && Files.isRegularFile(cfg)) {
+			List<String> names = Files.readAllLines(cfg);
+			if (names.isEmpty()) {
+				throw new Exception(String.format("%s manifest is empty.", sub));
+			}
+			try (Stream<Path> stream = Files.list(dir)) {
+				stream.filter(o -> !(o.getFileName().toString().equalsIgnoreCase(CFG)
+						|| o.getFileName().toString().equalsIgnoreCase(GIT))).forEach(o -> {
+							try {
+								if (names.remove(o.getFileName().toString())) {
+									// addURLToClassPath(o);
+									System.out.println("load jar:" + o.toString());
+									INST.appendToSystemClassLoaderSearch(new JarFile(o.toString()));
+								} else {
+									Files.delete(o);
+									System.out.printf("delete unnecessary file from %s: %s.", sub,
+											o.getFileName().toString());
+								}
+							} catch (IOException e) {
+								e.printStackTrace();
+							}
+						});
+			}
+			for (String name : names) {
+				System.out.printf("can not load jar from %s: %s", sub, name);
+			}
+		} else {
+			throw new Exception(String.format("invalid directory: %s", sub));
+		}
+	}
+
+	private static Path getBasePath() throws Exception {
+		Path path = Paths.get(InstrumentationAgent.class.getProtectionDomain().getCodeSource().getLocation().toURI());
+		Path version = path.resolveSibling("version.o2");
+		if (Files.exists(version) && Files.isRegularFile(version)) {
+			return version.getParent();
+		}
+		throw new Exception("can not define o2server base directory.");
+	}
+
+	private static void addURLToClassPath(Path jarPath) {
+		ClassLoader classLoader = ClassLoader.getSystemClassLoader();
+		try {
+			if (classLoader instanceof URLClassLoader) {
+				Method method = classLoader.getClass().getDeclaredMethod("addURL", URL.class);
+				method.setAccessible(true);
+				method.invoke(classLoader, jarPath.toUri().toURL());
+			} else {
+				Method method = classLoader.getClass().getDeclaredMethod("appendToClassPathForInstrumentation",
+						String.class);
+				method.setAccessible(true);
+				method.invoke(classLoader, jarPath.toAbsolutePath().toString());
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+}

+ 22 - 4
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/form/FormAction.java

@@ -45,7 +45,6 @@ public class FormAction extends StandardJaxrsAction {
 			logger.error(e, effectivePerson, request, null);
 			logger.error(e, effectivePerson, request, null);
 			result.error(e);
 			result.error(e);
 		}
 		}
-		/* 修改过的方法 */
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 	}
 
 
@@ -65,7 +64,6 @@ public class FormAction extends StandardJaxrsAction {
 			logger.error(e, effectivePerson, request, null);
 			logger.error(e, effectivePerson, request, null);
 			result.error(e);
 			result.error(e);
 		}
 		}
-		/* 修改过的方法 */
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 	}
 
 
@@ -129,8 +127,8 @@ public class FormAction extends StandardJaxrsAction {
 	@Path("{flag}/application/{applicationFlag}/mobile")
 	@Path("{flag}/application/{applicationFlag}/mobile")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	@Consumes(MediaType.APPLICATION_JSON)
-	public void getWithApplicationMobile(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
-			@JaxrsParameterDescribe("表单标识") @PathParam("flag") String flag,
+	public void getWithApplicationMobile(@Suspended final AsyncResponse asyncResponse,
+			@Context HttpServletRequest request, @JaxrsParameterDescribe("表单标识") @PathParam("flag") String flag,
 			@JaxrsParameterDescribe("应用标识") @PathParam("applicationFlag") String applicationFlag) {
 			@JaxrsParameterDescribe("应用标识") @PathParam("applicationFlag") String applicationFlag) {
 		ActionResult<ActionGetWithApplicationMobile.Wo> result = new ActionResult<>();
 		ActionResult<ActionGetWithApplicationMobile.Wo> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
 		EffectivePerson effectivePerson = this.effectivePerson(request);
@@ -142,4 +140,24 @@ public class FormAction extends StandardJaxrsAction {
 		}
 		}
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 	}
+
+	@JaxrsMethodDescribe(value = "V2根据工作或完成工作标识获取表单,合并关联表单和关联脚本输出.", action = V2GetWithWorkOrWorkCompleted.class)
+	@GET
+	@Path("v2/workorworkcompleted/{workOrWorkCompleted}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void V2GetWithWorkOrWorkCompleted(@Suspended final AsyncResponse asyncResponse,
+			@Context HttpServletRequest request,
+			@JaxrsParameterDescribe("工作或完成工作标识") @PathParam("workOrWorkCompleted") String workOrWorkCompleted) {
+		ActionResult<V2GetWithWorkOrWorkCompleted.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new V2GetWithWorkOrWorkCompleted().execute(effectivePerson, workOrWorkCompleted);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
 }
 }

+ 12 - 8
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/form/V2GetWithWorkOrWorkCompleted.java

@@ -2,10 +2,15 @@ package com.x.processplatform.assemble.surface.jaxrs.form;
 
 
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
 
 
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
-import com.x.base.core.project.cache.ApplicationCache;
+import com.x.base.core.project.cache.Cache.CacheCategory;
+import com.x.base.core.project.cache.Cache.CacheKey;
+import com.x.base.core.project.cache.CacheManager;
 import com.x.base.core.project.exception.ExceptionAccessDenied;
 import com.x.base.core.project.exception.ExceptionAccessDenied;
 import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.gson.GsonPropertyObject;
 import com.x.base.core.project.gson.GsonPropertyObject;
@@ -21,8 +26,6 @@ import com.x.processplatform.core.entity.element.Activity;
 import com.x.processplatform.core.entity.element.Form;
 import com.x.processplatform.core.entity.element.Form;
 import com.x.processplatform.core.entity.element.Script;
 import com.x.processplatform.core.entity.element.Script;
 
 
-import org.apache.commons.lang3.StringUtils;
-
 import net.sf.ehcache.Element;
 import net.sf.ehcache.Element;
 
 
 class V2GetWithWorkOrWorkCompleted extends BaseAction {
 class V2GetWithWorkOrWorkCompleted extends BaseAction {
@@ -38,10 +41,11 @@ class V2GetWithWorkOrWorkCompleted extends BaseAction {
 				throw new ExceptionAccessDenied(effectivePerson);
 				throw new ExceptionAccessDenied(effectivePerson);
 			}
 			}
 			Wo wo = null;
 			Wo wo = null;
-			String cacheKey = ApplicationCache.concreteCacheKey(this.getClass(), workOrWorkCompleted);
-			Element element = CACHE.get(cacheKey);
-			if (null != element && null != element.getObjectValue()) {
-				wo = (Wo) element.getObjectValue();
+			CacheCategory cacheCategory = new CacheCategory(Form.class, Script.class);
+			CacheKey cacheKey = new CacheKey(this.getClass(), workOrWorkCompleted);
+			Optional<?> optional = CacheManager.get(cacheCategory, cacheKey);
+			if (optional.isPresent()) {
+				wo = (Wo) optional.get();
 			} else {
 			} else {
 				Work work = emc.find(workOrWorkCompleted, Work.class);
 				Work work = emc.find(workOrWorkCompleted, Work.class);
 				if (null != work) {
 				if (null != work) {
@@ -49,7 +53,7 @@ class V2GetWithWorkOrWorkCompleted extends BaseAction {
 				} else {
 				} else {
 					wo = this.workCompleted(business, emc.flag(workOrWorkCompleted, WorkCompleted.class));
 					wo = this.workCompleted(business, emc.flag(workOrWorkCompleted, WorkCompleted.class));
 				}
 				}
-				CACHE.put(new Element(cacheKey, wo));
+				CacheManager.put(cacheCategory, cacheKey, wo);
 				result.setData(wo);
 				result.setData(wo);
 			}
 			}
 			return result;
 			return result;