Changeset 142

Show
Ignore:
Timestamp:
01/30/06 16:14:29 (3 years ago)
Author:
dsandler
Message:

New feed syntax in publisher.conf allows you to specify a separate public_url
from the feed's canonical URL. This allows you to have, for example, a
private full-content feed pushed out by FeedTree, and a public summaries-only
feed for conventional RSS users. (Another example: A public URL for your
FeedBurner?-hosted feed and a private URL for your *real* feed.)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • feedtree/trunk/publisher.conf

    r141 r142  
    1414 
    1515# list of feed URLs to be fetched by the publisher & pushed to FeedTree 
     16# (comma-separated, square-bracket-enclosed) 
    1617feeds = [ 
    17     "http://dsandler.org/wp/feed/atom/" 
     18     
     19    # just a simple feed URL 
     20    "http://dsandler.org/wp/feed/atom/", 
     21     
     22    # more complex example: a feed with a private fetch URL and a public URL 
     23    { url: "http://dsandler.org/wp/feed/rss2/",   # private fetch URL 
     24      public_url: "http://dsandler.org/wp/feed/"  # public URL 
     25    }, 
    1826] 
    1927 
     
    5563node_port = 29691 
    5664 
    57 # port for the Publisher web interface (currently unused) 
     65# port for the Publisher web interface 
    5866web_port = 8502 
    5967 
  • feedtree/trunk/src/net/feedtree/publisher/Publisher.java

    r141 r142  
    2020/// \verbinclude publisher.conf 
    2121///  
    22 /// At a minimum, \c feed_urls must be specified for Publisher to operate. 
     22/// At a minimum, \c feed_feeds must be specified for Publisher to operate. 
    2323/// To generate signed entries, at least \c keystore must be specified. 
    2424 
     
    9999    public static final String PROP_WEB_PORT = "web_port"; 
    100100     
    101     /// JSON list (i.e. enclosed in square-brackets) of feed URLs 
    102     /// Example: 
     101    /// JSON list (i.e. enclosed in square-brackets) of feed URLs or feed 
     102    /// structures.  Example: 
    103103    /// feeds = [ 
    104104    ///   "http://site.com/feed/atom/", 
    105     ///   "http://site.com/feed/rss2/" 
     105    ///   { 
     106    ///      url: "file:///local/site/rss2.xml", 
     107    ///      publicUrl: "http://site.com/feed/rss2/" 
     108    ///   } 
    106109    /// ] 
    107110    public static final String PROP_FEEDS = "feeds"; 
     111 
     112    /// In a feed structure (element of <code>feeds</code>), the URL of the 
     113    /// feed to fetch and publish.  Required in a feed structure. 
     114    public static final String PROP_FEEDS_FEED_URL = "url"; 
     115     
     116    /// In a feed structure (element of <code>feeds</code>), the public URL of 
     117    /// the feed (if different from the URL used for fetching).  Optional. 
     118    public static final String PROP_FEEDS_FEED_PUBLIC_URL = "public_url"; 
    108119 
    109120    /// Filename of a local keystore (optional; required for signing entries) 
     
    134145    protected PrivateKey m_key = null; 
    135146    protected Signature m_signer = null; 
    136     protected String[] m_urls; 
     147    protected Feed[] m_feeds; 
    137148     
    138149    protected Shelf m_storage; 
     
    165176    public static String REPORT_URL = "http://stats.feedtree.net/report"; 
    166177     
     178    protected static class Feed { 
     179        public String fetchUrl; 
     180        public String topic; 
     181        public Feed(String url) { this.fetchUrl = this.topic = url; } 
     182        public Feed(String fetchUrl, String topic) { 
     183            this.fetchUrl = fetchUrl; 
     184            this.topic = topic; 
     185        } 
     186    } 
     187 
    167188    protected static int hashEntry(SyndEntry e) { 
    168189        String desc = ""; 
     
    172193        String title = e.getTitle(); 
    173194        String link = e.getLink(); 
     195        String author = ""; 
    174196        List authors = e.getAuthors(); 
    175         String author = (authors == null) ? "" : (String) authors.get(0); 
     197        if (authors != null) { 
     198            Object a0 = authors.get(0); 
     199            if (a0 != null) 
     200                author = a0.toString(); 
     201        } 
    176202        Date date = e.getPublishedDate(); 
    177203 
     
    227253        public void run() {  
    228254            Logger.global.fine("### Refreshing all feeds"); 
    229             for (int i=0; i<m_urls.length; i++) { 
     255            for (int i=0; i<m_feeds.length; i++) { 
    230256                boolean anyNew = false; 
    231257                 
    232                 String feedUrl = m_urls[i]; 
     258                String feedTopic = m_feeds[i].topic; 
     259                String fetchUrl = m_feeds[i].fetchUrl; 
    233260                 
    234261                /*the*/ long now = new Date().getTime(); 
    235262 
    236                 Logger.global.fine("### Refreshing: " + feedUrl); 
     263                Logger.global.fine("### Refreshing: " + feedTopic); 
     264                Logger.global.fine("### Fetching feed data from URL: " + fetchUrl); 
    237265                LinkedList toPublish = new LinkedList(); 
    238266                 
    239267                LinkedHashMap entriesSeen  
    240                     = (LinkedHashMap)m_feedStorage.get(feedUrl); 
     268                    = (LinkedHashMap)m_feedStorage.get(feedTopic); 
    241269                if (entriesSeen == null) { 
    242270                    entriesSeen = new LinkedHashMap(); 
    243                     m_feedStorage.put(feedUrl, entriesSeen); 
     271                    m_feedStorage.put(feedTopic, entriesSeen); 
    244272                } 
    245273                 
     
    247275 
    248276                try { 
    249                     URLConnection cx = new URL(feedUrl).openConnection(); 
     277                    URLConnection cx = new URL(fetchUrl).openConnection(); 
    250278                    cx.setRequestProperty("User-Agent", "FeedTreePublisher/1"); 
    251279                    feed = new SyndFeedInput().build(new XmlReader(cx)); 
    252280                     
    253281                } catch (MalformedURLException exc) { 
    254                     Logger.global.warning("error: invalid URL: " + feedUrl); 
     282                    Logger.global.warning("error: invalid URL: " + fetchUrl); 
    255283                } catch (IOException exc) { 
    256                     Logger.global.warning("warning: couldn't read from URL: " + feedUrl + " ("+exc+")"); 
     284                    Logger.global.warning("warning: couldn't read from URL: " + fetchUrl + " ("+exc+")"); 
    257285                } catch (ParsingFeedException exc) {  
    258286                    Logger.global.warning("warning: couldn't parse feed (line "  
    259287                            + exc.getLineNumber() + ", column "  
    260288                            + exc.getColumnNumber() + ") at URL: " 
    261                             + feedUrl + " ("+exc+" <- " + exc.getCause()  
     289                            + fetchUrl + " ("+exc+" <- " + exc.getCause()  
    262290                            + (exc.getCause() == null ? ""  
    263291                                : (" <- " + exc.getCause().getCause())) 
    264292                            + ")"); 
    265293                } catch (FeedException exc) {  
    266                     Logger.global.warning("warning: couldn't interpret feed at URL: " + feedUrl + " ("+exc+")"); 
     294                    Logger.global.warning("warning: couldn't interpret feed at URL: " + fetchUrl + " ("+exc+")"); 
    267295                } 
    268296 
     
    303331                                 
    304332                                IFeedUpdateEvent feedEvent =  
    305                                     generateSignedEvent(feedUrl, feed, e); 
     333                                    generateSignedEvent(feedTopic, feed, e); 
    306334                                 
    307335                                toPublish.add(feedEvent); 
     
    320348 
    321349                    if (!anyNew) { 
    322                         Logger.global.fine("### Nothing new: " + feedUrl); 
    323                         if ((now - getLastEventTimeForFeed(feedUrl))  
     350                        Logger.global.fine("### Nothing new: " + feedTopic); 
     351                        if ((now - getLastEventTimeForFeed(feedTopic))  
    324352                                > m_heartbeatInterval)  
    325353                        { 
    326                             Logger.global.fine("### Due for a heartbeat: " + feedUrl); 
    327                             toPublish.add(generateSignedHeartbeat(feedUrl)); 
     354                            Logger.global.fine("### Due for a heartbeat: " + feedTopic); 
     355                            toPublish.add(generateSignedHeartbeat(feedTopic)); 
    328356                        } 
    329357                    } 
     
    335363                    // have another full heartbeat interval before we have 
    336364                    // to send another HB. 
    337                     setLastEventTimeForFeed(feedUrl, now); 
     365                    setLastEventTimeForFeed(feedTopic, now); 
    338366                     
    339367                    for(Iterator eventIterator = toPublish.iterator();  
     
    419447                    + getLocalNodeHandle().toString()  
    420448                    + "</title></head><body>"); 
     449 
     450                output.write("<h2>FeedTree Publisher: " 
     451                    + getLocalNodeHandle().toString()  
     452                    + "</h2>"); 
    421453                 
    422454                // TODO: make this pretty 
    423455 
    424                 for(Iterator i = m_feedStorage.keySet().iterator(); i.hasNext();) 
    425                 { 
    426                     String feedUrl = (String)(i.next()); 
    427                     Map entries = (Map)m_feedStorage.get(feedUrl); 
    428                     output.write("<h3>Feed: <tt>" + feedUrl + "</tt></h3><ol>"); 
     456                for(int i=0; i<m_feeds.length; i++) { 
     457                    Feed feed = m_feeds[i]; 
     458                    String feedTopic = feed.topic; 
     459                    output.write("<h3>Feed: <tt>" + feedTopic + "</tt></h3>"); 
     460                    output.write("<p>Fetched from: <tt>"  
     461                            + feed.fetchUrl + "</tt></p><ol>"); 
     462                    Map entries = (Map)m_feedStorage.get(feedTopic); 
    429463                    if (entries != null) { 
    430464                        for (Iterator j = entries.values().iterator(); j.hasNext();)  
     
    436470                                + "</tt></small></li>"); 
    437471                        } 
    438                         output.write("</ol>"); 
    439472                    } 
     473                    output.write("</ol><hr/>"); 
    440474                } 
    441475                output.write("</body></html>"); 
     
    519553            query.append("&published_feeds="); 
    520554 
    521             for(int i=0; i<m_urls.length; i++) { 
     555            for(int i=0; i<m_feeds.length; i++) { 
    522556                if (i>0) query.append("|"); 
     557                String topicUrl = m_feeds[i].topic; 
    523558                try { 
    524                     query.append(URLEncoder.encode(m_urls[i], "UTF-8")); 
     559                    query.append(URLEncoder.encode(topicUrl, "UTF-8")); 
    525560                } catch (java.io.UnsupportedEncodingException exc) { 
    526561                    query.append(release); // sigh 
    527562                } 
    528563                query.append(','); 
    529                 if (m_topics.containsKey(m_urls[i])) {  
    530                     Topic topic = (Topic) m_topics.get(m_urls[i]); 
     564                if (m_topics.containsKey(topicUrl)) {  
     565                    Topic topic = (Topic) m_topics.get(topicUrl); 
    531566                    query.append(topic.getId().toStringFull()); 
    532567                } 
     
    597632     
    598633    public Publisher(Node node, int nodePort, int webPort,  
    599         String[] urls, PrivateKey key)  
     634        Feed[] feeds, PrivateKey key)  
    600635    { 
    601636        super(node, nodePort); 
     
    636671        m_nodePort = nodePort; m_webPort = webPort; 
    637672 
    638         m_urls = urls; 
     673        m_feeds = feeds; 
    639674 
    640675        g_classLoader = this.getClass().getClassLoader(); 
     
    740775        int webPort = g_config.optInt(PROP_WEB_PORT, 8500); 
    741776 
    742         String[] urls = null; 
     777        Feed[] feeds = null; 
    743778         
    744779        JSONArray urlList = g_config.optJSONArray(PROP_FEEDS); 
     
    749784        } else { 
    750785            int len = urlList.length(); 
    751             urls = new String[len]; 
     786            feeds = new Feed[len]; 
    752787            try { 
    753788                for (int i=0; i<len; i++) { 
    754                     urls[i] = urlList.getString(i); 
     789                    Object feedEntry = urlList.get(i); 
     790                    if (feedEntry instanceof JSONObject) { 
     791                        JSONObject fe = (JSONObject)feedEntry; 
     792                        String url = fe.getString(PROP_FEEDS_FEED_URL); 
     793                        feeds[i] = new Feed( 
     794                                url, 
     795                                fe.optString(PROP_FEEDS_FEED_PUBLIC_URL, url) 
     796                        ); 
     797                    } else { 
     798                        feeds[i] = new Feed(feedEntry.toString()); 
     799                    } 
     800 
     801                    Logger.global.info("feed: " + feeds[i].topic); 
     802                    Logger.global.info("feed's public URL: " + feeds[i].fetchUrl); 
    755803                } 
    756804            } catch (JSONException exc) { 
     
    795843        Node node = Client.start_node(myPort, bs, bsPort, true); 
    796844         
    797         Publisher appl = new Publisher(node, myPort, webPort, urls, privateKey); 
     845        Publisher appl = new Publisher(node, myPort, webPort, feeds, privateKey); 
    798846    } 
    799847}