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:
* <news>
* <headline>...</headline>
* <content>...</content>
* <date>...</date>
* </news>
*
* - 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;
}
}
}