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 [2/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/ThemeManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/ThemeManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/ThemeManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/ThemeManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,390 @@
+/*
+* 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.
+*/
+/*
+ * ThemeManagerImpl.java
+ *
+ * Created on June 27, 2005, 1:33 PM
+ */
+
+package org.apache.roller.business;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.RollerException;
+import org.apache.roller.ThemeNotFoundException;
+import org.apache.roller.config.RollerConfig;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.model.ThemeManager;
+import org.apache.roller.model.UserManager;
+import org.apache.roller.pojos.Theme;
+import org.apache.roller.pojos.ThemeTemplate;
+import org.apache.roller.pojos.WeblogTemplate;
+import org.apache.roller.pojos.WebsiteData;
+
+
+/**
+ * Base implementation of a ThemeManager.
+ * 
+ * This particular implementation reads theme data off the filesystem 
+ * and assumes that those themes are not changable at runtime.
+ *
+ * @author Allen Gilliland
+ */
+public class ThemeManagerImpl implements ThemeManager {
+    
+    private static Log mLogger = 
+        LogFactory.getFactory().getInstance(ThemeManagerImpl.class);
+    
+    private Map themes;
+    
+    
+    protected ThemeManagerImpl() {
+        
+        // rather than be lazy we are going to load all themes from
+        // the disk preemptively during initialization and cache them
+        mLogger.debug("Initializing ThemeManagerImpl");
+        
+        this.themes = this.loadAllThemesFromDisk();
+        mLogger.info("Loaded "+this.themes.size()+" themes from disk.");
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.ThemeManager#getTheme(java.lang.String)
+     */
+    public Theme getTheme(String name) 
+        throws ThemeNotFoundException, RollerException {
+        
+        Theme theme = (Theme) this.themes.get(name);
+        if(theme == null)
+            throw new ThemeNotFoundException("Couldn't find theme ["+name+"]");
+        
+        return theme;
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.ThemeManager#getThemeById(java.lang.String)
+     */
+    public Theme getThemeById(String id) 
+        throws ThemeNotFoundException, RollerException {
+        
+        // In this implementation where themes come from the filesystem we
+        // know that the name and id for a theme are the same
+        return this.getTheme(id);
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.ThemeManager#getThemesList()
+     */
+    public List getThemesList() {
+        
+        List themes = new ArrayList(this.themes.keySet());
+        
+        // sort 'em ... the natural sorting order for Strings is alphabetical
+        Collections.sort(themes);
+        
+        return themes;
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.ThemeManager#getEnabledThemesList()
+     */
+    public List getEnabledThemesList() {
+        
+        Collection all_themes = this.themes.values();
+        
+        // make a new list of only the enabled themes
+        List enabled_themes = new ArrayList();
+        Iterator it = all_themes.iterator();
+        Theme theme = null;
+        while(it.hasNext()) {
+            theme = (Theme) it.next();
+            if(theme.isEnabled())
+                enabled_themes.add(theme.getName());
+        }
+                
+        // sort 'em ... the natural sorting order for Strings is alphabetical
+        Collections.sort(enabled_themes);
+        
+        return enabled_themes;
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.ThemeManager#getTemplate(String, String)
+     */
+    public ThemeTemplate getTemplate(String theme_name, String template_name)
+        throws ThemeNotFoundException, RollerException {
+        
+        // basically we just try and lookup the theme first, then template
+        Theme theme = this.getTheme(theme_name);
+        
+        return theme.getTemplate(template_name);
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.ThemeManager#getTemplateById(java.lang.String)
+     */
+    public ThemeTemplate getTemplateById(String id)
+        throws ThemeNotFoundException, RollerException {
+        
+        if(id == null)
+            throw new ThemeNotFoundException("Theme id was null");
+        
+        // in our case we expect a template id to be <theme>:<template>
+        // so extract each piece and do the lookup
+        String[] split = id.split(":",  2);
+        if(split.length != 2)
+            throw new ThemeNotFoundException("Invalid theme id ["+id+"]");
+        
+        return this.getTemplate(split[0], split[1]);
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.ThemeManager#getTemplateByLink(java.lang.String)
+     */
+    public ThemeTemplate getTemplateByLink(String theme_name, String template_link)
+        throws ThemeNotFoundException, RollerException {
+        
+        // basically we just try and lookup the theme first, then template
+        Theme theme = this.getTheme(theme_name);
+        
+        return theme.getTemplateByLink(template_link);
+    }
+    
+    
+    /**
+     * This is a convenience method which loads all the theme data from
+     * themes stored on the filesystem in the roller webapp /themes/ directory.
+     */
+    private Map loadAllThemesFromDisk() {
+        
+        Map themes = new HashMap();
+        
+        // NOTE: we need to figure out how to get the roller context path
+        String themespath = RollerConfig.getProperty("context.realpath");
+        if(themespath.endsWith(File.separator))
+            themespath += "themes";
+        else
+            themespath += File.separator + "themes";
+        
+        // first, get a list of the themes available
+        File themesdir = new File(themespath);
+        FilenameFilter filter = new FilenameFilter() {
+            public boolean accept(File dir, String name) {
+                File file =
+                        new File(dir.getAbsolutePath() + File.separator + name);
+                return file.isDirectory();
+            }
+        };
+        String[] themenames = themesdir.list(filter);
+        
+        if(themenames == null)
+            themenames = new String[0];
+        
+        // now go through each theme and read all it's templates
+        Theme theme = null;
+        for(int i=0; i < themenames.length; i++) {
+            try {
+                theme = this.loadThemeFromDisk(themenames[i], 
+                            themespath + File.separator + themenames[i]);            
+                themes.put(theme.getName(), theme);
+            } catch (Throwable unexpected) {
+                // shouldn't happen, so let's learn why it did
+                mLogger.error("Problem reading theme " + themenames[i], unexpected);
+            }
+        }
+        
+        return themes;
+    }
+        
+    /**
+     * Another convenience method which knows how to load a single theme
+     * off the filesystem and return a Theme object
+     */
+    private Theme loadThemeFromDisk(String theme_name, String themepath) {
+        
+        mLogger.info("Loading theme "+theme_name);  
+        
+        Theme theme = new Theme();
+        theme.setName(theme_name);
+        theme.setAuthor("Roller");
+        theme.setLastEditor("Roller");
+        theme.setEnabled(true);
+        
+        // start by getting a list of the .vm files for this theme
+        File themedir = new File(themepath);
+        FilenameFilter filter = new FilenameFilter()
+        {
+            public boolean accept(File dir, String name)
+            {
+                return name.endsWith(".vm");
+            }
+        };
+        String[] templates = themedir.list(filter);
+        
+        // go through each .vm file and read in its contents to a ThemeTemplate
+        String template_name = null;
+        ThemeTemplate theme_template = null;
+        for (int i=0; i < templates.length; i++) {
+            // strip off the .vm part
+            template_name = templates[i].substring(0, templates[i].length() - 3);            
+            File template_file = new File(themepath + File.separator + templates[i]);
+            
+            // Continue reading theme even if problem encountered with one file
+            String msg = "read theme template file ["+template_file+"]";
+            if(!template_file.exists() && !template_file.canRead()) {
+                mLogger.error("Couldn't " + msg);
+                continue;
+            }
+            char[] chars = null;
+            try {
+                FileReader reader = new FileReader(template_file);
+                chars = new char[(int) template_file.length()];
+                reader.read(chars);            
+            } catch (Exception noprob) {
+                mLogger.error("Exception while attempting to " + msg);
+                if (mLogger.isDebugEnabled()) mLogger.debug(noprob);
+                continue;
+            }
+
+            // construct ThemeTemplate representing this file
+            theme_template = new ThemeTemplate(
+                    theme_name+":"+template_name,
+                    template_name,
+                    template_name,
+                    new String(chars),
+                    template_name,
+                    new Date(template_file.lastModified()));
+
+            // add it to the theme
+            theme.setTemplate(template_name, theme_template);
+        }
+        
+        // use the last mod date of the last template file
+        // as the last mod date of the theme
+        theme.setLastModified(theme_template.getLastModified());
+        
+        return theme;
+    }
+
+    /**
+     * Helper method that copies down the pages from a given theme into a
+     * users weblog templates.
+     *
+     * @param rreq Request wrapper.
+     * @param theme Name of theme to save.
+     * @throws RollerException
+     */
+    public void saveThemePages(WebsiteData website, Theme theme)
+        throws RollerException {
+        
+        mLogger.debug("Setting custom templates for website: "+website.getName());
+        
+        try {
+            UserManager userMgr = RollerFactory.getRoller().getUserManager();
+            
+            Collection templates = theme.getTemplates();
+            Iterator iter = templates.iterator();
+            ThemeTemplate theme_template = null;
+            while ( iter.hasNext() ) {
+                theme_template = (ThemeTemplate) iter.next();
+                
+                WeblogTemplate template = null;
+                
+                if(theme_template.getName().equals(WeblogTemplate.DEFAULT_PAGE)) {
+                    // this is the main Weblog template
+                    try {
+                        template = userMgr.getPage(website.getDefaultPageId());
+                    } catch(Exception e) {
+                        // user may not have a default page yet
+                    }
+                } else {
+                    // any other template
+                    template = userMgr.getPageByName(website, theme_template.getName());
+                }
+                
+                
+                if (template != null) {
+                    // User already has page by that name, so overwrite it.
+                    template.setContents(theme_template.getContents());
+                    
+                } else {
+                    // User does not have page by that name, so create new page.
+                    template = new WeblogTemplate( null,
+                            website,                            // website
+                            theme_template.getName(),           // name
+                            theme_template.getDescription(),    // description
+                            theme_template.getName(),           // link
+                            theme_template.getContents(),       // contents
+                            new Date()                          // last mod
+                            );
+                    userMgr.savePage( template );
+                }
+            }
+            
+            // now update this website's theme to custom
+            website.setEditorTheme(Theme.CUSTOM);
+            
+            // if this is the first time someone is customizing a theme then
+            // we need to set a default page
+            if(website.getDefaultPageId() == null ||
+                    website.getDefaultPageId().trim().equals("") ||
+                    website.getDefaultPageId().equals("dummy")) {
+                // we have to go back to the db to figure out the id
+                WeblogTemplate template = userMgr.getPageByName(website, "Weblog");
+                if(template != null) {
+                    mLogger.debug("Setting default page to "+template.getId());
+                    website.setDefaultPageId(template.getId());
+                }
+            }
+            
+            // we also want to set the weblogdayid
+            WeblogTemplate dayTemplate = userMgr.getPageByName(website, "_day");
+            if(dayTemplate != null) {
+                mLogger.debug("Setting default day page to "+dayTemplate.getId());
+                website.setWeblogDayPageId(dayTemplate.getId());
+            }
+            
+            // save our updated website
+            userMgr.saveWebsite(website);
+            
+        } catch (Exception e) {
+            mLogger.error("ERROR in action",e);
+            throw new RollerException( e );
+        }       
+    }
+}

Added: incubator/roller/trunk/src/org/apache/roller/business/ThreadManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/ThreadManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/ThreadManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/ThreadManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,109 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+*  contributor license agreements.  The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.roller.business;
+
+import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;
+import EDU.oswego.cs.dl.util.concurrent.DirectExecutor;
+import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
+import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;
+
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.apache.roller.model.ThreadManager;
+import org.apache.roller.util.DateUtil;
+
+/**
+ * Manage Roller's background thread use. Currently, Roller starts background
+ * threads for two purposes: 1) the nightly purge of referer counts and 2)
+ * following linkbacks (only occurs if linkbacks are enabled).
+ *
+ * @author aim4min
+ */
+public class ThreadManagerImpl implements ThreadManager
+{
+    private PooledExecutor backgroundExecutor;
+    private DirectExecutor nodelayExecutor;
+    private Timer scheduler;
+
+    public ThreadManagerImpl()
+    {
+        backgroundExecutor = new PooledExecutor(new BoundedBuffer(10), 25);
+        backgroundExecutor.setMinimumPoolSize(4);
+        backgroundExecutor.setKeepAliveTime(1000 * 60 * 5);
+        backgroundExecutor.waitWhenBlocked();
+        backgroundExecutor.createThreads(9);
+
+        backgroundExecutor.setThreadFactory(new ThreadFactory() {
+            public Thread newThread(Runnable command)
+            {
+                Thread t = new Thread(command);
+                t.setDaemon(false);
+                t.setName("Background Execution Threads");
+                t.setPriority(Thread.NORM_PRIORITY);
+
+                return t;
+            }
+        });
+
+        nodelayExecutor = new DirectExecutor();
+        scheduler = new Timer(true);
+    }
+
+    public void executeInBackground(Runnable runnable)
+            throws InterruptedException
+    {
+        backgroundExecutor.execute(runnable);
+    }
+
+    public void executeInForeground(Runnable runnable)
+            throws InterruptedException
+    {
+        nodelayExecutor.execute(runnable);
+    }
+
+    public void scheduleDailyTimerTask(TimerTask task)
+    {
+        scheduler.scheduleAtFixedRate(task,
+                DateUtil.getEndOfDay(new Date()), DateUtil.millisInDay);
+    }
+
+    public void scheduleHourlyTimerTask(TimerTask task)
+    {
+        scheduler.scheduleAtFixedRate(task, new Date(), 60*60*1000);
+    }
+
+    public void scheduleFixedRateTimerTask(TimerTask task, long delayMins, long periodMins) {
+        if (periodMins < MIN_RATE_INTERVAL_MINS) {
+            throw new IllegalArgumentException("Period (" + periodMins +
+                ") shorter than minimum allowed (" + MIN_RATE_INTERVAL_MINS + ")");
+        }
+        scheduler.scheduleAtFixedRate(task, delayMins * 60 * 1000, periodMins * 60 * 1000);
+    }
+
+    public void shutdown()
+    {
+        backgroundExecutor.shutdownAfterProcessingCurrentlyQueuedTasks();
+        scheduler.cancel();
+    }
+
+    public void release()
+    {
+    }
+}
\ No newline at end of file

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateAutoPingManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateAutoPingManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateAutoPingManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateAutoPingManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.business.hibernate;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.criterion.Expression;
+import org.apache.roller.RollerException;
+import org.apache.roller.pojos.AutoPingData;
+import org.apache.roller.pojos.PingTargetData;
+import org.apache.roller.pojos.WeblogEntryData;
+import org.apache.roller.pojos.WebsiteData;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.config.PingConfig;
+import org.apache.roller.model.AutoPingManager;
+import org.apache.roller.model.PingQueueManager;
+import org.apache.roller.model.RollerFactory;
+
+
+/**
+ * Hibernate implementation of the AutoPingManager.
+ *
+ * @author <a href="mailto:anil@busybuddha.org">Anil Gangolli</a>
+ */
+public class HibernateAutoPingManagerImpl implements AutoPingManager {
+    
+    static final long serialVersionUID = 5420615676256979199L;
+    
+    private static Log log = LogFactory.getLog(HibernateAutoPingManagerImpl.class);
+    
+    private HibernatePersistenceStrategy strategy = null;
+    
+    
+    public HibernateAutoPingManagerImpl(HibernatePersistenceStrategy strat) {
+        this.strategy = strat;
+    }
+    
+    
+    public AutoPingData getAutoPing(String id) throws RollerException {
+        return (AutoPingData) strategy.load(id, AutoPingData.class);
+    }
+    
+    
+    public void saveAutoPing(AutoPingData autoPing) throws RollerException {
+        strategy.store(autoPing);
+    }
+    
+    
+    public void removeAutoPing(AutoPingData autoPing)  throws RollerException {
+        //TODO: first remove all related category restrictions (category restrictions are not yet implemented)
+        strategy.remove(autoPing);
+    }
+    
+    
+    public void removeAutoPing(PingTargetData pingTarget, WebsiteData website) throws RollerException {
+        try {
+            Session session = strategy.getSession();
+            Criteria criteria = session.createCriteria(AutoPingData.class);
+            
+            // Currently category restrictions are not yet implemented, so we 
+            // return all auto ping configs for the website.
+            criteria.add(Expression.eq("pingTarget", pingTarget));
+            criteria.add(Expression.eq("website", website));
+            List matches = criteria.list();
+            
+            // This should have at most one element, but we remove them all regardless.
+            this.removeAutoPings(matches);
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    public void removeAutoPings(Collection autopings) throws RollerException {
+        
+        // just go through the list and remove each auto ping
+        Iterator pings = autopings.iterator();
+        while (pings.hasNext()) {
+            this.strategy.remove((AutoPingData) pings.next());
+        }
+    }
+    
+    
+    public void removeAllAutoPings() throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+            Criteria criteria = session.createCriteria(AutoPingData.class);
+            List allAutoPings = criteria.list();
+            this.removeAutoPings(allAutoPings);
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    public void queueApplicableAutoPings(WeblogEntryData changedWeblogEntry) throws RollerException {
+        if (PingConfig.getSuspendPingProcessing()) {
+            if (log.isDebugEnabled()) log.debug("Ping processing is suspended.  No auto pings will be queued.");
+            return;
+        }
+        
+        // TODO: new manager method for addQueueEntries(list)?
+        PingQueueManager pingQueueMgr = RollerFactory.getRoller().getPingQueueManager();
+        List applicableAutopings = getApplicableAutoPings(changedWeblogEntry);
+        for (Iterator i = applicableAutopings.iterator(); i.hasNext(); ) {
+            AutoPingData autoPing = (AutoPingData) i.next();
+            pingQueueMgr.addQueueEntry(autoPing);
+        }
+    }
+    
+    
+    public List getAutoPingsByWebsite(WebsiteData website) throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+            Criteria criteria = session.createCriteria(AutoPingData.class);
+            // Currently category restrictions are not yet implemented, so we return all auto ping configs for the
+            // website.
+            criteria.add(Expression.eq("website", website));
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    public List getAutoPingsByTarget(PingTargetData pingTarget) throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+            Criteria criteria = session.createCriteria(AutoPingData.class);
+            // Currently category restrictions are not yet implemented, so we return all auto ping configs for the
+            // website.
+            criteria.add(Expression.eq("pingTarget", pingTarget));
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    public List getApplicableAutoPings(WeblogEntryData changedWeblogEntry) throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+            Criteria criteria = session.createCriteria(AutoPingData.class);
+            // Currently category restrictions are not yet implemented, so we return all auto ping configs for the
+            // website.
+            criteria.add(Expression.eq("website", changedWeblogEntry.getWebsite()));
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    public List getCategoryRestrictions(AutoPingData autoPing) throws RollerException {
+        return Collections.EMPTY_LIST;
+    }
+    
+    
+    public void setCategoryRestrictions(AutoPingData autoPing, Collection newCategories) {
+        // NOT YET IMPLEMENTED
+        return;
+    }
+    
+    
+    public void release() {}
+    
+}

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateBookmarkManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateBookmarkManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateBookmarkManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateBookmarkManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,544 @@
+/*
+* 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 Jun 18, 2004
+ */
+package org.apache.roller.business.hibernate;
+
+import java.io.IOException;
+import java.io.StringReader;
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.criterion.Expression;
+import org.apache.roller.RollerException;
+import org.apache.roller.pojos.Assoc;
+import org.apache.roller.pojos.BookmarkData;
+import org.apache.roller.pojos.FolderAssoc;
+import org.apache.roller.pojos.FolderData;
+import org.apache.roller.pojos.WebsiteData;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.apache.roller.model.BookmarkManager;
+import org.apache.roller.util.Utilities;
+
+
+/**
+ * Hibernate implementation of the BookmarkManager.
+ */
+public class HibernateBookmarkManagerImpl implements BookmarkManager {
+    
+    static final long serialVersionUID = 5286654557062382772L;
+    
+    private static Log log = LogFactory.getLog(HibernateBookmarkManagerImpl.class);
+    
+    private HibernatePersistenceStrategy strategy = null;
+    
+    
+    /**
+     * @param pstrategy
+     * @param roller
+     */
+    public HibernateBookmarkManagerImpl(HibernatePersistenceStrategy strat) {
+        log.debug("Instantiating Hibernate Bookmark Manager");
+        
+        this.strategy = strat;
+    }
+    
+    
+    public void saveBookmark(BookmarkData bookmark) throws RollerException {
+        this.strategy.store(bookmark);
+    }
+    
+    
+    public BookmarkData getBookmark(String id) throws RollerException {
+        BookmarkData bd = (BookmarkData)
+        strategy.load(id, BookmarkData.class);
+        // TODO: huh?  why do we do this?
+        if (bd != null) bd.setBookmarkManager(this);
+        return bd;
+    }
+    
+    
+    public void removeBookmark(BookmarkData bookmark) throws RollerException {
+        this.strategy.remove(bookmark);
+    }
+    
+    //------------------------------------------------------------ Folder CRUD
+    
+    
+    public void saveFolder(FolderData folder) throws RollerException {
+        
+        if(isDuplicateFolderName(folder)) {
+            throw new RollerException("Duplicate folder name");
+        }
+        
+        this.strategy.store(folder);
+    }
+    
+    
+    public void removeFolder(FolderData folder) throws RollerException {
+        
+        this.strategy.remove(folder);
+    }
+    
+    
+    /**
+     * Retrieve folder and lazy-load it's sub-folders and bookmarks.
+     */
+    public FolderData getFolder(String id) throws RollerException {
+        return (FolderData)strategy.load(id, FolderData.class);
+    }
+    
+    //------------------------------------------------------------ Operations
+    
+    public void importBookmarks(WebsiteData website, String folderName, String opml)
+            throws RollerException {
+        
+        String msg = "importBookmarks";
+        try {
+            // Build JDOC document OPML string
+            SAXBuilder builder = new SAXBuilder();
+            StringReader reader = new StringReader( opml );
+            Document doc = builder.build( reader );
+            
+            FolderData newFolder = getFolder(website, folderName);
+            if (newFolder == null) {
+                newFolder = new FolderData(
+                        getRootFolder(website), folderName, folderName, website);
+                this.strategy.store(newFolder);
+            }
+            
+            // Iterate through children of OPML body, importing each
+            Element body = doc.getRootElement().getChild("body");
+            Iterator iter = body.getChildren().iterator();
+            while (iter.hasNext()) {
+                Element elem = (Element)iter.next();
+                importOpmlElement( website, elem, newFolder );
+            }
+            
+        } catch (Exception ex) {
+            throw new RollerException(ex);
+        }
+    }
+    
+    // convenience method used when importing bookmarks
+    // NOTE: this method does not commit any changes, that is done by importBookmarks()
+    private void importOpmlElement(
+            WebsiteData website, Element elem, FolderData parent)
+            throws RollerException {
+        String text = elem.getAttributeValue("text");
+        String title = elem.getAttributeValue("title");
+        String desc = elem.getAttributeValue("description");
+        String url = elem.getAttributeValue("url");
+        //String type = elem.getAttributeValue("type");
+        String xmlUrl = elem.getAttributeValue("xmlUrl");
+        String htmlUrl = elem.getAttributeValue("htmlUrl");
+        
+        title =   null!=title ? title : text;
+        desc =    null!=desc ? desc : title;
+        xmlUrl =  null!=xmlUrl ? xmlUrl : url;
+        url =     null!=htmlUrl ? htmlUrl : url;
+        
+        if (elem.getChildren().size()==0) {
+            // Leaf element.  Store a bookmark
+            // Currently bookmarks must have at least a name and HTML url to be stored. Previous logic was
+            // trying to skip invalid ones, but was letting ones with an xml url and no html url through
+            // which could result in a db exception.
+            // TODO: Consider providing error feedback instead of silently skipping the invalid bookmarks here.
+            if (null != title && null != url) {
+                BookmarkData bd = new BookmarkData(parent,
+                        title,
+                        desc,
+                        url,
+                        xmlUrl,
+                        new Integer(0),
+                        new Integer(100),
+                        null);
+                parent.addBookmark(bd);
+                // TODO: maybe this should be saving the folder?
+                this.strategy.store(bd);
+            }
+        } else {
+            // Store a folder
+            FolderData fd = new FolderData(
+                    parent,
+                    title,
+                    desc,
+                    parent.getWebsite());
+            this.strategy.store(fd);
+            
+            // Import folder's children
+            Iterator iter = elem.getChildren("outline").iterator();
+            while ( iter.hasNext() ) {
+                Element subelem = (Element)iter.next();
+                importOpmlElement( website, subelem, fd  );
+            }
+        }
+    }
+    
+    //----------------------------------------------------------------
+    public void moveFolderContents(FolderData src, FolderData dest)
+            throws RollerException {
+        
+        if (dest.descendentOf(src)) {
+            throw new RollerException(
+                    "ERROR cannot move parent folder into it's own child");
+        }
+        
+        try {
+            // Add to destination folder
+            LinkedList deleteList = new LinkedList();
+            Iterator srcBookmarks = src.getBookmarks().iterator();
+            while (srcBookmarks.hasNext()) {
+                BookmarkData bd = (BookmarkData)srcBookmarks.next();
+                deleteList.add(bd);
+                
+                BookmarkData movedBd = new BookmarkData();
+                movedBd.setData(bd);
+                movedBd.setId(null);
+                
+                dest.addBookmark(movedBd);
+                this.strategy.store(movedBd);
+            }
+            
+            // Remove from source folder
+            Iterator deleteIter = deleteList.iterator();
+            while (deleteIter.hasNext()) {
+                BookmarkData bd = (BookmarkData)deleteIter.next();
+                src.removeBookmark(bd);
+                // TODO: this won't conflict with the bookmark we store above right?
+                this.strategy.remove(bd);
+            }
+            
+        } catch (Exception ex) {
+            throw new RollerException(ex);
+        }
+    }
+    
+    //----------------------------------------------------------------
+    public void removeFolderContents(FolderData src) throws RollerException {
+        
+        // just go through the folder and remove each bookmark
+        Iterator srcBookmarks = src.getBookmarks().iterator();
+        while (srcBookmarks.hasNext()) {
+            BookmarkData bd = (BookmarkData)srcBookmarks.next();
+            this.strategy.remove(bd);
+        }
+    }
+    
+    //---------------------------------------------------------------- Queries
+    
+    public FolderData getFolder(WebsiteData website, String folderPath)
+    throws RollerException {
+        return getFolderByPath(website, null, folderPath);
+    }
+    
+    public String getPath(FolderData folder) throws RollerException {
+        if (null == folder.getParent()) {
+            return "/";
+        } else {
+            String parentPath = getPath(folder.getParent());
+            parentPath = "/".equals(parentPath) ? "" : parentPath;
+            return parentPath + "/" + folder.getName();
+        }
+    }
+    
+    public FolderData getFolderByPath(
+            WebsiteData website, FolderData folder, String path)
+            throws RollerException {
+        final Iterator folders;
+        final String[] pathArray = Utilities.stringToStringArray(path, "/");
+        
+        if (folder == null && (null == path || "".equals(path.trim()))) {
+            throw new RollerException("Bad arguments.");
+        }
+        
+        if (path.trim().equals("/")) {
+            return getRootFolder(website);
+        } else if (folder == null || path.trim().startsWith("/")) {
+            folders = getRootFolder(website).getFolders().iterator();
+        } else {
+            folders = folder.getFolders().iterator();
+        }
+        
+        while (folders.hasNext()) {
+            FolderData possibleMatch = (FolderData)folders.next();
+            if (possibleMatch.getName().equals(pathArray[0])) {
+                if (pathArray.length == 1) {
+                    return possibleMatch;
+                } else {
+                    String[] subpath = new String[pathArray.length - 1];
+                    System.arraycopy(pathArray, 1, subpath, 0, subpath.length);
+                    
+                    String pathString= Utilities.stringArrayToString(subpath,"/");
+                    return getFolderByPath(website, possibleMatch, pathString);
+                }
+            }
+        }
+        
+        // The folder did not match and neither did any subfolders
+        return null;
+    }
+    
+    //----------------------------------------------- FolderAssoc CRUD
+    
+    
+    public FolderAssoc retrieveFolderAssoc(String id) throws RollerException {
+        return (FolderAssoc)strategy.load(id, FolderAssoc.class);
+    }
+    
+    public void release() {}
+    
+    /**
+     * @see org.apache.roller.model.BookmarkManager#retrieveBookmarks(
+     *      org.apache.roller.pojos.FolderData, boolean)
+     */
+    public List getBookmarks(FolderData folder, boolean subfolders)
+    throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+            List bookmarks = new LinkedList();
+            if (subfolders) {
+                // get bookmarks in subfolders
+                Criteria assocsQuery = session
+                        .createCriteria(FolderAssoc.class);
+                assocsQuery.add(Expression.eq("ancestorFolder", folder));
+                Iterator assocs = assocsQuery.list().iterator();
+                while (assocs.hasNext()) {
+                    FolderAssoc assoc = (FolderAssoc) assocs.next();
+                    Criteria bookmarksQuery = session
+                            .createCriteria(BookmarkData.class);
+                    bookmarksQuery.add(Expression.eq("folder", assoc
+                            .getFolder()));
+                    Iterator bookmarkIter = bookmarksQuery.list().iterator();
+                    while (bookmarkIter.hasNext()) {
+                        BookmarkData entry = (BookmarkData) bookmarkIter.next();
+                        bookmarks.add(entry);
+                    }
+                }
+            }
+            
+            // get bookmarks in folder
+            Criteria bookmarksQuery = session
+                    .createCriteria(BookmarkData.class);
+            bookmarksQuery.add(Expression.eq("folder", folder));
+            Iterator bookmarkIter = bookmarksQuery.list().iterator();
+            while (bookmarkIter.hasNext()) {
+                BookmarkData bookmark = (BookmarkData) bookmarkIter.next();
+                bookmarks.add(bookmark);
+            }
+            return bookmarks;
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    public FolderData getRootFolder(WebsiteData website) throws RollerException {
+        if (website == null)
+            throw new RollerException("website is null");
+        try {
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+            Criteria criteria = session.createCriteria(FolderAssoc.class);
+            criteria.createAlias("folder", "f");
+            criteria.add(Expression.eq("f.website", website));
+            criteria.add(Expression.isNull("ancestorFolder"));
+            criteria.add(Expression.eq("relation", FolderAssoc.PARENT));
+            List results = criteria.list();
+            if (results.size() > 1) {
+                // Should not have more than one root
+                throw new RollerException(
+                        "More than one root folder found for website "
+                        + website.getId());
+            } else if (results.size() == 1) {
+                // Return root
+                return ((FolderAssoc) results.get(0)).getFolder();
+            }
+            return null;
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    public List getAllFolders(WebsiteData website) throws RollerException {
+        if (website == null)
+            throw new RollerException("Website is null");
+        
+        try {
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+            Criteria criteria = session.createCriteria(FolderData.class);
+            criteria.add(Expression.eq("website", website));
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+        
+    }
+    
+    /**
+     * @see org.apache.roller.model.BookmarkManager#isDuplicateFolderName(org.apache.roller.pojos.FolderData)
+     */
+    public boolean isDuplicateFolderName(FolderData folder) throws RollerException {
+        // ensure that no sibling folders share the same name
+        boolean isNewFolder = (folder.getId() == null);
+        FolderData parent =
+                isNewFolder ? (FolderData)folder.getNewParent() : folder.getParent();
+        
+        if (null != parent) {
+            List sameNames;
+            try {
+                Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+                Criteria criteria = session.createCriteria(FolderAssoc.class);
+                criteria.createAlias("folder", "f");
+                criteria.add(Expression.eq("f.name", folder.getName()));
+                criteria.add(Expression.eq("ancestorFolder", parent));
+                criteria.add(Expression.eq("relation", Assoc.PARENT));
+                sameNames = criteria.list();
+            } catch (HibernateException e) {
+                throw new RollerException(e);
+            }
+            // If we got some matches
+            if (sameNames.size() > 0) {
+                // if we're saving a new folder, any matches are dups
+                if (isNewFolder) return true;
+                // otherwise it's a dup it isn't the same one (one match with the same id).
+                if (!(sameNames.size() == 1 && folder.getId().equals(((FolderAssoc)sameNames.get(0)).getFolder().getId())))
+                    return true;
+            }
+        }
+        return false;
+    }
+    
+    /**
+     * @see org.apache.roller.model.BookmarkManager#getFolderParentAssoc(
+     * org.apache.roller.pojos.FolderData)
+     */
+    public Assoc getFolderParentAssoc(FolderData folder) throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(FolderAssoc.class);
+            criteria.add(Expression.eq("folder", folder));
+            criteria.add(Expression.eq("relation", Assoc.PARENT));
+            List parents = criteria.list();
+            if (parents.size() > 1) {
+                throw new RollerException("ERROR: more than one parent");
+            } else if (parents.size() == 1) {
+                return (Assoc) parents.get(0);
+            } else {
+                return null;
+            }
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    /**
+     * @see org.apache.roller.model.BookmarkManager#getFolderChildAssocs(
+     * org.apache.roller.pojos.FolderData)
+     */
+    public List getFolderChildAssocs(FolderData folder) throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(FolderAssoc.class);
+            criteria.add(Expression.eq("ancestorFolder", folder));
+            criteria.add(Expression.eq("relation", Assoc.PARENT));
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    /**
+     * @see org.apache.roller.model.BookmarkManager#getAllFolderDecscendentAssocs(
+     * org.apache.roller.pojos.FolderData)
+     */
+    public List getAllFolderDecscendentAssocs(FolderData folder) throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(FolderAssoc.class);
+            criteria.add(Expression.eq("ancestorFolder", folder));
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    /**
+     * @see org.apache.roller.model.BookmarkManager#getFolderAncestorAssocs(
+     * org.apache.roller.pojos.FolderData)
+     */
+    public List getFolderAncestorAssocs(FolderData folder) throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(FolderAssoc.class);
+            criteria.add(Expression.eq("folder", folder));
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    /**
+     * @see org.apache.roller.model.BookmarkManager#isFolderInUse(org.apache.roller.pojos.FolderData)
+     */
+    public boolean isFolderInUse(FolderData folder) throws RollerException {
+        try {
+            // We consider a folder to be "in use" if it contains any bookmarks or has
+            // any children.
+            
+            // We first determine the number of bookmark entries.
+            // NOTE: This seems to be an attempt to optimize, rather than just use getBookmarks(),
+            // but I'm not sure that this optimization is really worthwhile, and it ignores
+            // caching in the case that the (lazy) getBookmarks has been done already. --agangolli
+            // TODO: condider changing to just use getBookmarks().size()
+            
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(BookmarkData.class);
+            criteria.add(Expression.eq("folder", folder));
+            criteria.setMaxResults(1);
+            int entryCount = criteria.list().size();
+            
+            // Return true if we have bookmarks or (, failing that, then checking) if we have children
+            return (entryCount > 0 || folder.getFolders().size() > 0);
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    public boolean isDescendentOf(FolderData child, FolderData ancestor)
+    throws RollerException {
+        boolean ret = false;
+        try {
+            Session session = ((HibernatePersistenceStrategy)strategy).getSession();
+            Criteria criteria = session.createCriteria(FolderAssoc.class);
+            criteria.add(Expression.eq("folder", child));
+            criteria.add(Expression.eq("ancestorFolder", ancestor));
+            ret = criteria.list().size() > 0;
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+        return ret;
+    }
+}

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateConfigManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateConfigManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateConfigManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernateConfigManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,107 @@
+/*
+* 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 Jun 18, 2004
+ */
+package org.apache.roller.business.hibernate;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.apache.roller.RollerException;
+import org.apache.roller.pojos.RollerConfigData;
+import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.model.ConfigManager;
+
+
+/**
+ * The *OLD* Roller configuration mechanism.
+ *
+ * This has been replaced by the PropertiesManager and the roller.properties
+ * file.
+ */
+public class HibernateConfigManagerImpl implements ConfigManager {
+    
+    static final long serialVersionUID = -3674252864091781177L;
+    
+    private static Log log = LogFactory.getLog(HibernateConfigManagerImpl.class);
+    
+    private HibernatePersistenceStrategy strategy = null;
+    
+    
+    public HibernateConfigManagerImpl(HibernatePersistenceStrategy strategy) {
+        log.debug("Instantiating Hibernate Config Manager");
+        
+        this.strategy = strategy;
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.ConfigManager#storeRollerConfig(org.apache.roller.pojos.RollerConfig)
+     */
+    public void storeRollerConfig(RollerConfigData data) throws RollerException {
+        // no longer supported
+    }
+    
+    
+    /**
+     * This isn't part of the ConfigManager Interface, because really
+     * we shouldn't ever delete the RollerConfig.  This is mostly here
+     * to assist with unit testing.
+     */
+    public void removeRollerConfig(String id) throws RollerException {
+        // no longer supported
+    }
+    
+    
+    /**
+     * Fetch all RollerConfigs and return the first one, if any.
+     * Note: there should only be one!
+     * @see org.apache.roller.model.ConfigManager#getRollerConfig()
+     */
+    public RollerConfigData getRollerConfig() throws RollerException {
+        
+        log.error("Someone is trying to use the old config!!\n"+
+                "This configuration mechanism has been deprecated\n"+
+                "You should see this message only once when you first upgrade\n"+
+                "your installation to roller 1.2\n\n"+
+                "If you continue to see this message please shoot us an email\n"+
+                "at roller-dev@incubator.apache.org with some output\n"+
+                "from your log files.\n");
+        
+        try {
+            Session session = this.strategy.getSession();
+            Criteria criteria = session.createCriteria(RollerConfigData.class);
+            criteria.setMaxResults(1);
+            return (RollerConfigData) criteria.uniqueResult();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    public RollerConfigData readFromFile(String file) {
+        return null;
+    }
+    
+    
+    public void release() {}
+    
+}

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePersistenceStrategy.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePersistenceStrategy.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePersistenceStrategy.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePersistenceStrategy.java Mon May  1 15:23:02 2006
@@ -0,0 +1,403 @@
+/*
+* 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 Mar 7, 2003
+ */
+package org.apache.roller.business.hibernate;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.cfg.Configuration;
+import org.apache.roller.RollerException;
+import org.apache.roller.pojos.Assoc;
+import org.apache.roller.pojos.HierarchicalPersistentObject;
+import org.apache.roller.pojos.PersistentObject;
+
+
+/**
+ * Base class for Hibernate persistence implementation.
+ *
+ * This class serves as a helper/util class for all of the Hibernate
+ * manager implementations by providing a set of basic persistence methods
+ * that can be easily reused.
+ *
+ */
+public class HibernatePersistenceStrategy {
+    
+    static final long serialVersionUID = 2561090040518169098L;
+    
+    private static SessionFactory sessionFactory = null;
+    
+    private static Log log = LogFactory.getLog(HibernatePersistenceStrategy.class);
+    
+    
+    /**
+     * Construct using Hibernate Session Factory.
+     */
+    public HibernatePersistenceStrategy() throws Exception {
+        
+        log.debug("Initializing Hibernate SessionFactory");
+        
+        Configuration config = new Configuration();
+        config.configure("/hibernate.cfg.xml");
+        this.sessionFactory = config.buildSessionFactory();
+        
+    }
+
+    
+    /**
+     * Get persistence session on current thread.
+     *
+     * This will open a new Session if one is not already open, otherwise
+     * it will return the already open Session.
+     */
+    protected Session getSession() {
+        
+        log.debug("Opening Hibernate Session");
+        
+        // get Hibernate Session and make sure we are in a transaction
+        // this will join existing Session/Transaction if they exist
+        Session session = sessionFactory.getCurrentSession();
+        session.beginTransaction();
+        
+        return session;
+    }
+    
+    
+    protected void flush() throws RollerException {
+        
+        Session session = getSession();
+        try {
+            session.getTransaction().commit();
+        } catch(Throwable t) {
+            // uh oh ... failed persisting, gotta release
+            release();
+        }
+    }
+    
+    
+    /**
+     * Release database session, rollback any uncommitted changes.
+     *
+     * IMPORTANT: we don't want to open a transaction and force the use of a
+     * jdbc connection just to close the session and do a rollback, so this
+     * method must be sensitive about how the release is triggered.
+     *
+     * In particular we don't want to use our custom getSession() method which
+     * automatically begins a transaction.  Instead we get a Session and check
+     * if there is already an active transaction that needs to be rolled back.
+     * If not then we can close the Session without ever getting a jdbc
+     * connection, which is important for scalability.
+     */
+    protected void release() {
+        
+        try {
+            Session session = sessionFactory.getCurrentSession();
+            
+            if(session != null && session.isOpen()) {
+                
+                log.debug("Closing Hibernate Session");
+                
+                try {
+                    Transaction tx = session.getTransaction();
+                    
+                    if(tx != null && tx.isActive()) {
+                        log.debug("Forcing rollback on active transaction");
+                        tx.rollback();
+                    }
+                } catch(Throwable t) {
+                    log.error("ERROR doing Hibernate rollback", t);
+                } finally {
+                    if(session.isOpen()) {
+                        session.close();
+                    }
+                }
+            }
+        } catch(Throwable t) {
+            log.error("ERROR closing Hibernate Session", t);
+        }
+    }
+
+    
+    /**
+     * Retrieve object.  We return null if the object is not found.
+     */
+    protected PersistentObject load(String id, Class clazz) throws RollerException {
+        
+        if(id == null || clazz == null) {
+            throw new RollerException("Cannot load objects when value is null");
+        }
+        
+        return (PersistentObject) getSession().get(clazz, id);
+    }
+    
+    
+    /**
+     * Store object.
+     */
+    protected void store(PersistentObject obj) throws HibernateException {
+        
+        if(obj == null) {
+            throw new HibernateException("Cannot save null object");
+        }
+        
+        Session session = getSession();
+        
+        // TODO BACKEND: this is wacky, we should double check logic here
+        
+        // TODO BACKEND: better to use session.saveOrUpdate() here, if possible
+        if ( obj.getId() == null || obj.getId().trim().equals("") ) {
+            // Object has never been written to database, so save it.
+            // This makes obj into a persistent instance.
+            session.save(obj);
+        }
+        
+        /* 
+         * technically we shouldn't have any reason to support the saving
+         * of detached objects, so at some point we should re-evaluate this.
+         *
+         * objects should be re-attached before being saved again. it would
+         * be more appropriate to reject these kinds of saves because they are
+         * not really safe.
+         *
+         * NOTE: this may be coming from the way we use formbeans on the UI.
+         *   we very commonly repopulate all data in a pojo (including id) from
+         *   form data rather than properly loading the object from a Session
+         *   then modifying its properties.
+         */
+        if ( !session.contains(obj) ) {
+            
+            log.debug("storing detached object: "+obj.toString());
+            
+            // Object has been written to database, but instance passed in
+            // is not a persistent instance, so must be loaded into session.
+            PersistentObject vo =
+                    (PersistentObject)session.load(obj.getClass(),obj.getId());
+            vo.setData(obj);
+            obj = vo;
+        }
+        
+    }
+    
+    
+    /**
+     * Remove object.
+     *
+     * TODO BACKEND: force the use of remove(Object) moving forward.
+     */
+    protected void remove(String id, Class clazz) throws HibernateException {
+        
+        if(id == null || clazz == null) {
+            throw new HibernateException("Cannot remove object when values are null");
+        }
+        
+        Session session = getSession();
+        
+        PersistentObject obj = (PersistentObject) session.load(clazz,id);
+        session.delete(obj);
+    }
+    
+    
+    /**
+     * Remove object.
+     */
+    protected void remove(PersistentObject obj) throws HibernateException {
+        
+        if(obj == null) {
+            throw new HibernateException("Cannot remove null object");
+        }
+        
+        // TODO BACKEND: can hibernate take care of this check for us?
+        //               what happens if object does not use id?
+        // can't remove transient objects
+        if (obj.getId() != null) {
+            
+            getSession().delete(obj);
+        }
+    }
+    
+    
+    /**
+     * Store hierarchical object.
+     *
+     * NOTE: if the object has proper cascade setting then is all this necessary?
+     */
+    protected void store(HierarchicalPersistentObject obj) 
+            throws HibernateException, RollerException {
+        
+        if(obj == null) {
+            throw new HibernateException("Cannot save null object");
+        }
+        
+        log.debug("Storing hierarchical object "+obj);
+        
+        Session session = getSession();
+        
+        HierarchicalPersistentObject mNewParent = obj.getNewParent();
+        boolean fresh = (obj.getId() == null || "".equals(obj.getId()));
+        
+        if (fresh) {
+            // Object has never been written to database, so save it.
+            // This makes obj into a persistent instance.
+            session.save(obj);
+        }
+ 
+        if(!session.contains(obj)) {
+            
+            // Object has been written to database, but instance passed in
+            // is not a persistent instance, so must be loaded into session.
+            HierarchicalPersistentObject vo =
+                    (HierarchicalPersistentObject)session.load(obj.getClass(),obj.getId());
+            vo.setData(obj);
+            obj = vo;
+        }
+        
+        if (fresh) {
+            // Every fresh cat needs a parent assoc
+            Assoc parentAssoc = obj.createAssoc(
+                    obj, mNewParent, Assoc.PARENT);
+            this.store(parentAssoc);
+        } else if (null != mNewParent) {
+            // New parent must be added to parentAssoc
+            Assoc parentAssoc = obj.getParentAssoc();
+            if(parentAssoc == null)
+                log.error("parent assoc is null");
+            parentAssoc.setAncestor(mNewParent);
+            this.store(parentAssoc);
+        }
+        
+        // Clear out existing grandparent associations
+        Iterator ancestors = obj.getAncestorAssocs().iterator();
+        while (ancestors.hasNext()) {
+            Assoc assoc = (Assoc)ancestors.next();
+            if (assoc.getRelation().equals(Assoc.GRANDPARENT)) {
+                this.remove(assoc);
+            }
+        }
+        
+        // Walk parent assocations, creating new grandparent associations
+        int count = 0;
+        Assoc currentAssoc = obj.getParentAssoc();
+        while (null != currentAssoc.getAncestor()) {
+            if (count > 0) {
+                Assoc assoc = obj.createAssoc(obj,
+                        currentAssoc.getAncestor(),
+                        Assoc.GRANDPARENT);
+                this.store(assoc);
+            }
+            currentAssoc = currentAssoc.getAncestor().getParentAssoc();
+            count++;
+        }
+        
+        Iterator children = obj.getChildAssocs().iterator();
+        while (children.hasNext()) {
+            Assoc assoc = (Assoc) children.next();
+            
+            // resetting parent will cause reset of ancestors links
+            assoc.getObject().setParent(obj);
+            
+            // recursively...
+            this.store(assoc.getObject());
+        }
+        
+        // Clear new parent now that new parent has been saved
+        mNewParent = null;
+    }
+    
+    
+    /**
+     * Store assoc.
+     */
+    protected void store(Assoc assoc) throws HibernateException {
+        
+        if(assoc == null) {
+            throw new HibernateException("Cannot save null object");
+        }
+        
+        getSession().saveOrUpdate(assoc);
+    }
+    
+    
+    /**
+     * Remove hierarchical object.
+     *
+     * NOTE: if the object has proper cascade setting then is all this necessary?
+     */
+    protected void remove(HierarchicalPersistentObject obj) throws RollerException {
+        
+        if(obj == null) {
+            throw new RollerException("Cannot remove null object");
+        }
+        
+        log.debug("Removing hierarchical object "+obj.getId());
+        
+        // loop to remove all descendents and associations
+        List toRemove = new LinkedList();
+        List assocs = obj.getAllDescendentAssocs();
+        for (int i=assocs.size()-1; i>=0; i--) {
+            Assoc assoc = (Assoc)assocs.get(i);
+            HierarchicalPersistentObject hpo = assoc.getObject();
+            
+            // remove my descendent's parent and grandparent associations
+            Iterator ancestors = hpo.getAncestorAssocs().iterator();
+            while (ancestors.hasNext()) {
+                Assoc dassoc = (Assoc)ancestors.next();
+                this.remove(dassoc);
+            }
+            
+            // remove decendent association and descendents
+            //assoc.remove();
+            toRemove.add(hpo);
+        }
+        Iterator removeIterator = toRemove.iterator();
+        while (removeIterator.hasNext()) {
+            PersistentObject po = (PersistentObject) removeIterator.next();
+            getSession().delete(po);
+        }
+        
+        // loop to remove my own parent and grandparent associations
+        Iterator ancestors = obj.getAncestorAssocs().iterator();
+        while (ancestors.hasNext()) {
+            Assoc assoc = (Assoc)ancestors.next();
+            this.remove(assoc);
+        }
+        
+        getSession().delete(obj);
+    }
+    
+    
+    /**
+     * Remove assoc.
+     */
+    protected void remove(Assoc assoc) throws HibernateException {
+        
+        if(assoc == null) {
+            throw new HibernateException("Cannot save null object");
+        }
+        
+        getSession().delete(assoc);
+    }
+    
+}

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePingQueueManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePingQueueManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePingQueueManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePingQueueManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+
+package org.apache.roller.business.hibernate;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+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.pojos.AutoPingData;
+import org.apache.roller.pojos.PingQueueEntryData;
+import java.sql.Timestamp;
+import java.util.List;
+import org.apache.roller.model.PingQueueManager;
+
+
+/**
+ * Hibernate implementation of the PingQueueManager.
+ *
+ * @author <a href="mailto:anil@busybuddha.org">Anil Gangolli</a>
+ */
+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 getQueueEntry(String id) throws RollerException {
+        return (PingQueueEntryData) strategy.load(id, PingQueueEntryData.class);
+    }
+    
+    
+    public void saveQueueEntry(PingQueueEntryData pingQueueEntry) throws RollerException {
+        log.debug("Storing ping queue entry: " + pingQueueEntry);
+        strategy.store(pingQueueEntry);
+    }
+    
+    
+    public void removeQueueEntry(PingQueueEntryData pingQueueEntry) throws RollerException {
+        log.debug("Removing ping queue entry: " + pingQueueEntry);
+        strategy.remove(pingQueueEntry);
+    }
+    
+    
+    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.saveQueueEntry(pingQueueEntry);
+    }
+    
+    
+    public List getAllQueueEntries() throws RollerException {
+        try {
+            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 = ((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) {
+            throw new RollerException("ERROR determining if preexisting queue entry is present.",e);
+        }
+    }
+    
+    
+    public void release() {}
+    
+}

Added: incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePingTargetManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePingTargetManagerImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePingTargetManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/business/hibernate/HibernatePingTargetManagerImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.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.apache.roller.RollerException;
+import org.apache.roller.pojos.PingTargetData;
+import org.apache.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.apache.roller.model.AutoPingManager;
+import org.apache.roller.model.PingTargetManager;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.pojos.AutoPingData;
+import org.apache.roller.pojos.PingQueueEntryData;
+
+
+/**
+ * Hibernate implementation of the PingTargetManager.
+ *
+ * @author <a href="mailto:anil@busybuddha.org">Anil Gangolli</a>
+ */
+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 void removePingTarget(String id) throws RollerException {
+        
+        PingTargetData pingTarget = getPingTarget(id);
+        
+        // remove contents and then target
+        this.removePingTargetContents(pingTarget);
+        strategy.remove(pingTarget);
+    }
+    
+    
+    public void removePingTarget(PingTargetData pingTarget) throws RollerException {
+        this.strategy.remove(pingTarget);
+    }
+    
+    
+    /**
+     * Convenience method which removes any queued pings or auto pings that
+     * reference the given ping target.
+     */
+    private void removePingTargetContents(PingTargetData ping) 
+            throws RollerException {
+        
+        Session session = this.strategy.getSession();
+        
+        // Remove the website's ping queue entries
+        Criteria criteria = session.createCriteria(PingQueueEntryData.class);
+        criteria.add(Expression.eq("pingTarget", ping));
+        List queueEntries = criteria.list();
+        
+        // Remove the website's auto ping configurations
+        AutoPingManager autoPingMgr = RollerFactory.getRoller().getAutopingManager();
+        List autopings = autoPingMgr.getAutoPingsByTarget(ping);
+        Iterator it = autopings.iterator();
+        while(it.hasNext()) {
+            this.strategy.remove((AutoPingData) it.next());
+        }
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.PingTargetManager#removeAllCustomPingTargets()
+     */
+    public void removeAllCustomPingTargets() throws RollerException {
+        
+        try {
+            Session session = strategy.getSession();
+            Criteria criteria = session.createCriteria(PingTargetData.class);
+            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 {
+        
+        // just go through the list and remove each auto ping
+        Iterator targets = customTargets.iterator();
+        while (targets.hasNext()) {
+            this.strategy.remove((PingTargetData) targets.next());
+        }
+    }
+    
+    
+    public void savePingTarget(PingTargetData pingTarget) throws RollerException {
+        strategy.store(pingTarget);
+    }
+    
+    
+    public PingTargetData getPingTarget(String id) throws RollerException {
+        return (PingTargetData) strategy.load(id, PingTargetData.class);
+    }
+
+    
+    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.apache.roller.model.PingTargetManager#getCommonPingTargets()
+     */
+    public List getCommonPingTargets() throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+            Criteria criteria = session.createCriteria(PingTargetData.class);
+            criteria.add(Expression.isNull("website"));
+            criteria.addOrder(Order.asc("name"));
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+        
+    }
+    
+    
+    /**
+     * @see org.apache.roller.model.PingTargetManager#getCustomPingTargets(org.apache.roller.pojos.WebsiteData)
+     */
+    public List getCustomPingTargets(WebsiteData website) throws RollerException {
+        try {
+            Session session = ((HibernatePersistenceStrategy) strategy).getSession();
+            Criteria criteria = session.createCriteria(PingTargetData.class);
+            criteria.add(Expression.eq("website", website));
+            criteria.addOrder(Order.asc("name"));
+            return criteria.list();
+        } catch (HibernateException e) {
+            throw new RollerException(e);
+        }
+    }
+    
+    
+    public void release() {}
+    
+}