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 2006/12/12 05:54:20 UTC

svn commit: r486019 - in /incubator/roller/trunk/sandbox/planetroller: ./ src/org/apache/roller/planet/business/hibernate/ src/org/apache/roller/planet/tasks/ src/org/apache/roller/util/ web/WEB-INF/scripts/

Author: snoopdave
Date: Mon Dec 11 20:54:19 2006
New Revision: 486019

URL: http://svn.apache.org/viewvc?view=rev&rev=486019
Log:
Fixes and temporary hacks to get planet working again

Added:
    incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/DateUtil.java
    incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/ISO8601DateParser.java
    incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/OldUtilities.java
    incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/StandaloneWebappClassLoader.java
    incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/TaskRunner.java
    incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/UtilitiesModel.java
Modified:
    incubator/roller/trunk/sandbox/planetroller/build.xml
    incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/planet/business/hibernate/HibernatePlanetManagerImpl.java
    incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/planet/tasks/GeneratePlanetTask.java
    incubator/roller/trunk/sandbox/planetroller/web/WEB-INF/scripts/genplanet.sh
    incubator/roller/trunk/sandbox/planetroller/web/WEB-INF/scripts/refreshplanet.sh

Modified: incubator/roller/trunk/sandbox/planetroller/build.xml
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/build.xml?view=diff&rev=486019&r1=486018&r2=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/build.xml (original)
+++ incubator/roller/trunk/sandbox/planetroller/build.xml Mon Dec 11 20:54:19 2006
@@ -195,8 +195,9 @@
 
         <copy todir="${build.webapp}">
             <fileset dir="${ro.web}" includes="**/**" />
-        </copy> 
-
+        </copy>         
+        <chmod perm="+x" dir="${build.webapp}/WEB-INF/scripts" includes="*.sh" />
+        
         <mkdir dir="${build.webapp}/WEB-INF/templates" />
         <copy todir="${build.webapp}/WEB-INF/templates">
             <fileset dir="./templates" includes="**/**" />

