package org.openslx.dozmod.util; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.sql.Date; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.SessionData; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * Class representing the news given by the satellite * Makes use of the News-API of the webservice slx-admin: * http://satellite.ip/slx-admin/api.php?do=news * * Access the data through the public getters: * String newsHeadline = News.getHeadline(); * String newsContent = News.getContent(); * Date newsLatestDate = News.getDate(); */ public class News { // Logger instance for this class private final static Logger LOGGER = Logger.getLogger(News.class); // Private members representing the news private static String headline = null; private static String content = null; private static Date date = null; /** * Gets the headline as String. * * @return String Contains the headline text. */ public static String getHeadline() { if (headline != null) return headline; else { init(); // check if it is still null if (headline != null) return headline; else return null; } } /** * Gets the content as String. * * @return String Contains the content text. */ public static String getContent() { if (content != null) return content; else { init(); if (content != null) return content; else return null; } } /** * Gets the date of the latest news as Date. * * @return Date Represent last modification date. */ public static Date getDate() { if (date != null) return date; else { init(); if (date != null) return date; else return null; } } /** * Private 'init' function doing the main work. * It is called by getters if their object is null. * Follows these steps: * - Opens URL as stream * - Parse stream as (XML-)Document * - Check validity of the news format: * * ... * ... * ... * * * - Sets private members */ private static void init(){ // Document representing the XML Document doc = null; String satIp = SessionData._Fields.SERVER_ADDRESS.toString(); // sanity check to see if we have the satellite IP if (satIp == null || satIp.isEmpty()) { LOGGER.error("No satellite IP adress is set in SessionData, aborting news fetching..."); return; } // URL to news API URL url = null; try { url = new URL("http://" + SessionData._Fields.SERVER_ADDRESS.toString() + "/slx-admin/api.php?do=news"); } catch (MalformedURLException e) { LOGGER.error("Malformated URL to News-API, see trace: ", e); } // check is the url got created. if (url == null) { // no URL, log it and return LOGGER.error("URL to the News-API not defined!"); return; } // set timeout for URLConnection URLConnection urlCon = null; try { urlCon = url.openConnection(); // 5 seconds timeout for connection urlCon.setConnectTimeout(5000); // 10 seconds timeout for reading the stream urlCon.setReadTimeout(10000); } catch (IOException e) { LOGGER.error("IO error while requesting News URL, see trace: ", e); return; } InputStream is = null; try { is = urlCon.getInputStream(); } catch (IOException e1) { LOGGER.error("Could not open stream to URL '" + url.toString() + "', see trace: ", e1); return; } // use java's DocumentBuilder engine to parse the XML DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = null; try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { LOGGER.error("XML parsing configuration error, see trace: ", e); return; } // try the parsing try { doc = builder.parse(is); } catch (SAXException e) { LOGGER.error("XML parsing error, see trace: ", e); return; } catch (IOException e) { LOGGER.error("IO-Error, see trace: ", e); return; } // now that we have parsed the XML, check if it is valid Element docRoot = doc.getDocumentElement(); // first element has to be name "news" if (docRoot.getNodeName().equals("news")) { Node headlineNode = null; Node contentNode = null; Node dateNode = null; // get list of every child NodeList nList = docRoot.getElementsByTagName("*"); // fail if the list is empty if (nList == null) return; // now we go through the list looking for our elements // TODO: get definition of tags externally/through static api? for (int i = 0; i < nList.getLength(); i++) { Node current = nList.item(i); if (current.getNodeType() == Node.ELEMENT_NODE) { if (current.getNodeName().equals("headline") && current.getFirstChild().getNodeType() == Node.TEXT_NODE) headlineNode = current.getFirstChild(); // FIXME: temporary workaround for possibly different slx-admin versions! if ((current.getNodeName().equals("info") || current.getNodeName().equals("content")) && current.getFirstChild().getNodeType() == Node.TEXT_NODE) contentNode = current.getFirstChild(); if (current.getNodeName().equals("date") && current.getFirstChild().getNodeType() == Node.TEXT_NODE) dateNode = current.getFirstChild(); } } // set what the elements we found if (headlineNode != null) headline = headlineNode.getNodeValue().trim(); if (contentNode != null) content = contentNode.getNodeValue().trim(); if (dateNode != null) { // for the date we need a bit more stuff Date tmpDate = null; try { tmpDate = new Date(Long.parseLong(dateNode.getNodeValue().trim()) * 1000); } catch (NumberFormatException nfe) { LOGGER.error("Date format is invalid, see trace: ", nfe); } // Date creation worked, save it if (tmpDate != null) date = tmpDate; } } else { LOGGER.error("No valid news in the response!"); return; } } }