package dk.thoerup.traininfoservice.banedk; import java.io.IOException; import java.net.URL; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import com.gargoylesoftware.htmlunit.BrowserVersion; import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.RefreshHandler; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.DomNodeList; import com.gargoylesoftware.htmlunit.html.HtmlElement; import com.gargoylesoftware.htmlunit.html.HtmlPage; import dk.thoerup.circuitbreaker.CircuitBreaker; import dk.thoerup.circuitbreaker.CircuitBreakerManager; import dk.thoerup.traininfoservice.StationDAO; import dk.thoerup.traininfoservice.Statistics; public class TimetableFetcher { class NullRefreshHandler implements RefreshHandler { public void handleRefresh(Page arg0, URL arg1, int arg2) throws IOException { } } Map> cache; Map stationCache; StationDAO stationDao = new StationDAO(); Logger logger = Logger.getLogger(TimetableFetcher.class.getName()); private boolean useTempSite; public TimetableFetcher(boolean tmpSite, int cacheTimeout) { useTempSite = tmpSite; cache = new TimeoutMap>(cacheTimeout); stationCache = new TimeoutMap( 3*60*60*1000 ); } List cachedLookupTimetable(String trainID, String type) throws Exception { String key = trainID+type; List list = null;//cache.get(key); if (list == null) { list = lookupTimetable(trainID,type); cache.put(key, list); } else { Statistics.getInstance().incrementTimetableCacheHits(); logger.info("Timetable: Cache hit " + trainID); } return list; } List lookupTimetable(String trainID, String type) throws Exception { if (useTempSite == false ){ return lookupTimetableRealSite(trainID, type); } else { return new ArrayList(); // no timetable data on temp site } } int getStationId(String name) { Integer id = stationCache.get(name); if (id == null) { try { id = stationDao.getBySpecificName(name); stationCache.put(name, id); } catch (SQLException e) { logger.log(Level.SEVERE, "getStationId failed", e); id = -1; } } return id; } List lookupTimetableRealSite(String trainID, String type) throws Exception { List timetableList = new ArrayList(); String url = "http://www.bane.dk/visRute.asp?W=" + type + "&TogNr=" + trainID + "&artikelId=4276"; final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3); webClient.setTimeout(2500); webClient.setJavaScriptEnabled(false); webClient.setRefreshHandler( new NullRefreshHandler() ); webClient.setCssEnabled(false); BanedkInvocation wrapper = new BanedkInvocation(webClient, url); CircuitBreaker breaker = CircuitBreakerManager.getManager().getCircuitBreaker("banedk"); HtmlPage page = (HtmlPage) breaker.invoke(wrapper); boolean currentStation = false; boolean currentStationSaved = false; List tables = page.getDocumentElement().getElementsByAttribute("table", "class", "Rute"); if (tables.size() == 1) { HtmlElement timetable = tables.get(0); DomNodeList rows = timetable.getElementsByTagName("tr"); for (int i=0; i fields = row.getElementsByTagName("td"); if (currentStationSaved == false && fields.get(0).getAttribute("class").equalsIgnoreCase("Tidsstreg")) { currentStation = true; continue; } TimetableBean bean = new TimetableBean(); String station = fields.get(0).asText() ; if (station.equals("København")) station = "København H"; //correct inconsistency in naming bean.setStation( station ); bean.setArrival( fields.get(1).asText() ); bean.setDeparture( fields.get(2).asText() ); if (currentStation == true && currentStationSaved == false ) { bean.setCurrent(currentStation); currentStationSaved = true; } bean.setStationId( getStationId( station )); timetableList.add(bean); } } else { logger.warning("No time table found, trainID=" + trainID + " type=" + type); } webClient.closeAllWindows(); return timetableList; } }