Modified: incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/planet/business/hibernate/HibernatePlanetManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/planet/business/hibernate/HibernatePlanetManagerImpl.java?view=diff&rev=486019&r1=486018&r2=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/planet/business/hibernate/HibernatePlanetManagerImpl.java (original)
+++ incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/planet/business/hibernate/HibernatePlanetManagerImpl.java Mon Dec 11 20:54:19 2006
@@ -247,7 +247,8 @@
         try {
             Session session = ((HibernatePersistenceStrategy)strategy).getSession();
             Criteria criteria = session.createCriteria(PlanetEntryData.class);
-            criteria.add(Expression.eq("subscription.feedURL", feedURL));
+            criteria.createAlias("subscription", "sub");
+            criteria.add(Expression.eq("sub.feedURL", feedURL));
             criteria.addOrder(Order.desc("pubTime"));
             criteria.setFirstResult(offset);
             if (length != -1) criteria.setMaxResults(length);

Modified: incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/planet/tasks/GeneratePlanetTask.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/planet/tasks/GeneratePlanetTask.java?view=diff&rev=486019&r1=486018&r2=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/planet/tasks/GeneratePlanetTask.java (original)
+++ incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/planet/tasks/GeneratePlanetTask.java Mon Dec 11 20:54:19 2006
@@ -24,11 +24,12 @@
 import java.util.List;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.RollerException;
 import org.apache.roller.planet.config.PlanetConfig;
 import org.apache.roller.planet.business.Planet;
 import org.apache.roller.planet.business.PlanetFactory;
 import org.apache.roller.planet.business.PlanetManager;
+import org.apache.roller.util.OldUtilities;
+import org.apache.roller.util.UtilitiesModel;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.VelocityEngine;
 import org.apache.velocity.texen.Generator;
@@ -79,9 +80,9 @@
             // Build context with current date 
             VelocityContext context = new VelocityContext();
             context.put("date", new Date());
-            // TODO fix
-            //context.put("utils", new UtilitiesModel());
-            //context.put("utilities", new OldUtilities());
+            // TODO fix: Use one utilities model and not one of the below
+            context.put("utils", new UtilitiesModel());
+            context.put("utilities", new OldUtilities());
             context.put("planet", new StaticPlanetModel());
             
             // Ensure that output directories exists, one for each group

Added: incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/DateUtil.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/DateUtil.java?view=auto&rev=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/DateUtil.java (added)
+++ incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/DateUtil.java Mon Dec 11 20:54:19 2006
@@ -0,0 +1,472 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * 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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.util;
+
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+import org.apache.commons.lang.StringUtils;
+
+
+/**
+ * General purpose date utilities.
+ */
+public abstract class DateUtil {
+    
+    public static final long millisInDay = 86400000;
+    
+    // a bunch of date formats
+    private static final String formatDefaultDate = "dd.MM.yyyy";
+    private static final String formatDefaultDateMinimal = "d.M.yy";
+    private static final String formatDefaultTimestamp = "yyyy-MM-dd HH:mm:ss.SSS";
+    
+    private static final String formatFriendlyTimestamp = "dd.MM.yyyy HH:mm:ss";
+    
+    private static final String format6chars = "yyyyMM";
+    private static final String format8chars = "yyyyMMdd";
+    
+    private static final String formatIso8601 = "yyyy-MM-dd'T'HH:mm:ssZ";
+    private static final String formatIso8601Day = "yyyy-MM-dd";
+    
+    private static final String formatRfc822 = "EEE, d MMM yyyy HH:mm:ss Z";
+    
+    
+    /**
+     * Returns a Date set to the last possible millisecond of the day, just
+     * before midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getEndOfDay(Date day) {
+        return getEndOfDay(day,Calendar.getInstance());
+    }
+    
+    
+    public static Date getEndOfDay(Date day,Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
+        cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the last possible millisecond of the day, just
+     * before midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getEndOfHour(Date day) {
+        return getEndOfHour(day, Calendar.getInstance());
+    }
+    
+    
+    public static Date getEndOfHour(Date day, Calendar cal) {
+        if (day == null || cal == null) {
+            return day;
+        }
+        
+        cal.setTime(day);
+        cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the first possible millisecond of the month, just
+     * after midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getStartOfMonth(Date day) {
+        return getStartOfMonth(day, Calendar.getInstance());
+    }
+    
+    
+    public static Date getStartOfMonth(Date day, Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        
+        // set time to start of day
+        cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
+        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
+        
+        // set time to first day of month
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+        
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the last possible millisecond of the month, just
+     * before midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getEndOfMonth(Date day) {
+        return getEndOfMonth(day, Calendar.getInstance());
+    }
+    
+    
+    public static Date getEndOfMonth(Date day,Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        
+        // set time to end of day
+        cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
+        cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
+        
+        // set time to first day of month
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+        
+        // add one month
+        cal.add(Calendar.MONTH, 1);
+        
+        // back up one day
+        cal.add(Calendar.DAY_OF_MONTH, -1);
+        
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the first possible millisecond of the day, just
+     * after midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getStartOfDay(Date day) {
+        return getStartOfDay(day, Calendar.getInstance());
+    }
+    
+    
+    /**
+     * Returns a Date set to the first possible millisecond of the day, just
+     * after midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getStartOfDay(Date day, Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
+        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set just to Noon, to the closest possible millisecond
+     * of the day. If a null day is passed in, a new Date is created.
+     * nnoon (00m 12h 00s)
+     */
+    public static Date getNoonOfDay(Date day, Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        cal.set(Calendar.HOUR_OF_DAY, 12);
+        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a java.sql.Timestamp equal to the current time
+     **/
+    public static java.sql.Timestamp now() {
+        return new java.sql.Timestamp(new java.util.Date().getTime());
+    }
+    
+    
+    /**
+     * Returns a string the represents the passed-in date parsed
+     * according to the passed-in format.  Returns an empty string
+     * if the date or the format is null.
+     **/
+    public static String format(Date aDate, SimpleDateFormat aFormat) {
+        if (aDate == null || aFormat == null ) { return ""; }
+        synchronized (aFormat) {
+            return aFormat.format(aDate);
+        }
+    }
+    
+    
+    /**
+     * Returns a Date using the passed-in string and format.  Returns null if the string
+     * is null or empty or if the format is null.  The string must match the format.
+     **/
+    public static Date parse(String aValue, SimpleDateFormat aFormat) throws ParseException {
+        if (StringUtils.isEmpty(aValue) || aFormat == null) {
+            return null;
+        }
+        synchronized(aFormat) {
+            return aFormat.parse(aValue);
+        }
+    }
+    
+    
+    /**
+     * Returns true if endDate is after startDate or if startDate equals endDate
+     * or if they are the same date.  Returns false if either value is null.
+     **/
+    public static boolean isValidDateRange(Date startDate, Date endDate) {
+        return isValidDateRange(startDate, endDate, true);
+    }
+    
+    
+    /**
+     * Returns true if endDate is after startDate or if startDate equals endDate.
+     * Returns false if either value is null.  If equalOK, returns true if the
+     * dates are equal.
+     **/
+    public static boolean isValidDateRange(Date startDate, Date endDate, boolean equalOK) {
+        // false if either value is null
+        if (startDate == null || endDate == null) { return false; }
+        
+        if (equalOK) {
+            // true if they are equal
+            if (startDate.equals(endDate)) { return true; }
+        }
+        
+        // true if endDate after startDate
+        if (endDate.after(startDate)) { return true; }
+        
+        return false;
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat defaultDateFormat() {
+        return DateUtil.friendlyDateFormat(true);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static java.text.SimpleDateFormat minimalDateFormat() {
+        return friendlyDateFormat(true);
+    }
+    
+    
+    // convenience method that returns friendly data format
+    // using full month, day, year digits.
+    public static SimpleDateFormat fullDateFormat() {
+        return friendlyDateFormat(false);
+    }
+    
+    
+    /** 
+     * Returns a "friendly" date format.
+     * @param mimimalFormat Should the date format allow single digits.
+     **/
+    public static SimpleDateFormat friendlyDateFormat(boolean minimalFormat) {
+        if (minimalFormat) {
+            return new SimpleDateFormat(formatDefaultDateMinimal);
+        }
+        
+        return new SimpleDateFormat(formatDefaultDate);
+    }
+    
+    
+    // returns full timestamp format
+    public static SimpleDateFormat defaultTimestampFormat() {
+        return new SimpleDateFormat(formatDefaultTimestamp);
+    }
+    
+    
+    // convenience method returns long friendly timestamp format
+    public static SimpleDateFormat friendlyTimestampFormat() {
+        return new SimpleDateFormat(formatFriendlyTimestamp);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat get8charDateFormat() {
+        return new SimpleDateFormat(format8chars);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat get6charDateFormat() {
+        return new SimpleDateFormat(format6chars);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat getIso8601DateFormat() {
+        return new SimpleDateFormat(formatIso8601);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat getIso8601DayDateFormat() {
+        return new SimpleDateFormat(formatIso8601Day);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat getRfc822DateFormat() {
+        // http://www.w3.org/Protocols/rfc822/Overview.html#z28
+        // Using Locale.US to fix ROL-725 and ROL-628
+        return new SimpleDateFormat(formatRfc822, Locale.US);
+    }
+    
+    
+    // convenience method
+    public static String defaultDate(Date date) {
+        return format(date, defaultDateFormat());
+    }
+    
+    
+    // convenience method using minimal date format
+    public static String minimalDate(Date date) {
+        return format(date, DateUtil.minimalDateFormat());
+    }
+    
+    
+    public static String fullDate(Date date) {
+        return format(date, DateUtil.fullDateFormat());
+    }
+    
+    
+    /**
+     * Format the date using the "friendly" date format.
+     */
+    public static String friendlyDate(Date date, boolean minimalFormat) {
+        return format(date, friendlyDateFormat(minimalFormat));
+    }
+    
+    
+    // convenience method
+    public static String friendlyDate(Date date) {
+        return format(date, friendlyDateFormat(true));
+    }
+    
+    
+    // convenience method
+    public static String defaultTimestamp(Date date) {
+        return format(date, defaultTimestampFormat());
+    }
+    
+    
+    // convenience method returns long friendly formatted timestamp
+    public static String friendlyTimestamp(Date date) {
+        return format(date, friendlyTimestampFormat());
+    }
+    
+    
+    // convenience method returns 8 char day stamp YYYYMMDD
+    public static String format8chars(Date date) {
+        return format(date, get8charDateFormat());
+    }
+    
+    
+    // convenience method returns 6 char month stamp YYYYMM
+    public static String format6chars(Date date) {
+        return format(date, get6charDateFormat());
+    }
+    
+    
+    // convenience method returns long friendly formatted timestamp
+    public static String formatIso8601Day(Date date) {
+        return format(date, getIso8601DayDateFormat());
+    }
+    
+    
+    public static String formatRfc822(Date date) {
+        return format(date, getRfc822DateFormat());
+    }
+    
+    
+    // This is a hack, but it seems to work
+    public static String formatIso8601(Date date) {
+        if (date == null) return "";
+        
+        // Add a colon 2 chars before the end of the string
+        // to make it a valid ISO-8601 date.
+        
+        String str = format(date, getIso8601DateFormat());
+        StringBuffer sb = new StringBuffer();
+        sb.append( str.substring(0,str.length()-2) );
+        sb.append( ":" );
+        sb.append( str.substring(str.length()-2) );
+        return sb.toString();
+    }
+    
+    
+    public static Date parseIso8601(String value) throws Exception {
+        return ISO8601DateParser.parse(value);
+    }
+    
+    
+    /**
+     * Parse data as either 6-char or 8-char format.
+     */
+    public static Date parseWeblogURLDateString(String dateString, TimeZone tz, Locale locale) {
+        
+        Date ret = new Date();
+        SimpleDateFormat char8DateFormat = DateUtil.get8charDateFormat();
+        SimpleDateFormat char6DateFormat = DateUtil.get6charDateFormat();
+        
+        if (dateString != null
+                && dateString.length()==8
+                && StringUtils.isNumeric(dateString) ) {
+            ParsePosition pos = new ParsePosition(0);
+            ret = char8DateFormat.parse(dateString, pos);
+            
+            // make sure the requested date is not in the future
+            Date today = null;
+            Calendar todayCal = Calendar.getInstance();
+            todayCal = Calendar.getInstance(tz, locale);
+            todayCal.setTime(new Date());
+            today = todayCal.getTime();
+            if(ret.after(today)) {
+                ret = today;
+            }
+            
+        } else if(dateString != null
+                && dateString.length()==6
+                && StringUtils.isNumeric(dateString)) {
+            ParsePosition pos = new ParsePosition(0);
+            ret = char6DateFormat.parse(dateString, pos);
+            
+            // make sure the requested date is not in the future
+            Calendar todayCal = Calendar.getInstance();
+            todayCal = Calendar.getInstance(tz, locale);
+            todayCal.setTime(new Date());
+            Date today = todayCal.getTime();
+            if(ret.after(today)) {
+                ret = today;
+            }
+        }
+        
+        return ret;
+    }
+    
+}

Added: incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/ISO8601DateParser.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/ISO8601DateParser.java?view=auto&rev=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/ISO8601DateParser.java (added)
+++ incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/ISO8601DateParser.java Mon Dec 11 20:54:19 2006
@@ -0,0 +1,122 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * 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.apache.roller.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * ISO 8601 date parsing utility.  Designed for parsing the ISO subset used in
+ * Dublin Core, RSS 1.0, and Atom.
+ * 
+ * @author <a href="mailto:burton@apache.org">Kevin A. Burton (burtonator)</a>
+ * @version $Id: ISO8601DateParser.java,v 1.2 2005/06/03 20:25:29 snoopdave Exp $
+ */
+public class ISO8601DateParser {
+
+    // 2004-06-14T19:GMT20:30Z
+    // 2004-06-20T06:GMT22:01Z
+
+    // http://www.cl.cam.ac.uk/~mgk25/iso-time.html
+    //    
+    // http://www.intertwingly.net/wiki/pie/DateTime
+    //
+    // http://www.w3.org/TR/NOTE-datetime
+    //
+    // Different standards may need different levels of granularity in the date and
+    // time, so this profile defines six levels. Standards that reference this
+    // profile should specify one or more of these granularities. If a given
+    // standard allows more than one granularity, it should specify the meaning of
+    // the dates and times with reduced precision, for example, the result of
+    // comparing two dates with different precisions.
+
+    // The formats are as follows. Exactly the components shown here must be
+    // present, with exactly this punctuation. Note that the "T" appears literally
+    // in the string, to indicate the beginning of the time element, as specified in
+    // ISO 8601.
+
+    //    Year:
+    //       YYYY (eg 1997)
+    //    Year and month:
+    //       YYYY-MM (eg 1997-07)
+    //    Complete date:
+    //       YYYY-MM-DD (eg 1997-07-16)
+    //    Complete date plus hours and minutes:
+    //       YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
+    //    Complete date plus hours, minutes and seconds:
+    //       YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
+    //    Complete date plus hours, minutes, seconds and a decimal fraction of a
+    // second
+    //       YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
+
+    // where:
+
+    //      YYYY = four-digit year
+    //      MM   = two-digit month (01=January, etc.)
+    //      DD   = two-digit day of month (01 through 31)
+    //      hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
+    //      mm   = two digits of minute (00 through 59)
+    //      ss   = two digits of second (00 through 59)
+    //      s    = one or more digits representing a decimal fraction of a second
+    //      TZD  = time zone designator (Z or +hh:mm or -hh:mm)
+    public static Date parse( String input ) throws java.text.ParseException {
+
+        //NOTE: SimpleDateFormat uses GMT[-+]hh:mm for the TZ which breaks
+        //things a bit.  Before we go on we have to repair this.
+        SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssz" );
+        
+        //this is zero time so we need to add that TZ indicator for 
+        if ( input.endsWith( "Z" ) ) {
+            input = input.substring( 0, input.length() - 1) + "GMT-00:00";
+        } else {
+            int inset = 6;
+        
+            String s0 = input.substring( 0, input.length() - inset );
+            String s1 = input.substring( input.length() - inset, input.length() );
+
+            input = s0 + "GMT" + s1;
+        }
+        
+        return df.parse( input );
+        
+    }
+
+    public static String toString( Date date ) {
+        
+        SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssz" );
+        
+        TimeZone tz = TimeZone.getTimeZone( "UTC" );
+        
+        df.setTimeZone( tz );
+
+        String output = df.format( date );
+
+        int inset0 = 9;
+        int inset1 = 6;
+        
+        String s0 = output.substring( 0, output.length() - inset0 );
+        String s1 = output.substring( output.length() - inset1, output.length() );
+
+        String result = s0 + s1;
+
+        result = result.replaceAll( "UTC", "+00:00" );
+        
+        return result;
+        
+    }
+
+}
\ No newline at end of file

Added: incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/OldUtilities.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/OldUtilities.java?view=auto&rev=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/OldUtilities.java (added)
+++ incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/OldUtilities.java Mon Dec 11 20:54:19 2006
@@ -0,0 +1,733 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * 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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+package org.apache.roller.util;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.util.DateUtil;
+import org.apache.roller.util.RegexUtil;
+import org.apache.roller.util.Utilities;
+
+
+/**
+ * Utility methods needed by old Roller 2.X macros/templates.
+ * Deprecated because they are either redundant or unnecesary.
+ */
+public class OldUtilities {    
+    
+    /** The <code>Log</code> instance for this class. */
+    private static Log mLogger = LogFactory.getLog(OldUtilities.class);
+    
+    private static Pattern mLinkPattern =
+            Pattern.compile("<a href=.*?>", Pattern.CASE_INSENSITIVE);    
+    private static final Pattern OPENING_B_TAG_PATTERN = 
+            Pattern.compile("&lt;b&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_B_TAG_PATTERN = 
+            Pattern.compile("&lt;/b&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_I_TAG_PATTERN = 
+            Pattern.compile("&lt;i&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_I_TAG_PATTERN = 
+            Pattern.compile("&lt;/i&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_BLOCKQUOTE_TAG_PATTERN = 
+            Pattern.compile("&lt;blockquote&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_BLOCKQUOTE_TAG_PATTERN = 
+            Pattern.compile("&lt;/blockquote&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern BR_TAG_PATTERN = 
+            Pattern.compile("&lt;br */*&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_P_TAG_PATTERN = 
+            Pattern.compile("&lt;p&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_P_TAG_PATTERN = 
+            Pattern.compile("&lt;/p&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_PRE_TAG_PATTERN = 
+            Pattern.compile("&lt;pre&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_PRE_TAG_PATTERN = 
+            Pattern.compile("&lt;/pre&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_UL_TAG_PATTERN = 
+            Pattern.compile("&lt;ul&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_UL_TAG_PATTERN = 
+            Pattern.compile("&lt;/ul&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_OL_TAG_PATTERN = 
+            Pattern.compile("&lt;ol&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_OL_TAG_PATTERN = 
+            Pattern.compile("&lt;/ol&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_LI_TAG_PATTERN = 
+            Pattern.compile("&lt;li&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_LI_TAG_PATTERN = 
+            Pattern.compile("&lt;/li&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_A_TAG_PATTERN = 
+            Pattern.compile("&lt;/a&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_A_TAG_PATTERN = 
+            Pattern.compile("&lt;a href=.*?&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern QUOTE_PATTERN = 
+            Pattern.compile("&quot;", Pattern.CASE_INSENSITIVE);
+            
+    public static boolean isEmpty(String str) {
+        if (str == null) return true;
+        return "".equals(str.trim());
+    }
+    
+    public static boolean isNotEmpty(String str) {
+        return !isEmpty(str);
+    }
+    
+    public static String[] split(String str1, String str2) {
+        return StringUtils.split(str1, str2);
+    }
+    
+    public static String replace(String src, String target, String rWith) {
+        return StringUtils.replace(src, target, rWith);
+    }
+    
+    public static String replace(String src, String target, String rWith, int maxCount) {
+        return StringUtils.replace(src, target, rWith, maxCount);
+    }
+    
+    public static boolean equals(String str1, String str2) {
+        return StringUtils.equals(str1, str2);
+    }
+    
+    public static boolean isAlphanumeric(String str) {
+        return StringUtils.isAlphanumeric(str);
+    }
+    
+    public static String[] stripAll(String[] strs) {
+        return StringUtils.stripAll(strs);
+    }
+    
+    public static String left(String str, int length) {
+        return StringUtils.left(str, length);
+    }
+    
+    public static String escapeHTML(String str) {
+        return StringEscapeUtils.escapeHtml(str);
+    }
+    
+    public static String unescapeHTML(String str) {
+        return StringEscapeUtils.unescapeHtml(str);
+    }
+               
+    /**
+     * 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.
+     */
+    public static String removeHTML(String str, boolean addSpace) {
+        return Utilities.removeHTML(str, addSpace);
+    }
+        
+    /**
+     * Autoformat.
+     */
+    public static String autoformat(String s) {
+        String ret = StringUtils.replace(s, "\n", "<br />");
+        return ret;
+    }
+    
+    /**
+     * Return date for current time.
+     */
+    public static Date getNow() {
+        return new Date();
+    }
+    
+    /**
+     * Format date using SimpleDateFormat format string.
+     */
+    public static String formatDate(Date d, String fmt) {
+        SimpleDateFormat format = new SimpleDateFormat(fmt);
+        return format.format(d);
+    }
+    
+    /**
+     * 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);
+    }
+    
+    /**
+     * 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;
+    }
+    
+    public static String truncateNicely(String str, int lower, int upper, String appendToEnd) {
+        return Utilities.truncateNicely(str, lower, upper, appendToEnd);
+    }
+    
+    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;
+    }    
+    
+    public static String hexEncode(String str) {
+        if (StringUtils.isEmpty(str)) return str;
+        
+        return RegexUtil.encode(str);
+    }
+    
+    public static String encodeEmail(String str) {
+        return str!=null ? RegexUtil.encodeEmail(str) : null;
+    }
+    
+    /**
+     * URL encoding.
+     * @param s a string to be URL-encoded
+     * @return URL encoding of s using character encoding UTF-8; null if s is null.
+     */
+    public static final String encode(String s) {
+        try {
+            if (s != null)
+                return URLEncoder.encode(s, "UTF-8");
+            else
+                return s;
+        } catch (UnsupportedEncodingException e) {
+            // Java Spec requires UTF-8 be in all Java environments, so this should not happen
+            return s;
+        }
+    }
+    
+    /**
+     * URL decoding.
+     * @param s a URL-encoded string to be URL-decoded
+     * @return URL decoded value of s using character encoding UTF-8; null if s is null.
+     */
+    public static final String decode(String s) {
+        try {
+            if (s != null)
+                return URLDecoder.decode(s, "UTF-8");
+            else
+                return s;
+        } catch (UnsupportedEncodingException e) {
+            // Java Spec requires UTF-8 be in all Java environments, so this should not happen
+            return s;
+        }
+    }
+        
+    /**
+     * 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();
+    }
+    
+    /**
+     * Transforms the given String into a subset of HTML displayable on a web
+     * page. The subset includes &lt;b&gt;, &lt;i&gt;, &lt;p&gt;, &lt;br&gt;,
+     * &lt;pre&gt; and &lt;a href&gt; (and their corresponding end tags).
+     *
+     * @param s   the String to transform
+     * @return    the transformed String
+     */
+    public static String transformToHTMLSubset(String s) {
+        
+        if (s == null) {
+            return null;
+        }
+        
+        s = replace(s, OPENING_B_TAG_PATTERN, "<b>");
+        s = replace(s, CLOSING_B_TAG_PATTERN, "</b>");
+        s = replace(s, OPENING_I_TAG_PATTERN, "<i>");
+        s = replace(s, CLOSING_I_TAG_PATTERN, "</i>");
+        s = replace(s, OPENING_BLOCKQUOTE_TAG_PATTERN, "<blockquote>");
+        s = replace(s, CLOSING_BLOCKQUOTE_TAG_PATTERN, "</blockquote>");
+        s = replace(s, BR_TAG_PATTERN, "<br />");
+        s = replace(s, OPENING_P_TAG_PATTERN, "<p>");
+        s = replace(s, CLOSING_P_TAG_PATTERN, "</p>");
+        s = replace(s, OPENING_PRE_TAG_PATTERN, "<pre>");
+        s = replace(s, CLOSING_PRE_TAG_PATTERN, "</pre>");
+        s = replace(s, OPENING_UL_TAG_PATTERN, "<ul>");
+        s = replace(s, CLOSING_UL_TAG_PATTERN, "</ul>");
+        s = replace(s, OPENING_OL_TAG_PATTERN, "<ol>");
+        s = replace(s, CLOSING_OL_TAG_PATTERN, "</ol>");
+        s = replace(s, OPENING_LI_TAG_PATTERN, "<li>");
+        s = replace(s, CLOSING_LI_TAG_PATTERN, "</li>");
+        s = replace(s, QUOTE_PATTERN, "\"");
+        
+        // HTTP links
+        s = replace(s, CLOSING_A_TAG_PATTERN, "</a>");
+        Matcher m = OPENING_A_TAG_PATTERN.matcher(s);
+        while (m.find()) {
+            int start = m.start();
+            int end = m.end();
+            String link = s.substring(start, end);
+            link = "<" + link.substring(4, link.length() - 4) + ">";
+            s = s.substring(0, start) + link + s.substring(end, s.length());
+            m = OPENING_A_TAG_PATTERN.matcher(s);
+        }
+        
+        // escaped angle brackets
+        s = s.replaceAll("&amp;lt;", "&lt;");
+        s = s.replaceAll("&amp;gt;", "&gt;");
+        s = s.replaceAll("&amp;#", "&#");
+        
+        return s;
+    }
+    
+    private static String replace(String string, Pattern pattern, String replacement) {
+        Matcher m = pattern.matcher(string);
+        return m.replaceAll(replacement);
+    }
+    
+    /**
+     * Convert a byte array into a Base64 string (as used in mime formats)
+     */
+    public static String toBase64(byte[] aValue) {
+        
+        final String m_strBase64Chars =
+                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+        
+        int byte1;
+        int byte2;
+        int byte3;
+        int iByteLen = aValue.length;
+        StringBuffer tt = new StringBuffer();
+        
+        for (int i = 0; i < iByteLen; i += 3) {
+            boolean bByte2 = (i + 1) < iByteLen;
+            boolean bByte3 = (i + 2) < iByteLen;
+            byte1 = aValue[i] & 0xFF;
+            byte2 = (bByte2) ? (aValue[i + 1] & 0xFF) : 0;
+            byte3 = (bByte3) ? (aValue[i + 2] & 0xFF) : 0;
+            
+            tt.append(m_strBase64Chars.charAt(byte1 / 4));
+            tt.append(m_strBase64Chars.charAt((byte2 / 16) + ((byte1 & 0x3) * 16)));
+            tt.append(((bByte2) ? m_strBase64Chars.charAt((byte3 / 64) + ((byte2 & 0xF) * 4)) : '='));
+            tt.append(((bByte3) ? m_strBase64Chars.charAt(byte3 & 0x3F) : '='));
+        }
+        
+        return tt.toString();
+    }
+    
+    
+    //------------------------------------------------------------------------
+    /**
+     * Escape, but do not replace HTML.
+     * @param escapeAmpersand Optionally escape
+     * ampersands (&amp;).
+     */
+    public static String escapeHTML(String s, boolean escapeAmpersand) {
+        return Utilities.escapeHTML(s, escapeAmpersand);
+    }
+                
+    //------------------------------------------------------------------------
+    /**
+     * 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;
+    }
+        
+
+    
+    /**
+     * 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);
+    }
+               
+    /**
+     * @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();
+    }
+    
+    
+    /**
+     * 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) {
+        if (text == null) return "null";
+        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) {
+        if (text == null) return "null";
+        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));
+        }
+    }
+    
+}

Added: incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/StandaloneWebappClassLoader.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/StandaloneWebappClassLoader.java?view=auto&rev=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/StandaloneWebappClassLoader.java (added)
+++ incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/StandaloneWebappClassLoader.java Mon Dec 11 20:54:19 2006
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * 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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ * StandaloneWebappClassLoader.java
+ * Created on October 20, 2006, 11:11 PM
+ */
+
+package org.apache.roller.util;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * ClassLoader to enable running webapp classes outside of webapp.  
+ * You provide webappDir and jarsDir paths and the classloader will include 
+ * webappDir/WEB-INF/classes, webappDir/WEB-INF/lib/*jar and jarsDir/*.jar.
+ */
+public class StandaloneWebappClassLoader extends URLClassLoader {
+    public static String FS = File.separator;
+    
+    /** Use calling class's parent classloader */
+    public StandaloneWebappClassLoader(String webappDir, String jarsDir) throws Exception {
+        super(buildURLsArray(webappDir, jarsDir));
+    }
+    
+    /** Use a specific parent classloader, or null for no parent */
+    public StandaloneWebappClassLoader(String webappDir, String jarsDir, ClassLoader cl) throws Exception {
+        super(buildURLsArray(webappDir, jarsDir), cl);
+    }
+    
+    private static URL[] buildURLsArray(String webappDir, String jarsDir) throws Exception {
+        // Create collection of URLs needed for classloader
+        List urlList = new ArrayList();
+
+        // Add WEB-INF/lib jars
+        String libPath = webappDir + FS + "WEB-INF" + FS + "lib";
+        addURLs(libPath, urlList);
+        
+        // Added WEB-INF/classes
+        String classesPath = webappDir + FS + "WEB-INF" + FS + "classes" + FS;
+        urlList.add(new URL("file://" + classesPath));
+        
+        // Add additional jars
+        addURLs(jarsDir, urlList);
+                
+        return (URL[])urlList.toArray(new URL[urlList.size()]);  
+    }
+    
+    private static void addURLs(String dirPath, List urlList) throws Exception {
+        File libDir = new File(dirPath);
+        String[] libJarNames = libDir.list(new FilenameFilter() {
+            public boolean accept(File dir, String pathname) {
+                if (pathname.endsWith(".jar")) {
+                    return true;
+                }
+                return false;
+            }
+        });       
+        for (int i=0; i<libJarNames.length; i++) {
+            String url = "file://" + dirPath + FS + libJarNames[i];
+            urlList.add(new URL(url));
+        }
+    }
+}

Added: incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/TaskRunner.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/TaskRunner.java?view=auto&rev=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/TaskRunner.java (added)
+++ incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/TaskRunner.java Mon Dec 11 20:54:19 2006
@@ -0,0 +1,81 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+*  contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.roller.util;
+        
+import java.io.File;
+import org.apache.roller.util.StandaloneWebappClassLoader;
+
+/**
+ * Sets up classpath for Roller and runs a task. 
+ * Expects these JVM parameters:
+ * webapp.dir must specify Roller webapp directory
+ * jars.dir must specify additional jars directory (e.g. Tomcat commons/lib)
+ */
+public class TaskRunner {   
+    
+    public TaskRunner() {} 
+    
+    public static void main(String[] args) throws Exception {
+        if (args.length < 3) {
+            System.err.println("USAGE: java -cp roller-planet.jar TaskRunner WEBAPPDIR JARSDIR CLASSNAME");
+            System.err.println("WEBAPPDIR: The directory path to the web application ");
+            System.err.println("           (e.g. $CATALINA_HOME/webapps/roller)");
+            System.err.println("JARSDIR:   The directory path to the additional jars ");
+            System.err.println("           directory (e.g. $CATALINA_HOME/common/lib)");
+            System.err.println("CLASSNAME: The name of the class to be executed by TaskRunner ");
+            System.exit(-1);
+        }
+        String webappDir     = args[0];
+        String jarsDir       = args[1];
+        String taskClassName = args[2];
+        System.out.println("WEBAPPDIR = " + webappDir); 
+        System.out.println("JARSDIR   = " + jarsDir);
+        System.out.println("CLASSNAME = " + taskClassName);
+        
+        File webappDirFile = new File(webappDir);
+        File jarsDirFile = new File(jarsDir);
+        if (!webappDirFile.isDirectory() || !jarsDirFile.isDirectory()) {
+            System.err.println("ERROR: webapp.dir and jars.dir must specify existing directories");
+            System.exit(-1);
+        }        
+        
+        ClassLoader cl = new StandaloneWebappClassLoader(webappDir, jarsDir, null);
+       
+        // We're using the new classloader from here on out
+        Thread.currentThread().setContextClassLoader(cl);
+
+        // Go!
+        Class taskClass = cl.loadClass(taskClassName);
+        Runnable task = (Runnable)taskClass.newInstance();
+        task.run();
+    }
+}
+
+
+/* for example:
+ 
+java \
+    -Dplanet.custom.config=planet-custom.properties \
+    -Dcatalina.base=. \
+    -cp ./build/webapp/WEB-INF/lib/roller-business.jar \
+    org.apache.roller.util.TaskRunner \
+    ~/roller_trunk/sandbox/planetroller/build/webapp \
+    /Applications/Java/jakarta-tomcat-5.5.9/common/lib \
+    org.apache.roller.planet.tasks.GeneratePlanetTask
+ 
+ */

Added: incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/UtilitiesModel.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/UtilitiesModel.java?view=auto&rev=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/UtilitiesModel.java (added)
+++ incubator/roller/trunk/sandbox/planetroller/src/org/apache/roller/util/UtilitiesModel.java Mon Dec 11 20:54:19 2006
@@ -0,0 +1,527 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * 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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.RollerException;
+//import org.apache.roller.pojos.wrapper.WeblogEntryDataWrapper;
+//import org.apache.roller.pojos.wrapper.WebsiteDataWrapper;
+//import org.apache.roller.ui.core.RollerSession;
+//import org.apache.roller.ui.rendering.util.WeblogRequest;
+import org.apache.roller.util.DateUtil;
+import org.apache.roller.util.RegexUtil;
+import org.apache.roller.util.Utilities;
+
+/**
+ * Model which provides access to a set of general utilities.
+ */
+public class UtilitiesModel { // implements Model {
+    
+    private static Log log = LogFactory.getLog(UtilitiesModel.class); 
+    
+    private static Pattern mLinkPattern =
+            Pattern.compile("<a href=.*?>", Pattern.CASE_INSENSITIVE);    
+    private static final Pattern OPENING_B_TAG_PATTERN = 
+            Pattern.compile("&lt;b&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_B_TAG_PATTERN = 
+            Pattern.compile("&lt;/b&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_I_TAG_PATTERN = 
+            Pattern.compile("&lt;i&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_I_TAG_PATTERN = 
+            Pattern.compile("&lt;/i&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_BLOCKQUOTE_TAG_PATTERN = 
+            Pattern.compile("&lt;blockquote&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_BLOCKQUOTE_TAG_PATTERN = 
+            Pattern.compile("&lt;/blockquote&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern BR_TAG_PATTERN = 
+            Pattern.compile("&lt;br */*&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_P_TAG_PATTERN = 
+            Pattern.compile("&lt;p&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_P_TAG_PATTERN = 
+            Pattern.compile("&lt;/p&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_PRE_TAG_PATTERN = 
+            Pattern.compile("&lt;pre&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_PRE_TAG_PATTERN = 
+            Pattern.compile("&lt;/pre&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_UL_TAG_PATTERN = 
+            Pattern.compile("&lt;ul&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_UL_TAG_PATTERN = 
+            Pattern.compile("&lt;/ul&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_OL_TAG_PATTERN = 
+            Pattern.compile("&lt;ol&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_OL_TAG_PATTERN = 
+            Pattern.compile("&lt;/ol&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_LI_TAG_PATTERN = 
+            Pattern.compile("&lt;li&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_LI_TAG_PATTERN = 
+            Pattern.compile("&lt;/li&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern CLOSING_A_TAG_PATTERN = 
+            Pattern.compile("&lt;/a&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern OPENING_A_TAG_PATTERN = 
+            Pattern.compile("&lt;a href=.*?&gt;", Pattern.CASE_INSENSITIVE);
+    private static final Pattern QUOTE_PATTERN = 
+            Pattern.compile("&quot;", Pattern.CASE_INSENSITIVE);
+    
+    private HttpServletRequest request = null;
+    private TimeZone tz = null;
+    
+    
+    /** Template context name to be used for model */
+    public String getModelName() {
+        return "utils";
+    }
+    
+    
+//    /** Init page model based on request */
+//    public void init(Map initData) throws RollerException {
+//        
+//        // extract request object
+//        this.request = (HttpServletRequest) initData.get("request");        
+//
+//        // extract timezone if available
+//        WeblogRequest weblogRequest = (WeblogRequest)initData.get("weblogRequest");
+//        if (weblogRequest != null && weblogRequest.getWeblog() != null) {
+//            tz = weblogRequest.getWeblog().getTimeZoneInstance();
+//        }
+//    }
+//     
+//    
+//    //---------------------------------------------------- Authentication utils 
+//    
+//    public boolean isUserAuthorizedToAuthor(WebsiteDataWrapper weblog) {
+//        try {
+//            RollerSession rses = RollerSession.getRollerSession(request);
+//            if (rses != null && rses.getAuthenticatedUser() != null) {
+//                return rses.isUserAuthorizedToAuthor(weblog.getPojo());
+//            }
+//        } catch (Exception e) {
+//            log.warn("ERROR: checking user authorization", e);
+//        }
+//        return false;
+//    }
+//    
+//    public boolean isUserAuthorizedToAdmin(WebsiteDataWrapper weblog) {
+//        try {
+//            RollerSession rses = RollerSession.getRollerSession(request);
+//            if (rses != null && rses.getAuthenticatedUser() != null) {
+//                return rses.isUserAuthorizedToAdmin(weblog.getPojo());
+//            }
+//        } catch (Exception e) {
+//            log.warn("ERROR: checking user authorization", e);
+//        }
+//        return false;
+//    }
+//    
+//    public boolean isUserAuthenticated() {
+//        return (request.getUserPrincipal() != null);
+//    }
+        
+    //-------------------------------------------------------------- Date utils
+    /**
+     * Return date for current time.
+     */
+    public static Date getNow() {
+        return new Date();
+    }
+    
+    /**
+     * Format date using SimpleDateFormat format string.
+     */
+    public String formatDate(Date d, String fmt) {
+        if(d == null || fmt == null)
+            return fmt;
+        
+        SimpleDateFormat format = new SimpleDateFormat(fmt);
+        if (tz != null) {
+            format.setTimeZone(tz);
+        }
+        return format.format(d);
+    }
+    
+    /**
+     * Format date using SimpleDateFormat format string.
+     */
+    public static String formatDate(Date d, String fmt, TimeZone tzOverride) {
+        if(d == null || fmt == null)
+            return fmt;
+        
+        SimpleDateFormat format = new SimpleDateFormat(fmt);
+        format.setTimeZone(tzOverride);
+        return format.format(d);
+    }
+    
+    /**
+     * 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);
+    }
+
+    //------------------------------------------------------------ String utils
+    
+    public static boolean isEmpty(String str) {
+        if (str == null) return true;
+        return "".equals(str.trim());
+    }
+    
+    public static boolean isNotEmpty(String str) {
+        return !isEmpty(str);
+    }
+    
+    public static String[] split(String str1, String str2) {
+        return StringUtils.split(str1, str2);
+    }
+    
+    
+    public static boolean equals(String str1, String str2) {
+        return StringUtils.equals(str1, str2);
+    }
+    
+    public static boolean isAlphanumeric(String str) {
+        return StringUtils.isAlphanumeric(str);
+    }
+    
+    public static String[] stripAll(String[] strs) {
+        return StringUtils.stripAll(strs);
+    }
+    
+    public static String left(String str, int length) {
+        return StringUtils.left(str, length);
+    }
+    
+    public static String escapeHTML(String str) {
+        return StringEscapeUtils.escapeHtml(str);
+    }
+    
+    public static String unescapeHTML(String str) {
+        return StringEscapeUtils.unescapeHtml(str);
+    }
+    
+    public static String escapeXML(String str) {
+        return StringEscapeUtils.escapeXml(str);
+    }
+    
+    public static String unescapeXML(String str) {
+        return StringEscapeUtils.unescapeXml(str);
+    }
+    
+    public static String replace(String src, String target, String rWith) {
+        return StringUtils.replace(src, target, rWith);
+    }
+    
+    public static String replace(String src, String target, String rWith, int maxCount) {
+        return StringUtils.replace(src, target, rWith, maxCount);
+    }
+    
+    private static String replace(String string, Pattern pattern, String replacement) {
+        Matcher m = pattern.matcher(string);
+        return m.replaceAll(replacement);
+    }
+    
+    /**
+     * 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.
+     */
+    public static String removeHTML(String str, boolean addSpace) {
+        return Utilities.removeHTML(str, addSpace);
+    }
+        
+    /**
+     * Autoformat.
+     */
+    public static String autoformat(String s) {
+        String ret = StringUtils.replace(s, "\n", "<br />");
+        return ret;
+    }
+    /**
+     * 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;
+    }
+    
+    public static String truncateNicely(String str, int lower, int upper, String appendToEnd) {
+        return Utilities.truncateNicely(str, lower, upper, appendToEnd);
+    }
+    
+    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;
+    }    
+    
+    public static String hexEncode(String str) {
+        if (StringUtils.isEmpty(str)) return str;
+        
+        return RegexUtil.encode(str);
+    }
+    
+    public static String encodeEmail(String str) {
+        return str!=null ? RegexUtil.encodeEmail(str) : null;
+    }
+    
+    /**
+     * URL encoding.
+     * @param s a string to be URL-encoded
+     * @return URL encoding of s using character encoding UTF-8; null if s is null.
+     */
+    public static final String encode(String s) {
+        try {
+            if (s != null)
+                return URLEncoder.encode(s, "UTF-8");
+            else
+                return s;
+        } catch (UnsupportedEncodingException e) {
+            // Java Spec requires UTF-8 be in all Java environments, so this should not happen
+            return s;
+        }
+    }
+    
+    /**
+     * URL decoding.
+     * @param s a URL-encoded string to be URL-decoded
+     * @return URL decoded value of s using character encoding UTF-8; null if s is null.
+     */
+    public static final String decode(String s) {
+        try {
+            if (s != null)
+                return URLDecoder.decode(s, "UTF-8");
+            else
+                return s;
+        } catch (UnsupportedEncodingException e) {
+            // Java Spec requires UTF-8 be in all Java environments, so this should not happen
+            return s;
+        }
+    }
+        
+    /**
+     * 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();
+    }
+    
+    /**
+     * Transforms the given String into a subset of HTML displayable on a web
+     * page. The subset includes &lt;b&gt;, &lt;i&gt;, &lt;p&gt;, &lt;br&gt;,
+     * &lt;pre&gt; and &lt;a href&gt; (and their corresponding end tags).
+     *
+     * @param s   the String to transform
+     * @return    the transformed String
+     */
+    public static String transformToHTMLSubset(String s) {
+        
+        if (s == null) {
+            return null;
+        }
+        
+        s = replace(s, OPENING_B_TAG_PATTERN, "<b>");
+        s = replace(s, CLOSING_B_TAG_PATTERN, "</b>");
+        s = replace(s, OPENING_I_TAG_PATTERN, "<i>");
+        s = replace(s, CLOSING_I_TAG_PATTERN, "</i>");
+        s = replace(s, OPENING_BLOCKQUOTE_TAG_PATTERN, "<blockquote>");
+        s = replace(s, CLOSING_BLOCKQUOTE_TAG_PATTERN, "</blockquote>");
+        s = replace(s, BR_TAG_PATTERN, "<br />");
+        s = replace(s, OPENING_P_TAG_PATTERN, "<p>");
+        s = replace(s, CLOSING_P_TAG_PATTERN, "</p>");
+        s = replace(s, OPENING_PRE_TAG_PATTERN, "<pre>");
+        s = replace(s, CLOSING_PRE_TAG_PATTERN, "</pre>");
+        s = replace(s, OPENING_UL_TAG_PATTERN, "<ul>");
+        s = replace(s, CLOSING_UL_TAG_PATTERN, "</ul>");
+        s = replace(s, OPENING_OL_TAG_PATTERN, "<ol>");
+        s = replace(s, CLOSING_OL_TAG_PATTERN, "</ol>");
+        s = replace(s, OPENING_LI_TAG_PATTERN, "<li>");
+        s = replace(s, CLOSING_LI_TAG_PATTERN, "</li>");
+        s = replace(s, QUOTE_PATTERN, "\"");
+        
+        // HTTP links
+        s = replace(s, CLOSING_A_TAG_PATTERN, "</a>");
+        Matcher m = OPENING_A_TAG_PATTERN.matcher(s);
+        while (m.find()) {
+            int start = m.start();
+            int end = m.end();
+            String link = s.substring(start, end);
+            link = "<" + link.substring(4, link.length() - 4) + ">";
+            s = s.substring(0, start) + link + s.substring(end, s.length());
+            m = OPENING_A_TAG_PATTERN.matcher(s);
+        }
+        
+        // escaped angle brackets
+        s = s.replaceAll("&amp;lt;", "&lt;");
+        s = s.replaceAll("&amp;gt;", "&gt;");
+        s = s.replaceAll("&amp;#", "&#");
+        
+        return s;
+    }
+    
+    /**
+     * Convert a byte array into a Base64 string (as used in mime formats)
+     */
+    public static String toBase64(byte[] aValue) {
+        
+        final String m_strBase64Chars =
+                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+        
+        int byte1;
+        int byte2;
+        int byte3;
+        int iByteLen = aValue.length;
+        StringBuffer tt = new StringBuffer();
+        
+        for (int i = 0; i < iByteLen; i += 3) {
+            boolean bByte2 = (i + 1) < iByteLen;
+            boolean bByte3 = (i + 2) < iByteLen;
+            byte1 = aValue[i] & 0xFF;
+            byte2 = (bByte2) ? (aValue[i + 1] & 0xFF) : 0;
+            byte3 = (bByte3) ? (aValue[i + 2] & 0xFF) : 0;
+            
+            tt.append(m_strBase64Chars.charAt(byte1 / 4));
+            tt.append(m_strBase64Chars.charAt((byte2 / 16) + ((byte1 & 0x3) * 16)));
+            tt.append(((bByte2) ? m_strBase64Chars.charAt((byte3 / 64) + ((byte2 & 0xF) * 4)) : '='));
+            tt.append(((bByte3) ? m_strBase64Chars.charAt(byte3 & 0x3F) : '='));
+        }
+        
+        return tt.toString();
+    }
+       
+}

Modified: incubator/roller/trunk/sandbox/planetroller/web/WEB-INF/scripts/genplanet.sh
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/web/WEB-INF/scripts/genplanet.sh?view=diff&rev=486019&r1=486018&r2=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/web/WEB-INF/scripts/genplanet.sh (original)
+++ incubator/roller/trunk/sandbox/planetroller/web/WEB-INF/scripts/genplanet.sh Mon Dec 11 20:54:19 2006
@@ -19,7 +19,7 @@
 java \
     -Dcatalina.base=. \
     -Dplanet.custom.config=${CONFIG_OVERRIDE} \
-    -cp ${WEBAPP_DIR}/WEB-INF/lib/roller-business.jar \
-    org.apache.roller.business.runnable.TaskRunner \
+    -cp ${WEBAPP_DIR}/WEB-INF/lib/roller-planet.jar \
+    org.apache.roller.util.TaskRunner \
     ${WEBAPP_DIR} ${JARS_DIR} \
     org.apache.roller.planet.tasks.GeneratePlanetTask

Modified: incubator/roller/trunk/sandbox/planetroller/web/WEB-INF/scripts/refreshplanet.sh
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/sandbox/planetroller/web/WEB-INF/scripts/refreshplanet.sh?view=diff&rev=486019&r1=486018&r2=486019
==============================================================================
--- incubator/roller/trunk/sandbox/planetroller/web/WEB-INF/scripts/refreshplanet.sh (original)
+++ incubator/roller/trunk/sandbox/planetroller/web/WEB-INF/scripts/refreshplanet.sh Mon Dec 11 20:54:19 2006
@@ -19,7 +19,7 @@
 java \
     -Dcatalina.base=. \
     -Dplanet.custom.config=${CONFIG_OVERRIDE} \
-    -cp ${WEBAPP_DIR}/WEB-INF/lib/roller-business.jar \
-    org.apache.roller.business.runnable.TaskRunner \
+    -cp ${WEBAPP_DIR}/WEB-INF/lib/roller-planet.jar \
+    org.apache.roller.util.TaskRunner \
     ${WEBAPP_DIR} ${JARS_DIR} \
     org.apache.roller.planet.tasks.RefreshPlanetTask