weaver      2003/03/20 10:09:39

  Added:       src/java/org/apache/jetspeed/portal/portlets/viewprocessor
                        XSLViewProcessor.java JSPViewProcessor.java
                        ViewProcessorFactory.java ViewProcessor.java
                        VelocityViewProcessor.java RSSViewProcessor.java
               src/java/org/apache/jetspeed/portal/portlets
                        GenericMVCPortlet.java GenericMVCContext.java
               src/java/org/apache/jetspeed/modules/actions/portlets
                        GenericMVCAction.java PortletAction.java
                        PortletActionEvent.java
  Log:
  Relative to enhancement bug id's17747 and 17756.  
  
  The MVC portlet api will allow developers to create template-portlets from a single
  base class as opposed to previously having to extending entirely different classes
  based on the view/template technology that was to be implemented.
  
  Added:
  -GenericMVCPortlet: view-agnostic portlet for template-based presentation 
development. 
    Easily replaces all JspPortlet/VelocityPortlet classes and sub-classes.
  -PortletActionEvent: extends ActionEvent, 
  -PortletAction: Extends PortletActionEvent and provides support for event execution.
  -GenericMVCAction: Concrete implementation of the PortletAction.  Should be used in 
combination
   with the GenericMVCPortlet
  - view processors: These classes are used by the MVCPortlet to render content base 
