package dk.thoerup.traininfoservice.banedk; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.Element; import dk.thoerup.circuitbreaker.CircuitBreakerException; import dk.thoerup.traininfoservice.Statistics; /** * Servlet implementation class DepartureServlet */ @WebServlet(urlPatterns={"/DepartureServlet"}) public class DepartureServlet extends HttpServlet { private static final long serialVersionUID = 1L; Logger logger = Logger.getLogger( DepartureServlet.class.getName() ); DepartureFetcher fetcher; TransformerFactory transformerFactory = TransformerFactory.newInstance(); DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); @Override public void init() throws ServletException { super.init(); boolean useAzureSite = Boolean.parseBoolean( getServletContext().getInitParameter("useazuresite") ); int cacheTimeout = Integer.parseInt( getServletContext().getInitParameter("cache_timeout") ); int replyTimeout = Integer.parseInt( getServletContext().getInitParameter("reply_timeout") ); logger.info( "DepartureServlet, use temp site=" + useAzureSite + ", cache=" + cacheTimeout); fetcher = new DepartureFetcher(useAzureSite, cacheTimeout, replyTimeout); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getParameter("station") == null) { resp.sendError(400, "not enough parameters"); return; } boolean arrival = false; try { arrival = Integer.parseInt( req.getParameter("arrival")) != 0; } catch (Exception e) {} Statistics.getInstance().incrementDepartureLookups(); int station = Integer.parseInt( req.getParameter("station") ); String format = req.getParameter("format"); DepartureBean beans; try { beans = fetcher.cachedLookupDepartures(station, arrival); } catch (java.io.IOException ioe) { logger.warning("Read failed, station="+station + ". " + ioe.getMessage() ); Statistics.getInstance().incrementDepartureErrors(); resp.sendError(500); return; } catch (CircuitBreakerException cbe) { logger.warning("Circuitbreaker - failing fast"); Statistics.getInstance().incrementDepartureErrors(); resp.sendError(500); return; } catch (Exception e) { logger.log(Level.WARNING, "Unknown exception, station=" +station, e); Statistics.getInstance().incrementDepartureErrors(); resp.sendError(500); return; } resp.setDateHeader("Expires", 0); resp.setHeader("Cache-Control", "no-cache, must-revalidate"); if (format.equalsIgnoreCase("xml")) { resp.setContentType("text/xml"); resp.getWriter().print( formatXml(beans, arrival) ); } else if (format.equalsIgnoreCase("html")) { String advStr = req.getParameter("advanced"); boolean advanced = advStr != null ? Boolean.parseBoolean(advStr) : false; req.setAttribute("advanced", advanced); req.setAttribute("departurebeans", beans); req.setAttribute("stationID", station ); getServletContext().getRequestDispatcher("/ViewDepartures.jsp").forward(req,resp); } else { resp.sendError(400, "Unknown format"); } } protected String formatXml(DepartureBean beans, boolean arrival) throws ServletException{ String xml = ""; try { DocumentBuilder builder = docBuilderFactory.newDocumentBuilder(); DOMImplementation impl = builder.getDOMImplementation(); Document doc = impl.createDocument(null,null,null); Element root = doc.createElement("departureinfo"); root.setAttribute("station", beans.getStationName()); root.setAttribute("arrival", Boolean.toString(arrival) ); for (String notif : beans.notifications) { Element notElem = doc.createElement("notification"); notElem.setTextContent(notif); root.appendChild(notElem); } for (DepartureEntry departure : beans.departureEntries) { Element train = doc.createElement("train"); Element time = doc.createElement("time"); time.setTextContent( departure.getTime() ); train.appendChild(time); Element updated = doc.createElement("updated"); updated.setTextContent( String.valueOf(departure.getUpdated()) ); train.appendChild(updated); Element trainNumber = doc.createElement("trainnumber"); trainNumber.setTextContent( departure.getTrainNumber() ); train.appendChild(trainNumber); Element destination = doc.createElement("destination"); destination.setTextContent( departure.getDestination()); train.appendChild(destination); Element origin = doc.createElement("origin"); origin.setTextContent( departure.getOrigin() ); train.appendChild(origin); Element location= doc.createElement("location"); location.setTextContent( departure.getLocation() ); train.appendChild(location); Element status = doc.createElement("status"); status.setTextContent( departure.getStatus() ); train.appendChild(status); Element note = doc.createElement("note"); note.setTextContent( departure.getNote() ); train.appendChild(note); Element type = doc.createElement("type"); type.setTextContent( departure.getType() ); train.appendChild(type); root.appendChild(train); } doc.appendChild(root); DOMSource domSource = new DOMSource(doc); Transformer transformer = transformerFactory.newTransformer(); //transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "1"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); java.io.StringWriter sw = new java.io.StringWriter(); StreamResult sr = new StreamResult(sw); transformer.transform(domSource, sr); xml = sw.toString(); } catch (Exception e) { throw new ServletException(e); } return xml; } }