diff --git a/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java b/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java index 732b814a7663e86262ad540ecfd5b1d327d2c231..e418c8640ca491bd85fc9c7e9be3ce1c291f03a9 100644 --- a/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java +++ b/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java @@ -1,6 +1,7 @@ package net.i2p.router.news; import java.util.List; +import net.i2p.util.VersionComparator; /** * The update metadata. @@ -15,14 +16,41 @@ public class NewsMetadata { public String feedID; public long feedUpdated; - // I2P update metadata - public long date; - public String minVersion; - public String minJavaVersion; - public String i2pVersion; - public String sudTorrent; - public String su2Torrent; - public String su3Torrent; - public List<String> su3Clearnet; - public List<String> su3SSL; + // I2P metadata + public List<Release> releases; + + public static class Release implements Comparable<Release> { + public long date; + public String minVersion; + public String minJavaVersion; + public String i2pVersion; + public List<Update> updates; + + @Override + public int compareTo(Release other) { + // Sort latest version first. + return VersionComparator.comp(other.i2pVersion, i2pVersion); + } + } + + public static class Update implements Comparable<Update> { + public String type; + public List<String> torrent; + public List<String> clearnet; + public List<String> ssl; + + @Override + public int compareTo(Update other) { + return Integer.compare(getTypeOrder(), other.getTypeOrder()); + } + + protected int getTypeOrder() { + if ("su3".equalsIgnoreCase(type)) + return 1; + else if ("su2".equalsIgnoreCase(type)) + return 2; + else + return 3; + } + } } diff --git a/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java b/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java index f3b01bdd9ee81cd7fa3bd074ab7c3fa77165f657..e643643ce8ddb89536c254fda68001053978f87b 100644 --- a/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java +++ b/apps/routerconsole/java/src/net/i2p/router/news/NewsXMLParser.java @@ -15,6 +15,7 @@ import java.util.Set; import net.i2p.I2PAppContext; import net.i2p.util.Log; + import org.cybergarage.util.Debug; import org.cybergarage.xml.Attribute; import org.cybergarage.xml.Node; @@ -169,38 +170,63 @@ public class NewsXMLParser { } } - Node r = feed.getNode("i2p:release"); - if (r == null) + List<NewsMetadata.Release> releases = new ArrayList<NewsMetadata.Release>(); + List<Node> releaseNodes = getNodes(feed, "i2p:release"); + if (releaseNodes.size() == 0) throw new I2PParserException("no release data in XML"); - // release attributes - String a = r.getAttributeValue("date"); - if (a.length() > 0) { - long time = RFC3339Date.parse3339Date(a); - if (time > 0) - rv.date = time; - } - a = r.getAttributeValue("minVersion"); - if (a.length() > 0) - rv.minVersion = a; - a = r.getAttributeValue("minJavaVersion"); - if (a.length() > 0) - rv.minJavaVersion = a; - // release nodes - n = r.getNode("i2p:version"); - if (n != null) - rv.i2pVersion = n.getValue(); - List<Node> urls = getNodes(r, "i2p:torrent"); - for (Node t : urls) { - // returns "" for none - String href = t.getAttributeValue("href"); - if (href.length() > 0) { - String type = t.getAttributeValue("type"); - if (type.equals("su2")) - rv.su2Torrent = href; - else if (type.equals("su3")) - rv.su3Torrent = href; + for (Node r : releaseNodes) { + NewsMetadata.Release release = new NewsMetadata.Release(); + // release attributes + String a = r.getAttributeValue("date"); + if (a.length() > 0) { + long time = RFC3339Date.parse3339Date(a); + if (time > 0) + release.date = time; + } + a = r.getAttributeValue("minVersion"); + if (a.length() > 0) + release.minVersion = a; + a = r.getAttributeValue("minJavaVersion"); + if (a.length() > 0) + release.minJavaVersion = a; + // release nodes + n = r.getNode("i2p:version"); + if (n != null) + release.i2pVersion = n.getValue(); + + List<NewsMetadata.Update> updates = new ArrayList<NewsMetadata.Update>(); + List<Node> updateNodes = getNodes(r, "i2p:update"); + for (Node u : updateNodes) { + // returns "" for none + String type = u.getAttributeValue("type"); + if (type.length() > 0) { + NewsMetadata.Update update = new NewsMetadata.Update(); + update.type = type; + int totalSources = 0; + + List<String> torrents = new ArrayList<String>(); + List<Node> torrentNodes = getNodes(u, "i2p:torrent"); + for (Node t : torrentNodes) { + // returns "" for none + String href = t.getAttributeValue("href"); + if (href.length() > 0) { + torrents.add(href); + } + } + update.torrent = torrents; + totalSources += torrents.size(); + + if (totalSources == 0) + throw new I2PParserException("no sources for update type " + type); + updates.add(update); + } } + Collections.sort(updates); + release.updates = updates; + releases.add(release); } + Collections.sort(releases); + rv.releases = releases; return rv; } @@ -388,8 +414,9 @@ public class NewsXMLParser { parser.parse(new File(args[0])); NewsMetadata ud = parser.getMetadata(); List<NewsEntry> entries = parser.getEntries(); - System.out.println("Latest version is " + ud.i2pVersion); - System.out.println("Release timestamp: " + ud.date); + NewsMetadata.Release latestRelease = ud.releases.get(0); + System.out.println("Latest version is " + latestRelease.i2pVersion); + System.out.println("Release timestamp: " + latestRelease.date); System.out.println("Feed timestamp: " + ud.feedUpdated); System.out.println("Found " + entries.size() + " news entries"); for (int i = 0; i < entries.size(); i++) { diff --git a/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java b/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java index a17926ed3a3320ca0183c915fb52eae8e23e50c8..063068cdcae3ff59f53d34be1adf0d6eb551939d 100644 --- a/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java +++ b/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java @@ -459,22 +459,35 @@ class NewsFetcher extends UpdateRunner { */ private void outputOldNewsXML(NewsMetadata data, List<NewsEntry> entries, String sudVersion, String signingKeyName, File to) throws IOException { + NewsMetadata.Release latestRelease = data.releases.get(0); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(to), "UTF-8")); out.write("<!--\n"); // update metadata in old format out.write("<i2p.release "); - if (data.i2pVersion != null) - out.write(" version=\"" + data.i2pVersion + '"'); - if (data.minVersion != null) - out.write(" minVersion=\"" + data.minVersion + '"'); - if (data.minJavaVersion != null) - out.write(" minJavaVersion=\"" + data.minJavaVersion + '"'); - if (data.su2Torrent != null) - out.write(" su2Torrent=\"" + data.su2Torrent + '"'); - if (data.su3Torrent != null) - out.write(" su3Torrent=\"" + data.su3Torrent + '"'); + if (latestRelease.i2pVersion != null) + out.write(" version=\"" + latestRelease.i2pVersion + '"'); + if (latestRelease.minVersion != null) + out.write(" minVersion=\"" + latestRelease.minVersion + '"'); + if (latestRelease.minJavaVersion != null) + out.write(" minJavaVersion=\"" + latestRelease.minJavaVersion + '"'); + String su3Torrent = ""; + String su2Torrent = ""; + for (NewsMetadata.Update update : latestRelease.updates) { + if (update.torrent.size() > 0) { + // Only take the first torrent magnet + // TODO handle multiple torrent magnetss + if ("su3".equals(update.type) && su3Torrent.isEmpty()) + su3Torrent = update.torrent.get(0); + else if ("su2".equals(update.type) && su2Torrent.isEmpty()) + su2Torrent = update.torrent.get(0); + } + } + if (!su2Torrent.isEmpty()) + out.write(" su2Torrent=\"" + su2Torrent + '"'); + if (!su3Torrent.isEmpty()) + out.write(" su3Torrent=\"" + su3Torrent + '"'); out.write("/>\n"); // su3 and feed metadata for debugging out.write("** News version:\t" + DataHelper.stripHTML(sudVersion) + '\n');