/*
 * Druid - a distributed column store.
 * Copyright (C) 2012, 2013  Metamarkets Group Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package io.druid.server;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.inject.Injector;
import io.druid.initialization.DruidModule;
import io.druid.initialization.Initialization;
import io.druid.server.initialization.ExtensionsConfig;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import java.util.ArrayList;
import java.util.List;

/**
 */
@Path("/{a:status|health}")
public class StatusResource
{
  @GET
  @Produces("application/json")
  public Status doGet()
  {
    return getStatus();
  }

  public static Status getStatus()
  {
    return new Status(
        Initialization.class.getPackage().getImplementationVersion(),
        getExtensionVersions(),
        new Memory(Runtime.getRuntime())
    );
  }

  /**
   * Load the unique extensions and return their implementation-versions
   *
   * @return map of extensions loaded with their respective implementation versions.
   */
  private static List<ModuleVersion> getExtensionVersions()
  {
    final Injector injector = Initialization.makeStartupInjector();
    final ExtensionsConfig config = injector.getInstance(ExtensionsConfig.class);
    final List<DruidModule> druidModules = Initialization.getFromExtensions(config, DruidModule.class);

    List<ModuleVersion> moduleVersions = new ArrayList<>();
    for (DruidModule module : druidModules) {

      String artifact = module.getClass().getPackage().getImplementationTitle();
      String version = module.getClass().getPackage().getImplementationVersion();

      ModuleVersion moduleVersion;
      if (artifact != null) {
        moduleVersion = new ModuleVersion(module.getClass().getCanonicalName(), artifact, version);
      } else {
        moduleVersion = new ModuleVersion(module.getClass().getCanonicalName());
      }

      moduleVersions.add(moduleVersion);
    }
    return moduleVersions;
  }

  public static class Status
  {
    final String version;
    final List<ModuleVersion> modules;
    final Memory memory;

    public Status(
        String version, List<ModuleVersion> modules, Memory memory
    )
    {
      this.version = version;
      this.modules = modules;
      this.memory = memory;
    }

    @JsonProperty
    public String getVersion()
    {
      return version;
    }

    @JsonProperty
    public List<ModuleVersion> getModules()
    {
      return modules;
    }

    @JsonProperty
    public Memory getMemory()
    {
      return memory;
    }

    @Override
    public String toString()
    {
      final String NL = "\n";
      StringBuilder output = new StringBuilder();
      output.append(String.format("Druid version - %s", version)).append(NL).append(NL);

      if (modules.size() > 0) {
        output.append("Registered Druid Modules").append(NL);
      } else {
        output.append("No Druid Modules loaded !");
      }

      for (ModuleVersion moduleVersion : modules) {
        output.append(moduleVersion).append(NL);
      }
      return output.toString();
    }
  }

  public static class ModuleVersion
  {
    final String name;
    final String artifact;
    final String version;

    public ModuleVersion(String name)
    {
      this(name, "", "");
    }

    public ModuleVersion(String name, String artifact, String version)
    {
      this.name = name;
      this.artifact = artifact;
      this.version = version;
    }

    @JsonProperty
    public String getName()
    {
      return name;
    }

    @JsonProperty
    public String getArtifact()
    {
      return artifact;
    }

    @JsonProperty
    public String getVersion()
    {
      return version;
    }

    @Override
    public String toString()
    {
      if (artifact.isEmpty()) {
        return String.format("  - %s ", name);
      } else {
        return String.format("  - %s (%s-%s)", name, artifact, version);
      }
    }
  }

  public static class Memory
  {
    final long maxMemory;
    final long totalMemory;
    final long freeMemory;
    final long usedMemory;

    public Memory(Runtime runtime)
    {
      maxMemory = runtime.maxMemory();
      totalMemory = runtime.totalMemory();
      freeMemory = runtime.freeMemory();
      usedMemory = totalMemory - freeMemory;
    }

    @JsonProperty
    public long getMaxMemory()
    {
      return maxMemory;
    }

    @JsonProperty
    public long getTotalMemory()
    {
      return totalMemory;
    }

    @JsonProperty
    public long getFreeMemory()
    {
      return freeMemory;
    }

    @JsonProperty
    public long getUsedMemory()
    {
      return usedMemory;
    }

  }
}

@@ -905,181 +905,46 @@
 ort 
-com.google.inject.Injector;%0Aimport io.druid.initialization.DruidModule;%0Aimport io.druid.initialization.Initialization;%0Aimport io.druid.server.initialization.ExtensionsConfig
+io.druid.initialization.Initialization
 ;%0A%0Ai
@@ -1023,59 +1023,8 @@
 ces;
-%0Aimport java.util.ArrayList;%0Aimport java.util.List;
 %0A%0A/*
@@ -1319,40 +1319,8 @@
 (),%0A
-        getExtensionVersions(),%0A
     
@@ -1372,1122 +1372,8 @@
  %7D%0A%0A
-  /**%0A   * Load the unique extensions and return their implementation-versions%0A   *%0A   * @return map of extensions loaded with their respective implementation versions.%0A   */%0A  private static List%3CModuleVersion%3E getExtensionVersions()%0A  %7B%0A    final Injector injector = Initialization.makeStartupInjector();%0A    final ExtensionsConfig config = injector.getInstance(ExtensionsConfig.class);%0A    final List%3CDruidModule%3E druidModules = Initialization.getFromExtensions(config, DruidModule.class);%0A%0A    List%3CModuleVersion%3E moduleVersions = new ArrayList%3C%3E();%0A    for (DruidModule module : druidModules) %7B%0A%0A      String artifact = module.getClass().getPackage().getImplementationTitle();%0A      String version = module.getClass().getPackage().getImplementationVersion();%0A%0A      ModuleVersion moduleVersion;%0A      if (artifact != null) %7B%0A        moduleVersion = new ModuleVersion(module.getClass().getCanonicalName(), artifact, version);%0A      %7D else %7B%0A        moduleVersion = new ModuleVersion(module.getClass().getCanonicalName());%0A      %7D%0A%0A      moduleVersions.add(moduleVersion);%0A    %7D%0A    return moduleVersions;%0A  %7D%0A%0A
   pu
@@ -1431,47 +1431,8 @@
 on;%0A
-    final List%3CModuleVersion%3E modules;%0A
     
@@ -1499,37 +1499,8 @@
 ion,
- List%3CModuleVersion%3E modules,
  Mem
@@ -1556,38 +1556,8 @@
 on;%0A
-      this.modules = modules;%0A
     
@@ -1675,105 +1675,8 @@
  %7D%0A%0A
-    @JsonProperty%0A    public List%3CModuleVersion%3E getModules()%0A    %7B%0A      return modules;%0A    %7D%0A%0A
     
@@ -1830,463 +1830,108 @@
 L = 
-%22%5Cn%22;%0A      StringBuilder output = new StringBuilder();%0A      output.append(String.format(%22Druid version - %25s%22, version)).append(NL).append(NL);%0A%0A      if (modules.size() %3E 0) %7B%0A        output.append(%22Registered Druid Modules%22).append(NL);%0A      %7D else %7B%0A        output.append(%22No Druid Modules loaded !%22);%0A      %7D%0A%0A      for (ModuleVersion moduleVersion : modules) %7B%0A        output.append(moduleVersion).append(NL);%0A      %7D%0A      return output.toString()
+System.getProperty(%22line.separator%22);%0A      return String.format(%22Druid version - %25s%22, version) + NL
 ;%0A  

Remove extension versions