I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 7912d765 authored by zzz's avatar zzz
Browse files

News: new NewsManager to maintain current news entries.

WIP, not yet hooked in.
parent 6f5739b9
No related branches found
No related tags found
No related merge requests found
package net.i2p.router.news;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppState;
import static net.i2p.app.ClientAppState.*;
import net.i2p.router.app.RouterApp;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
import net.i2p.util.TranslateReader;
import org.cybergarage.xml.Node;
/**
* Manage current news.
* Keeps current entries in memory, and provide methods to
* add new entries and store them to disk.
*
* @since 0.9.23
*/
public class NewsManager implements RouterApp {
private final I2PAppContext _context;
private final Log _log;
private final ClientAppManager _cmgr;
private volatile ClientAppState _state = UNINITIALIZED;
private List<NewsEntry> _currentNews;
private NewsMetadata _currentMetadata;
public static final String APP_NAME = "news";
private static final String BUNDLE_NAME = "net.i2p.router.news.messages";
/**
* @param args ignored
*/
public NewsManager(I2PAppContext ctx, ClientAppManager listener, String[] args) {
_context = ctx;
_cmgr = listener;
_log = ctx.logManager().getLog(NewsManager.class);
_state = INITIALIZED;
}
/**
*
* @return non-null, sorted by updated date, newest first
*/
public synchronized List<NewsEntry> getEntries() {
if (!_currentNews.isEmpty())
return new ArrayList(_currentNews);
// load old news.xml
List<NewsEntry> rv = parseOldNews();
if (!rv.isEmpty()) {
_currentNews = rv;
// don't save to disk as we don't have the UUIDs so they will be dups ??
return rv;
}
// load and translate initialnews
// We don't save it to _currentNews, as the language may change
return parseInitialNews();
}
/**
* Store each entry.
* Old entries are always overwritten, as they may change even without the updated date changing.
* Does NOT update the NewsEntry list.
*
* @param entries each one should be "entry" at the root
* @return success
*/
public synchronized boolean storeEntries(List<Node> entries) {
return PersistNews.store(_context, entries);
}
/**
* Add or replace each entry in the list.
* Does NOT store them to disk.
*/
public synchronized void addEntries(List<NewsEntry> entries) {
for (NewsEntry e : entries) {
String id = e.id;
if (id == null)
continue;
boolean found = false;
for (int i = 0; i < _currentNews.size(); i++) {
NewsEntry old = _currentNews.get(i);
if (id.equals(old.id)) {
_currentNews.set(i, e);
found = true;
break;
}
}
if (!found)
_currentNews.add(e);
}
Collections.sort(_currentNews);
}
/////// ClientApp methods
/**
* ClientApp interface
*/
public synchronized void startup() {
changeState(STARTING);
_currentNews = PersistNews.load(_context);
changeState(RUNNING);
if (_cmgr != null)
_cmgr.register(this);
}
/**
* ClientApp interface
* @param args ignored
*/
public synchronized void shutdown(String[] args) {
changeState(STOPPED);
}
public ClientAppState getState() {
return _state;
}
public String getName() {
return APP_NAME;
}
public String getDisplayName() {
return "News Manager";
}
/////// end ClientApp methods
private synchronized void changeState(ClientAppState state) {
_state = state;
if (_cmgr != null)
_cmgr.notify(this, state, null, null);
}
private List<NewsEntry> parseOldNews() {
File file = new File(_context.getConfigDir(), "docs/news.xml");
String newsContent = FileUtil.readTextFile(file.toString(), -1, true);
if (newsContent == null || newsContent.equals(""))
return Collections.emptyList();
return parseNews(newsContent);
}
private List<NewsEntry> parseInitialNews() {
NewsEntry entry = new NewsEntry();
File file = new File(_context.getBaseDir(), "docs/initialNews/initialNews.xml");
Reader reader = null;
try {
char[] buf = new char[512];
StringBuilder out = new StringBuilder(2048);
reader = new TranslateReader(_context, BUNDLE_NAME, new FileInputStream(file));
int len;
while((len = reader.read(buf)) > 0) {
out.append(buf, 0, len);
}
List<NewsEntry> rv = parseNews(out.toString());
if (!rv.isEmpty()) {
rv.get(0).updated = RFC3339Date.parse3339Date("2015-01-01");
} else {
if (_log.shouldWarn())
_log.warn("failed to load " + file);
}
return rv;
} catch (IOException ioe) {
if (_log.shouldWarn())
_log.warn("failed to load " + file, ioe);
return Collections.emptyList();
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException foo) {}
}
}
private List<NewsEntry> parseNews(String newsContent) {
List<NewsEntry> rv = new ArrayList<NewsEntry>();
// Parse news content for headings.
boolean foundEntry = false;
int start = newsContent.indexOf("<h3>");
while (start >= 0) {
NewsEntry entry = new NewsEntry();
// Add offset to start:
// 4 - gets rid of <h3>
// 16 - gets rid of the date as well (assuming form "<h3>yyyy-mm-dd: Foobarbaz...")
// Don't truncate the "congratulations" in initial news
if (newsContent.length() > start + 16 &&
newsContent.substring(start + 4, start + 6).equals("20") &&
newsContent.substring(start + 14, start + 16).equals(": ")) {
entry.updated = RFC3339Date.parse3339Date(newsContent.substring(start + 4, start + 14));
newsContent = newsContent.substring(start+16);
} else {
newsContent = newsContent.substring(start+4);
}
int end = newsContent.indexOf("</h3>");
if (end >= 0) {
String heading = newsContent.substring(0, end);
entry.title = heading;
// use title as UUID
entry.id = heading;
newsContent = newsContent.substring(end + 5);
end = newsContent.indexOf("<h3>");
if (end > 0)
entry.content = newsContent.substring(0, end);
else
entry.content = newsContent;
rv.add(entry);
start = end;
}
}
Collections.sort(rv);
return rv;
}
public static void main(String[] args) {
if (args.length != 0) {
System.err.println("Usage: NewsManager");
System.exit(1);
}
I2PAppContext ctx = new I2PAppContext();
NewsManager mgr = new NewsManager(ctx, null, null);
mgr.startup();
List<NewsEntry> entries = mgr.getEntries();
System.out.println("Loaded " + entries.size() + " news entries");
for (int i = 0; i < entries.size(); i++) {
NewsEntry e = entries.get(i);
System.out.println("\n****** News #" + (i+1) + ": " + e.title + ' ' + new Date(e.updated) + '\n' + e.content);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment