Java tutorial
/* * Copyright (c) 2012 Jeremy Goetsch * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.jgoetsch.eventtrader.source; import java.io.IOException; import java.util.Date; import java.util.HashSet; import java.util.Set; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpUriRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.jgoetsch.eventtrader.Msg; import com.jgoetsch.eventtrader.source.parser.MsgParser; public class HttpPollingMsgSource extends AbstractHttpMsgSource { private Logger log = LoggerFactory.getLogger(HttpPollingMsgSource.class); private long pollingInterval = 60000; private long freshnessThreshold = 30000; private MsgParser msgParser; private boolean useIfModifiedSince = false; private boolean alertInitial = false; private String lastModifiedDate; private class NewMsgHandler implements MsgHandler { private Set<Msg> lastMsgs; private Set<Msg> msgs = new HashSet<Msg>(); private Date lastCheckAt; public boolean newMsg(Msg msg) { msgs.add(msg); if (lastCheckAt != null && new Date().getTime() - lastCheckAt.getTime() > pollingInterval + freshnessThreshold) { if (lastMsgs != null) lastMsgs.clear(); lastMsgs = null; } if (lastMsgs == null) { log.debug("Previous message: {}", msg); } if ((lastMsgs != null && !lastMsgs.contains(msg)) || (lastMsgs == null && alertInitial)) { if (!HttpPollingMsgSource.this.newMsg(msg)) return false; } return true; } public void nextPass() { if (lastMsgs != null) lastMsgs.clear(); lastMsgs = msgs; msgs = new HashSet<Msg>(lastMsgs.size() + 4); lastCheckAt = new Date(); } }; public void receiveMsgs(HttpClient client) { NewMsgHandler msgHandler = new NewMsgHandler(); HttpUriRequest req = createRequest(); for (;;) { HttpEntity entity = null; try { if (isUseIfModifiedSince() && lastModifiedDate != null) req.setHeader("If-Modified-Since", lastModifiedDate); long startTime = System.currentTimeMillis(); HttpResponse rsp = client.execute(req); if (rsp.containsHeader("Last-Modified")) { lastModifiedDate = rsp.getFirstHeader("Last-Modified").getValue(); //log.debug("Resource last modified: " + lastModifiedDate); } entity = rsp.getEntity(); if (rsp.getStatusLine().getStatusCode() >= 400) { log.warn("HTTP request to " + req.getURI().getHost() + " failed [" + rsp.getStatusLine().getStatusCode() + " " + rsp.getStatusLine().getReasonPhrase() + ", " + (System.currentTimeMillis() - startTime) + " ms]"); // 400 level error should be unrecoverable so just quit out if (rsp.getStatusLine().getStatusCode() < 500) return; else { // give server some more time to recover before retrying if it returned 500 level error // probably means site crashed and continuing to hit it will only make things worse try { Thread.sleep(pollingInterval * 6); } catch (InterruptedException e) { } } } else { boolean bContinue = true; if (entity != null && rsp.getStatusLine().getStatusCode() != 304) { // 304 = not modified bContinue = getMsgParser().parseContent(entity.getContent(), entity.getContentLength(), entity.getContentType() == null ? null : entity.getContentType().getValue(), msgHandler); msgHandler.nextPass(); } if (log.isDebugEnabled()) { log.debug( "Checked site at " + req.getURI().getHost() + " [" + rsp.getStatusLine().getStatusCode() + " " + rsp.getStatusLine().getReasonPhrase() + ", " + (entity != null ? (entity.getContentLength() != -1 ? entity.getContentLength() + " bytes, " : "unknown length, ") : "") + (System.currentTimeMillis() - startTime) + " ms]"); } if (!bContinue) return; } } catch (IOException e) { log.warn(e.getClass() + ": " + e.getMessage()); } catch (Exception e) { log.warn(e.getClass() + ": " + e.getMessage(), e); } finally { if (entity != null) { // release connection gracefully try { entity.consumeContent(); } catch (IOException e) { } } } delay(); } } protected void delay() { try { Thread.sleep(pollingInterval); } catch (InterruptedException e) { } } protected void doLoginAction(HttpClient client) { } /* private LocalTime parseLocalTime(String time) { String tok[] = time.split("[\\:\\s]"); if (tok.length < 3 || tok.length > 4) throw new IllegalArgumentException("Time must be in format \"HH:MM:SS [timezone]\""); return new LocalTime(Integer.parseInt(tok[0]), Integer.parseInt(tok[1]), Integer.parseInt(tok[2])); } */ public void setPollingInterval(long milliseconds) { this.pollingInterval = milliseconds; } public long getPollingInterval() { return pollingInterval; } public void setPollingIntervalSeconds(long seconds) { this.pollingInterval = seconds * 1000; } public void setPollingIntervalMinutes(long minutes) { this.pollingInterval = minutes * 60000; } public void setMsgParser(MsgParser msgParser) { this.msgParser = msgParser; } public MsgParser getMsgParser() { return msgParser; } public void setUseIfModifiedSince(boolean useIfModifiedSince) { this.useIfModifiedSince = useIfModifiedSince; } public boolean isUseIfModifiedSince() { return useIfModifiedSince; } public void setAlertInitial(boolean alertInitial) { this.alertInitial = alertInitial; } public boolean isAlertInitial() { return alertInitial; } public long getFreshnessThreshold() { return freshnessThreshold; } public void setFreshnessThreshold(long freshnessThreshold) { this.freshnessThreshold = freshnessThreshold; } }