You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by ag...@apache.org on 2008/06/28 21:18:57 UTC

svn commit: r672574 [5/16] - in /roller/planet/core/trunk: ./ lib/ lib/buildtime/ lib/jakarta-taglibs-standard-1.1.2/ lib/jakarta-taglibs-standard-1.1.2/lib/ lib/jakarta-taglibs-standard-1.1.2/tld/ lib/openjpa-0.9.7/ lib/rome-0.9/ lib/spring-1.2/ lib/s...

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/business/jpa/JPAPropertiesManagerImpl.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/business/jpa/JPAPropertiesManagerImpl.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/business/jpa/JPAPropertiesManagerImpl.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/business/jpa/JPAPropertiesManagerImpl.java Sat Jun 28 12:18:17 2008
@@ -24,11 +24,11 @@
 import java.util.Map;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.planet.PlanetException;
 import org.apache.roller.planet.business.AbstractManagerImpl;
 import org.apache.roller.planet.business.InitializationException;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.business.PlanetPersistenceException;
 import org.apache.roller.planet.business.PropertiesManager;
-import org.apache.roller.planet.config.PlanetRuntimeConfig;
 import org.apache.roller.planet.config.runtime.ConfigDef;
 import org.apache.roller.planet.config.runtime.DisplayGroup;
 import org.apache.roller.planet.config.runtime.PropertyDef;
@@ -37,7 +37,7 @@
 
 
 /**
- * Hibernate implementation of the PropertiesManager.
+ * JPA implementation of the PropertiesManager.
  */
 @com.google.inject.Singleton
 public class JPAPropertiesManagerImpl  extends AbstractManagerImpl implements PropertiesManager {
@@ -62,7 +62,7 @@
     /**
      * Retrieve a single property by name.
      */
-    public RuntimeConfigProperty getProperty(String name) throws PlanetException {
+    public RuntimeConfigProperty getProperty(String name) throws PlanetPersistenceException {
         return (RuntimeConfigProperty)strategy.load(RuntimeConfigProperty.class, name);
     }
     
@@ -74,7 +74,7 @@
      * uses the property name as the key and the RuntimeConfigProperty object
      * as the value.
      */
-    public Map getProperties() throws PlanetException {
+    public Map getProperties() throws PlanetPersistenceException {
         
         HashMap props = new HashMap();
         List list = strategy.getNamedQuery("RuntimeConfigProperty.getAll").getResultList();
@@ -99,7 +99,7 @@
     /**
      * Save a single property.
      */
-    public void saveProperty(RuntimeConfigProperty property) throws PlanetException {
+    public void saveProperty(RuntimeConfigProperty property) throws PlanetPersistenceException {
         
         strategy.store(property);
     }
@@ -108,7 +108,7 @@
     /**
      * Save all properties.
      */
-    public void saveProperties(Map properties) throws PlanetException {
+    public void saveProperties(Map properties) throws PlanetPersistenceException {
         
         // just go through the list and saveProperties each property
         Iterator props = properties.values().iterator();
@@ -155,7 +155,7 @@
         
         // start by getting our runtimeConfigDefs
         RuntimeConfigDefs runtimeConfigDefs =
-                PlanetRuntimeConfig.getRuntimeConfigDefs();
+                AggregatorFactory.getAggregator().getConfig().getRuntimeConfigDefs();
         
         // can't do initialization without our config defs
         if(runtimeConfigDefs == null)
@@ -195,7 +195,4 @@
         return props;
     }
     
-    
-    public void release() {}
-    
 }

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/business/jpa/JPAUserManagerImpl.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/business/jpa/JPAUserManagerImpl.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/business/jpa/JPAUserManagerImpl.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/business/jpa/JPAUserManagerImpl.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,484 @@
+/*
+ * 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.planet.business.jpa;
+
+import java.sql.Timestamp;
+import javax.persistence.NoResultException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+import javax.persistence.Query;
+import org.apache.roller.planet.business.PlanetPersistenceException;
+import org.apache.roller.planet.business.UserManager;
+import org.apache.roller.planet.pojos.Planet;
+import org.apache.roller.planet.pojos.PlanetPermission;
+import org.apache.roller.planet.pojos.User;
+import org.apache.roller.planet.pojos.UserRole;
+
+
+/**
+ * UserManager backed by a JPA data store.
+ */
+@com.google.inject.Singleton
+public class JPAUserManagerImpl implements UserManager {
+    
+    private static Log log = LogFactory.getLog(JPAUserManagerImpl.class);
+    
+    private final JPAPersistenceStrategy strategy;
+    
+    // cached mapping of userNames -> userIds
+    private Map userNameToIdMap = new Hashtable();
+    
+    
+    @com.google.inject.Inject
+    public JPAUserManagerImpl(JPAPersistenceStrategy strat) {
+        log.debug("Instantiating JPA User Manager");
+        this.strategy = strat;
+    }
+    
+    
+    public void saveUser(User data) throws PlanetPersistenceException {
+        this.strategy.store(data);
+    }
+    
+    public void removeUser(User user) throws PlanetPersistenceException {
+        
+        // make sure that both sides of the relationship are maintained
+        for (Iterator iterator = user.getPermissions().iterator(); iterator.hasNext();) {
+            PlanetPermission perms = (PlanetPermission) iterator.next();
+            
+            // Remove it from this user
+            iterator.remove();
+            
+            // Remove it from corresponding planet
+            Planet p = perms.getPlanet();
+            p.getPermissions().remove(perms);
+            
+            // Remove it from database
+            this.strategy.remove(perms);
+        }
+        
+        this.strategy.remove(user);
+        
+        // remove entry from cache mapping
+        this.userNameToIdMap.remove(user.getUserName());
+    }
+    
+    
+    public void addUser(User newUser) throws PlanetPersistenceException {
+
+        if (newUser == null) {
+            throw new PlanetPersistenceException("cannot add null user");
+        }
+        // TODO BACKEND: we must do this in a better fashion, like getUserCnt()?
+        boolean adminUser = false;
+        List existingUsers = this.getUsers(null, Boolean.TRUE, null, null, 0, 1);
+        if (existingUsers.size() == 0) {
+            // Make first user an admin
+            adminUser = true;
+        }
+
+        if (getUserByUserName(newUser.getUserName()) != null || getUserByUserName(newUser.getUserName().toLowerCase()) != null) {
+            throw new PlanetPersistenceException("error.add.user.userNameInUse");
+        }
+
+        newUser.grantRole("editor");
+        if (adminUser) {
+            newUser.grantRole("admin");
+
+            //if user was disabled (because of activation user account with e-mail property),
+            //enable it for admin user
+            newUser.setEnabled(Boolean.TRUE);
+            newUser.setActivationCode(null);
+        }
+
+        this.strategy.store(newUser);
+    }
+    
+    
+    /**
+     * Creates and stores a pending PermissionsData for user and planet specified.
+     * TODO BACKEND: do we really need this?  can't we just use storePermissions()?
+     */
+    public PlanetPermission inviteUser(Planet planet, User user, short mask) throws PlanetPersistenceException {
+
+        if (planet == null) {
+            throw new PlanetPersistenceException("planet cannot be null");
+        }
+        if (user == null) {
+            throw new PlanetPersistenceException("User cannot be null");
+        }
+        PlanetPermission perms = new PlanetPermission();
+        perms.setPlanet(planet);
+        perms.setUser(user);
+        perms.setPermissionMask(mask);
+        savePermissions(perms);
+
+        return perms;
+    }
+    
+    
+    /**
+     * Remove user permissions from a planet.
+     *
+     * TODO: replace this with a domain model method like Planet.retireUser(user)
+     */
+    public void retireUser(Planet planet, User user) throws PlanetPersistenceException {
+
+        if (planet == null) {
+            throw new PlanetPersistenceException("planet cannot be null");
+        }
+        if (user == null) {
+            throw new PlanetPersistenceException("User cannot be null");
+        }
+        Iterator perms = planet.getPermissions().iterator();
+        PlanetPermission target = null;
+        while (perms.hasNext()) {
+            PlanetPermission pd = (PlanetPermission) perms.next();
+            if (pd.getUser().getId().equals(user.getId())) {
+                target = pd;
+                break;
+            }
+        }
+        if (target == null) {
+            throw new PlanetPersistenceException("User not member of planet");
+        }
+        
+        planet.removePermission(target);
+        this.strategy.remove(target);
+    }
+    
+    
+    public User getUser(String id) throws PlanetPersistenceException {
+        return (User)this.strategy.load(User.class, id);
+    }
+    
+    public User getUserByUserName(String userName) throws PlanetPersistenceException {
+        return getUserByUserName(userName, Boolean.TRUE);
+    }
+    
+    public User getUserByUserName(String userName, Boolean enabled) throws PlanetPersistenceException {
+        
+        if (userName==null )
+            throw new PlanetPersistenceException("userName cannot be null");
+        
+        // check cache first
+        // NOTE: if we ever allow changing usernames then this needs updating
+        if(this.userNameToIdMap.containsKey(userName)) {
+            
+            User user = this.getUser(
+                    (String) this.userNameToIdMap.get(userName));
+            if(user != null) {
+                // only return the user if the enabled status matches
+                if(enabled == null || enabled.equals(user.getEnabled())) {
+                    log.debug("userNameToIdMap CACHE HIT - "+userName);
+                    return user;
+                }
+            } else {
+                // mapping hit with lookup miss?  mapping must be old, remove it
+                this.userNameToIdMap.remove(userName);
+            }
+        }
+        
+        // cache failed, do lookup
+        Query query;
+        Object[] params;
+        if (enabled != null) {
+            query = strategy.getNamedQuery(
+                    "User.getByUserName&Enabled");
+            params = new Object[] {userName, enabled};
+        } else {
+            query = strategy.getNamedQuery(
+                    "User.getByUserName");
+            params = new Object[] {userName};
+        }
+        for (int i=0; i<params.length; i++) {
+            query.setParameter(i+1, params[i]);
+        }
+        User user = null;
+        try {
+            user = (User)query.getSingleResult();
+        } catch (NoResultException e) {
+            user = null;
+        }
+        
+        // add mapping to cache
+        if(user != null) {
+            log.debug("userNameToIdMap CACHE MISS - "+userName);
+            this.userNameToIdMap.put(user.getUserName(), user.getId());
+        }
+        
+        return user;
+    }
+    
+    
+    public List getUsers(Planet planet, Boolean enabled, Date startDate,
+            Date endDate, int offset, int length) throws PlanetPersistenceException {
+        
+        Query query = null;
+        
+        // if we are doing date range then we must have an end date
+        if (startDate != null && endDate == null) {
+            endDate = new Date();
+        }
+
+        List params = new ArrayList();
+        int size = 0;
+        StringBuffer queryString = new StringBuffer();
+        StringBuffer whereClause = new StringBuffer();
+                            
+        if (planet != null) {
+            queryString.append("SELECT u FROM User u JOIN u.permissions p WHERE ");
+            params.add(size++, planet);
+            whereClause.append(" p.planet = ?" + size);   
+        } else {
+            queryString.append("SELECT u FROM User u WHERE ");
+        }         
+
+        if (enabled != null) {
+            if (whereClause.length() > 0) whereClause.append(" AND ");
+            params.add(size++, enabled);
+            whereClause.append("u.enabled = ?" + size);  
+        }
+
+        if (startDate != null) {
+            if (whereClause.length() > 0) whereClause.append(" AND ");
+
+            // if we are doing date range then we must have an end date
+            if(endDate == null) {
+                endDate = new Date();
+            }
+            Timestamp start = new Timestamp(startDate.getTime());
+            Timestamp end = new Timestamp(endDate.getTime());
+            params.add(size++, start);
+            whereClause.append("u.dateCreated > ?" + size);
+            params.add(size++, end);
+            whereClause.append(" AND u.dateCreated < ?" + size);
+        }
+        whereClause.append(" ORDER BY u.dateCreated DESC");
+        query = strategy.getDynamicQuery(queryString.toString() + whereClause.toString());
+
+        if (offset != 0) {
+            query.setFirstResult(offset);
+        }
+        if (length != -1) {
+            query.setMaxResults(length);
+        }
+        for (int i=0; i<params.size(); i++) {
+           query.setParameter(i+1, params.get(i));
+        }
+        
+        return query.getResultList();
+    }
+    
+    
+    public List getUsersStartingWith(String startsWith, Boolean enabled,
+            int offset, int length) throws PlanetPersistenceException {
+        
+        Query query = null;
+        
+        if (enabled != null) {
+            if (startsWith != null) {
+                query = strategy.getNamedQuery(
+                        "User.getByUserNameOrEmailAddressStartsWith&Enabled");
+                query.setParameter(1, enabled);
+                query.setParameter(2, startsWith + '%');
+                query.setParameter(3, startsWith + '%');
+            } else {
+                query = strategy.getNamedQuery(
+                        "User.getByEnabled");
+                query.setParameter(1, enabled);
+            }
+        } else {
+            if (startsWith != null) {
+                query = strategy.getNamedQuery(
+                        "User.getByUserNameOrEmailAddressStartsWith");
+                query.setParameter(1, startsWith +  '%');
+            } else {
+                query = strategy.getNamedQuery("User.getAll");
+            }
+        }
+        if (offset != 0) {
+            query.setFirstResult(offset);
+        }
+        if (length != -1) {
+            query.setMaxResults(length);
+        }
+        
+        return query.getResultList();
+    }
+    
+    
+    public void savePermissions(PlanetPermission perms) throws PlanetPersistenceException {
+        
+        if (getPermissions(perms.getId()) == null) { 
+            // New object, manage both sides of relationship
+            Planet planet = perms.getPlanet();
+            planet.getPermissions().add(perms);
+            
+            User user = perms.getUser();
+            user.getPermissions().add(perms);
+        }
+        
+        this.strategy.store(perms);
+    }
+    
+    public void removePermissions(PlanetPermission perms) throws PlanetPersistenceException {
+        
+        this.strategy.remove(perms);
+        
+        // manage both sides of relationship
+        Planet planet = perms.getPlanet();
+        planet.getPermissions().remove(perms);
+        
+        User user = perms.getUser();
+        user.getPermissions().remove(perms);
+    }
+    
+    
+    public PlanetPermission getPermissions(String inviteId) throws PlanetPersistenceException {
+        return (PlanetPermission) this.strategy.load(PlanetPermission.class, inviteId);
+    }
+    
+    
+    /**
+     * Return permissions for specified user in planet
+     */
+    public PlanetPermission getPermissions(Planet planet, User user) throws PlanetPersistenceException {
+        
+        Query q = strategy.getNamedQuery(
+                "PlanetPermission.getByPlanetAndUser");
+        q.setParameter(1, planet);
+        q.setParameter(2, user);
+        try {
+            return (PlanetPermission) q.getSingleResult();
+        } catch (NoResultException e) {
+            return null;
+        }
+    }
+    
+    
+    /**
+     * Get all permissions of a planet (pendings not including)
+     */
+    public List getAllPermissions(Planet planet) throws PlanetPersistenceException {
+        Query q = strategy.getNamedQuery(
+                "PlanetPermission.getByPlanetAndPending");
+        q.setParameter(1, planet);
+        q.setParameter(2, Boolean.FALSE);
+        return q.getResultList();
+    }
+    
+    
+    /**
+     * Get all permissions of a user.
+     */
+    public List getAllPermissions(User user) throws PlanetPersistenceException {
+        Query q = strategy.getNamedQuery(
+                "PlanetPermission.getByUserAndPending");
+        q.setParameter(1, user);
+        q.setParameter(2, Boolean.FALSE);
+        return q.getResultList();        
+    }
+    
+    
+    /**
+     * Get pending permissions for user
+     */
+    public List getPendingPermissions(User user) throws PlanetPersistenceException {
+        Query q = strategy.getNamedQuery(
+                "PlanetPermission.getByUserAndPending");
+        q.setParameter(1, user);
+        q.setParameter(2, Boolean.TRUE);
+        return q.getResultList();
+    }
+    
+    
+    /**
+     * Get pending permissions for planet
+     */
+    public List getPendingPermissions(Planet planet) throws PlanetPersistenceException {
+        Query q = strategy.getNamedQuery(
+                "PlanetPermission.getByPlanetAndPending");
+        q.setParameter(1, planet);
+        q.setParameter(2, Boolean.TRUE);
+        return q.getResultList();
+    }
+    
+    
+    public boolean hasPermissions(User user, Planet planet, short mask) {
+        
+        // look for user in planet's permissions
+        PlanetPermission userPerms = null;
+        Iterator iter = planet.getPermissions().iterator();
+        while (iter.hasNext()) {
+            PlanetPermission perms = (PlanetPermission) iter.next();
+            if (perms.getUser().getId().equals(user.getId())) {
+                userPerms = perms;
+                break;
+            }
+        }
+        // if we found one, does it satisfy the mask?
+        if (userPerms != null && !userPerms.isPending()) {
+            if (userPerms != null && (userPerms.getPermissionMask() & mask) == mask) {
+                return true;
+            }
+        }
+        // otherwise, check to see if user is a global admin
+        if (user != null && user.hasRole("admin")) return true;
+        return false;
+    }
+    
+    
+    public void revokeRole(String roleName, User user) throws PlanetPersistenceException {
+        Collection roles = user.getRoles();
+        Iterator iter = roles.iterator();
+        while (iter.hasNext()) {
+            UserRole role = (UserRole) iter.next();
+            if (role.getRole().equals(roleName)) {
+                this.strategy.remove(role);
+                iter.remove();
+            }
+        }
+    }
+    
+    
+    /**
+     * Get count of users, enabled only
+     */
+    public long getUserCount() throws PlanetPersistenceException {
+        long ret = 0;
+        Query q = strategy.getNamedQuery("User.getCountEnabledDistinct");
+        q.setParameter(1, Boolean.TRUE);
+        List results = q.getResultList();
+        ret = ((Long) results.get(0)).longValue();
+
+        return ret;
+    }
+    
+    
+    public void release() {}
+    
+}

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/business/startup/PlanetStartup.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/business/startup/PlanetStartup.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/business/startup/PlanetStartup.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/business/startup/PlanetStartup.java Sat Jun 28 12:18:17 2008
@@ -21,6 +21,8 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.planet.business.DatabaseProvider;
+import org.apache.roller.planet.business.MailProvider;
+import org.apache.roller.planet.config.PlanetConfig;
 
 
 /**
@@ -35,7 +37,9 @@
     private static DatabaseProvider dbProvider = null;
     private static StartupException dbProviderException = null;
     
-    
+    private static MailProvider mailProvider = null;
+    private static StartupException mailProviderException = null;
+        
     // non-instantiable
     private PlanetStartup() {}
     
@@ -74,20 +78,51 @@
 
     
     /**
+     * Get a reference to the currently configured MailProvider.
+     *
+     * @return MailProvider The configured mail provider.
+     * @throws IllegalStateException If the app has not been properly prepared yet.
+     */
+    public static MailProvider getMailProvider() {
+        if (mailProvider == null) {
+            throw new IllegalStateException("Roller Planet has not been prepared yet");
+        }
+        return mailProvider;
+    }
+    
+    /**
+     * Get a reference to the exception thrown while instantiating the 
+     * mail provider, if any.
+     *
+     * @return StartupException Exception from mail provider, or null if no exception thrown.
+     */
+    public static StartupException getMailProviderException() {
+        return mailProviderException;
+    }
+    
+    
+    /**
      * Run the Roller Weblogger preparation sequence.
      *
      * This sequence is what prepares the core services of the application such
      * as setting up the database and mail providers.
      */
-    public static void prepare() throws StartupException {
+    public static void prepare(PlanetConfig config) throws StartupException {
         
         // setup database provider
         try {
-            dbProvider = new DatabaseProvider();
+            dbProvider = new DatabaseProvider(config);
         } catch(StartupException ex) { 
             dbProviderException = ex;
             throw ex;
-        }   
+        }
+        
+        // setup mail provider
+        try {
+            mailProvider = new MailProvider(config);
+        } catch(StartupException ex) { 
+            mailProviderException = ex;
+        }
         
         prepared = true;
     }

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/business/updater/SingleThreadedFeedUpdater.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/business/updater/SingleThreadedFeedUpdater.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/business/updater/SingleThreadedFeedUpdater.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/business/updater/SingleThreadedFeedUpdater.java Sat Jun 28 12:18:17 2008
@@ -24,11 +24,11 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.planet.PlanetException;
-import org.apache.roller.planet.business.PlanetFactory;
+import org.apache.roller.planet.business.AggregatorFactory;
 import org.apache.roller.planet.business.PlanetManager;
 import org.apache.roller.planet.business.fetcher.FeedFetcher;
 import org.apache.roller.planet.business.fetcher.FetcherException;
-import org.apache.roller.planet.config.PlanetRuntimeConfig;
+import org.apache.roller.planet.config.PlanetConfig;
 import org.apache.roller.planet.pojos.PlanetGroup;
 import org.apache.roller.planet.pojos.Subscription;
 import org.apache.roller.planet.pojos.SubscriptionEntry;
@@ -41,9 +41,11 @@
     
     private static Log log = LogFactory.getLog(SingleThreadedFeedUpdater.class);
     
+    private final PlanetConfig config;
     
-    public SingleThreadedFeedUpdater() {
-        // no-op
+    
+    public SingleThreadedFeedUpdater(PlanetConfig config) {
+        this.config = config;
     }
     
     
@@ -56,6 +58,11 @@
             throw new IllegalArgumentException("cannot update null subscription");
         }
         
+        if(sub.getErrorCount() >= config.getIntProperty("feedUpdater.errorCount.threshold")) {
+            log.debug("Skipping error feed: "+sub.getFeedURL());
+            return;
+        }
+        
         updateProxySettings();
         
         log.debug("updating feed: "+sub.getFeedURL());
@@ -65,9 +72,21 @@
         Subscription updatedSub;
         try {
             // fetch the latest version of the subscription
-            FeedFetcher fetcher = PlanetFactory.getPlanet().getFeedFetcher();
+            FeedFetcher fetcher = AggregatorFactory.getAggregator().getFeedFetcher();
             updatedSub = fetcher.fetchSubscription(sub.getFeedURL(), sub.getLastUpdated());
         } catch (FetcherException ex) {
+            try {
+                // mark broken feeds
+                sub.setErrorCount(sub.getErrorCount() + 1);
+                sub.setErrorMessage(ex.getRootCauseMessage());
+                PlanetManager pmgr = AggregatorFactory.getAggregator().getPlanetManager();
+                pmgr.saveSubscription(sub);
+                AggregatorFactory.getAggregator().flush();
+            } catch(Exception e) {
+                log.error("Error saving subscription", e);
+            }
+            
+            // we still throw an exception indicating the update failed
             throw new UpdaterException("Error fetching updated subscription", ex);
         }
         
@@ -87,12 +106,14 @@
         sub.setTitle(updatedSub.getTitle());
         sub.setAuthor(updatedSub.getAuthor());
         sub.setLastUpdated(updatedSub.getLastUpdated());
+        sub.setErrorCount(0);
+        sub.setErrorMessage(null);
         
         // update subscription entries
         int entries = 0;
         Set<SubscriptionEntry> newEntries = updatedSub.getEntries();
         if(newEntries.size() > 0) try {
-            PlanetManager pmgr = PlanetFactory.getPlanet().getPlanetManager();
+            PlanetManager pmgr = AggregatorFactory.getAggregator().getPlanetManager();
             
             // clear out old entries
             pmgr.deleteEntries(sub);
@@ -103,7 +124,7 @@
             
             // save and flush
             pmgr.saveSubscription(sub);
-            PlanetFactory.getPlanet().flush();
+            AggregatorFactory.getAggregator().flush();
             
         } catch(PlanetException ex) {
             throw new UpdaterException("Error persisting updated subscription", ex);
@@ -129,7 +150,7 @@
         
         try {
             // update all subscriptions in the system
-            PlanetManager pmgr = PlanetFactory.getPlanet().getPlanetManager();
+            PlanetManager pmgr = AggregatorFactory.getAggregator().getPlanetManager();
             updateSubscriptions(pmgr.getSubscriptions());
         } catch (PlanetException ex) {
             throw new UpdaterException("Error getting subscriptions list", ex);
@@ -167,7 +188,7 @@
     // convenience method which handles updating any arbitrary collection of subs
     private void updateSubscriptions(Collection<Subscription> subscriptions) {
         
-        PlanetManager pmgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager pmgr = AggregatorFactory.getAggregator().getPlanetManager();
         
         Iterator subs = subscriptions.iterator();
         while (subs.hasNext()) {
@@ -204,8 +225,8 @@
     
     // upate proxy settings for jvm based on planet configuration
     private void updateProxySettings() {
-        String proxyHost = PlanetRuntimeConfig.getProperty("site.proxyhost");
-        int proxyPort = PlanetRuntimeConfig.getIntProperty("site.proxyport");
+        String proxyHost = config.getProperty("site.proxyhost");
+        int proxyPort = config.getIntProperty("site.proxyport");
         if (proxyHost != null && proxyPort > 0) {
             System.setProperty("proxySet", "true");
             System.setProperty("http.proxyHost", proxyHost);

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/config/PlanetConfig.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/config/PlanetConfig.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/config/PlanetConfig.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/config/PlanetConfig.java Sat Jun 28 12:18:17 2008
@@ -21,68 +21,83 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Properties;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.util.PropertyExpander;
+import org.apache.roller.planet.business.PropertiesManager;
+import org.apache.roller.planet.config.runtime.RuntimeConfigDefs;
+import org.apache.roller.planet.config.runtime.RuntimeConfigDefsParser;
+import org.apache.roller.planet.pojos.RuntimeConfigProperty;
 
 
 /**
- * This is the single entry point for accessing configuration properties in Roller.
+ * The Planet configuration.  Manages access to all general purpose Planet
+ * configuration information.
  */
 public class PlanetConfig {
-    
-    private static String default_config = "/org/apache/roller/planet/config/planet.properties";
-    private static String custom_config = "/planet-custom.properties";
-    private static String custom_jvm_param = "planet.custom.config";
-    private static File custom_config_file = null;
-
-    private static Properties mConfig;
 
     private static Log log = LogFactory.getLog(PlanetConfig.class);
     
+    public static final String DEFAULT = "/org/apache/roller/planet/config/planet-default.properties";
+    public static final String CUSTOM = "/planet.properties";
+    public static final String JVM_PARAM = "planet.custom.config";
+    
+    public static final String RUNTIME_CONFIG = "/org/apache/roller/planet/config/planetRuntimeConfigDefs.xml";
+    
+    private final Properties properties;
+    private final RuntimeConfigDefs runtimeConfigDefs;
+    
+    // reference to PropertiesManager to get runtime props from
+    private PropertiesManager propertiesManager = null;
+    
+    
+    public PlanetConfig(Properties staticProps, RuntimeConfigDefs defs) {
+        this.properties = staticProps;
+        this.runtimeConfigDefs = defs;
+    }
+
     
-    /*
-     * Static block run once at class loading
-     *
-     * We load the default properties and any custom properties we find
+    /**
+     * A convenience method which knows how to load up a config from a series
+     * of 3 potential locations.
      */
-    static {
-        mConfig = new Properties();
+    public static PlanetConfig getConfig(String defaultPath, 
+            String customPath, String customParam) {
 
-        try {
-            // we'll need this to get at our properties files in the classpath
-            Class config_class = Class.forName(
-                    "org.apache.roller.planet.config.PlanetConfig");
+        Properties props = new Properties();
 
+        try {
             // first, lets load our default properties
-            InputStream is = config_class.getResourceAsStream(default_config);
-            mConfig.load(is);
+            InputStream is = PlanetConfig.class.getResourceAsStream(defaultPath);
+            props.load(is);
             log.info("successfully loaded default properties.");
 
             // now, see if we can find our custom config
-            is = config_class.getResourceAsStream(custom_config);
-            if(is != null) {
-                mConfig.load(is);
+            is = PlanetConfig.class.getResourceAsStream(customPath);
+            if (is != null) {
+                props.load(is);
                 log.info("successfully loaded custom properties file from classpath");
             } else {
                 log.info("no custom properties file found in classpath");
             }
 
             // finally, check for an external config file
-            String env_file = System.getProperty(custom_jvm_param);
-            if(env_file != null && env_file.length() > 0) {
-                custom_config_file = new File(env_file);
+            String env_file = System.getProperty(customParam);
+            if (env_file != null && env_file.length() > 0) {
+                File custom_config_file = new File(env_file);
 
                 // make sure the file exists, then try and load it
-                if(custom_config_file != null && custom_config_file.exists()) {
+                if (custom_config_file != null && custom_config_file.exists()) {
                     is = new FileInputStream(custom_config_file);
-                    mConfig.load(is);
-                    log.info("successfully loaded custom properties from "+
+                    props.load(is);
+                    log.info("successfully loaded custom properties from " +
                             custom_config_file.getAbsolutePath());
                 } else {
-                    log.warn("failed to load custom properties from "+
+                    log.warn("failed to load custom properties from " +
                             custom_config_file.getAbsolutePath());
                 }
 
@@ -90,121 +105,174 @@
                 log.info("no custom properties file specified via jvm option");
             }
 
-            // Now expand system properties for properties in the config.expandedProperties list,
-            // replacing them by their expanded values.
-            String expandedPropertiesDef = (String) mConfig.get("config.expandedProperties");
-            if (expandedPropertiesDef != null) {
-                String[] expandedProperties = expandedPropertiesDef.split(",");
-                for (int i = 0; i < expandedProperties.length; i++) {
-                    String propName = expandedProperties[i].trim();
-                    String initialValue = (String) mConfig.get(propName);
-                    if (initialValue != null) {
-                        String expandedValue = PropertyExpander.expandSystemProperties(initialValue);
-                        mConfig.put(propName,expandedValue);
-                        if (log.isDebugEnabled()) {
-                            log.info("Expanded value of " + propName + " from '" +
-                                initialValue + "' to '" + expandedValue + "'");
-                        }
-                    }
-                }
-            }
-
             // some debugging for those that want it
-            if(log.isDebugEnabled()) {
+            if (log.isDebugEnabled()) {
                 log.debug("PlanetConfig looks like this ...");
 
                 String key = null;
-                Enumeration keys = mConfig.keys();
-                while(keys.hasMoreElements()) {
+                Enumeration keys = props.keys();
+                while (keys.hasMoreElements()) {
                     key = (String) keys.nextElement();
-                    log.debug(key+"="+mConfig.getProperty(key));
+                    log.debug(key + "=" + props.getProperty(key));
                 }
             }
 
-        } catch (Exception e) {
-            e.printStackTrace();
+        } catch (Exception ex) {
+            log.fatal("Fatal error constructing PlanetConfig", ex);
         }
+        
+        // load up runtime config defs
+        RuntimeConfigDefs runtimeConfigDefs = null;
+        try {
+            InputStream is = PlanetConfig.class.getResourceAsStream(RUNTIME_CONFIG);
 
-    }
-
-
-    // no, you may not instantiate this class :p
-    private PlanetConfig() {}
-
+            RuntimeConfigDefsParser parser = new RuntimeConfigDefsParser();
+            runtimeConfigDefs = parser.unmarshall(is);
 
+        } catch (Exception ex) {
+            // error while parsing :(
+            log.error("Error parsing runtime config defs", ex);
+        }
+        
+        return new PlanetConfig(props, runtimeConfigDefs);
+    }
+    
+    
     /**
-     * Retrieve a property value
+     * Retrieve a property value.  This method looks first at our static
+     * config properties, then to our runtime properties.  If no value is found
+     * then null is returned.
+     * 
      * @param     key Name of the property
      * @return    String Value of property requested, null if not found
      */
-    public static String getProperty(String key) {
-        log.debug("Fetching property ["+key+"="+mConfig.getProperty(key)+"]");
-        return mConfig.getProperty(key);
+    public String getProperty(String key) {
+        
+        String value = properties.getProperty(key);
+        if(value == null && propertiesManager != null) {
+            // not found in static config, try runtime config
+            log.debug(key+" prop not found in static config, trying runtime config");
+            try {
+                RuntimeConfigProperty prop = propertiesManager.getProperty(key);
+                if(prop != null) {
+                    value = prop.getValue();
+                }
+            } catch (Exception ex) {
+                log.warn("Trouble accessing property: " + key, ex);
+            }
+        }
+        
+        if(value == null) {
+            log.warn("Failed to lookup property ["+key+"]");
+        } else {
+            log.debug("Fetched property [" + key + "=" + value + "]");
+        }
+        
+        return value;
     }
     
+    
     /**
      * Retrieve a property value
+     * 
      * @param     key Name of the property
      * @param     defaultValue Default value of property if not found     
      * @return    String Value of property requested or defaultValue
      */
-    public static String getProperty(String key, String defaultValue) {
-        log.debug("Fetching property ["+key+"="+mConfig.getProperty(key)+",defaultValue="+defaultValue+"]");
-        String value = mConfig.getProperty(key);
-        if(value == null)
-          return defaultValue;
+    public String getProperty(String key, String defaultValue) {
+        
+        String value = getProperty(key);
+        if (value == null) {
+            return defaultValue;
+        }
         
         return value;
     }
 
+    
     /**
      * Retrieve a property as a boolean ... defaults to false if not present.
      */
-    public static boolean getBooleanProperty(String name) {
-        return getBooleanProperty(name,false);
+    public boolean getBooleanProperty(String name) {
+        return getBooleanProperty(name, false);
     }
 
+    
     /**
      * Retrieve a property as a boolean ... with specified default if not present.
      */
-    public static boolean getBooleanProperty(String name, boolean defaultValue) {
+    public boolean getBooleanProperty(String name, boolean defaultValue) {
         // get the value first, then convert
-        String value = PlanetConfig.getProperty(name);
+        String value = getProperty(name);
 
-        if(value == null)
+        if (value == null) {
             return defaultValue;
+        }
 
         return (new Boolean(value)).booleanValue();
     }
 
+    
     /**
      * Retrieve a property as an int ... defaults to 0 if not present.
      */
-    public static int getIntProperty(String name) {
+    public int getIntProperty(String name) {
         return getIntProperty(name, 0);
     }
 
+    
     /**
      * Retrieve a property as a int ... with specified default if not present.
      */
-    public static int getIntProperty(String name, int defaultValue) {
+    public int getIntProperty(String name, int defaultValue) {
         // get the value first, then convert
-        String value = PlanetConfig.getProperty(name);
+        String value = getProperty(name);
 
-        if (value == null)
+        if (value == null) {
             return defaultValue;
+        }
 
         return (new Integer(value)).intValue();
     }
 
+    
+    /**
+     * Retrieve a property as a list of strings.
+     * 
+     * @param name The name of the property to look up.
+     * @return The list containing the property values, or an empty list if no value found.
+     */
+    public List<String> getListProperty(String name) {
+        // get the value first, then convert
+        String value = getProperty(name);
+
+        if (value == null)
+            return Collections.EMPTY_LIST;
+        
+        // always separate on commas (,) and trim spaces
+        String[] items = value.split(",");
+        if(items != null) {
+            ArrayList propsList = new ArrayList(items.length);
+            for(int i=0; i < items.length; i++) {
+                propsList.add(i, items[i].trim());
+            }
+            
+            return propsList;
+        } else {
+            return Collections.EMPTY_LIST;
+        }
+    }
+    
+    
     /**
      * Retrieve all property keys
      * @return Enumeration A list of all keys
      **/
-    public static Enumeration keys() {
-        return mConfig.keys();
+    public Enumeration keys() {
+        return properties.keys();
     }
-      
+
+    
     /**
      * Set the "context.realpath" property at runtime.
      * <p />
@@ -213,7 +281,27 @@
      * <p />
      * This property is *not* persisted in any way.
      */
-    public static void setPlanetCachePath(String path) {
-        mConfig.setProperty("planet.aggregator.cache.dir", path);
+    public void setPlanetCachePath(String path) {
+        properties.setProperty("planet.aggregator.cache.dir", path);
     }
+    
+    
+    /**
+     * Get a reference to the set of runtime config definitions.
+     * 
+     * @return RuntimeConfigDefs The runtime config defs.
+     */
+    public RuntimeConfigDefs getRuntimeConfigDefs() {
+        return runtimeConfigDefs;
+    }
+
+    
+    public PropertiesManager getPropertiesManager() {
+        return propertiesManager;
+    }
+
+    public void setPropertiesManager(PropertiesManager propertiesManager) {
+        this.propertiesManager = propertiesManager;
+    }
+    
 }

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/config/planet-default.properties
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/config/planet-default.properties?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/config/planet-default.properties (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/config/planet-default.properties Sat Jun 28 12:18:17 2008
@@ -0,0 +1,214 @@
+# 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.
+
+# planet.properties
+#
+# This file is for meant for Roller deployment properties
+# Any properties that don't change at runtime are defined here
+#
+# You can override the values in this file in a couple ways ..
+#   1. define a planet-custom.properties file and place it somewhere
+#       at the root of one of your classpath locations.
+#       for example:
+#           $TOMCAT_HOME/common/classes
+#           $PLANET_LOCATION/WEB-INF/classes
+#
+#   2. specify a custom properties file via jvm option
+#       example:
+#           planet.custom.config=/path/to/properties/file
+#
+#   **NOTE: if you run multiple instances of roller on the same server
+#           then you should beware of the fact that the override options above
+#           may affect *all* of you running instances.  if you want to do
+#           custom overrides for each instance then you must do it by
+#           placing a planet-custom.properties file at WEB-INF/classes/ in
+#           each of you planet installations.
+#
+# properties in this file are accessed like this ...
+#    PlanetConfig.getProperty("propname");
+
+
+#-----------------------------------------------------------------------------
+# Required configuration settings
+#-----------------------------------------------------------------------------
+
+cache.dir=/var/planet/cache
+output.dir=/usr/local/planet/webapp
+template.dir=/usr/local/planet/webapp/WEB-INF/templates
+
+# Specify database configuration type of 'jndi' or 'jdbc'
+database.configurationType=jndi
+
+# For database configuration type 'jndi',this will be used
+database.jndi.name=jdbc/rollerdb
+
+# For database configuration type of 'jdbc', you MUST override these
+database.jdbc.driverClass=
+database.jdbc.connectionURL=
+database.jdbc.username=
+database.jdbc.password=
+
+
+#-----------------------------------------------------------------------------
+# Pluggable backend
+#-----------------------------------------------------------------------------
+
+# Guice Provider
+planet.provider.class=org.apache.roller.planet.business.GuiceAggregatorProvider
+
+# default persistence module is JPA
+guice.backend.module=org.apache.roller.planet.business.jpa.GuiceJPAAggregatorModule
+
+
+#-----------------------------------------------------------------------------
+# User Management & Authentication Settings
+#-----------------------------------------------------------------------------
+
+# Is the application managing it's own users
+userManagement.external.enabled=false
+
+# Is the application managing it's own authentication?
+authentication.external.enabled=false
+
+# What characters are allowed in usernames and planet/group handles
+username.allowedChars=A-Za-z0-9
+
+
+#-----------------------------------------------------------------------------
+# Feed Fetching & Updating Settings
+#-----------------------------------------------------------------------------
+
+# If a feed fails to be fetched this # of times in a row then we stop trying.
+feedUpdater.errorCount.threshold=15
+
+
+#-----------------------------------------------------------------------------
+# Cache configuratation
+#-----------------------------------------------------------------------------
+
+# Remember... times are in seconds
+# Default settings suitable for 100 user system
+
+# Cache properties all follow the given format ...
+#     cache.<cache_id>.<prop>=<value>
+# we then pass all <prop>=<value> pairs into the cache manager when the cache
+# is being constructed.  this makes it easy to add cache properties that can
+# be used by the specified CacheFactory you are using.
+#
+# NOTE: it is expected that property validation happens in the CacheFactory
+
+# The default cache implementation we want to use
+cache.defaultFactory=org.apache.roller.planet.util.cache.ExpiringLRUCacheFactoryImpl
+cache.customHandlers=
+
+# Weblog page cache (html page content)
+cache.page.enabled=true
+cache.page.size=400
+cache.page.timeout=900
+
+# Feed cache (xml feeds like rss, atom, etc)
+cache.feed.enabled=true
+cache.feed.size=200
+cache.feed.timeout=900
+
+
+#-----------------------------------------------------------------------------
+# Security settings
+#-----------------------------------------------------------------------------
+
+# Enables HTTPS for login page only
+securelogin.enabled=false
+
+# Enable scheme enforcement?
+# Scheme enforcement ensures that specific URLs are viewed only via HTTPS
+schemeenforcement.enabled=false
+
+# URL patterns that require HTTPS
+schemeenforcement.https.urls=/roller_j_security_check,\
+/planet-ui/login-redirect.jsp,\
+/planet-ui/login.rol,\
+/planet-ui/register.rol,/planet-ui/register!save.rol,\
+/planet-ui/profile.rol,/planet-ui/profile!save.rol,\
+/planet-ui/admin/userAdmin.rol,\
+/planet-ui/admin/createUser.rol,/planet-ui/admin/createUser!save.rol,\
+/planet-ui/editor/userdata
+
+# Password security settings
+passwds.encryption.enabled=true
+passwds.encryption.algorithm=SHA
+
+
+#-----------------------------------------------------------------------------
+# Rendering system
+#-----------------------------------------------------------------------------
+
+# The set of default Roller renderer factories.
+rendering.rollerRendererFactories=\
+org.apache.roller.planet.ui.rendering.velocity.VelocityRendererFactory
+
+# The set of user defined renderer factories.  These are prepended to the list above.
+rendering.userRendererFactories=
+
+# The set of default Roller request mappers
+rendering.rollerRequestMappers=\
+org.apache.roller.planet.ui.rendering.MultiPlanetRequestMapper
+
+# The set of user defined request mappers.  These are prepended to the list above.
+rendering.userRequestMappers=
+
+# Url path elements which can NEVER be considered a weblog url
+# each represents a url at the application root, i.e. /<elem>/*
+rendering.multiPlanetMapper.rollerProtectedUrls=\
+planet-ui,index.jsp,favicon.ico,robots.txt
+
+# Set of user defined protected urls.  These are added to the set above.
+rendering.multiPlanetMapper.userProtectedUrls=
+
+rendering.homepageModels=\
+org.apache.roller.planet.ui.rendering.model.RequestContextModel,\
+org.apache.roller.planet.ui.rendering.model.SiteModel,\
+org.apache.roller.planet.ui.rendering.model.SiteURLModel,\
+org.apache.roller.planet.ui.rendering.model.UtilitiesModel
+
+# Set of models to be made available for planet/group page rendering
+rendering.pageModels=\
+org.apache.roller.planet.ui.rendering.model.RequestContextModel,\
+org.apache.roller.planet.ui.rendering.model.PageModel,\
+org.apache.roller.planet.ui.rendering.model.PlanetURLModel,\
+org.apache.roller.planet.ui.rendering.model.UtilitiesModel
+
+# Set of models to be made available for planet/group feed rendering
+rendering.feedModels=\
+org.apache.roller.planet.ui.rendering.model.RequestContextModel,\
+org.apache.roller.planet.ui.rendering.model.FeedModel,\
+org.apache.roller.planet.ui.rendering.model.PlanetURLModel,\
+org.apache.roller.planet.ui.rendering.model.UtilitiesModel
+
+# Set of models to be made available for planet/group opml rendering
+rendering.opmlModels=\
+org.apache.roller.planet.ui.rendering.model.RequestContextModel,\
+org.apache.roller.planet.ui.rendering.model.PlanetGroupModel,\
+org.apache.roller.planet.ui.rendering.model.PlanetURLModel,\
+org.apache.roller.planet.ui.rendering.model.UtilitiesModel
+
+
+#-----------------------------------------------------------------------------
+# Other settings
+#-----------------------------------------------------------------------------
+
+# Number of Technorati queries allowed per day
+planet.aggregator.technorati.limit=500
+

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/config/planetRuntimeConfigDefs.xml
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/config/planetRuntimeConfigDefs.xml?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/config/planetRuntimeConfigDefs.xml (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/config/planetRuntimeConfigDefs.xml Sat Jun 28 12:18:17 2008
@@ -46,39 +46,64 @@
  <config-def name="global-properties">
 
    <!-- Site Settings Group -->
-   <display-group name="siteSettings" key="ConfigForm.siteSettings" >
+   <display-group name="siteSettings" key="GlobalConfig.siteSettings" >
        
-       <property-def  name="site.name"  key="ConfigForm.title">
+       <property-def  name="site.name"  key="GlobalConfig.name">
            <type>string</type>
            <default-value>Roller Planet</default-value>
        </property-def>
-       <property-def  name="site.description"  key="ConfigForm.description">
+       <property-def  name="site.description"  key="GlobalConfig.description">
            <type>string</type>
            <default-value>A default install of the Roller Planet open source aggregation server</default-value>
        </property-def>
-       <property-def  name="site.adminname"  key="ConfigForm.adminName">
+       <property-def  name="site.adminname"  key="GlobalConfig.adminName">
            <type>string</type>
            <default-value></default-value>
        </property-def>
-       <property-def  name="site.adminemail"  key="ConfigForm.adminEmail">
+       <property-def  name="site.adminemail"  key="GlobalConfig.adminEmail">
            <type>string</type>
            <default-value></default-value>
        </property-def>
-       <property-def  name="site.absoluteurl"  key="ConfigForm.absoluteUrl">
+       <property-def  name="site.absoluteurl"  key="GlobalConfig.absoluteUrl">
            <type>string</type>
            <default-value></default-value>
        </property-def>
-       <property-def  name="site.proxyhost"  key="ConfigForm.proxyHost">
+       <property-def  name="site.proxyhost"  key="GlobalConfig.proxyHost">
            <type>string</type>
            <default-value></default-value>
        </property-def>
-       <property-def  name="site.proxyport"  key="ConfigForm.proxyPort">
+       <property-def  name="site.proxyport"  key="GlobalConfig.proxyPort">
            <type>string</type>
            <default-value>0</default-value>
        </property-def>
        
    </display-group >
    
+   
+   <!-- Registration and User Management Settings -->
+   <display-group name="userSettings" key="GlobalConfig.userSettings" >
+   
+      <property-def  name="users.registration.enabled"  key="GlobalConfig.registrationEnabled">
+         <type>boolean</type>
+         <default-value>true</default-value>
+      </property-def>
+      <!--
+      <property-def  name="user.account.activation.enabled"  key="GlobalConfig.accountActivation">
+         <type>boolean</type>
+         <default-value>false</default-value>
+      </property-def>
+      <property-def  name="user.account.activation.mail.from"  key="GlobalConfig.accountActivationFromAddress">
+         <type>string</type>
+         <default-value></default-value>
+      </property-def>
+      -->
+      <property-def  name="users.registration.url"  key="GlobalConfig.registrationUrl">
+          <type>string</type>
+          <default-value></default-value>
+      </property-def>
+
+   </display-group >
+   
  </config-def>
  
 </runtime-configs>

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Planet.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Planet.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Planet.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Planet.java Sat Jun 28 12:18:17 2008
@@ -18,15 +18,15 @@
 
 package org.apache.roller.planet.pojos;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
-import org.apache.roller.util.UUIDGenerator;
+import org.apache.roller.planet.util.UUIDGenerator;
 import java.util.TreeSet;
 
 
 /**
  * A Roller "Planet".
- * 
- * @hibernate.class lazy="true" table="rag_planet"
  */
 public class Planet implements Comparable {
     
@@ -34,7 +34,8 @@
     private String handle = null;
     private String title = null;
     private String description = null;
-    private Set groups = new TreeSet();
+    private Set<PlanetGroup> groups = new TreeSet<PlanetGroup>();
+    private List<PlanetPermission> permissions = new ArrayList<PlanetPermission>();
     
     
     public Planet() {
@@ -58,7 +59,7 @@
     
     
     /**
-     * @hibernate.id column="id" generator-class="assigned"
+     * Id.
      */
     public String getId() {
         return id;
@@ -70,7 +71,7 @@
     
     
     /**
-     * @hibernate.property column="handle" non-null="true" unique="true"
+     * Handle.
      */
     public String getHandle() {
         return handle;
@@ -82,7 +83,7 @@
     
        
     /**
-     * @hibernate.property column="title" non-null="true" unique="false"
+     * Title.
      */
     public String getTitle() {
         return title;
@@ -94,7 +95,7 @@
     
     
     /**
-     * @hibernate.property column="description" non-null="false" unique="false"
+     * Description.
      */
     public String getDescription() {
         return description;
@@ -106,16 +107,34 @@
 
     
     /** 
-     * @hibernate.set lazy="true" inverse="true" cascade="all" sort="natural"
-     * @hibernate.collection-key column="planet_id"
-     * @hibernate.collection-one-to-many class="org.apache.roller.planet.pojos.PlanetGroup"
+     * Get groups list.
      */
     public Set getGroups() {
         return groups;
     }
 
-    public void setGroups(Set groups) {
+    public void setGroups(Set<PlanetGroup> groups) {
         this.groups = groups;
     }
     
+    
+    /**
+     * Get permissions list.
+     */
+    public List getPermissions() {
+        return permissions;
+    }
+    
+    public void setPermissions(List<PlanetPermission> perms) {
+        permissions = perms;
+    }
+    
+    
+    /**
+     * Remove permission from collection.
+     */
+    public void removePermission(PlanetPermission perms) {
+        permissions.remove(perms);
+    }
+    
 }

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Planet.orm.xml
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Planet.orm.xml?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Planet.orm.xml (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Planet.orm.xml Sat Jun 28 12:18:17 2008
@@ -13,11 +13,14 @@
             class="org.apache.roller.planet.pojos.Planet">
         <table name="rag_planet"/>
         <named-query name="Planet.getAll">
-            <query>SELECT p FROM Planet p</query>
+            <query>SELECT p FROM Planet p ORDER BY p.title</query>
         </named-query>
         <named-query name="Planet.getByHandle">
             <query>SELECT p FROM Planet p WHERE p.handle = ?1</query>
         </named-query>
+        <named-query name="Planet.getByUser">
+            <query>SELECT p FROM Planet p JOIN p.permissions pms WHERE pms.user = ?1</query>
+        </named-query>
         <attributes>
             <id name="id">
                 <column name="id"/>
@@ -36,6 +39,11 @@
                     <cascade-all/>
                 </cascade>
             </one-to-many>
+            <one-to-many name="permissions" mapped-by="planet" target-entity="org.apache.roller.planet.pojos.PlanetPermission" fetch="LAZY">
+                <cascade>
+                    <cascade-remove/>
+                </cascade>
+            </one-to-many>
         </attributes>
     </entity>
 </entity-mappings>

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetGroup.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetGroup.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetGroup.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetGroup.java Sat Jun 28 12:18:17 2008
@@ -22,9 +22,9 @@
 import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.TreeSet;
-import org.apache.roller.planet.business.PlanetFactory;
+import org.apache.roller.planet.business.AggregatorFactory;
 import org.apache.roller.planet.business.PlanetManager;
-import org.apache.roller.util.UUIDGenerator;
+import org.apache.roller.planet.util.UUIDGenerator;
 
 
 /**
@@ -186,7 +186,7 @@
      * Return a list of the most recent 10 entries from this group.
      */
     public List getRecentEntries() {
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         try {
             return mgr.getEntries(this, 0, 10);
         } catch(Exception e) {

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetPermission.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetPermission.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetPermission.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetPermission.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,138 @@
+/*
+ * 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.planet.pojos;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.roller.planet.util.UUIDGenerator;
+
+
+/**
+ * Represents a user's permissions within a planet.
+ */
+public class PlanetPermission {
+
+    private String id = UUIDGenerator.generateUUID();
+    private Planet planet = null;
+    private User user = null;
+    private boolean pending = true;
+    public static short LIMITED = 0x00; // 0000
+    public static short AUTHOR = 0x01; // 0001
+    public static short ADMIN = 0x03; // 0011
+    private short permissionMask = LIMITED;
+
+    
+    public PlanetPermission() {
+    }
+
+    /**
+     * Check for specific permission.
+     */
+    public boolean has(short priv) {
+        return (getPermissionMask() & priv) == priv;
+    }
+    
+    
+    /**
+     * Id.
+     */
+    public String getId() {
+        return id;
+    }
+    
+    public void setId(String id) {
+        this.id = id;
+    }
+    
+    
+    /**
+     * Planet.
+     */
+    public Planet getPlanet() {
+        return planet;
+    }
+
+    public void setPlanet(Planet planet) {
+        this.planet = planet;
+    }
+    
+    
+    /**
+     * User.
+     */
+    public User getUser() {
+        return user;
+    }
+    
+    public void setUser(User user) {
+        this.user = user;
+    }
+    
+    
+    /**
+     * Bit mask that encodes user's permissions in Planet.
+     */
+    public short getPermissionMask() {
+        return permissionMask;
+    }
+    
+    public void setPermissionMask(short permissionMask) {
+        this.permissionMask = permissionMask;
+    }
+    
+    
+    /**
+     * True if user has been invited to join site but has not yet accepted.
+     * And false if user is member of Planet.
+     */
+    public boolean isPending() {
+        return pending;
+    }
+    
+    public void setPending(boolean pending) {
+        this.pending = pending;
+    }
+    
+    
+    //------------------------------------------------------- Good citizenship
+    
+    public String toString() {
+        StringBuffer buf = new StringBuffer();
+        buf.append("{");
+        buf.append(this.id);
+        buf.append(", ").append(this.permissionMask);
+        buf.append(", ").append(this.pending);
+        buf.append("}");
+        return buf.toString();
+    }
+
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if (other instanceof PlanetPermission != true) {
+            return false;
+        }
+        PlanetPermission o = (PlanetPermission) other;
+        return new EqualsBuilder().append(user, o.user).append(planet, o.planet).isEquals();
+    }
+
+    public int hashCode() {
+        return new HashCodeBuilder().append(user).append(planet).toHashCode();
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetPermission.orm.xml
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetPermission.orm.xml?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetPermission.orm.xml (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/PlanetPermission.orm.xml Sat Jun 28 12:18:17 2008
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity-mappings version="1.0" xmlns="http://java.sun.com/xml/ns/persistence/orm"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">
+    <description>Persistence Metadata for Roller</description>
+    <persistence-unit-metadata>
+        <persistence-unit-defaults>
+            <access>PROPERTY</access>
+        </persistence-unit-defaults>
+    </persistence-unit-metadata>
+    <package>org.apache.roller.planet.pojos</package>
+    <entity metadata-complete="true" name="PlanetPermission"
+            class="org.apache.roller.planet.pojos.PlanetPermission">
+        <table name="rag_user_permissions"/>
+        <named-query name="PlanetPermission.getByPlanetAndUser">
+            <query>SELECT p FROM PlanetPermission p WHERE p.planet = ?1 AND p.user = ?2</query>
+        </named-query>
+        <named-query name="PlanetPermission.getByUserAndPending">
+            <query>SELECT p FROM PlanetPermission p WHERE p.user = ?1 AND p.pending = ?2</query>
+        </named-query>
+        <named-query name="PlanetPermission.getByPlanetAndPending">
+            <query>SELECT p FROM PlanetPermission p WHERE p.planet = ?1 AND p.pending = ?2</query>
+        </named-query>
+        <attributes>
+            <id name="id">
+                <column name="id"/>
+            </id>
+            <basic name="permissionMask">
+                <column name="permission_mask" insertable="true" updatable="true" unique="false"/>
+            </basic>
+            <basic name="pending">
+                <column name="pending" insertable="true" updatable="true" unique="false"/>
+            </basic>
+            <many-to-one name="planet" target-entity="org.apache.roller.planet.pojos.Planet">
+                <join-column name="planet_id" insertable="true" updatable="true" nullable="true"/>
+            </many-to-one>
+            <many-to-one name="user" target-entity="org.apache.roller.planet.pojos.User">
+                <join-column name="user_id" insertable="true" updatable="true" nullable="true"/>
+            </many-to-one>
+        </attributes>
+    </entity>
+</entity-mappings>

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Subscription.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Subscription.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Subscription.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Subscription.java Sat Jun 28 12:18:17 2008
@@ -17,12 +17,14 @@
 package org.apache.roller.planet.pojos;
 
 import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
-import org.apache.roller.util.UUIDGenerator;
+import org.apache.roller.planet.util.UUIDGenerator;
 
 
 /**
@@ -37,6 +39,8 @@
     private String feedUrl;
     private String siteUrl;
     private Date lastUpdated;
+    private int errorCount = 0;
+    private String errorMessage = null;
     private int inboundlinks = 0;
     private int inboundblogs = 0;
     
@@ -47,6 +51,7 @@
     
     public Subscription() {}
     
+    
     /**
      * Compares subscriptions based on concatenation of title and feed URL.
      * This ensures that feeds are sorted by title, but that identical titles 
@@ -62,6 +67,7 @@
     /**
      * Determines if subscriotions are equal by comparing feed URLs.
      */
+    @Override
     public boolean equals(Object other) {        
         if(this == other) return true;
         if(!(other instanceof Subscription)) return false;        
@@ -69,10 +75,12 @@
         return this.feedUrl.equals(that.getFeedURL());
     }
     
+    @Override
     public int hashCode() {
         return this.feedUrl.hashCode();
     }
     
+    @Override
     public String toString() {
         StringBuffer buf = new StringBuffer();
         
@@ -124,6 +132,13 @@
         this.feedUrl = feedUrl;
     }
     
+    public String getEncodedFeedURL() {
+        try {
+            return URLEncoder.encode(getFeedURL(), "UTF-8");
+        } catch (UnsupportedEncodingException ex) {
+            return getFeedURL();
+        }
+    }
     
     public String getSiteURL() {
         return siteUrl;
@@ -160,6 +175,23 @@
         this.inboundblogs = inboundblogs;
     }
     
+
+    public int getErrorCount() {
+        return errorCount;
+    }
+
+    public void setErrorCount(int errorCount) {
+        this.errorCount = errorCount;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    public void setErrorMessage(String lastErrorMessage) {
+        this.errorMessage = lastErrorMessage;
+    }
+    
     
     public Set getGroups() {
         return groups;

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Subscription.orm.xml
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Subscription.orm.xml?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Subscription.orm.xml (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/Subscription.orm.xml Sat Jun 28 12:18:17 2008
@@ -12,12 +12,16 @@
     <entity metadata-complete="true" name="Subscription"
             class="org.apache.roller.planet.pojos.Subscription">
         <table name="rag_subscription"/>
-        <named-query name="Subscription.getAll">
-            <query>SELECT p FROM Subscription p</query>
+        <named-query name="Subscription.getByFeedURL">
+            <query>SELECT p FROM Subscription p WHERE p.feedURL = ?1</query>
         </named-query>
         <named-query name="Subscription.getAllOrderByFeedURL">
             <query>SELECT p FROM Subscription p ORDER BY p.feedURL DESC</query>
         </named-query>
+        <named-query name="Subscription.getCount">
+            <query>SELECT COUNT(p) FROM Subscription p</query>
+        </named-query>
+        <!-- // Old getTopSubscriptions() queries
         <named-query name="Subscription.getAllOrderByInboundBlogsDesc">
             <query>SELECT p FROM Subscription p ORDER BY p.inboundblogs DESC</query>
         </named-query>
@@ -26,9 +30,7 @@
                 BY p.inboundblogs DESC
             </query>
         </named-query>
-        <named-query name="Subscription.getByFeedURL">
-            <query>SELECT p FROM Subscription p WHERE p.feedURL = ?1</query>
-        </named-query>
+        -->
         <attributes>
             <id name="id">
                 <column name="id"/>
@@ -49,6 +51,12 @@
             <basic name="author">
                 <column name="author" insertable="true" updatable="true" unique="false"/>
             </basic>
+            <basic name="errorCount">
+                <column name="error_count" insertable="true" updatable="true" unique="false"/>
+            </basic>
+            <basic name="errorMessage">
+                <column name="error_message" insertable="true" updatable="true" unique="false"/>
+            </basic>
             <basic name="inboundlinks">
                 <column name="inbound_links" insertable="true" updatable="true" unique="false"/>
             </basic>

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/SubscriptionEntry.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/SubscriptionEntry.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/SubscriptionEntry.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/SubscriptionEntry.java Sat Jun 28 12:18:17 2008
@@ -24,7 +24,7 @@
 import java.util.Iterator;
 import java.util.List;
 import org.apache.roller.planet.util.Utilities;
-import org.apache.roller.util.UUIDGenerator;
+import org.apache.roller.planet.util.UUIDGenerator;
 
 
 /**

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/User.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/User.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/User.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/User.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,280 @@
+/*
+ * 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.planet.pojos;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.util.UUIDGenerator;
+import org.apache.roller.planet.util.Utilities;
+
+
+/**
+ * User bean.
+ */
+public class User implements Serializable {
+    
+    private String  id = UUIDGenerator.generateUUID();
+    private String  userName;
+    private String  password;
+    private String  fullName;
+    private String  emailAddress;
+    private Date    dateCreated;
+    private Boolean enabled = Boolean.TRUE;
+    private String  activationCode;
+    
+    private Set roles = new HashSet();
+    private List permissions = new ArrayList();
+    
+    
+    public User() {
+    }
+    
+    public User(String userName,
+            String password, String fullName,
+            String emailAddress,
+            String locale, String timeZone,
+            Date dateCreated,
+            Boolean isEnabled) {
+        this.userName = userName;
+        this.password = password;
+        this.fullName = fullName;
+        this.emailAddress = emailAddress;
+        this.dateCreated = (Date)dateCreated.clone();
+        this.enabled = isEnabled;
+    }
+    
+    
+    /**
+     * Id of the User.
+     */
+    public String getId() {
+        return this.id;
+    }
+    
+    public void setId( String id ) {
+        this.id = id;
+    }
+    
+    
+    /**
+     * User name of the user.
+     */
+    public String getUserName() {
+        return this.userName;
+    }
+    
+    public void setUserName( String userName ) {
+        this.userName = userName;
+    }
+    
+    /**
+     * Get password.
+     * If password encryption is enabled, will return encrypted password.
+     */
+    public String getPassword() {
+        return this.password;
+    }
+    
+    /**
+     * Set password.
+     * If password encryption is turned on, then pass in an encrypted password.
+     */
+    public void setPassword( String password ) {
+        this.password = password;
+    }
+    
+    /**
+     * Reset this user's password, handles encryption if configured.
+     *
+     * @param newPassword The new password to be set.
+     */
+    public void resetPassword(String newPassword) {
+        
+        String encrypt = AggregatorFactory.getAggregator().getConfig().getProperty("passwds.encryption.enabled");
+        String algorithm = AggregatorFactory.getAggregator().getConfig().getProperty("passwds.encryption.algorithm");
+        if (new Boolean(encrypt).booleanValue()) {
+            setPassword(Utilities.encodePassword(newPassword, algorithm));
+        } else {
+            setPassword(newPassword);
+        }
+    }
+    
+    
+    /**
+     * Full name of the user.
+     */
+    public String getFullName() {
+        return this.fullName;
+    }
+    
+    public void setFullName( String fullName ) {
+        this.fullName = fullName;
+    }
+    
+    
+    /**
+     * E-mail address of the user.
+     */
+    public String getEmailAddress() {
+        return this.emailAddress;
+    }
+    
+    public void setEmailAddress( String emailAddress ) {
+        this.emailAddress = emailAddress;
+    }
+    
+    
+    /**
+     * The date the user was created.
+     */
+    public Date getDateCreated() {
+        if (dateCreated == null) {
+            return null;
+        } else {
+            return (Date)dateCreated.clone();
+        }
+    }
+    
+    public void setDateCreated(final Date date) {
+        if (date != null) {
+            dateCreated = (Date)date.clone();
+        } else {
+            dateCreated = null;
+        }
+    }
+    
+    
+    /**
+     * Is this user account enabled?  Disabled accounts cannot login.
+     *
+     * @hibernate.property column="isenabled" non-null="true" unique="false"
+     */
+    public Boolean getEnabled() {
+        return this.enabled;
+    }
+    
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+    
+    
+    /** 
+     * Activation code.
+     */
+    public String getActivationCode() {
+        return activationCode;
+    }
+    
+    public void setActivationCode(String activationCode) {
+        this.activationCode = activationCode;
+    }
+    
+    
+    /**
+     * List of weblog permissions for this user.
+     */
+    public List getPermissions() {
+        return permissions;
+    }
+    
+    public void setPermissions(List perms) {
+        permissions = perms;
+    }
+    
+    
+    /**
+     * The set of roles for this user.
+     */
+    public Set getRoles() {
+        return roles;
+    }
+    
+    /**
+     * this is private to force the use of grant/revokeRole() methods.
+     */
+    private void setRoles(Set roles) {
+        this.roles = roles;
+    }
+    
+    
+    /**
+     * Returns true if user has role specified.
+     */
+    public boolean hasRole(String roleName) {
+        Iterator iter = getRoles().iterator();
+        while (iter.hasNext()) {
+            UserRole role = (UserRole) iter.next();
+            if (role.getRole().equals(roleName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    /**
+     * Grant to user role specified by role name.
+     */
+    public void grantRole(String roleName) {
+        if (!hasRole(roleName)) {
+            UserRole role = new UserRole(this, roleName);
+            getRoles().add(role);
+            role.setUser(this);
+        }
+    }
+    
+    
+    
+    //------------------------------------------------------- Good citizenship
+    
+    @Override
+    public String toString() {
+        StringBuffer buf = new StringBuffer();
+        buf.append("{");
+        buf.append(this.id);
+        buf.append(", ").append(this.userName);
+        buf.append(", ").append(this.fullName);
+        buf.append(", ").append(this.emailAddress);
+        buf.append(", ").append(this.dateCreated);
+        buf.append(", ").append(this.enabled);
+        buf.append("}");
+        return buf.toString();
+    }
+    
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) return true;
+        if (other instanceof User != true) return false;
+        User o = (User)other;
+        return new EqualsBuilder().append(getUserName(), o.getUserName()).isEquals();
+    }
+    
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().append(getUserName()).toHashCode();
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/User.orm.xml
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/User.orm.xml?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/User.orm.xml (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/pojos/User.orm.xml Sat Jun 28 12:18:17 2008
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity-mappings version="1.0" xmlns="http://java.sun.com/xml/ns/persistence/orm"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">
+    <description>Persistence Metadata for Roller</description>
+    <persistence-unit-metadata>
+        <persistence-unit-defaults>
+            <access>PROPERTY</access>
+        </persistence-unit-defaults>
+    </persistence-unit-metadata>
+    <package>org.apache.roller.planet.pojos</package>
+    <entity metadata-complete="true" name="User" class="org.apache.roller.planet.pojos.User">
+        <table name="rag_user"/>
+        <named-query name="User.getAll">
+            <query>SELECT u FROM User u</query>
+        </named-query>
+        <named-query name="User.getByEnabled">
+            <query>SELECT u FROM User u WHERE u.enabled = ?1</query>
+        </named-query>
+        <named-query name="User.getByUserName">
+            <query>SELECT u FROM User u WHERE u.userName= ?1</query>
+        </named-query>
+        <named-query name="User.getByUserName&amp;Enabled">
+            <query>SELECT u FROM User u WHERE u.userName= ?1 AND u.enabled = ?2</query>
+        </named-query>
+        <named-query name="User.getByUserNameOrEmailAddressStartsWith">
+            <query>SELECT u FROM User u WHERE u.userName LIKE ?1 OR u.emailAddress LIKE ?1</query>
+        </named-query>
+        <named-query name="User.getByUserNameOrEmailAddressStartsWith&amp;Enabled">
+            <query>SELECT u FROM User u WHERE u.enabled = ?1 AND (u.userName LIKE ?2 OR u.emailAddress LIKE ?3)</query>
+        </named-query>
+        <named-query name="User.getCount">
+            <query>SELECT COUNT(u) FROM User u</query>
+        </named-query>
+        <named-query name="User.getCountEnabled">
+            <query>SELECT COUNT(u) FROM User u WHERE u.enabled = ?1</query>
+        </named-query>
+        <attributes>
+            <id name="id">
+                <column name="id"/>
+            </id>
+            <basic name="enabled">
+                <column name="isenabled" insertable="true" updatable="true" unique="false"/>
+            </basic>
+            <basic name="userName">
+                <column name="username" insertable="true" updatable="true" unique="true"/>
+            </basic>
+            <basic name="activationCode">
+                <column name="activationcode" insertable="true" updatable="true" unique="true"/>
+            </basic>
+            <basic name="password">
+                <column name="passphrase" insertable="true" updatable="true" unique="false"/>
+            </basic>
+            <basic name="fullName">
+                <column name="fullname" insertable="true" updatable="true" unique="true"/>
+            </basic>
+            <basic name="emailAddress">
+                <column name="emailaddress" insertable="true" updatable="true" unique="true"/>
+            </basic>
+            <basic name="dateCreated">
+                <column name="datecreated" insertable="true" updatable="true" unique="false"/>
+                <temporal>TIMESTAMP</temporal>
+            </basic>
+            <one-to-many name="permissions" mapped-by="user" target-entity="org.apache.roller.planet.pojos.PlanetPermission" fetch="LAZY">
+            </one-to-many>
+            <one-to-many name="roles" mapped-by="user" target-entity="org.apache.roller.planet.pojos.UserRole" fetch="LAZY">
+                <cascade>
+                    <cascade-all/>
+                </cascade>
+            </one-to-many>
+        </attributes>
+    </entity>
+</entity-mappings>