package org.hackreduce.storm.gnip.bolt; import backtype.storm.task.TopologyContext; import backtype.storm.topology.BasicOutputCollector; import backtype.storm.topology.OutputFieldsDeclarer; import backtype.storm.topology.base.BaseBasicBolt; import backtype.storm.tuple.Fields; import backtype.storm.tuple.Tuple; import org.apache.commons.codec.binary.Base64; import org.mortbay.xml.XmlParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; public class GnipEdcRequestBolt extends BaseBasicBolt { private static Logger LOG = LoggerFactory.getLogger(GnipEdcRequestBolt.class); private final String gnipConnectionUrl; private final String gnipConnectionLogin; private final String gnipConnectionPassword; private final String gnipEventsStreamName; private final String gnipEventFieldName; private String refreshUrl; private String componentId; public GnipEdcRequestBolt(String gnipConnectionUrl, String gnipConnectionLogin, String gnipConnectionPassword, String gnipEventsStreamName, String gnipEventFieldName) { this.gnipConnectionUrl = gnipConnectionUrl; this.gnipConnectionLogin = gnipConnectionLogin; this.gnipConnectionPassword = gnipConnectionPassword; this.gnipEventsStreamName = gnipEventsStreamName; this.gnipEventFieldName = gnipEventFieldName; } @Override public void prepare(Map map, TopologyContext topologyContext) { super.prepare(map, topologyContext); componentId = topologyContext.getThisComponentId(); } @Override public void execute(Tuple tuple, BasicOutputCollector basicOutputCollector) { try { for (XmlParser.Node event : requestGnipData()) { String strEvent = event.toString(); basicOutputCollector.emit(gnipEventsStreamName, Arrays.asList((Object) strEvent)); } } catch (GnipRequestException e) { LOG.error("GNIP Request Failed", e); } } @Override public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) { outputFieldsDeclarer.declareStream(gnipEventsStreamName, new Fields(gnipEventFieldName)); } private List<XmlParser.Node> requestGnipData() throws GnipRequestException { URLConnection uc; URL connectionUrl; try { connectionUrl = refreshUrl == null ? new URL(gnipConnectionUrl) : new URL(refreshUrl); } catch (MalformedURLException e) { throw new GnipRequestException("Failed parsing connection URL", e); } try { uc = connectionUrl.openConnection(); } catch (IOException e) { throw new GnipRequestException("Failed opening connection", e); } String authorizationString = "Basic " + Base64.encodeBase64String((gnipConnectionLogin + ":" + gnipConnectionPassword).getBytes()).replaceAll("[\r\n]", ""); uc.setRequestProperty("Authorization", authorizationString); InputStream in = null; try { try { in = uc.getInputStream(); } catch (IOException e) { throw new GnipRequestException("Failed opening input stream", e); } XmlParser p = new XmlParser(); XmlParser.Node doc; try { doc = p.parse(in); } catch (IOException e) { throw new GnipRequestException("Failed reading input stream", e); } catch (SAXException e) { throw new GnipRequestException("Failed parsing input stream", e); } refreshUrl = doc.getAttribute("refreshURL"); List<XmlParser.Node> result = new ArrayList<XmlParser.Node>(); for (int i = 0; i < doc.size(); i++) { Object nodeObj = doc.get(i); if (nodeObj instanceof XmlParser.Node) { XmlParser.Node node = (XmlParser.Node) nodeObj; result.add(node); } } LOG.info("{} completed request", componentId); return result; } finally { if (in != null) { try { in.close(); } catch (IOException e) { } } } } }