All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jianggujin.modulelink.impl.JAbstractModuleManager Maven / Gradle / Ivy

/**
 * Copyright 2018 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.modulelink.impl;

import java.beans.Introspector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.jianggujin.modulelink.JModule;
import com.jianggujin.modulelink.JModuleConfig;
import com.jianggujin.modulelink.JModuleLinkException;
import com.jianggujin.modulelink.JModuleManager;
import com.jianggujin.modulelink.JModuleNotFoundException;
import com.jianggujin.modulelink.util.JAssert;
import com.jianggujin.modulelink.util.JLogFactory;
import com.jianggujin.modulelink.util.JLogFactory.JLog;
import com.jianggujin.modulelink.util.JModuleClassLoader;
import com.jianggujin.modulelink.util.JModuleUtils;

/**
 * 模块管理器抽象实现
 * 
 * @author jianggujin
 *
 */
public abstract class JAbstractModuleManager implements JModuleManager {

   private static final JLog logger = JLogFactory.getLog(JAbstractModuleManager.class);
   private final ConcurrentHashMap parallelLockMap;

   public JAbstractModuleManager() {
      parallelLockMap = new ConcurrentHashMap();
   }

   /**
    * 已注册的所有模块,key:moduleName
    */
   private final Map modules = new ConcurrentHashMap();

   @Override
   public JModule load(JModuleConfig moduleConfig) {
      JAssert.checkNotNull(moduleConfig, "moduleConfig must not be null");
      if (logger.isInfoEnabled()) {
         logger.info("Loading module: " + moduleConfig);
      }
      String moduleName = moduleConfig.getName(), version = moduleConfig.getVersion();
      JModule module = null;
      synchronized (getLock(moduleName)) {
         JRuntimeModule runtimeModule = this.modules.get(moduleName);
         JAssert.checkState(runtimeModule == null || !runtimeModule.hasVersion(version), "module name already exists");
         if (runtimeModule == null) {
            runtimeModule = new JRuntimeModule(moduleName);
            this.modules.put(moduleName, runtimeModule);
         }

         ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
         // 获取模块的ClassLoader
         ClassLoader moduleClassLoader = new JModuleClassLoader(moduleConfig.getModuleUrls(), getParentClassLoader(),
               moduleConfig.getOverridePackages());

         try {
            // 把当前线程的ClassLoader切换成模块的
            Thread.currentThread().setContextClassLoader(moduleClassLoader);
            module = load(moduleConfig, moduleClassLoader);
            if (module == null) {
               throw new NullPointerException("load module is null.");
            }
            runtimeModule.add(module);
         } catch (Throwable e) {
            loadModuleError(moduleClassLoader);
            throw new JModuleLinkException("load module error.", e);
         } finally {
            // 还原当前线程的ClassLoader
            Thread.currentThread().setContextClassLoader(currentClassLoader);
         }
      }

      if (logger.isInfoEnabled()) {
         logger.info("loading module complete:" + moduleConfig);
      }
      return module;
   }

   /**
    * 获得父级ClassLoader
    * 
    * @return
    */
   protected ClassLoader getParentClassLoader() {
      return Thread.currentThread().getContextClassLoader();
   }

   /**
    * 加载模块
    * 
    * @param moduleConfig
    * @param moduleClassLoader
    * @return
    * @throws Exception
    */
   protected abstract JModule load(JModuleConfig moduleConfig, ClassLoader moduleClassLoader) throws Exception;

   /**
    * 加载模块失败,此处可以做一些清理的事情
    * 
    * @param moduleClassLoader
    */
   protected void loadModuleError(ClassLoader moduleClassLoader) {
      Introspector.flushCaches();
      // 从已经使用给定类加载器加载的缓存中移除所有资源包
      ResourceBundle.clearCache(moduleClassLoader);
   }

