package com.jivesoftware.os.amza.ui; import com.google.common.collect.Lists; import com.google.template.soy.SoyFileSet; import com.google.template.soy.tofu.SoyTofu; import com.jivesoftware.os.amza.api.AmzaInterner; import com.jivesoftware.os.amza.api.PartitionClientProvider; import com.jivesoftware.os.amza.api.ring.RingHost; import com.jivesoftware.os.amza.service.AmzaService; import com.jivesoftware.os.amza.service.ring.AmzaRingWriter; import com.jivesoftware.os.amza.service.stats.AmzaStats; import com.jivesoftware.os.amza.ui.endpoints.AmzaChatterPluginEndpoints; import com.jivesoftware.os.amza.ui.endpoints.AmzaClusterPluginEndpoints; import com.jivesoftware.os.amza.ui.endpoints.AmzaInspectPluginEndpoints; import com.jivesoftware.os.amza.ui.endpoints.AmzaPartitionsPluginEndpoints; import com.jivesoftware.os.amza.ui.endpoints.AmzaRingsPluginEndpoints; import com.jivesoftware.os.amza.ui.endpoints.AmzaStressPluginEndpoints; import com.jivesoftware.os.amza.ui.endpoints.AmzaUIEndpoints; import com.jivesoftware.os.amza.ui.endpoints.AmzaUIEndpoints.AmzaClusterName; import com.jivesoftware.os.amza.ui.endpoints.AquariumPluginEndpoints; import com.jivesoftware.os.amza.ui.endpoints.CompactionsPluginEndpoints; import com.jivesoftware.os.amza.ui.endpoints.MetricsPluginEndpoints; import com.jivesoftware.os.amza.ui.endpoints.OverviewPluginEndpoints; import com.jivesoftware.os.amza.ui.region.AmzaChatterPluginRegion; import com.jivesoftware.os.amza.ui.region.AmzaClusterPluginRegion; import com.jivesoftware.os.amza.ui.region.AmzaInspectPluginRegion; import com.jivesoftware.os.amza.ui.region.AmzaPartitionsPluginRegion; import com.jivesoftware.os.amza.ui.region.AmzaRingsPluginRegion; import com.jivesoftware.os.amza.ui.region.AmzaStressPluginRegion; import com.jivesoftware.os.amza.ui.region.AquariumPluginRegion; import com.jivesoftware.os.amza.ui.region.CompactionsPluginRegion; import com.jivesoftware.os.amza.ui.region.HeaderRegion; import com.jivesoftware.os.amza.ui.region.HomeRegion; import com.jivesoftware.os.amza.ui.region.ManagePlugin; import com.jivesoftware.os.amza.ui.region.MetricsPluginRegion; import com.jivesoftware.os.amza.ui.region.OverviewRegion; import com.jivesoftware.os.amza.ui.soy.SoyDataUtils; import com.jivesoftware.os.amza.ui.soy.SoyRenderer; import com.jivesoftware.os.amza.ui.soy.SoyService; import com.jivesoftware.os.aquarium.AquariumStats; import com.jivesoftware.os.jive.utils.ordered.id.IdPacker; import com.jivesoftware.os.jive.utils.ordered.id.TimestampProvider; import com.jivesoftware.os.mlogger.core.MetricLogger; import com.jivesoftware.os.mlogger.core.MetricLoggerFactory; import java.net.URL; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.apache.commons.io.IOUtils; /** * @author jonathan.colt */ public class AmzaUIInitializer { private static final MetricLogger LOG = MetricLoggerFactory.getLogger(); public interface InjectionCallback { void addEndpoint(Class clazz); void addInjectable(Class clazz, Object instance); void addSessionAuth(String... paths) throws Exception; } public void initialize(String clusterName, RingHost host, AmzaService amzaService, PartitionClientProvider clientProvider, AquariumStats aquariumStats, AmzaStats amzaStats, TimestampProvider timestampProvider, IdPacker idPacker, AmzaInterner amzaInterner, InjectionCallback injectionCallback) throws Exception { SoyFileSet.Builder soyFileSetBuilder = new SoyFileSet.Builder(); URL dirURL = AmzaUIInitializer.class.getClassLoader().getResource("resources/soy/amza/"); if (dirURL != null && dirURL.getProtocol().equals("jar")) { String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8")); Enumeration<JarEntry> entries = jar.entries(); while (entries.hasMoreElements()) { String name = entries.nextElement().getName(); if (name.endsWith(".soy") && name.startsWith("resources/soy/amza/")) { String soyName = name.substring(name.lastIndexOf('/') + 1); LOG.info("/" + name + " " + soyName); soyFileSetBuilder.add(this.getClass().getResource("/" + name), soyName); } } } else { List<String> soyFiles = IOUtils.readLines(this.getClass().getResourceAsStream("resources/soy/amza/"), StandardCharsets.UTF_8); for (String soyFile : soyFiles) { LOG.info("Adding {}", soyFile); soyFileSetBuilder.add(this.getClass().getResource("/resources/soy/amza/" + soyFile), soyFile); } } SoyFileSet sfs = soyFileSetBuilder.build(); SoyTofu tofu = sfs.compileToTofu(); SoyRenderer renderer = new SoyRenderer(tofu, new SoyDataUtils()); SoyService soyService = new SoyService(renderer, new HeaderRegion("soy.chrome.headerRegion", renderer), new HomeRegion("soy.page.homeRegion", renderer)); ManagePlugin overviewPlugin = new ManagePlugin("dashboard", "Overview", "/amza/ui/overview", OverviewPluginEndpoints.class, new OverviewRegion("soy.page.overviewRegion", renderer)); ManagePlugin inspectPlugin = new ManagePlugin("search", "Inspect", "/amza/ui/inspect", AmzaInspectPluginEndpoints.class, new AmzaInspectPluginRegion("soy.page.amzaInspectPluginRegion", renderer, amzaService, clientProvider)); ManagePlugin metricsPlugin = new ManagePlugin("dashboard", "Metrics", "/amza/ui/metrics", MetricsPluginEndpoints.class, new MetricsPluginRegion("soy.page.metricsPluginRegion", "soy.page.partitionMetricsPluginRegion", "soy.page.amzaStats", "soy.page.visualizePartitionPluginRegion", renderer, amzaService.getRingReader(), amzaService, amzaStats, timestampProvider, idPacker, amzaInterner)); ManagePlugin compactionsPlugin = new ManagePlugin("compressed", "Compactions", "/amza/ui/compactions", CompactionsPluginEndpoints.class, new CompactionsPluginRegion("soy.page.compactionsPluginRegion", renderer, amzaService.getRingReader(), amzaService, amzaStats)); ManagePlugin ringsPlugin = new ManagePlugin("repeat", "Rings", "/amza/ui/rings", AmzaRingsPluginEndpoints.class, new AmzaRingsPluginRegion("soy.page.amzaRingsPluginRegion", renderer, amzaService.getRingWriter(), amzaService.getRingReader())); ManagePlugin partitionsPlugin = new ManagePlugin("map-marker", "Partitions", "/amza/ui/partitions", AmzaPartitionsPluginEndpoints.class, new AmzaPartitionsPluginRegion("soy.page.amzaPartitionsPluginRegion", renderer, amzaService.getRingReader(), amzaService)); ManagePlugin aquariumPlugin = new ManagePlugin("piggy-bank", "Aquarium", "/amza/ui/aquarium", AquariumPluginEndpoints.class, new AquariumPluginRegion("soy.page.aquariumPluginRegion", renderer, amzaService.getRingReader(), amzaService.getAquariumProvider(), amzaService.getLiveliness(), aquariumStats)); ManagePlugin clusterPlugin = new ManagePlugin("leaf", "Cluster", "/amza/ui/cluster", AmzaClusterPluginEndpoints.class, new AmzaClusterPluginRegion("soy.page.amzaClusterPluginRegion", renderer, amzaService.getRingWriter(), amzaService.getRingReader())); ManagePlugin stressPlugin = new ManagePlugin("scale", "Stress", "/amza/ui/stress", AmzaStressPluginEndpoints.class, new AmzaStressPluginRegion("soy.page.amzaStressPluginRegion", renderer, amzaService, clientProvider)); ManagePlugin chatterPlugin = new ManagePlugin("transfer", "Chatter", "/amza/ui/chatter", AmzaChatterPluginEndpoints.class, new AmzaChatterPluginRegion("soy.page.amzaChatterPluginRegion", renderer, amzaService, amzaStats, timestampProvider, idPacker)); List<ManagePlugin> plugins = Lists.newArrayList(overviewPlugin, aquariumPlugin, ringsPlugin, partitionsPlugin, chatterPlugin, metricsPlugin, inspectPlugin, compactionsPlugin, clusterPlugin, stressPlugin); injectionCallback.addInjectable(SoyService.class, soyService); for (ManagePlugin plugin : plugins) { soyService.registerPlugin(plugin); injectionCallback.addEndpoint(plugin.endpointsClass); injectionCallback.addInjectable(plugin.region.getClass(), plugin.region); } injectionCallback.addSessionAuth("/amza/*"); injectionCallback.addEndpoint(AmzaUIEndpoints.class); injectionCallback.addInjectable(AmzaClusterName.class, new AmzaClusterName((clusterName == null) ? "manual" : clusterName)); injectionCallback.addInjectable(AmzaRingWriter.class, amzaService.getRingWriter()); injectionCallback.addInjectable(AmzaStats.class, amzaStats); injectionCallback.addInjectable(AquariumStats.class, aquariumStats); injectionCallback.addInjectable(RingHost.class, host); } }