summaryrefslogtreecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/util/News.java
blob: e8c44130c75816693dcba79ea6731a00935e1feb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
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;
		}
	}	
}