// Copyright (C) 2013 The Android Open Source Project
//
// 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.googlesource.gerrit.plugins.github.velocity;

import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.mail.VelocityRuntimeProvider.Slf4jLogChute;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;

import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.RuntimeInstance;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.apache.velocity.runtime.resource.loader.JarResourceLoader;

import java.util.Properties;

@Singleton
public class PluginVelocityRuntimeProvider implements Provider<RuntimeInstance> {
  private static final String VELOCITY_FILE_RESOURCE_LOADER_PATH =
      "file.resource.loader.path";
  private static final String VELOCITY_FILE_RESOURCE_LOADER_CLASS =
      "file.resource.loader.class";
  private static final String VELOCITY_CLASS_RESOURCE_LOADER_CLASS =
      "class.resource.loader.class";
  private static final String VELOCITY_JAR_RESOURCE_LOADER_CLASS =
      "jar.resource.loader.class";
  private static final String VELOCITY_JAR_RESOURCE_LOADER_PATH =
      "jar.resource.loader.path";
  private static final String VELOCITY_RESOURCE_LOADER = "resource.loader";
  private final SitePaths site;
  private String pluginName;

  @Inject
  PluginVelocityRuntimeProvider(SitePaths site, @PluginName String pluginName) {
    this.site = site;
    this.pluginName = pluginName;
  }

  @Override
  public RuntimeInstance get() {
    String pkg = "org.apache.velocity.runtime.resource.loader";

    Properties p = new Properties();
    p.setProperty(RuntimeConstants.VM_PERM_INLINE_LOCAL, "true");
    p.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
        Slf4jLogChute.class.getName());
    p.setProperty(RuntimeConstants.RUNTIME_REFERENCES_STRICT, "true");
    p.setProperty("runtime.log.logsystem.log4j.category", "velocity");

    p.setProperty(VELOCITY_RESOURCE_LOADER, "file, class, jar");
    p.setProperty(VELOCITY_FILE_RESOURCE_LOADER_CLASS, pkg
        + ".FileResourceLoader");
    p.setProperty(VELOCITY_FILE_RESOURCE_LOADER_PATH,
        site.static_dir.getParent().toAbsolutePath().toString());
    p.setProperty(VELOCITY_CLASS_RESOURCE_LOADER_CLASS,
        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());

    RuntimeInstance ri = new RuntimeInstance();
    try {
      ri.init(p);
    } catch (Exception err) {
      throw new ProvisionException("Cannot configure Velocity templates", err);
    }
    return ri;
  }
}

@@ -1247,16 +1247,69 @@
 oader;%0A%0A
+import java.net.URL;%0Aimport java.net.URLClassLoader;%0A
 import j
@@ -3226,114 +3226,23 @@
 TH, 
-%22jar:file:%22%0A        + site.plugins_dir.resolve(pluginName + %22.jar%22).toAbsolutePath()%0A            .toString
+detectPluginJar
 ());
@@ -3435,16 +3435,16 @@
 ;%0A    %7D%0A
-
     retu
@@ -3453,11 +3453,816 @@
  ri;%0A  %7D
+%0A%0A  private String detectPluginJar() %7B%0A    ClassLoader myClassLoader = this.getClass().getClassLoader();%0A    if (!URLClassLoader.class.isAssignableFrom(myClassLoader.getClass())) %7B%0A      throw new IllegalStateException(pluginName%0A          + %22 plugin can be loaded only from a Jar file%22);%0A    %7D%0A%0A    @SuppressWarnings(%22resource%22)%0A    URLClassLoader jarClassLoader = (URLClassLoader) myClassLoader;%0A    URL%5B%5D jarUrls = jarClassLoader.getURLs();%0A    for (URL url : jarUrls) %7B%0A      if (url.getProtocol().equals(%22file%22) && url.getPath().endsWith(%22.jar%22)) %7B%0A        return %22jar:%22 + url.toString();%0A      %7D%0A    %7D%0A%0A    throw new IllegalStateException(%22Cannot find any Jar file in %22 + pluginName%0A        + %22 plugin class loader URLs %22 + jarUrls%0A        + %22: unable to initialize Velocity resource loading.%22);%0A  %7D
 %0A%7D%0A

Allow plugin reload at runtime