   @Override
   public void unload(String name) {
      JAssert.checkNotNull(name, "module name must not be null");
      synchronized (getLock(name)) {
         JRuntimeModule runtimeModule = this.modules.remove(name);
         if (runtimeModule == null) {
            throw new JModuleNotFoundException("could not found module with name:" + name);
         }
         Collection list = null;
         if ((list = runtimeModule.clear()) != null) {
            for (JModule module : list) {
               JModuleUtils.destroyQuietly(module);
            }
         }
      }
   }

   @Override
   public void unload(String name, String version) {
      JAssert.checkNotNull(name, "module name must not be null");
      JAssert.checkNotNull(version, "module version must not be null");
      synchronized (getLock(name)) {
         JRuntimeModule runtimeModule = this.modules.get(name);
         if (runtimeModule == null) {
            throw new JModuleNotFoundException("could not found module with name:" + name);
         }
         JModule module = runtimeModule.remove(version);
         if (module == null) {
            throw new JModuleNotFoundException("could not found module with name:" + name + " and version:" + version);
         }
         JModuleUtils.destroyQuietly(module);
         // 移除空数据
         if (runtimeModule.count() == 0) {
            this.modules.remove(name);
         }
      }
   }

   @Override
   public JModule find(String name) {
      JAssert.checkNotNull(name, "module name must not be null");
      synchronized (getLock(name)) {
         JRuntimeModule runtimeModule = this.modules.get(name);
         if (runtimeModule == null)
            throw new JModuleNotFoundException("could not found module with name:" + name);
         JModule module = runtimeModule.getDefaultModule();
         if (module == null)
            throw new JModuleNotFoundException("could not found module with name:" + name);
         return module;
      }
   }

   @Override
   public JModule find(String name, String version) {
      JAssert.checkNotNull(name, "module name must not be null");
      JAssert.checkNotNull(version, "module version must not be null");
      synchronized (getLock(name)) {
         JRuntimeModule runtimeModule = this.modules.get(name);
         if (runtimeModule == null)
            throw new JModuleNotFoundException("could not found module with name:" + name);
         JModule module = runtimeModule.findModule(version);
         if (module == null)
            throw new JModuleNotFoundException("could not found module with name:" + name + " and version:" + version);
         return module;
      }
   }

   @Override
   public void activeVersion(String name, String version) {
      JAssert.checkNotNull(name, "module name must not be null");
      JAssert.checkNotNull(version, "module version must not be null");
      synchronized (getLock(name)) {
         JRuntimeModule runtimeModule = this.modules.get(name);
         if (runtimeModule == null)
            throw new JModuleNotFoundException("could not found module with name:" + name);
         runtimeModule.setDefaultVersion(version);
      }
   }

   @Override
   public String getActiveVersion(String name) {
      JAssert.checkNotNull(name, "module name must not be null");
      synchronized (getLock(name)) {
         JRuntimeModule runtimeModule = this.modules.get(name);
         if (runtimeModule == null)
            throw new JModuleNotFoundException("could not found module with name:" + name);
         return runtimeModule.getDefaultVersion();
      }
   }

   @Override
   public boolean has(String name) {
      if (name == null)
         return false;
      synchronized (getLock(name)) {
         return this.modules.containsKey(name);
      }
   }

   @Override
   public Set getModuleNames() {
      return Collections.unmodifiableSet(this.modules.keySet());
   }
   
   @Override
   public List getModules() {
      List modules = new ArrayList();
      for (JRuntimeModule runtimeModule : this.modules.values()) {
         modules.addAll(runtimeModule.list());
      }
      return Collections.unmodifiableList(modules);
   }

   /**
    * 获得密钥加载锁
    * 
    * @param uid
    * @return
    */
   protected Object getLock(String uid) {
      Object lock = this;
      if (parallelLockMap != null) {
         Object newLock = new Object();
         lock = parallelLockMap.putIfAbsent(uid, newLock);
         if (lock == null) {
            lock = newLock;
         }
      }
      return lock;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy