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 [7/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/ui/rendering/util/ParsedRequest.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/ParsedRequest.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/ParsedRequest.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/ParsedRequest.java Sat Jun 28 12:18:17 2008
@@ -18,14 +18,22 @@
 
 package org.apache.roller.planet.ui.rendering.util;
 
-import java.util.Locale;
-import javax.servlet.http.HttpServletRequest;
+import java.util.Collections;
+import java.util.Map;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.business.UserManager;
+import org.apache.roller.planet.pojos.User;
 
 
 /**
- * An abstract class representing any request made to Roller that has been
- * parsed in order to extract relevant pieces of information from the url.
+ * An abstract class representing any rendering request made that has been
+ * parsed in order to extract relevant pieces of information.
  *
+ * NOTE: this class purposely exposes a getUnparsedURI() method which provides the
+ * path info specified by the request that has not been parsed by this
+ * particular class.  this makes it relatively easy for subclasses to extend
+ * this class and simply pick up where the parent left off in the parsing process.
+ * 
  * NOTE: It is extremely important to mention that this class and all of its
  * subclasses are meant to be extremely light weight.  Meaning they should
  * avoid any time consuming operations at all costs, especially operations
@@ -35,46 +43,114 @@
  */
 public abstract class ParsedRequest {
     
-    HttpServletRequest request = null;
+    // the URI representing this parsed request
+    private String URI = null;
     
-    private String authenticUser = null;
+    // a Map representing query string paramters from the request
+    private Map<String,String[]> parameters = Collections.EMPTY_MAP;
     
+    // the user name of the user logged in for this request, if any
+    private String authenticUserName = null;
     
-    ParsedRequest() {}
+    // the User object representing the logged in user of this request, if any
+    private User authenticUser = null;
+    
+    // the part of the URI that is considered "unparsed" still
+    private String unparsedURI = null;
+    
+    
+    public ParsedRequest() {}
     
     
     /**
      * Parse the given http request and extract any information we can.
      *
      * This abstract version of the constructor gathers info likely to be
-     * relevant to all requests to Roller.
+     * relevant to all requests.
      */
-    public ParsedRequest(HttpServletRequest request) throws InvalidRequestException {
+    public ParsedRequest(String uri) throws InvalidRequestException {
+        
+        // our original URI
+        URI = uri;
         
-        // keep a reference to the original request
-        this.request = request;
+        // set unparsed URI, which is everything at this point
+        unparsedURI = uri;
         
-        // login status
-        java.security.Principal prince = request.getUserPrincipal();
-        if(prince != null) {
-            this.authenticUser = prince.getName();
+        // strip off leading slash if needed
+        if(unparsedURI != null && unparsedURI.startsWith("/")) {
+            unparsedURI = unparsedURI.substring(1);
         }
         
+        // strip off trailing slash if needed
+        if (unparsedURI != null && unparsedURI.endsWith("/")) {
+            unparsedURI = unparsedURI.substring(0, unparsedURI.length() - 1);
+        }
+    }
+    
+    
+    public String getURI() {
+        return URI;
+    }
+
+    public void setURI(String URI) {
+        this.URI = URI;
+    }
+    
+    public String getParameter(String key) {
+        String[] value = (String[]) parameters.get(key);
+        if(value != null && value.length > 0) {
+            return value[0];
+        } else {
+            return null;
+        }
     }
     
+    public String[] getParameterList(String key) {
+        return parameters.get(key);
+    }
     
-    public String getAuthenticUser() {
-        return this.authenticUser;
+    public Map<String, String[]> getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(Map<String, String[]> parameters) {
+        this.parameters = parameters;
     }
     
+    public String getAuthenticUserName() {
+        return this.authenticUserName;
+    }
     
-    public void setAuthenticUser(String authenticUser) {
-        this.authenticUser = authenticUser;
+    public void setAuthenticUserName(String authenticUser) {
+        this.authenticUserName = authenticUser;
     }
     
+    public User getAuthenticUser() {
+        if(authenticUser == null && authenticUserName != null) try {
+            UserManager umgr = AggregatorFactory.getAggregator().getUserManager();
+            authenticUser = umgr.getUserByUserName(authenticUserName);
+        } catch(Exception ex) {
+            throw new RuntimeException("Error looking up authenticated user = "+authenticUserName, ex);
+        }
+        
+        return authenticUser;
+    }
+    
+    public void setAuthenticUser(User user) {
+        authenticUser = user;
+        authenticUserName = user.getUserName();
+    }
     
     public boolean isLoggedIn() {
-        return (this.authenticUser != null);
+        return (this.authenticUserName != null);
+    }
+    
+    public String getUnparsedURI() {
+        return unparsedURI;
+    }
+
+    public void setUnparsedURI(String uri) {
+        this.unparsedURI = uri;
     }
     
 }

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupFeedRequest.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupFeedRequest.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupFeedRequest.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupFeedRequest.java Sat Jun 28 12:18:17 2008
@@ -18,11 +18,8 @@
 
 package org.apache.roller.planet.ui.rendering.util;
 
-import javax.servlet.http.HttpServletRequest;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.planet.ui.rendering.util.InvalidRequestException;
-import org.apache.roller.planet.ui.rendering.util.PlanetRequest;
 
 
 /**
@@ -30,8 +27,10 @@
  * 
  * /planet-ui/rendering/feeds/*
  *
- * We use this class as a helper to parse an incoming url and sort out the
- * information embedded in the url for later use.
+ * We expect the path info to be in the form ...
+ * 
+ * /<planetHandle>/<groupHandle>/<feedFormat>
+ * 
  */
 public class PlanetGroupFeedRequest extends PlanetGroupRequest {
     
@@ -41,24 +40,24 @@
     private String format = null;
     
     
-    public PlanetGroupFeedRequest() {}
+    public PlanetGroupFeedRequest() {
+        super();
+    }
     
     
     /**
-     * Construct the WeblogFeedRequest by parsing the incoming url
+     * Construct the PlanetGroupFeedRequest by parsing the incoming url
      */
-    public PlanetGroupFeedRequest(HttpServletRequest request) 
-            throws InvalidRequestException {
+    public PlanetGroupFeedRequest(String requestURI) throws InvalidRequestException {
         
         // let our parent take care of their business first
-        // parent determines weblog handle and locale if specified
-        super(request);
+        super(requestURI);
         
         // we only want the path info left over from after our parents parsing
-        String pathInfo = this.getPathInfo();
+        String myPathInfo = this.getUnparsedURI();
         
         // parse the request object and figure out what we've got
-        log.debug("parsing path "+pathInfo);
+        log.debug("parsing path "+myPathInfo);
         
         
         /* 
@@ -66,13 +65,13 @@
          *
          * <format>
          */
-        if(pathInfo != null && pathInfo.trim().length() > 1) {
+        if(myPathInfo != null && myPathInfo.trim().length() > 1) {
             
-            this.format = pathInfo;
+            this.format = myPathInfo;
             
         } else {
             throw new InvalidRequestException("not a valid planet group feed, "+
-                    request.getRequestURL());
+                    requestURI);
         }
         
         if(log.isDebugEnabled()) {

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupOpmlRequest.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupOpmlRequest.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupOpmlRequest.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupOpmlRequest.java Sat Jun 28 12:18:17 2008
@@ -18,11 +18,8 @@
 
 package org.apache.roller.planet.ui.rendering.util;
 
-import javax.servlet.http.HttpServletRequest;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.planet.ui.rendering.util.InvalidRequestException;
-import org.apache.roller.planet.ui.rendering.util.PlanetRequest;
 
 
 /**
@@ -40,28 +37,28 @@
     // lightweight attributes
     
     
-    public PlanetGroupOpmlRequest() {}
+    public PlanetGroupOpmlRequest() {
+        super();
+    }
     
     
     /**
      * Construct the WeblogFeedRequest by parsing the incoming url
      */
-    public PlanetGroupOpmlRequest(HttpServletRequest request) 
-            throws InvalidRequestException {
+    public PlanetGroupOpmlRequest(String requestURI) throws InvalidRequestException {
         
         // let our parent take care of their business first
-        // parent determines weblog handle and locale if specified
-        super(request);
+        super(requestURI);
         
         // we only want the path info left over from after our parents parsing
-        String pathInfo = this.getPathInfo();
+        String pathInfo = this.getUnparsedURI();
         
         // parse the request object and figure out what we've got
         log.debug("parsing path "+pathInfo);
         
         if(pathInfo != null) {
             throw new InvalidRequestException("not a valid planet opml page, "+
-                    request.getRequestURL());
+                    requestURI);
         }
     }
     

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupPageRequest.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupPageRequest.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupPageRequest.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupPageRequest.java Sat Jun 28 12:18:17 2008
@@ -18,7 +18,7 @@
 
 package org.apache.roller.planet.ui.rendering.util;
 
-import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -39,33 +39,38 @@
     private int pageNum = 0;
     
     
-    public PlanetGroupPageRequest() {}
+    public PlanetGroupPageRequest() {
+        super();
+    }
     
     
     /**
-     * Construct the WeblogFeedRequest by parsing the incoming url
+     * Construct the PlanetGroupPageRequest by parsing the incoming url
      */
-    public PlanetGroupPageRequest(HttpServletRequest request) 
+    public PlanetGroupPageRequest(String requestURI, Map<String, String[]> requestParams) 
             throws InvalidRequestException {
         
         // let our parent take care of their business first
         // parent determines planet handle
-        super(request);
+        super(requestURI);
         
         // we only want the path info left over from after our parents parsing
-        String pathInfo = this.getPathInfo();
+        String pathInfo = this.getUnparsedURI();
         
         // parse the request object and figure out what we've got
         log.debug("parsing path "+pathInfo);
         
         if(pathInfo != null) {
             throw new InvalidRequestException("not a valid planet group page, "+
-                    request.getRequestURL());
+                    requestURI);
         }
         
+        // store request params
+        setParameters(requestParams);
+        
         // parse request parameters, right now we only allow for a "page" param
-        if(request.getParameter("page") != null) {
-            String pageInt = request.getParameter("page");
+        if(requestParams.get("page") != null) {
+            String pageInt = getParameter("page");
             try {
                 this.pageNum = Integer.parseInt(pageInt);
             } catch(NumberFormatException e) {

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupRequest.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupRequest.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupRequest.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/PlanetGroupRequest.java Sat Jun 28 12:18:17 2008
@@ -18,69 +18,122 @@
 
 package org.apache.roller.planet.ui.rendering.util;
 
-import javax.servlet.http.HttpServletRequest;
 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.pojos.Planet;
 import org.apache.roller.planet.pojos.PlanetGroup;
 
 
 /**
- * Represents a request to a planet group.
+ * Represents a request to a planet or a group.
  * 
- * /<planetHandle>/group/<groupHandle>[/extra/path/info]
+ * When we are parsing the data from request path info we expect it to
+ * be in the form ...
+ * 
+ * /<planetHandle>/<groupHandle>[/extra/path/info]
  *
  */
-public class PlanetGroupRequest extends PlanetRequest {
+public class PlanetGroupRequest extends ParsedRequest {
     
     private static Log log = LogFactory.getLog(PlanetGroupRequest.class);
     
     // lightweight attributes
+    private String planetHandle = null;
     private String groupHandle = null;
     
     // heavyweight attributes
+    private Planet planet = null;
     private PlanetGroup group = null;
     
     
-    public PlanetGroupRequest() {}
+    public PlanetGroupRequest() {
+        super();
+    }
     
     
-    public PlanetGroupRequest(HttpServletRequest request) 
+    public PlanetGroupRequest(String requestURI) 
             throws InvalidRequestException {
         
         // let our parent take care of their business first
-        super(request);
+        super(requestURI);
         
-        String myPathInfo = this.getPathInfo();
+        String myPathInfo = getUnparsedURI();
         
-        log.debug("parsing path "+myPathInfo);
+        log.debug("parsing path - "+myPathInfo);
         
         /* 
          * parse the path info.  must look like this ...
          *
-         * <groupHandle>[/extra/info]
+         * <planetHandle>/<groupHandle>[/extra/info]
          */
-        if(myPathInfo != null && myPathInfo.trim().length() > 1) {
+        if(myPathInfo != null && myPathInfo.trim().length() > 0) {
+            
+            String[] pathElements = myPathInfo.split("/", 3);
+            
+            // first look for the planet handle
+            if(pathElements[0].length() > 0) {
+                this.planetHandle = pathElements[0];
+            } else {
+                // no planetHandle in path info
+                throw new InvalidRequestException("not a planet/group request, "+
+                        requestURI);
+            }
             
-            String[] urlPath = myPathInfo.split("/", 2);
-            this.groupHandle = urlPath[0];
-            this.pathInfo = null;
+            // check if there was a group handle
+            if(pathElements.length >= 2) {
+                this.groupHandle = pathElements[1];
+            }
             
-            if(urlPath.length == 2) {
-                this.pathInfo = urlPath[1];
+            // update path info
+            if(pathElements.length == 3) {
+                setUnparsedURI(pathElements[2]);
+            } else {
+                setUnparsedURI(null);
             }
             
+        } else {
+            throw new InvalidRequestException("not a planet/group request, "+
+                        requestURI);
         }
         
         if(log.isDebugEnabled()) {
+            log.debug("planetHandle = "+this.planetHandle);
             log.debug("groupHandle = "+this.groupHandle);
-            log.debug("pathInfo = "+this.pathInfo);
+            log.debug("pathInfo = "+getUnparsedURI());
         }
     }
     
     
+    public String getPlanetHandle() {
+        return planetHandle;
+    }
+
+    public void setPlanetHandle(String planetHandle) {
+        this.planetHandle = planetHandle;
+    }
+
+    public Planet getPlanet() {
+        
+        if(planet == null && planetHandle != null) {
+            try {
+                PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
+                planet = mgr.getPlanet(planetHandle);
+            } catch (PlanetException ex) {
+                log.error("Error looking up planet "+planetHandle, ex);
+            }
+        }
+        
+        return planet;
+    }
+
+    public void setPlanet(Planet planet) {
+        this.planet = planet;
+        setPlanetHandle(planet.getHandle());
+    }
+    
     public String getGroupHandle() {
         return groupHandle;
     }
@@ -93,7 +146,7 @@
         
         if(group == null && groupHandle != null) {
             try {
-                PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+                PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
                 group = mgr.getGroup(getPlanet(), groupHandle);
             } catch (PlanetException ex) {
                 log.error("Error looking up group "+groupHandle, ex);
@@ -105,6 +158,7 @@
 
     public void setGroup(PlanetGroup group) {
         this.group = group;
+        setGroupHandle(group.getHandle());
     }
     
 }

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/cache/FeedCache.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/cache/FeedCache.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/cache/FeedCache.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/cache/FeedCache.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,188 @@
+/*
+ * 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.ui.rendering.util.cache;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.config.PlanetConfig;
+import org.apache.roller.planet.pojos.Planet;
+import org.apache.roller.planet.pojos.PlanetGroup;
+import org.apache.roller.planet.ui.rendering.util.PlanetGroupFeedRequest;
+import org.apache.roller.planet.ui.rendering.util.PlanetGroupOpmlRequest;
+import org.apache.roller.planet.util.cache.Cache;
+import org.apache.roller.planet.util.cache.CacheHandler;
+import org.apache.roller.planet.util.cache.CacheManager;
+
+
+/**
+ * Cache for planet page content.
+ */
+public class FeedCache implements CacheHandler {
+    
+    private static Log log = LogFactory.getLog(FeedCache.class);
+    
+    // a unique identifier for this cache, this is used as the prefix for
+    // roller config properties that apply to this cache
+    public static final String CACHE_ID = "cache.feed";
+    
+    // keep cached content
+    private boolean cacheEnabled = true;
+    private Cache contentCache = null;
+    
+    // reference to our singleton instance
+    private static FeedCache singletonInstance = new FeedCache();
+    
+    
+    private FeedCache() {
+        
+        PlanetConfig config = AggregatorFactory.getAggregator().getConfig();
+        
+        cacheEnabled = config.getBooleanProperty(CACHE_ID+".enabled");
+        
+        Map<String, String> cacheProps = new HashMap<String, String>();
+        cacheProps.put("id", CACHE_ID);
+        Enumeration allProps = config.keys();
+        String prop = null;
+        while(allProps.hasMoreElements()) {
+            prop = (String) allProps.nextElement();
+            
+            // we are only interested in props for this cache
+            if(prop.startsWith(CACHE_ID+".")) {
+                cacheProps.put(prop.substring(CACHE_ID.length()+1), 
+                        config.getProperty(prop));
+            }
+        }
+        
+        log.info(cacheProps);
+        
+        if(cacheEnabled) {
+            contentCache = CacheManager.constructCache(this, cacheProps);
+        } else {
+            log.warn("Caching has been DISABLED");
+        }
+    }
+    
+    
+    public static FeedCache getInstance() {
+        return singletonInstance;
+    }
+    
+    
+    public Object get(String key) {
+        
+        if(!cacheEnabled)
+            return null;
+        
+        Object entry = this.contentCache.get(key);
+        if (entry != null) {
+            log.debug("HIT " + key);
+        } else {
+            log.debug("MISS " + key);
+        }
+        
+        return entry;
+    }
+    
+    
+    public void put(String key, Object value) {
+        
+        if(!cacheEnabled)
+            return;
+        
+        contentCache.put(key, value);
+        log.debug("PUT "+key);
+    }
+    
+    
+    public void remove(String key) {
+        
+        if(!cacheEnabled)
+            return;
+        
+        contentCache.remove(key);
+        log.debug("REMOVE "+key);
+    }
+    
+    
+    public void clear() {
+        
+        if(!cacheEnabled)
+            return;
+        
+        contentCache.clear();
+        log.debug("CLEAR");
+    }
+    
+    
+    /**
+     * Generate a cache key from a parsed group feed request.
+     * This generates a key of the form ...
+     *
+     * <planet>/<group>/<format>
+     *
+     */
+    public String generateKey(PlanetGroupFeedRequest groupPage) {
+        
+        StringBuffer key = new StringBuffer();
+        
+        key.append(CACHE_ID).append(":");
+        key.append(groupPage.getPlanetHandle());
+        key.append("/").append(groupPage.getGroupHandle());
+        key.append("/").append(groupPage.getFormat());
+        
+        return key.toString();
+    }
+    
+    
+    /**
+     * Generate a cache key from a parsed group feed request.
+     * This generates a key of the form ...
+     *
+     * <planet>/<group>/type=opml
+     *
+     */
+    public String generateKey(PlanetGroupOpmlRequest groupPage) {
+        
+        StringBuffer key = new StringBuffer();
+        
+        key.append(CACHE_ID).append(":");
+        key.append(groupPage.getPlanetHandle());
+        key.append("/").append(groupPage.getGroupHandle());
+        key.append("/").append("type=opml");
+        
+        return key.toString();
+    }
+    
+    
+    public void invalidate(Planet planet) {
+        // invalidate whole cache.
+        contentCache.clear();
+    }
+    
+    
+    public void invalidate(PlanetGroup group) {
+        // invalidate whole cache.
+        contentCache.clear();
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/cache/PageCache.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/cache/PageCache.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/cache/PageCache.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/util/cache/PageCache.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,167 @@
+/*
+ * 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.ui.rendering.util.cache;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.config.PlanetConfig;
+import org.apache.roller.planet.pojos.Planet;
+import org.apache.roller.planet.pojos.PlanetGroup;
+import org.apache.roller.planet.ui.rendering.util.PlanetGroupPageRequest;
+import org.apache.roller.planet.util.cache.Cache;
+import org.apache.roller.planet.util.cache.CacheHandler;
+import org.apache.roller.planet.util.cache.CacheManager;
+
+
+/**
+ * Cache for planet page content.
+ */
+public class PageCache implements CacheHandler {
+    
+    private static Log log = LogFactory.getLog(PageCache.class);
+    
+    // a unique identifier for this cache, this is used as the prefix for
+    // roller config properties that apply to this cache
+    public static final String CACHE_ID = "cache.page";
+    
+    // keep cached content
+    private boolean cacheEnabled = true;
+    private Cache contentCache = null;
+    
+    // reference to our singleton instance
+    private static PageCache singletonInstance = new PageCache();
+    
+    
+    private PageCache() {
+        
+        PlanetConfig config = AggregatorFactory.getAggregator().getConfig();
+                
+        cacheEnabled = config.getBooleanProperty(CACHE_ID+".enabled");
+        
+        Map<String, String> cacheProps = new HashMap<String, String>();
+        cacheProps.put("id", CACHE_ID);
+        Enumeration allProps = config.keys();
+        String prop = null;
+        while(allProps.hasMoreElements()) {
+            prop = (String) allProps.nextElement();
+            
+            // we are only interested in props for this cache
+            if(prop.startsWith(CACHE_ID+".")) {
+                cacheProps.put(prop.substring(CACHE_ID.length()+1), 
+                        config.getProperty(prop));
+            }
+        }
+        
+        log.info(cacheProps);
+        
+        if(cacheEnabled) {
+            contentCache = CacheManager.constructCache(this, cacheProps);
+        } else {
+            log.warn("Caching has been DISABLED");
+        }
+    }
+    
+    
+    public static PageCache getInstance() {
+        return singletonInstance;
+    }
+    
+    
+    public Object get(String key) {
+        
+        if(!cacheEnabled)
+            return null;
+        
+        Object entry = this.contentCache.get(key);
+        if (entry != null) {
+            log.debug("HIT " + key);
+        } else {
+            log.debug("MISS " + key);
+        }
+        
+        return entry;
+    }
+    
+    
+    public void put(String key, Object value) {
+        
+        if(!cacheEnabled)
+            return;
+        
+        contentCache.put(key, value);
+        log.debug("PUT "+key);
+    }
+    
+    
+    public void remove(String key) {
+        
+        if(!cacheEnabled)
+            return;
+        
+        contentCache.remove(key);
+        log.debug("REMOVE "+key);
+    }
+    
+    
+    public void clear() {
+        
+        if(!cacheEnabled)
+            return;
+        
+        contentCache.clear();
+        log.debug("CLEAR");
+    }
+    
+    
+    /**
+     * Generate a cache key from a parsed group page request.
+     * This generates a key of the form ...
+     *
+     * <planet>/<group>/<pagenum>
+     *
+     */
+    public String generateKey(PlanetGroupPageRequest groupPage) {
+        
+        StringBuffer key = new StringBuffer();
+        
+        key.append(CACHE_ID).append(":");
+        key.append(groupPage.getPlanetHandle());
+        key.append("/").append(groupPage.getGroupHandle());
+        key.append("/").append(groupPage.getPageNum());
+        
+        return key.toString();
+    }
+    
+    
+    public void invalidate(Planet planet) {
+        // invalidate whole cache.
+        contentCache.clear();
+    }
+    
+    
+    public void invalidate(PlanetGroup group) {
+        // invalidate whole cache.
+        contentCache.clear();
+    }
+    
+}

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/velocity/TemplateResourceLoader.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/velocity/TemplateResourceLoader.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/velocity/TemplateResourceLoader.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/rendering/velocity/TemplateResourceLoader.java Sat Jun 28 12:18:17 2008
@@ -23,7 +23,7 @@
 import org.apache.commons.collections.ExtendedProperties;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.planet.config.PlanetConfig;
+import org.apache.roller.planet.business.AggregatorFactory;
 import org.apache.velocity.exception.ResourceNotFoundException;
 import org.apache.velocity.runtime.resource.Resource;
 import org.apache.velocity.runtime.resource.loader.ResourceLoader;
@@ -47,7 +47,7 @@
         log.debug("TemplateResourceLoader : initialization starting.");
         
         if (templateDir == null) {
-            templateDir = PlanetConfig.getProperty("template.dir");
+            templateDir = AggregatorFactory.getAggregator().getConfig().getProperty("template.dir");
             log.debug("Templates dir = "+templateDir);
         }
         

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/CreateUser.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/CreateUser.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/CreateUser.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/CreateUser.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,149 @@
+/*
+ * 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.ui.struts2.admin;
+
+import org.apache.commons.lang.CharSetUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.planet.PlanetException;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.business.UserManager;
+import org.apache.roller.planet.pojos.User;
+import org.apache.roller.planet.ui.struts2.core.Register;
+import org.apache.roller.planet.ui.struts2.util.UIAction;
+
+
+/**
+ * Action for admins to manually create new user accounts.
+ */
+public class CreateUser extends UIAction {
+    
+    private static Log log = LogFactory.getLog(CreateUser.class);
+    
+    // a bean to store our form data
+    private CreateUserBean bean = new CreateUserBean();
+    
+    
+    public CreateUser() {
+        this.pageTitle = "CreateUser.title";
+    }
+    
+    
+    @Override
+    public String requiredUserRole() {
+        return "admin";
+    }
+    
+    @Override
+    public boolean isPlanetRequired() {
+        return false;
+    }
+    
+    
+    /**
+     * Show admin user creation form.
+     */
+    @Override
+    public String execute() {
+        
+        return INPUT;
+    }
+    
+    
+    /**
+     * Create a new user.
+     */
+    public String save() {
+        
+        // run some validation
+        myValidate();
+        
+        if (!hasActionErrors()) try {
+            
+            UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+            
+            // copy form data into new user pojo
+            User newUser = new User();
+            getBean().copyTo(newUser, getLocale()); // doesn't copy password
+            newUser.setDateCreated(new java.util.Date());
+            
+            // set username and password
+            newUser.setUserName(getBean().getUserName());
+            newUser.resetPassword(getBean().getPassword());
+            
+            // are we granting the user admin rights?
+            if(getBean().isAdministrator()) {
+                newUser.grantRole("admin");
+            }
+            
+            // save new user
+            mgr.addUser(newUser);
+            AggregatorFactory.getAggregator().flush();
+            
+            // TODO: i18n
+            addMessage("New user created");
+            
+            return INPUT;
+            
+        } catch (PlanetException e) {
+            log.error("Error adding new user", e);
+            // TODO: i18n
+            addError("Error creating user");
+        }
+        
+        return INPUT;
+    }
+    
+    
+    // TODO: replace with struts2 validation
+    private void myValidate() {
+        
+        String allowed = getPlanetConfig().getProperty("username.allowedChars");
+        if(allowed == null || allowed.trim().length() == 0) {
+            allowed = Register.DEFAULT_ALLOWED_CHARS;
+        }
+        String safe = CharSetUtils.keep(getBean().getUserName(), allowed);
+        
+        if (StringUtils.isEmpty(getBean().getUserName())) {
+            addError("error.add.user.missingUserName");
+        } else if (!safe.equals(getBean().getUserName()) ) {
+            addError("error.add.user.badUserName");
+        }
+        
+        if (StringUtils.isEmpty(getBean().getEmailAddress())) {
+            addError("error.add.user.missingEmailAddress");
+        }
+        
+        if (StringUtils.isEmpty(getBean().getPassword()) && 
+                StringUtils.isEmpty(getBean().getPassword())) {
+            addError("error.add.user.missingPassword");
+        }
+    }
+    
+    
+    public CreateUserBean getBean() {
+        return bean;
+    }
+
+    public void setBean(CreateUserBean bean) {
+        this.bean = bean;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/CreateUserBean.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/CreateUserBean.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/CreateUserBean.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/CreateUserBean.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,117 @@
+/*
+ * 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.ui.struts2.admin;
+
+import java.util.Locale;
+import org.apache.roller.planet.pojos.User;
+
+
+/**
+ * Bean used by CreateUser action.
+ */
+public class CreateUserBean {
+    
+    private String id = null;
+    private String userName = null;
+    private String password = null;
+    private String fullName = null;
+    private String emailAddress = null;
+    private Boolean enabled = Boolean.TRUE;
+    
+    private boolean administrator = false;
+    
+    
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+    
+    public String getFullName() {
+        return fullName;
+    }
+
+    public void setFullName(String fullName) {
+        this.fullName = fullName;
+    }
+
+    public String getEmailAddress() {
+        return emailAddress;
+    }
+
+    public void setEmailAddress(String emailAddress) {
+        this.emailAddress = emailAddress;
+    }
+    
+    public Boolean getEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+    
+    public boolean isAdministrator() {
+        return administrator;
+    }
+
+    public void setAdministrator(boolean administrator) {
+        this.administrator = administrator;
+    }
+    
+    
+    public void copyTo(User dataHolder, Locale locale) {
+        
+        dataHolder.setFullName(this.fullName);
+        dataHolder.setEmailAddress(this.emailAddress);
+        dataHolder.setEnabled(new Boolean(this.enabled));
+    }
+    
+    
+    public void copyFrom(User dataHolder, Locale locale) {
+        
+        this.id = dataHolder.getId();
+        this.userName = dataHolder.getUserName();
+        this.password = dataHolder.getPassword();
+        this.fullName = dataHolder.getFullName();
+        this.emailAddress = dataHolder.getEmailAddress();
+        this.enabled = dataHolder.getEnabled();
+        
+        this.administrator = dataHolder.hasRole("admin");
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/GlobalConfig.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/GlobalConfig.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/GlobalConfig.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/GlobalConfig.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,186 @@
+/*
+ * 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.ui.struts2.admin;
+
+import java.util.Collections;
+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.planet.PlanetException;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.business.PropertiesManager;
+import org.apache.roller.planet.config.runtime.ConfigDef;
+import org.apache.roller.planet.config.runtime.RuntimeConfigDefs;
+import org.apache.roller.planet.pojos.RuntimeConfigProperty;
+import org.apache.roller.planet.ui.struts2.util.UIAction;
+import org.apache.roller.planet.util.cache.CacheManager;
+import org.apache.struts2.interceptor.ParameterAware;
+
+
+/**
+ * Handles editing of global runtime properties.
+ *
+ * TODO: validation and security.
+ */
+public class GlobalConfig extends UIAction implements ParameterAware {
+    
+    private static Log log = LogFactory.getLog(GlobalConfig.class);
+    
+    // the runtime config def used to populate the display
+    private ConfigDef globalConfigDef = null;
+    
+    // original request parameters
+    private Map parameters = Collections.EMPTY_MAP;
+    
+    // runtime properties data
+    private Map properties = Collections.EMPTY_MAP;
+    
+    
+    public GlobalConfig() {
+        this.pageTitle = "GlobalConfig.title";
+    }
+    
+    
+    @Override
+    public boolean isPlanetRequired() {
+        return false;
+    }
+    
+    @Override
+    public String requiredUserRole() {
+        return "admin";
+    }
+    
+    
+    @Override
+    public void myPrepare() {
+        try {
+            // just grab our properties map and put it in the request
+            PropertiesManager pmgr = AggregatorFactory.getAggregator().getPropertiesManager();
+            setProperties(pmgr.getProperties());
+        } catch (PlanetException ex) {
+            log.error("Error loading runtime properties", ex);
+        }
+        
+        // set config def used to draw the view
+        RuntimeConfigDefs defs = AggregatorFactory.getAggregator().getConfig().getRuntimeConfigDefs();
+        List<ConfigDef> configDefs = defs.getConfigDefs();
+        for(ConfigDef configDef : configDefs) {
+            if("global-properties".equals(configDef.getName())) {
+                setGlobalConfigDef(configDef);
+            }
+        }
+    }
+
+    
+    @Override
+    public String execute() {
+        return INPUT;
+    }
+    
+    
+    public String save() {
+        
+        log.debug("Handling update request");
+        
+        try {
+            // only set values for properties that are already defined
+            String propName = null;
+            RuntimeConfigProperty updProp = null;
+            String incomingProp = null;
+            Iterator propsIT = getProperties().keySet().iterator();
+            while(propsIT.hasNext()) {
+                propName = (String) propsIT.next();
+                
+                log.debug("Checking property ["+propName+"]");
+                
+                updProp = (RuntimeConfigProperty) getProperties().get(propName);
+                String[] propValues = (String[]) this.parameters.get(updProp.getName());
+                if(propValues != null && propValues.length > 0) {
+                    // we don't deal with multi-valued props
+                    incomingProp = propValues[0];
+                }
+                
+                // some special treatment for booleans
+                // this is a bit hacky since we are assuming that any prop
+                // with a value of "true" or "false" is meant to be a boolean
+                // it may not always be the case, but we should be okay for now
+                if( updProp.getValue() != null // null check needed w/Oracle
+                        && (updProp.getValue().equals("true") || updProp.getValue().equals("false"))) {
+                    
+                    if(incomingProp == null || !incomingProp.equals("on"))
+                        incomingProp = "false";
+                    else
+                        incomingProp = "true";
+                }
+                
+                // only work on props that were submitted with the request
+                if(incomingProp != null) {
+                    log.debug("Setting new value for ["+propName+"]");
+                    
+                    updProp.setValue(incomingProp.trim());
+                }
+            }
+            
+            // save it
+            PropertiesManager pMgr = AggregatorFactory.getAggregator().getPropertiesManager();
+            pMgr.saveProperties(getProperties());
+            AggregatorFactory.getAggregator().flush();
+            
+            addMessage("GlobalConfig.message.saveSucceeded");
+            
+            // Clear cache entries associated with website
+            CacheManager.clear();
+            
+        } catch (PlanetException e) {
+            log.error(e);
+            addError("GlobalConfig.error.saveFailed");
+        }
+        
+        return INPUT;
+    }
+
+    
+    public Map getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(Map parameters) {
+        this.parameters = parameters;
+    }
+
+    public Map getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Map properties) {
+        this.properties = properties;
+    }
+
+    public ConfigDef getGlobalConfigDef() {
+        return globalConfigDef;
+    }
+
+    public void setGlobalConfigDef(ConfigDef globalConfigDef) {
+        this.globalConfigDef = globalConfigDef;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/ModifyUser.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/ModifyUser.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/ModifyUser.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/ModifyUser.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,226 @@
+/*
+ * 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.ui.struts2.admin;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.planet.PlanetException;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.business.UserManager;
+import org.apache.roller.planet.pojos.PlanetPermission;
+import org.apache.roller.planet.pojos.User;
+import org.apache.roller.planet.ui.core.PlanetContext;
+import org.apache.roller.planet.ui.struts2.util.UIAction;
+
+
+/**
+ * Action that allows an admin to modify a users profile.
+ */
+public class ModifyUser extends UIAction {
+    
+    private static Log log = LogFactory.getLog(ModifyUser.class);
+    
+    // user we are modifying
+    private User user = new User();
+    
+    // a bean to store our form data
+    private CreateUserBean bean = new CreateUserBean();
+    
+    private String userName = null;
+    
+    
+    public ModifyUser() {
+        this.pageTitle = "ModifyUser.title";
+    }
+    
+    
+    @Override
+    public String requiredUserRole() {
+        return "admin";
+    }
+    
+    @Override
+    public boolean isPlanetRequired() { 
+        return false;
+    }
+    
+    
+    // prepare for action by loading user object we are modifying
+    @Override
+    public void myPrepare() {
+        
+        // load the user object we are modifying
+        if(getUserName() != null) {
+            try {
+                UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+                
+                // use enabled = 'null' to get both enabled and disabled users
+                setUser(mgr.getUserByUserName(getUserName(), null));
+                
+            } catch(Exception e) {
+                log.error("Error looking up user - "+getUserName(), e);
+            }
+        } else if(getBean().getId() != null) {
+            try {
+                UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+                setUser(mgr.getUser(getBean().getId()));
+            } catch(Exception e) {
+                log.error("Error looking up user - "+getBean().getId(), e);
+            }
+        }
+    }
+    
+    
+    /**
+     * Show admin user edit page.
+     */
+    @Override
+    public String execute() {
+        
+        if (getUser() != null && getUser().getId() != null) {
+            // populate form data from user profile data
+            getBean().copyFrom(getUser(), getLocale());
+        } else {
+            addError("userAdmin.error.userNotFound");
+            return ERROR;
+        }
+
+        return INPUT;
+    }
+    
+    
+    /**
+     * Save modified user profile.
+     */
+    public String save() {
+        
+        // custom validation
+        myValidate();
+        
+        if (!hasActionErrors()) {
+            
+            getBean().copyTo(getUser(), getLocale());
+            
+            // reset password if set
+            if (!StringUtils.isEmpty(getBean().getPassword())) {
+                try {
+                    getUser().resetPassword(getBean().getPassword());
+                } catch (Throwable e) {
+                    addMessage("yourProfile.passwordResetError");
+                }
+            }
+            
+            try {
+                UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+                
+                // grant/revoke admin role if needed
+                if (getUser().hasRole("admin") && !getBean().isAdministrator()) {
+                    
+                    if (!isUserEditingSelf()) {
+                        // revoke role
+                        mgr.revokeRole("admin", getUser());
+                    } else {
+                        addError("userAdmin.cantChangeOwnRole");
+                    }
+                    
+                } else if(!getUser().hasRole("admin") && getBean().isAdministrator()) {
+                    
+                    if (!isUserEditingSelf()) {
+                        // grant role
+                        getUser().grantRole("admin");
+                    } else {
+                        addError("userAdmin.cantChangeOwnRole"); 
+                    }
+                    
+                }
+            
+                PlanetContext.flushAuthenticationUserCache(getUser().getUserName());
+
+                // save the updated profile
+                mgr.saveUser(getUser());
+                AggregatorFactory.getAggregator().flush();
+                
+                addMessage("userAdmin.userSaved");
+                                
+                return INPUT;
+                
+            } catch (PlanetException ex) {
+                log.error("ERROR in action", ex);
+                // TODO: i18n
+                addError("userAdmin.error.unexpectedError");
+            }
+            
+        }
+        
+        return INPUT;
+    }
+    
+    
+    // TODO: replace with struts2 validation
+    private void myValidate() {
+        
+        if(getUser().getId() == null) {
+            addError("userAdmin.error.userNotFound");
+        }
+        if (StringUtils.isEmpty(getBean().getEmailAddress())) {
+            addError("error.add.user.missingEmailAddress");
+        }
+    }
+    
+    
+    public CreateUserBean getBean() {
+        return bean;
+    }
+
+    public void setBean(CreateUserBean bean) {
+        this.bean = bean;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    public void setUser(User user) {
+        this.user = user;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+    
+    public boolean isUserEditingSelf() {
+        return getUser().equals(getAuthenticatedUser());
+    }
+    
+    public boolean isExistingPermissions() {
+        if(getUser() != null) {
+            return (getUser().getPermissions().size() > 0);
+        } else {
+            return false;
+        }
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/UserAdmin.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/UserAdmin.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/UserAdmin.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/UserAdmin.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,54 @@
+/*
+ * 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.ui.struts2.admin;
+
+import org.apache.roller.planet.ui.struts2.util.UIAction;
+
+
+/**
+ * Action which displays user admin search page.
+ */
+public class UserAdmin extends UIAction {
+    
+    
+    public UserAdmin() {
+        this.pageTitle = "UserAdmin.title";
+    }
+    
+    
+    @Override
+    public String requiredUserRole() {
+        return "admin";
+    }
+    
+    @Override
+    public boolean isPlanetRequired() {
+        return false;
+    }
+    
+    
+    /**
+     * Show user admin search page.
+     */
+    @Override
+    public String execute() {
+        return SUCCESS;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/package.properties
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/package.properties?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/package.properties (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/admin/package.properties Sat Jun 28 12:18:17 2008
@@ -0,0 +1,81 @@
+
+# Global Config
+
+GlobalConfig.title=Global Configuration
+
+GlobalConfig.prompt=You can set the title, description and administrator \
+information to be used in all pages and feeds generated by Roller-Planet. \
+You can also set the default group, the aggregation group that will \
+be featured on the front page of the site.
+
+GlobalConfig.siteSettings=General Settings
+GlobalConfig.name=Site Title
+GlobalConfig.description=Site Description
+GlobalConfig.adminName=Admin Name
+GlobalConfig.adminEmail=Admin Email
+GlobalConfig.absoluteUrl=Site URL
+GlobalConfig.proxyHost=Proxy Host
+GlobalConfig.proxyPort=Proxy Port
+
+GlobalConfig.userSettings=User Accounts and Registration
+GlobalConfig.registrationEnabled=Allow Registration?
+GlobalConfig.registrationUrl=External Registration Url
+
+GlobalConfig.message.saveSucceeded=Configuration saved.
+GlobalConfig.error.saveFailed=Failed to save configuration.
+
+
+# User Admin
+
+UserAdmin.title=User Administration
+UserAdmin.subtitle=Find a user to edit
+UserAdmin.prompt=Find users by typing first letters of username \
+or email address. Select user and click edit button to edit the user''s profile \
+and the user''s planets.
+
+UserAdmin.search=Username or email
+UserAdmin.button.edit=edit
+
+UserAdmin.prompt.orYouCan=Or you can
+UserAdmin.prompt.createANewUser=create a new user.
+
+
+# Create User
+
+CreateUser.title=Create User Account
+CreateUser.prompt=Create a new user, all fields are required.
+
+CreateUser.userName=User Name
+CreateUser.password=Password
+CreateUser.fullName=Full Name
+CreateUser.emailAddress=Email Address
+CreateUser.enabled=Enabled
+CreateUser.administrator=Administrator
+CreateUser.button.save=Save
+CreateUser.button.cancel=Cancel
+
+CreateUser.tip.fullName=User''s full name (with no HTML).
+CreateUser.tip.userName=A short one-word username for the user account.\
+Please limit it to simple ASCII alphanumeric characters (a-z, A-Z and 0-9), \
+and do not use HTML.
+CreateUser.tip.password=User''s password.
+CreateUser.tip.email=Valid email address neeeded for automated notification.
+CreateUser.tip.enabled=Disabled users are unable to login to Roller.
+
+
+# Modify User
+
+ModifyUser.title=Edit Profile
+ModifyUser.subtitle=Editing profile and permissions for user <span>{0}</span>
+ModifyUser.prompt=You can change a user''s profile, give them \
+global admin privileges or disable them. \
+NOTE: You can also reset a users password here, but if they use Roller''s \
+remember me feature, they may have to clear browser cookies before they can \
+login again.
+
+ModifyUser.userPlanets=Users Planets
+ModifyUser.userMemberOf=User is a member of the following planet(s)
+ModifyUser.userHasNoPlanets=User is a member of no planets.
+ModifyUser.config=Configuration
+ModifyUser.groups=Manage Groups
+

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/ajax/UserDataServlet.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/ajax/UserDataServlet.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/ajax/UserDataServlet.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/ajax/UserDataServlet.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,84 @@
+/*
+ * 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.ui.struts2.ajax;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.roller.planet.PlanetException;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.business.UserManager;
+import org.apache.roller.planet.pojos.User;
+
+
+/**
+ * Return list of users matching a startsWith strings. <br />
+ * Accepts request params (none required):<br />
+ *     startsWith: string to be matched against username and email address<br />
+ *     enabled: true include only enabled users (default: no restriction<br />
+ *     offset: offset into results (for paging)<br />
+ *     length: number of users to return (max is 50)<br /><br />
+ * List format:<br />
+ *     username0, emailaddress0 <br/>
+ *     username1, emailaddress1 <br/>
+ *     username2, emailaddress2 <br/>
+ *     usernameN, emailaddressN <br/>
+ */
+public class UserDataServlet extends HttpServlet {
+    
+    private final int MAX_LENGTH = 50;
+    
+    @Override
+    public void doGet(HttpServletRequest request, 
+                      HttpServletResponse response)
+            throws ServletException, IOException {
+        
+        String startsWith = request.getParameter("startsWith");
+        Boolean enabledOnly = null;
+        int offset = 0;
+        int length = MAX_LENGTH;
+        if ("true".equals(request.getParameter("enabled"))) enabledOnly = Boolean.TRUE;
+        if ("false".equals(request.getParameter("enabled"))) enabledOnly = Boolean.FALSE;
+        try { offset = Integer.parseInt(request.getParameter("offset"));
+        } catch (Throwable ignored) {}
+        try { length = Integer.parseInt(request.getParameter("length"));
+        } catch (Throwable ignored) {}
+        
+        try {
+            UserManager umgr = AggregatorFactory.getAggregator().getUserManager();
+            List users =
+                    umgr.getUsersStartingWith(startsWith, enabledOnly, offset, length);
+            Iterator userIter = users.iterator();
+            while (userIter.hasNext()) {
+                User user = (User)userIter.next();
+                response.getWriter().print(user.getUserName());
+                response.getWriter().print(",");
+                response.getWriter().println(user.getEmailAddress());
+            }
+            response.flushBuffer();
+        } catch (PlanetException e) {
+            throw new ServletException(e.getMessage());
+        }
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanet-validation.xml
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanet-validation.xml?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanet-validation.xml (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanet-validation.xml Sat Jun 28 12:18:17 2008
@@ -0,0 +1,34 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+       "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+    
+    <field name="bean.handle">
+        <field-validator type="requiredstring">
+            <message key="CreatePlanet.error.handleNull">unspecified key</message>
+        </field-validator>
+        
+        <field-validator type="stringlength">
+            <param name="maxLength">255</param>
+            <message key="CreatePlanet.error.handleSize">unspecified key</message>
+        </field-validator>
+    </field>
+    
+    <field name="bean.title">
+        <field-validator type="requiredstring">
+            <message key="CreatePlanet.error.titleNull">unspecified key</message>
+        </field-validator>
+        
+        <field-validator type="stringlength">
+            <param name="maxLength">255</param>
+            <message key="CreatePlanet.error.titleSize">unspecified key</message>
+        </field-validator>
+    </field>
+    
+    <field name="bean.description">
+        <field-validator type="stringlength">
+            <param name="maxLength">255</param>
+            <message key="CreatePlanet.error.descriptionSize">unspecified key</message>
+        </field-validator>
+    </field>
+    
+</validators>

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanet.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanet.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanet.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanet.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,145 @@
+/*
+ * 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.ui.struts2.core;
+
+import org.apache.commons.lang.CharSetUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.planet.PlanetException;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.business.PlanetManager;
+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.ui.struts2.util.UIAction;
+import org.apache.roller.planet.util.cache.CacheManager;
+import org.apache.struts2.interceptor.validation.SkipValidation;
+
+
+/**
+ * Allows user to create a new website.
+ */
+public class CreatePlanet extends UIAction {
+    
+    private static Log log = LogFactory.getLog(CreatePlanet.class);
+    
+    private CreatePlanetBean bean = new CreatePlanetBean();
+    
+
+    public CreatePlanet() {
+        this.pageTitle = "CreatePlanet.pageTitle";
+    }
+    
+    
+    // override default security, we do not require an action weblog
+    @Override
+    public boolean isPlanetRequired() {
+        return false;
+    }
+    
+    
+    @SkipValidation
+    @Override
+    public String execute() {
+        return INPUT;
+    }
+    
+    
+    public String save() {
+        
+        myValidate();
+        
+        if (!hasActionErrors()) {
+            try {
+                Planet newPlanet = new Planet(getBean().getHandle(), 
+                        getBean().getTitle(), 
+                        getBean().getDescription());
+
+                // add new planet
+                PlanetManager pmgr = AggregatorFactory.getAggregator().getPlanetManager();
+                pmgr.savePlanet(newPlanet);
+
+                // make user an admin member
+                UserManager umgr = AggregatorFactory.getAggregator().getUserManager();
+                PlanetPermission perms = new PlanetPermission();
+                perms.setUser(getAuthenticatedUser());
+                perms.setPlanet(newPlanet);
+                perms.setPermissionMask(PlanetPermission.ADMIN);
+                perms.setPending(false);
+                umgr.savePermissions(perms);
+                
+                // flush
+                AggregatorFactory.getAggregator().flush();
+
+                // tell the user their planet was created
+                addMessage("CreatePlanet.created", getBean().getTitle());
+                
+                // Clear cache entries associated with planet
+                CacheManager.invalidate(newPlanet);
+            
+                return SUCCESS;
+                
+            } catch (PlanetException e) {
+                log.error("ERROR adding planet", e);
+                addError("CreatePlanet.error.unexpected");
+            }
+        }
+        
+        return INPUT;
+    }
+    
+    
+    public void myValidate()  {
+        
+        String allowed = getPlanetConfig().getProperty("username.allowedChars");
+        if(allowed == null || allowed.trim().length() == 0) {
+            allowed = Register.DEFAULT_ALLOWED_CHARS;
+        }
+        
+        // make sure handle only contains safe characters
+        String safe = CharSetUtils.keep(getBean().getHandle(), allowed);
+        if (!safe.equals(getBean().getHandle()) ) {
+            addError("CreatePlanet.error.invalidHandle", Register.DEFAULT_ALLOWED_CHARS);
+        }
+        
+        // make sure handle isn't already taken
+        if(!StringUtils.isEmpty(getBean().getHandle())) try {
+            PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
+            if (mgr.getPlanet(getBean().getHandle()) != null) {
+                addError("CreatePlanet.error.handleExists");
+                // reset handle
+                getBean().setHandle(null);
+            }
+        } catch (PlanetException ex) {
+            log.error("error checking for weblog", ex);
+            addError("CreatePlanet.error.unexpected");
+        }
+    }
+    
+    
+    public CreatePlanetBean getBean() {
+        return bean;
+    }
+
+    public void setBean(CreatePlanetBean bean) {
+        this.bean = bean;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanetBean.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanetBean.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanetBean.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/CreatePlanetBean.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,56 @@
+/*
+ * 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.ui.struts2.core;
+
+
+/**
+ * form bean use by CreatePlanet action.
+ */
+public class CreatePlanetBean {
+    
+    private String handle;
+    private String title;
+    private String description;
+    
+    
+    public String getHandle() {
+        return handle;
+    }
+    
+    public void setHandle(String handle) {
+        this.handle = handle;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+    
+    public String getDescription() {
+        return description;
+    }
+    
+    public void setDescription(String description) {
+        this.description = description;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/Login.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/Login.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/Login.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/Login.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,76 @@
+/*
+ * 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.ui.struts2.core;
+
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.ui.struts2.util.UIAction;
+
+
+/**
+ * Handle user logins.
+ */
+public class Login extends UIAction {
+    
+    private String error = null;
+    
+    
+    public Login() {
+        this.pageTitle = "Login.title";
+    }
+    
+    
+    @Override
+    public boolean isEnabled() {
+        return ( ! AggregatorFactory.getAggregator().getConfig().getBooleanProperty("authentication.external.enabled") );
+    }
+    
+    // override default security, we do not require an authenticated user
+    @Override
+    public boolean isUserRequired() {
+        return false;
+    }
+    
+    // override default security, we do not require an action weblog
+    @Override
+    public boolean isPlanetRequired() {
+        return false;
+    }
+    
+    
+    @Override
+    public String execute() {
+        
+        // set action error message if there was login error
+        if(getError() != null) {
+            addError("error.password.mismatch");
+        }
+        
+        return SUCCESS;
+    }
+
+    
+    public String getError() {
+        return error;
+    }
+
+    public void setError(String error) {
+        this.error = error;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/MainMenu.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/MainMenu.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/MainMenu.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/MainMenu.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,176 @@
+/*
+ * 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.ui.struts2.core;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.planet.PlanetException;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.business.PlanetManager;
+import org.apache.roller.planet.business.UserManager;
+import org.apache.roller.planet.pojos.PlanetPermission;
+import org.apache.roller.planet.pojos.User;
+import org.apache.roller.planet.pojos.Planet;
+import org.apache.roller.planet.ui.struts2.util.UIAction;
+
+
+/**
+ * Allows user to view and pick from list of his/her websites.
+ */
+public class MainMenu extends UIAction {
+    
+    private static Log log = LogFactory.getLog(MainMenu.class);
+    
+    private String planetId = null;
+    private String inviteId = null;
+    
+    
+    public MainMenu() {
+        this.pageTitle = "MainMenu.title";
+    }
+    
+    
+    // override default security, we do not require an action planet
+    @Override
+    public boolean isPlanetRequired() {
+        return false;
+    }
+    
+    
+    @Override
+    public String execute() {
+        
+        return SUCCESS;
+    }
+    
+    
+    public String accept() {
+        
+        try {
+            UserManager userMgr = AggregatorFactory.getAggregator().getUserManager();
+            PlanetPermission perms = userMgr.getPermissions(getInviteId());
+            if (perms != null) {
+                perms.setPending(false);
+                userMgr.savePermissions(perms);
+                AggregatorFactory.getAggregator().flush();
+
+                addMessage("MainMenu.message.acceptSucceeded", perms.getPlanet().getTitle());
+            } else {
+                addError("MainMenu.permNotFound");
+            }
+        } catch (PlanetException ex) {
+            log.error("Error handling invitation accept - "+getInviteId(), ex);
+            addError("MainMenu.error.acceptFailed");
+        }
+        
+        return SUCCESS;
+    }
+    
+    
+    public String decline() {
+        
+        try {
+            UserManager userMgr = AggregatorFactory.getAggregator().getUserManager();
+            PlanetPermission perms = userMgr.getPermissions(getInviteId());
+            if (perms != null) {
+                Planet planet = perms.getPlanet();
+                
+                userMgr.removePermissions(perms);
+                AggregatorFactory.getAggregator().flush();
+
+                addMessage("MainMenu.message.declineSucceeded", planet.getTitle());
+            } else {
+                addError("MainMenu.permNotFound");
+            }
+        } catch (PlanetException ex) {
+            log.error("Error handling invitation decline - "+getInviteId(), ex);
+            addError("MainMenu.error.declineFailed");
+        }
+        
+        return SUCCESS;
+    }
+    
+    
+    public String resign() {
+        
+        User user = getAuthenticatedUser();
+        
+        try {
+            PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
+            Planet planet = mgr.getPlanetById(getPlanetId());
+            
+            UserManager userMgr = AggregatorFactory.getAggregator().getUserManager();
+            PlanetPermission perms = userMgr.getPermissions(planet, user);
+            
+            if (perms != null) {
+                userMgr.removePermissions(perms);
+                AggregatorFactory.getAggregator().flush();
+            }
+            
+            addMessage("MainMenu.message.resignSucceeded", planet.getTitle());
+            
+        } catch (PlanetException ex) {
+            log.error("Error doing planet resign - "+getPlanetId(), ex);
+            addError("MainMenu.error.resignFailed");
+        }
+        
+        return SUCCESS;
+    }
+    
+    
+    public List getExistingPermissions() {
+        try {
+            UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+            return mgr.getAllPermissions(getAuthenticatedUser());
+        } catch(Exception e) {
+            log.error("Error getting permissions list", e);
+            return Collections.EMPTY_LIST;
+        }
+    }
+    
+    public List getPendingPermissions() {
+        try {
+            UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+            return mgr.getPendingPermissions(getAuthenticatedUser());
+        } catch(Exception e) {
+            log.error("Error getting pending permissions list", e);
+            return Collections.EMPTY_LIST;
+        }
+    }
+    
+
+    public String getPlanetId() {
+        return planetId;
+    }
+
+    public void setPlanetId(String planetId) {
+        this.planetId = planetId;
+    }
+
+    public String getInviteId() {
+        return inviteId;
+    }
+
+    public void setInviteId(String inviteId) {
+        this.inviteId = inviteId;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/Profile-validation.xml
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/Profile-validation.xml?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/Profile-validation.xml (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/core/Profile-validation.xml Sat Jun 28 12:18:17 2008
@@ -0,0 +1,31 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+       "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+    
+    <field name="bean.fullName">
+        <field-validator type="requiredstring">
+            <message key="Register.error.fullNameNull">unspecified key</message>
+        </field-validator>
+        
+        <field-validator type="stringlength">
+            <param name="maxLength">255</param>
+            <message key="Register.error.fullNameSize">unspecified key</message>
+        </field-validator>
+    </field>
+    
+    <field name="bean.emailAddress">
+        <field-validator type="requiredstring">
+            <message key="Register.error.emailAddressNull">unspecified key</message>
+        </field-validator>
+        
+        <field-validator type="stringlength">
+            <param name="maxLength">255</param>
+            <message key="Register.error.emailAddressSize">unspecified key</message>
+        </field-validator>
+        
+        <field-validator type="email">
+            <message key="Register.error.emailAddressBad">unspecified key</message>
+        </field-validator>
+    </field>
+    
+</validators>