|
@@ -0,0 +1,238 @@
|
|
|
+package com.usoftchina.uas.plugin;
|
|
|
+
|
|
|
+import com.usoftchina.uas.plugin.json.JsonPluginDescriptorFinder;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+
|
|
|
+import java.net.URL;
|
|
|
+import java.nio.file.Path;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+
|
|
|
+ * @author yingp
|
|
|
+ * @date 2018/7/31
|
|
|
+ */
|
|
|
+public abstract class AbstractPluginManager implements PluginManager {
|
|
|
+
|
|
|
+ protected static final Logger log = LoggerFactory.getLogger(AbstractPluginManager.class);
|
|
|
+
|
|
|
+ private PluginRepository pluginRepository;
|
|
|
+
|
|
|
+ private PluginFactory pluginFactory;
|
|
|
+
|
|
|
+ private PluginDescriptorFinder pluginDescriptorFinder;
|
|
|
+
|
|
|
+ private Map<String, PluginRunner> runners;
|
|
|
+
|
|
|
+ private List<PluginStateListener> pluginStateListeners;
|
|
|
+
|
|
|
+ public AbstractPluginManager(Path pluginInstallPath, PluginFactory pluginFactory) {
|
|
|
+ this.pluginRepository = new DefaultPluginRepository(pluginInstallPath.toAbsolutePath());
|
|
|
+ this.pluginFactory = pluginFactory;
|
|
|
+ this.pluginDescriptorFinder = new JsonPluginDescriptorFinder();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized void addPluginStateListener(PluginStateListener listener) {
|
|
|
+ if (null == pluginStateListeners) {
|
|
|
+ pluginStateListeners = new ArrayList<>();
|
|
|
+ }
|
|
|
+ pluginStateListeners.add(listener);
|
|
|
+ }
|
|
|
+
|
|
|
+ private synchronized void changePluginState(PluginInstance instance, PluginState newState, boolean fireEvent) {
|
|
|
+ PluginState oldState = instance.getPluginState();
|
|
|
+ instance.setPluginState(newState);
|
|
|
+
|
|
|
+ if (fireEvent && null != pluginStateListeners) {
|
|
|
+ PluginStateEvent event = new PluginStateEvent(this, this, instance, oldState);
|
|
|
+ pluginStateListeners.forEach(listener -> listener.pluginStateChanged(event));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<PluginInstance> getPlugins() {
|
|
|
+ if (null != runners) {
|
|
|
+ return runners.entrySet().stream().map(entry -> entry.getValue().getPluginInstance())
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public PluginInstance getPlugin(String name) {
|
|
|
+ if (runners.containsKey(name)) {
|
|
|
+ return runners.get(name).getPluginInstance();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void startPlugin(PluginDescriptor descriptor) throws PluginException {
|
|
|
+ try {
|
|
|
+ PluginRunner runner = loadPlugin(descriptor);
|
|
|
+ if (null != runner) {
|
|
|
+ if (descriptor.isEnabled()) {
|
|
|
+ runner.start();
|
|
|
+ log.info("Plugin {} started", descriptor.getName());
|
|
|
+ changePluginState(runner.getPluginInstance(), PluginState.STARTED, false);
|
|
|
+ } else {
|
|
|
+ log.info("Plugin {} disabled", descriptor.getName());
|
|
|
+ changePluginState(runner.getPluginInstance(), PluginState.DISABLED, false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(descriptor.getName() + " start error", e);
|
|
|
+ throw new PluginException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void startPlugins() throws PluginException {
|
|
|
+ List<PluginDescriptor> descriptors = pluginRepository.listPlugins();
|
|
|
+ if (!CollectionUtils.isEmpty(descriptors)) {
|
|
|
+ runners = new ConcurrentHashMap<>(descriptors.size());
|
|
|
+ for (PluginDescriptor descriptor : descriptors) {
|
|
|
+ startPlugin(descriptor);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private PluginRunner loadPlugin(PluginDescriptor descriptor) throws Exception {
|
|
|
+ ClassLoader pluginClassLoader = new PluginClassLoader(new URL(descriptor.getUrl()), getClass().getClassLoader());
|
|
|
+ PluginInstance instance = new PluginInstance(this, descriptor, pluginClassLoader);
|
|
|
+ PluginRunner runner = pluginFactory.create(instance);
|
|
|
+ if (null != runner) {
|
|
|
+ if (null == runners) {
|
|
|
+ runners = new ConcurrentHashMap<>(1);
|
|
|
+ }
|
|
|
+ runners.put(descriptor.getName(), runner);
|
|
|
+ }
|
|
|
+ return runner;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void enablePlugin(String name) throws PluginException {
|
|
|
+ if (null != runners && runners.containsKey(name)) {
|
|
|
+ PluginRunner runner = runners.get(name);
|
|
|
+ if (PluginState.DISABLED == runner.getPluginInstance().getPluginState()) {
|
|
|
+ try {
|
|
|
+ runner.start();
|
|
|
+ log.info("Plugin {} started", name);
|
|
|
+ changePluginState(runner.getPluginInstance(), PluginState.STARTED, true);
|
|
|
+
|
|
|
+ pluginRepository.enablePlugin(runner.getPluginInstance().getPluginDescriptor());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(name + " start error", e);
|
|
|
+ throw new PluginException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void stopPlugin(PluginRunner runner) throws PluginException {
|
|
|
+ PluginDescriptor descriptor = runner.getPluginInstance().getPluginDescriptor();
|
|
|
+ try {
|
|
|
+ runner.stop();
|
|
|
+ log.info("Plugin {} stopped", descriptor.getName());
|
|
|
+ changePluginState(runner.getPluginInstance(), PluginState.STOPPED, false);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(descriptor.getName() + " stop error", e);
|
|
|
+ throw new PluginException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void stopPlugins() throws PluginException {
|
|
|
+ if (null != runners) {
|
|
|
+ for (String name : runners.keySet()) {
|
|
|
+ stopPlugin(runners.get(name));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void disablePlugin(String name) throws PluginException {
|
|
|
+ if (null != runners && runners.containsKey(name)) {
|
|
|
+ PluginRunner runner = runners.get(name);
|
|
|
+ if (PluginState.STARTED == runner.getPluginInstance().getPluginState()) {
|
|
|
+ try {
|
|
|
+ runner.stop();
|
|
|
+ log.info("Plugin {} stopped", name);
|
|
|
+ changePluginState(runner.getPluginInstance(), PluginState.DISABLED, true);
|
|
|
+
|
|
|
+ pluginRepository.disablePlugin(runner.getPluginInstance().getPluginDescriptor());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(name + " stop error", e);
|
|
|
+ throw new PluginException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void installPlugin(Path pluginPath) throws PluginException {
|
|
|
+ PluginDescriptor descriptor = pluginDescriptorFinder.find(pluginPath);
|
|
|
+ if (null != descriptor) {
|
|
|
+ installPlugin(pluginPath, descriptor);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void installPlugin(Path pluginPath, PluginDescriptor descriptor) throws PluginException {
|
|
|
+ try {
|
|
|
+ PluginRunner runner = loadPlugin(descriptor);
|
|
|
+ if (null != runner) {
|
|
|
+ pluginRepository.savePluginDescriptor(descriptor);
|
|
|
+ log.info("Plugin {} added", descriptor.getName());
|
|
|
+ runner.start();
|
|
|
+ log.info("Plugin {} started", descriptor.getName());
|
|
|
+ runner.install();
|
|
|
+ log.info("Plugin {} installed", descriptor.getName());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(descriptor.getName() + " start error", e);
|
|
|
+ throw new PluginException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void installPlugin(byte[] fileBytes, String fileName) throws PluginException {
|
|
|
+ Path pluginFile = pluginRepository.savePluginFile(fileBytes, fileName);
|
|
|
+ if (null != pluginFile) {
|
|
|
+ installPlugin(pluginFile);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void installPlugin(byte[] fileBytes, String fileName, PluginDescriptor descriptor) throws PluginException {
|
|
|
+ Path pluginFile = pluginRepository.savePluginFile(fileBytes, fileName);
|
|
|
+ if (null != pluginFile) {
|
|
|
+ installPlugin(pluginFile, descriptor);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void uninstallPlugin(String name) throws PluginException {
|
|
|
+ if (null != runners && runners.containsKey(name)) {
|
|
|
+ PluginRunner runner = runners.get(name);
|
|
|
+ try {
|
|
|
+ runner.uninstall();
|
|
|
+ log.info("Plugin {} uninstalled", name);
|
|
|
+ runner.stop();
|
|
|
+ log.info("Plugin {} stopped ", name);
|
|
|
+ pluginRepository.deletePlugin(runner.getPluginInstance().getPluginDescriptor());
|
|
|
+ log.info("Plugin {} removed ", name);
|
|
|
+ changePluginState(runner.getPluginInstance(), PluginState.REMOVED, true);
|
|
|
+ runners.remove(name);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(name + " uninstall error", e);
|
|
|
+ throw new PluginException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|