/******************************************************************************* * Copyright © 2012-2015 eBay Software Foundation * This program is dual licensed under the MIT and Apache 2.0 licenses. * Please see LICENSE for more information. *******************************************************************************/ package com.ebay.jetstream.application.dataflows; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.PostMethod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.jmx.export.annotation.ManagedResource; import com.ebay.jetstream.config.AbstractNamedBean; import com.ebay.jetstream.config.RootConfiguration; import com.ebay.jetstream.management.Management; import com.ebay.jetstream.util.CommonUtils; import com.ebay.jetstream.xmlser.Hidden; import com.ebay.jetstream.xmlser.XSerializable; /** * Visualizes the Jetstream pipeline using yuml.me * * @author varavindan * */ @ManagedResource(objectName = "Event/DataFlows", description = "data flow visualization") public class VisualDataFlow extends AbstractNamedBean implements XSerializable, InitializingBean { private Map<String, Set<String>> graph; private DefaultListableBeanFactory beanFactory; private static final String yumlUrl = "http://yuml.me/"; private static final String yumlActivityUrl = "http://yuml.me/diagram/scruffy/activity"; private static final int BUF = 512; private final Map<String, URL> graphYuml = new HashMap<String, URL>(); private static Logger logger = LoggerFactory.getLogger(VisualDataFlow.class); public Map<String, URL> getGraphYuml() { return graphYuml; } public VisualDataFlow() { } private URL getYumlPic(String yumlData) { try { if (!graphYuml.containsKey(yumlData)) { HttpClient httpclient = new HttpClient(); PostMethod post = new PostMethod(yumlActivityUrl); List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); post.addParameter(new NameValuePair("dsl_text", yumlData)); httpclient.executeMethod(post); URL url = new URL(yumlUrl + post.getResponseBodyAsString()); graphYuml.put(yumlData, url); return url; } else { return graphYuml.get(yumlData); } } catch (Exception e) { logger.error(" Exception while rendering pipeline ", e); return null; } } public ByteBuffer getAsByteArray(URL url) throws IOException { URLConnection connection = url.openConnection(); InputStream in = connection.getInputStream(); int contentLength = connection.getContentLength(); ByteArrayOutputStream tmpOut; if (contentLength != -1) { tmpOut = new ByteArrayOutputStream(contentLength); } else { tmpOut = new ByteArrayOutputStream(16384); } byte[] buf = new byte[BUF]; while (true) { int len = in.read(buf); if (len == -1) { break; } tmpOut.write(buf, 0, len); } in.close(); tmpOut.close(); byte[] array = tmpOut.toByteArray(); return ByteBuffer.wrap(array); } @Hidden public ByteBuffer getVisual() { try { String yumlData = ""; DataFlows dFlow = (DataFlows) RootConfiguration.get("DataFlows"); Map<String, Set<String>> graph = dFlow.getGraph(); int edges = graph.size(); for (Entry<String, Set<String>> edge : graph.entrySet()) { if (!CommonUtils.isEmpty(edge.getValue())) { for (String v : edge.getValue()) { yumlData += "(" + edge.getKey() + ")" + "->" + "(" + v + ")"; yumlData += ","; } } else { yumlData += "(" + edge.getKey() + ")"; yumlData += ","; } } yumlData = yumlData.replaceAll(",$", ""); return getAsByteArray(getYumlPic(yumlData)); } catch (Throwable e) { logger.error(" Exception while construting pipeline data ", e); return null; } } public void setGraph(Map<String, Set<String>> graph) { this.graph = graph; } @Override public void afterPropertiesSet() throws Exception { Management.addBean(getBeanName(), this); } }