| 1 |  |   | 
  | 2 |  |   | 
  | 3 |  |   | 
  | 4 |  |   | 
  | 5 |  |   | 
  | 6 |  |   | 
  | 7 |  |   | 
  | 8 |  |   | 
  | 9 |  |   | 
  | 10 |  |   | 
  | 11 |  |   | 
  | 12 |  |   | 
  | 13 |  |   | 
  | 14 |  |   | 
  | 15 |  |   | 
  | 16 |  |  package org.kuali.rice.kew.plugin; | 
  | 17 |  |   | 
  | 18 |  |  import org.apache.log4j.Logger; | 
  | 19 |  |  import org.kuali.rice.core.api.config.property.Config; | 
  | 20 |  |  import org.kuali.rice.core.api.config.property.ConfigContext; | 
  | 21 |  |  import org.kuali.rice.core.api.util.ClassLoaderUtils; | 
  | 22 |  |  import org.kuali.rice.kew.plugin.PluginUtils.PluginZipFileFilter; | 
  | 23 |  |   | 
  | 24 |  |  import java.io.File; | 
  | 25 |  |  import java.util.HashSet; | 
  | 26 |  |  import java.util.List; | 
  | 27 |  |  import java.util.Set; | 
  | 28 |  |   | 
  | 29 |  |   | 
  | 30 |  |   | 
  | 31 |  |   | 
  | 32 |  |   | 
  | 33 |  |   | 
  | 34 |  |   | 
  | 35 |  |  public class HotDeployer implements Runnable { | 
  | 36 | 0 |          private static final Logger LOG = Logger.getLogger(HotDeployer.class); | 
  | 37 |  |   | 
  | 38 |  |   | 
  | 39 |  |          private PluginRegistry registry; | 
  | 40 |  |          private File sharedPluginDirectory; | 
  | 41 |  |          private List<String> pluginDirectories; | 
  | 42 |  |   | 
  | 43 | 0 |          public HotDeployer(PluginRegistry registry, File sharedPluginDirectory, List<String> pluginDirectories) { | 
  | 44 | 0 |                  this.registry = registry; | 
  | 45 | 0 |                  this.sharedPluginDirectory = sharedPluginDirectory; | 
  | 46 | 0 |                  this.pluginDirectories = pluginDirectories; | 
  | 47 | 0 |          } | 
  | 48 |  |   | 
  | 49 |  |          public synchronized void run() { | 
  | 50 |  |                  try { | 
  | 51 | 0 |                          LOG.debug("Checking for added and removed plugins..."); | 
  | 52 | 0 |                          Set<PluginEnvironment> removedPlugins = getRemovedPlugins(); | 
  | 53 | 0 |                          for (PluginEnvironment pluginContext : removedPlugins) { | 
  | 54 | 0 |                                  LOG.info("Detected a removed plugin '" + pluginContext.getPluginName() + "', shutting down plugin."); | 
  | 55 |  |                                  try { | 
  | 56 | 0 |                                          pluginContext.unload(); | 
  | 57 | 0 |                                          registry.removePluginEnvironment(pluginContext.getPluginName()); | 
  | 58 | 0 |                                  } catch (Exception e) { | 
  | 59 | 0 |                                          LOG.error("Failed to unload plugin '" + pluginContext.getPluginName() + "'", e); | 
  | 60 | 0 |                                  } | 
  | 61 |  |                          } | 
  | 62 | 0 |                          Set<PluginEnvironment> addedPlugins = getAddedPlugins(); | 
  | 63 | 0 |                          for (PluginEnvironment pluginContext : addedPlugins) { | 
  | 64 |  |                                  try { | 
  | 65 | 0 |                                          LOG.info("Detected a new plugin.  Loading plugin..."); | 
  | 66 | 0 |                                          pluginContext.load(); | 
  | 67 | 0 |                                          LOG.info("...plugin '" + pluginContext.getPluginName() + "' loaded.");                                         | 
  | 68 | 0 |                                  } catch (Exception e) { | 
  | 69 |  |                                       | 
  | 70 | 0 |                                      String pluginName= "<<unknown>>"; | 
  | 71 | 0 |                                      if (pluginContext.getPlugin() != null) { | 
  | 72 | 0 |                                          pluginName = String.valueOf(pluginContext.getPluginName()); | 
  | 73 |  |                                      } | 
  | 74 | 0 |                                          LOG.error("Failed to load plugin '" + pluginName + "'", e); | 
  | 75 |  |                                  } finally { | 
  | 76 |  |                                       | 
  | 77 |  |                                       | 
  | 78 | 0 |                                      registry.addPluginEnvironment(pluginContext); | 
  | 79 | 0 |                                  } | 
  | 80 |  |                          } | 
  | 81 | 0 |                  } catch (Exception e) { | 
  | 82 | 0 |                          LOG.warn("Failed to check for hot deploy.", e); | 
  | 83 | 0 |                  } | 
  | 84 | 0 |          } | 
  | 85 |  |   | 
  | 86 |  |          protected Set<PluginEnvironment> getRemovedPlugins() { | 
  | 87 | 0 |                  Set<PluginEnvironment> removedPlugins = new HashSet<PluginEnvironment>(); | 
  | 88 | 0 |                  for (PluginEnvironment environment : registry.getPluginEnvironments()) { | 
  | 89 | 0 |                          if (environment.getLoader().isRemoved()) { | 
  | 90 | 0 |                                  removedPlugins.add(environment); | 
  | 91 |  |                          } | 
  | 92 |  |                  } | 
  | 93 | 0 |                  return removedPlugins; | 
  | 94 |  |          } | 
  | 95 |  |   | 
  | 96 |  |          protected Set<PluginEnvironment> getAddedPlugins() throws Exception { | 
  | 97 | 0 |                  Set<PluginEnvironment> addedPlugins = new HashSet<PluginEnvironment>(); | 
  | 98 | 0 |                  Set<File> newPluginZipFiles = new HashSet<File>(); | 
  | 99 |  |                   | 
  | 100 |  |                   | 
  | 101 |  |                   | 
  | 102 | 0 |                  for (String pluginDirName : pluginDirectories) { | 
  | 103 | 0 |                          File pluginDir = new File(pluginDirName); | 
  | 104 | 0 |                          if (pluginDir.exists() && pluginDir.isDirectory()) { | 
  | 105 | 0 |                                  File[] pluginDirFiles = pluginDir.listFiles(new PluginZipFileFilter()); | 
  | 106 | 0 |                                  for (File pluginZip : pluginDirFiles) { | 
  | 107 | 0 |                                          int indexOf = pluginZip.getName().lastIndexOf(".zip"); | 
  | 108 | 0 |                                          String pluginName = pluginZip.getName().substring(0, indexOf); | 
  | 109 |  |                                           | 
  | 110 | 0 |                                          List<PluginEnvironment> currentEnvironments = registry.getPluginEnvironments(); | 
  | 111 | 0 |                                          boolean pluginExists = false; | 
  | 112 | 0 |                                          for (PluginEnvironment environment : currentEnvironments) { | 
  | 113 | 0 |                                                  if (environment.getPluginName().equals(pluginName)) { | 
  | 114 | 0 |                                                          pluginExists = true; | 
  | 115 | 0 |                                                          break; | 
  | 116 |  |                                                  } | 
  | 117 |  |                                          } | 
  | 118 | 0 |                                          if (!pluginExists) { | 
  | 119 |  |                                                   | 
  | 120 | 0 |                                                  long lastModified1 = pluginZip.lastModified(); | 
  | 121 | 0 |                                                  Thread.sleep(100); | 
  | 122 | 0 |                                                  long lastModified2 = pluginZip.lastModified(); | 
  | 123 | 0 |                                                  if (lastModified1 == lastModified2) { | 
  | 124 | 0 |                                                          newPluginZipFiles.add(pluginZip); | 
  | 125 |  |                                                  } else { | 
  | 126 | 0 |                                                          LOG.warn("Detected that the plugin zip is still being modified, holding off on hot deploy: " + pluginZip.getAbsolutePath()); | 
  | 127 |  |                                                  } | 
  | 128 |  |                                          } | 
  | 129 |  |                                  } | 
  | 130 |  |                          } | 
  | 131 | 0 |                  } | 
  | 132 |  |   | 
  | 133 | 0 |                  ClassLoader parentClassLoader = ClassLoaderUtils.getDefaultClassLoader(); | 
  | 134 | 0 |                  Config parentConfig = ConfigContext.getCurrentContextConfig(); | 
  | 135 | 0 |                  for (File newPluginZipFile : newPluginZipFiles) { | 
  | 136 | 0 |                          PluginLoader loader = new ZipFilePluginLoader(newPluginZipFile, sharedPluginDirectory, parentClassLoader, parentConfig); | 
  | 137 | 0 |                          PluginEnvironment environment = new PluginEnvironment(loader, registry); | 
  | 138 | 0 |                          addedPlugins.add(environment); | 
  | 139 | 0 |                  } | 
  | 140 | 0 |                  return addedPlugins; | 
  | 141 |  |          } | 
  | 142 |  |   | 
  | 143 |  |  } |