You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by ag...@apache.org on 2006/04/09 00:36:28 UTC

svn commit: r392618 [2/5] - in /incubator/roller/branches/roller-newbackend/src/org/roller/business: ./ hibernate/ search/operations/

Modified: incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePingQueueManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePingQueueManagerImpl.java?rev=392618&r1=392617&r2=392618&view=diff
==============================================================================
--- incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePingQueueManagerImpl.java (original)
+++ incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePingQueueManagerImpl.java Sat Apr  8 15:36:25 2006
@@ -16,123 +16,181 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.roller.RollerException;
-import org.roller.business.PersistenceStrategy;
-import org.roller.business.PingQueueManagerImpl;
 import org.roller.pojos.AutoPingData;
 import org.roller.pojos.PingQueueEntryData;
 import org.roller.pojos.WebsiteData;
 import org.roller.pojos.PingTargetData;
-
 import java.sql.Timestamp;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Collection;
+import org.roller.model.PingQueueManager;
 
-public class HibernatePingQueueManagerImpl extends PingQueueManagerImpl
-{
-    static final long serialVersionUID = -7660638707453106615L;
-
-    private static Log logger = LogFactory.getLog(HibernatePingQueueManagerImpl.class);
-
-    public HibernatePingQueueManagerImpl(PersistenceStrategy persistenceStrategy)
-    {
-        super(persistenceStrategy);
-    }
-
-    public void addQueueEntry(AutoPingData autoPing) throws RollerException
-    {
-        if (logger.isDebugEnabled()) logger.debug("Creating new ping queue entry for auto ping configuration: " + autoPing);
 
-        // First check if there is an existing ping queue entry for the same target and website
-        if (isAlreadyQueued(autoPing))
-        {
-            if (logger.isDebugEnabled()) logger.debug("A ping queue entry is already present for this ping target and website: " + autoPing);
-            return;
-        }
-
-        Timestamp now = new Timestamp(System.currentTimeMillis());
-        PingQueueEntryData pingQueueEntry =
-            new PingQueueEntryData(null, now, autoPing.getPingTarget(), autoPing.getWebsite(), 0);
-        storeQueueEntry(pingQueueEntry);
-    }
-
-    public void dropQueue() throws RollerException
-    {
-        logger.info("NOTICE Dropping all ping queue entries.");
-        List queueEntries = getAllQueueEntries();
-        removeEntries(queueEntries);
-    }
-
-    public List getAllQueueEntries() throws RollerException
-    {
-        Session session = ((HibernateStrategy) persistenceStrategy).getSession();
-        Criteria criteria = session.createCriteria(PingQueueEntryData.class);
-        criteria.addOrder(Order.asc("entryTime"));
-        try
-        {
-            return criteria.list();
-        }
-        catch (HibernateException e)
-        {
-            throw new RollerException("ERROR retrieving queue entries.", e);
-        }
+/**
+ * Hibernate implementation of the PingQueueManager.
+ */
+public class HibernatePingQueueManagerImpl implements PingQueueManager {
+    
+    static final long serialVersionUID = -7660638707453106615L;
+    
+    private static Log log = LogFactory.getLog(HibernatePingQueueManagerImpl.class);
+    
+    private HibernatePersistenceStrategy strategy = null;
+    
+    
+    public HibernatePingQueueManagerImpl(HibernatePersistenceStrategy strat) {
+        this.strategy = strat;
+    }
+    
+    
+    public PingQueueEntryData retrieveQueueEntry(String id) throws RollerException {
+        return (PingQueueEntryData) strategy.load(id, PingQueueEntryData.class);
+    }
+    
+    
+    public void storeQueueEntry(PingQueueEntryData pingQueueEntry) throws RollerException {
+        log.debug("Storing ping queue entry: " + pingQueueEntry);
+        strategy.storeAndCommit(pingQueueEntry);
+    }
+    
+    
+    public void removeQueueEntry(String id) throws RollerException {
+        log.debug("Removing ping queue entry with id: " + id);
+        strategy.removeAndCommit(id, PingQueueEntryData.class);
+    }
+    
+    
+    public void removeQueueEntry(PingQueueEntryData pingQueueEntry) throws RollerException {
+        log.debug("Removing ping queue entry: " + pingQueueEntry);
+        strategy.removeAndCommit(pingQueueEntry);
     }
-
+    
+    
     public void removeQueueEntriesByPingTarget(PingTargetData pingTarget) throws RollerException {
-        try
-        {
-            if (logger.isDebugEnabled()) logger.debug("Removing all ping queue entries for ping target " + pingTarget);
-            Session session = ((HibernateStrategy) persistenceStrategy).getSession();
+        
+        try {
+            log.debug("Removing all ping queue entries for ping target " + pingTarget);
+            
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = strategy.getSession();
             Criteria criteria = session.createCriteria(PingQueueEntryData.class);
             criteria.add(Expression.eq("pingTarget", pingTarget));
             List queueEntries = criteria.list();
             removeEntries(queueEntries);
-        }
-        catch (HibernateException e)
-        {
+        } catch (HibernateException e) {
             throw new RollerException("ERROR removing queue entries for ping target " + pingTarget, e);
         }
     }
-
+    
+    
     public void removeQueueEntriesByWebsite(WebsiteData website) throws RollerException {
-        try
-        {
-            if (logger.isDebugEnabled()) logger.debug("Removing all ping queue entries for website " + website);
-            Session session = ((HibernateStrategy) persistenceStrategy).getSession();
+        
+        try {
+            log.debug("Removing all ping queue entries for website " + website);
+            
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
             Criteria criteria = session.createCriteria(PingQueueEntryData.class);
             criteria.add(Expression.eq("website", website));
             List queueEntries = criteria.list();
             removeEntries(queueEntries);
-        }
-        catch (HibernateException e)
-        {
+        } catch (HibernateException e) {
             throw new RollerException("ERROR removing queue entries for website " + website, e);
         }
     }
-
+    
+    
+    public void addQueueEntry(AutoPingData autoPing) throws RollerException {
+        log.debug("Creating new ping queue entry for auto ping configuration: " + autoPing);
+        
+        // First check if there is an existing ping queue entry for the same target and website
+        if (isAlreadyQueued(autoPing)) {
+            log.debug("A ping queue entry is already present for this ping target and website: " + autoPing);
+            return;
+        }
+        
+        Timestamp now = new Timestamp(System.currentTimeMillis());
+        PingQueueEntryData pingQueueEntry =
+                new PingQueueEntryData(null, now, autoPing.getPingTarget(), autoPing.getWebsite(), 0);
+        this.storeQueueEntry(pingQueueEntry);
+    }
+    
+    
+    public void dropQueue() throws RollerException {
+        log.info("NOTICE Dropping all ping queue entries.");
+        List queueEntries = getAllQueueEntries();
+        removeEntries(queueEntries);
+    }
+    
+    
+    public List getAllQueueEntries() throws RollerException {
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+            Criteria criteria = session.createCriteria(PingQueueEntryData.class);
+            criteria.addOrder(Order.asc("entryTime"));
+            
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException("ERROR retrieving queue entries.", e);
+        }
+    }
+    
+    
     // private helper to determine if an has already been queued for the same website and ping target.
-    private boolean isAlreadyQueued(AutoPingData autoPing) throws RollerException
-    {
-        try
-        {
-            Session session = ((HibernateStrategy) persistenceStrategy).getSession();
+    private boolean isAlreadyQueued(AutoPingData autoPing) throws RollerException {
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
             Criteria criteria = session.createCriteria(PingQueueEntryData.class);
             criteria.add(Expression.eq("pingTarget", autoPing.getPingTarget()));
             criteria.add(Expression.eq("website", autoPing.getWebsite()));
             return !criteria.list().isEmpty();
-        }
-        catch (HibernateException e)
-        {
+        } catch (HibernateException e) {
             throw new RollerException("ERROR determining if preexisting queue entry is present.",e);
         }
     }
-
+    
+    
     // Private helper to remove a collection of queue entries
     private void removeEntries(Collection queueEntries) throws RollerException {
-        for (Iterator i = queueEntries.iterator(); i.hasNext();)
-        {
-            PingQueueEntryData pqe = (PingQueueEntryData) i.next();
-            pqe.remove();
-        }
-    }
+        
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            // just go through the list and remove each auto ping
+            Iterator entries = queueEntries.iterator();
+            while (entries.hasNext()) {
+                    this.strategy.remove((PingQueueEntryData) entries.next());
+            }
+            
+            // commit changes
+            this.strategy.getSession().getTransaction().commit();
+        } catch (HibernateException ex) {
+            
+            try {
+                this.strategy.getSession().getTransaction().rollback();
+            } catch(HibernateException he) {
+                log.error("Error doing rollback", he);
+            }
+            
+            strategy.release();
+            
+            throw new RollerException(ex);
+        }
+    }
+    
+    
+    public void release() {}
+    
 }

Modified: incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePingTargetManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePingTargetManagerImpl.java?rev=392618&r1=392617&r2=392618&view=diff
==============================================================================
--- incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePingTargetManagerImpl.java (original)
+++ incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePingTargetManagerImpl.java Sat Apr  8 15:36:25 2006
@@ -8,106 +8,230 @@
 
 package org.roller.business.hibernate;
 
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.UnknownHostException;
 import org.hibernate.Criteria;
 import org.hibernate.HibernateException;
 import org.hibernate.Session;
 import org.hibernate.criterion.Expression;
 import org.hibernate.criterion.Order;
 import org.roller.RollerException;
-import org.roller.business.PersistenceStrategy;
-import org.roller.business.PingTargetManagerImpl;
 import org.roller.pojos.PingTargetData;
 import org.roller.pojos.WebsiteData;
-
 import java.util.Iterator;
 import java.util.List;
 import java.util.Collection;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.model.PingTargetManager;
 
-public class HibernatePingTargetManagerImpl extends PingTargetManagerImpl
-{
-    static final long serialVersionUID = 121008492583382718L;
 
-    public HibernatePingTargetManagerImpl(PersistenceStrategy persistenceStrategy)
-    {
-        super(persistenceStrategy);
+/**
+ * Hibernate implementation of the PingTargetManager.
+ */
+public class HibernatePingTargetManagerImpl implements PingTargetManager {
+    
+    static final long serialVersionUID = 121008492583382718L;
+    
+    private static Log log = LogFactory.getLog(HibernatePingTargetManagerImpl.class);
+    
+    private HibernatePersistenceStrategy strategy = null;
+    
+    
+    public HibernatePingTargetManagerImpl(HibernatePersistenceStrategy strat) {
+        this.strategy = strat;
+    }
+    
+    
+    public PingTargetData createCommonPingTarget(String name, String pingUrl) throws RollerException {
+        return new PingTargetData(null, name, pingUrl, null);
+    }
+    
+    
+    public PingTargetData createCustomPingTarget(String name, String pingUrl, WebsiteData website) throws RollerException {
+        if (website == null) throw new RollerException(new IllegalArgumentException("website == null"));
+        return new PingTargetData(null, name, pingUrl, website);
+    }
+    
+    
+    public void storePingTarget(PingTargetData pingTarget) throws RollerException {
+        strategy.storeAndCommit(pingTarget);
+    }
+    
+    
+    public PingTargetData retrievePingTarget(String id) throws RollerException {
+        return (PingTargetData) strategy.load(id, PingTargetData.class);
+    }
+    
+    
+    public void removePingTarget(String id) throws RollerException {
+        // The retrieval is necessary in order to do the necessary cleanup of references in pingTarget.remove().
+        PingTargetData pingTarget = retrievePingTarget(id);
+        strategy.removeAndCommit(pingTarget);
     }
-
+    
+    
     /**
-     * @see org.roller.model.PingTargetManager#getCommonPingTargets()
+     * @see org.roller.model.PingTargetManager#removeCustomPingTargets(org.roller.pojos.WebsiteData)
      */
-    public List getCommonPingTargets() throws RollerException
-    {
-        try
-        {
-            Session session = ((HibernateStrategy) persistenceStrategy).getSession();
+    public void removeCustomPingTargets(WebsiteData website) throws RollerException {
+        List customTargets = getCustomPingTargets(website);
+        removeTargets(customTargets);
+    }
+    
+    
+    /**
+     * @see org.roller.model.PingTargetManager#removeAllCustomPingTargets()
+     */
+    public void removeAllCustomPingTargets() throws RollerException {
+        
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = strategy.getSession();
             Criteria criteria = session.createCriteria(PingTargetData.class);
-            criteria.add(Expression.isNull("website"));
-            criteria.addOrder(Order.asc("name"));
-            return criteria.list();
-        }
-        catch (HibernateException e)
-        {
+            criteria.add(Expression.isNotNull("website"));
+            List allCustomTargets = criteria.list();
+            removeTargets(allCustomTargets);
+        } catch (HibernateException e) {
             throw new RollerException(e);
         }
-
     }
-
+    
+    
+    // Private helper to remove a collection of targets.
+    private void removeTargets(Collection customTargets) throws RollerException {
+        
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            // just go through the list and remove each auto ping
+            Iterator targets = customTargets.iterator();
+            while (targets.hasNext()) {
+                    this.strategy.remove((PingTargetData) targets.next());
+            }
+            
+            // commit changes
+            this.strategy.getSession().getTransaction().commit();
+        } catch (HibernateException ex) {
+            
+            try {
+                this.strategy.getSession().getTransaction().rollback();
+            } catch(HibernateException he) {
+                log.error("Error doing rollback", he);
+            }
+            
+            strategy.release();
+            
+            throw new RollerException(ex);
+        }
+    }
+    
+    
+    public boolean isNameUnique(PingTargetData pingTarget) throws RollerException {
+        String name = pingTarget.getName();
+        if (name == null || name.trim().length() == 0) return false;
+        
+        String id = pingTarget.getId();
+        
+        // Determine the set of "brother" targets (custom or common) among which this name should be unique.
+        List brotherTargets = null;
+        WebsiteData website = pingTarget.getWebsite();
+        if (website == null) {
+            brotherTargets = getCommonPingTargets();
+        } else {
+            brotherTargets = getCustomPingTargets(website);
+        }
+        
+        // Within that set of targets, fail if there is a target with the same name and that target doesn't
+        // have the same id.
+        for (Iterator i = brotherTargets.iterator(); i.hasNext();) {
+            PingTargetData brother = (PingTargetData) i.next();
+            // Fail if it has the same name but not the same id.
+            if (brother.getName().equals(name) && (id == null || !brother.getId().equals(id))) {
+                return false;
+            }
+        }
+        // No conflict found
+        return true;
+    }
+    
+    
+    public boolean isUrlWellFormed(PingTargetData pingTarget) throws RollerException {
+        String url = pingTarget.getPingUrl();
+        if (url == null || url.trim().length() == 0) return false;
+        try {
+            URL parsedUrl = new URL(url);
+            // OK.  If we get here, it parses ok.  Now just check that the protocol is http and there is a host portion.
+            boolean isHttp = parsedUrl.getProtocol().equals("http");
+            boolean hasHost = (parsedUrl.getHost() != null) && (parsedUrl.getHost().trim().length() > 0);
+            return isHttp && hasHost;
+        } catch (MalformedURLException e) {
+            return false;
+        }
+    }
+    
+    
+    public boolean isHostnameKnown(PingTargetData pingTarget) throws RollerException {
+        String url = pingTarget.getPingUrl();
+        if (url == null || url.trim().length() == 0) return false;
+        try {
+            URL parsedUrl = new URL(url);
+            String host = parsedUrl.getHost();
+            if (host == null || host.trim().length() == 0) return false;
+            InetAddress addr = InetAddress.getByName(host);
+            return true;
+        } catch (MalformedURLException e) {
+            return false;
+        } catch (UnknownHostException e) {
+            return false;
+        }
+    }
+    
+    
     /**
-     * @see org.roller.model.PingTargetManager#getCustomPingTargets(org.roller.pojos.WebsiteData)
+     * @see org.roller.model.PingTargetManager#getCommonPingTargets()
      */
-    public List getCustomPingTargets(WebsiteData website) throws RollerException
-    {
-        try
-        {
-            Session session = ((HibernateStrategy) persistenceStrategy).getSession();
+    public List getCommonPingTargets() throws RollerException {
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
             Criteria criteria = session.createCriteria(PingTargetData.class);
-            criteria.add(Expression.eq("website", website));
+            criteria.add(Expression.isNull("website"));
             criteria.addOrder(Order.asc("name"));
             return criteria.list();
-        }
-        catch (HibernateException e)
-        {
+        } catch (HibernateException e) {
             throw new RollerException(e);
         }
+        
     }
-
-    /**
-     * @see org.roller.model.PingTargetManager#removeCustomPingTargets(org.roller.pojos.WebsiteData) 
-     */
-    public void removeCustomPingTargets(WebsiteData website) throws RollerException
-    {
-        List customTargets = getCustomPingTargets(website);
-        removeTargets(customTargets);
-    }
-
+    
+    
     /**
-     * @see org.roller.model.PingTargetManager#removeAllCustomPingTargets()
+     * @see org.roller.model.PingTargetManager#getCustomPingTargets(org.roller.pojos.WebsiteData)
      */
-    public void removeAllCustomPingTargets() throws RollerException
-    {
-        try
-        {
-            Session session = ((HibernateStrategy) persistenceStrategy).getSession();
+    public List getCustomPingTargets(WebsiteData website) throws RollerException {
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
             Criteria criteria = session.createCriteria(PingTargetData.class);
-            criteria.add(Expression.isNotNull("website"));
-            List allCustomTargets = criteria.list();
-            removeTargets(allCustomTargets);
-        }
-        catch (HibernateException e)
-        {
+            criteria.add(Expression.eq("website", website));
+            criteria.addOrder(Order.asc("name"));
+            return criteria.list();
+        } catch (HibernateException e) {
             throw new RollerException(e);
         }
     }
-
-    // Private helper to remove a collection of targets.
-    private void removeTargets(Collection customTargets)
-        throws RollerException
-    {
-        for (Iterator i = customTargets.iterator(); i.hasNext();)
-        {
-            PingTargetData pt = (PingTargetData) i.next();
-            pt.remove();
-        }
-    }
-
+    
+    
+    public void release() {}
+    
 }

Modified: incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePlanetManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePlanetManagerImpl.java?rev=392618&r1=392617&r2=392618&view=diff
==============================================================================
--- incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePlanetManagerImpl.java (original)
+++ incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePlanetManagerImpl.java Sat Apr  8 15:36:25 2006
@@ -16,10 +16,17 @@
 
 package org.roller.business.hibernate;
 
+import com.sun.syndication.feed.synd.SyndEntry;
+import com.sun.syndication.feed.synd.SyndFeed;
 import com.sun.syndication.fetcher.FeedFetcher;
 import com.sun.syndication.fetcher.impl.FeedFetcherCache;
+import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher;
+import com.sun.syndication.fetcher.impl.SyndFeedInfo;
+import java.io.File;
+import java.net.URL;
 import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -27,23 +34,21 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
-
+import org.apache.commons.lang.StringUtils;
 import org.hibernate.Criteria;
 import org.hibernate.HibernateException;
 import org.hibernate.Query;
 import org.hibernate.Session;
 import org.hibernate.criterion.Expression;
 import org.hibernate.criterion.Order;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.velocity.VelocityContext;
 import org.roller.RollerException;
-import org.roller.business.PersistenceStrategy;
-import org.roller.business.PlanetManagerImpl;
 import org.roller.config.RollerConfig;
 import org.roller.config.RollerRuntimeConfig;
 import org.roller.model.PagePluginManager;
+import org.roller.model.PlanetManager;
 import org.roller.model.Roller;
 import org.roller.model.UserManager;
 import org.roller.model.WeblogManager;
@@ -54,56 +59,109 @@
 import org.roller.pojos.PlanetSubscriptionData;
 import org.roller.pojos.WeblogEntryData;
 import org.roller.pojos.WebsiteData;
+import org.roller.util.rome.DiskFeedInfoCache;
+
 
 /**
- * Manages Planet Roller objects and entry aggregations in a database.
- * @author Dave Johnson
+ * Hibernate implementation of the PlanetManager.
  */
-public class HibernatePlanetManagerImpl extends PlanetManagerImpl {
-    protected Map lastUpdatedByGroup = new HashMap();
+public class HibernatePlanetManagerImpl implements PlanetManager {
+    
+    private static Log log = LogFactory.getLog(HibernatePlanetManagerImpl.class);
+    
     protected static final String NO_GROUP = "zzz_nogroup_zzz";
     
-    private static Log logger =
-            LogFactory.getFactory().getInstance(HibernatePlanetManagerImpl.class);
+    private Roller roller = null;
+    private HibernatePersistenceStrategy strategy = null;
+    private String localURL = null;
+    private Map lastUpdatedByGroup = new HashMap();
     
-    public HibernatePlanetManagerImpl(
-            PersistenceStrategy strategy, Roller roller) {
-        super(strategy, roller);
+    
+    public HibernatePlanetManagerImpl(HibernatePersistenceStrategy strat, Roller roller) {
+        this.strategy = strat;
+        this.roller = roller;
+        // TODO: this is bad.  this property should be in the planet config.
+        localURL = RollerRuntimeConfig.getProperty("site.absoluteurl");
     }
     
-    public void saveConfiguration(PlanetConfigData config)
-    throws RollerException {
-        config.save();
+    
+    public void saveConfiguration(PlanetConfigData config) throws RollerException {
+        strategy.storeAndCommit(config);
     }
     
+    
     public void saveGroup(PlanetGroupData group) throws RollerException {
-        Iterator assocs = group.getGroupSubscriptionAssocs().iterator();
-        while (assocs.hasNext()) {
-            PlanetGroupSubscriptionAssoc assoc =
-                    (PlanetGroupSubscriptionAssoc)assocs.next();
-            assoc.save();
+        // TODO: decide how to handle saving members of objects
+        // NOTE: with hibernate, cascade="all" should handle this for us
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            // save each sub assoc first, then the group
+            Iterator assocs = group.getGroupSubscriptionAssocs().iterator();
+            while (assocs.hasNext()) {
+                PlanetGroupSubscriptionAssoc assoc =
+                        (PlanetGroupSubscriptionAssoc)assocs.next();
+                strategy.store(assoc);
+            }
+            strategy.store(group);
+            
+            // commit changes
+            this.strategy.getSession().getTransaction().commit();
+        } catch (HibernateException ex) {
+            
+            try {
+                this.strategy.getSession().getTransaction().rollback();
+            } catch(HibernateException he) {
+                log.error("Error doing rollback", he);
+            }
+            
+            strategy.release();
+            
+            throw new RollerException(ex);
         }
-        group.save();
+        
     }
     
+    
     public void saveEntry(PlanetEntryData entry) throws RollerException {
-        entry.save();
+        strategy.storeAndCommit(entry);
     }
     
-    public void saveSubscription(PlanetSubscriptionData sub)
-    throws RollerException {
+    
+    public void saveSubscription(PlanetSubscriptionData sub) throws RollerException {
         PlanetSubscriptionData existing = getSubscription(sub.getFeedUrl());
         if (existing == null || (existing.getId().equals(sub.getId()))) {
-            sub.save();
+            this.strategy.storeAndCommit(sub);
         } else {
             throw new RollerException("ERROR: duplicate feed URLs not allowed");
         }
     }
     
+    
+    public void deleteEntry(PlanetEntryData entry) throws RollerException {
+        strategy.removeAndCommit(entry);
+    }
+    
+    
+    public void deleteGroup(PlanetGroupData group) throws RollerException {
+        // TODO: how to remove hierarchical objects
+        strategy.removeAndCommit(group);
+    }
+    
+    
+    public void deleteSubscription(PlanetSubscriptionData sub) throws RollerException {
+        strategy.removeAndCommit(sub);
+    }
+    
+    
     public PlanetConfigData getConfiguration() throws RollerException {
         PlanetConfigData config = null;
         try {
-            Session session = ((HibernateStrategy)strategy).getSession();
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
             Criteria criteria = session.createCriteria(PlanetConfigData.class);
             criteria.setMaxResults(1);
             List list = criteria.list();
@@ -121,77 +179,169 @@
         return config;
     }
     
-    public List getGroups() throws RollerException {
+    
+    public PlanetSubscriptionData getSubscription(String feedUrl) throws RollerException {
         try {
-            Session session = ((HibernateStrategy)strategy).getSession();
-            Criteria criteria = session.createCriteria(PlanetGroupData.class);
-            return criteria.list();
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria =
+                    session.createCriteria(PlanetSubscriptionData.class);
+            criteria.setMaxResults(1);
+            criteria.add(Expression.eq("feedUrl", feedUrl));
+            List list = criteria.list();
+            return list.size()!=0 ? (PlanetSubscriptionData)list.get(0) : null;
         } catch (HibernateException e) {
             throw new RollerException(e);
         }
     }
     
-    public List getGroupHandles() throws RollerException {
-        List handles = new ArrayList();
-        Iterator list = getGroups().iterator();
-        while (list.hasNext()) {
-            PlanetGroupData group = (PlanetGroupData)list.next();
-            handles.add(group.getHandle());
-        }
-        return handles;
+    
+    public PlanetSubscriptionData getSubscriptionById(String id) throws RollerException {
+        return (PlanetSubscriptionData) strategy.load(id, PlanetSubscriptionData.class);
     }
     
-    public PlanetSubscriptionData getSubscription(String feedUrl)
-    throws RollerException {
+    
+    public Iterator getAllSubscriptions() {
         try {
-            Session session = ((HibernateStrategy)strategy).getSession();
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
             Criteria criteria =
                     session.createCriteria(PlanetSubscriptionData.class);
-            criteria.setMaxResults(1);
-            criteria.add(Expression.eq("feedUrl", feedUrl));
+            criteria.addOrder(Order.asc("feedUrl"));
             List list = criteria.list();
-            return list.size()!=0 ? (PlanetSubscriptionData)list.get(0) : null;
+            return list.iterator();
+        } catch (Throwable e) {
+            throw new RuntimeException(
+                    "ERROR fetching subscription collection", e);
+        }
+    }
+    
+    public int getSubscriptionCount() throws RollerException {
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Integer count = (Integer)session.createQuery(
+                    "select count(*) from org.roller.pojos.PlanetSubscriptionData").uniqueResult();
+            return count.intValue();
+        } catch (Throwable e) {
+            throw new RuntimeException(
+                    "ERROR fetching subscription count", e);
+        }
+    }
+    
+    public synchronized List getTopSubscriptions(int max) throws RollerException {
+        String groupHandle = NO_GROUP;
+        List ret = null;
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria =
+                    session.createCriteria(PlanetSubscriptionData.class);
+            criteria.setMaxResults(max);
+            criteria.addOrder(Order.desc("inboundblogs"));
+            ret = criteria.list();
         } catch (HibernateException e) {
             throw new RollerException(e);
         }
+        return ret;
     }
     
-    public PlanetSubscriptionData getSubscriptionById(String id)
-    throws RollerException {
-        return (PlanetSubscriptionData)
-        strategy.load(id, PlanetSubscriptionData.class);
+    public synchronized List getTopSubscriptions(
+            PlanetGroupData group, int max) throws RollerException {
+        String groupHandle = (group == null) ? NO_GROUP : group.getHandle();
+        List ret = null;
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Query query = session.createQuery(
+                    "select sub from org.roller.pojos.PlanetSubscriptionData sub "
+                    +"join sub.groupSubscriptionAssocs assoc "
+                    +"where "
+                    +"assoc.group.handle=:groupHandle "
+                    +"order by sub.inboundblogs desc");
+            query.setString("groupHandle", group.getHandle());
+            query.setMaxResults(max);
+            ret = query.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+        return ret;
     }
     
+    
     public PlanetGroupData getGroup(String handle) throws RollerException {
         try {
-            Session session = ((HibernateStrategy)strategy).getSession();
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = strategy.getSession();
             Criteria criteria = session.createCriteria(PlanetGroupData.class);
             criteria.setMaxResults(1);
             criteria.add(Expression.eq("handle", handle));
-            List list = criteria.list();
-            return list.size()!=0 ? (PlanetGroupData)list.get(0) : null;
+            return (PlanetGroupData) criteria.uniqueResult();
         } catch (HibernateException e) {
             throw new RollerException(e);
         }
     }
     
     public PlanetGroupData getGroupById(String id) throws RollerException {
-        return (PlanetGroupData)
-        strategy.load(id, PlanetGroupData.class);
+        return (PlanetGroupData) strategy.load(id, PlanetGroupData.class);
     }
     
+    
+    public List getGroups() throws RollerException {
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(PlanetGroupData.class);
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    public List getGroupHandles() throws RollerException {
+        List handles = new ArrayList();
+        Iterator list = getGroups().iterator();
+        while (list.hasNext()) {
+            PlanetGroupData group = (PlanetGroupData)list.next();
+            handles.add(group.getHandle());
+        }
+        return handles;
+    }
+    
+    
     public synchronized List getAggregation(int maxEntries) throws RollerException {
         return getAggregation(null, maxEntries);
     }
     
+    
     public synchronized List getAggregation(PlanetGroupData group, int maxEntries)
-    throws RollerException {
+            throws RollerException {
+        
         List ret = null;
         try {
             String groupHandle = (group == null) ? NO_GROUP : group.getHandle();
             long startTime = System.currentTimeMillis();
             Session session =
-                    ((HibernateStrategy)strategy).getSession();
+                    ((HibernatePersistenceStrategy)strategy).getSession();
+            
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
             if (group != null) {
                 Query query = session.createQuery(
                         "select entry from org.roller.pojos.PlanetEntryData entry "
@@ -220,102 +370,124 @@
             lastUpdatedByGroup.put(groupHandle, retLastUpdated);
             
             long endTime = System.currentTimeMillis();
-            logger.info("Generated aggregation in "
+            log.info("Generated aggregation in "
                     +((endTime-startTime)/1000.0)+" seconds");
         } catch (Throwable e) {
-            logger.error("ERROR: building aggregation for: "+group, e);
+            log.error("ERROR: building aggregation for: "+group, e);
             throw new RollerException(e);
         }
         return ret;
     }
     
-    public void deleteEntry(PlanetEntryData entry) throws RollerException {
-        entry.remove();
-    }
     
-    public void deleteGroup(PlanetGroupData group) throws RollerException {
-        group.remove();
+    public synchronized void clearCachedAggregations() {
+        lastUpdatedByGroup.clear();
     }
     
-    public void deleteSubscription(PlanetSubscriptionData sub)
-    throws RollerException {
-        sub.remove();
+    public Date getLastUpdated() {
+        return (Date)lastUpdatedByGroup.get(NO_GROUP);
     }
     
-    public Iterator getAllSubscriptions() {
-        try {
-            Session session = ((HibernateStrategy)strategy).getSession();
-            Criteria criteria =
-                    session.createCriteria(PlanetSubscriptionData.class);
-            criteria.addOrder(Order.asc("feedUrl"));
-            List list = criteria.list();
-            return list.iterator();
-        } catch (Throwable e) {
-            throw new RuntimeException(
-                    "ERROR fetching subscription collection", e);
-        }
+    public Date getLastUpdated(PlanetGroupData group) {
+        return (Date)lastUpdatedByGroup.get(group);
     }
     
-    public int getSubscriptionCount() throws RollerException {
-        try {
-            Session session = ((HibernateStrategy)strategy).getSession();
-            Integer count = (Integer)session.createQuery(
-                    "select count(*) from org.roller.pojos.PlanetSubscriptionData").uniqueResult();
-            return count.intValue();
-        } catch (Throwable e) {
-            throw new RuntimeException(
-                    "ERROR fetching subscription count", e);
-        }
-    }
     
-    public synchronized List getTopSubscriptions(int max) throws RollerException {
-        String groupHandle = NO_GROUP;
-        List ret = null;
-        try {
-            Session session = ((HibernateStrategy)strategy).getSession();
-            Criteria criteria =
-                    session.createCriteria(PlanetSubscriptionData.class);
-            criteria.setMaxResults(max);
-            criteria.addOrder(Order.desc("inboundblogs"));
-            ret = criteria.list();
-        } catch (HibernateException e) {
-            throw new RollerException(e);
+    public void refreshEntries() throws RollerException {
+        
+        Date now = new Date();
+        long startTime = System.currentTimeMillis();
+        PlanetConfigData config = getConfiguration();
+        
+        // can't continue without cache dir
+        if (config == null || config.getCacheDir() == null) {
+            log.warn("Planet cache directory not set, aborting refresh");
+            return;
         }
-        return ret;
-    }
-    
-    public synchronized List getTopSubscriptions(
-            PlanetGroupData group, int max) throws RollerException {
-        String groupHandle = (group == null) ? NO_GROUP : group.getHandle();
-        List ret = null;
+        
+        // allow ${user.home} in cache dir property
+        String cacheDirName = config.getCacheDir().replaceFirst(
+                "\\$\\{user.home}",System.getProperty("user.home"));
+        
+        // allow ${catalina.home} in cache dir property
+        cacheDirName = cacheDirName.replaceFirst(
+                "\\$\\{catalina.home}",System.getProperty("catalina.home"));
+        
+        // create cache  dir if it does not exist
+        File cacheDir = null;
         try {
-            Session session = ((HibernateStrategy)strategy).getSession();
-            Query query = session.createQuery(
-                    "select sub from org.roller.pojos.PlanetSubscriptionData sub "
-                    +"join sub.groupSubscriptionAssocs assoc "
-                    +"where "
-                    +"assoc.group.handle=:groupHandle "
-                    +"order by sub.inboundblogs desc");
-            query.setString("groupHandle", group.getHandle());
-            query.setMaxResults(max);
-            ret = query.list();
-        } catch (HibernateException e) {
-            throw new RollerException(e);
+            cacheDir = new File(cacheDirName);
+            if (!cacheDir.exists()) cacheDir.mkdirs();
+        } catch (Exception e) {
+            log.error("Unable to create planet cache directory");
+            return;
         }
-        return ret;
-    }
-    
-    public synchronized void clearCachedAggregations() {
-        lastUpdatedByGroup.clear();
-    }
-    
-    public Date getLastUpdated() {
-        return (Date)lastUpdatedByGroup.get(NO_GROUP);
+        
+        // abort if cache dir is not writable
+        if (!cacheDir.canWrite()) {
+            log.error("Planet cache directory is not writable");
+            return;
+        }
+        
+        FeedFetcherCache feedInfoCache =
+                new DiskFeedInfoCache(cacheDirName);
+        
+        if (config.getProxyHost()!=null && config.getProxyPort() > 0) {
+            System.setProperty("proxySet", "true");
+            System.setProperty("http.proxyHost", config.getProxyHost());
+            System.setProperty("http.proxyPort",
+                    Integer.toString(config.getProxyPort()));
+        }
+        /** a hack to set 15 sec timeouts for java.net.HttpURLConnection */
+        System.setProperty("sun.net.client.defaultConnectTimeout", "15000");
+        System.setProperty("sun.net.client.defaultReadTimeout", "15000");
+        
+        FeedFetcher feedFetcher = new HttpURLFeedFetcher(feedInfoCache);
+        //FeedFetcher feedFetcher = new HttpClientFeedFetcher(feedInfoCache);
+        feedFetcher.setUsingDeltaEncoding(false);
+        feedFetcher.setUserAgent("RollerPlanetAggregator");
+        
+        // Loop through all subscriptions in the system
+        Iterator subs = getAllSubscriptions();
+        while (subs.hasNext()) {
+            long subStartTime = System.currentTimeMillis();
+            
+            // Fetch latest entries for each subscription
+            Set newEntries = null;
+            int count = 0;
+            PlanetSubscriptionData sub = (PlanetSubscriptionData)subs.next();
+            if (!StringUtils.isEmpty(localURL) && sub.getFeedUrl().startsWith(localURL)) {
+                newEntries = getNewEntriesLocal(sub, feedFetcher, feedInfoCache);
+            } else {
+                newEntries = getNewEntriesRemote(sub, feedFetcher, feedInfoCache);
+            }
+            count = newEntries.size();
+            
+            // TODO: wrap this in a transaction
+            log.debug("   Entry count: " + count);
+            if (count > 0) {
+                Iterator entryIter = sub.getEntries().iterator();
+                while (entryIter.hasNext()) {
+                    deleteEntry((PlanetEntryData)entryIter.next());
+                }
+                sub.purgeEntries();
+                sub.addEntries(newEntries);
+                if (roller != null) roller.commit();
+            }
+            long subEndTime = System.currentTimeMillis();
+            log.info("   " + count + " - "
+                    + ((subEndTime-subStartTime)/1000.0)
+                    + " seconds to process (" + count + ") entries of "
+                    + sub.getFeedUrl());
+        }
+        // Clear the aggregation cache
+        clearCachedAggregations();
+        
+        long endTime = System.currentTimeMillis();
+        log.info("--- DONE --- Refreshed entries in "
+                + ((endTime-startTime)/1000.0) + " seconds");
     }
     
-    public Date getLastUpdated(PlanetGroupData group) {
-        return (Date)lastUpdatedByGroup.get(group);
-    }
     
     protected Set getNewEntriesLocal(PlanetSubscriptionData sub,
             FeedFetcher feedFetcher, FeedFetcherCache feedInfoCache)
@@ -326,8 +498,8 @@
             // for local feeds, sub.author = website.handle
             if (sub.getAuthor()!=null && sub.getFeedUrl().endsWith(sub.getAuthor())) {
                 
-                logger.debug("Getting LOCAL feed "+sub.getFeedUrl());
-            
+                log.debug("Getting LOCAL feed "+sub.getFeedUrl());
+                
                 // get corresponding website object
                 UserManager usermgr = roller.getUserManager();
                 WebsiteData website = usermgr.getWebsiteByHandle(sub.getAuthor());
@@ -338,62 +510,169 @@
                 
                 Date siteUpdated = blogmgr.getWeblogLastPublishTime(website);
                 if (siteUpdated == null) { // Site never updated, skip it
-                    logger.warn("Last-publish time null, skipping local feed ["
-                                 + website.getHandle() + "]");
-                    return newEntries; 
+                    log.warn("Last-publish time null, skipping local feed ["
+                            + website.getHandle() + "]");
+                    return newEntries;
                 }
                 
                 // if website last update time > subsciption last update time
                 List entries = new ArrayList();
                 if (sub.getLastUpdated()==null || siteUpdated.after(sub.getLastUpdated())) {
                     int entryCount = RollerRuntimeConfig.getIntProperty(
-                        "site.newsfeeds.defaultEntries");    
-                     entries = blogmgr.getWeblogEntries(
-                        website, 
-                        null,                        // startDate
-                        new Date(),                  // endDate
-                        null,                        // catName
-                        WeblogEntryData.PUBLISHED,   // status
-                        null,                        // sortby (null means pubTime)
-                        new Integer(entryCount));    // maxEntries
+                            "site.newsfeeds.defaultEntries");
+                    entries = blogmgr.getWeblogEntries(
+                            website,
+                            null,                        // startDate
+                            new Date(),                  // endDate
+                            null,                        // catName
+                            WeblogEntryData.PUBLISHED,   // status
+                            null,                        // sortby (null means pubTime)
+                            new Integer(entryCount));    // maxEntries
                     
                     sub.setLastUpdated(siteUpdated);
                     saveSubscription(sub);
                     
                 } else {
-                    if (logger.isDebugEnabled()) {
+                    if (log.isDebugEnabled()) {
                         String msg = MessageFormat.format(
-                            "   Skipping ({0} / {1})", new Object[] {
+                                "   Skipping ({0} / {1})", new Object[] {
                             siteUpdated, sub.getLastUpdated()});
-                            logger.debug(msg);
+                        log.debug(msg);
                     }
-                }  
+                }
                 // Populate subscription object with new entries
                 PagePluginManager ppmgr = roller.getPagePluginManager();
                 Map pagePlugins = ppmgr.createAndInitPagePlugins(
-                    website, 
-                    null,
-                    RollerRuntimeConfig.getProperty("site.absoluteurl"),
-                    new VelocityContext());
+                        website,
+                        null,
+                        RollerRuntimeConfig.getProperty("site.absoluteurl"),
+                        new VelocityContext());
                 Iterator entryIter = entries.iterator();
                 while (entryIter.hasNext()) {
                     try {
-                        WeblogEntryData rollerEntry = 
-                            (WeblogEntryData)entryIter.next();
+                        WeblogEntryData rollerEntry =
+                                (WeblogEntryData)entryIter.next();
                         PlanetEntryData entry =
-                            new PlanetEntryData(rollerEntry, sub, pagePlugins);
+                                new PlanetEntryData(rollerEntry, sub, pagePlugins);
                         saveEntry(entry);
                         newEntries.add(entry);
                     } catch (Exception e) {
-                        logger.error("ERROR processing subscription entry", e);
+                        log.error("ERROR processing subscription entry", e);
                     }
                 }
                 return newEntries;
             }
         } catch (Exception e) {
-            logger.warn("Problem reading local feed", e);
+            log.warn("Problem reading local feed", e);
         }
         return getNewEntriesRemote(sub, feedFetcher, feedInfoCache);
     }
+    
+    
+    /**
+     * Override this if you have local feeds (i.e. feeds that you don't
+     * have to fetch via HTTP and parse with ROME).
+     */
+    // TODO: broken by backend refactoring
+    //       this should probably be handled by providing a special RollerPlanetManager
+    //       which overrides some normal planet behavior to be Roller specific
+    //       another example of why planet should be separated out
+//    protected Set getNewEntriesLocal(PlanetSubscriptionData sub,
+//            FeedFetcher feedFetcher, FeedFetcherCache feedInfoCache)
+//            throws RollerException {
+//
+//        // If you don't override, local feeds will be treated as remote feeds
+//        return getNewEntriesRemote(sub, feedFetcher, feedInfoCache);
+//    }
+    
+    
+    // TODO: transaction support
+    protected Set getNewEntriesRemote(PlanetSubscriptionData sub,
+            FeedFetcher feedFetcher, FeedFetcherCache feedInfoCache)
+            throws RollerException {
+        
+        Set newEntries = new TreeSet();
+        SyndFeed feed = null;
+        URL feedUrl = null;
+        Date lastUpdated = new Date();
+        try {
+            feedUrl = new URL(sub.getFeedUrl());
+            log.debug("Get feed from cache "+sub.getFeedUrl());
+            feed = feedFetcher.retrieveFeed(feedUrl);
+            SyndFeedInfo feedInfo = feedInfoCache.getFeedInfo(feedUrl);
+            if (feedInfo.getLastModified() != null) {
+                long lastUpdatedLong =
+                        ((Long)feedInfo.getLastModified()).longValue();
+                if (lastUpdatedLong != 0) {
+                    lastUpdated = new Date(lastUpdatedLong);
+                }
+            }
+            Thread.sleep(100); // be nice
+        } catch (Exception e) {
+            log.warn("ERROR parsing " + sub.getFeedUrl()
+            + " : " + e.getClass().getName() + " : " + e.getMessage());
+            log.debug(e);
+            return newEntries; // bail out
+        }
+        if (lastUpdated!=null && sub.getLastUpdated()!=null) {
+            Calendar feedCal = Calendar.getInstance();
+            feedCal.setTime(lastUpdated);
+            
+            Calendar subCal = Calendar.getInstance();
+            subCal.setTime(sub.getLastUpdated());
+            
+            if (!feedCal.after(subCal)) {
+                if (log.isDebugEnabled()) {
+                    String msg = MessageFormat.format(
+                            "   Skipping ({0} / {1})",
+                            new Object[] {
+                        lastUpdated, sub.getLastUpdated()});
+                    log.debug(msg);
+                }
+                return newEntries; // bail out
+            }
+        }
+        if (feed.getPublishedDate() != null) {
+            sub.setLastUpdated(feed.getPublishedDate());
+            saveSubscription(sub);
+        }
+        
+        // Kludge for Feeds without entry dates: most recent entry is given
+        // feed's last publish date (or yesterday if none exists) and earler
+        // entries are placed at once day intervals before that.
+        Calendar cal = Calendar.getInstance();
+        if (sub.getLastUpdated() != null) {
+            cal.setTime(sub.getLastUpdated());
+        } else {
+            cal.setTime(new Date());
+            cal.add(Calendar.DATE, -1);
+        }
+        
+        // Populate subscription object with new entries
+        Iterator entries = feed.getEntries().iterator();
+        while (entries.hasNext()) {
+            try {
+                SyndEntry romeEntry = (SyndEntry) entries.next();
+                PlanetEntryData entry =
+                        new PlanetEntryData(feed, romeEntry, sub);
+                if (entry.getPublished() == null) {
+                    log.debug(
+                            "No published date, assigning fake date for "+feedUrl);
+                    entry.setPublished(cal.getTime());
+                }
+                if (entry.getPermalink() == null) {
+                    log.warn("No permalink, rejecting entry from "+feedUrl);
+                } else {
+                    saveEntry(entry);
+                    newEntries.add(entry);
+                }
+                cal.add(Calendar.DATE, -1);
+            } catch (Exception e) {
+                log.error("ERROR processing subscription entry", e);
+            }
+        }
+        return newEntries;
+    }
+    
 }
 

Modified: incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePropertiesManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePropertiesManagerImpl.java?rev=392618&r1=392617&r2=392618&view=diff
==============================================================================
--- incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePropertiesManagerImpl.java (original)
+++ incubator/roller/branches/roller-newbackend/src/org/roller/business/hibernate/HibernatePropertiesManagerImpl.java Sat Apr  8 15:36:25 2006
@@ -13,44 +13,53 @@
 import org.hibernate.Criteria;
 import org.hibernate.HibernateException;
 import org.hibernate.Session;
-import org.hibernate.criterion.Expression;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.roller.RollerException;
-import org.roller.business.PersistenceStrategy;
-import org.roller.business.PropertiesManagerImpl;
+import org.roller.config.RollerRuntimeConfig;
+import org.roller.config.runtime.ConfigDef;
+import org.roller.config.runtime.DisplayGroup;
+import org.roller.config.runtime.PropertyDef;
+import org.roller.config.runtime.RuntimeConfigDefs;
+import org.roller.model.PropertiesManager;
+import org.roller.model.Roller;
+import org.roller.model.RollerFactory;
+import org.roller.pojos.RollerConfigData;
 import org.roller.pojos.RollerPropertyData;
 
 
 /**
- * A hibernate specific implementation of the properties manager.
- *
- * @author Allen Gilliland
+ * Hibernate implementation of the PropertiesManager.
  */
-public class HibernatePropertiesManagerImpl extends PropertiesManagerImpl {
+public class HibernatePropertiesManagerImpl implements PropertiesManager {
     
     static final long serialVersionUID = -4326713177137796936L;
     
-    private static Log mLogger =
-            LogFactory.getLog(HibernatePropertiesManagerImpl.class);
+    private static Log log = LogFactory.getLog(HibernatePropertiesManagerImpl.class);
+    
+    private HibernatePersistenceStrategy strategy = null;
     
     
     /** 
      * Creates a new instance of HibernatePropertiesManagerImpl
      */
-    public HibernatePropertiesManagerImpl(PersistenceStrategy strategy) {
-        super(strategy);
-        mLogger.debug("Instantiating Hibernate Properties Manager");
+    public HibernatePropertiesManagerImpl(HibernatePersistenceStrategy strat) {
+        
+        log.debug("Instantiating Hibernate Properties Manager");
+        
+        this.strategy = strat;
+        
+        // TODO: and new method initialize(props)
+        init();
     }
     
     
     /** 
-     * Retrieve a single property by name
+     * Retrieve a single property by name.
      */
     public RollerPropertyData getProperty(String name) throws RollerException {
         try {
-            Session session = ((HibernateStrategy) mStrategy).getSession();
-            return (RollerPropertyData) mStrategy.load(name, RollerPropertyData.class);
+            return (RollerPropertyData) strategy.load(name, RollerPropertyData.class);
         } catch (HibernateException e) {
             throw new RollerException(e);
         }
@@ -58,14 +67,21 @@
     
     
     /** 
-     * Retrieve all properties 
+     * Retrieve all properties.
+     *
+     * Properties are returned in a Map to make them easy to lookup.  The Map
+     * uses the property name as the key and the RollerPropertyData object
+     * as the value.
      */
     public Map getProperties() throws RollerException {
         
         HashMap props = new HashMap();
         
         try {
-            Session session = ((HibernateStrategy) mStrategy).getSession();
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Session session = strategy.getSession();
             Criteria criteria = session.createCriteria(RollerPropertyData.class);
             List list = criteria.list();
             
@@ -87,5 +103,203 @@
         
         return props;
     }
+    
+    
+    /**
+     * Save a single property.
+     */
+    public void store(RollerPropertyData property) throws RollerException {
+        
+        this.strategy.storeAndCommit(property);
+    }
+
+    
+    /**
+     * Save all properties.
+     */
+    public void store(Map properties) throws RollerException {
+        
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            // just go through the list and store each property
+            Iterator props = properties.values().iterator();
+            while (props.hasNext()) {
+                    this.strategy.store((RollerPropertyData) props.next());
+            }
+            
+            // commit changes
+            this.strategy.getSession().getTransaction().commit();
+        } catch (HibernateException ex) {
+            
+            try {
+                this.strategy.getSession().getTransaction().rollback();
+            } catch(HibernateException he) {
+                log.error("Error doing rollback", he);
+            }
+            
+            strategy.release();
+            
+            throw new RollerException(ex);
+        }
+    }
+    
+    
+    private void init() {
+        Map props = null;
+        try {
+            props = this.getProperties();
+            
+            if(props.size() < 1) {
+                // empty props table ... try migrating, then load defaults
+                props = migrateOldRollerConfig(props);
+                props = initializeMissingProps(props);
+            } else {
+                // found existing props ... check for new props
+                props = initializeMissingProps(props);
+            }
+            
+            // save our changes
+            this.store(props);
+        } catch (Exception e) {
+            log.fatal("Failed to initialize runtime configuration properties."+
+                    "Please check that the database has been upgraded!", e);
+            throw new RuntimeException(e);
+        }
+        
+    }
+    
+    
+    /**
+     * Migrate data from the old roller config.
+     * This is called only if the existing runtime properties are empty.
+     */
+    private Map migrateOldRollerConfig(Map props) {
+        // try to get the old config
+        Roller roller = RollerFactory.getRoller();
+        RollerConfigData rollerConfig = null;
+        
+        try {
+            rollerConfig = roller.getConfigManager().getRollerConfig();
+        } catch (Exception e) {
+            // We currently treat any exception obtaining the roller config
+            // as if we had not found it.
+            log.error(e);
+        }
+        
+        if (rollerConfig != null) {
+            log.info("Found old roller config ... doing migration to new runtime properties.");
+            // copy over data
+            props.put("site.name",
+                    new RollerPropertyData("site.name", rollerConfig.getSiteName()));
+            props.put("site.description",
+                    new RollerPropertyData("site.description", rollerConfig.getSiteDescription()));
+            props.put("site.adminemail",
+                    new RollerPropertyData("site.adminemail", rollerConfig.getEmailAddress()));
+            props.put("site.absoluteurl",
+                    new RollerPropertyData("site.absoluteurl", rollerConfig.getAbsoluteURL()));
+            props.put("site.linkbacks.enabled",
+                    new RollerPropertyData("site.linkbacks.enabled", rollerConfig.getEnableLinkback().toString()));
+            props.put("users.registration.enabled",
+                    new RollerPropertyData("users.registration.enabled", rollerConfig.getNewUserAllowed().toString()));
+            props.put("users.themes.path",
+                    new RollerPropertyData("users.themes.path", rollerConfig.getUserThemes()));
+            props.put("users.editor.pages",
+                    new RollerPropertyData("users.editor.pages", rollerConfig.getEditorPages()));
+            props.put("users.comments.enabled",
+                    new RollerPropertyData("users.comments.enabled", "true"));
+            props.put("users.comments.autoformat",
+                    new RollerPropertyData("users.comments.autoformat", rollerConfig.getAutoformatComments().toString()));
+            props.put("users.comments.escapehtml",
+                    new RollerPropertyData("users.comments.escapehtml", rollerConfig.getEscapeCommentHtml().toString()));
+            props.put("users.comments.emailnotify",
+                    new RollerPropertyData("users.comments.emailnotify", rollerConfig.getEmailComments().toString()));
+            props.put("uploads.enabled",
+                    new RollerPropertyData("uploads.enabled", rollerConfig.getUploadEnabled().toString()));
+            props.put("uploads.types.allowed",
+                    new RollerPropertyData("uploads.types.allowed", rollerConfig.getUploadAllow()));
+            props.put("uploads.types.forbid",
+                    new RollerPropertyData("uploads.types.forbid", rollerConfig.getUploadForbid()));
+            props.put("uploads.file.maxsize",
+                    new RollerPropertyData("uploads.file.maxsize", rollerConfig.getUploadMaxFileMB().toString()));
+            props.put("uploads.dir.maxsize",
+                    new RollerPropertyData("uploads.dir.maxsize", rollerConfig.getUploadMaxDirMB().toString()));
+            /* no longer part of runtime config
+            props.put("aggregator.enabled",
+                new RollerPropertyData("aggregator.enabled", rollerConfig.getEnableAggregator().toString()));
+            props.put("aggregator.cache.enabled",
+                new RollerPropertyData("aggregator.cache.enabled", rollerConfig.getRssUseCache().toString()));
+            props.put("aggregator.cache.timeout",
+                new RollerPropertyData("aggregator.cache.timeout", rollerConfig.getRssCacheTime().toString()));
+            props.put("debug.memory.enabled",
+                new RollerPropertyData("debug.memory.enabled", rollerConfig.getMemDebug().toString()));
+             */
+            props.put("spam.blacklist",
+                    new RollerPropertyData("spam.blacklist", rollerConfig.getRefererSpamWords()));
+        } else {
+            log.info("Old roller config not found ... default values will be loaded");
+        }
+        
+        return props;
+    }
+    
+    
+    /**
+     * This method compares the property definitions in the RuntimeConfigDefs
+     * file with the properties in the given Map and initializes any properties
+     * that were not found in the Map.
+     *
+     * If the Map of props is empty/null then we will initialize all properties.
+     **/
+    private Map initializeMissingProps(Map props) {
+        
+        if(props == null)
+            props = new HashMap();
+        
+        // start by getting our runtimeConfigDefs
+        RuntimeConfigDefs runtimeConfigDefs =
+                RollerRuntimeConfig.getRuntimeConfigDefs();
+        
+        // can't do initialization without our config defs
+        if(runtimeConfigDefs == null)
+            return props;
+        
+        // iterator through all the definitions and add properties
+        // that are not already in our props map
+        ConfigDef configDef = null;
+        DisplayGroup dGroup = null;
+        PropertyDef propDef = null;
+        Iterator defs = runtimeConfigDefs.getConfigDefs().iterator();
+        while(defs.hasNext()) {
+            configDef = (ConfigDef) defs.next();
+            
+            Iterator groups = configDef.getDisplayGroups().iterator();
+            while(groups.hasNext()) {
+                dGroup = (DisplayGroup) groups.next();
+                
+                Iterator propdefs = dGroup.getPropertyDefs().iterator();
+                while(propdefs.hasNext()) {
+                    propDef = (PropertyDef) propdefs.next();
+                    
+                    // do we already have this prop?  if not then add it
+                    if(!props.containsKey(propDef.getName())) {
+                        RollerPropertyData newprop =
+                                new RollerPropertyData(propDef.getName(), propDef.getDefaultValue());
+                        
+                        props.put(propDef.getName(), newprop);
+                        
+                        log.info("Found uninitialized property "+propDef.getName()+
+                                " ... setting value to ["+propDef.getDefaultValue()+"]");
+                    }
+                }
+            }
+        }
+        
+        return props;
+    }
+    
+    
+    public void release() {}
     
 }