on the "viewtype"
  registry setting.
  
  Revision  Changes    Path
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/viewprocessor/XSLViewProcessor.java
  
  Index: XSLViewProcessor.java
  ===================================================================
  /* ===================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.jetspeed.portal.portlets.viewprocessor;
  
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Iterator;
  
  import org.apache.ecs.ConcreteElement;
  
  import org.apache.jetspeed.capability.CapabilityMap;
  import org.apache.jetspeed.portal.Portlet;
  import org.apache.jetspeed.portal.portlets.*;
  import org.apache.jetspeed.portal.portlets.GenericMVCContext;
  import org.apache.jetspeed.portal.portlets.viewprocessor.*;
  import org.apache.jetspeed.services.rundata.JetspeedRunData;
  
  //Element Construction Set
  import org.apache.jetspeed.util.JetspeedClearElement;
  import org.apache.jetspeed.util.MimeType;
  import org.apache.jetspeed.util.SimpleTransform;
  
  
  //turbine
  import org.apache.turbine.util.Log;
  
  
  //SAX
  import org.xml.sax.SAXException;
  
  
  /**
   * Simple ViewProcessor which does a basic XSLT transform with the stylesheet 
parameter
   * and the given URL.
   *
   * @author [EMAIL PROTECTED]
   * @version $Id: XSLViewProcessor.java,v 1.1.2.2 2003/02/24 21:52:27 tkuebler Exp $
   *
   */
  public class XSLViewProcessor
      implements ViewProcessor
    {
  
      /**
      The stylesheet parameter
      */
      public static final String STYLESHEET = "stylesheet";
      public static final String ERROR_NOT_VALID = "This does not appear to be an XML 
document";
      public static final String INVALID_TYPE = "Unable to display for this browser";
      private Hashtable stylesheets = null;
  
      /**
      Constructor
      */
      public XSLViewProcessor()
        {
        }
  
      /**
      This methods outputs the content of the portlet for a given
      request.
  
      @param data the RunData object for the request
      @return the content to be displayed to the user-agent
      */
      public Object processView(GenericMVCContext context)
        {
          getStylesheets((Portlet) context.get("portlet")); // used to be in portlet 
init, do we
  
          // need to get this functionality
          // into the model?
          CapabilityMap map = ((JetspeedRunData) context.get("data")).getCapability();
          String type = map.getPreferredType().toString();
          ConcreteElement content = new JetspeedClearElement(INVALID_TYPE);
          String stylesheet = (String) stylesheets.get(type);
  
          if (stylesheet != null)
            {
  
              try
                {
                  content = new JetspeedClearElement(
                              SimpleTransform.transform(
                                  ((Portlet) 
context.get("portlet")).getPortletConfig().getURL(), 
                                  stylesheet, 
                                  ((Portlet) 
context.get("portlet")).getPortletConfig().getInitParameters()));
                }
              catch (SAXException e)
                {
                  Log.error(e);
                  content = new JetspeedClearElement(e.getMessage());
                }
            }
  
          return content;
        }
  
      /**
      This portlet supports has many types as those
      it has stylesheets defined for in its parameters
  
      @see Portlet#supportsType
      @param mimeType the MIME type queried
      @return true if the portlet knows how to display
      content for mimeType
      */
      public boolean supportsType(MimeType mimeType)
        {
  
          Enumeration en = stylesheets.keys();
  
          while (en.hasMoreElements())
            {
  
              String type = (String) en.nextElement();
  
              if (type.equals(mimeType.toString()))
                {
  
                  return true;
                }
            }
  
          return false;
        }
  
      private void getStylesheets(Portlet portlet)
        {
          stylesheets = new Hashtable();
  
          Iterator en = portlet.getPortletConfig().getInitParameterNames();
  
          while (en.hasNext())
            {
  
              String name = (String) en.next();
              String base = MimeType.HTML.toString();
  
              if (name.startsWith(STYLESHEET))
                {
  
                  int idx = -1;
  
                  if ((idx = name.indexOf(".")) > -1)
                    {
                      base = name.substring(idx + 1, name.length());
                    }
  
                  stylesheets.put(base, 
portlet.getPortletConfig().getInitParameter(name));
                }
            }
        }
  
      /** Process the template passed in the context
       * (context.get("template")).  Invoked by the GenericMVCPortlet
       * after action handling to process the template type
       * in question.
       *
       */
      public void init(Portlet portlet)
        {
        }
    }
  
  
  
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/viewprocessor/JSPViewProcessor.java
  
  Index: JSPViewProcessor.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  /*
   * JSPViewProcessor.java
   *
   * Created on January 27, 2003, 5:37 PM
   */
  package org.apache.jetspeed.portal.portlets.viewprocessor;
  
  
  // Ecs
  import org.apache.ecs.ElementContainer;
  import org.apache.ecs.StringElement;
  
  
  // Jetspeed portal
  import org.apache.jetspeed.portal.Portlet;
  import org.apache.jetspeed.portal.portlets.*;
  import org.apache.jetspeed.portal.portlets.GenericMVCContext;
  import org.apache.jetspeed.portal.portlets.viewprocessor.*;
  import org.apache.jetspeed.services.TemplateLocator;
  
  import org.apache.turbine.services.TurbineServices;
  import org.apache.turbine.services.jsp.JspService;
  import org.apache.turbine.util.Log;
  
  // Turbine util
  import org.apache.turbine.util.RunData;
  
  
  /**
   *
   * @author  tkuebler
   */
  public class JSPViewProcessor
      implements ViewProcessor
    {
  
      /** Creates a new instance of JSPViewProcessor */
      public JSPViewProcessor()
        {
        }
  
      public Object processView(GenericMVCContext context)
        {
  
          String template = (String) context.get("template");
          Log.info("JSPViewProcessor - processing template " + template);
  
          try
            {
  
              //
              // gets the jsp page from the xreg configuration
              // NOTE: wouldn't it be better to get the param from the PSML?
              //
              if (-1 == template.indexOf(".jsp"))
                {
                  template = template + ".jsp";
                }
  
              Log.info("JSPViewProcessor - locating template - " + ((RunData) 
context.get("data")).toString() + " - " + template);
  
              //we use the template locator to translate the template
              String locatedTemplate = TemplateLocator.locatePortletTemplate((RunData) 
context.get("data"), template);
              Log.info("JSPViewProcessor - located template: " + locatedTemplate);
  
              JspService service = (JspService) 
TurbineServices.getInstance().getService(JspService.SERVICE_NAME);
  
              // this is only necessary if we ddon't run in a JSP page environment
              // but better be safe than sorry...
              service.addDefaultObjects((RunData) context.get("data"));
  
              // Allow access to portlet from .jsp template
              ((RunData) context.get("data")).getRequest().setAttribute("portlet", 
(Portlet) context.get("portlet"));
  
              // put context in attribute so you can get to it from .jsp template
              ((RunData) context.get("data")).getRequest().setAttribute("context", 
context);
  
              // Add js_peid out of convenience
              ((RunData) context.get("data")).getRequest().setAttribute("js_peid", 
((Portlet) context.get("portlet")).getID());
  
              // handle request
              service.handleRequest((RunData) context.get("data"), locatedTemplate);
            }
          catch (Exception e)
            {
  
              String message = "JspViewProcessor: Could not include the following JSP 
Page:  [" + template + "] :\n\t" + 
                               e.getMessage();
              Log.error(message, e);
  
              return new StringElement(message);
            }
  
          return new ElementContainer();
        }
  
      /** Process the template passed in the context
       * (context.get("template")).  Invoked by the GenericMVCPortlet
       * after action handling to process the template type
       * in question.
       *
       */
      public void init(Portlet portlet)
        {
        }
    }
  
  
  
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/viewprocessor/ViewProcessorFactory.java
  
  Index: ViewProcessorFactory.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
   
  /*
   * ViewProcessorFactory.java
   *
   * Created on January 27, 2003, 5:16 PM
   */
  package org.apache.jetspeed.portal.portlets.viewprocessor;
  
  import org.apache.jetspeed.portal.portlets.*;
  import org.apache.jetspeed.portal.portlets.viewprocessor.*;
  import org.apache.turbine.util.Log;
  
  
  /**
   * Creates the appropriate ViewProcessor to process the template
   *
   * @author  tkuebler
   * @version $Id: ViewProcessorFactory.java,v 1.1.2.2 2003/02/24 21:52:27 tkuebler 
Exp $
   * @stereotype factory
   * 
   */
  public class ViewProcessorFactory
    {
  
      /** Creates a new instance of ViewProcessorFactory */
      public ViewProcessorFactory()
        {
  
          // load the type -> processor map
          // this should probably be a turbine service...
        }
  
      public static ViewProcessor getViewProcessor(String viewType)
        {
  
          ViewProcessor viewProcessor;
  
          // figure out the type of portlet based on the map
          // will use properties file or xreg based map later
          // create and return appropriate processor
          // hardcoded for now, will use some config file map in future
          if (viewType.equals("Velocity"))
            {
              Log.info("ViewProcessorFactory - creating Velocity processor");
              viewProcessor = new VelocityViewProcessor();
            }
          else if (viewType.equals("JSP"))
            {
              Log.info("ViewProcessorFactory - creating JSP processor");
              viewProcessor = new JSPViewProcessor();
            }
          else if (viewType.equals("XSL"))
            {
              Log.info("ViewProcessorFactory - creating XSL processor");
              viewProcessor = new XSLViewProcessor();
            }
          else if (viewType.equals("RSS"))
            {
              Log.info("ViewProcessorFactory - creating RSS processor");
              viewProcessor = new RSSViewProcessor();
            }
          else
            {
              Log.error("ViewProcessorFactory - problem figuring out what view 
processor type you want - " + 
                        viewType);
              Log.error("ViewProcessorFactory - returing a JSP processor");
              viewProcessor = new JSPViewProcessor();
            }
  
          return viewProcessor;
        }
    }
  
  
  
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/viewprocessor/ViewProcessor.java
  
  Index: ViewProcessor.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  /*
   * ViewProcessor.java
   *
   * Created on January 27, 2003, 5:18 PM
   */
  package org.apache.jetspeed.portal.portlets.viewprocessor;
  
  import org.apache.ecs.ConcreteElement;
  
  import org.apache.jetspeed.portal.Portlet;
  import org.apache.jetspeed.portal.PortletException;
  import org.apache.jetspeed.portal.portlets.*;
  
  /**
   * Interface that defines a ViewProcessor.  This is what the
   * GenericMVCPortlet uses via the ViewProcessorFactory to
   * do the template processing portion of the MVC design pattern.
   * 
   * @author  tkuebler
   * @version 1.0
   * @stereotype plug-in point
   */
  public interface ViewProcessor
    {
  
      /**
       * Process the template passed in the context
       * (context.get("template")).  Invoked by the GenericMVCPortlet
       * after action handling to process the template type
       * in question.
       */
      void init(Portlet portlet)
                throws PortletException;
  
      Object processView(GenericMVCContext context);
    }
  
  
  
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/viewprocessor/VelocityViewProcessor.java
  
  Index: VelocityViewProcessor.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  /*
   * VelocityViewProcessor.java
   *
   *
   * Created on January 27, 2003, 8:54 PM
   */
  package org.apache.jetspeed.portal.portlets.viewprocessor;
  
  import org.apache.jetspeed.portal.Portlet;
  import org.apache.jetspeed.portal.PortletException;
  import org.apache.jetspeed.portal.portlets.*;
  import org.apache.jetspeed.portal.portlets.GenericMVCContext;
  import org.apache.jetspeed.portal.portlets.viewprocessor.*;
  import org.apache.jetspeed.services.TemplateLocator;
  import org.apache.jetspeed.util.JetspeedClearElement;
  
  import org.apache.turbine.services.velocity.TurbineVelocity;
  import org.apache.turbine.util.Log;
  import org.apache.turbine.util.RunData;
  
  
  /**
   *
   * @author  tkuebler
   */
  public class VelocityViewProcessor
      implements ViewProcessor
    {
  
      /** Creates a new instance of VelocityViewProcessor */
      public VelocityViewProcessor()
        {
        }
  
      public void init(Portlet portlet)
                throws PortletException
        {
        }
  
      /** Process the template passed in the context
       * (context.get("template")).  Invoked by the GenericMVCPortlet
       * after action handling to process the template type
       * in question.
       *
       */
      public Object processView(GenericMVCContext context)
        {
  
          // generate the content
          JetspeedClearElement element = null;
          String template = (String) context.get("template");
          Log.info("VelocityViewProcessor - processing " + template);
  
          try
            {
  
              if (-1 == template.indexOf(".vm"))
                {
                  template = template + ".vm";
                }
  
              Log.info("VelocityViewProcessor - locating template - " + 
                       ((RunData) context.get("data")).toString() + template);
  
              String templatePath = TemplateLocator.locatePortletTemplate(
                                            (RunData) context.get("data"), 
                                            template);
  
              // need to add cache support
              String s = TurbineVelocity.handleRequest(context, templatePath);
  
              //setExpirationMillis(cachePeriod + System.currentTimeMillis());
              element = new JetspeedClearElement(s);
            }
          catch (Exception e)
            {
              element = new JetspeedClearElement(e.toString());
              Log.error("VelocityViewProcessor - had problems handling request - " + 
e);
              e.printStackTrace();
            }
  
          TurbineVelocity.requestFinished(context);
  
          if (element == null)
            {
              element = new JetspeedClearElement("");
            }
  
          return element;
        }
    }
  
  
  
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/viewprocessor/RSSViewProcessor.java
  
  Index: RSSViewProcessor.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.jetspeed.portal.portlets.viewprocessor;
  
  import java.io.IOException;
  
  //standard java stuff
  import java.io.Reader;
  import java.io.StringReader;
  
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Iterator;
  
  
  //JAXP support
  import javax.xml.parsers.DocumentBuilder;
  import javax.xml.parsers.DocumentBuilderFactory;
  
  import org.apache.ecs.ConcreteElement;
  
  import org.apache.jetspeed.cache.disk.JetspeedDiskCache;
  import org.apache.jetspeed.capability.CapabilityMap;
  import org.apache.jetspeed.capability.CapabilityMapFactory;
  import org.apache.jetspeed.portal.Portlet;
  import org.apache.jetspeed.portal.PortletException;
  import org.apache.jetspeed.portal.portlets.*;
  import org.apache.jetspeed.portal.portlets.GenericMVCContext;
  import org.apache.jetspeed.portal.portlets.viewprocessor.*;
  import org.apache.jetspeed.services.rundata.JetspeedRunData;
  
  // Element Construction Set
  import org.apache.jetspeed.util.JetspeedClearElement;
  import org.apache.jetspeed.util.MimeType;
  import org.apache.jetspeed.util.SimpleTransform;
  import org.apache.jetspeed.xml.JetspeedXMLEntityResolver;
  
  import org.apache.turbine.util.Log;
  import org.apache.turbine.util.RunData;
  
  
  // XML stuff
  import org.w3c.dom.Document;
  import org.w3c.dom.Node;
  import org.w3c.dom.NodeList;
  
  import org.xml.sax.InputSource;
  import org.xml.sax.SAXException;
  
  
  /**
  <p>Portlet which renders RDF Site Summary.</p>
  <p>This portlet uses XML stylesheet for transforming the RSS
  content into display markup depending on the MimeType requested
  by the user-agent</p>
  <p>It accepts the following parameters :
  <dl>
  <dt>itemDisplayed</dt>
  <dd>The number of items from the RSS file to display on screen. Default 15 for HTML, 
5 for WML</dd>
  <dt>showDescription</dt>
  <dd>Should the portlet show the item descriptions. Must be true or false. Default: 
true for HTML, false for WML</dd>
  <dt>showTitle</dt>
  <dd>Should the portlet show the channel description. Must be true or false. Default: 
true for HTML, false for WML</dd>
  <dt>stylesheet[.<mime>]</dt>
  <dd>The stylesheet URL. If a mime-type is specified, the stylesheet
  is only used for this mime-type</dd>
  </dl>
  @author <A HREF="mailto:[EMAIL PROTECTED]">Rapha�l Luta</A>
  @version $Id: RSSViewProcessor.java,v 1.1.2.2 2003/02/24 21:52:27 tkuebler Exp $
  */
  public class RSSViewProcessor
      implements ViewProcessor
    {
  
      private static final String XMLDECL = "<?xml version=";
      public static final String ERROR_NOT_VALID = "This does not appear to be an RSS 
document";
      public static final String INVALID_TYPE = "Unable to display for this browser";
      private Document document = null;
      private Hashtable stylesheets = null;
      private Hashtable params = null;
  
      /**
          This method loads the init parameters and
          parse the document tied to this portlet
      */
      public void init(Portlet portlet)
                throws PortletException
        {
  
          DocumentBuilder parser = null;
          String url = null;
  
          // load stylesheets available
          stylesheets = new Hashtable();
          params = new Hashtable();
  
          Iterator i = portlet.getPortletConfig().getInitParameterNames();
  
          while (i.hasNext())
            {
  
              String name = (String) i.next();
              String base = MimeType.HTML.toString();
  
              if (name.startsWith("stylesheet"))
                {
  
                  int idx = -1;
  
                  if ((idx = name.indexOf(".")) > -1)
                    {
                      base = name.substring(idx + 1, name.length());
                    }
  
                  stylesheets.put(base, 
portlet.getPortletConfig().getInitParameter(name));
                }
              else
                {
                  params.put(name.toLowerCase(), 
portlet.getPortletConfig().getInitParameter(name));
                }
            }
  
          // read content, clean it, parse it and cache the DOM
          try
            {
  
              final DocumentBuilderFactory docfactory = 
DocumentBuilderFactory.newInstance();
  
              //Have it non-validating
              docfactory.setValidating(false);
              parser = docfactory.newDocumentBuilder();
              parser.setEntityResolver(new JetspeedXMLEntityResolver());
              url = portlet.getPortletConfig().getURL();
  
              String content = JetspeedDiskCache.getInstance().getEntry(url).getData();
              CapabilityMap xmap = 
CapabilityMapFactory.getCapabilityMap(CapabilityMapFactory.AGENT_XML);
  
              // no cache yet // portlet.setContent( new 
JetspeedClearElement(content), xmap );
              InputSource isrc = new InputSource(this.cleanse(content));
              isrc.setSystemId(url);
              isrc.setEncoding("UTF-8");
              this.document = parser.parse(isrc);
            }
          catch (Throwable t)
            {
  
              String message = "RSSPortlet:  Couldn't parse out XML document -> " + 
url;
              Log.error(message, t);
              throw new PortletException(t.getMessage());
            }
  
          //Determine title and description for this portlet
          String title = null;
          String description = null;
  
          //now find the channel node.
          Node channel = null;
          NodeList list = document.getElementsByTagName("channel");
  
          if (list.getLength() != 1)
            {
              throw new PortletException(ERROR_NOT_VALID);
            }
  
          channel = list.item(0);
  
          Node tn = getNode(channel, "title");
  
          if (tn == null)
            {
              throw new PortletException(ERROR_NOT_VALID);
            }
          else
            {
              title = tn.getFirstChild().getNodeValue();
            }
  
          Node dn = getNode(channel, "description");
  
          if (dn != null)
            {
              description = dn.getFirstChild().getNodeValue();
            }
  
          portlet.setTitle(title);
          portlet.setDescription(description);
        }
  
      /**
      This methods outputs the content of the portlet for a given
      request.
  
      @param data the RunData object for the request
      @return the content to be displayed to the user-agent
      */
      public Object processView(GenericMVCContext context)
        {
  
          try
            {
              init((Portlet) context.get("portlet"));
            }
          catch (PortletException pe)
            {
              pe.printStackTrace();
              Log.error("RSSViewProcessor - error: " + pe);
            }
  
          RunData data = (RunData) context.get("data");
          CapabilityMap map = ((JetspeedRunData) data).getCapability();
          String type = map.getPreferredType().toString();
          ConcreteElement content = new JetspeedClearElement(INVALID_TYPE);
          String stylesheet = (String) stylesheets.get(type);
  
          if (stylesheet != null)
            {
  
              try
                {
                  content = new 
JetspeedClearElement(SimpleTransform.transform(this.document, stylesheet, 
this.params));
  
                  // no caching yet // setContent( content, map );
                }
              catch (SAXException e)
                {
                  Log.error(e);
                  content = new JetspeedClearElement(e.getMessage());
                }
            }
          else
            {
              content = new JetspeedClearElement("stylesheet not defined");
            }
  
          return content;
        }
  
      /**
      This portlet supports has many types as those
      it has stylesheets defined for in its parameters
  
      @see Portlet#supportsType
      @param mimeType the MIME type queried
      @return true if the portlet knows how to display
      content for mimeType
      */
      public boolean supportsType(MimeType mimeType)
        {
  
          Enumeration en = stylesheets.keys();
  
          while (en.hasMoreElements())
            {
  
              String type = (String) en.nextElement();
  
              if (type.equals(mimeType.toString()))
                {
  
                  return true;
                }
            }
  
          return false;
        }
  
      /**
      Utility method for traversing the document parsed
      DOM tree and retrieving a Node by tagname
  
      @param start the parent node for the search
      @param name the tag name to be searched for
      @return the first child node of start whose tagname
      is name
      */
      private final Node getNode(Node start, String name)
        {
  
          NodeList list = start.getChildNodes();
  
          for (int i = 0; i < list.getLength(); ++i)
            {
  
              Node node = list.item(i);
  
              if (node.getNodeName().equals(name))
                {
  
                  return node;
                }
            }
  
          return null;
        }
  
      /**
      Given a URL to some content, clean the content to Xerces can handle it
      better.  Right now this involves:
      <ul>
          <li>
              If the document doesn't begin with "<?xml version=" truncate the
              content until this is the first line
          </li>
  
      </ul>
  
      */
      private Reader cleanse(String content)
                      throws IOException
        {
  
          String filtered = null;
          int start = content.indexOf(XMLDECL);
  
          if (start <= 0)
            {
              filtered = content;
            }
          else
            {
              filtered = content.substring(start, content.length());
            }
  
          return new StringReader(filtered);
        }
    }
  
  
  
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/GenericMVCPortlet.java
  
  Index: GenericMVCPortlet.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  /*
   * GenericMVCPortlet.java
   *
   * Created on January 27, 2003, 5:10 PM
   */
  package org.apache.jetspeed.portal.portlets;
  
  import javax.servlet.http.HttpServletRequest;
  
  import org.apache.ecs.ConcreteElement;
  
  import org.apache.jetspeed.portal.PortletException;
  import org.apache.jetspeed.portal.portlets.viewprocessor.*;
  // using the * form due to the puggable nature
  //ie no recompile to support new view processors
  import org.apache.jetspeed.util.template.JetspeedLink;
  import org.apache.jetspeed.util.template.JetspeedTemplateLink;
  
  import org.apache.turbine.modules.ActionLoader;
  import org.apache.turbine.services.pull.TurbinePull;
  import org.apache.turbine.util.Log;
  import org.apache.turbine.util.RunData;
  
  /**
   * Provides the basic MVC Portlet functionality independant of any
   * specific view technology (ie jsp, velocity, xslt, etc).  It handles
   * the views via a ViewProcessor, which is a pluggable, factory
   * created, run time module for which ever view technology your portlet
   * uses.
   *
   * There is no need to extend this portlet class, just define your porlet
   * entry in the registy as a child of this class and provide your template
   * and action class (extened from GenericMVCAction of course) and you
   * are good to go.
   *
   * Example .xreg entry:
   *
   *  <portlet-entry name="GenericMVCPortlet" hidden="false"
   *       type="abstract" application="false">
   *       <security-ref parent="default"/>
   *       <classname>com.cisco.it.psf.portal.portlets.GenericMVCPortlet</classname>
   *      <media-type ref="html"/>
   *      <url cachedOnURL="true"/>
   *  </portlet-entry>
   *  <portlet-entry name="VelocityMVCExample" hidden="false" type="ref"
   *      parent="GenericMVCPortlet" application="false">
   *      <meta-info>
   *          <title>Velocity MVC Portlet</title>
   *          <description>Velocity Generic MVC Portlet</description>
   *      </meta-info>
   *      <classname>com.cisco.it.psf.portal.portlets.GenericMVCPortlet</classname>
   *      <parameter name="template" value="mvc-example" hidden="true"
   *          cachedOnName="true" cachedOnValue="true"/>
   *      <parameter name="viewtype" value="Velocity" hidden="true"
   *          cachedOnName="true" cachedOnValue="true"/>
   *      <parameter name="action"
   *          value="portlets.ExampleGenericMVCAction" hidden="true"
   *          cachedOnName="true" cachedOnValue="true"/>
   *      <url cachedOnURL="true"/>
   *  </portlet-entry>
   *
   * See the Velocity and JSP MVC Portlet examples for template and action class clues.
   *
   * To add new view processor types, simply implement the ViewProcessor
   * interface and add your type into the <b>viewprocessor.properties</b> file as 
   * shown in the example below:
   *
   * mvc.viewprocessor.Velocity = 
org.apache.jetspeedportlets.viewprocessors.VelocityViewProcessor
   * mvc.viewprocessor.JSP = 
org.apache.jetspeedportlets.viewprocessors.JSPViewProcessor
   * mvc.viewprocessor.XSL = 
org.apache.jetspeedportlets.viewprocessors.XSLViewProcessor
   *
   * @author  tkuebler
   * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
   * @version $Id: GenericMVCPortlet.java,v 1.11 2003/02/11 23:09:18 tkuebler Exp $
   * @stereotype role
   */
  public class GenericMVCPortlet extends AbstractInstancePortlet
  {
  
      // need cache timer, etc
      private String viewType = "ERROR: not set in config";
      private String actionName = "ERROR: not set in config";
      private String template = "ERROR: not set in config";
      private String configureTemplate;
      private String maximizedTemplate;
      private ViewProcessor processor = null;
      private boolean providesCustomization;
  
      public void init() throws PortletException
      {
  
          //STW: Added caching setUp  
          if (isCacheable())
          {
              try
              {
                  setExpirationMillis(
                      Long.parseLong(
                          
getPortletConfig().getInitParameter("cache-period-milliseconds", "0")));
              }
              catch (NumberFormatException e)
              {
                  setExpirationMillis(0);
              }
          }
          
          //STW: check custimization attribute
          String provConf = 
getPortletConfig().getInitParameter("provides.customization", "false");
          providesCustomization = new Boolean(provConf).booleanValue();
          
          // pull the important info out of the portlet config
          actionName = getPortletConfig().getInitParameter("action");
          // STW: Allow subclasses to set viewtype for backward compatibillity
          if (getPortletConfig().getInitParameter("viewtype") != null)
          {
              viewType = getPortletConfig().getInitParameter("viewtype");
          }
  
          template = getPortletConfig().getInitParameter("template");
  
          // get viewprocessor from factory
          Log.info(
              "GenericMVCPortlet - creating view processor for viewtype = "
                  + viewType
                  + ", template = "
                  + template);
          processor = ViewProcessorFactory.getViewProcessor(viewType);
  
          // initialize view processor with portlet info
          processor.init(this);
  
          // should make this config file driven
          // STW removed this so subclasses can decide this for
          // themselves.
          // setCacheable(false);
      }
  
  /**
   * Whether or not this portlet provides it's own customizer.
   * This can be set at the registry level by adding a 
   * boolean paramter "provides.customization"
   * Defaults to "false"
   */
      public boolean providesCustomization()
      {
          return providesCustomization;
      }
  
      public ConcreteElement getContent(RunData rundata)
      {
  
          //if caching is turned off or no expiration time set, generate and return 
the content
          if (!isCacheable() || null == getExpirationMillis())
          {
              return buildContent(rundata);
          }
  
          //is the cached content still valid, if not, generate and return the content
          if (getExpirationMillis().longValue() <= System.currentTimeMillis())
          {
              return buildContent(rundata);
          }
  
          //else, the cached content is fine to be returned
          return getContent(rundata, null, true);
  
      }
  
      protected ConcreteElement buildContent(RunData rundata)
      {
          // create a new context
          // populate it with data
          GenericMVCContext context = new 
GenericMVCContext(TurbinePull.getGlobalContext());
          context.put("data", rundata);
          context.put("portlet", this);
          context.put("conf", this.getPortletConfig());
          context.put("skin", this.getPortletConfig().getPortletSkin());
          context.put("template", template);
          context.put("viewType", viewType);
          populateRequest(rundata);
  
          // put references to the pull tools in the context
          TurbinePull.populateContext(context, rundata);
          Object fTool = context.get("format");
          // Initialize jlink and jslink tools with ourselves
          // to enable links between portlets
          Object jlink = context.get("jlink");
  
          if (jlink instanceof JetspeedTemplateLink)
          {
              ((JetspeedTemplateLink) jlink).setPortlet(this);
          }
  
          Object jslink = context.get("jslink");
  
          if (jslink instanceof JetspeedLink)
          {
              ((JetspeedLink) jslink).setPortlet(this);
          }
  
          // Handle Action
          if (actionName != null)
          {
  
              try
              {
  
                  // store the context so that the action can retrieve it
                  //Log.debug("VelocityPortlet found action "+actionName+" context 
"+context);
                  // note: the name it is stored under is legacy, leaving it this way
                  // because some of the routines fall back to old default behavior
                  // of the velocity portlet and might depend on the name
                  
rundata.getTemplateInfo().setTemplateContext("VelocityPortletContext", context);
  
                  if (Log.getLogger().isDebugEnabled())
                  {
                      Log.debug(
                          "GenericMVCPortlet: Executing action ["
                              + actionName
                              + "] for portlet ["
                              + this.getName()
                              + "]");
                  }
  
                  ActionLoader.getInstance().exec(rundata, actionName);
              }
              catch (Exception e)
              {
                  Log.error("GenericMVCPortlet - error executing action" + e);
                  e.printStackTrace();
              }
          }
  
          // Process View
          // call processView method
          Log.info("GenericMVCPortlet - calling processView on processor");
  
          ConcreteElement result = (ConcreteElement) processor.processView(context);
          Log.info("GenericMVCPortlet - setting this portlet's content");
          clearContent();
          setContent(result); // only needed when caching is true I believe
  
          // return result
          return result;
      }
      /**
       * @see setViewType()
       * @return String
       */
      protected String getViewType()
      {
          return viewType;
      }
  
      /**
      * STW: Added for backward compatibility when using this
       * class to subclass the existing Jsp and Velocity portlets
       * so they can set their view prior to super.init();
       * @param viewType The viewType to set
       */
      protected void setViewType(String viewType)
      {
          this.viewType = viewType;
      }
  
      /**
       * This is called before any action execution happens.
       * This provides backward compatibility to JspPortletActions
       * who retreive  information, like Portlet, from the request
       * BEFORE the ViewProcessor.processView() is called
       * which normally populates the request with Context objects.
       * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
       */
      protected void populateRequest(RunData rundata)
      {
          HttpServletRequest request = rundata.getRequest();
          request.setAttribute("data", rundata);
          request.setAttribute("portlet", this);
          request.setAttribute("conf", this.getPortletConfig());
          request.setAttribute("skin", this.getPortletConfig().getPortletSkin());
          request.setAttribute("template", template);
          request.setAttribute("viewType", viewType);
      }
  }
  
  
  
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/GenericMVCContext.java
  
  Index: GenericMVCContext.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  /*
   * GenericMVCContext.java
   *
   * Created on January 27, 2003, 8:47 PM
   */
  package org.apache.jetspeed.portal.portlets;
  
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.Set;
  
  import org.apache.velocity.context.Context;
  
  /**
   *
   * Context that holds all the data you want to transfer to your view.  You
   * populate this during your action handling.
   * <p>
   * This context also supports chaining of additional contexts.  The initial
   * context created by this object always has priority over an addtional 
   * chained objects.  In short matching keys within the initial context
   * will "hide" matching keys within the addtional context(s).
   * </p>
   * 
   * @author  tkuebler
   * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
   * @version $Id: GenericMVCContext.java,v 1.3 2003/02/05 00:32:13 tkuebler Exp $
   * @stereotype thing
   * 
   */
  
  /*
   * Note:
   *
   * create the generic context interface later
   * just use Velocity's for now
   *
   */
  public class GenericMVCContext implements Context
  {
  
      private HashMap data;
      private HashSet additionalContexts;
  
      /** Creates a new instance of GenericMVCContext */
      public GenericMVCContext()
      {
          data = new HashMap();
          additionalContexts = new HashSet();
  
      }
  
      /**
       * Adds an existing Collection of contexts into this one.  
       * Externally added contexts are maintained indvidually
       * and are not merged into the existing context.
       * Done to facilitate the context chanining.
       * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
       */
      public GenericMVCContext(Collection contexts)
      {
          this();
          additionalContexts.addAll(contexts);
      }
      
       /**
       * Adds an existing context into this one.  
       * Externally added contexts are maintained indvidually
       * and are not merged into the existing context
       * Done to facilitate the context chanining.
       * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
       */
      public GenericMVCContext(Context context)
      {
          this();
          additionalContexts.add(context);
      }
      
     
      public boolean containsKey(java.lang.Object key)
      {
          boolean found = data.containsKey(key);
          if (!found)
          {
              Iterator itr = additionalContexts.iterator();
              while (itr.hasNext() && !found)
              {
                  found = ((Context) itr.next()).containsKey(key);
              }
          }
  
          return found;
      }
  
      public Object get(java.lang.String key)
      {
          Object value = data.get(key);
  
          // Proceed to search chained contexts
          if (value == null)
          {
              Iterator itr = additionalContexts.iterator();
              while (itr.hasNext() && value == null)
              {
                  value = ((Context) itr.next()).get(key);
              }
          }
  
          return value;
      }
  
      public Object[] getKeys()
      {
          Set keySet = data.keySet();
  
          Iterator itr = additionalContexts.iterator();
  
          while (itr.hasNext())
          {
              Object[] keys = ((Context) itr.next()).getKeys();
              for (int i = 0; i < keys.length; i++)
              {
                  keySet.add(keys[i]);
              }
          }
  
          // (Object[])java.lang.reflect.Array.newInstance((new 
Object()).getClass(),2);
          return data.keySet().toArray();
      }
  
      public Object put(java.lang.String key, java.lang.Object value)
      {
  
          return data.put(key, value);
      }
  
      public Object remove(java.lang.Object key)
      {
          Object obj = data.remove(key);
          if (obj == null)
          {
              Iterator itr = additionalContexts.iterator();
              while (itr.hasNext() && obj == null)
              {
                  obj = ((Context) itr.next()).remove(key);
              }
          }
  
          return obj;
      }
      
       /**
       * Add an additional context to this one
       * @param Context context Additional Context object to add.
       * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
       */
      public void addContext(Context context)
      {
          additionalContexts.add(context);
      }
      
      /**
       * This Collection is "live" as it is the same Collection
       * that maintains this Context's chained contexts.  This
       * Collection DOES NOT include objects maintained in
       * the initial context.
       * @return a Collection all the chained contexts
       * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>-
       */
      public Collection getChainedContexts()
      {
          return additionalContexts;
      }
  
  }
  
  
  
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/modules/actions/portlets/GenericMVCAction.java
  
  Index: GenericMVCAction.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  /*
   * GenericMVCAction.java
   *
   * Created on January 29, 2003, 2:56 PM
   */
  package org.apache.jetspeed.modules.actions.portlets;
  
  import org.apache.jetspeed.portal.Portlet;
  import org.apache.jetspeed.portal.PortletInstance;
  import org.apache.jetspeed.portal.portlets.GenericMVCContext;
  import org.apache.jetspeed.portal.portlets.GenericMVCPortlet;
  import org.apache.jetspeed.services.persistence.PersistenceManager;
  import org.apache.jetspeed.services.persistence.PortalPersistenceException;
  import org.apache.jetspeed.services.rundata.JetspeedRunData;
  import org.apache.jetspeed.util.PortletSessionState;
  
  import org.apache.turbine.util.Log;
  import org.apache.turbine.util.RunData;
  
  import org.apache.velocity.context.Context;
  
  
  /**
   * Provides standard portal and MVC related action functionality.  Developers
   * extend this class for thier own actions and provide implementations of the
   * build*Context methods apropos to thier portlet needs.
   *
   * @author  tkuebler
   * @version $Id: GenericMVCAction.java,v 1.8 2003/02/11 23:09:17 tkuebler Exp $
   * @stereotype moment-interval
   */
  public class GenericMVCAction
      extends PortletAction
    {
  
      /** Creates a new instance of GenericMVCAction */
      public GenericMVCAction()
        {
  
          // remove if empty at end of design phase
        }
  
      // override what you need to here
      protected void perform(RunData rundata)
                      throws Exception
        {
  
          Context context = getContext(rundata);
  
          if ((context != null) && (rundata.getParameters().getString("action") != 
null))
            {
  
              // if context is already defined and Actions defined, events
              // have already been processed, call doPerform
              Log.debug("Action detected with action + context");
              doPerform(rundata, context);
            }
          else
            {
  
              // if context is null, create a new one
              if (context == null)
                {
                  Log.debug("Action: building action context");
                  context = new GenericMVCContext();
                  
rundata.getTemplateInfo().setTemplateContext("VelocityActionContext", context);
                }
  
              try
                {
  
                  // process implicit ActionEvent invocation
                  Log.debug("Action: try executing events");
  
                  GenericMVCPortlet portlet = (GenericMVCPortlet) 
context.get("portlet");
  
                  if (portlet != null)
                    {
  
                      // verify this portlet is the one requested by checking the
                      // js_peid request var.  If there is no js_peid
                      // do not worry a about verifing.  helps with backward compat.
                      if (rundata.getParameters().getString("js_peid") == null || 
PortletSessionState.isMyRequest(rundata, portlet))
                        {
                          executeEvents(rundata, context);
                        }
                      else
                        {
                          Log.debug("Action: calling doPerform");
                          doPerform(rundata, context);
                        }
                    }
                  else
                    {
                      executeEvents(rundata, context);
                    }
                }
              catch (NoSuchMethodException e)
                {
  
                  // no event selected, process normal context generation
                  Log.debug("Action: calling doPerform");
                  doPerform(rundata, context);
                }
            }
        }
  
      public void doPerform(RunData rundata, Context context)
                     throws Exception
        {
  
          GenericMVCPortlet portlet = null;
          JetspeedRunData jdata = (JetspeedRunData) rundata;
          Log.debug("GenericMVCAction: retrieved context: " + context);
  
          if (context != null)
            {
              portlet = (GenericMVCPortlet) context.get("portlet");
            }
  
          Log.debug("GenericMVCAction: retrieved portlet: " + portlet);
  
          if (portlet != null)
            {
  
              //System.out.println("class = " + this.getClass().getName());
              //rundata.getUser().setTemp(this.getClass().getName(), portlet.getID());
              // we're bein configured
              if ((jdata.getMode() == jdata.CUSTOMIZE) && 
(portlet.getName().equals(jdata.getCustomized().getName())))
                {
                  Log.debug("GenericMVCAction: building customize");
                  buildConfigureContext(portlet, context, rundata);
  
                  return;
                }
  
              // we're maximized
              if (jdata.getMode() == jdata.MAXIMIZE)
                {
                  Log.debug("GenericMVCAction: building maximize");
                  buildMaximizedContext(portlet, context, rundata);
  
                  return;
                }
  
              Log.debug("GenericMVCAction: building normal");
              buildNormalContext(portlet, context, rundata);
            }
        }
  
      /**
       * Subclasses should override this method if they wish to
       * build specific content when maximized. Default behavior is
       * to do the same as normal content.
       */
      protected void buildMaximizedContext(Portlet portlet, Context context, RunData 
rundata)
                                    throws Exception
        {
          buildNormalContext(portlet, context, rundata);
        }
  
      /**
       * Subclasses should override this method if they wish to
       * provide their own customization behavior.
       * Default is to use Portal base customizer action
       */
      protected void buildConfigureContext(Portlet portlet, Context context, RunData 
rundata)
                                    throws Exception
        {
  
          // code goes here. :)
        }
  
      /**
       * Subclasses must override this method to provide default behavior
       * for the portlet action
       */
      protected void buildNormalContext(Portlet portlet, Context context, RunData 
rundata)
                                 throws Exception
        {
        }
  
      /**
       * Convenience method for retreiving this action's Portlet
       * @param Context context Current context object.
       * @return Portlet the Portlet for this action
       * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
       */
      public Portlet getPortlet(Context context)
      {
          return (Portlet) context.get("portlet");
      }
      
      /**
       * Convenience method for retreiving this action's PortletInstance
       * @param Context context Current context object.
       * @return Portlet the Portlet for this action
       * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
       */
      public PortletInstance getPortletInstance(Context context)
      {
          return getPortlet(context).getInstance((RunData) context.get("data"));
      }
      
      /**
      * Convenience method for retreiving this action's PortletInstance
      * attribute.
      * @param String Attribute Name
      * @param Context context Current context object.
      * @return String portlet attribute
      * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
      */   
      public String getAttribute(String attrName, Context context)
      {
          return getPortletInstance(context).getAttribute(attrName);
      }
      
      /**
      * Convenience method for retreiving this action's PortletInstance
      * attribute.
      * @param String Attribute Name
      * @param String Default to return if no attribute is found
      * @param Context context Current context object.
      * @return String portlet attribute
      * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
      */
      public String getAttribute(String attrName, String defaultValue, Context context)
      {
          return getPortletInstance(context).getAttribute(attrName, defaultValue);
      }
      /**
      * Convenience method for setting this action's PortletInstance
      * attribute.
      * @param String Attribute Name
      * @param String Attribute Value
      * @param Context context Current context object.
      * @author <a href="mailto:[EMAIL PROTECTED]">Scott Weaver</a>
      */
      public void setAttribute(String attrName, String value, Context context)
          throws PortalPersistenceException
      {
          PortletInstance instance = getPortletInstance(context);
          instance.setAttribute(attrName, value);
          PersistenceManager.store(instance);
      }
    }
  
  
  
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/modules/actions/portlets/PortletAction.java
  
  Index: PortletAction.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  /*
   * PortletAction.java
   *
   *
   * $Id: PortletAction.java,v 1.8.2.1 2003/02/24 18:45:42 tkuebler Exp $
   *
   * Created on January 29, 2003, 2:52 PM
   */
  package org.apache.jetspeed.modules.actions.portlets;
  
  import org.apache.jetspeed.portal.Portlet;
  
  import org.apache.turbine.util.RunData;
  
  import org.apache.velocity.context.Context;
  
  
  /**
   *
   * Abstract holder for the portlet specific methods required above and
   * beyond the standard turbine action.
   * 
   * Extends the PortletActionEvent, which
   * encapsulates the event handling feature.
   * 
   * @author  tkuebler
   * @version $Id: PortletAction.java,v 1.8.2.1 2003/02/24 18:45:42 tkuebler Exp $
   * @stereotype moment-interval
   * 
   */
  
  
  /*
   * Note:
   * assumes a templated portlet, maybe should break this up into two classes
   * the portletaction would only have the build*Context methods
   * the templatedportletaction would have the rest
   * skipping this complexity for now since non-templated portlet actions can just
   * extend ActionEvent and forget about the context probably
   */
  public abstract class PortletAction
      extends PortletActionEvent
    {
  
      /** Creates a new instance of PortletAction */
      public PortletAction()
        {
        }
  
      public void doPerform(RunData data)
                     throws Exception
        {
  
          // assumes a context for the portlet...
          // should check for null and create one
          doPerform(data, getContext(data));
        }
  
      /**
       * You SHOULD override this method and implement it in your
       * action.
       *
       * @param data Turbine information.
       * @param context Context for web pages.
       * @exception Exception, a generic exception.
       */
      public abstract void doPerform(RunData data, Context context)
                              throws Exception;
  
      /**
       * Return the Context
       *
       * @param RunData data
       * @return Context, a context for web pages.
       */
      protected Context getContext(RunData data)
        {
  
          return (Context) 
data.getTemplateInfo().getTemplateContext("VelocityPortletContext");
        }
  
      /**
       * This method is used when you want to short circuit an Action
       * and change the template that will be executed next.
       *
       * @param data Turbine information.
       * @param template The template that will be executed next.
       */
      public void setTemplate(RunData data, String template)
        {
          getContext(data).put("template", template);
        }
  
      protected abstract void buildConfigureContext(Portlet portlet, Context context, 
RunData data)
                                             throws Exception;
  
      protected abstract void buildMaximizedContext(Portlet portlet, Context context, 
RunData data)
                                             throws Exception;
  
      protected abstract void buildNormalContext(Portlet portlet, Context context, 
RunData data)
                                          throws Exception;
    }
  
  
  
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/modules/actions/portlets/PortletActionEvent.java
  
  Index: PortletActionEvent.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  /*
   * PortletActionEvent.java
   *
   * Created on January 29, 2003, 4:20 PM
   */
  package org.apache.jetspeed.modules.actions.portlets;
  
  import java.lang.reflect.Method;
  
  import java.util.Enumeration;
  
  import org.apache.turbine.modules.ActionEvent;
  import org.apache.turbine.services.velocity.TurbineVelocity;
  import org.apache.turbine.util.ParameterParser;
  import org.apache.turbine.util.RunData;
  
  import org.apache.velocity.context.Context;
  
  
  /**
   * Provides form based action handling via the eventSubmit_do[action] pattern.
   * Works just like the mechanism described for the velocity portlet.  Extends
   * this convienent functionality to all GenericMVCPortlets
   * 
   * @author  tkuebler
   * @version $Id: PortletActionEvent.java,v 1.3.2.1 2003/02/24 18:45:42 tkuebler Exp $
   * @stereotype moment-interval
   */
  public abstract class PortletActionEvent
      extends ActionEvent
    {
  
      /**
       * You need to implement this in your classes that extend this
       * class.
       *
       * @param data A Turbine RunData object.
       * @exception Exception, a generic exception.
       */
      public abstract void doPerform(RunData data)
                              throws Exception;
  
      /**
       * This overrides the default Action.perform() to execute the
       * doEvent() method.  If that fails, then it will execute the
       * doPerform() method instead.
       *
       * @param data A Turbine RunData object.
       * @exception Exception, a generic exception.
       */
      protected void perform(RunData data)
                      throws Exception
        {
  
          try
            {
              executeEvents(data, TurbineVelocity.getContext(data));
            }
          catch (NoSuchMethodException e)
            {
              doPerform(data);
            }
        }
  
      /**
       * This method should be called to execute the event based system.
       *
       * @param data A Turbine RunData object.
       * @param context context information.
       * @exception Exception, a generic exception.
       */
      public void executeEvents(RunData data, Context context)
                         throws Exception
        {
  
          // Name of the button.
          String theButton = null;
  
          // ParameterParser.
          ParameterParser pp = data.getParameters();
          String button = pp.convert(BUTTON);
  
          // Loop through and find the button.
          for (Enumeration e = pp.keys(); e.hasMoreElements();)
            {
  
              String key = (String) e.nextElement();
  
              if (key.startsWith(button))
                {
                  theButton = formatString(key);
  
                  break;
                }
            }
  
          if (theButton == null)
            {
              throw new NoSuchMethodException("ActionEvent: The button was null");
            }
  
          try
            {
  
              // The arguments to the method to find.
              Class[] classes = new Class[2];
              classes[0] = RunData.class;
              classes[1] = Context.class;
  
              // The arguments to pass to the method to execute.
              Object[] args = new Object[2];
              Method method = getClass().getMethod(theButton, classes);
              args[0] = data;
              args[1] = context;
              method.invoke(this, args);
            }
          catch (NoSuchMethodException nsme)
            {
  
              // Attempt to execut things the old way..
              super.executeEvents(data);
            }
        }
    }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to