You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2006/05/02 00:23:34 UTC

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

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/LinkTag.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/LinkTag.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/LinkTag.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/LinkTag.java Mon May  1 15:23:02 2006
@@ -0,0 +1,304 @@
+/*
+ * $Header: /cvs/roller/roller/src/org/roller/presentation/tags/LinkTag.java,v 1.3 2004/09/23 02:15:36 snoopdave Exp $
+ * $Revision: 1.3 $
+ * $Date: 2004/09/23 02:15:36 $
+ *
+ * ====================================================================
+ */
+package org.apache.roller.presentation.tags;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URLEncoder;
+import java.util.Map;
+import javax.servlet.jsp.JspException;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.log4j.Category;
+import org.apache.struts.taglib.TagUtils;
+import org.apache.struts.util.RequestUtils;
+import org.apache.struts.util.ResponseUtils;
+
+/**
+ * Generates an HTML link. This class adds the parameter feature to the Struts
+ * html link tag. <br/>It should be use as follow:
+ * 
+ * <pre>
+ * 
+ *   &lt;hm:link href=&quot;http://java.sun.com&quot;&gt;
+ *     &lt;hm:linkparam name=&quot;action&quot; value=&quot;submit&quot; /&gt;
+ *     &lt;hm:linkparam name=&quot;ref&quot; value=&quot;144532&quot; /&gt;
+ *   &lt;/hm:linl&gt;
+ *   
+ * </pre>
+ * 
+ * This will produce the equivalent of
+ * 
+ * <pre>
+ * &lt;href=&quot;http://java.sun.com?_action=submit&amp;ref=144532&quot;&gt;
+ * </pre>
+ * 
+ * Title: BSquare Description: Bsquare Projects Copyright: Copyright (c) 2001
+ * Company: HubMethods
+ * 
+ * @author $Author: snoopdave $
+ * @version $Revision: 1.3 $
+ */
+public class LinkTag extends org.apache.struts.taglib.html.LinkTag
+{
+    // ------------------------------------------------------ Logging
+    static Category cat = Category.getInstance(LinkTag.class);
+    // ------------------------------------------------------ Instance Vartables
+    /**
+     * The full HREF URL
+     */
+    private StringBuffer hrefURL = new StringBuffer();
+
+    // ------------------------------------------------------------- Properties
+    //--------------------------------------------------------- Public Methods
+    /**
+     * Intialize the hyperlink.
+     * 
+     * @exception JspException
+     *                if a JSP exception has occurred
+     */
+    public int doStartTag() throws JspException
+    {
+        // Special case for name anchors
+        if (linkName != null)
+        {
+            StringBuffer results = new StringBuffer("<a name=\"");
+            results.append(linkName);
+            results.append("\">");
+            return (EVAL_BODY_TAG);
+        }
+        // Generate the hyperlink URL
+        Map params = RequestUtils.computeParameters(pageContext, paramId,
+                        paramName, paramProperty, paramScope, name, property,
+                        scope, transaction);
+        String url = null;
+        try
+        {
+            url = RequestUtils.computeURL(pageContext, forward, href, page,
+                            params, anchor, false);
+        }
+        catch (MalformedURLException e)
+        {
+            RequestUtils.saveException(pageContext, e);
+            throw new JspException(messages.getMessage("rewrite.url", e
+                            .toString()));
+        }
+        // Generate the opening anchor element
+        hrefURL = new StringBuffer("<a href=\"");
+        hrefURL.append(url);
+        if (cat.isDebugEnabled())
+            cat.debug("hrefURL = '" + hrefURL.toString());
+        // Evaluate the body of this tag
+        this.text = null;
+        return (EVAL_BODY_TAG);
+    }
+
+    /**
+     * Add a new parameter to the request
+     * 
+     * @param name
+     *            the name of the request parameter
+     * @param value
+     *            the value of the request parameter
+     */
+    public void addRequestParameter(String name, String value)
+    {
+        if (cat.isDebugEnabled())
+            cat.debug("Adding '" + name + "' with value '" + value + "'");
+        boolean question = (hrefURL.toString().indexOf('?') >= 0);
+        if (question)
+        { // There are request parameter already
+            hrefURL.append('&');
+        }
+        else
+            hrefURL.append('?');
+        hrefURL.append(name);
+        hrefURL.append('=');
+        hrefURL.append(URLEncoder.encode(value));
+        if (cat.isDebugEnabled())
+            cat.debug("hrefURL = '" + hrefURL.toString() + "'");
+    }
+
+    /**
+     * Render the href reference
+     * 
+     * @exception JspException
+     *                if a JSP exception has occurred
+     */
+    public int doEndTag() throws JspException
+    {
+        hrefURL.append("\"");
+        if (target != null)
+        {
+            hrefURL.append(" target=\"");
+            hrefURL.append(target);
+            hrefURL.append("\"");
+        }
+        hrefURL.append(prepareStyles());
+        hrefURL.append(prepareEventHandlers());
+        hrefURL.append(">");
+        if (text != null)
+            hrefURL.append(text);
+        hrefURL.append("</a>");
+        if (cat.isDebugEnabled())
+            cat.debug("Total request is = '" + hrefURL.toString() + "'");
+        // Print this element to our output writer
+        ResponseUtils.write(pageContext, hrefURL.toString());
+        return (EVAL_PAGE);
+    }
+
+    /**
+     * Release any acquired resources.
+     */
+    public void release()
+    {
+        super.release();
+        forward = null;
+        href = null;
+        name = null;
+        property = null;
+        target = null;
+    }
+
+    // ----------------------------------------------------- Protected Methods
+    /**
+     * Return the specified hyperlink, modified as necessary with optional
+     * request parameters.
+     * 
+     * @exception JspException
+     *                if an error occurs preparing the hyperlink
+     */
+    protected String hyperlink() throws JspException
+    {
+        String href = this.href;
+        // If "forward" was specified, compute the "href" to forward to
+//        if (forward != null)
+//        {
+//            ActionForwards forwards = (ActionForwards) pageContext
+//                            .getAttribute(Action.FORWARDS_KEY,
+//                                            PageContext.APPLICATION_SCOPE);
+//            ActionMapping mapping = (ActionMapping)pageContext.getAttribute(ActionConfig.)            
+//            if (forwards == null)
+//                throw new JspException(messages.getMessage("linkTag.forwards"));
+//            ActionForward forward = forwards.findForward(this.forward);
+//            if (forward == null)
+//                throw new JspException(messages.getMessage("linkTag.forward"));
+//            HttpServletRequest request = (HttpServletRequest) pageContext
+//                            .getRequest();
+//            href = request.getContextPath() + forward.getPath();
+//        }
+        // Just return the "href" attribute if there is no bean to look up
+        if ((property != null) && (name == null))
+            throw new JspException(messages.getMessage("getter.name"));
+        if (name == null)
+            return (href);
+        // Look up the map we will be using
+        Object bean = pageContext.findAttribute(name);
+        if (bean == null)
+            throw new JspException(messages.getMessage("getter.bean", name));
+        Map map = null;
+        if (property == null)
+        {
+            try
+            {
+                map = (Map) bean;
+            }
+            catch (ClassCastException e)
+            {
+                throw new JspException(messages.getMessage("linkTag.type"));
+            }
+        }
+        else
+        {
+            try
+            {
+                map = (Map) PropertyUtils.getProperty(bean, property);
+                if (map == null)
+                    throw new JspException(messages.getMessage(
+                                    "getter.property", property));
+            }
+            catch (IllegalAccessException e)
+            {
+                throw new JspException(messages.getMessage("getter.access",
+                                property, name));
+            }
+            catch (InvocationTargetException e)
+            {
+                Throwable t = e.getTargetException();
+                throw new JspException(messages.getMessage("getter.result",
+                                property, t.toString()));
+            }
+            catch (ClassCastException e)
+            {
+                throw new JspException(messages.getMessage("linkTag.type"));
+            }
+            catch (NoSuchMethodException e)
+            {
+                throw new JspException(messages.getMessage("getter.method",
+                                property, name));
+            }
+        }
+            // Append the required query parameters
+//        StringBuffer sb = new StringBuffer(href);
+//        boolean question = (href.indexOf("?") >= 0);
+//        Iterator keys = map.keySet().iterator();
+//        while (keys.hasNext())
+//        {
+//            String key = (String) keys.next();
+//            Object value = map.get(key);
+//            if (value instanceof String[])
+//            {
+//                String values[] = (String[]) value;
+//                for (int i = 0; i < values.length; i++)
+//                {
+//                    if (question)
+//                        sb.append('&');
+//                    else
+//                    {
+//                        sb.append('?');
+//                        question = true;
+//                    }
+//                    sb.append(key);
+//                    sb.append('=');
+//                    sb.append(URLEncoder.encode(values[i]));
+//                }
+//            }
+//            else
+//            {
+//                if (question)
+//                    sb.append('&');
+//                else
+//                {
+//                    sb.append('?');
+//                    question = true;
+//                }
+//                sb.append(key);
+//                sb.append('=');
+//                sb.append(URLEncoder.encode(value.toString()));
+//            }
+//        }
+//        // Return the final result
+//        return (sb.toString());
+        try
+        {
+            return TagUtils.getInstance().computeURL(
+                            pageContext,
+                            forward,
+                            href,
+                            null, 
+                            null,
+                            null,
+                            map,
+                            null,
+                            false
+                            );
+        }
+        catch (MalformedURLException e)
+        {
+            throw new JspException(e);
+        }
+    }
+}

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/RowTag.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/RowTag.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/RowTag.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/RowTag.java Mon May  1 15:23:02 2006
@@ -0,0 +1,385 @@
+/*
+* 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.presentation.tags;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.taglib.logic.IterateTag;
+
+import java.io.IOException;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspWriter;
+import javax.servlet.jsp.tagext.Tag;
+
+
+/**
+ * <p>This tag generates table rows (i.e. &lt;tr&gt;....&lt;/tr&gt; elements) 
+ * with the background color set differently for alternating odd and even 
+ * rows. This tag only operates properly if embedded in an IterateTag.</p>
+ *
+ * <p>The following parameters can be specified for this Tag:</p>
+ * <ul>
+ * <li><code>oddColor </code> - The color for Odd numbered rows
+ * <li><code>evenColor</code> - The color for Even numbered rows
+ * <li><code>oddStyleClass</code> - The style class for Odd numbered rows
+ * <li><code>evenStyleClass</code> - The style class for Even numbered rows
+ * <li><code>align</code> - The alignment for the table row
+ * <li><code>valign</code> - The vertical alignment for the table row
+ * </ul>
+ *
+ * <p>Additionally this tag inherits the Event Handler and Style attributes
+ * from the BaseHandlerTag which can also be specified</p>
+ * 
+ * TODO Make RowTag work with STL's forEach tag too.
+ * 
+ * @jsp.tag name="row"
+ *
+ * @author Amarda Business Systems Ltd
+ * @version 1.0
+ */
+public class RowTag extends org.apache.struts.taglib.html.BaseHandlerTag
+{
+    // ----------------------------------------------------- Instance Variables
+    private static Log mLogger = LogFactory.getFactory()
+                                           .getInstance(RowTag.class);
+    protected final static String QUOTE = "\"";
+
+    /**
+     * Color of Odd rows in a table
+     */
+    protected String oddColor = null;
+
+    /**
+     *  Color of Even rows in a table
+     */
+    protected String evenColor = null;
+
+    /**
+     *  StyleClass of Odd rows in a table
+     */
+    protected String oddStyleClass = null;
+
+    /**
+     *  Style Class of Even rows in a table
+     */
+    protected String evenStyleClass = null;
+
+    /**
+     *  Alignment of the table row
+     */
+    protected String align = null;
+
+    /**
+     *  Vertical Alignment of the table row
+     */
+    protected String valign = null;
+
+    /**
+     * Return the color of Odd rows
+     * @jsp.attribute
+     */
+    public String getOddColor()
+    {
+        return (this.oddColor);
+    }
+
+    /**
+     * Set the color of Odd rows
+     *
+     * @param color HTML bgcolor value for Odd rows
+     */
+    public void setOddColor(String color)
+    {
+        this.oddColor = color;
+    }
+
+    /**
+     *  Return the color of Even rows
+     * @jsp.attribute
+     */
+    public String getEvenColor()
+    {
+        return (this.evenColor);
+    }
+
+    /**
+     * Set the color of Even rows
+     *
+     * @param color HTML bgcolor value for Even rows
+     */
+    public void setEvenColor(String color)
+    {
+        this.evenColor = color;
+    }
+
+    /**
+     * Return the Style Class of Odd rows
+     * @jsp.attribute
+     */
+    public String getOddStyleClass()
+    {
+        return (this.oddStyleClass);
+    }
+
+    /**
+     * Set the Style Class of Odd rows
+     *
+     * @param styleClass HTML Style Class value for Odd rows
+     */
+    public void setOddStyleClass(String styleClass)
+    {
+        this.oddStyleClass = styleClass;
+    }
+
+    /**
+     *  Return the Style Class of Even rows
+     * @jsp.attribute
+     */
+    public String getEvenStyleClass()
+    {
+        return (this.evenStyleClass);
+    }
+
+    /**
+     * Set the styleClass of Even rows
+     *
+     * @param styleClass HTML Style Class value for Even rows
+     */
+    public void setEvenStyleClass(String styleClass)
+    {
+        this.evenStyleClass = styleClass;
+    }
+
+    /**
+     *  Return the Alignment
+     * @jsp.attribute
+     */
+    public String getAlign()
+    {
+        return (this.align);
+    }
+
+    /**
+     * Set the Alignment
+     *
+     * @param Value for Alignment
+     */
+    public void setAlign(String align)
+    {
+        this.align = align;
+    }
+
+    /**
+     *  Return the Vertical Alignment
+     * @jsp.attribute
+     */
+    public String getValign()
+    {
+        return (this.valign);
+    }
+
+    /**
+     * Set the Vertical Alignment
+     *
+     * @param Value for Vertical Alignment
+     */
+    public void setValign(String valign)
+    {
+        this.valign = valign;
+    }
+
+    // ----------------------------------------------------- Public Methods
+
+    /**
+     * Start of Tag processing
+     *
+     * @exception JspException if a JSP exception occurs
+     */
+    public int doStartTag() throws JspException
+    {
+        // Continue processing this page
+        return EVAL_BODY_BUFFERED;
+    }
+
+    /**
+     * End of Tag Processing
+     *
+     * @exception JspException if a JSP exception occurs
+     */
+    public int doEndTag() throws JspException
+    {
+        StringBuffer buffer = new StringBuffer();
+
+
+        // Create a <tr> element based on the parameters
+        buffer.append("<tr");
+
+
+        // Prepare this HTML elements attributes
+        prepareAttributes(buffer);
+
+        buffer.append(">");
+
+        // Add Body Content
+        if (bodyContent != null)
+        {
+            buffer.append(bodyContent.getString().trim());
+        }
+
+        buffer.append("</tr>");
+
+        // Render this element to our writer
+        JspWriter writer = pageContext.getOut();
+
+        try
+        {
+            writer.print(buffer.toString());
+        }
+        catch (IOException e)
+        {
+            mLogger.error("ERROR in tag", e);
+            throw new JspException("Exception in RowTag doEndTag():" + 
+                                   e.toString());
+        }
+
+        return EVAL_PAGE;
+    }
+
+    /**
+     * Prepare the attributes of the HTML element
+     */
+    protected void prepareAttributes(StringBuffer buffer)
+    {
+        // Determine if it is an "Odd" or "Even" row
+        boolean evenNumber = ((getRowNumber() % 2) == 0)                     
+                             ? true : false;
+
+
+        // Append bgcolor parameter
+        buffer.append(prepareBgcolor(evenNumber));
+
+
+        // Append CSS class parameter
+        buffer.append(prepareClass(evenNumber));
+
+
+        // Append "align" parameter
+        buffer.append(prepareAttribute("align", align));
+
+
+        // Append "valign" parameter
+        buffer.append(prepareAttribute("valign", valign));
+
+
+        // Append Event Handler details
+        buffer.append(prepareEventHandlers());
+
+        try
+        {
+            // Append Style details
+            buffer.append(prepareStyles());
+        }
+        catch (Exception e)
+        {
+            mLogger.error("Unexpected exception", e);
+        }
+    }
+
+    /**
+     * Format attribute="value" from the specified attribute & value
+     */
+    protected String prepareAttribute(String attribute, String value)
+    {
+        return (value == null)       
+               ? "" : " " + attribute + "=" + QUOTE + value + QUOTE;
+    }
+
+    /**
+     * Format the bgcolor attribute depending on whether
+     * the row is odd or even.
+     *
+     * @param evenNumber Boolean set to true if an even numbered row
+     *
+     */
+    protected String prepareBgcolor(boolean evenNumber)
+    {
+        if (evenNumber)
+        {
+            return prepareAttribute("bgcolor", evenColor);
+        }
+        else
+        {
+            return prepareAttribute("bgcolor", oddColor);
+        }
+    }
+
+    /**
+     * Format the Style sheet class attribute depending on whether
+     * the row is odd or even.
+     *
+     * @param evenNumber Boolean set to true if an even numbered row
+     *
+     */
+    protected String prepareClass(boolean evenNumber)
+    {
+        if (evenNumber)
+        {
+            return prepareAttribute("class", evenStyleClass);
+        }
+        else
+        {
+            return prepareAttribute("class", oddStyleClass);
+        }
+    }
+
+    /**
+     * Determine the Row Number - from the IterateTag
+     */
+    protected int getRowNumber()
+    {
+        // Determine if embedded in an IterateTag
+        Tag tag = findAncestorWithClass(this, IterateTag.class);
+
+        if (tag == null)
+        {
+            return 1;
+        }
+
+        // Determine the current row number
+        IterateTag iterator = (IterateTag) tag;
+
+        //        return iterator.getLengthCount() + 1;
+        return iterator.getIndex() + 1;
+    }
+
+    /**
+     * Release resources after Tag processing has finished.
+     */
+    public void release()
+    {
+        super.release();
+
+        oddColor = null;
+        evenColor = null;
+        oddStyleClass = null;
+        evenStyleClass = null;
+        align = null;
+        valign = null;
+    }
+}
\ No newline at end of file

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/StatusMessageTag.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/StatusMessageTag.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/StatusMessageTag.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/StatusMessageTag.java Mon May  1 15:23:02 2006
@@ -0,0 +1,82 @@
+/*
+* 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.presentation.tags;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.presentation.RollerSession;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspWriter;
+import javax.servlet.jsp.tagext.Tag;
+import javax.servlet.jsp.tagext.TagSupport;
+
+
+/**
+ * If there is an status message, then print it in red.
+ * @jsp.tag name="StatusMessage"
+ */
+public class StatusMessageTag extends TagSupport
+{
+    static final long serialVersionUID = -1086963203859216226L;
+    
+    private static Log mLogger = 
+       LogFactory.getFactory().getInstance(StatusMessageTag.class);
+
+    public int doStartTag() throws JspException
+	{
+		try
+		{
+			JspWriter pw = pageContext.getOut();
+			HttpServletRequest req = 
+				(HttpServletRequest)pageContext.getRequest();
+
+			String msg = null;
+
+			msg = (String)req.getSession().getAttribute(
+                RollerSession.ERROR_MESSAGE);
+			if (msg != null)
+			{
+				pw.println("<span class=\"error\">");
+				pw.println(msg);
+				pw.println("</span>");
+				req.getSession().removeAttribute(RollerSession.ERROR_MESSAGE);
+			}
+
+			msg = (String)req.getSession().getAttribute(
+                RollerSession.STATUS_MESSAGE);
+			if (msg != null)
+			{
+				pw.println("<span class=\"statusMsg\">");
+				pw.println(msg);
+				pw.println("</span>");
+				req.getSession().removeAttribute(RollerSession.STATUS_MESSAGE);
+			}
+		}
+		catch (IOException e)
+		{
+            mLogger.error("Exception",e);
+			throw new JspException(e);
+		}
+		return Tag.SKIP_BODY;
+    }
+}
+

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/VelocityTag.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/VelocityTag.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/VelocityTag.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/VelocityTag.java Mon May  1 15:23:02 2006
@@ -0,0 +1,187 @@
+/*
+* 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.presentation.tags; 
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.app.VelocityEngine;
+
+import java.io.StringWriter;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.TagSupport;
+
+/**
+ * @author David M Johnson, Gregory Gerard
+ * @version 1.0
+ */
+public abstract class VelocityTag extends HybridTag // TagSupport 
+{
+    private static Log mLogger = 
+        LogFactory.getFactory().getInstance(VelocityTag.class);
+/*
+    private String              title;
+    private String              subtitle;
+    private List                images;
+    private Map                 ingredients;
+*/
+
+	/** Return path to Velocity template to render this tag */
+	public abstract String getTemplateClasspath();
+
+	/** Prepare context for execution */
+	public abstract void prepareContext( VelocityContext ctx );
+
+
+    public VelocityTag()
+    {
+    }
+
+    /**
+     * Release any resources we might have acquired.
+     */
+    public void release()
+    {
+        super.release();
+        /*
+        title       = null;
+        subtitle    = null;
+        images      = null;
+        ingredients = null;
+        */
+    }
+
+    /**
+     * Evaluate any tags inside us.  This will also allow us to have child tags
+     * send us messages.
+     * @return
+     * @throws JspException
+     */
+    public int doStartTag(java.io.PrintWriter pw)
+        throws JspException
+    {
+        return TagSupport.EVAL_BODY_INCLUDE;
+    }
+
+    /**
+     * Check all all the public properties that must be set by now, either by
+     * tag arguments or tag children.
+     * @return
+     * @throws JspException
+     */
+    public int doEndTag(java.io.PrintWriter pw) throws JspException
+    {
+        String myResource= getVelocityClasspathResource(getTemplateClasspath());
+
+        try
+        {
+            VelocityContext myVelocityContext = getVelocityContext();
+
+			// ask concrete class to prepare context 
+			prepareContext( myVelocityContext );
+
+            StringWriter myStringWriter = new StringWriter();
+
+            Velocity.mergeTemplate(myResource,
+            	org.apache.velocity.runtime.RuntimeSingleton.getString(
+					Velocity.INPUT_ENCODING, Velocity.ENCODING_DEFAULT),
+                 myVelocityContext, myStringWriter);
+
+            pw.println(myStringWriter);
+
+            return EVAL_PAGE;
+        }
+        catch (Exception e)
+        {
+            mLogger.error("Unexpected exception",e);
+
+            throw new JspException(
+				"Exception; TEMPLATE_CLASSPATH=" + getTemplateClasspath() 
+				+ "; exception=" + e.getMessage());
+        }
+    }
+
+    public String doStandaloneTest(Map inMap)
+        throws Exception
+    {
+        String          resource = getVelocityClasspathResource(
+										getTemplateClasspath());
+        VelocityContext context  = getVelocityContext();
+        StringWriter    w        = new StringWriter();
+        Iterator        iter     = inMap.keySet().iterator();
+
+        while (iter.hasNext())
+        {
+            Object o = iter.next();
+
+            context.put(o.toString(), inMap.get(o));
+        }
+
+        Velocity.mergeTemplate(resource, 
+			org.apache.velocity.runtime.RuntimeSingleton.getString(
+				Velocity.INPUT_ENCODING, Velocity.ENCODING_DEFAULT),
+            context, w);
+
+        return w.toString();
+    }
+
+    protected static VelocityContext getVelocityContext()
+        throws java.lang.Exception
+    {
+        Velocity.addProperty(Velocity.RESOURCE_LOADER, "classpath");
+        Velocity.addProperty("classpath." + Velocity.RESOURCE_LOADER + ".class",
+        "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+        Velocity.setProperty(
+			VelocityEngine.COUNTER_INITIAL_VALUE, new Integer(0));
+        Velocity.init();
+
+        return new VelocityContext();
+    }
+
+    /**
+     * Velocity wants classpath resources to not have a leading slash.  This is
+     * contrary to how one would normally load a resource off the classpath
+     * (e.g. SampleTag.class.getResourceAsStream("/extag/resources/test.html")
+     * @param inClasspathString
+     * @return
+     */
+    protected static String getVelocityClasspathResource(
+		String inClasspathString)
+    {
+        if (inClasspathString.length() < 1)
+        {
+            return inClasspathString;
+        }
+        else
+        {
+            if (inClasspathString.startsWith("/"))
+            {
+                return inClasspathString.substring(1);
+            }
+            else
+            {
+                return inClasspathString;
+            }
+        }
+    }
+}

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/CalendarModel.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/CalendarModel.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/CalendarModel.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/CalendarModel.java Mon May  1 15:23:02 2006
@@ -0,0 +1,62 @@
+/*
+* 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.presentation.tags.calendar;
+import java.util.Calendar;
+import java.util.Date;
+
+/** 
+ * Model interface for the CalendarTag. The CalendarTag will set a day, 
+ * then use the computeUrl method to get the URLs it needs.
+ */
+public interface CalendarModel 
+{    
+    public Calendar getCalendar();
+    
+	public void setDay( String month ) throws Exception;
+    
+	public Date getDay();
+    
+    public Date getNextMonth();
+    
+    public String computePrevMonthUrl();    
+
+    public String computeTodayMonthUrl();    
+
+    public String computeNextMonthUrl();
+    
+    /** 
+     * Create URL for use on edit-weblog page, preserves the request
+     * parameters used by the tabbed-menu tag for navigation.
+     * 
+     * @param day   Day for URL
+     * @param valid Always return a URL, never return null 
+     * @return URL for day, or null if no weblog entry on that day
+     */
+    public String computeUrl( java.util.Date day, boolean valid );
+    
+    /** 
+     * Get calendar cell content or null if none.
+     * 
+     * @param day Day for URL
+     * @param valid Always return a URL, never return null 
+     * @return Calendar cell content or null if none.
+     */
+    public String getContent( java.util.Date day );
+}
+

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/CalendarTag.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/CalendarTag.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/CalendarTag.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/CalendarTag.java Mon May  1 15:23:02 2006
@@ -0,0 +1,378 @@
+/*
+* 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.presentation.tags.calendar;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.Globals;
+import org.apache.struts.config.ModuleConfig;
+import org.apache.struts.util.MessageResources;
+import org.apache.struts.util.RequestUtils;
+import org.apache.roller.presentation.tags.HybridTag;
+import org.apache.roller.util.DateUtil;
+
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.Tag;
+import org.apache.roller.presentation.RollerContext;
+
+
+/**
+ * Calendar tag.
+ * @jsp.tag name="Calendar"
+ */
+public class CalendarTag extends HybridTag
+{
+    private static Log mLogger =
+        LogFactory.getFactory().getInstance(CalendarTag.class);
+
+    // JSP Attributes
+
+    /** @jsp.attribute required="true" */
+    public String getName() { return mName; }
+    public void setName( String name ) { mName = name; }
+    private String mName = null;
+
+    /* @jsp.attribute description="Date in yyyyMMdd format"
+    public String getDate() { return mDate; }
+    public void setDate( String s ) { mDate = s; }
+    private String mDate = null;
+    */
+
+    /** @jsp.attribute */
+    public String getModel() { return mModelName; }
+    public void setModel( String s ) { mModelName= s; }
+    private String mModelName = null;
+
+    /** @jsp.attribute */
+    public String getClassSuffix() { return mClassSuffix; }
+    public void setClassSuffix( String s ) { mClassSuffix= s; }
+    private String mClassSuffix = "";
+
+    // not a tag attribute
+    public void setLocale(Locale locale) {
+        if (locale != null)
+            mLocale = locale;
+    }
+    private Locale mLocale = Locale.getDefault();
+
+    // not a tag attribute
+    /*
+    private TimeZone mTimeZone = TimeZone.getDefault();
+    public void setTimeZone(TimeZone zone) {
+        if (zone != null)
+            mTimeZone = zone;
+    }
+    private TimeZone getTimeZone()
+    {
+        // I've seen TimeZone.getDefault() return null. -Lance
+        if (mTimeZone == null) 
+            mTimeZone = TimeZone.getTimeZone("America/New_York");
+        return mTimeZone;
+    }
+    */
+
+    private String[] mDayNames = null;
+
+    public CalendarTag()
+    {
+        /*
+         * Empty constructor.
+         *
+         * Used to build the day names, but the correct locale
+         * was not set at this stage. Day-name-building has moved to the
+         * doStartTag() method.
+         */
+    }
+
+    //------------------------------------------------------------------------
+    /**
+     * Write to a PrintWriter so that tag may be used from Velocity
+     */
+    public int doStartTag( PrintWriter pw ) throws JspException
+    {
+        try
+        {
+            // build week day names
+            this.buildDayNames();
+
+            Date day=null;       // day to be displayed
+            Calendar dayCal;     // set to day to be displayed
+            Calendar cal;        // for iterating through days of month
+            Calendar todayCal;   // for iterating through days of month
+            CalendarModel model; // the calendar model
+
+            // ---------------------------------
+            // --- initialize date variables ---
+            // ---------------------------------
+
+            // check for parameter map and target url
+            StringTokenizer toker = new StringTokenizer(mModelName,".");
+            String tok1 = toker.nextToken();
+            if (toker.hasMoreTokens())
+            {
+                String tok2 = toker.nextToken();
+                Object bean = pageContext.findAttribute(tok1);
+                model = (CalendarModel)PropertyUtils.getProperty(bean, tok2);
+            }
+            else
+            {
+                model = (CalendarModel)pageContext.findAttribute( mModelName );
+            }
+            
+            // no model specified, nothing to generate
+            if (model == null)
+            {
+                return SKIP_BODY;
+            }
+            
+            day = model.getDay();
+
+            // ceate object to represent today
+            todayCal = model.getCalendar();
+            todayCal.setTime( new Date() );
+
+            // formatter Month-Year title of calendar
+            SimpleDateFormat formatTitle = new SimpleDateFormat("MMMM yyyy", mLocale);
+
+            HttpServletRequest request =
+                (HttpServletRequest)pageContext.getRequest();
+
+            // get Resource Bundle
+            MessageResources resources = getResources(request);
+
+            // go back to first day in month
+            cal = model.getCalendar();
+            day = DateUtil.getNoonOfDay(day, cal);
+            cal.set( Calendar.DAY_OF_MONTH, cal.getMinimum(Calendar.DAY_OF_MONTH) );
+
+            // go back to sunday before that: the first sunday in the calendar
+            while ( cal.get( Calendar.DAY_OF_WEEK ) != Calendar.SUNDAY )
+            {
+                cal.add( Calendar.DATE, -1 );
+            }
+
+            // create table of 5 weeks, 7 days per row
+            dayCal = model.getCalendar();
+            dayCal.setTime( day );
+
+            // -------------------------
+            // --- draw the calendar ---
+            // -------------------------
+            pw.print("<table cellspacing=\"0\" border=\"0\" ");
+            pw.print(" summary=\""
+                +resources.getMessage(mLocale, "calendar.summary")
+                +"\" class=\"hCalendarTable"
+                +mClassSuffix+"\">");
+            pw.print("<tr>");
+            pw.print("<td colspan=\"7\" align=\"center\" "+
+                "class=\"hCalendarMonthYearRow"+mClassSuffix+"\">");
+            pw.print("<a href=\"" + model.computePrevMonthUrl()
+                     + "\" title=\"" + resources.getMessage(mLocale, "calendar.prev")
+                     + "\" class=\"hCalendarNavBar\">&laquo;</a> ");
+            pw.print( formatTitle.format(day) );
+            if (todayCal.getTime().compareTo(model.getNextMonth()) >= 0)
+            {    
+                pw.print(" <a href=\"" + model.computeNextMonthUrl()
+                     + "\" title=\"" + resources.getMessage(mLocale, "calendar.next")
+                     + "\" class=\"hCalendarNavBar\">&raquo;</a>");
+            }
+            pw.print("</td></tr>");
+
+            // emit the HTML calendar
+            for ( int w=-1; w<6; w++ )
+            {
+                pw.print("<tr>");
+                for ( int d=0; d<7; d++ )
+                {
+                    if ( w == -1 )
+                    {
+                        pw.print(
+                            "<th class=\"hCalendarDayNameRow"
+                            +mClassSuffix+"\" align=\"center\">");
+                        pw.print( mDayNames[d] );
+                        pw.print("</th>");
+                        continue;
+                    }
+
+                    // determine URL for this calendar day
+                    Date tddate = cal.getTime();
+                    String url = model.computeUrl( tddate, false );
+                    String content = model.getContent( tddate );
+
+                    if // day is in calendar month
+                       ((cal.get(Calendar.MONTH) == dayCal.get(Calendar.MONTH))
+                     && (cal.get(Calendar.YEAR) == dayCal.get(Calendar.YEAR)))
+                    {
+                        if // day is today then use today style
+                            ((          cal.get(Calendar.DAY_OF_MONTH)
+                                == todayCal.get(Calendar.DAY_OF_MONTH))
+                            && (        cal.get(Calendar.MONTH)
+                                == todayCal.get(Calendar.MONTH))
+                            && (        cal.get(Calendar.YEAR)
+                                == todayCal.get(Calendar.YEAR)))
+                        {
+                            printToday(pw, cal, url, content);
+                        }
+                        else
+                        {
+                            printDayInThisMonth(pw, cal, url, content);
+                        }
+                    }
+                    else // apply day-not-in-month style ;-)
+                    {
+                        printDayNotInMonth(pw, cal);
+                    }
+
+                    // increment calendar by one day
+                    cal.add( Calendar.DATE, 1 );
+                }
+                pw.print("</tr>");
+            }
+
+            pw.print("<tr class=\"hCalendarNextPrev"
+                +mClassSuffix+"\">");
+            pw.print("<td colspan=\"7\" align=\"center\">");
+
+            pw.print("<a href=\""+model.computeTodayMonthUrl()
+                +"\" class=\"hCalendarNavBar\">"
+                +resources.getMessage(mLocale, "calendar.today")
+                +"</a>");
+
+            pw.print("</td>");
+            pw.print("</tr>");
+
+            pw.print("</table>");
+        }
+        catch (Exception e)
+        {
+            pw.print("<span class=\"error\">");
+            pw.print("<p><b>An ERROR has occured CalendarTag</b></p>");
+            pw.print("</span>");
+            mLogger.error("Calendar tag exception",e);
+        }
+        return Tag.SKIP_BODY;
+    }
+
+    private void printDayNotInMonth(PrintWriter pw, Calendar cal)
+    {
+        pw.print("<td class=\"hCalendarDayNotInMonth"+mClassSuffix+"\">");
+        //pw.print(cal.get(Calendar.DAY_OF_MONTH));
+        pw.print("&nbsp;");
+        pw.print("</td>");
+    }
+    
+    private void printDayInThisMonth(PrintWriter pw, Calendar cal, String url, String content)
+    {
+        if ( content!=null )
+        {
+            pw.print("<td class=\"hCalendarDayCurrent"
+                +mClassSuffix+"\">");
+            pw.print( content );
+            pw.print("</td>");
+        }
+        else if (url!=null)
+        {
+            pw.print("<td class=\"hCalendarDayLinked"
+                +mClassSuffix+"\">");
+            pw.print("<div class=\"hCalendarDayTitle"
+                +mClassSuffix+"\">");
+            pw.print("<a href=\""+url+"\">");
+            pw.print(cal.get(Calendar.DAY_OF_MONTH));
+            pw.print("</a></div>");
+            pw.print("</td>");
+        }
+        else
+        {
+            pw.print("<td class=\"hCalendarDay"
+                +mClassSuffix+"\">");
+            pw.print("<div class=\"hCalendarDayTitle"
+                +mClassSuffix+"\">");
+            pw.print(cal.get(Calendar.DAY_OF_MONTH));
+            pw.print("</div>");
+            pw.print("</td>");
+        }
+    }
+    
+    private void printToday(PrintWriter pw, Calendar cal, String url, String content)
+    {
+        if ( content!=null )
+        {
+            pw.print("<td class=\"hCalendarDayCurrent"
+                +mClassSuffix+"\">");
+            pw.print( content );
+            pw.print("</td>");
+        }
+        else if (url!=null)
+        {
+            pw.print("<td class=\"hCalendarDayCurrent"
+               +mClassSuffix+"\">");
+            pw.print("<a href=\""+url+"\" "
+               +"class=\"hCalendarDayTitle"+mClassSuffix+"\">");
+            pw.print(cal.get(Calendar.DAY_OF_MONTH));
+            pw.print("</a>");
+            pw.print("</td>");
+        }
+        else
+        {
+            pw.print("<td class=\"hCalendarDayCurrent"
+                +mClassSuffix+"\">");
+            pw.print("<div class=\"hCalendarDayTitle"
+                +mClassSuffix+"\">");
+            pw.print(cal.get(Calendar.DAY_OF_MONTH));
+            pw.print("</div></td>");
+        }
+    }
+    private MessageResources getResources(HttpServletRequest request) {
+        ServletContext app = RollerContext.getServletContext();
+        ModuleConfig moduleConfig = RequestUtils.getModuleConfig(request, app);
+        return (MessageResources)app.getAttribute(Globals.MESSAGES_KEY +
+                                                  moduleConfig.getPrefix());
+    }
+
+    /**
+     * Helper method to build the names of the weekdays. This
+     * used to take place in the <code>CalendarTag</code> constructor,
+     * but there, <code>mLocale</code> doesn't have the correct value yet.
+     */
+    private void buildDayNames()
+    {
+        // build array of names of days of week
+        mDayNames = new String[7];
+        Calendar dayNameCal = Calendar.getInstance();
+        SimpleDateFormat dayFormatter = new SimpleDateFormat("EEE", mLocale);
+        dayNameCal.set(Calendar.DAY_OF_WEEK, 0);
+        for (int dnum = 0; dnum < 7; dnum++)
+        {
+            dayNameCal.add(Calendar.DATE, 1);
+            mDayNames[dnum] = dayFormatter.format(dayNameCal.getTime());
+        }
+    }
+
+}
+

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/package.html
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/package.html?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/package.html (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/calendar/package.html Mon May  1 15:23:02 2006
@@ -0,0 +1,27 @@
+<!--
+  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.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+  <title></title>
+</head>
+<body>
+JSP CalendarTag and CalendarModel
+
+</body>
+</html>

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/BaseRollerMenu.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/BaseRollerMenu.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/BaseRollerMenu.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/BaseRollerMenu.java Mon May  1 15:23:02 2006
@@ -0,0 +1,233 @@
+/*
+* 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.presentation.tags.menu;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.PageContext;
+import org.apache.struts.util.RequestUtils;
+
+import org.apache.roller.RollerException;
+import org.apache.roller.config.RollerConfig;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.pojos.PermissionsData;
+import org.apache.roller.pojos.UserData;
+import org.apache.roller.pojos.WebsiteData;
+import org.apache.roller.presentation.BasePageModel;
+import org.apache.roller.presentation.RollerRequest;
+import org.apache.roller.presentation.RollerSession;
+import org.apache.roller.util.Utilities;
+
+/**
+ * Base class for Roller menu objects.
+ * @author Dave Johnson
+ */
+public abstract class BaseRollerMenu
+{
+    protected String mName = null;
+	protected String mForward = null;
+	protected String mSubforwards = null;
+    protected String mEnabledProperty = null;
+    protected String mDisabledProperty = null;
+    protected List mRoles = new ArrayList();
+    protected List mPerms = new ArrayList();
+    
+    public BaseRollerMenu() 
+    {
+        init();
+    }
+    
+    public BaseRollerMenu(String name, String forward) 
+    { 
+        mName = name; 
+        mForward = forward;
+        init();
+    }
+    
+    /**
+     * Set defaults as described in WEB-INF/editor-menu.xml
+     */
+    public void init() 
+    {
+        mRoles.add("admin"); 
+        mRoles.add("editor");
+        
+        mPerms.add("admin");
+        mPerms.add("author");
+    }
+    
+    /** Name of menu */ 
+    public void setName( String v ) { mName = v; }
+
+    /** Name of menu */
+    public String getName() { return mName; }
+    
+    /** Struts forward */ 
+	public String getForward() { return mForward; }
+
+	/** Struts forward */ 
+	public void setForward( String forward ) { mForward = forward; }
+
+    /** Subforward: other forwards grouped under this menu */ 
+	public String getSubforwards() { return mSubforwards; }
+
+	/** Subforwards: other forwards grouped under this menu */ 
+	public void setSubforwards( String subforwards ) { mSubforwards = subforwards; }
+
+    /** Roles allowed to view menu, comma separated */ 
+    public void setRoles( String roles ) 
+    {
+        mRoles = Arrays.asList(Utilities.stringToStringArray(roles,","));
+    }
+    
+    /** Website permissions required to view menu, comma separated */ 
+    public void setPerms( String perms ) 
+    {
+        mPerms = Arrays.asList(Utilities.stringToStringArray(perms,","));
+    }
+    
+    /** Name of property that enables menu (or null if always enabled) */
+    public void setEnabledProperty(String enabledProperty)
+    {
+        mEnabledProperty = enabledProperty;
+    }
+
+    /** Name of property that disable menu (or null if always enabled) */
+    public void setDisabledProperty(String disabledProperty)
+    {
+        mDisabledProperty = disabledProperty;
+    }
+    
+    /** Determine if menu  should be shown to use of specified request */
+    public boolean isPermitted(HttpServletRequest req) throws RollerException
+    {
+        // first, bail out if menu is disabled
+        if (mEnabledProperty != null) 
+        {
+            String enabledProp = RollerConfig.getProperty(mEnabledProperty);
+            if (enabledProp != null && enabledProp.equalsIgnoreCase("false"))
+            {
+                return false;
+            }
+        }
+        if (mDisabledProperty != null) 
+        {
+            String disabledProp = RollerConfig.getProperty(mDisabledProperty);
+            if (disabledProp != null && disabledProp.equalsIgnoreCase("true"))
+            {
+                return false;
+            }
+        }
+        RollerSession rses = RollerSession.getRollerSession(req);
+        RollerRequest rreq = RollerRequest.getRollerRequest(req);
+        boolean ret = true;
+        
+        if (rses != null && rses.isGlobalAdminUser()) return true;
+   
+        // next, make sure that users role permits it
+        if (mRoles != null && mRoles.size() > 0)
+        {
+            ret = false;
+            Iterator roles = mRoles.iterator();
+            while (roles.hasNext())
+            {
+                String role = (String)roles.next();
+                if (req.isUserInRole(role) || role.equals("any"))  
+                {
+                    ret = true;
+                    break;
+                }
+            }
+        }
+        
+        // finally make sure that user has required website permissions
+        if (ret && mPerms != null && mPerms.size() > 0)
+        {
+            UserData user = null;
+            if (rses != null) user = rses.getAuthenticatedUser();
+            
+            WebsiteData website = rreq.getWebsite();
+            BasePageModel pageModel = (BasePageModel)req.getAttribute("model");
+            if (pageModel != null)
+            {
+                website = pageModel.getWebsite();
+            }            
+            
+            PermissionsData permsData = null;
+            if (user != null && website != null) 
+            {
+                permsData = RollerFactory.getRoller()
+                               .getUserManager().getPermissions(website, user);
+            }
+            ret = false;
+            Iterator perms = mPerms.iterator();
+            while (perms.hasNext())
+            {
+               String perm = (String)perms.next();
+               if (perm.equals("any")) 
+               {
+                   ret = true; // any permission will do (including none)
+                   break;
+               }
+               if (permsData != null && 
+                  ((perm.equals("admin")  && permsData.has(PermissionsData.ADMIN)) 
+               || (perm.equals("author")  && permsData.has(PermissionsData.AUTHOR))
+               || (perm.equals("limited") && permsData.has(PermissionsData.LIMITED))))                     
+               {
+                   ret = true; // user has one of the required permissions
+                   break;
+               }
+            }
+        }
+        return ret;
+    }
+    
+	/** Name of Struts forward menu item should link to */
+	public String getUrl( PageContext pctx ) 
+	{
+		String url = null;
+		try 
+		{
+			Hashtable params = RollerMenuModel.createParams(
+					(HttpServletRequest)pctx.getRequest());
+			params.put( RollerMenuModel.MENU_ITEM_KEY, getName() );
+
+			url = RequestUtils.computeURL( 
+				pctx, 
+				mForward, // forward
+				null,     // href
+				null,     // page
+				null,
+				params,   // params 
+				null,     // anchor
+				false );  // redirect
+		}
+		catch (Exception e)
+		{
+			pctx.getServletContext().log(
+				"ERROR in menu item creating URL",e);
+		}
+		return url;
+	}
+
+}

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/EditorNavigationBarTag.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/EditorNavigationBarTag.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/EditorNavigationBarTag.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/EditorNavigationBarTag.java Mon May  1 15:23:02 2006
@@ -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.presentation.tags.menu;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.JspException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.presentation.RollerRequest;
+import org.apache.roller.presentation.RollerSession;
+
+
+/**
+ * Draws the most complete possible Roller navigation bar based on request
+ * parameters userName, folderId and authenticated user (if there is one).
+ * @jsp.tag name="EditorNavigationBar"
+ */
+public class EditorNavigationBarTag extends MenuTag 
+{
+    private static Log mLogger = 
+        LogFactory.getFactory().getInstance(EditorNavigationBarTag.class);
+
+   	//------------------------------------------------------------- 
+	public EditorNavigationBarTag()
+	{
+	}
+
+   	//------------------------------------------------------------- 
+	public String view()
+	{
+		return emit();
+	}
+
+   	//------------------------------------------------------------- 
+    public int doEndTag(java.io.PrintWriter pw) throws JspException
+    {
+		try 
+		{
+			HttpServletRequest request = 
+				(HttpServletRequest)pageContext.getRequest(); 
+			RollerRequest rreq = RollerRequest.getRollerRequest(request);
+			RollerSession rollerSession = RollerSession.getRollerSession(request);
+			if ( rollerSession.isGlobalAdminUser() )
+			{
+				return super.doEndTag(pw);
+			}
+			else
+			{
+				return EVAL_PAGE;
+			}
+		}
+		catch (Exception e)
+		{
+			mLogger.error("EditorNavigationBarTag exception",e);
+			throw new JspException(e);
+		}
+    }
+}
+

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/Menu.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/Menu.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/Menu.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/Menu.java Mon May  1 15:23:02 2006
@@ -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.presentation.tags.menu;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.roller.RollerException;
+
+/** An individual menu which contains MenuItems */ 
+public interface Menu 
+{
+	/** Name of Menu */
+	public String getName();
+
+	/** Collection of MenuItem objects contained in this menu */
+	public java.util.Vector getMenuItems();
+
+	/** Determine if this menu is selected based on request */
+	public boolean isSelected( HttpServletRequest req ) throws RollerException;
+
+	/** Get currently selected menu item in this menu */
+	public MenuItem getSelectedMenuItem( HttpServletRequest req ) throws RollerException;
+
+    /** Url to be displayed in menu */ 
+    public String getUrl( javax.servlet.jsp.PageContext pctx );
+    
+    /** Is user principal permitted to use this menu? */ 
+    public boolean isPermitted( HttpServletRequest req ) throws RollerException;
+    
+    /** Set roles allowed to use this menu (comma separated list). */ 
+    public void setRoles( String roles );
+
+    /** Name of true/false configuration property that enables this menu */ 
+    public void setEnabledProperty( String enabledProperty );
+
+    /** Name of true/false configuration property that disables this menu */ 
+    public void setDisabledProperty( String disabledProperty );
+}
+

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuImpl.java Mon May  1 15:23:02 2006
@@ -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.presentation.tags.menu;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import javax.servlet.ServletContext;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.servlet.jsp.PageContext;
+import org.apache.struts.Globals;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.config.ForwardConfig;
+import org.apache.struts.config.ModuleConfig;
+import org.apache.struts.util.RequestUtils;
+
+import org.apache.roller.RollerException;
+import org.apache.roller.presentation.RollerContext;
+
+/////////////////////////////////////////////////////////////////////////
+
+/** MenuImpl model has collection of menus */
+public class MenuImpl extends BaseRollerMenu implements Menu 
+{
+	private String mMenuId = null;
+
+    /** Vector of MenuItemImpl objects */
+	Vector mMenuItems = new Vector();
+	
+	/** Is this the default menu? */
+	boolean mDefault = false;
+	
+	public MenuImpl() {}
+
+	/** Construct with name */
+	public MenuImpl(String n) { super(n, null); }
+	
+	/** Add MenuItemImpl to MenuImpl */
+	public void addItem( MenuItemImpl item ) { mMenuItems.addElement(item); };
+	
+	/** Parent menu's ID */ 
+	public void setMenuId( String v ) { mMenuId = v; }
+
+	/** Parent menu's ID */
+	public String getMenuId() { return mMenuId; }
+
+	/** Collection of MenuItemImpl objects */
+	public Vector getMenuItems() { return mMenuItems; }
+
+	/** Get currently selected menu item in this menu 
+	 * @throws RollerException*/
+	public MenuItem getSelectedMenuItem( HttpServletRequest req ) throws RollerException
+	{
+		return getSelectedMenuItem( req, true ) ;
+	}
+
+	/** 
+     * Get currently selected menu item in this menu 
+	 * @throws RollerException
+     */
+	public MenuItem getSelectedMenuItem( HttpServletRequest req, 
+			boolean returnDefault ) throws RollerException
+	{
+		MenuItemImpl def = null;
+		MenuItemImpl selected = null;
+		for ( int i=0; i<mMenuItems.size(); i++ ) 
+		{
+			MenuItemImpl item = (MenuItemImpl)mMenuItems.elementAt(i);
+			if ( item.isSelected( req ) )
+			{
+				selected = item;
+				break;
+			}
+		    // Set first permitted and enabled menu item in each menu as default
+			if ( item.isPermitted(req) && def == null)
+			{
+				def = item;
+			}
+		}
+		if ( selected != null )
+		{
+			return selected;
+		}
+		else if ( returnDefault )
+		{
+			return def;
+		}
+		else 
+		{
+			return null;
+		}
+	}
+    
+	/** 
+     * Get default menu item (first one that is permitted)
+	 * @throws RollerException
+     */
+	public MenuItem getDefaultMenuItem( HttpServletRequest req ) 
+        throws RollerException
+	{
+		MenuItemImpl def = null;
+		MenuItemImpl selected = null;
+		for ( int i=0; i<mMenuItems.size(); i++ ) 
+		{
+		    // Set first permitted and enabled menu item in each menu as default
+			MenuItemImpl item = (MenuItemImpl)mMenuItems.elementAt(i);
+			if (item.isPermitted(req) && def == null)
+			{
+				def = item;
+			}
+		}
+		return def;
+	}
+
+	/** 
+     * Is this menu selected? 
+	 * @throws RollerException
+     */ 
+	public boolean isSelected( HttpServletRequest req ) throws RollerException
+	{
+        boolean selected = false;
+        HttpSession ses = req.getSession(false);
+        
+        // try to get state from request param then attribute
+        String menuKey = req.getParameter(RollerMenuModel.MENU_KEY );
+        if (null == menuKey) 
+        {
+            menuKey = (String)req.getAttribute(RollerMenuModel.MENU_KEY);
+        }
+        if (menuKey != null && menuKey.equals(mName)) 
+        {
+            selected = true;
+        }
+        // next, if submenu is selected, then we're selected
+        else if (getSelectedMenuItem(req, false) != null)
+		{
+            selected = true;
+		}
+        // next, try to use Struts forward to determine state
+        else if (mForward != null)
+        {
+            ServletContext ctx = RollerContext.getServletContext();     
+			ModuleConfig mConfig = RequestUtils.getModuleConfig(req, ctx);
+            ActionMapping amapping = (ActionMapping)req.getAttribute(Globals.MAPPING_KEY);
+            List fconfigs = new ArrayList();
+			fconfigs.add(mConfig.findForwardConfig(mForward));
+            if (mSubforwards != null) {
+                String[] subforwards = mSubforwards.split(",");
+                for (int i=0; i<subforwards.length; i++) {
+                    fconfigs.add(mConfig.findForwardConfig(subforwards[i]));
+                }
+            }
+            for (Iterator iter = fconfigs.iterator(); iter.hasNext();) {
+                ForwardConfig fconfig = (ForwardConfig)iter.next();
+                String fwdPath = fconfig.getPath();
+                int end = fwdPath.indexOf(".do");
+                fwdPath = (end == -1) ? fwdPath : fwdPath.substring(0, end);
+                if  (fwdPath.equals(amapping.getPath()))
+                {
+                    selected = true;
+                    break;
+                } 
+            }
+        }
+		return selected;
+	}
+
+	/** Name of Struts forward menu item should link to */
+	public String getUrl(PageContext pctx) 
+	{
+		String url = null;
+		try 
+		{
+            // If no forward specified, use default submenu URL
+            if (mForward == null && mMenuItems != null && mMenuItems.size() > 0)
+            {
+                HttpServletRequest req = (HttpServletRequest)pctx.getRequest();
+                String surl = getDefaultMenuItem( req ).getUrl( pctx ); 
+                StringBuffer sb = new StringBuffer( surl ); 
+                if ( surl.indexOf("?") == -1 )
+                {
+                    sb.append( "?" ); 
+                }
+                else
+                {
+                    sb.append( "&amp;" ); 
+                }
+                sb.append( RollerMenuModel.MENU_KEY );
+                sb.append( "=" ); 
+                sb.append( getName() );	
+                url = sb.toString();
+            }
+            else
+            {
+                return super.getUrl(pctx);
+            }
+		}
+		catch (Exception e)
+		{
+			pctx.getServletContext().log(
+				"ERROR in menu creating URL",e);
+		}
+		return url;
+	}
+
+}
+

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuItem.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuItem.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuItem.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuItem.java Mon May  1 15:23:02 2006
@@ -0,0 +1,41 @@
+/*
+* 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.presentation.tags.menu;
+import java.util.Vector;
+import javax.servlet.http.HttpServletRequest;
+
+/** An individual menu item, contained in a Menu */ 
+public interface MenuItem 
+{
+	/** Name of menu */
+	public String getName();
+
+	/** Url to be displayed in menu */ 
+	public String getUrl( javax.servlet.jsp.PageContext pctx );
+
+	/** Determine if this menu item is selected */
+	public boolean isSelected( HttpServletRequest req );
+    
+    /** Name of true/false configuration property that enables this menu */ 
+    public void setEnabledProperty( String enabledProperty );
+
+    /** Collection of MenuItemImpl objects */
+	//public Vector getMenuItems();
+}
+

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuItemImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuItemImpl.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuItemImpl.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuItemImpl.java Mon May  1 15:23:02 2006
@@ -0,0 +1,164 @@
+/*
+* 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.presentation.tags.menu;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import org.apache.struts.Globals;
+import org.apache.struts.action.ActionMapping;
+
+import org.apache.struts.config.ForwardConfig;
+import org.apache.struts.config.ModuleConfig;
+import org.apache.struts.util.RequestUtils;
+import org.apache.roller.presentation.RollerContext;
+
+
+/////////////////////////////////////////////////////////////////////////
+
+/** 
+ * MenuImpls has collection of menu items. Multiple menus can be used 
+ * in one session, but they must have unique names.
+ */ 
+public class MenuItemImpl extends BaseRollerMenu implements MenuItem
+{
+	private String mMenuId = null;
+    
+    //private Vector mMenuItems = new Vector();
+		
+	/** Is this the default menu? */
+	boolean mDefault = false;
+
+	//---------------------------------------------------
+
+	public MenuItemImpl() {}
+
+	/** Construct with name and Struts forward */
+	public MenuItemImpl(String n, String f) 
+    { 
+        super(n, f); 
+    }
+
+	/** Parent menu's ID */ 
+	public void setMenuId( String v ) { mMenuId = v; }
+
+	/** Parent menu's ID */
+	public String getMenuId() { return mMenuId; }
+
+	/** Given a request, tells if menu item is selected */ 
+	public boolean isSelected( HttpServletRequest req )
+	{
+		boolean selected = false;
+        HttpSession ses = req.getSession(false);
+        
+        // first look for menu state in request params, then attributes
+        String itemKey = req.getParameter(RollerMenuModel.MENU_ITEM_KEY );
+        if (null == itemKey) 
+        {
+            itemKey = (String)req.getAttribute(RollerMenuModel.MENU_ITEM_KEY);
+        }
+        
+        ActionMapping amapping = (ActionMapping)req.getAttribute(Globals.MAPPING_KEY);
+        if (itemKey != null && itemKey.equals(mName)) 
+        {
+            selected = true;
+        }
+		else if (mForward != null && amapping != null) 
+		{
+            ServletContext ctx = RollerContext.getServletContext();     
+			ModuleConfig mConfig = RequestUtils.getModuleConfig(req, ctx);
+            List fconfigs = new ArrayList();
+			fconfigs.add(mConfig.findForwardConfig(mForward));
+            if (mSubforwards != null) {
+                String[] subforwards = mSubforwards.split(",");
+                for (int i=0; i<subforwards.length; i++) {
+                    fconfigs.add(mConfig.findForwardConfig(subforwards[i]));
+                }
+            }
+            for (Iterator iter = fconfigs.iterator(); iter.hasNext();) {
+                ForwardConfig fconfig = (ForwardConfig)iter.next();
+                String fwdPath = fconfig.getPath();
+                int end = fwdPath.indexOf(".do");
+                fwdPath = (end == -1) ? fwdPath : fwdPath.substring(0, end);
+                if  (fwdPath.equals(amapping.getPath()))
+                {
+                    selected = true;
+                    break;
+                } 
+            }
+		}
+        
+        // still not found, look for menu state in session attributes
+		if (ses != null && selected)
+		{
+			ses.setAttribute(mMenuId+"_"+RollerMenuModel.MENU_ITEM_KEY, mName);
+		}
+		return selected;
+	}
+    
+    /*
+    public Vector getMenuItems() 
+    {
+        return mMenuItems;
+    }
+
+    public addMenuItem(MenuItem item)
+    {
+        mMenuItems.add(item);
+    }
+    */
+}
+
+
+
+//// get menu key from request param or from cookie
+//String menuKeyName = mMenuId+"rmk";
+//String menuKey = req.getParameter("rmk");
+//if (menuKey == null) 
+//{
+//  Cookie menuCookie = RequestUtil.getCookie(req, menuKeyName);
+//  if (menuCookie != null)
+//  {
+//      menuKey = menuCookie.getValue();
+//      req.setAttribute("rmk", menuKey);
+//  }
+//}
+//// save menu key in cookie
+//RequestUtil.setCookie(res, menuKeyName, menuKey, req.getContextPath());
+//
+//// get menu item key from request param or from cookie
+//String itemKeyName = mMenuId+"rmik";
+//String itemKey = req.getParameter("rmik");
+//if (itemKey == null) 
+//{
+//  Cookie itemCookie = RequestUtil.getCookie(req, itemKeyName);
+//  if (itemCookie != null)
+//  {
+//      itemKey = itemCookie.getValue();
+//      req.setAttribute("rmik", itemKey);
+//  }
+//}
+//// save menu item key in cookie
+//RequestUtil.setCookie(res, itemKeyName, itemKey, req.getContextPath());
+        
+

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuModel.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuModel.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuModel.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuModel.java Mon May  1 15:23:02 2006
@@ -0,0 +1,37 @@
+/*
+* 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.presentation.tags.menu;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.roller.RollerException;
+
+
+/** Menu model contains Menus */ 
+public interface MenuModel 
+{
+	/** Collection of Menu objects contained in this menu model */
+	public java.util.Vector getMenus();
+
+	/** Return menu selected by current request or first menu.
+	 *  If request does not indicate a menu then first menu is returned.
+	 * @throws RollerException
+	 */
+	public Menu getSelectedMenu( HttpServletRequest req ) throws RollerException;
+}
+

Added: incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuTag.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuTag.java?rev=398712&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuTag.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/presentation/tags/menu/MenuTag.java Mon May  1 15:23:02 2006
@@ -0,0 +1,89 @@
+/*
+* 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.presentation.tags.menu;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.velocity.VelocityContext;
+import org.apache.roller.RollerException;
+import org.apache.roller.presentation.RollerRequest;
+import org.apache.roller.presentation.tags.VelocityTag;
+import org.apache.roller.presentation.velocity.ContextLoader;
+//import javax.servlet.jsp.tagext.*;
+
+
+/**
+ * @jsp.tag name="Menu"
+ */
+public class MenuTag extends VelocityTag 
+{
+	private static Log mLogger = 
+		LogFactory.getFactory().getInstance(RollerRequest.class);
+
+	/** Unique ID for this menu within the user's session. 
+	  * @jsp.attribute 
+	  */
+	public String getId() { return mMenuId; }
+    public void setId( String v ) { mMenuId= v; }
+	private String mMenuId;
+
+	/** Name of the view to be used to render the menu.
+      * The view is a Velocity template and it must be in the classpath. 
+	  * Values: tabbed, vertical, horizontal.
+	  * @jsp.attribute  required="true"
+	  */
+	public String getView() { return mView; }
+    public void setView( String v ) { mView = v; }
+	private String mView;
+
+	/** Name of the model to be used.
+	  * Must correspond to name of XML file in WEB-INF directory.
+	  * @jsp.attribute required="true"
+	  */
+	public String getModel() { return mModel; }
+    public void setModel( String v ) { mModel = v; }
+	private String mModel;
+
+    public String getTemplateClasspath()
+    {
+        return mView;
+    }
+
+   	//------------------------------------------------------------- 
+
+	public void prepareContext( VelocityContext ctx )
+	{
+		HttpServletRequest req = (HttpServletRequest)pageContext.getRequest();
+		HttpServletResponse res = (HttpServletResponse)pageContext.getResponse();
+
+		RollerMenuModel model = new RollerMenuModel( 
+			mMenuId, "/WEB-INF/"+mModel, pageContext.getServletContext() );
+		ctx.put("menuModel", model );
+		ctx.put("ctx", pageContext );
+		ctx.put("req", req );
+		ctx.put("res", res );
+		
+                ContextLoader.loadToolboxContext(req, res, ctx);
+	}
+
+}
+