You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2005/10/21 23:46:28 UTC

svn commit: r327589 [45/72] - in /incubator/roller/branches/roller_1.x: ./ contrib/ contrib/lib/ contrib/plugins/ contrib/plugins/src/ contrib/plugins/src/org/ contrib/plugins/src/org/roller/ contrib/plugins/src/org/roller/presentation/ contrib/plugins...

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/Utilities.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/Utilities.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/Utilities.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/Utilities.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,1123 @@
+package org.roller.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.security.MessageDigest;
+import java.util.Date;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * General purpose utilities. 
+ * 
+ * <pre>
+ * Includes TextToHTML methods dondated by Erik Thauvin - "Donated to the 
+ * Roller Weblogger project for publication under the terms of the Roller 
+ * Software License. 
+ * Copyright (C) 2002-2003 by Erik C. Thauvin (erik@thauvin.net).
+ * All rights reserved.
+ * </pre>
+ * 
+ * @author David M Johnson
+ * @author Lance Lavandowska
+ * @author Matt Raible (added encryption methods)
+ */
+public class Utilities
+{
+    /** The <code>Log</code> instance for this class. */
+    private static Log mLogger = LogFactory.getLog(Utilities.class);
+    
+    /** Pattern for matching HTML links */
+    private static Pattern mLinkPattern = 
+        Pattern.compile("<a href=.*?>", Pattern.CASE_INSENSITIVE);
+    
+    /**
+     * Utility methods for calling StringUtils since it cannot be 
+     * instantiated and Utilties can.
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return StringUtils.isNotEmpty(str);
+    }
+    
+    //------------------------------------------------------------------------
+    /** Strip jsessionid off of a URL */
+    public static String stripJsessionId( String url )
+    {
+        // Strip off jsessionid found in referer URL
+        int startPos = url.indexOf(";jsessionid=");
+        if ( startPos != -1 )
+        {
+            int endPos = url.indexOf("?",startPos);
+            if ( endPos == -1 )
+            {
+                url = url.substring(0,startPos);   
+            }
+            else
+            {
+                url = url.substring(0,startPos)
+                    + url.substring(endPos,url.length());   
+            }
+        }
+        return url;
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * Escape, but do not replace HTML.
+     * The default behaviour is to escape ampersands.
+     */
+    public static String escapeHTML(String s)
+    {
+        return escapeHTML(s, true);
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * Escape, but do not replace HTML.
+     * @param escapseAmpersand Optionally escape
+     * ampersands (&amp;).
+     */
+    public static String escapeHTML(String s, boolean escapeAmpersand)
+    {
+        // got to do amp's first so we don't double escape
+        if (escapeAmpersand)
+        {
+            s = stringReplace(s, "&", "&amp;");
+        }
+        s = stringReplace(s, "&nbsp;", " ");
+        s = stringReplace(s, "\"", "&quot;");
+        s = stringReplace(s, "<", "&lt;");
+        s = stringReplace(s, ">", "&gt;");
+        return s;
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * Remove occurences of html, defined as any text
+     * between the characters "&lt;" and "&gt;".  Replace
+     * any HTML tags with a space.
+     */
+    public static String removeHTML(String str)
+    {
+        return removeHTML(str, true);
+    }
+    
+    /**
+     * Remove occurences of html, defined as any text
+     * between the characters "&lt;" and "&gt;". 
+     * Optionally replace HTML tags with a space.
+     * 
+     * @param str
+     * @param addSpace
+     * @return
+     */
+    public static String removeHTML(String str, boolean addSpace)
+    {
+        if (str == null) return "";
+        StringBuffer ret = new StringBuffer(str.length());
+        int start = 0;
+        int beginTag = str.indexOf("<");
+        int endTag = 0;
+        if (beginTag == -1)
+            return str;
+
+        while (beginTag >= start)
+        {
+            if (beginTag > 0)
+            {
+                ret.append(str.substring(start, beginTag));
+                
+                // replace each tag with a space (looks better)
+                if (addSpace) ret.append(" ");
+            }
+            endTag = str.indexOf(">", beginTag);
+            
+            // if endTag found move "cursor" forward
+            if (endTag > -1)
+            {
+                start = endTag + 1;
+                beginTag = str.indexOf("<", start);
+            }
+            // if no endTag found, get rest of str and break
+            else
+            {
+                ret.append(str.substring(beginTag));
+                break;
+            }
+        }
+        // append everything after the last endTag
+        if (endTag > -1 && endTag + 1 < str.length())
+        {
+            ret.append(str.substring(endTag + 1));
+        }
+        return ret.toString().trim();
+    }
+
+    //------------------------------------------------------------------------
+    /** Run both removeHTML and escapeHTML on a string.
+     * @param s String to be run through removeHTML and escapeHTML.
+     * @return String with HTML removed and HTML special characters escaped.
+     */
+    public static String removeAndEscapeHTML( String s )
+    {
+        if ( s==null ) return "";
+        else return Utilities.escapeHTML( Utilities.removeHTML(s) );
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * Autoformat.
+     */
+    public static String autoformat(String s)
+    {
+        String ret = StringUtils.replace(s, "\n", "<br />");
+        return ret;
+    }
+    
+    //------------------------------------------------------------------------
+    /**
+     * Format date in ISO-8601 format.
+     */
+    public static String formatIso8601Date(Date d)
+    {
+        return DateUtil.formatIso8601(d);
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * Format date in ISO-8601 format.
+     */
+    public static String formatIso8601Day(Date d)
+    {
+        return DateUtil.formatIso8601Day(d);
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * Return a date in RFC-822 format.
+     */
+    public static String formatRfc822Date(Date date) 
+    {
+        return DateUtil.formatRfc822(date);
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * Return a date in RFC-822 format.
+     */
+    public static String format8charsDate(Date date) 
+    {
+        return DateUtil.format8chars(date);
+    }
+
+	//------------------------------------------------------------------------
+	/**
+	 * Replaces occurences of non-alphanumeric characters with an underscore.
+	 */
+	public static String replaceNonAlphanumeric(String str)
+	{
+		return replaceNonAlphanumeric(str, '_');
+	}
+
+	//------------------------------------------------------------------------
+	/**
+	 * Replaces occurences of non-alphanumeric characters with a
+	 * supplied char.
+	 */
+	public static String replaceNonAlphanumeric(String str, char subst)
+	{
+		StringBuffer ret = new StringBuffer(str.length());
+		char[] testChars = str.toCharArray();
+		for (int i = 0; i < testChars.length; i++)
+		{
+			if (Character.isLetterOrDigit(testChars[i]))
+			{
+				ret.append(testChars[i]);
+			}
+			else
+			{
+				ret.append( subst );
+			}
+		}
+		return ret.toString();
+	}
+
+    //------------------------------------------------------------------------
+    /**
+     * Remove occurences of non-alphanumeric characters.
+     */
+    public static String removeNonAlphanumeric(String str)
+    {
+        StringBuffer ret = new StringBuffer(str.length());
+        char[] testChars = str.toCharArray();
+        for (int i = 0; i < testChars.length; i++)
+        {
+            // MR: Allow periods in page links
+            if (Character.isLetterOrDigit(testChars[i]) ||
+                testChars[i] == '.')
+            {
+                ret.append(testChars[i]);
+            }
+        }
+        return ret.toString();
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * @param pathArray
+     * @return
+     */
+    public static String stringArrayToString(String[] stringArray, String delim)
+    {
+        String ret = "";
+        for (int i = 0; i < stringArray.length; i++)
+        {
+            if (ret.length() > 0)
+                ret = ret + delim + stringArray[i];
+            else
+                ret = stringArray[i];
+        }
+        return ret;
+    }
+    
+    //------------------------------------------------------------------------
+    /**
+     * Replace occurrences of str1 in string str with str2 
+     */
+    public static String stringReplace(String str, String str1, String str2)
+    {
+        String ret = StringUtils.replace(str,str1,str2);
+        return ret;
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * Replace occurrences of str1 in string str with str2
+     * @param str String to operate on 
+     * @param str1 String to be replaced
+     * @param str2 String to be used as replacement
+     * @param maxCount Number of times to replace, 0 for all
+     */
+    public static String stringReplace(
+        String str,
+        String str1,
+        String str2,
+        int maxCount)
+    {
+        String ret = StringUtils.replace(str,str1,str2,maxCount);
+        return ret;
+    }
+
+    //--------------------------------------------------------------------------
+    /** Convert string to string array. */
+    public static String[] stringToStringArray(String instr, String delim)
+        throws NoSuchElementException, NumberFormatException
+    {
+        StringTokenizer toker = new StringTokenizer(instr, delim);
+        String stringArray[] = new String[toker.countTokens()];
+        int i = 0;
+
+        while (toker.hasMoreTokens())
+        {
+            stringArray[i++] = toker.nextToken();
+        }
+        return stringArray;
+    }
+
+    //--------------------------------------------------------------------------
+    /** Convert string to integer array. */
+    public static int[] stringToIntArray(String instr, String delim)
+        throws NoSuchElementException, NumberFormatException
+    {
+        StringTokenizer toker = new StringTokenizer(instr, delim);
+        int intArray[] = new int[toker.countTokens()];
+        int i = 0;
+
+        while (toker.hasMoreTokens())
+        {
+            String sInt = toker.nextToken();
+            int nInt = Integer.parseInt(sInt);
+            intArray[i++] = new Integer(nInt).intValue();
+        }
+        return intArray;
+    }
+
+    //-------------------------------------------------------------------
+    /** Convert integer array to a string. */
+    public static String intArrayToString(int[] intArray)
+    {
+        String ret = "";
+        for (int i = 0; i < intArray.length; i++)
+        {
+            if (ret.length() > 0)
+                ret = ret + "," + Integer.toString(intArray[i]);
+            else
+                ret = Integer.toString(intArray[i]);
+        }
+        return ret;
+    }
+
+    //------------------------------------------------------------------------
+    public static void copyFile(File from, File to) throws IOException
+    {
+        InputStream in = null;
+        OutputStream out = null;
+
+        try
+        {
+            in = new FileInputStream(from);
+        }
+        catch (IOException ex)
+        {
+            throw new IOException(
+                "Utilities.copyFile: opening input stream '"
+                    + from.getPath()
+                    + "', "
+                    + ex.getMessage());
+        }
+
+        try
+        {
+            out = new FileOutputStream(to);
+        }
+        catch (Exception ex)
+        {
+            try
+            {
+                in.close();
+            }
+            catch (IOException ex1)
+            {
+            }
+            throw new IOException(
+                "Utilities.copyFile: opening output stream '"
+                    + to.getPath()
+                    + "', "
+                    + ex.getMessage());
+        }
+
+        copyInputToOutput(in, out, from.length());
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * Utility method to copy an input stream to an output stream.
+     * Wraps both streams in buffers. Ensures right numbers of bytes copied.
+     */
+    public static void copyInputToOutput(
+        InputStream input,
+        OutputStream output,
+        long byteCount)
+        throws IOException
+    {
+        int bytes;
+        long length;
+
+        BufferedInputStream in = new BufferedInputStream(input);
+        BufferedOutputStream out = new BufferedOutputStream(output);
+
+        byte[] buffer;
+        buffer = new byte[8192];
+
+        for (length = byteCount; length > 0;)
+        {
+            bytes = (int) (length > 8192 ? 8192 : length);
+
+            try
+            {
+                bytes = in.read(buffer, 0, bytes);
+            }
+            catch (IOException ex)
+            {
+                try
+                {
+                    in.close();
+                    out.close();
+                }
+                catch (IOException ex1)
+                {
+                }
+                throw new IOException(
+                    "Reading input stream, " + ex.getMessage());
+            }
+
+            if (bytes < 0)
+                break;
+
+            length -= bytes;
+
+            try
+            {
+                out.write(buffer, 0, bytes);
+            }
+            catch (IOException ex)
+            {
+                try
+                {
+                    in.close();
+                    out.close();
+                }
+                catch (IOException ex1)
+                {
+                }
+                throw new IOException(
+                    "Writing output stream, " + ex.getMessage());
+            }
+        }
+
+        try
+        {
+            in.close();
+            out.close();
+        }
+        catch (IOException ex)
+        {
+            throw new IOException("Closing file streams, " + ex.getMessage());
+        }
+    }
+
+    //------------------------------------------------------------------------
+    public static void copyInputToOutput(
+        InputStream input,
+        OutputStream output)
+        throws IOException
+    {
+        BufferedInputStream in = new BufferedInputStream(input);
+        BufferedOutputStream out = new BufferedOutputStream(output);
+        byte buffer[] = new byte[8192];
+        for (int count = 0; count != -1;)
+        {
+            count = in.read(buffer, 0, 8192);
+            if (count != -1)
+                out.write(buffer, 0, count);
+        }
+
+        try
+        {
+            in.close();
+            out.close();
+        }
+        catch (IOException ex)
+        {
+            throw new IOException("Closing file streams, " + ex.getMessage());
+        }
+    }
+    
+    /**
+     * Encode a string using algorithm specified in web.xml and return the
+     * resulting encrypted password. If exception, the plain credentials
+     * string is returned
+     *
+     * @param password Password or other credentials to use in authenticating
+     *        this username
+     * @param algorithm Algorithm used to do the digest
+     *
+     * @return encypted password based on the algorithm.
+     */
+    public static String encodePassword(String password, String algorithm) 
+    {
+        byte[] unencodedPassword = password.getBytes();
+
+        MessageDigest md = null;
+
+        try 
+        {
+            // first create an instance, given the provider
+            md = MessageDigest.getInstance(algorithm);
+        } 
+        catch (Exception e) 
+        {
+            mLogger.error("Exception: " + e);
+            return password;
+        }
+
+        md.reset();
+
+        // call the update method one or more times
+        // (useful when you don't know the size of your data, eg. stream)
+        md.update(unencodedPassword);
+
+        // now calculate the hash
+        byte[] encodedPassword = md.digest();
+
+        StringBuffer buf = new StringBuffer();
+
+        for (int i = 0; i < encodedPassword.length; i++) 
+        {
+            if ((encodedPassword[i] & 0xff) < 0x10) 
+            {
+                buf.append("0");
+            }
+
+            buf.append(Long.toString(encodedPassword[i] & 0xff, 16));
+        }
+
+        return buf.toString();
+    }
+
+    /**
+     * Encode a string using Base64 encoding. Used when storing passwords
+     * as cookies.
+     *
+     * This is weak encoding in that anyone can use the decodeString
+     * routine to reverse the encoding.
+     *
+     * @param str
+     * @return String
+     * @throws IOException
+     */
+    public static String encodeString(String str) throws IOException 
+    {
+        sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
+        String encodedStr = encoder.encodeBuffer(str.getBytes());
+
+        return (encodedStr.trim());
+    }
+
+    /**
+     * Decode a string using Base64 encoding.
+     *
+     * @param str
+     * @return String
+     * @throws IOException
+     */
+    public static String decodeString(String str) throws IOException 
+    {
+        sun.misc.BASE64Decoder dec = new sun.misc.BASE64Decoder();
+        String value = new String(dec.decodeBuffer(str));
+
+        return (value);
+    }
+    
+    /**
+     * Strips HTML and truncates.
+     */
+    public static String truncate(
+            String str, int lower, int upper, String appendToEnd)
+    {
+        // strip markup from the string
+        String str2 = removeHTML(str, false);
+        
+        // quickly adjust the upper if it is set lower than 'lower'
+        if (upper < lower) 
+        {
+            upper = lower;
+        }       
+        
+        // now determine if the string fits within the upper limit
+        // if it does, go straight to return, do not pass 'go' and collect $200
+        if(str2.length() > upper) 
+        {
+            // the magic location int
+            int loc;
+        
+            // first we determine where the next space appears after lower
+            loc = str2.lastIndexOf(' ', upper);
+            
+            // now we'll see if the location is greater than the lower limit
+            if(loc >= lower) 
+            {
+                // yes it was, so we'll cut it off here
+                str2 = str2.substring(0, loc);
+            } 
+            else 
+            {
+                // no it wasnt, so we'll cut it off at the upper limit
+                str2 = str2.substring(0, upper);
+                loc = upper;
+            }
+           
+            // the string was truncated, so we append the appendToEnd String                
+            str2 = str2 + appendToEnd;
+        }
+        
+        return str2;
+    }
+    
+    /**
+     * This method based on code from the String taglib at Apache Jakarta:
+     * http://cvs.apache.org/viewcvs/jakarta-taglibs/string/src/org/apache/taglibs/string/util/StringW.java?rev=1.16&content-type=text/vnd.viewcvs-markup
+     * Copyright (c) 1999 The Apache Software Foundation.
+     * Author: Henri Yandell bayard@generationjava.com
+     * 
+     * @param str
+     * @param lower
+     * @param upper
+     * @param appendToEnd
+     * @return
+     */
+    public static String truncateNicely(String str, int lower, int upper, String appendToEnd)
+    {
+        // strip markup from the string
+        String str2 = removeHTML(str, false);
+        boolean diff = (str2.length() < str.length());
+        
+        // quickly adjust the upper if it is set lower than 'lower'
+        if(upper < lower) {
+            upper = lower;
+        }       
+        
+        // now determine if the string fits within the upper limit
+        // if it does, go straight to return, do not pass 'go' and collect $200
+        if(str2.length() > upper) {
+            // the magic location int
+            int loc;
+        
+            // first we determine where the next space appears after lower
+            loc = str2.lastIndexOf(' ', upper);
+            
+            // now we'll see if the location is greater than the lower limit
+            if(loc >= lower) {
+                // yes it was, so we'll cut it off here
+                str2 = str2.substring(0, loc);
+            } else {
+                // no it wasnt, so we'll cut it off at the upper limit
+                str2 = str2.substring(0, upper);
+                loc = upper;
+            }
+            
+            // HTML was removed from original str
+            if (diff)
+            {
+                
+                // location of last space in truncated string
+                loc = str2.lastIndexOf(' ', loc);
+                
+                // get last "word" in truncated string (add 1 to loc to eliminate space
+                String str3 = str2.substring(loc+1);
+                
+                // find this fragment in original str, from 'loc' position
+                loc = str.indexOf(str3, loc) + str3.length();
+                
+                // get truncated string from original str, given new 'loc'
+                str2 = str.substring(0, loc);
+                
+                // get all the HTML from original str after loc
+                str3 = extractHTML(str.substring(loc));
+                
+                // remove any tags which generate visible HTML
+                // This call is unecessary, all HTML has already been stripped
+                //str3 = removeVisibleHTMLTags(str3);
+                
+                // append the appendToEnd String and
+                // add extracted HTML back onto truncated string
+                str = str2 + appendToEnd + str3;
+            }
+            else
+            {
+                // the string was truncated, so we append the appendToEnd String                
+                str = str2 + appendToEnd;
+            }
+    
+        }
+        
+        return str;
+    }
+    
+    public static String truncateText(String str, int lower, int upper, String appendToEnd)
+    {
+        // strip markup from the string
+        String str2 = removeHTML(str, false);
+        boolean diff = (str2.length() < str.length());
+        
+        // quickly adjust the upper if it is set lower than 'lower'
+        if(upper < lower) {
+            upper = lower;
+        }       
+        
+        // now determine if the string fits within the upper limit
+        // if it does, go straight to return, do not pass 'go' and collect $200
+        if(str2.length() > upper) {
+            // the magic location int
+            int loc;
+        
+            // first we determine where the next space appears after lower
+            loc = str2.lastIndexOf(' ', upper);
+            
+            // now we'll see if the location is greater than the lower limit
+            if(loc >= lower) {
+                // yes it was, so we'll cut it off here
+                str2 = str2.substring(0, loc);
+            } else {
+                // no it wasnt, so we'll cut it off at the upper limit
+                str2 = str2.substring(0, upper);
+                loc = upper;
+            }            
+            // the string was truncated, so we append the appendToEnd String                
+            str = str2 + appendToEnd;
+        }        
+        return str;
+    }
+    
+    /**
+	 * @param str
+	 * @return
+	 */
+	private static String stripLineBreaks(String str)
+	{
+        // TODO: use a string buffer, ignore case !
+		str = str.replaceAll("<br>", "");
+        str = str.replaceAll("<br/>", "");
+        str = str.replaceAll("<br />", "");
+        str = str.replaceAll("<p></p>", "");
+        str = str.replaceAll("<p/>","");
+        str = str.replaceAll("<p />","");
+        return str;
+	}
+	
+    /**
+     * Need need to get rid of any user-visible HTML tags once all text has been 
+     * removed such as &lt;BR&gt;. This sounds like a better approach than removing 
+     * all HTML tags and taking the chance to leave some tags un-closed.
+     * 
+     * WARNING: this method has serious performance problems a
+     * 
+     * @author Alexis Moussine-Pouchkine <al...@france.sun.com>
+     * @author Lance Lavandowska
+     * @param str the String object to modify
+     * @return the new String object without the HTML "visible" tags
+     */
+    private static String removeVisibleHTMLTags(String str) 
+    {
+        str = stripLineBreaks(str);
+        StringBuffer result = new StringBuffer(str);
+        StringBuffer lcresult = new StringBuffer(str.toLowerCase());
+
+        // <img should take care of smileys
+        String[] visibleTags = {"<img"}; // are there others to add?        
+        int stringIndex;
+        for ( int j = 0 ;  j < visibleTags.length ; j++ ) {
+            while ( (stringIndex = lcresult.indexOf(visibleTags[j])) != -1 ) {
+                if ( visibleTags[j].endsWith(">") )  {
+                    result.delete(stringIndex, stringIndex+visibleTags[j].length() );
+                    lcresult.delete(stringIndex, stringIndex+visibleTags[j].length() );
+                } else {
+                    // need to delete everything up until next closing '>', for <img for instance
+                    int endIndex = result.indexOf(">", stringIndex);
+                    if (endIndex > -1) {
+                        // only delete it if we find the end!  If we don't the HTML may be messed up, but we
+                        // can't safely delete anything.
+                        result.delete(stringIndex, endIndex + 1 );
+                        lcresult.delete(stringIndex, endIndex + 1 );
+                    }
+                }
+            }
+        }
+
+        // TODO:  This code is buggy by nature.  It doesn't deal with nesting of tags properly.
+        // remove certain elements with open & close tags
+        String[] openCloseTags = {"li", "a", "div", "h1", "h2", "h3", "h4"}; // more ?
+        for (int j = 0; j < openCloseTags.length; j++)
+        {
+            // could this be better done with a regular expression?
+            String closeTag = "</"+openCloseTags[j]+">";
+            int lastStringIndex = 0;
+            while ( (stringIndex = lcresult.indexOf( "<"+openCloseTags[j], lastStringIndex)) > -1)
+            {
+                lastStringIndex = stringIndex;
+                // Try to find the matching closing tag  (ignores possible nesting!)
+                int endIndex = lcresult.indexOf(closeTag, stringIndex);
+                if (endIndex > -1) {
+                    // If we found it delete it.
+                    result.delete(stringIndex, endIndex+closeTag.length());
+                    lcresult.delete(stringIndex, endIndex+closeTag.length());
+                } else {
+                    // Try to see if it is a self-closed empty content tag, i.e. closed with />.
+                    endIndex = lcresult.indexOf(">", stringIndex);
+                    int nextStart = lcresult.indexOf("<", stringIndex+1);
+                    if (endIndex > stringIndex && lcresult.charAt(endIndex-1) == '/' && (endIndex < nextStart || nextStart == -1)) {
+                        // Looks like it, so remove it.
+                        result.delete(stringIndex, endIndex + 1);
+                        lcresult.delete(stringIndex, endIndex + 1);
+
+                    }
+                }
+            }
+        }
+        
+        return result.toString();
+    }
+
+	/**
+     * Extract (keep) JUST the HTML from the String.
+     * @param str
+     * @return
+     */
+    public static String extractHTML(String str)
+    {
+        if (str == null) return "";
+        StringBuffer ret = new StringBuffer(str.length());
+        int start = 0;
+        int beginTag = str.indexOf("<");
+        int endTag = 0;
+        if (beginTag == -1)
+            return str;
+
+        while (beginTag >= start)
+        {
+            endTag = str.indexOf(">", beginTag);
+            
+            // if endTag found, keep tag
+            if (endTag > -1)
+            {
+                ret.append( str.substring(beginTag, endTag+1) );
+                
+                // move start forward and find another tag
+                start = endTag + 1;
+                beginTag = str.indexOf("<", start);
+            }
+            // if no endTag found, break
+            else
+            {
+                break;
+            }
+        }
+        return ret.toString();
+    }
+
+    
+    public static String hexEncode(String str)
+    {
+        if (StringUtils.isEmpty(str)) return str;
+        
+        return RegexUtil.encode(str);
+    }
+    
+    public static String encodeEmail(String str)
+    {
+        return RegexUtil.encodeEmail(str);
+    }
+
+    /**
+     * Converts a character to HTML or XML entity.
+     *
+     * @param ch The character to convert.
+     * @param xml Convert the character to XML if set to true.
+     * @author Erik C. Thauvin
+     *
+     * @return The converted string.
+     */
+    public static final String charToHTML(char ch, boolean xml)
+    {
+        int c;
+
+        // Convert left bracket
+        if (ch == '<')
+        {
+            return ("&lt;");
+        }
+
+        // Convert left bracket
+        else if (ch == '>')
+        {
+            return ("&gt;");
+        }
+
+        // Convert ampersand
+        else if (ch == '&')
+        {
+            return ("&amp;");
+        }
+
+        // Commented out to eliminate redundant numeric character codes (ROL-507)
+        // High-ASCII character
+        //else if (ch >= 128)
+        //{
+            //c = ch;
+            //return ("&#" + c + ';');
+        //}
+
+        // Convert double quote
+        else if (xml && (ch == '"'))
+        {
+            return ("&quot;");
+        }
+
+        // Convert single quote
+        else if (xml && (ch == '\''))
+        {
+            return ("&#39;");
+        }
+
+        // No conversion
+        else
+        {
+            // Return character as string
+            return (String.valueOf(ch));
+        }
+    }
+
+    /**
+     * Converts a text string to HTML or XML entities.
+     *
+     * @author Erik C. Thauvin
+     * @param text The string to convert.
+     * @param xml Convert the string to XML if set to true.
+     *
+     * @return The converted string.
+     */
+    public static final String textToHTML(String text, boolean xml)
+    {
+        final StringBuffer html = new StringBuffer();
+
+        // Loop thru each characters of the text
+        for (int i = 0; i < text.length(); i++)
+        {
+            // Convert character to HTML/XML
+            html.append(charToHTML(text.charAt(i), xml));
+        }
+
+        // Return HTML/XML string
+        return html.toString();
+    }
+
+    /**
+     * Converts a text string to HTML or XML entities.
+     *
+     * @param text The string to convert.
+     * @author Erik C. Thauvin
+     * @return The converted string.
+     */
+    public static final String textToHTML(String text)
+    {
+        return textToHTML(text, false);
+    }
+
+    /**
+     * Converts a text string to XML entities.
+     *
+     * @param text The string to convert.
+     * @author Erik C. Thauvin
+     * @return The converted string.
+     */
+    public static final String textToXML(String text)
+    {
+        return textToHTML(text, true);
+    }
+
+    /**
+     * Converts a text string to HTML or XML entities.
+     * @param text The string to convert.
+     * @return The converted string.
+     */
+    public static final String textToCDATA(String text)
+    {
+        final StringBuffer html = new StringBuffer();
+
+        // Loop thru each characters of the text
+        for (int i = 0; i < text.length(); i++)
+        {
+            // Convert character to HTML/XML
+            html.append(charToCDATA(text.charAt(i)));
+        }
+
+        // Return HTML/XML string
+        return html.toString();
+    }
+
+    /**
+     * Converts a character to CDATA character.
+     * @param ch The character to convert.
+     * @return The converted string.
+     */
+    public static final String charToCDATA(char ch)
+    {
+        int c;
+
+        if (ch >= 128)
+        {
+            c = ch;
+
+            return ("&#" + c + ';');
+        }
+
+        // No conversion
+        else
+        {
+            // Return character as string
+            return (String.valueOf(ch));
+        }
+    }
+    
+    public static final String encode(String s) 
+    {
+        try 
+        {
+            return URLEncoder.encode(s, "utf-8");
+        } 
+        catch (UnsupportedEncodingException e) 
+        {
+            return s;
+        }
+    }
+
+    /**
+     * @param string
+     * @return
+     */
+    public static int stringToInt(String string)
+    {
+        try
+        {
+            return Integer.valueOf(string).intValue();
+        }
+        catch (NumberFormatException e)
+        {
+            mLogger.debug("Invalid Integer:" + string);
+        }
+        return 0;
+    }
+    
+    /** 
+     * Code (stolen from Pebble) to add rel="nofollow" string to all links in HTML.
+     */
+    public static String addNofollow(String html) 
+    {
+        if (html == null || html.length() == 0) 
+        {
+            return html;
+        }
+        Matcher m = mLinkPattern.matcher(html);
+        StringBuffer buf = new StringBuffer();
+        while (m.find()) 
+        {
+            int start = m.start();
+            int end = m.end();
+            String link = html.substring(start, end);
+            buf.append(html.substring(0, start));
+            if (link.indexOf("rel=\"nofollow\"") == -1) 
+            {
+                buf.append(
+                    link.substring(0, link.length() - 1) + " rel=\"nofollow\">");
+            } 
+            else 
+            {
+                buf.append(link);
+            }            
+            html = html.substring(end, html.length());
+            m = mLinkPattern.matcher(html);
+        }
+        buf.append(html);
+        return buf.toString();
+    }
+    
+    public static String unescapeHTML(String str) 
+    {
+        return StringEscapeUtils.unescapeHtml(str);
+    }
+}

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/XSLTransform.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/XSLTransform.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/XSLTransform.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/XSLTransform.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.roller.util;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+/**
+ * Run an XSL transform (from the Java Almanac)
+ * @author Dave Johnson
+ */
+public class XSLTransform
+{
+    public static void main(String[] args)
+    {
+        if (args.length < 3)
+        {
+            System.out.println("USAGE: infile outfile xslfile");
+            System.exit(-1);
+        }
+        String inFilename = args[0];
+        String outFilename = args[1];
+        String xslFilename = args[2];
+        try
+        {
+            // Create transformer factory
+            TransformerFactory factory = TransformerFactory.newInstance();
+
+            // Use the factory to create a template containing the xsl file
+            Templates template = factory.newTemplates(new StreamSource(
+                    new FileInputStream(xslFilename)));
+
+            // Use the template to create a transformer
+            Transformer xformer = template.newTransformer();
+
+            // Prepare the input and output files
+            Source source = new StreamSource(new FileInputStream(inFilename));
+            Result result = new StreamResult(new FileOutputStream(outFilename));
+
+            // Apply the xsl file to the source file and write the result to the
+            // output file
+            xformer.transform(source, result);
+        }
+        catch (FileNotFoundException e)
+        {
+            e.printStackTrace();
+        }
+        catch (TransformerConfigurationException e)
+        {
+            // An error occurred in the XSL file
+            e.printStackTrace();
+        }
+        catch (TransformerException e)
+        {
+            // An error occurred while applying the XSL file
+            // Get location of error in input file
+            SourceLocator locator = e.getLocator();
+            int col = locator.getColumnNumber();
+            int line = locator.getLineNumber();
+            String publicId = locator.getPublicId();
+            String systemId = locator.getSystemId();
+            System.out.println("ERROR: line = "+line+" col = "+col);
+        }
+    }
+}
\ No newline at end of file

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/package.html
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/package.html?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/package.html (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/package.html Fri Oct 21 14:27:36 2005
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+  <title></title>
+</head>
+<body>
+Roller utility classes including date processing, mail, caching, etc.
+
+</body>
+</html>

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModule.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModule.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModule.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModule.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.roller.util.rome;
+
+import com.sun.syndication.feed.module.Module;
+
+public interface ContentModule extends Module {
+    public static final String URI = "http://purl.org/rss/1.0/modules/content/";
+    public String getEncoded();
+    public void setEncoded(String encoded);
+}

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleGenerator.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleGenerator.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleGenerator.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleGenerator.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.roller.util.rome;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jdom.Element;
+import org.jdom.Namespace;
+
+import com.sun.syndication.feed.module.Module;
+import com.sun.syndication.io.ModuleGenerator;
+
+public class ContentModuleGenerator implements ModuleGenerator {
+    private static final Namespace CONTENT_NS  = 
+        Namespace.getNamespace(ContentModule.URI);
+
+    public String getNamespaceUri() {
+        return ContentModule.URI;
+    }
+
+    private static final Set NAMESPACES;
+
+    static {
+        Set nss = new HashSet();
+        nss.add(CONTENT_NS);
+        NAMESPACES = Collections.unmodifiableSet(nss);
+    }
+
+    public Set getNamespaces() {
+        return NAMESPACES;
+    }
+
+    public void generate(Module module, Element element) {
+        ContentModule fm = (ContentModule)module;
+        if (fm.getEncoded() != null) {
+            element.addContent(generateSimpleElement("encoding", fm.getEncoded()));
+        }
+    }
+
+    protected Element generateSimpleElement(String name, String value)  {
+        Element element = new Element(name, CONTENT_NS);
+        element.addContent(value);
+        return element;
+    }
+
+}

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleImpl.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleImpl.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleImpl.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.roller.util.rome;
+
+import com.sun.syndication.feed.module.ModuleImpl;
+
+public class ContentModuleImpl extends ModuleImpl implements ContentModule {
+    private String _encoded;
+
+    public ContentModuleImpl() {
+        super(ContentModule.class,ContentModule.URI);
+    }
+    public String getEncoded() {
+        return _encoded;
+    }
+    public void setEncoded(String encoded) {
+        _encoded = encoded;
+    }
+    public Class getInterface() {
+        return ContentModule.class;
+    }
+    public void copyFrom(Object obj) {
+        ContentModule sm = (ContentModule) obj;
+        setEncoded(sm.getEncoded());
+    }
+
+}

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleParser.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleParser.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleParser.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/ContentModuleParser.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.roller.util.rome;
+
+import org.jdom.Element;
+import org.jdom.Namespace;
+
+import com.sun.syndication.feed.module.Module;
+import com.sun.syndication.io.ModuleParser;
+
+public class ContentModuleParser implements ModuleParser {
+
+    public String getNamespaceUri() {
+        return ContentModule.URI;
+    }
+
+    public Namespace getContentNamespace() {
+        return Namespace.getNamespace(ContentModule.URI);
+    }
+    public Module parse(Element dcRoot) {
+        boolean foundSomething = false;
+        ContentModule fm = new ContentModuleImpl();
+
+        Element e = dcRoot.getChild("encoded", getContentNamespace());
+        if (e != null) {
+            foundSomething = true;
+            fm.setEncoded(e.getText());
+        }
+        return (foundSomething) ? fm : null;
+    }
+}
+

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/DiskFeedInfoCache.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/DiskFeedInfoCache.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/DiskFeedInfoCache.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/DiskFeedInfoCache.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.roller.util.rome;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.URL;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.sun.syndication.fetcher.impl.FeedFetcherCache;
+import com.sun.syndication.fetcher.impl.SyndFeedInfo;
+
+/**
+ * @author David M. Johnson
+ */
+public class DiskFeedInfoCache implements FeedFetcherCache
+{
+    private static Log logger = 
+        LogFactory.getFactory().getInstance(DiskFeedInfoCache.class);
+    
+    protected String cachePath = null;
+    public DiskFeedInfoCache(String cachePath)
+    {
+        this.cachePath = cachePath;
+    }
+    public SyndFeedInfo getFeedInfo(URL url)
+    {
+        SyndFeedInfo info = null;
+        String fileName = cachePath + File.separator + "feed_" + url.hashCode();
+        FileInputStream fis;
+        try
+        {
+            fis = new FileInputStream(fileName);
+            ObjectInputStream ois = new ObjectInputStream(fis);
+            info = (SyndFeedInfo)ois.readObject();
+            fis.close();
+        }
+        catch (FileNotFoundException fnfe)
+        {
+            logger.debug("Cache miss for " + url.toString());
+        }
+        catch (ClassNotFoundException cnfe)
+        {
+            // Error writing to cahce is fatal
+            throw new RuntimeException("Attempting to read from cache", cnfe);
+        }
+        catch (IOException fnfe)
+        {
+            // Error writing to cahce is fatal
+            throw new RuntimeException("Attempting to read from cache", fnfe);
+        }
+        if (info == null) logger.info("Cache MISS!");
+        return info;
+    }
+
+    public void setFeedInfo(URL url, SyndFeedInfo feedInfo)
+    {
+        String fileName = cachePath + File.separator + "feed_" + url.hashCode();
+        FileOutputStream fos;
+        try
+        {
+            fos = new FileOutputStream(fileName);
+            ObjectOutputStream oos = new ObjectOutputStream(fos);
+            oos.writeObject(feedInfo);
+            fos.flush();
+            fos.close();
+        }
+        catch (Exception e)
+        {
+            // Error writing to cahce is fatal
+            throw new RuntimeException("Attempting to write to cache", e);
+        }
+    }
+}

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS091N.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS091N.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS091N.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS091N.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.roller.util.rome;
+
+import com.sun.syndication.feed.rss.Item;
+import com.sun.syndication.feed.synd.SyndEntry;
+import com.sun.syndication.feed.synd.impl.ConverterForRSS091Userland;
+
+/**
+ */
+public class PlanetConverterForRSS091N extends ConverterForRSS091Userland {
+
+    public PlanetConverterForRSS091N() {
+        this("rss_0.91N");
+    }
+    protected PlanetConverterForRSS091N(String type) {
+        super(type);
+    }
+    protected SyndEntry createSyndEntry(Item item) {
+        SyndEntry entry = super.createSyndEntry(item);
+        entry.setPublishedDate(item.getPubDate()); 
+        return entry;
+    }
+}

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS091U.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS091U.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS091U.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS091U.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.roller.util.rome;
+
+import com.sun.syndication.feed.rss.Item;
+import com.sun.syndication.feed.synd.SyndEntry;
+import com.sun.syndication.feed.synd.impl.ConverterForRSS091Userland;
+
+/**
+ */
+public class PlanetConverterForRSS091U extends ConverterForRSS091Userland {
+
+    public PlanetConverterForRSS091U() {
+        this("rss_0.91U");
+    }
+
+    protected PlanetConverterForRSS091U(String type) {
+        super(type);
+    }
+    protected SyndEntry createSyndEntry(Item item) {
+        SyndEntry entry = super.createSyndEntry(item);
+        entry.setPublishedDate(item.getPubDate()); 
+        return entry;
+    }
+}

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS20.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS20.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS20.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetConverterForRSS20.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.roller.util.rome;
+
+import java.util.Date;
+
+import com.sun.syndication.feed.WireFeed;
+import com.sun.syndication.feed.module.DCModule;
+import com.sun.syndication.feed.rss.Channel;
+import com.sun.syndication.feed.rss.Item;
+import com.sun.syndication.feed.synd.SyndEntry;
+import com.sun.syndication.feed.synd.SyndFeed;
+import com.sun.syndication.feed.synd.impl.ConverterForRSS20;
+
+/**
+ * Workaround Rome bug.
+ */
+public class PlanetConverterForRSS20 extends ConverterForRSS20 {
+
+    public PlanetConverterForRSS20() {
+        this("rss_2.0");
+    }
+    protected PlanetConverterForRSS20(String type) {
+        super(type);
+    }
+    protected SyndEntry createSyndEntry(Item item) {
+        DCModule dcm = (DCModule)item.getModule(DCModule.URI);
+        Date dcdate = dcm != null ? dcm.getDate() : null;
+        SyndEntry syndEntry = super.createSyndEntry(item);
+        if (dcdate != null)
+        {
+            ((DCModule)syndEntry.getModule(DCModule.URI)).setDate(dcdate);
+        }
+        return syndEntry;
+    }
+}

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetRSS091NParser.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetRSS091NParser.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetRSS091NParser.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetRSS091NParser.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.roller.util.rome;
+
+import org.jdom.Element;
+
+import com.sun.syndication.feed.rss.Item;
+import com.sun.syndication.io.impl.DateParser;
+import com.sun.syndication.io.impl.RSS091UserlandParser;
+
+/**
+ */
+public class PlanetRSS091NParser extends RSS091UserlandParser {
+
+    public PlanetRSS091NParser() {
+        this("rss_0.91N");
+    }
+
+    protected PlanetRSS091NParser(String type) {
+        super(type);
+    }
+
+    protected Item parseItem(Element rssRoot,Element eItem) {
+        Item item = super.parseItem(rssRoot, eItem);
+        Element e = eItem.getChild("pubDate",getRSSNamespace());
+        if (e!=null) {
+            item.setPubDate(DateParser.parseRFC822(e.getText()));
+        }
+        return item;
+    }
+}

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetRSS091UParser.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetRSS091UParser.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetRSS091UParser.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/PlanetRSS091UParser.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.roller.util.rome;
+
+import org.jdom.Element;
+
+import com.sun.syndication.feed.rss.Item;
+import com.sun.syndication.io.impl.DateParser;
+import com.sun.syndication.io.impl.RSS091UserlandParser;
+
+/**
+ */
+public class PlanetRSS091UParser extends RSS091UserlandParser {
+
+    public PlanetRSS091UParser() {
+        this("rss_0.91U");
+    }
+
+    protected PlanetRSS091UParser(String type) {
+        super(type);
+    }
+
+    protected Item parseItem(Element rssRoot,Element eItem) {
+        Item item = super.parseItem(rssRoot, eItem);
+        Element e = eItem.getChild("pubDate",getRSSNamespace());
+        if (e!=null) {
+            item.setPubDate(DateParser.parseRFC822(e.getText()));
+        }
+        return item;
+    }
+}

Added: incubator/roller/branches/roller_1.x/src/org/roller/util/rome/package.html
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/util/rome/package.html?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/util/rome/package.html (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/util/rome/package.html Fri Oct 21 14:27:36 2005
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+  <title></title>
+</head>
+<body>
+ROME modules, converters and cache needed for Planet aggregator.
+
+</body>
+</html>