This post originated from an RSS feed registered with Java Buzz
by scot mcphee.
Original Post: del.icio.us jsp taglib
Feed Title: SystemExxception()
Feed URL: http://www.autonomous.org/pebble/systemexxception/rss.xml?category=Java
Feed Description: java design and culture by scot mcphee
Latest Java Buzz Posts
Latest Java Buzz Posts by scot mcphee
Latest Posts From SystemExxception()
Advertisement
I just completed a del.icio.us jsp taglib. Which is currently driving the list of delicious links you should see to the lower left on my blog here.
It is dependent on the current HEAD of the delicious-java project on sourceforge (not the 1.0 release). The delicious-java project provides the basic framework for connecting and parsing the del.icio.us feed. Currently the delicious-java library depends on some jakarta-commons jar files - commons-codec-1.3.jar, commons-httpclient-3.0-alpha2.jar and commons-logging-1.0.4.jar. The biggest headache you might find there is the alpha version of the httpclient, however in Pebble which only uses httpclient v2.0 I replaced it without any noticable deleterious effects so far (touch wood).
Currently in my taglib there is only a single tag, which lists the last x del.icio.us links for a user. The set of links is cached and only reloaded if the list requires updating from del.icio.us, otherwise it is reused from the cache.
The taglib is declared in your jsp page as follows;
<%@ taglib uri="/WEB-INF/delicious.tld" prefix="del" %>
The tag itself looks like this;
<del:listDelicious
username="username"
password="password"
itemcount="20"
itembullet="- "/>
This would display the last 20 links for a user called 'username' - assuming the password is correct of course. Each link would have a "- " prepended to it.
TODO: A couple of things still to do with the taglib:
Optionally turn off the category display.
Show another user's links as well as or instead of the logged in user's links
More tags such as listing the categories only, category and links, list-by-date, etc
Source Listings
Here are the source listings for the three components of the taglib - the .tld file, the Tag itself and the list Cache. I will attach a binary .jar of the compiled classes including the source code and the current version delicious-java that I'm using once I sort out all the javadoc and clean it up a little.
delicious.tld
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>del</shortname>
<tag>
<name>listDelicious</name>
<tagclass>org.autonomous.delicious.tag.DeliciousTaglet</tagclass>
<bodycontent>empty</bodycontent>
<info>del.icio.us tag</info>
<attribute>
<name>username</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>password</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>itemcount</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>itembullet</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>
org.autonomous.delicious.tag.DeliciousTaglet
/**
* This is a tag lib that displays a configurable number of recent posts from Delicious
* 'social bookmark' project.(see http://del.icio.us/ for information).
* Requires the Delicious-Java project from SourceForge;
* http://sourceforge.net/projects/delicious-java/
*
* Copyright Scot Mcphee 2004. GPL licence applies.
*
* DeliciousTaglet.java
* by Scot Mcphee Created on Oct 15, 2004, 9:15:38 PM.
*/
package org.autonomous.delicious.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.tagext.TagSupport;
/**
* @author scot mcphee
*/
public class DeliciousTaglet extends TagSupport {
/**
* Manages the delicious connection and caches the results.
*/
private static DeliciousBookmarkCache mCache = null;
private String username;
private String password;
private int itemcount;
private String itembullet;
/**
* Default constructor.
*/
public DeliciousTaglet() {
super();
}
/**
* @see javax.servlet.jsp.tagext.Tag#doEndTag()
*/
public int doEndTag() throws JspException {
try {
DeliciousBookmarkCache cache = getCache();
cache.setItembullet(getItembullet());
cache.setPosts(getItemcount());
pageContext.getOut().write(cache.listRecentPostsHtml());
} catch (java.io.IOException e) {
throw new JspTagException("IO Error: " + e.getMessage());
}
return EVAL_PAGE;
}
/**
* Gets the cache, if null, initialises it. The bookmarks are cached in
* order to prevent del.icio.us service from being overloaded - if you add a
* bookmark to del.icio.us the bookmark list will be reloaded.
*
* @return
*/
private synchronized DeliciousBookmarkCache getCache() {
if (mCache == null) {
mCache = new DeliciousBookmarkCache(getItemcount(), getUsername(),
getPassword());
}
return mCache;
}
/**
* @return Returns the itemcount.
*/
public int getItemcount() {
return itemcount;
}
/**
* @param itemcount
* The itemcount to set.
*/
public void setItemcount(int itemcount) {
this.itemcount = itemcount;
}
/**
* @return Returns the password.
*/
public String getPassword() {
return password;
}
/**
* @param password
* The password to set.
*/
public void setPassword(String password) {
this.password = password
8
;
}
1ff8
/**
* @return Returns the username.
*/
public String getUsername() {
return username;
}
/**
* @param username
* The username to set.
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return Returns the itembullet.
*/
public String getItembullet() {
return itembullet;
}
/**
* @param itembullet
* The itembullet to set.
*/
public void setItembullet(String itembullet) {
this.itembullet = itembullet;
}
}
org.autonomous.delicious.tag.DeliciousBookmarkCache
/**
* This is a tag lib that displays a configurable number of recent posts from Delicious
* 'social bookmark' project.(see http://del.icio.us/ for information).
* Requires the Delicious-Java project from SourceForge;
* http://sourceforge.net/projects/delicious-java/
*
* Copyright Scot Mcphee 2004. GPL licence applies.
*
* DeliciousBookmarkCache.java
* by Scot Mcphee Created on Oct 15, 2004.
*/
package org.autonomous.delicious.tag;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import del.icio.us.Delicious;
import del.icio.us.beans.DeliciousDate;
import del.icio.us.beans.Post;
/**
* This class wraps a delicous connection and outputs delicous bookmarks.
*
* @author scot mcphee
*/
public class DeliciousBookmarkCache {
/**
* Replace characters having special meaning inside HTML tags with their
* escaped equivalents, using character entities such as <tt>'&'</tt>.
*/
public static String forHTMLTag(String aTagFragment) {
final StringBuffer result = new StringBuffer();
final StringCharacterIterator iterator = new StringCharacterIterator(
aTagFragment);
char character = iterator.current();
while (character != StringCharacterIterator.DONE) {
if (character == '<') {
result.append("<");
} else if (character == '>') {
result.append(">");
} else if (character == '\"') {
result.append(""");
} else if (character == '\'') {
result.append("'");
} else if (character == '\\') {
result.append("\");
} else if (character == '&') {
result.append("&");
} else {
//the char is not a special one
//add it to the result as is
result.append(character);
}
character = iterator.next();
}
return result.toString();
}
/**
* Synonym for <tt>URLEncoder.encode(String, "UTF-8")</tt>.
*/
public static String forURL(String aURLFragment) {
String result = null;
try {
result = URLEncoder.encode(aURLFragment, "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException("UTF-8 not supported", ex);
}
return result;
}
private String itembullet = null;
private DeliciousDate mDate;
private final Delicious mDelicious;
private final String mDeliciousUrl = "http://del.icio.us/";
private List mList = Collections.synchronizedList(new ArrayList());
private final String mPassword;
private int mPosts = 10;
private final String mUsername;
public DeliciousBookmarkCache(int posts, String username, String password) {
mUsername = username;
mPassword = password;
if (posts > 0) {
mPosts = posts;
}
mDelicious = new Delicious(mUsername, mPassword);
reloadIfNewer(mPosts);
}
/**
* @param buf
* @param p
*/
private void doEntry(StringBuffer buf, Post p) {
if (getItembullet() != null) {
buf.append(getItembullet());
}
buf.append("<a href=\"");
buf.append(p.getHref());
buf.append("\" ");
if (p.getExtended() != null) {
buf.append("title=\"");
buf.append(forHTMLTag(p.getExtended()));
buf.append(" - ");
buf.append(forHTMLTag(p.getTimeAsDate().toString()));
buf.append("\" ");
} else {
buf.append("title=\"posted to del.icio.us on ");
buf.append(forHTMLTag(p.getTimeAsDate().toString()));
buf.append("\" ");
}
buf.append("target=\"_new\">");
buf.append(forHTMLTag(p.getDescription()));
buf.append("</a> ");
doTags(buf, p);
buf.append("<br/>\n");
}
private void doTags(StringBuffer buf, Post p) {
buf.append("[in ");
String[] tags = p.getTag().split(" ");
for (int i = 0; i < tags.length; i++) {
String s = tags[i];
buf.append("<a href=\"");
buf.append(mDeliciousUrl);
buf.append(mUsername);
buf.append("/");
buf.append(forURL(s));
buf.append("/");
buf.append("\" target=\"_new\">");
buf.append(forHTMLTag(s));
buf.append("</a>, ");
}
buf.delete(buf.length() - 2, buf.length());
buf.append("]");
}
/**
* @param buf
*/
private void doTitle(StringBuffer buf) {
buf.append("<p><b>");
buf.append("<img src=\"" + mDeliciousUrl
+ "delicious.gif\" height=10 width=10 /> ");
buf.append("<a href=\"");
buf.append(mDeliciousUrl);
buf.append(mUsername);
buf.append("/\">del.icio.us / ");
buf.append(mUsername);
buf.append("</a> (last ");
buf.append(mPosts);
buf.append(")");
buf.append("</b></p>\n");
}
/**
* @return Returns the itembullet.
*/
public String getItembullet() {
return itembullet;
}
/**
* @return Returns the posts.
*/
public int getPosts() {
return mPosts;
}
/**
* Output a simple HTML list of the last few delicious entries.
*
* @return
*/
public String listRecentPostsHtml() {
StringBuffer buf = new StringBuffer();
reloadIfNewer(mPosts);
Iterator iter = mList.iterator();
buf.append("\n<div class='small'>");
doTitle(buf);
while (iter.hasNext()) {
Post p = (Post) iter.next();
doEntry(buf, p);
}
buf.append("</div>\n\n");
return buf.toString();
}
/**
* See if there's any newer date or posts for the latest data on del.icio.us
* as compared to the last cached list and date.
*/
private synchronized boolean reloadIfNewer(int num) {
DeliciousDate d = (DeliciousDate) mDelicious.getDatesWithPost(null)
.get(0);
if ((mList == null) || (mDate == null)
|| (!d.getDate().equals(mDate.getDate()))
|| (d.getCount() != mDate.getCount())) {
System.out.println("Initialising
8
the date
1b3f
!!!");
List aList = mDelicious.getRecentPosts(null, num);
int i = mDelicious.getHttpResult();
if (i > 199 && i < 300) {
mList = Collections.synchronizedList(aList);
mDate = d;
return true;
}
}
return false;
}
/**
* @param itembullet
* The itembullet to set.
*/
public void setItembullet(String itembullet) {
this.itembullet = itembullet;
}
/**
* @param posts
* The posts to set.
*/
public void setPosts(int posts) {
if (posts <= 0) {
posts = 1;
}
if (posts != mPosts) {
mList = null;
}
mPosts = posts;
}
}
Read: del.icio.us jsp taglib