Allow plugin reload at runtime

When Gerrit needs to load a plugin, copies the jar file to a temporary
location so that overwrites do not impact the normal class and 
resource loading. This makes the plugin reloadable at runtime.

Until now the GitHub plugin has used instead the original jar for
loading its Velocity resources which made the plugin NOT reloadable.

This change makes the detection of the Jar file where the plugin is 
loaded from discoverable at runtime and the magic happens: GitHub plugin
becomes fully reloadable allowing hot-deploys.

Change-Id: Icd16059de2522d1fcc5c5e6f4e15c06b3d38d699
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityRuntimeProvider.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityRuntimeProvider.java
index da7d67a..e3a6135 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityRuntimeProvider.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/velocity/PluginVelocityRuntimeProvider.java
@@ -26,6 +26,8 @@
 import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
 import org.apache.velocity.runtime.resource.loader.JarResourceLoader;
 
+import java.net.URL;
+import java.net.URLClassLoader;
 import java.util.Properties;
 
 @Singleton
@@ -70,9 +72,7 @@
         ClasspathResourceLoader.class.getName());
     p.setProperty(VELOCITY_JAR_RESOURCE_LOADER_CLASS,
         JarResourceLoader.class.getName());
-    p.setProperty(VELOCITY_JAR_RESOURCE_LOADER_PATH, "jar:file:"
-        + site.plugins_dir.resolve(pluginName + ".jar").toAbsolutePath()
-            .toString());
+    p.setProperty(VELOCITY_JAR_RESOURCE_LOADER_PATH, detectPluginJar());
 
     RuntimeInstance ri = new RuntimeInstance();
     try {
@@ -82,4 +82,25 @@
     }
     return ri;
   }
+
+  private String detectPluginJar() {
+    ClassLoader myClassLoader = this.getClass().getClassLoader();
+    if (!URLClassLoader.class.isAssignableFrom(myClassLoader.getClass())) {
+      throw new IllegalStateException(pluginName
+          + " plugin can be loaded only from a Jar file");
+    }
+
+    @SuppressWarnings("resource")
+    URLClassLoader jarClassLoader = (URLClassLoader) myClassLoader;
+    URL[] jarUrls = jarClassLoader.getURLs();
+    for (URL url : jarUrls) {
+      if (url.getProtocol().equals("file") && url.getPath().endsWith(".jar")) {
+        return "jar:" + url.toString();
+      }
+    }
+
+    throw new IllegalStateException("Cannot find any Jar file in " + pluginName
+        + " plugin class loader URLs " + jarUrls
+        + ": unable to initialize Velocity resource loading.");
+  }
 }