package 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.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import models.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 {
// 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;
// URL to news API
URL url = null;
try {
url = new URL("http://" + SessionData.session.getServerAdress() + "/slx-admin/api.php?do=news");
} catch (MalformedURLException e2) {
e2.printStackTrace();
// This shouldn't happen, but in case it does, alert user.
JOptionPane.showMessageDialog(null,
"News-URL falsch formatiert!",
"Fehler", JOptionPane.ERROR_MESSAGE);
}
// check for argument
if (url == null) {
// no URL, alert user.
JOptionPane.showMessageDialog(null,
"Keine News-URL angegben!",
"Fehler", JOptionPane.ERROR_MESSAGE);
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 e1) {
e1.printStackTrace();
JOptionPane.showMessageDialog(null,
"Satellite antwortete auf die Anfrage der News-XML nicht!",
"Fehler", JOptionPane.ERROR_MESSAGE);
return;
}
InputStream is = null;
try {
is = urlCon.getInputStream();
} catch (IOException e1) {
e1.printStackTrace();
JOptionPane.showMessageDialog(null,
"Konnte den News-URL-Stream nicht öffnen!",
"Fehler", JOptionPane.ERROR_MESSAGE);
return;
}
// use java's DocumentBuilder engine to parse the XML
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e1) {
e1.printStackTrace();
JOptionPane.showMessageDialog(null,
"XML-Parser falsch konfiguriert!",
"Fehler", JOptionPane.ERROR_MESSAGE);
return;
}
// try the parsing
try {
doc = builder.parse(is);
} catch (SAXException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null,
"Konnte die News-XML nicht parsen!",
"Fehler", JOptionPane.ERROR_MESSAGE);
return;
} catch (IOException e) {
JOptionPane.showMessageDialog(null,
"IO-Fehler!",
"Fehler", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
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) {
nfe.printStackTrace();
JOptionPane.showMessageDialog(null,
"Zeitstempel aus der XML is invalid!",
"Fehler", JOptionPane.ERROR_MESSAGE);
// TODO: set current date.
}
// Date creation worked, save it
if (tmpDate != null) date = tmpDate;
}
} else {
JOptionPane.showMessageDialog(null,
"Invalides XML! Kein 'news' Wurzelelement. News wird leer gelassen.",
"Fehler", JOptionPane.ERROR_MESSAGE);
return;
}
}
}