Search in sources :

Example 1 with CoreModule

use of com.shulie.instrument.simulator.core.CoreModule in project LinkAgent by shulieTech.

the class ModuleHttpServlet method doMethod.

private void doMethod(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
    // 获取请求路径
    final String path = req.getPathInfo();
    // 如果心跳则直接回复,不经过命令
    if (heartbeatPath.equals(path)) {
        doHeartbeat(req, resp);
        return;
    }
    if (shutdownPath.equals(path)) {
        doShutdown(req, resp);
        return;
    }
    /**
     * 如果在销毁中,则忽略除心跳外的所有一切请求
     */
    if (isDestroying) {
        return;
    }
    // 获取模块ID
    final String moduleId = parseModuleId(path);
    if (StringUtils.isBlank(moduleId)) {
        logger.warn("SIMULATOR: path={} is not matched any module.", path);
        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    // 获取模块
    final CoreModule coreModule = coreModuleManager.get(moduleId);
    if (null == coreModule) {
        logger.warn("SIMULATOR: path={} is matched module {}, but not existed.", path, moduleId);
        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    // 匹配对应的方法
    final Method method = matchingModuleMethod(path, moduleId, coreModule.getModule().getClass());
    if (null == method) {
        logger.warn("SIMULATOR: path={} is not matched any method in module {}", path, moduleId);
        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    } else {
        if (logger.isDebugEnabled()) {
            logger.debug("SIMULATOR: path={} is matched method {} in module {}", path, method.getName(), moduleId);
        }
    }
    // 自动释放I/O资源
    final List<Closeable> autoCloseResources = coreModule.append(new ReleaseResource<List<Closeable>>(new ArrayList<Closeable>()) {

        @Override
        public void release() {
            final List<Closeable> list = get();
            if (CollectionUtils.isEmpty(list)) {
                return;
            }
            for (final Closeable closeable : list) {
                if (closeable instanceof Flushable) {
                    try {
                        ((Flushable) closeable).flush();
                    } catch (Exception cause) {
                        logger.warn("SIMULATOR: path={} flush I/O occur error!", path, cause);
                    }
                }
                try {
                    closeable.close();
                } catch (IOException e) {
                }
            }
        }
    });
    // 生成方法调用参数
    final Object[] parameterObjectArray = generateParameterObjectArray(method, req, resp);
    final boolean isAccessible = method.isAccessible();
    final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
    try {
        method.setAccessible(true);
        // 将当前的 ClassLoader置成是模块的 ClassLoader,处理模块执行时的类加载问题
        Thread.currentThread().setContextClassLoader(coreModule.getClassLoaderFactory().getDefaultClassLoader());
        Object value = method.invoke(coreModule.getModule(), parameterObjectArray);
        if (logger.isDebugEnabled()) {
            logger.debug("SIMULATOR: path={} invoke module {} method {} success.", path, moduleId, method.getName());
        }
        // do response之前
        Thread.currentThread().setContextClassLoader(currentClassLoader);
        doResponse(value, req, resp);
    } catch (IllegalAccessException iae) {
        logger.warn("SIMULATOR: path={} invoke module {} method {} occur access denied.", path, moduleId, method.getName(), iae);
        throw new ServletException(iae);
    } catch (InvocationTargetException ite) {
        logger.warn("SIMULATOR: path={} invoke module {} method {} occur error.", path, moduleId, method.getName(), ite.getTargetException());
        final Throwable targetCause = ite.getTargetException();
        if (targetCause instanceof ServletException) {
            throw (ServletException) targetCause;
        }
        if (targetCause instanceof IOException) {
            throw (IOException) targetCause;
        }
        throw new ServletException(targetCause);
    } finally {
        Thread.currentThread().setContextClassLoader(currentClassLoader);
        method.setAccessible(isAccessible);
        coreModule.release(autoCloseResources);
    }
}
Also used : Closeable(java.io.Closeable) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) IOException(java.io.IOException) Flushable(java.io.Flushable) ServletException(javax.servlet.ServletException) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ServletException(javax.servlet.ServletException) ArrayList(java.util.ArrayList) List(java.util.List) CoreModule(com.shulie.instrument.simulator.core.CoreModule)

Example 2 with CoreModule

use of com.shulie.instrument.simulator.core.CoreModule in project LinkAgent by shulieTech.

the class DefaultModuleManager method active.

@Override
public void active(String moduleId) throws ModuleException {
    final CoreModule coreModule = coreModuleManager.getThrowsExceptionIfNull(moduleId);
    coreModuleManager.active(coreModule);
}
Also used : CoreModule(com.shulie.instrument.simulator.core.CoreModule)

Example 3 with CoreModule

use of com.shulie.instrument.simulator.core.CoreModule in project LinkAgent by shulieTech.

the class DefaultCoreModuleManager method unloadInOrder.

/**
 * unload module in order
 *
 * @param coreModule
 * @param modules
 */
private void unloadInOrder(CoreModule coreModule, List<CoreModule> modules) {
    if (!coreModule.isLoaded()) {
        return;
    }
    Iterator<CoreModule> it = modules.iterator();
    while (it.hasNext()) {
        CoreModule module = it.next();
        // ignore if moduleSpec is null or dependencies is null
        if (!module.isLoaded() || !module.getModuleSpec().getDependencies().contains(coreModule.getModuleId())) {
            continue;
        }
        unloadInOrder(module, modules);
    }
    try {
        unload(coreModule, true, false);
    } catch (ModuleException cause) {
        // 强制卸载不可能出错,这里不对外继续抛出任何异常
        logger.warn("SIMULATOR: force unloading module occur error! module={};", coreModule.getModuleId(), cause);
    }
}
Also used : CoreModule(com.shulie.instrument.simulator.core.CoreModule)

Example 4 with CoreModule

use of com.shulie.instrument.simulator.core.CoreModule in project LinkAgent by shulieTech.

the class DefaultCoreModuleManager method softFlush.

/**
 * 软刷新
 * 找出有变动的模块文件,有且仅有改变这些文件所对应的模块
 */
private void softFlush() {
    if (isInfoEnabled) {
        logger.info("SIMULATOR: soft-flushing modules:{}", loadedModuleMap.keySet());
    }
    final File systemModuleLibDir = new File(config.getSystemModuleLibPath());
    try {
        final ArrayList<File> appendJarFiles = new ArrayList<File>();
        final ArrayList<CoreModule> removeCoreModules = new ArrayList<CoreModule>();
        final ArrayList<Long> checksumCRC32s = new ArrayList<Long>();
        // 1. 找出所有有变动的文件(add/remove)
        for (final File jarFile : this.moduleLoader.loadModuleLibs(config.getAppName(), config.getUserModulePaths())) {
            final long checksumCRC32;
            try {
                checksumCRC32 = FileUtils.checksumCRC32(jarFile);
            } catch (IOException cause) {
                logger.warn("SIMULATOR: soft-flushing module: compute module-jar CRC32 occur error. module-jar={};", jarFile, cause);
                continue;
            }
            checksumCRC32s.add(checksumCRC32);
            // 如果CRC32已经在已加载的模块集合中存在,则说明这个文件没有变动,忽略
            if (isChecksumCRC32Existed(checksumCRC32)) {
                if (isInfoEnabled) {
                    logger.info("SIMULATOR: soft-flushing module: module-jar is not changed, ignored. module-jar={};CRC32={};", jarFile, checksumCRC32);
                }
                continue;
            }
            if (isInfoEnabled) {
                logger.info("SIMULATOR: soft-flushing module: module-jar is changed, will be flush. module-jar={};CRC32={};", jarFile, checksumCRC32);
            }
            appendJarFiles.add(jarFile);
        }
        // 2. 找出所有待卸载的已加载用户模块
        for (final CoreModule coreModule : loadedModuleMap.values()) {
            final ClassLoaderFactory classLoaderFactory = coreModule.getClassLoaderFactory();
            // 如果是系统模块目录则跳过
            if (isOptimisticDirectoryContainsFile(systemModuleLibDir, coreModule.getJarFile())) {
                if (isDebugEnabled) {
                    logger.debug("SIMULATOR: soft-flushing module: module-jar is in system-lib, will be ignored. module-jar={};system-lib={};", coreModule.getJarFile(), systemModuleLibDir);
                }
                continue;
            }
            // 如果CRC32已经在这次待加载的集合中,则说明这个文件没有变动,忽略
            if (checksumCRC32s.contains(classLoaderFactory.getChecksumCRC32())) {
                if (isInfoEnabled) {
                    logger.info("SIMULATOR: soft-flushing module: module-jar already loaded, ignored. module-jar={};CRC32={};", coreModule.getJarFile(), classLoaderFactory.getChecksumCRC32());
                }
                continue;
            }
            if (isInfoEnabled) {
                logger.info("SIMULATOR: soft-flushing module: module-jar is changed, module will be reload/remove. module={};module-jar={};", coreModule.getModuleId(), coreModule.getJarFile());
            }
            removeCoreModules.add(coreModule);
        }
        // 3. 删除remove
        for (final CoreModule coreModule : removeCoreModules) {
            unload(coreModule, true);
        }
        // 3. 加载所有用户自定义模块
        List<ModuleSpec> userModuleSpecs = ModuleSpecUtils.loadModuleSpecs(appendJarFiles, false);
        loadModules(userModuleSpecs, "soft-flush");
    } catch (Throwable cause) {
        logger.warn("SIMULATOR: soft-flushing modules: occur error.", cause);
    }
}
Also used : ClassLoaderFactory(com.shulie.instrument.simulator.core.classloader.ClassLoaderFactory) IOException(java.io.IOException) CoreModule(com.shulie.instrument.simulator.core.CoreModule) File(java.io.File)

Example 5 with CoreModule

use of com.shulie.instrument.simulator.core.CoreModule in project LinkAgent by shulieTech.

the class DefaultCoreModuleManager method load.

/**
 * 加载并注册模块
 * <p>1. 如果模块已经存在则返回已经加载过的模块</p>
 * <p>2. 如果模块不存在,则进行常规加载</p>
 * <p>3. 如果模块初始化失败,则抛出异常</p>
 *
 * @param module             模块对象
 * @param moduleJarFile      模块所在JAR文件
 * @param classLoaderFactory 负责加载模块的ClassLoader工厂
 * @throws ModuleException 加载模块失败
 */
private synchronized void load(final ModuleSpec moduleSpec, final ExtensionModule module, final File moduleJarFile, final ClassLoaderFactory classLoaderFactory) throws ModuleException {
    if (loadedModuleMap.containsKey(moduleSpec.getModuleId())) {
        if (isDebugEnabled) {
            logger.debug("SIMULATOR: module already loaded. module={};", moduleSpec);
        }
        return;
    }
    if (isInfoEnabled) {
        logger.info("SIMULATOR: loading module, module={};class={};module-jar={};", moduleSpec, module.getClass().getName(), moduleJarFile);
    }
    // 初始化模块信息
    final CoreModule coreModule = new CoreModule(moduleSpec, moduleJarFile, classLoaderFactory, module, this);
    /**
     * 注入CoreModule需要的资源
     */
    injectCoreModule(coreModule);
    // 注入@Resource资源
    injectResource(coreModule.getModule(), coreModule);
    callAndFireModuleLifeCycle(coreModule, MODULE_LOAD);
    // 设置为已经加载
    coreModule.markLoaded(true);
    // 如果模块标记了加载时自动激活,则需要在加载完成之后激活模块
    markActiveOnLoadIfNecessary(coreModule);
    // 注册到模块列表中
    loadedModuleMap.put(moduleSpec.getModuleId(), coreModule);
    // 通知生命周期,模块加载完成
    callAndFireModuleLifeCycle(coreModule, MODULE_LOAD_COMPLETED);
}
Also used : CoreModule(com.shulie.instrument.simulator.core.CoreModule)

Aggregations

CoreModule (com.shulie.instrument.simulator.core.CoreModule)10 IOException (java.io.IOException)3 Closeable (java.io.Closeable)2 File (java.io.File)2 Flushable (java.io.Flushable)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 Method (java.lang.reflect.Method)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 CommandResponse (com.shulie.instrument.simulator.api.CommandResponse)1 ModuleRuntimeException (com.shulie.instrument.simulator.api.ModuleRuntimeException)1 ClassLoaderFactory (com.shulie.instrument.simulator.core.classloader.ClassLoaderFactory)1 SimulatorException (com.shulie.instrument.simulator.core.exception.SimulatorException)1 ServletException (javax.servlet.ServletException)1