FeedTool is built on the Rome API and provides the ability to retrieve and manipulate RSS and Atom feeds from within Velocity templates.

The tool works by retrieving a feed from a specified URI and returning it in a ContextFeedWrapper class. The idea wth the wrapper class is to have a convenient location for the provision of convenience methods for feed and feed entry manipulation ... although it could easily be incorporated into a single class.

The tool consists of:

package org.apache.velocity.tools.view.tools;

import java.net.URL;
import java.net.HttpURLConnection;
import java.io.IOException;
import java.net.MalformedURLException;

import sun.misc.BASE64Encoder;

import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.XmlReader;
import com.sun.syndication.fetcher.FeedFetcher;
import com.sun.syndication.fetcher.FetcherException;
import com.sun.syndication.fetcher.impl.FeedFetcherCache;
import com.sun.syndication.fetcher.impl.HashMapFeedInfoCache;
import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher;

/**
 * FeedTool
 * <p>
 * A Velocity View Tool for working with RSS and Atom APIs using Rome
 * </p>
 * @author C.Townson
 */
public class ViewFeedTool {
	/**
	 * The URL of the feed to be fetched by RomeFetcher
	 */
	private URL feedURL;
	
	/**
	 * The FeedObject returned from fetch by RomeFetcher
	 */
	private ContextFeedWrapper feed;

	/**
	 * Default view tool no-arg constructor
	 */
	public ViewFeedTool() {
		// do nothing - View Tools must have public no-arg constructor
	}
	
	/**
	 * Returns the feed located at the specified URL
	 * <p>
	 * This is the core method provided with this tool - use this
	 * from template, rather than any of the other public methods
	 * </p>
	 * TODO overloaded method with authenication parameterss
	 * @param feedURL the url of the feed to retrieve
	 * @return feed The feed object inside a utility wrapper class
	 */
	public ContextFeedWrapper get(String feedURL) {
		// cast String to URL
		this.setFeedURL(feedURL);
		
		// rev up RomeFetcher
		FeedFetcherCache feedInfoCache = HashMapFeedInfoCache.getInstance();
	    FeedFetcher feedFetcher = new HttpURLFeedFetcher(feedInfoCache);
	    
	    // retrieve feed or freak out (silently!)
	    try {
	    	// grab feed
	    	this.setFeed(feedFetcher.retrieveFeed(this.getFeedURL()));
	    } catch (FetcherException fetchx) {
	    	// do something here?
	    } catch (FeedException feedx) {
	    	// do something here?
	    } catch (IOException iox) {
	    	// do something here?
	    } catch (Exception x) {
	    	// do something here?
	    }
	    
	    // return wrapped feed
		return this.getFeed();
	}
	
	/**
	 * Returns the feed located at the specified (password protected) URL
	 * @param feedURL the URL of the feed to retrieve
	 * @param userName the userName to access the protected URL with
	 * @param password the password to access the protected URL with
	 * @return feed the feed object inside a utility wrapper class
	 */
	public ContextFeedWrapper get(String feedURL, String userName, String password) {
		// set feed url
		this.setFeedURL(feedURL);
		
		// construct auth string
		String auth = userName + ":" + password;
		
		// initialize httpcon variable
		HttpURLConnection httpcon = null;
		
		try {
			// create connection
			httpcon = (HttpURLConnection) this.getFeedURL().openConnection();
			
			// encode username:password
			String encoding = new BASE64Encoder().encode(auth.getBytes());
			
			// set request property
			httpcon.setRequestProperty("Authorization","Basic " + encoding);
			
			// connect
			httpcon.connect();
		} catch(IOException iox) {
			// do something here?
		}
		
		// rev up Rome (not using fetcher this time)
		SyndFeedInput input = new SyndFeedInput();
		
		// grab and wrap feed
		try {
			this.setFeed(input.build(new XmlReader(httpcon)));
		} catch(FeedException fx) {
			// do something here?
		} catch(IOException iox) {
			// do something here?
		}
		
		// if we have a connection, disconnect now
		if(httpcon != null) {
			httpcon.disconnect();
		}
		
		// return wrapped feed
		return this.getFeed();
	}

	/**
	 * @return Returns the feed.
	 */
	public ContextFeedWrapper getFeed() {
		return this.feed;
	}

	/**
	 * @param feed The feed to set.
	 */
	public void setFeed(ContextFeedWrapper feed) {
		this.feed = feed;
	}
	
	/**
	 * @param feed The feed to set
	 */
	public void setFeed(SyndFeed feed) {
		this.setFeed(new ContextFeedWrapper(feed));
	}

	/**
	 * @return Returns the feedURL.
	 */
	public URL getFeedURL() {
		return feedURL;
	}

	/**
	 * @param feedURL The feedURL to set.
	 */
	public void setFeedURL(URL feedURL) {
		this.feedURL = feedURL;
	}
	
	/**
	 * Private helper method to covert String to URL
	 * @param url
	 */
	public void setFeedURL(String url) {
		// try to cast URL string to URL
		try {
			this.setFeedURL(new URL(url));
		} catch(MalformedURLException mfux) {
			// do something here?
		} catch (Exception x) {
			// do something here?
		}
	}
}
  • A wrapper class for feeds
package org.apache.velocity.tools.view.tools;

import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndEntry;

/**
 * Feed wrapper for Velocity context providing
 * utility methods for accessing feed object properties
 * 
 * @author Christopher Townson
 *
 */
public class ContextFeedWrapper {
	
	/**
	 * The feed
	 */
	private SyndFeed feed;
	
	/**
	 * An interger containing the total number of items in the retrieved feed
	 */
	private int numberOfEntries;
	
	/**
	 * A SyndEntry object for holding the most recent feed entry
	 */
	private SyndEntry latest;
	
	/**
	 * 
	 * @param feed
	 */
	public ContextFeedWrapper(SyndFeed feed) {
		// assign feed object
		this.setFeed(feed);
		
		// grab number of entries
		this.numberOfEntries = this.getFeed().getEntries().size();
		
		// grab most recent entry (presently: just first entry)
		// TODO make this loop through entries and compare dates
		this.latest = (SyndEntry) this.getFeed().getEntries().get(0);
	}
	
	/**
	 * @return Returns the feed.
	 */
	public SyndFeed getFeed() {
		return this.feed;
	}

	/**
	 * @param feed The feed to set.
	 */
	public void setFeed(SyndFeed feed) {
		this.feed = feed;
	}

	/**
	 * @return Returns the numberOfEntries.
	 */
	public int getNumberOfEntries() {
		return numberOfEntries;
	}

	/**
	 * @param numberOfEntries The numberOfEntries to set.
	 */
	public void setNumberOfEntries(int numberOfEntries) {
		this.numberOfEntries = numberOfEntries;
	}

	/**
	 * @return Returns the latest feed entry.
	 */
	public SyndEntry getLatest() {
		return latest;
	}

	/**
	 * @param latest The entry to set as the latest
	 */
	public void setLatest(SyndEntry latest) {
		this.latest = latest;
	}

}
  • A toolbox.xml entry
<!-- FeedTool: for fetching, parsing, and otherwise handling syndicated feeds of any type -->
<tool>
    <key>FeedTool</key>
    <scope>request</scope>
    <class>com.nature.velocity.tools.view.tools.ViewFeedTool</class>
</tool>
  • No labels