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/05/02 00:23:34 UTC

svn commit: r398712 [3/32] - in /incubator/roller/trunk/src/org/apache: ./ roller/ roller/business/ roller/business/hibernate/ roller/business/referrers/ roller/business/runnable/ roller/business/search/ roller/business/search/operations/ roller/busine...

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePlanetManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePlanetManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePlanetManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePlanetManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,533 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.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;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+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.roller.RollerException;
+import org.apache.roller.config.RollerConfig;
+import org.apache.roller.config.RollerRuntimeConfig;
+import org.apache.roller.model.PlanetManager;
+import org.apache.roller.model.Roller;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.pojos.PlanetConfigData;
+import org.apache.roller.pojos.PlanetEntryData;
+import org.apache.roller.pojos.PlanetGroupData;
+import org.apache.roller.pojos.PlanetGroupSubscriptionAssoc;
+import org.apache.roller.pojos.PlanetSubscriptionData;
+import org.apache.roller.util.rome.DiskFeedInfoCache;
+
+
+/**
+ * Hibernate implementation of the PlanetManager.
+ */
+public class HibernatePlanetManagerImpl implements PlanetManager {
+    
+    private static Log log = LogFactory.getLog(HibernatePlanetManagerImpl.class);
+    
+    protected static final String NO_GROUP = "zzz_nogroup_zzz";
+    
+    private HibernatePersistenceStrategy strategy = null;
+    private String localURL = null;
+    private Map lastUpdatedByGroup = new HashMap();
+    
+    
+    public HibernatePlanetManagerImpl(HibernatePersistenceStrategy strat) {
+        
+        this.strategy = strat;
+        
+        // TODO: this is bad.  this property should be in the planet config.
+        localURL = RollerRuntimeConfig.getProperty("site.absoluteurl");
+    }
+    
+    
+    public void saveConfiguration(PlanetConfigData config) throws RollerException {
+        strategy.store(config);
+    }
+    
+    
+    public void saveGroup(PlanetGroupData group) throws RollerException {
+        
+        // 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);
+    }
+    
+    
+    public void saveEntry(PlanetEntryData entry) throws RollerException {
+        strategy.store(entry);
+    }
+    
+    
+    public void saveSubscription(PlanetSubscriptionData sub) throws RollerException {
+        PlanetSubscriptionData existing = getSubscription(sub.getFeedUrl());
+        if (existing == null || (existing.getId().equals(sub.getId()))) {
+            this.strategy.store(sub);
+        } else {
+            throw new RollerException("ERROR: duplicate feed URLs not allowed");
+        }
+    }
+    
+    
+    public void deleteEntry(PlanetEntryData entry) throws RollerException {
+        strategy.remove(entry);
+    }
+    
+    
+    public void deleteGroup(PlanetGroupData group) throws RollerException {
+        strategy.remove(group);
+    }
+    
+    
+    public void deleteSubscription(PlanetSubscriptionData sub) throws RollerException {
+        strategy.remove(sub);
+    }
+    
+    
+    public PlanetConfigData getConfiguration() throws RollerException {
+        PlanetConfigData config = null;
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(PlanetConfigData.class);
+            criteria.setMaxResults(1);
+            List list = criteria.list();
+            config = list.size()!=0 ? (PlanetConfigData)list.get(0) : null;
+            
+            // We inject the cache dir into the config object here to maintain
+            // compatibility with the standaline version of the aggregator.
+            if (config != null) {
+                config.setCacheDir(
+                        RollerConfig.getProperty("planet.aggregator.cache.dir"));
+            }
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+        return config;
+    }
+    
+    
+    public PlanetSubscriptionData getSubscription(String feedUrl) throws RollerException {
+        try {
+            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 PlanetSubscriptionData getSubscriptionById(String id) throws RollerException {
+        return (PlanetSubscriptionData) strategy.load(id, PlanetSubscriptionData.class);
+    }
+    
+    
+    public Iterator getAllSubscriptions() {
+        try {
+            Session session = ((HibernatePersistenceStrategy)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 int getSubscriptionCount() throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Integer count = (Integer)session.createQuery(
+                    "select count(*) from org.apache.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 = ((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 synchronized List getTopSubscriptions(
+            PlanetGroupData group, int max) throws RollerException {
+        String groupHandle = (group == null) ? NO_GROUP : group.getHandle();
+        List ret = null;
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Query query = session.createQuery(
+                    "select sub from org.apache.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 = strategy.getSession();
+            Criteria criteria = session.createCriteria(PlanetGroupData.class);
+            criteria.setMaxResults(1);
+            criteria.add(Expression.eq("handle", handle));
+            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);
+    }
+    
+    
+    public List getGroups() throws RollerException {
+        try {
+            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 {
+        
+        List ret = null;
+        try {
+            String groupHandle = (group == null) ? NO_GROUP : group.getHandle();
+            long startTime = System.currentTimeMillis();
+            Session session =
+                    ((HibernatePersistenceStrategy)strategy).getSession();
+            
+            if (group != null) {
+                Query query = session.createQuery(
+                        "select entry from org.apache.roller.pojos.PlanetEntryData entry "
+                        +"join entry.subscription.groupSubscriptionAssocs assoc "
+                        +"where assoc.group=:group order by entry.published desc");
+                query.setEntity("group", group);
+                query.setMaxResults(maxEntries);
+                ret = query.list();
+            } else {
+                Query query = session.createQuery(
+                        "select entry from org.apache.roller.pojos.PlanetEntryData entry "
+                        +"join entry.subscription.groupSubscriptionAssocs assoc "
+                        +"where "
+                        +"assoc.group.handle='external' or assoc.group.handle='all'"
+                        +" order by entry.published desc");
+                query.setMaxResults(maxEntries);
+                ret = query.list();
+            }
+            Date retLastUpdated = null;
+            if (ret.size() > 0) {
+                PlanetEntryData entry = (PlanetEntryData)ret.get(0);
+                retLastUpdated = entry.getPublished();
+            } else {
+                retLastUpdated = new Date();
+            }
+            lastUpdatedByGroup.put(groupHandle, retLastUpdated);
+            
+            long endTime = System.currentTimeMillis();
+            log.info("Generated aggregation in "
+                    +((endTime-startTime)/1000.0)+" seconds");
+        } catch (Throwable e) {
+            log.error("ERROR: building aggregation for: "+group, e);
+            throw new RollerException(e);
+        }
+        return ret;
+    }
+    
+    
+    public synchronized void clearCachedAggregations() {
+        lastUpdatedByGroup.clear();
+    }
+    
+    public Date getLastUpdated() {
+        return (Date)lastUpdatedByGroup.get(NO_GROUP);
+    }
+    
+    public Date getLastUpdated(PlanetGroupData group) {
+        return (Date)lastUpdatedByGroup.get(group);
+    }
+    
+    
+    public void refreshEntries() throws RollerException {
+        
+        Roller roller = RollerFactory.getRoller();
+        
+        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;
+        }
+        
+        // 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 {
+            cacheDir = new File(cacheDirName);
+            if (!cacheDir.exists()) cacheDir.mkdirs();
+        } catch (Exception e) {
+            log.error("Unable to create planet cache directory");
+            return;
+        }
+        
+        // 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();
+            
+            PlanetSubscriptionData sub = (PlanetSubscriptionData)subs.next();
+            
+            // reattach sub.  sub gets detached as we iterate
+            sub = this.getSubscriptionById(sub.getId());
+            
+            // Fetch latest entries for each subscription
+//            Set newEntries = null;
+//            int count = 0;
+//            if (!StringUtils.isEmpty(localURL) && sub.getFeedUrl().startsWith(localURL)) {
+//                newEntries = getNewEntriesLocal(sub, feedFetcher, feedInfoCache);
+//            } else {
+//                newEntries = getNewEntriesRemote(sub, feedFetcher, feedInfoCache);
+//            }
+            Set newEntries = this.getNewEntries(sub, feedFetcher, feedInfoCache);
+            int count = newEntries.size();
+            
+            log.debug("   Entry count: " + count);
+            if (count > 0) {
+                sub.purgeEntries();
+                sub.addEntries(newEntries);
+                this.saveSubscription(sub);
+                if(roller != null) roller.flush();
+            }
+            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");
+    }
+    
+    
+    protected Set getNewEntries(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());
+            // saving sub here causes detachment issues, so we save it later
+        }
+        
+        // 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 {
+                    newEntries.add(entry);
+                }
+                cal.add(Calendar.DATE, -1);
+            } catch (Exception e) {
+                log.error("ERROR processing subscription entry", e);
+            }
+        }
+        return newEntries;
+    }
+
+    protected String getLocalURL() {
+        return localURL;
+    }
+    
+}
+

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePropertiesManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePropertiesManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePropertiesManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePropertiesManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,300 @@
+/*
+* 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.
+*/
+/*
+ * HibernatePropertiesManagerImpl.java
+ *
+ * Created on April 21, 2005, 10:40 AM
+ */
+
+package org.apache.roller.business.hibernate;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.RollerException;
+import org.apache.roller.config.RollerRuntimeConfig;
+import org.apache.roller.config.runtime.ConfigDef;
+import org.apache.roller.config.runtime.DisplayGroup;
+import org.apache.roller.config.runtime.PropertyDef;
+import org.apache.roller.config.runtime.RuntimeConfigDefs;
+import org.apache.roller.model.PropertiesManager;
+import org.apache.roller.model.Roller;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.pojos.RollerConfigData;
+import org.apache.roller.pojos.RollerPropertyData;
+
+
+/**
+ * Hibernate implementation of the PropertiesManager.
+ */
+public class HibernatePropertiesManagerImpl implements PropertiesManager {
+    
+    static final long serialVersionUID = -4326713177137796936L;
+    
+    private static Log log = LogFactory.getLog(HibernatePropertiesManagerImpl.class);
+    
+    private HibernatePersistenceStrategy strategy = null;
+    
+    
+    /** 
+     * Creates a new instance of HibernatePropertiesManagerImpl
+     */
+    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.
+     */
+    public RollerPropertyData getProperty(String name) throws RollerException {
+        try {
+            return (RollerPropertyData) strategy.load(name, RollerPropertyData.class);
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    /** 
+     * 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 = strategy.getSession();
+            Criteria criteria = session.createCriteria(RollerPropertyData.class);
+            List list = criteria.list();
+            
+            /* 
+             * for convenience sake we are going to put the list of props
+             * into a map for users to access it.  The value element of the
+             * hash still needs to be the RollerPropertyData object so that
+             * we can save the elements again after they have been updated
+             */
+            RollerPropertyData prop = null;
+            Iterator it = list.iterator();
+            while(it.hasNext()) {
+                prop = (RollerPropertyData) it.next();
+                props.put(prop.getName(), prop);
+            }
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+        
+        return props;
+    }
+    
+    
+    /**
+     * Save a single property.
+     */
+    public void saveProperty(RollerPropertyData property) throws RollerException {
+        
+        this.strategy.store(property);
+    }
+
+    
+    /**
+     * Save all properties.
+     */
+    public void saveProperties(Map properties) throws RollerException {
+        
+        // just go through the list and saveProperties each property
+        Iterator props = properties.values().iterator();
+        while (props.hasNext()) {
+            this.strategy.store((RollerPropertyData) props.next());
+        }
+    }
+
+    
+    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.saveProperties(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() {}
+    
+}

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRefererManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRefererManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRefererManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRefererManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,866 @@
+/*
+* 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.
+*/
+/*
+ * Created on Feb 23, 2003
+ */
+package org.apache.roller.business.hibernate;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.Criteria;
+import org.hibernate.Hibernate;
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.criterion.Expression;
+import org.hibernate.criterion.Junction;
+import org.hibernate.criterion.Order;
+import org.hibernate.type.Type;
+import org.apache.roller.RollerException;
+import org.apache.roller.config.RollerRuntimeConfig;
+import org.apache.roller.model.RefererManager;
+import org.apache.roller.pojos.RefererData;
+import org.apache.roller.pojos.WeblogEntryData;
+import org.apache.roller.pojos.WebsiteData;
+import org.apache.roller.pojos.WebsiteDisplayData;
+import org.hibernate.dialect.DB2Dialect;
+import org.hibernate.dialect.DerbyDialect;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.dialect.OracleDialect;
+import org.hibernate.dialect.SQLServerDialect;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.dialect.Dialect;
+import org.apache.roller.model.Roller;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.model.UserManager;
+import org.apache.roller.model.WeblogManager;
+import org.apache.roller.util.DateUtil;
+import org.apache.roller.util.LinkbackExtractor;
+import org.apache.roller.util.Utilities;
+
+
+/**
+ * Hibernate implementation of the RefererManager.
+ */
+public class HibernateRefererManagerImpl implements RefererManager {
+    
+    static final long serialVersionUID = -4966091850482256435L;
+    
+    private static Log log = LogFactory.getLog(HibernateRefererManagerImpl.class);
+    
+    protected static final String DAYHITS = "dayHits";
+    protected static final String TOTALHITS = "totalHits";
+    
+    private HibernatePersistenceStrategy strategy = null;
+    private Date mRefDate = new Date();
+    private SimpleDateFormat mDateFormat = DateUtil.get8charDateFormat();
+    
+    
+    public HibernateRefererManagerImpl(HibernatePersistenceStrategy strat) {
+        
+        log.debug("Instantiating Hibernate Referer Manager");
+        
+        strategy = strat;
+    }
+    
+    
+    /**
+     * 
+     * 
+     * @see org.apache.roller.pojos.RefererManager#saveReferer(org.apache.roller.pojos.RefererData)
+     */
+    public void saveReferer(RefererData referer) throws RollerException {
+        strategy.store(referer);
+    }
+    
+    
+    public void removeReferer(RefererData referer) throws RollerException {
+        strategy.remove(referer);
+    }
+    
+    
+    /**
+     * Clear referrer dayhits and remove referrers without excerpts.
+     *
+     * TODO: do we really need dialect specific queries?
+     */
+    public void clearReferrers() throws RollerException {
+        
+        if (log.isDebugEnabled()) {
+            log.debug("clearReferrers");
+        }
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Dialect currentDialect = ((SessionFactoryImplementor)session.getSessionFactory()).getDialect();
+            String reset = "update RefererData set dayHits=0";
+            session.createQuery(reset).executeUpdate();
+            String delete = null;
+            if ( currentDialect instanceof SQLServerDialect || currentDialect instanceof OracleDialect ){
+                delete = "delete RefererData where excerpt is null or excerpt like ''";
+            } else {
+                delete = "delete RefererData where excerpt is null or excerpt=''";
+            }
+            session.createQuery(delete).executeUpdate();
+        } catch (Exception e) {
+            log.error("EXCEPTION resetting referers",e);
+        }
+    }
+    
+    
+    /**
+     * Clear referrer dayhits and remove referrers without excerpts.
+     *
+     * TODO: do we really need dialect specific queries?
+     */
+    public void clearReferrers(WebsiteData website) throws RollerException {
+        
+        if (log.isDebugEnabled()) {
+            log.debug("clearReferrers");
+        }
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Dialect currentDialect = ((SessionFactoryImplementor)session.getSessionFactory()).getDialect();
+            String reset = "update RefererData set dayHits=0 where website=:site";
+            session.createQuery(reset)
+            .setParameter("site",website).executeUpdate();
+            String delete = null;
+            if ( currentDialect instanceof SQLServerDialect || currentDialect instanceof OracleDialect ){
+                delete = "delete RefererData where website=:site and (excerpt is null or excerpt like '')";
+            } else {
+                delete = "delete RefererData where website=:site and (excerpt is null or excerpt='')";
+            }
+            session.createQuery(delete)
+            .setParameter("site",website).executeUpdate();
+        } catch (Exception e) {
+            log.error("EXCEPTION resetting referers",e);
+        }
+    }
+    
+    
+    /**
+     * Apply ignoreWord/spam filters to all referers in system.
+     */
+    public void applyRefererFilters() throws RollerException {
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(RefererData.class);
+            
+            String spamwords = RollerRuntimeConfig.getProperty("spam.blacklist");
+            
+            String[] blacklist = StringUtils.split(
+                    StringUtils.deleteWhitespace(spamwords),",");
+            Junction or = Expression.disjunction();
+            for (int i=0; i<blacklist.length; i++) {
+                String ignoreWord = blacklist[i].trim();
+                //log.debug("including ignore word - "+ignoreWord);
+                or.add(Expression.ilike("refererUrl","%"+ignoreWord+"%"));
+            }
+            criteria.add(Expression.conjunction()
+            .add(Expression.disjunction().add(Expression.isNull("excerpt")).add(Expression.eq("excerpt", "")))
+            .add(or)
+            );
+            
+            log.debug("removing spam referers - "+criteria.list().size());
+            
+            Iterator referer = criteria.list().iterator();
+            while (referer.hasNext()) {
+                this.strategy.remove((RefererData) referer.next());
+            }
+
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    /**
+     * Apply ignoreWord/spam filters to all referers in website.
+     */
+    public void applyRefererFilters(WebsiteData website) throws RollerException {
+        
+        if (null == website) throw new RollerException("website is null");
+        if (null == website.getBlacklist()) return;
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(RefererData.class);
+            
+            String[] blacklist = StringUtils.split(
+                    StringUtils.deleteWhitespace(website.getBlacklist()),",");
+            if (blacklist.length == 0) return;
+            
+            Junction or = Expression.disjunction();
+            for (int i=0; i<blacklist.length; i++) {
+                String ignoreWord = blacklist[i].trim();
+                or.add(Expression.ilike("refererUrl","%"+ignoreWord+"%"));
+            }
+            criteria.add(Expression.conjunction()
+            .add(Expression.disjunction().add(Expression.isNull("excerpt")).add(Expression.eq("excerpt", "")))
+            .add(Expression.eq("website",website))
+            .add(or)
+            );
+            
+            Iterator referer = criteria.list().iterator();
+            while (referer.hasNext()) {
+                this.strategy.remove((RefererData) referer.next());
+            }
+            
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    /**
+     * Use Hibernate directly because Roller's Query API does too much allocation.
+     */
+    protected List getExistingReferers(WebsiteData website, String dateString,
+            String permalink) throws RollerException {
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(RefererData.class);
+            criteria.add(Expression.conjunction()
+            .add(Expression.eq("website",website))
+            .add(Expression.eq("dateString",dateString))
+            .add(Expression.eq("refererPermalink",permalink)));
+            
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    /**
+     * Use Hibernate directly because Roller's Query API does too much allocation.
+     */
+    protected List getMatchingReferers(WebsiteData website, String requestUrl,
+            String refererUrl) throws RollerException {
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(RefererData.class);
+            criteria.add(Expression.conjunction()
+            .add(Expression.eq("website",website))
+            .add(Expression.eq("requestUrl",requestUrl))
+            .add(Expression.eq("refererUrl",refererUrl)));
+            
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    /**
+     * Use raw SQL because Hibernate can't handle sorting by sum.
+     *
+     * TODO: do we really need raw sql?  can't hibernate do this?
+     */
+    public List getDaysPopularWebsites(int max) throws RollerException {
+        // TODO Move to full use of mSupport
+        String msg = "Getting popular websites";
+        Session ses = null; // the session will eventually be release by RequestFilter
+        Connection con = null;
+        try {
+            List list = new ArrayList();
+            
+            ses = ((HibernatePersistenceStrategy)strategy).getSession();
+            con = ses.connection();
+            
+            final PreparedStatement stmt;
+            
+            Dialect currentDialect = ((SessionFactoryImplementor)ses.getSessionFactory()).getDialect();
+            
+            if (currentDialect instanceof HSQLDialect) {
+                // special handling for HSQLDB
+                stmt = con.prepareStatement(
+                        "select top ? w.id, w.name, w.handle, sum(r.dayhits) as s "+
+                        "from website as w, referer as r "+
+                        "where r.websiteid=w.id and w.isenabled=? and w.isactive=? " +
+                        "group by w.name, w.handle, w.id order by s desc");
+                stmt.setInt(1, max);
+                stmt.setBoolean(2, true);
+                stmt.setBoolean(3, true);
+            } else if(currentDialect instanceof DerbyDialect) {
+                // special handling for Derby
+                stmt = con.prepareStatement(
+                        "select w.id, w.name, w.handle, sum(r.dayhits) as s "+
+                        "from website as w, referer as r "+
+                        "where r.websiteid=w.id and w.isenabled=? and w.isactive=? " +
+                        "group by w.name, w.handle, w.id order by s desc");
+                stmt.setBoolean(1, true);
+                stmt.setBoolean(2, true);
+                stmt.setMaxRows(max);
+            } else if(currentDialect instanceof DB2Dialect) {
+                // special handling for IBM DB2
+                stmt = con.prepareStatement(
+                        "select w.id, w.name, w.handle, sum(r.dayhits) as s "+
+                        "from website as w, referer as r "+
+                        "where r.websiteid=w.id and w.isenabled=? and w.isactive=? " +
+                        "group by w.name, w.handle, w.id order by s desc fetch first " +
+                        Integer.toString(max) + " rows only");
+                stmt.setBoolean(1, true);
+                stmt.setBoolean(2, true);
+            } else if (currentDialect instanceof OracleDialect) {
+                stmt = con.prepareStatement(
+                        "select w.id, w.name, w.handle, sum(r.dayhits) as s "+
+                        "from website w, referer r "+
+                        "where r.websiteid=w.id and w.isenabled=? and w.isactive=? and rownum <= ? " +
+                        "group by w.name, w.handle, w.id order by s desc");
+                stmt.setBoolean(1, true);
+                stmt.setBoolean(2, true);
+                stmt.setInt(3, max );
+            } else if (currentDialect instanceof SQLServerDialect) {
+                stmt = con.prepareStatement("select top " + max + " w.id, w.name, w.handle, sum(r.dayhits) as s " +
+                        "from website as w, referer as r where r.websiteid=w.id and w.isenabled=? and w.isactive=? " +
+                        "group by w.name, w.handle, w.id order by s desc");
+                stmt.setBoolean(1, true);
+                stmt.setBoolean(2, true);
+            } else { // for MySQL and PostgreSQL
+                stmt = con.prepareStatement(
+                        "select w.id, w.name, w.handle, sum(r.dayhits) as s "+
+                        "from website as w, referer as r "+
+                        "where r.websiteid=w.id and w.isenabled= ? and w.isactive=? " +
+                        // Ben Walding (a Postgres SQL user): Basically, you have
+                        // to have all non-aggregated columns that exist in your
+                        // 'SELECT' section, in the 'GROUP BY' section as well:
+                        "group by w.name, w.handle, w.id order by s desc limit ?");
+                stmt.setBoolean(1, true);
+                stmt.setBoolean(2, true);
+                stmt.setInt(3, max);
+            }
+            ResultSet rs = stmt.executeQuery();
+            if ( rs.next() ) {
+                do
+                {
+                    String websiteId = rs.getString(1);
+                    String websiteName = rs.getString(2);
+                    String websiteHandle = rs.getString(3);
+                    Integer hits = new Integer(rs.getInt(4));
+                    list.add(new WebsiteDisplayData(
+                            websiteId,
+                            websiteName,
+                            websiteHandle,
+                            hits));
+                    if(list.size() >= max) {
+                        rs.close();
+                        break;
+                    }
+                }
+                while ( rs.next() );
+            }
+            return list;
+        } catch (Throwable pe) {
+            log.error(msg, pe);
+            throw new RollerException(msg, pe);
+        }
+    }
+    
+    
+    /**
+     * Use raw SQL because Hibernate can't handle the query.
+     */
+    protected int getHits(WebsiteData website, String type) throws RollerException {
+        int hits = 0;
+        if (log.isDebugEnabled()) {
+            log.debug("getHits: " + website.getName());
+        }
+        
+        Object[] args = { Boolean.TRUE, website.getId() };
+        Type[] types = { Hibernate.BOOLEAN, Hibernate.STRING };
+        
+        // For a query like this, Hibernate returns a list of lists
+        Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+        List results;
+        try {
+            // begin transaction
+            this.strategy.getSession().beginTransaction();
+            
+            Query q = session.createQuery(
+                    "select sum(h.dayHits),sum(h.totalHits) from h in class " +
+                    "org.apache.roller.pojos.RefererData " +
+                    "where h.website.enabled=? and h.website.id=? ");
+            q.setParameters(args, types);
+            results = q.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+        Object[] resultsArray = (Object[]) results.get(0);
+        
+        if (resultsArray.length > 0 && type.equals(DAYHITS)) {
+            if ( resultsArray[0] != null ) {
+                hits = ((Integer) resultsArray[0]).intValue();
+            }
+        } else if ( resultsArray.length > 0 ) {
+            if ( resultsArray[0] != null ) {
+                hits = ((Integer) resultsArray[1]).intValue();
+            }
+        } else {
+            hits = 0;
+        }
+        
+        return hits;
+    }
+    
+    
+    /**
+     * @see org.apache.roller.pojos.RefererManager#getReferers(java.lang.String)
+     */
+    public List getReferers(WebsiteData website) throws RollerException {
+        if (website==null )
+            throw new RollerException("website is null");
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(RefererData.class);
+            criteria.add(Expression.eq("website",website));
+            criteria.addOrder(Order.desc("totalHits"));
+            
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    /**
+     * @see org.apache.roller.pojos.RefererManager#getTodaysReferers(String)
+     */
+    public List getTodaysReferers(WebsiteData website) throws RollerException {
+        if (website==null )
+            throw new RollerException("website is null");
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(RefererData.class);
+            criteria.add(Expression.eq("website", website));
+            criteria.add(Expression.gt("dayHits", new Integer(0)));
+            criteria.addOrder(Order.desc("dayHits"));
+            
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    /**
+     * Returns referers for a specified day. Duplicate enties are not
+     * included in this list so the hit counts may not be accurate.
+     * @see org.apache.roller.pojos.RefererManager#getReferersToDate(
+     * org.apache.roller.pojos.WebsiteData, java.lang.String)
+     */
+    public List getReferersToDate(WebsiteData website, String date)
+            throws RollerException {
+        if (website==null )
+            throw new RollerException("website is null");
+        
+        if (date==null )
+            throw new RollerException("Date is null");
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(RefererData.class);
+            criteria.add(Expression.eq("website", website));
+            criteria.add(Expression.eq("dateString", date));
+            criteria.add(Expression.eq("duplicate", Boolean.FALSE));
+            criteria.addOrder(Order.desc("totalHits"));
+            
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    /**
+     * @see org.apache.roller.pojos.RefererManager#getReferersToEntry(
+     * java.lang.String, java.lang.String)
+     */
+    public List getReferersToEntry(String entryid) throws RollerException {
+        if (null == entryid)
+            throw new RollerException("entryid is null");
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(RefererData.class);
+            criteria.createAlias("weblogEntry","e");
+            
+            criteria.add(Expression.eq("e.id", entryid));
+            criteria.add(Expression.isNotNull("title"));
+            criteria.add(Expression.isNotNull("excerpt"));
+            
+            criteria.addOrder(Order.desc("totalHits"));
+            
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    /**
+     * Query for collection of referers.
+     */
+    protected List getReferersToWebsite(WebsiteData website, String refererUrl)
+            throws RollerException {
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(RefererData.class);
+            criteria.add(Expression.eq("website", website));
+            criteria.add(Expression.eq("refererUrl", refererUrl));
+            
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    /**
+     * Query for collection of referers.
+     */
+    protected List getReferersWithSameTitle(WebsiteData website,
+                                            String requestUrl,
+                                            String title,
+                                            String excerpt)
+            throws RollerException {
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(RefererData.class);
+            
+            Junction conjunction = Expression.conjunction();
+            conjunction.add(Expression.eq("website", website));
+            conjunction.add(Expression.eq("requestUrl", requestUrl));
+            
+            Junction disjunction = Expression.conjunction();
+            disjunction.add(Expression.eq("title", title));
+            disjunction.add(Expression.eq("excerpt", excerpt));
+            
+            criteria.add(conjunction);
+            criteria.add(disjunction);
+            
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    public int getDayHits(WebsiteData website) throws RollerException {
+        return getHits(website, DAYHITS);
+    }
+    
+    
+    public int getTotalHits(WebsiteData website) throws RollerException {
+        return getHits(website, TOTALHITS);
+    }
+    
+    
+    /**
+     * @see org.apache.roller.pojos.RefererManager#retrieveReferer(java.lang.String)
+     */
+    public RefererData getReferer(String id) throws RollerException {
+        return (RefererData)strategy.load(id,RefererData.class);
+    }
+    
+    
+    public void processReferrer(String requestUrl,
+                                String referrerUrl,
+                                String weblogHandle,
+                                String entryAnchor,
+                                String dateString) {
+        
+        log.debug("processing referrer ["+referrerUrl+
+                "] accessing ["+requestUrl+"]");
+        
+        if (weblogHandle == null)
+            return;
+        
+        String selfSiteFragment = "/page/"+weblogHandle;
+        WebsiteData weblog = null;
+        WeblogEntryData entry = null;
+        
+        // lookup the weblog now
+        try {
+            UserManager userMgr = RollerFactory.getRoller().getUserManager();
+            weblog = userMgr.getWebsiteByHandle(weblogHandle);
+            if (weblog == null) return;
+            
+            // now lookup weblog entry if possible
+            if (entryAnchor != null) {
+                WeblogManager weblogMgr = RollerFactory.getRoller().getWeblogManager();
+                entry = weblogMgr.getWeblogEntryByAnchor(weblog, entryAnchor);
+            }
+        } catch (RollerException re) {
+            // problem looking up website, gotta bail
+            log.error("Error looking up website object", re);
+            return;
+        }
+        
+        try {
+            List matchRef = null;
+            
+            // try to find existing RefererData for referrerUrl
+            if (referrerUrl == null || referrerUrl.trim().length() < 8) {
+                referrerUrl = "direct";
+                
+                // Get referer specified by referer URL of direct
+                matchRef = getReferersToWebsite(weblog, referrerUrl);
+            } else {
+                referrerUrl = Utilities.stripJsessionId(referrerUrl);
+                
+                // Query for referer with same referer and request URLs
+                matchRef = getMatchingReferers(weblog, requestUrl, referrerUrl);
+                
+                // If referer was not found, try adding or leaving off 'www'
+                if ( matchRef.size() == 0 ) {
+                    String secondTryUrl = null;
+                    if ( referrerUrl.startsWith("http://www") ) {
+                        secondTryUrl = "http://"+referrerUrl.substring(11);
+                    } else {
+                        secondTryUrl = "http://www"+referrerUrl.substring(7);
+                    }
+                    
+                    matchRef = getMatchingReferers(weblog, requestUrl, secondTryUrl);
+                    if ( matchRef.size() == 1 ) {
+                        referrerUrl = secondTryUrl;
+                    }
+                }
+            }
+            
+            if (matchRef.size() == 1) {
+                // Referer was found in database, so bump up hit count
+                RefererData ref = (RefererData)matchRef.get(0);
+                
+                ref.setDayHits(new Integer(ref.getDayHits().intValue() + 1));
+                ref.setTotalHits(new Integer(ref.getTotalHits().intValue() + 1));
+                
+                log.debug("Incrementing hit count on existing referer: "+referrerUrl);
+                
+                saveReferer(ref);
+                
+            } else if (matchRef.size() == 0) {
+                
+                // Referer was not found in database, so new Referer object
+                Integer one = new Integer(1);
+                RefererData ref =
+                        new RefererData(
+                        null,
+                        weblog,
+                        entry,
+                        dateString,
+                        referrerUrl,
+                        null,
+                        requestUrl,
+                        null,
+                        "", // Read comment above regarding Derby bug
+                        Boolean.FALSE,
+                        Boolean.FALSE,
+                        one,
+                        one);
+                
+                if (log.isDebugEnabled()) {
+                    log.debug("newReferer="+ref.getRefererUrl());
+                }
+                
+                String refurl = ref.getRefererUrl();
+                
+                // If not a direct or search engine then search for linkback
+                boolean doLinkbackExtraction =
+                        RollerRuntimeConfig.getBooleanProperty("site.linkbacks.enabled");
+                if (doLinkbackExtraction
+                        && entry != null
+                        && !refurl.equals("direct")
+                        && !refurl.startsWith("http://google")
+                        && !refurl.startsWith("http://www.google")
+                        && !refurl.startsWith("http://search.netscape")
+                        && !refurl.startsWith("http://www.blinkpro")
+                        && !refurl.startsWith("http://search.msn")
+                        && !refurl.startsWith("http://search.yahoo")
+                        && !refurl.startsWith("http://uk.search.yahoo")
+                        && !refurl.startsWith("http://www.javablogs.com")
+                        && !refurl.startsWith("http://www.teoma")
+                        ) {
+                    // Launch thread to extract referer linkback
+                    
+                    try {
+                        Roller mRoller = RollerFactory.getRoller();
+                        mRoller.getThreadManager().executeInBackground(
+                                new LinkbackExtractorRunnable(ref));
+                    } catch (InterruptedException e) {
+                        log.warn("Interrupted during linkback extraction",e);
+                    }
+                } else {
+                    saveReferer(ref);
+                }
+            }
+        } catch (RollerException pe) {
+            log.error(pe);
+        } catch (NullPointerException npe) {
+            log.error(npe);
+        }
+    }
+    
+    
+    /**
+     * Use LinkbackExtractor to parse title and excerpt from referer
+     */
+    class LinkbackExtractorRunnable implements Runnable {
+        
+        private RefererData mReferer = null;
+        
+        public LinkbackExtractorRunnable( RefererData referer) {
+            mReferer = referer;
+        }
+        
+        public void run() {
+            
+            try {
+                LinkbackExtractor lb = new LinkbackExtractor(
+                        mReferer.getRefererUrl(),mReferer.getRequestUrl());
+                
+                if ( lb.getTitle()!=null && lb.getExcerpt()!=null ) {
+                    mReferer.setTitle(lb.getTitle());
+                    mReferer.setExcerpt(lb.getExcerpt());
+                    
+                    if ( lb.getPermalink() != null ) {
+                        // The presence of a permalink indicates that this
+                        // linkback was parsed out of an RSS feed and is
+                        // presumed to be a good linkback.
+                        
+                        mReferer.setRefererPermalink(lb.getPermalink());
+                        
+                        // See if this request/permalink is in the DB
+                        List matchRef = getExistingReferers(
+                                mReferer.getWebsite(),
+                                mReferer.getDateString(),
+                                mReferer.getRefererPermalink());
+                        
+                        // If it is the first, then set it to be visible
+                        if ( matchRef.size() == 0 ) {
+                            mReferer.setVisible(Boolean.TRUE);
+                        } else {
+                            // We can't throw away duplicates or we will
+                            // end up reparsing them everytime a hit comes
+                            // in from one of them, but we can mark them
+                            // as duplicates.
+                            mReferer.setDuplicate(Boolean.TRUE);
+                        }
+                        
+                        saveReferer(mReferer);
+                        
+                    }
+                    
+                    else {
+                        // Store the new referer
+                        saveReferer(mReferer);
+                        
+                        // Hacky Referer URL weighting kludge:
+                        //
+                        // If there are multple referers to a request URL,
+                        // then we want to pick the best one. The others
+                        // are marked as duplicates. To do this we use a
+                        // weight. The weight formula is:
+                        //
+                        // w = URL length + (100 if URL contains anchor)
+                        
+                        // LOOP: find the referer with the highest weight
+                        Boolean visible = Boolean.FALSE;
+                        List refs= getReferersWithSameTitle(
+                                mReferer.getWebsite(),
+                                mReferer.getRequestUrl(),
+                                lb.getTitle(),
+                                lb.getExcerpt());
+                        RefererData chosen = null;
+                        int maxweight = 0;
+                        for (Iterator rdItr = refs.iterator();rdItr.hasNext();) {
+                            RefererData referer = (RefererData) rdItr.next();
+                            
+                            int weight = referer.getRefererUrl().length();
+                            if (referer.getRefererUrl().indexOf('#') != -1) {
+                                weight += 100;
+                            }
+                            
+                            if ( weight > maxweight ) {
+                                chosen = referer;
+                                maxweight = weight;
+                            }
+                            
+                            if (referer.getVisible().booleanValue()) {
+                                // If any are visible then chosen
+                                // replacement must be visible as well.
+                                visible = Boolean.TRUE;
+                            }
+                            
+                        }
+                        
+                        // LOOP: to mark all of the lower weight ones
+                        // as duplicates
+                        for (Iterator rdItr = refs.iterator();rdItr.hasNext();) {
+                            RefererData referer = (RefererData) rdItr.next();
+                            
+                            if (referer != chosen) {
+                                referer.setDuplicate(Boolean.TRUE);
+                            } else {
+                                referer.setDuplicate(Boolean.FALSE);
+                                referer.setVisible(visible);
+                            }
+                            saveReferer(referer);
+                        }
+                        
+                        
+                    }
+                } else {
+                    // It is not a linkback, but store it anyway
+                    saveReferer(mReferer);
+                    
+                    log.info("No excerpt found at refering URL "
+                            + mReferer.getRefererUrl());
+                }
+            } catch (Exception e) {
+                log.error("Processing linkback",e);
+            } finally {
+                strategy.release();
+            }
+            
+        }
+        
+    }
+    
+    
+    public void release() {}
+    
+}
+
+
+

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRollerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRollerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRollerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRollerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,228 @@
+/*
+* 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.
+*/
+/*
+ * Created on Feb 23, 2003
+ */
+package org.apache.roller.business.hibernate;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.RollerException;
+import org.apache.roller.business.RollerImpl;
+import org.apache.roller.model.BookmarkManager;
+import org.apache.roller.model.ConfigManager;
+import org.apache.roller.model.AutoPingManager;
+import org.apache.roller.model.PingQueueManager;
+import org.apache.roller.model.PingTargetManager;
+import org.apache.roller.model.PlanetManager;
+import org.apache.roller.model.PropertiesManager;
+import org.apache.roller.model.RefererManager;
+import org.apache.roller.model.Roller;
+import org.apache.roller.model.UserManager;
+import org.apache.roller.model.WeblogManager;
+
+
+/**
+ * A Hibernate specific implementation of the Roller business layer.
+ */
+public class HibernateRollerImpl extends RollerImpl {
+    
+    static final long serialVersionUID = 5256135928578074652L;
+    
+    private static Log mLogger = LogFactory.getLog(HibernateRollerImpl.class);
+    
+    // our singleton instance
+    private static HibernateRollerImpl me = null;
+    
+    // a persistence utility class
+    private HibernatePersistenceStrategy strategy = null;
+    
+    // references to the managers we maintain
+    private BookmarkManager bookmarkManager = null;
+    private ConfigManager configManager = null;
+    private PropertiesManager propertiesManager = null;
+    private PlanetManager planetManager = null;
+    private RefererManager refererManager = null;
+    private UserManager userManager = null;
+    private WeblogManager weblogManager = null;
+    private PingQueueManager pingQueueManager = null;
+    private AutoPingManager autoPingManager = null;
+    private PingTargetManager pingTargetManager = null;
+    
+    
+    protected HibernateRollerImpl() throws RollerException {
+        try {
+            strategy = new HibernatePersistenceStrategy();
+        } catch(Throwable t) {
+            // if this happens then we are screwed
+            throw new RollerException(t);
+        }
+    }
+    
+    
+    /**
+     * Instantiates and returns an instance of HibernateRollerImpl.
+     */
+    public static Roller instantiate() throws RollerException {
+        if (me == null) {
+            mLogger.debug("Instantiating HibernateRollerImpl");
+            me = new HibernateRollerImpl();
+        }
+        
+        return me;
+    }
+    
+    
+    public void flush() throws RollerException {
+        this.strategy.flush();
+    }
+    
+    
+    public void release() {
+        
+        // release our own stuff first
+        if (bookmarkManager != null) bookmarkManager.release();
+        if (configManager != null) configManager.release();
+        if (refererManager != null) refererManager.release();
+        if (userManager != null) userManager.release();
+        if (weblogManager != null) weblogManager.release();
+        if (pingTargetManager != null) pingTargetManager.release();
+        if (pingQueueManager != null) pingQueueManager.release();
+        if (autoPingManager != null) autoPingManager.release();
+        
+        // tell Hibernate to close down
+        this.strategy.release();
+        
+        // then let parent do its thing
+        super.release();
+    }
+    
+    
+    public void shutdown() {
+        
+        // do our own shutdown first
+        this.release();
+        
+        // then let parent do its thing
+        super.shutdown();
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.Roller#getUserManager()
+     */
+    public UserManager getUserManager() throws RollerException {
+        if ( userManager == null ) {
+            userManager = new HibernateUserManagerImpl(strategy);
+        }
+        return userManager;
+    }
+    
+    /**
+     * @see org.apache.roller.model.Roller#getBookmarkManager()
+     */
+    public BookmarkManager getBookmarkManager() throws RollerException {
+        if ( bookmarkManager == null ) {
+            bookmarkManager = new HibernateBookmarkManagerImpl(strategy);
+        }
+        return bookmarkManager;
+    }
+    
+    /**
+     * @see org.apache.roller.model.Roller#getWeblogManager()
+     */
+    public WeblogManager getWeblogManager() throws RollerException {
+        if ( weblogManager == null ) {
+            weblogManager = new HibernateWeblogManagerImpl(strategy);
+        }
+        return weblogManager;
+    }
+    
+    /**
+     * @see org.apache.roller.model.Roller#getRefererManager()
+     */
+    public RefererManager getRefererManager() throws RollerException {
+        if ( refererManager == null ) {
+            refererManager = new HibernateRefererManagerImpl(strategy);
+        }
+        return refererManager;
+    }
+    
+    /**
+     * @see org.apache.roller.model.Roller#getConfigManager()
+     */
+    public ConfigManager getConfigManager() throws RollerException {
+        if (configManager == null) {
+            configManager = new HibernateConfigManagerImpl(strategy);
+        }
+        return configManager;
+    }
+    
+    /**
+     * @see org.apache.roller.model.Roller#getPropertiesManager()
+     */
+    public PropertiesManager getPropertiesManager() throws RollerException {
+        if (propertiesManager == null) {
+            propertiesManager = new HibernatePropertiesManagerImpl(strategy);
+        }
+        return propertiesManager;
+    }
+    
+    /**
+     * @see org.apache.roller.model.Roller#getPingTargetManager()
+     */
+    public PingQueueManager getPingQueueManager() throws RollerException {
+        if (pingQueueManager == null) {
+            pingQueueManager = new HibernatePingQueueManagerImpl(strategy);
+        }
+        return pingQueueManager;
+    }
+    
+    /**
+     * @see org.apache.roller.model.Roller#getPlanetManager()
+     */
+    public PlanetManager getPlanetManager() throws RollerException {
+        if ( planetManager == null ) {
+            planetManager = new HibernateRollerPlanetManagerImpl(strategy);
+        }
+        return planetManager;
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.Roller#getPingTargetManager()
+     */
+    public AutoPingManager getAutopingManager() throws RollerException {
+        if (autoPingManager == null) {
+            autoPingManager = new HibernateAutoPingManagerImpl(strategy);
+        }
+        return autoPingManager;
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.Roller#getPingTargetManager()
+     */
+    public PingTargetManager getPingTargetManager() throws RollerException {
+        if (pingTargetManager == null) {
+            pingTargetManager = new HibernatePingTargetManagerImpl(strategy);
+        }
+        return pingTargetManager;
+    }
+    
+}

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRollerPlanetManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRollerPlanetManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRollerPlanetManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateRollerPlanetManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,169 @@
+/*
+* 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.
+*/
+/*
+ * HibernateRollerPlanetManagerImpl.java
+ *
+ * Created on April 17, 2006, 1:53 PM
+ */
+
+package org.apache.roller.business.hibernate;
+
+import com.sun.syndication.fetcher.FeedFetcher;
+import com.sun.syndication.fetcher.impl.FeedFetcherCache;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.velocity.VelocityContext;
+import org.apache.roller.RollerException;
+import org.apache.roller.config.RollerRuntimeConfig;
+import org.apache.roller.model.PagePluginManager;
+import org.apache.roller.model.Roller;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.model.UserManager;
+import org.apache.roller.model.WeblogManager;
+import org.apache.roller.pojos.PlanetEntryData;
+import org.apache.roller.pojos.PlanetSubscriptionData;
+import org.apache.roller.pojos.WeblogEntryData;
+import org.apache.roller.pojos.WebsiteData;
+import org.apache.roller.util.StringUtils;
+
+
+/**
+ * An extended version of the base PlanetManager implementation.
+ * 
+ * This is meant for use by Roller installations that are running the planet
+ * aggregator in the same application instance and want to fetch feeds from
+ * their local Roller blogs in a more efficient manner.
+ */
+public class HibernateRollerPlanetManagerImpl extends HibernatePlanetManagerImpl {
+    
+    private static Log log = LogFactory.getLog(HibernateRollerPlanetManagerImpl.class);
+    
+    
+    public HibernateRollerPlanetManagerImpl(HibernatePersistenceStrategy strat) {
+        
+        super(strat);
+        
+        log.info("Instantiating Hibernate Roller Planet Manager");
+    }
+    
+    
+    protected Set getNewEntries(PlanetSubscriptionData sub,
+                                FeedFetcher feedFetcher,
+                                FeedFetcherCache feedInfoCache)
+            throws RollerException {
+        
+        String localURL = RollerRuntimeConfig.getProperty("site.absoluteurl");
+        
+        // if this is not a local url then let parent deal with it
+        if (StringUtils.isEmpty(localURL) || !sub.getFeedUrl().startsWith(localURL)) {
+            
+            log.debug("Feed is remote, letting parent handle it "+sub.getFeedUrl());
+            
+            return super.getNewEntries(sub, feedFetcher, feedInfoCache);
+        }
+        
+        // url must be local, lets deal with it
+        Set newEntries = new TreeSet();
+        try {
+            // for local feeds, sub.author = website.handle
+            if (sub.getAuthor()!=null && sub.getFeedUrl().endsWith(sub.getAuthor())) {
+                
+                log.debug("Getting LOCAL feed "+sub.getFeedUrl());
+                
+                // get corresponding website object
+                UserManager usermgr = RollerFactory.getRoller().getUserManager();
+                WebsiteData website = usermgr.getWebsiteByHandle(sub.getAuthor());
+                if (website == null) return newEntries;
+                
+                // figure website last update time
+                WeblogManager blogmgr = RollerFactory.getRoller().getWeblogManager();
+                
+                Date siteUpdated = blogmgr.getWeblogLastPublishTime(website);
+                if (siteUpdated == null) { // Site never updated, skip it
+                    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
+                    
+                    sub.setLastUpdated(siteUpdated);
+                    saveSubscription(sub);
+                    
+                } else {
+                    if (log.isDebugEnabled()) {
+                        String msg = MessageFormat.format(
+                                "   Skipping ({0} / {1})", new Object[] {
+                            siteUpdated, sub.getLastUpdated()});
+                        log.debug(msg);
+                    }
+                }
+                
+                // Populate subscription object with new entries
+                PagePluginManager ppmgr = RollerFactory.getRoller().getPagePluginManager();
+                Map pagePlugins = ppmgr.createAndInitPagePlugins(
+                        website,
+                        null,
+                        RollerRuntimeConfig.getProperty("site.absoluteurl"),
+                        new VelocityContext());
+                Iterator entryIter = entries.iterator();
+                while (entryIter.hasNext()) {
+                    try {
+                        WeblogEntryData rollerEntry =
+                                (WeblogEntryData)entryIter.next();
+                        PlanetEntryData entry =
+                                new PlanetEntryData(rollerEntry, sub, pagePlugins);
+                        saveEntry(entry);
+                        newEntries.add(entry);
+                    } catch (Exception e) {
+                        log.error("ERROR processing subscription entry", e);
+                    }
+                }
+                return newEntries;
+            }
+        } catch (Exception e) {
+            log.warn("Problem reading local feed", e);
+        }
+        
+        log.debug("Failed to fetch locally, trying remote "+sub.getFeedUrl());
+        
+        // if there was an error then try normal planet method
+        return super.getNewEntries(sub, feedFetcher, feedInfoCache);
+    }
+    
+}