/*******************************************************************************
* 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);
}
}