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 [9/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...

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIAction.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIAction.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIAction.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIAction.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,328 @@
+/*
+ * 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.util;
+
+import com.opensymphony.xwork2.ActionSupport;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.roller.planet.config.PlanetConfig;
+import org.apache.roller.planet.pojos.User;
+import org.apache.roller.planet.pojos.Planet;
+import org.apache.roller.planet.pojos.PlanetGroup;
+import org.apache.roller.planet.pojos.PlanetPermission;
+
+
+/**
+ * Extends the Struts2 ActionSupport class to add in support for handling an
+ * error and status success.  Other actions extending this one only need to
+ * calle setError() and setSuccess() accordingly.
+ * 
+ * NOTE: as a small convenience, all errors and messages are assumed to be keys
+ * which point to a success in a resource bundle, so we automatically call
+ * getText(key) on the param passed into setError() and setSuccess().
+ */
+public abstract class UIAction extends ActionSupport 
+        implements UIActionPreparable, UISecurityEnforced {
+    
+    // a result that sends the user to an access denied warning
+    public static final String DENIED = "access-denied";
+    
+    // a common result name used to indicate the result should list some data
+    public static final String LIST = "list";
+    
+    // the PlanetConfig we are working from
+    private PlanetConfig planetConfig = null;
+    
+    // the authenticated user accessing this action, or null if client is not logged in
+    private User authenticatedUser = null;
+    
+    // the handle of the action planet
+    private String planet = null;
+    
+    // the planet this action is intended to work on, or null if no planet specified
+    private Planet actionPlanet = null;
+    
+    // the handle of the action group
+    private String group = null;
+    
+    // the group object this action is intended to work on, or null if no group required
+    private PlanetGroup actionGroup = null;
+    
+    // action name (used by tabbed menu utility)
+    protected String actionName = null;
+    
+    // the name of the menu this action wants to show, or null for no menu
+    protected String desiredMenu = null;
+    
+    // page title
+    protected String pageTitle = null;
+    
+    
+    public void myPrepare() {
+        // no-op
+    }
+    
+    
+    // all UIActions default to "enabled"
+    public boolean isEnabled() {
+        return true;
+    }
+    
+    // default action permissions, user is required
+    public boolean isUserRequired() {
+        return true;
+    }
+    
+    // default action permissions, planet is required
+    public boolean isPlanetRequired() {
+        return true;
+    }
+    
+    // default action permissions, group is not required
+    public boolean isGroupRequired() {
+        return false;
+    }
+    
+    // default action permissions, "editor" role required
+    public String requiredUserRole() {
+        return "editor";
+    }
+    
+    // default action permissions, ADMIN required
+    public short requiredPlanetPermissions() {
+        return PlanetPermission.ADMIN;
+    }
+    
+    // convenient way to tell if user being dealt with is an admin
+    public boolean isUserIsAdmin() {
+        return getAuthenticatedUser().hasRole("admin");
+    }
+    
+    
+    public String getSiteURL() {
+        return getPlanetConfig().getProperty("site.absoluteurl");
+    }
+    
+    public String getProp(String key) {
+        String value = getPlanetConfig().getProperty(key);
+        
+        return (value == null) ? key : value;
+    }
+    
+    public boolean getBooleanProp(String key) {
+        String value = getPlanetConfig().getProperty(key);
+        
+        return (value == null) ? false : (new Boolean(value)).booleanValue();
+    }
+    
+    public int getIntProp(String key) {
+        String value = getPlanetConfig().getProperty(key);
+        
+        return (value == null) ? 0 : (new Integer(value)).intValue();
+    }
+    
+    
+    public void addError(String errorKey) {
+        addActionError(getText(errorKey));
+    }
+    
+    public void addError(String errorKey, String param) {
+        addActionError(getText(errorKey, errorKey, param));
+    }
+    
+    public void addError(String errorKey, List args) {
+        addActionError(getText(errorKey, args));
+    }
+    
+    /**
+     * This simply returns the result of hasActionErrors() but we need it
+     * because without it you can't easily check if there were errors since
+     * you can't call a hasXXX() method via OGNL.
+     */
+    public boolean errorsExist() {
+        return hasActionErrors();
+    }
+    
+    
+    public void addMessage(String msgKey) {
+        addActionMessage(getText(msgKey));
+    }
+    
+    public void addMessage(String msgKey, String param) {
+        addActionMessage(getText(msgKey, msgKey, param));
+    }
+    
+    public void addMessage(String msgKey, List args) {
+        addActionMessage(getText(msgKey, args));
+    }
+    
+    /**
+     * This simply returns the result of hasActionMessages() but we need it
+     * because without it you can't easily check if there were messages since
+     * you can't call a hasXXX() method via OGNL.
+     */
+    public boolean messagesExist() {
+        return hasActionMessages();
+    }
+    
+    
+    public PlanetConfig getPlanetConfig() {
+        return planetConfig;
+    }
+    
+    public void setPlanetConfig(PlanetConfig config) {
+        this.planetConfig = config;
+    }
+    
+    public User getAuthenticatedUser() {
+        return authenticatedUser;
+    }
+
+    public void setAuthenticatedUser(User authenticatedUser) {
+        this.authenticatedUser = authenticatedUser;
+    }
+
+    public Planet getActionPlanet() {
+        return actionPlanet;
+    }
+
+    public void setActionPlanet(Planet workingPlanet) {
+        this.actionPlanet = workingPlanet;
+    }
+
+    public String getPlanet() {
+        return planet;
+    }
+
+    public void setPlanet(String planet) {
+        this.planet = planet;
+    }
+
+    public PlanetGroup getActionGroup() {
+        return actionGroup;
+    }
+
+    public void setActionGroup(PlanetGroup actionGroup) {
+        this.actionGroup = actionGroup;
+    }
+
+    public String getGroup() {
+        return group;
+    }
+
+    public void setGroup(String group) {
+        this.group = group;
+    }
+    
+    public String getPageTitle() {
+        return getText(pageTitle);
+    }
+    
+    public String getActionName() {
+        return this.actionName;
+    }
+    
+    public void setActionName(String actionName) {
+        this.actionName = actionName;
+    }
+
+    public String getDesiredMenu() {
+        return desiredMenu;
+    }
+
+    public void setDesiredMenu(String desiredMenu) {
+        this.desiredMenu = desiredMenu;
+    }
+    
+    
+    public String getShortDateFormat() {
+        DateFormat sdf = DateFormat.getDateInstance(
+                DateFormat.SHORT, getLocale());
+        if (sdf instanceof SimpleDateFormat) {
+            return ((SimpleDateFormat)sdf).toPattern();
+        }
+        return "yyyy/MM/dd";
+    }
+    
+    public String getMediumDateFormat() {
+        DateFormat sdf = DateFormat.getDateInstance(
+                DateFormat.MEDIUM, getLocale());
+        if (sdf instanceof SimpleDateFormat) {
+            return ((SimpleDateFormat)sdf).toPattern();
+        }
+        return "MMM dd, yyyy";
+    }
+    
+    public List getLocalesList() {
+        return UIUtils.getLocales();
+    }
+    
+    public List getTimeZonesList() {
+        return UIUtils.getTimeZones();
+    }
+    
+    public List getHoursList() {
+        List ret = new ArrayList();
+        for (int i=0; i<24; i++) {
+            ret.add(i);
+        }
+        return ret;
+    }
+    
+    public List getMinutesList() {
+        List ret = new ArrayList();
+        for (int i=0; i<60; i++) {
+            ret.add(i);
+        }
+        return ret;
+    }
+    
+    public List getSecondsList() {
+        return getMinutesList();
+    }
+    
+    public List getCommentDaysList() {
+        
+        List opts = new ArrayList();
+        
+        opts.add(new KeyValueObject(new Integer(0), getText("planetEdit.unlimitedCommentDays")));
+        opts.add(new KeyValueObject(new Integer(1), getText("planetEdit.days1")));
+        opts.add(new KeyValueObject(new Integer(2), getText("planetEdit.days2")));
+        opts.add(new KeyValueObject(new Integer(3), getText("planetEdit.days3")));
+        opts.add(new KeyValueObject(new Integer(4), getText("planetEdit.days4")));
+        opts.add(new KeyValueObject(new Integer(5), getText("planetEdit.days5")));
+        opts.add(new KeyValueObject(new Integer(7), getText("planetEdit.days7")));
+        opts.add(new KeyValueObject(new Integer(10), getText("planetEdit.days10")));
+        opts.add(new KeyValueObject(new Integer(20), getText("planetEdit.days20")));
+        opts.add(new KeyValueObject(new Integer(30), getText("planetEdit.days30")));
+        opts.add(new KeyValueObject(new Integer(60), getText("planetEdit.days60")));
+        opts.add(new KeyValueObject(new Integer(90), getText("planetEdit.days90")));
+        
+        return opts;
+    }
+    
+    
+    public String escapeJavascript(String str) {
+        return StringEscapeUtils.escapeJavaScript(str);
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionInterceptor.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionInterceptor.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionInterceptor.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionInterceptor.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.planet.ui.struts2.util;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.business.PlanetManager;
+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.pojos.User;
+import org.apache.roller.planet.ui.core.PlanetContext;
+import org.apache.struts2.StrutsStatics;
+
+
+/**
+ * A struts2 interceptor for configuring specifics of the planet ui.
+ */
+public class UIActionInterceptor extends AbstractInterceptor 
+        implements StrutsStatics {
+    
+    private static Log log = LogFactory.getLog(UIActionInterceptor.class);
+    
+    
+    public String intercept(ActionInvocation invocation) throws Exception {
+        
+        log.debug("Entering UIActionInterceptor");
+        
+        final Object action = invocation.getAction();
+        final ActionContext context = invocation.getInvocationContext();
+        
+        HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
+        
+        // is this one of our own UIAction classes?
+        if (action instanceof UIAction) {
+            
+            log.debug("action is a UIAction, setting relevant attributes");
+            
+            UIAction theAction = (UIAction) action;
+            
+            // first off, lets inject our PlanetConfig
+            PlanetConfig config = AggregatorFactory.getAggregator().getConfig();
+            theAction.setPlanetConfig(config);
+            
+            // extract the authenticated user and set it
+            User authenticUser = PlanetContext.getAuthenticatedUser(request);
+            if(authenticUser != null) {
+                theAction.setAuthenticatedUser(authenticUser);
+            }
+            
+            // extract the work planet and set it
+            String planetHandle = theAction.getPlanet();
+            if(!StringUtils.isEmpty(planetHandle)) {
+                Planet planet = null;
+                try {
+                    PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
+                    planet = mgr.getPlanet(planetHandle);
+                    if(planet != null) {
+                        theAction.setActionPlanet(planet);
+                    }
+                } catch(Exception e) {
+                    log.error("Error looking up action planet - "+planetHandle, e);
+                }
+            }
+            
+            // extract the work group and set it
+            String groupHandle = theAction.getGroup();
+            if(!StringUtils.isEmpty(groupHandle) && theAction.getActionPlanet() != null) {
+                PlanetGroup group = null;
+                try {
+                    PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
+                    group = mgr.getGroup(theAction.getActionPlanet(), groupHandle);
+                    if(group != null) {
+                        theAction.setActionGroup(group);
+                    }
+                } catch(Exception e) {
+                    log.error("Error looking up action group - "+groupHandle, e);
+                }
+            }
+        }
+        
+        return invocation.invoke();
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionPreparable.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionPreparable.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionPreparable.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionPreparable.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,43 @@
+/*
+ * 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.util;
+
+
+/**
+ * A Roller specific version of the struts2 Preparable interface.
+ *
+ * We only have this because we don't want to use the struts2 Preparable IF due
+ * to the fact that it is meant to be called much earlier in the interceptor
+ * stack, namely before our custom interceptors have been processed.  While
+ * that may make sense in some cases, typically we want to prepare things based
+ * on the user or weblog that we are working on, so it's often of more use for
+ * us to prepare *after* our custom interceptors have been processed.
+ *
+ * So, this duplicate of the struts2 Preparable interface is here so that we
+ * can leave the default struts2 prepare() logic in place for any actions we
+ * may define that want to use that, but also provide a prepare option that is
+ * executed at the very end of our interceptor stack, just before the action
+ * method is executed.  This way our custom prepare method can make use of 
+ * anything our custom interceptors provide.
+ */
+public interface UIActionPreparable {
+    
+    public void myPrepare();
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionPrepareInterceptor.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionPrepareInterceptor.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionPrepareInterceptor.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIActionPrepareInterceptor.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,53 @@
+/*
+ * 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.util;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * A struts2 interceptor for doing custom prepare logic.
+ */
+public class UIActionPrepareInterceptor extends AbstractInterceptor {
+    
+    private static Log log = LogFactory.getLog(UIActionPrepareInterceptor.class);
+    
+    
+    public String intercept(ActionInvocation invocation) throws Exception {
+        
+        log.debug("Entering UIActionPrepareInterceptor");
+        
+        final Object action = invocation.getAction();
+        
+        // is this one of our own UIAction classes?
+        if (action instanceof UIActionPreparable) {
+            
+            log.debug("action is UIActionPreparable, calling myPrepare() method");
+            
+            UIActionPreparable theAction = (UIActionPreparable) action;
+            theAction.myPrepare();
+        }
+        
+        return invocation.invoke();
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UISecurityEnforced.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UISecurityEnforced.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UISecurityEnforced.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UISecurityEnforced.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,95 @@
+/*
+ * 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.util;
+
+
+/**
+ * Implemented by struts2 actions which want to enforce some level of security
+ * protection on their action.
+ * 
+ * Available enforcements are ...
+ *   - require action to be "enabled"
+ *   - require a logged in user
+ *   - reguire a valid Planet to work on
+ *   - require a specific user role, such as "admin"
+ *   - require a specific Planet permission
+ *
+ */
+public interface UISecurityEnforced {
+    
+    /**
+     * Is the action enabled for use?
+     * 
+     * NOTE: this method is the first security check that is processed, so it
+     * cannot depend on the outcome of other security checks.
+     * 
+     * @return boolean True if the action is enabled for use, false otherwise.
+     */
+    public boolean isEnabled();
+    
+    
+    /**
+     * Does the action require an authenticated user?
+     *
+     * @return boolean True if authenticated user is required, false otherwise.
+     */
+    public boolean isUserRequired();
+    
+    
+    /**
+     * Does the action require a valid Planet to work on?
+     *
+     * This only takes effect if isUserRequired() is 'true'.
+     *
+     * @return boolean True if action Planet is required, false otherwise.
+     */
+    public boolean isPlanetRequired();
+    
+    
+    /**
+     * Does the action require a valid PlanetGroup to work on?
+     *
+     * This only takes effect if isPlanetRequired() is 'true'.
+     *
+     * @return boolean True if action PlanetGroup is required, false otherwise.
+     */
+    public boolean isGroupRequired();
+    
+    
+    /**
+     * What is the required user role, if any?
+     *
+     * This method only takes effect if isUserRequired() is 'true'.
+     *
+     * @return String The required user role, or null if no role required.
+     */
+    public String requiredUserRole();
+    
+    
+    /**
+     * What are the required Planet permissions for this action, if any?
+     *
+     * This method only takes effect if both isUserRequired() and isPlanetRequired()
+     * are 'true'.
+     *
+     * @return short The required Planet permissions, or -1 if no permissions required.
+     */
+    public short requiredPlanetPermissions();
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UISecurityInterceptor.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UISecurityInterceptor.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UISecurityInterceptor.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UISecurityInterceptor.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,115 @@
+/*
+ * 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.util;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+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.pojos.Planet;
+import org.apache.roller.planet.pojos.PlanetGroup;
+
+
+/**
+ * A struts2 interceptor for configuring specifics of the planetger ui.
+ */
+public class UISecurityInterceptor extends AbstractInterceptor {
+    
+    private static Log log = LogFactory.getLog(UISecurityInterceptor.class);
+    
+    
+    public String intercept(ActionInvocation invocation) throws Exception {
+        
+        log.debug("Entering UISecurityInterceptor");
+        
+        final Object action = invocation.getAction();
+        
+        // is this one of our own UIAction classes?
+        if (action instanceof UISecurityEnforced &&
+                action instanceof UIAction) {
+            
+            log.debug("action is UISecurityEnforced ... enforcing security rules");
+            
+            final UISecurityEnforced theAction = (UISecurityEnforced) action;
+            
+            // first check, is access to this action enabled?
+            if( !theAction.isEnabled() ) {
+                log.debug("DISABLED: action is not enabled");
+                return "access-disabled";
+            }
+            
+            // are we requiring an authenticated user?
+            if(theAction.isUserRequired()) {
+                
+                User authenticatedUser = ((UIAction)theAction).getAuthenticatedUser();
+                if(authenticatedUser == null) {
+                    log.debug("DENIED: required user not found");
+                    return "access-denied";
+                }
+                
+                // are we also enforcing a specific role?
+                if(theAction.requiredUserRole() != null) {
+                    if(!authenticatedUser.hasRole(theAction.requiredUserRole())) {
+                        log.debug("DENIED: user does not have role = "+theAction.requiredUserRole());
+                        return "access-denied";
+                    }
+                }
+                
+                // are we requiring a valid action planet?
+                if(theAction.isPlanetRequired()) {
+                    
+                    Planet actionPlanet = ((UIAction)theAction).getActionPlanet();
+                    if(actionPlanet == null) {
+                        log.debug("DENIED: required action planet not found");
+                        return "access-denied";
+                    }
+                    
+                    // are we also enforcing a specific planet permission?
+                    if(theAction.requiredPlanetPermissions() > -1) {
+                        UserManager umgr = AggregatorFactory.getAggregator().getUserManager();
+                        if(!umgr.hasPermissions(authenticatedUser, actionPlanet,
+                                theAction.requiredPlanetPermissions())) {
+                            log.debug("DENIED: user does not have required planet permissions = "+
+                                    theAction.requiredPlanetPermissions());
+                            return "access-denied";
+                        }
+                    }
+                    
+                    // are we requiring a valid action group?
+                    if(theAction.isGroupRequired()) {
+                        
+                        PlanetGroup actionGroup = ((UIAction) theAction).getActionGroup();
+                        if (actionGroup == null) {
+                            log.debug("DENIED: required action group not found");
+                            return "access-denied";
+                        }
+                    }
+                }
+                
+            }
+            
+        }
+        
+        return invocation.invoke();
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIUtils.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIUtils.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIUtils.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/ui/struts2/util/UIUtils.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.util;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+
+/**
+ * A utilities class used by the Weblogger UI.
+ */
+public final class UIUtils {
+    
+    private static final List locales;
+    private static final List timeZones;
+    
+    
+    // load up the locales and time zones lists
+    static {
+        // build locales list
+        locales = Arrays.asList(Locale.getAvailableLocales());
+        Collections.sort(locales, new LocaleComparator());
+        
+        // build time zones list
+        timeZones = Arrays.asList(TimeZone.getAvailableIDs());
+        Collections.sort(timeZones);
+    }
+    
+    
+    public static List getLocales() {
+        return locales;
+    }
+    
+    
+    public static List getTimeZones() {
+        return timeZones;
+    }
+    
+    
+    // special comparator for sorting locales
+    private static final class LocaleComparator implements Comparator {
+        public int compare(Object obj1, Object obj2) {
+            if (obj1 instanceof Locale && obj2 instanceof Locale) {
+                Locale locale1 = (Locale)obj1;
+                Locale locale2 = (Locale)obj2;
+                int compName = locale1.getDisplayName().compareTo(locale2.getDisplayName());
+                if (compName == 0) {
+                    return locale1.toString().compareTo(locale2.toString());
+                }
+                return compName;
+            }
+            return 0;
+        }
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/DateUtil.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/DateUtil.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/DateUtil.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/DateUtil.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,631 @@
+/*
+ * 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.util;
+
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+import org.apache.commons.lang.StringUtils;
+
+
+/**
+ * General purpose date utilities.
+ *
+ * TODO: all date handling functions need to be aware of locale and timezone.
+ */
+public abstract class DateUtil {
+    
+    public static final long millisInDay = 86400000;
+    
+    // a bunch of date formats
+    private static final String formatDefaultDate = "dd.MM.yyyy";
+    private static final String formatDefaultDateMinimal = "d.M.yy";
+    private static final String formatDefaultTimestamp = "yyyy-MM-dd HH:mm:ss.SSS";
+    
+    private static final String formatFriendlyTimestamp = "dd.MM.yyyy HH:mm:ss";
+    
+    private static final String format6chars = "yyyyMM";
+    private static final String format8chars = "yyyyMMdd";
+    
+    private static final String formatIso8601 = "yyyy-MM-dd'T'HH:mm:ssZ";
+    private static final String formatIso8601Day = "yyyy-MM-dd";
+    
+    private static final String formatRfc822 = "EEE, d MMM yyyy HH:mm:ss Z";
+    
+    
+    /**
+     * Returns a Date set to the first possible millisecond of the day, just
+     * after midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getStartOfDay(Date day) {
+        return getStartOfDay(day, Calendar.getInstance());
+    }
+    
+    
+    /**
+     * Returns a Date set to the first possible millisecond of the day, just
+     * after midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getStartOfDay(Date day, Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
+        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the last possible millisecond of the day, just
+     * before midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getEndOfDay(Date day) {
+        return getEndOfDay(day,Calendar.getInstance());
+    }
+    
+    
+    public static Date getEndOfDay(Date day,Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
+        cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the first possible millisecond of the hour.
+     * If a null day is passed in, a new Date is created.
+     */
+    public static Date getStartOfHour(Date day) {
+        return getStartOfHour(day, Calendar.getInstance());
+    }
+    
+    
+    /**
+     * Returns a Date set to the first possible millisecond of the hour.
+     * If a null day is passed in, a new Date is created.
+     */
+    public static Date getStartOfHour(Date day, Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the last possible millisecond of the day, just
+     * before midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getEndOfHour(Date day) {
+        return getEndOfHour(day, Calendar.getInstance());
+    }
+    
+    
+    public static Date getEndOfHour(Date day, Calendar cal) {
+        if (day == null || cal == null) {
+            return day;
+        }
+        
+        cal.setTime(day);
+        cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the first possible millisecond of the minute.
+     * If a null day is passed in, a new Date is created.
+     */
+    public static Date getStartOfMinute(Date day) {
+        return getStartOfMinute(day, Calendar.getInstance());
+    }
+    
+    
+    /**
+     * Returns a Date set to the first possible millisecond of the minute.
+     * If a null day is passed in, a new Date is created.
+     */
+    public static Date getStartOfMinute(Date day, Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the last possible millisecond of the minute.
+     * If a null day is passed in, a new Date is created.
+     */
+    public static Date getEndOfMinute(Date day) {
+        return getEndOfMinute(day, Calendar.getInstance());
+    }
+    
+    
+    public static Date getEndOfMinute(Date day, Calendar cal) {
+        if (day == null || cal == null) {
+            return day;
+        }
+        
+        cal.setTime(day);
+        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the first possible millisecond of the month, just
+     * after midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getStartOfMonth(Date day) {
+        return getStartOfMonth(day, Calendar.getInstance());
+    }
+    
+    
+    public static Date getStartOfMonth(Date day, Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        
+        // set time to start of day
+        cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
+        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
+        
+        // set time to first day of month
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+        
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set to the last possible millisecond of the month, just
+     * before midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getEndOfMonth(Date day) {
+        return getEndOfMonth(day, Calendar.getInstance());
+    }
+    
+    
+    public static Date getEndOfMonth(Date day,Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        
+        // set time to end of day
+        cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
+        cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
+        
+        // set time to first day of month
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+        
+        // add one month
+        cal.add(Calendar.MONTH, 1);
+        
+        // back up one day
+        cal.add(Calendar.DAY_OF_MONTH, -1);
+        
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a Date set just to Noon, to the closest possible millisecond
+     * of the day. If a null day is passed in, a new Date is created.
+     * nnoon (00m 12h 00s)
+     */
+    public static Date getNoonOfDay(Date day, Calendar cal) {
+        if (day == null) day = new Date();
+        cal.setTime(day);
+        cal.set(Calendar.HOUR_OF_DAY, 12);
+        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
+     * Returns a java.sql.Timestamp equal to the current time
+     **/
+    public static java.sql.Timestamp now() {
+        return new java.sql.Timestamp(new java.util.Date().getTime());
+    }
+    
+    
+    /**
+     * Returns a string the represents the passed-in date parsed
+     * according to the passed-in format.  Returns an empty string
+     * if the date or the format is null.
+     **/
+    public static String format(Date aDate, SimpleDateFormat aFormat) {
+        if (aDate == null || aFormat == null ) { return ""; }
+        synchronized (aFormat) {
+            return aFormat.format(aDate);
+        }
+    }
+    
+    
+    /**
+     * Returns a Date using the passed-in string and format.  Returns null if the string
+     * is null or empty or if the format is null.  The string must match the format.
+     **/
+    public static Date parse(String aValue, SimpleDateFormat aFormat) throws ParseException {
+        if (StringUtils.isEmpty(aValue) || aFormat == null) {
+            return null;
+        }
+        synchronized(aFormat) {
+            return aFormat.parse(aValue);
+        }
+    }
+    
+    
+    /**
+     * Returns true if endDate is after startDate or if startDate equals endDate
+     * or if they are the same date.  Returns false if either value is null.
+     **/
+    public static boolean isValidDateRange(Date startDate, Date endDate) {
+        return isValidDateRange(startDate, endDate, true);
+    }
+    
+    
+    /**
+     * Returns true if endDate is after startDate or if startDate equals endDate.
+     * Returns false if either value is null.  If equalOK, returns true if the
+     * dates are equal.
+     **/
+    public static boolean isValidDateRange(Date startDate, Date endDate, boolean equalOK) {
+        // false if either value is null
+        if (startDate == null || endDate == null) { return false; }
+        
+        if (equalOK) {
+            // true if they are equal
+            if (startDate.equals(endDate)) { return true; }
+        }
+        
+        // true if endDate after startDate
+        if (endDate.after(startDate)) { return true; }
+        
+        return false;
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat defaultDateFormat() {
+        return DateUtil.friendlyDateFormat(true);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static java.text.SimpleDateFormat minimalDateFormat() {
+        return friendlyDateFormat(true);
+    }
+    
+    
+    // convenience method that returns friendly data format
+    // using full month, day, year digits.
+    public static SimpleDateFormat fullDateFormat() {
+        return friendlyDateFormat(false);
+    }
+    
+    
+    /** 
+     * Returns a "friendly" date format.
+     * @param mimimalFormat Should the date format allow single digits.
+     **/
+    public static SimpleDateFormat friendlyDateFormat(boolean minimalFormat) {
+        if (minimalFormat) {
+            return new SimpleDateFormat(formatDefaultDateMinimal);
+        }
+        
+        return new SimpleDateFormat(formatDefaultDate);
+    }
+    
+    
+    // returns full timestamp format
+    public static SimpleDateFormat defaultTimestampFormat() {
+        return new SimpleDateFormat(formatDefaultTimestamp);
+    }
+    
+    
+    // convenience method returns long friendly timestamp format
+    public static SimpleDateFormat friendlyTimestampFormat() {
+        return new SimpleDateFormat(formatFriendlyTimestamp);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat get8charDateFormat() {
+        return new SimpleDateFormat(format8chars);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat get6charDateFormat() {
+        return new SimpleDateFormat(format6chars);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat getIso8601DateFormat() {
+        return new SimpleDateFormat(formatIso8601);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat getIso8601DayDateFormat() {
+        return new SimpleDateFormat(formatIso8601Day);
+    }
+    
+    
+    // convenience method returns minimal date format
+    public static SimpleDateFormat getRfc822DateFormat() {
+        // http://www.w3.org/Protocols/rfc822/Overview.html#z28
+        // Using Locale.US to fix ROL-725 and ROL-628
+        return new SimpleDateFormat(formatRfc822, Locale.US);
+    }
+    
+    
+    // convenience method
+    public static String defaultDate(Date date) {
+        return format(date, defaultDateFormat());
+    }
+    
+    
+    // convenience method using minimal date format
+    public static String minimalDate(Date date) {
+        return format(date, DateUtil.minimalDateFormat());
+    }
+    
+    
+    public static String fullDate(Date date) {
+        return format(date, DateUtil.fullDateFormat());
+    }
+    
+    
+    /**
+     * Format the date using the "friendly" date format.
+     */
+    public static String friendlyDate(Date date, boolean minimalFormat) {
+        return format(date, friendlyDateFormat(minimalFormat));
+    }
+    
+    
+    // convenience method
+    public static String friendlyDate(Date date) {
+        return format(date, friendlyDateFormat(true));
+    }
+    
+    
+    // convenience method
+    public static String defaultTimestamp(Date date) {
+        return format(date, defaultTimestampFormat());
+    }
+    
+    
+    // convenience method returns long friendly formatted timestamp
+    public static String friendlyTimestamp(Date date) {
+        return format(date, friendlyTimestampFormat());
+    }
+    
+    
+    // convenience method returns 8 char day stamp YYYYMMDD
+    public static String format8chars(Date date) {
+        return format(date, get8charDateFormat());
+    }
+    
+    
+    // convenience method returns 6 char month stamp YYYYMM
+    public static String format6chars(Date date) {
+        return format(date, get6charDateFormat());
+    }
+    
+    
+    // convenience method returns long friendly formatted timestamp
+    public static String formatIso8601Day(Date date) {
+        return format(date, getIso8601DayDateFormat());
+    }
+    
+    
+    public static String formatRfc822(Date date) {
+        return format(date, getRfc822DateFormat());
+    }
+    
+    
+    // This is a hack, but it seems to work
+    public static String formatIso8601(Date date) {
+        if (date == null) return "";
+        
+        // Add a colon 2 chars before the end of the string
+        // to make it a valid ISO-8601 date.
+        
+        String str = format(date, getIso8601DateFormat());
+        StringBuffer sb = new StringBuffer();
+        sb.append( str.substring(0,str.length()-2) );
+        sb.append( ":" );
+        sb.append( str.substring(str.length()-2) );
+        return sb.toString();
+    }
+    
+    
+    /**
+     * This was the original ISO8601 formatter from our ISO8601DateParser class.
+     * I don't know why it was replaced with the above method, but it was.
+    public static String toString( Date date ) {
+        
+        SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssz" );
+        
+        TimeZone tz = TimeZone.getTimeZone( "UTC" );
+        
+        df.setTimeZone( tz );
+
+        String output = df.format( date );
+
+        int inset0 = 9;
+        int inset1 = 6;
+        
+        String s0 = output.substring( 0, output.length() - inset0 );
+        String s1 = output.substring( output.length() - inset1, output.length() );
+
+        String result = s0 + s1;
+
+        result = result.replaceAll( "UTC", "+00:00" );
+        
+        return result;
+        
+    }*/
+    
+    
+    // 2004-06-14T19:GMT20:30Z
+    // 2004-06-20T06:GMT22:01Z
+
+    // http://www.cl.cam.ac.uk/~mgk25/iso-time.html
+    //    
+    // http://www.intertwingly.net/wiki/pie/DateTime
+    //
+    // http://www.w3.org/TR/NOTE-datetime
+    //
+    // Different standards may need different levels of granularity in the date and
+    // time, so this profile defines six levels. Standards that reference this
+    // profile should specify one or more of these granularities. If a given
+    // standard allows more than one granularity, it should specify the meaning of
+    // the dates and times with reduced precision, for example, the result of
+    // comparing two dates with different precisions.
+
+    // The formats are as follows. Exactly the components shown here must be
+    // present, with exactly this punctuation. Note that the "T" appears literally
+    // in the string, to indicate the beginning of the time element, as specified in
+    // ISO 8601.
+
+    //    Year:
+    //       YYYY (eg 1997)
+    //    Year and month:
+    //       YYYY-MM (eg 1997-07)
+    //    Complete date:
+    //       YYYY-MM-DD (eg 1997-07-16)
+    //    Complete date plus hours and minutes:
+    //       YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
+    //    Complete date plus hours, minutes and seconds:
+    //       YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
+    //    Complete date plus hours, minutes, seconds and a decimal fraction of a
+    // second
+    //       YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
+
+    // where:
+
+    //      YYYY = four-digit year
+    //      MM   = two-digit month (01=January, etc.)
+    //      DD   = two-digit day of month (01 through 31)
+    //      hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
+    //      mm   = two digits of minute (00 through 59)
+    //      ss   = two digits of second (00 through 59)
+    //      s    = one or more digits representing a decimal fraction of a second
+    //      TZD  = time zone designator (Z or +hh:mm or -hh:mm)
+    public static Date parseIso8601( String input ) throws java.text.ParseException {
+
+        //NOTE: SimpleDateFormat uses GMT[-+]hh:mm for the TZ which breaks
+        //things a bit.  Before we go on we have to repair this.
+        SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssz" );
+        
+        //this is zero time so we need to add that TZ indicator for 
+        if ( input.endsWith( "Z" ) ) {
+            input = input.substring( 0, input.length() - 1) + "GMT-00:00";
+        } else {
+            int inset = 6;
+        
+            String s0 = input.substring( 0, input.length() - inset );
+            String s1 = input.substring( input.length() - inset, input.length() );
+
+            input = s0 + "GMT" + s1;
+        }
+        
+        return df.parse( input );
+        
+    }
+    
+    
+    /**
+     * Parse data as either 6-char or 8-char format.
+     */
+    public static Date parseWeblogURLDateString(String dateString, TimeZone tz, Locale locale) {
+        
+        Date ret = new Date();
+        SimpleDateFormat char8DateFormat = DateUtil.get8charDateFormat();
+        SimpleDateFormat char6DateFormat = DateUtil.get6charDateFormat();
+        
+        if (dateString != null
+                && dateString.length()==8
+                && StringUtils.isNumeric(dateString) ) {
+            ParsePosition pos = new ParsePosition(0);
+            ret = char8DateFormat.parse(dateString, pos);
+            
+            // make sure the requested date is not in the future
+            Date today = null;
+            Calendar todayCal = Calendar.getInstance();
+            todayCal = Calendar.getInstance(tz, locale);
+            todayCal.setTime(new Date());
+            today = todayCal.getTime();
+            if(ret.after(today)) {
+                ret = today;
+            }
+            
+        } else if(dateString != null
+                && dateString.length()==6
+                && StringUtils.isNumeric(dateString)) {
+            ParsePosition pos = new ParsePosition(0);
+            ret = char6DateFormat.parse(dateString, pos);
+            
+            // make sure the requested date is not in the future
+            Calendar todayCal = Calendar.getInstance();
+            todayCal = Calendar.getInstance(tz, locale);
+            todayCal.setTime(new Date());
+            Date today = todayCal.getTime();
+            if(ret.after(today)) {
+                ret = today;
+            }
+        }
+        
+        return ret;
+    }
+    
+}

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/MailUtil.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/MailUtil.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/MailUtil.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/MailUtil.java Sat Jun 28 12:18:17 2008
@@ -1,25 +1,25 @@
 /*
-* 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.
-*/
+ * 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.util;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
 import javax.mail.Message;
 import javax.mail.MessagingException;
 import javax.mail.SendFailedException;
@@ -30,13 +30,15 @@
 import javax.mail.internet.MimeMessage;
 import org.apache.commons.lang.StringUtils;
 
+
+/**
+ * Mail utility class used to help with sending emails via javax.mail.
+ */
 public class MailUtil extends Object {
-   
-	private static Log mLogger = 
-		LogFactory.getFactory().getInstance(MailUtil.class);
 
-    // agangolli: Incorporated suggested changes from Ken Blackler.
+    private static Log log = LogFactory.getLog(MailUtil.class);
 
+    // agangolli: Incorporated suggested changes from Ken Blackler.
     /**
      * This method is used to send a Message with a pre-defined
      * mime-type.
@@ -48,97 +50,95 @@
      * @param mimeType type of message, i.e. text/plain or text/html
      * @throws MessagingException the exception to indicate failure
      */
-    public static void sendMessage
-    (
-    	Session session,
-        String from,
-        String[] to,
-        String[] cc,
-        String[] bcc,
-        String subject,
-        String content,
-        String mimeType
-    ) 
-    throws MessagingException
-    {
+    public static void sendMessage(
+            Session session,
+            String from,
+            String[] to,
+            String[] cc,
+            String[] bcc,
+            String subject,
+            String content,
+            String mimeType)
+            throws MessagingException {
         Message message = new MimeMessage(session);
 
         // n.b. any default from address is expected to be determined by caller.
-        if (! StringUtils.isEmpty(from)) {
-			InternetAddress sentFrom = new InternetAddress(from);
-			message.setFrom(sentFrom);
-			if (mLogger.isDebugEnabled()) mLogger.debug("e-mail from: " + sentFrom);
-        }
-
-		if (to!=null)
-		{
-			InternetAddress[] sendTo = new InternetAddress[to.length];
-	
-			for (int i = 0; i < to.length; i++) 
-			{
-				sendTo[i] = new InternetAddress(to[i]);
-				if (mLogger.isDebugEnabled()) mLogger.debug("sending e-mail to: " + to[i]);
-			}
-			message.setRecipients(Message.RecipientType.TO, sendTo);
-		}
-
-		if (cc != null) 
-		{
-			InternetAddress[] copyTo = new InternetAddress[cc.length];
-
-			for (int i = 0; i < cc.length; i++) 
-			{
-				copyTo[i] = new InternetAddress(cc[i]);
-				if (mLogger.isDebugEnabled()) mLogger.debug("copying e-mail to: " + cc[i]);
-			}
-			message.setRecipients(Message.RecipientType.CC, copyTo);
-		}	        
-
-		if (bcc != null) 
-		{
-			InternetAddress[] copyTo = new InternetAddress[bcc.length];
-
-			for (int i = 0; i < bcc.length; i++) 
-			{
-				copyTo[i] = new InternetAddress(bcc[i]);
-				if (mLogger.isDebugEnabled()) mLogger.debug("blind copying e-mail to: " + bcc[i]);
-			}
-			message.setRecipients(Message.RecipientType.BCC, copyTo);
-		}	        
+        if (!StringUtils.isEmpty(from)) {
+            InternetAddress sentFrom = new InternetAddress(from);
+            message.setFrom(sentFrom);
+            if (log.isDebugEnabled()) {
+                log.debug("e-mail from: " + sentFrom);
+            }
+        }
+
+        if (to != null) {
+            InternetAddress[] sendTo = new InternetAddress[to.length];
+
+            for (int i = 0; i < to.length; i++) {
+                sendTo[i] = new InternetAddress(to[i]);
+                if (log.isDebugEnabled()) {
+                    log.debug("sending e-mail to: " + to[i]);
+                }
+            }
+            message.setRecipients(Message.RecipientType.TO, sendTo);
+        }
+
+        if (cc != null) {
+            InternetAddress[] copyTo = new InternetAddress[cc.length];
+
+            for (int i = 0; i < cc.length; i++) {
+                copyTo[i] = new InternetAddress(cc[i]);
+                if (log.isDebugEnabled()) {
+                    log.debug("copying e-mail to: " + cc[i]);
+                }
+            }
+            message.setRecipients(Message.RecipientType.CC, copyTo);
+        }
+
+        if (bcc != null) {
+            InternetAddress[] copyTo = new InternetAddress[bcc.length];
+
+            for (int i = 0; i < bcc.length; i++) {
+                copyTo[i] = new InternetAddress(bcc[i]);
+                if (log.isDebugEnabled()) {
+                    log.debug("blind copying e-mail to: " + bcc[i]);
+                }
+            }
+            message.setRecipients(Message.RecipientType.BCC, copyTo);
+        }
         message.setSubject((subject == null) ? "(no subject)" : subject);
         message.setContent(content, mimeType);
-        message.setSentDate(new java.util.Date()); 
+        message.setSentDate(new java.util.Date());
 
-		// First collect all the addresses together.
+        // First collect all the addresses together.
         Address[] remainingAddresses = message.getAllRecipients();
         int nAddresses = remainingAddresses.length;
         boolean bFailedToSome = false;
-        
+
         SendFailedException sendex = new SendFailedException("Unable to send message to some recipients");
-        
-		// Try to send while there remain some potentially good addresses
-		do
-        {
-			// Avoid a loop if we are stuck
-			nAddresses = remainingAddresses.length;
-
-			try
-			{
-				// Send to the list of remaining addresses, ignoring the addresses attached to the message
-		        Transport.send(message,remainingAddresses);
-			}
-			catch(SendFailedException ex)
-			{
-				bFailedToSome=true;
-				sendex.setNextException(ex);
-				
-				// Extract the remaining potentially good addresses
-				remainingAddresses=ex.getValidUnsentAddresses();
-			}
-        } while (remainingAddresses!=null && remainingAddresses.length>0 && remainingAddresses.length!=nAddresses);
-        
-        if (bFailedToSome) throw sendex;
+
+        // Try to send while there remain some potentially good addresses
+        do {
+            // Avoid a loop if we are stuck
+            nAddresses = remainingAddresses.length;
+
+            try {
+                // Send to the list of remaining addresses, ignoring the addresses attached to the message
+                Transport.send(message, remainingAddresses);
+            } catch (SendFailedException ex) {
+                bFailedToSome = true;
+                sendex.setNextException(ex);
+
+                // Extract the remaining potentially good addresses
+                remainingAddresses = ex.getValidUnsentAddresses();
+            }
+        } while (remainingAddresses != null && remainingAddresses.length > 0 && remainingAddresses.length != nAddresses);
+
+        if (bFailedToSome) {
+            throw sendex;
+        }
     }
+    
 
     /**
      * This method is used to send a Text Message.
@@ -149,53 +149,51 @@
      * @param content the body of the e-mail
      * @throws MessagingException the exception to indicate failure
      */
-    public static void sendTextMessage
-    (
-    	Session session,
-        String from,
-        String[] to,
-        String[] cc,
-        String[] bcc,
-        String subject,
-        String content
-    ) 
-    throws MessagingException
-    {
+    public static void sendTextMessage(
+            Session session,
+            String from,
+            String[] to,
+            String[] cc,
+            String[] bcc,
+            String subject,
+            String content)
+            throws MessagingException {
         sendMessage(session, from, to, cc, bcc, subject, content, "text/plain; charset=utf-8");
     }
+
     
-	/**
-	 * This method overrides the sendTextMessage to specify
-	 * one receiver and mulitple cc recipients.
-	 * 
-	 * @param from e-mail address of sender
-	 * @param to e-mail addresses of recipients
-	 * @param subject subject of e-mail
-	 * @param content the body of the e-mail
-	 * @throws MessagingException the exception to indicate failure
-	 */
-	public static void sendTextMessage
-	(
-		Session session,
-		String from,
-		String to,
-		String[] cc,
-        String[] bcc,
-		String subject,
-		String content
-	) 
-	throws MessagingException
-	{
+    /**
+     * This method overrides the sendTextMessage to specify
+     * one receiver and mulitple cc recipients.
+     * 
+     * @param from e-mail address of sender
+     * @param to e-mail addresses of recipients
+     * @param subject subject of e-mail
+     * @param content the body of the e-mail
+     * @throws MessagingException the exception to indicate failure
+     */
+    public static void sendTextMessage(
+            Session session,
+            String from,
+            String to,
+            String[] cc,
+            String[] bcc,
+            String subject,
+            String content)
+            throws MessagingException {
         String[] recipient = null;
-		if (to!=null) recipient = new String[] {to};
+        if (to != null) {
+            recipient = new String[]{to};
+        }
+
+        sendMessage(session, from, recipient, cc, bcc, subject, content, "text/plain; charset=utf-8");
+    }
 
-		sendMessage(session, from, recipient, cc, bcc, subject, content, "text/plain; charset=utf-8");
-	}
-	
+    
     /**
-	 * This method overrides the sendTextMessage to specify
-	 * only one receiver and cc recipients, rather than 
-	 * an array of recipients.
+     * This method overrides the sendTextMessage to specify
+     * only one receiver and cc recipients, rather than 
+     * an array of recipients.
      * 
      * @param from e-mail address of sender
      * @param to e-mail address of recipient
@@ -204,28 +202,32 @@
      * @param content the body of the e-mail
      * @throws MessagingException the exception to indicate failure
      */
-    public static void sendTextMessage
-    (
-    	Session session,
-        String from,
-        String to,
-        String cc,
-        String bcc,
-        String subject,
-        String content
-    ) 
-    throws MessagingException
-    {
+    public static void sendTextMessage(
+            Session session,
+            String from,
+            String to,
+            String cc,
+            String bcc,
+            String subject,
+            String content)
+            throws MessagingException {
         String[] recipient = null;
         String[] copy = null;
         String[] bcopy = null;
 
-		if (to!=null) recipient = new String[] {to};
-		if (cc!=null) copy = new String[] {cc};
-		if (bcc!=null) bcopy = new String[] {bcc};
+        if (to != null) {
+            recipient = new String[]{to};
+        }
+        if (cc != null) {
+            copy = new String[]{cc};
+        }
+        if (bcc != null) {
+            bcopy = new String[]{bcc};
+        }
 
         sendMessage(session, from, recipient, copy, bcopy, subject, content, "text/plain; charset=utf-8");
     }
+
     
     /**
      * This method is used to send a HTML Message
@@ -236,20 +238,18 @@
      * @param content the body of the e-mail
      * @throws MessagingException the exception to indicate failure
      */
-    public static void sendHTMLMessage
-    (
-    	Session session,
-        String from,
-        String[] to,
-        String[] cc,
-        String[] bcc,
-        String subject,
-        String content
-    ) 
-    throws MessagingException
-    {
+    public static void sendHTMLMessage(
+            Session session,
+            String from,
+            String[] to,
+            String[] cc,
+            String[] bcc,
+            String subject,
+            String content)
+            throws MessagingException {
         sendMessage(session, from, to, cc, bcc, subject, content, "text/html; charset=utf-8");
     }
+
     
     /**
      * This method overrides the sendHTMLMessage to specify
@@ -261,56 +261,59 @@
      * @param content the body of the e-mail
      * @throws MessagingException the exception to indicate failure
      */
-	public static void sendHTMLMessage
-    (
-    	Session session,
-        String from,
-        String to,
-        String cc,
-        String bcc,
-        String subject,
-        String content
-    ) 
-    throws MessagingException
-    {
+    public static void sendHTMLMessage(
+            Session session,
+            String from,
+            String to,
+            String cc,
+            String bcc,
+            String subject,
+            String content)
+            throws MessagingException {
         String[] recipient = null;
         String[] copy = null;
         String[] bcopy = null;
 
-		if (to!=null) recipient = new String[] {to};
-		if (cc!=null) copy = new String[] {cc};
-		if (bcc!=null) bcopy = new String[] {bcc};
+        if (to != null) {
+            recipient = new String[]{to};
+        }
+        if (cc != null) {
+            copy = new String[]{cc};
+        }
+        if (bcc != null) {
+            bcopy = new String[]{bcc};
+        }
 
         sendMessage(session, from, recipient, copy, bcopy, subject, content, "text/html; charset=utf-8");
     }
+
     
-	/**
-	 * This method overrides the sendHTMLMessage to specify
-	 * one receiver and mulitple cc recipients.
-	 * 
-	 * @param from e-mail address of sender
-	 * @param to e-mail address of recipient
-	 * @param cc e-mail addresses of recipients
-	 * @param subject subject of e-mail
-	 * @param content the body of the e-mail
-	 * @throws MessagingException the exception to indicate failure
-	 */
-	public static void sendHTMLMessage
-	(
-		Session session,
-		String from,
-		String to,
-		String[] cc,
-		String[] bcc,
-		String subject,
-		String content
-	) 
-	throws MessagingException
-	{
+    /**
+     * This method overrides the sendHTMLMessage to specify
+     * one receiver and mulitple cc recipients.
+     * 
+     * @param from e-mail address of sender
+     * @param to e-mail address of recipient
+     * @param cc e-mail addresses of recipients
+     * @param subject subject of e-mail
+     * @param content the body of the e-mail
+     * @throws MessagingException the exception to indicate failure
+     */
+    public static void sendHTMLMessage(
+            Session session,
+            String from,
+            String to,
+            String[] cc,
+            String[] bcc,
+            String subject,
+            String content)
+            throws MessagingException {
         String[] recipient = null;
-		if (to!=null) recipient = new String[] {to};
+        if (to != null) {
+            recipient = new String[]{to};
+        }
 
-		sendMessage(session, from, recipient, cc, bcc, subject, content, "text/html; charset=utf-8");
-	}
+        sendMessage(session, from, recipient, cc, bcc, subject, content, "text/html; charset=utf-8");
+    }
+    
 }
-

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/RegexUtil.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/RegexUtil.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/RegexUtil.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/RegexUtil.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,119 @@
+/*
+ * 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.util;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.commons.codec.binary.Hex;
+
+
+/**
+ * Regular expressions utility class.
+ */
+public final class RegexUtil {
+    
+    public static final Pattern mailtoPattern = 
+            Pattern.compile("mailto:([a-zA-Z0-9\\.]+@[a-zA-Z0-9\\.]+\\.[a-zA-Z0-9]+)");
+    
+    public static final Pattern emailPattern = 
+            Pattern.compile("\\b[a-zA-Z0-9\\.]+(@)([a-zA-Z0-9\\.]+)(\\.)([a-zA-Z0-9]+)\\b");
+    
+    
+    public static String encodeEmail(String str) {
+        // obfuscate mailto's: turns them into hex encoded,
+        // so that browsers can still understand the mailto link
+        Matcher mailtoMatch = mailtoPattern.matcher(str);
+        while (mailtoMatch.find()) {
+            String email = mailtoMatch.group(1);
+            //System.out.println("email=" + email);
+            String hexed = encode(email);
+            str = str.replaceFirst("mailto:"+email, "mailto:"+hexed);
+        }
+        
+        return obfuscateEmail(str);
+    }
+    
+    
+    /**
+     * obfuscate plaintext emails: makes them
+     * "human-readable" - still too easy for
+     * machines to parse however.
+     */
+    public static String obfuscateEmail(String str) {
+        Matcher emailMatch = emailPattern.matcher(str);
+        while (emailMatch.find()) {
+            String at = emailMatch.group(1);
+            //System.out.println("at=" + at);
+            str = str.replaceFirst(at, "-AT-");
+            
+            String dot = emailMatch.group(2) + emailMatch.group(3) + emailMatch.group(4);
+            String newDot = emailMatch.group(2) + "-DOT-" + emailMatch.group(4);
+            //System.out.println("dot=" + dot);
+            str = str.replaceFirst(dot, newDot);
+        }
+        return str;
+    }
+    
+    
+    /**
+     * Return the specified match "groups" from the pattern.
+     * For each group matched a String will be entered in the ArrayList.
+     *
+     * @param pattern The Pattern to use.
+     * @param match The String to match against.
+     * @param group The group number to return in case of a match.
+     * @return
+     */
+    public static ArrayList getMatches(Pattern pattern, String match, int group) {
+        ArrayList matches = new ArrayList();
+        Matcher matcher = pattern.matcher(match);
+        while (matcher.find()) {
+            matches.add( matcher.group(group) );
+        }
+        return matches;
+    }
+    
+    
+    /**
+     * Thanks to the folks at Blojsom (http://sf.net/projects/blojsom)
+     * for showing me what I was doing wrong with the Hex class.
+     *
+     * @param email
+     * @return
+     */
+    public static String encode(String email) {
+        StringBuffer result = new StringBuffer();
+        try {
+            char[] hexString = Hex.encodeHex(email.getBytes("UTF-8"));
+            for (int i = 0; i < hexString.length; i++) {
+                if (i % 2 == 0) {
+                    result.append("%");
+                }
+                result.append(hexString[i]);
+            }
+        } catch (UnsupportedEncodingException e) {
+            return email;
+        }
+        
+        return result.toString();
+    }
+    
+}

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/URLUtilities.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/URLUtilities.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/URLUtilities.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/URLUtilities.java Sat Jun 28 12:18:17 2008
@@ -24,10 +24,8 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-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.config.PlanetRuntimeConfig;
 
 
 /**
@@ -52,9 +50,9 @@
         
         StringBuffer url = new StringBuffer();
         
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         
-        url.append(PlanetRuntimeConfig.getProperty("site.absoluteurl"));
+        url.append(AggregatorFactory.getAggregator().getConfig().getProperty("site.absoluteurl"));
         url.append("/").append(planet).append("/");
         
         return url.toString();

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/UUIDGenerator.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/UUIDGenerator.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/UUIDGenerator.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/UUIDGenerator.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,40 @@
+/*
+ * 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.util;
+
+import java.util.UUID;
+
+
+/**
+ * Generates UUID values.
+ */
+public class UUIDGenerator {
+    
+    // non-instantiable
+    private UUIDGenerator() {}
+    
+    
+    /**
+     * Generate a new UUID.
+     */
+    public static String generateUUID() {
+        return UUID.randomUUID().toString();
+    }
+    
+}

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/Utilities.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/Utilities.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/Utilities.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/Utilities.java Sat Jun 28 12:18:17 2008
@@ -24,7 +24,7 @@
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.util.RegexUtil;
+import org.apache.roller.planet.util.RegexUtil;
 
 /**
  * General purpose utilities, not for use in templates.

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/Cache.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/Cache.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/Cache.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/Cache.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,64 @@
+/*
+ * 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.util.cache;
+
+import java.util.Map;
+
+
+/**
+ * Base interface representing a cache in Roller.
+ */
+public interface Cache {
+    
+    /**
+     * a unique identifier for the cache.
+     */
+    public String getId();
+    
+    
+    /**
+     * put an item in the cache.
+     */
+    public void put(String key, Object value);
+    
+    
+    /**
+     * get an item from the cache.
+     */
+    public Object get(String key);
+    
+    
+    /**
+     * remove an item from the cache.
+     */
+    public void remove(String key);
+    
+    
+    /**
+     * clear the entire cache.
+     */
+    public void clear();
+    
+    
+    /**
+     * get cache stats.
+     */
+    public Map getStats();
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheFactory.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheFactory.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheFactory.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheFactory.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,35 @@
+/*
+ * 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.util.cache;
+
+import java.util.Map;
+
+
+/**
+ * An interface representing a cache factory.  Implementors of this interface
+ * are responsible for providing a method to construct cache implementations.
+ *
+ * In Roller you switch between various caching options by choosing a different
+ * cache factory before starting up the application.
+ */
+public interface CacheFactory {
+    
+    public Cache constructCache(Map properties);
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheHandler.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheHandler.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheHandler.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheHandler.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,40 @@
+/*
+ * 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.util.cache;
+
+import org.apache.roller.planet.pojos.Planet;
+import org.apache.roller.planet.pojos.PlanetGroup;
+
+
+/**
+ * Represents someone that wants to receive notifications about cache
+ * invalidation events.
+ *
+ * A CacheHandler can be registered with the CacheManager and then will
+ * receive all the various object invalidation events happening in the
+ * system.  Typically classes which are using a cache will want to implement
+ * this interface so that they can know when to remove items from their cache.
+ */
+public interface CacheHandler {
+    
+    public void invalidate(Planet planet);
+    
+    public void invalidate(PlanetGroup group);
+    
+}