You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by ta...@apache.org on 2003/11/02 21:07:17 UTC

cvs commit: jakarta-jetspeed/webapp/WEB-INF/templates/jsp/controllers/html x-multicolumn-customize.jsp

taylor      2003/11/02 12:07:17

  Modified:    src/java/org/apache/jetspeed/portal/portlets
                        GenericMVCPortlet.java
               webapp/WEB-INF/conf JetspeedSecurity.properties
                        demo-portlets.xreg
  Added:       src/java/org/apache/jetspeed/modules/actions/controllers
                        XMultiColumnControllerAction.java
               src/java/org/apache/jetspeed/util/template JspTemplate.java
               webapp/WEB-INF/conf enhancedPortletControllers.xreg
               webapp/WEB-INF/templates/jsp/controllers/html
                        x-multicolumn-customize.jsp
  Log:
  drag and drop multicolumn controller contributed by Jun Yang
  delayed rendering feature contributed by Jun Yang
  
  Revision  Changes    Path
  1.1                  jakarta-jetspeed/src/java/org/apache/jetspeed/modules/actions/controllers/XMultiColumnControllerAction.java
  
  Index: XMultiColumnControllerAction.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2003 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 apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "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.modules.actions.controllers;
  
  import java.util.List;
  import java.util.Map;
  
  import javax.servlet.ServletRequest;
  
  import org.apache.jetspeed.om.profile.psml.PsmlEntry;
  import org.apache.jetspeed.portal.Portlet;
  import org.apache.jetspeed.portal.PortletController;
  import org.apache.jetspeed.services.rundata.JetspeedRunData;
  import org.apache.jetspeed.services.statemanager.SessionState;
  import org.apache.jetspeed.util.template.JetspeedTool;
  import org.apache.jetspeed.util.template.JspTemplate;
  import org.apache.jetspeed.util.StringUtils;
  import org.apache.turbine.util.RunData;
  import org.apache.velocity.context.Context;
  
  /**
   * XMultiColumnControllerAction
   *
   * @author <a href="mailto:junyang@cisco.com">Jun Yang</a>
   * @version $Id: XMultiColumnControllerAction.java,v 1.1 2003/11/02 20:07:16 taylor Exp $
   */
  public class XMultiColumnControllerAction extends MultiColumnControllerAction
  {
      protected void buildCustomizeContext(
          PortletController controller,
          Context context,
          RunData rundata
      )
      {
          super.buildCustomizeContext(controller, context, rundata);
          context.put("template", "x-multicolumn-customize.vm");
          context.put("action", "controllers.XMultiColumnControllerAction");
  
          context.put("includedContent", new JspTemplate(rundata, "/controllers/html/x-multicolumn-customize.jsp"));
          ServletRequest request = rundata.getRequest();
          request.setAttribute("jspContext", context);
  
          // debug
          Object[] columns = (Object[]) context.get("portlets");
          Map portletTitleMap = (Map) context.get("titles");
          for (int i = 0; i < columns.length; i++)
          {
              List portletList = (List) columns[i];
              for (int j = 0; j < portletList.size(); j++)
              {
                  PsmlEntry entry = (PsmlEntry) portletList.get(j);
                  String portletTitle = (String) portletTitleMap.get(entry.getId());
                  String portletSkinName = entry.getSkin() == null ? "-- Default --" : entry.getSkin().getName();
                  String portletSecurityId =
                      entry.getSecurityRef() == null ?
                      "-- Default --" :
                      entry.getSecurityRef().getParent();
                  String controlListBox =
                  (entry.getControl() != null && entry.getControl().getName() != null) ?
                      JetspeedTool.getPortletParameter(rundata, 
                                                       (Portlet) rundata.getUser().getTemp("customizer"),
                                                        "control", entry.getControl().getName()) :
                      JetspeedTool.getPortletParameter(rundata, (Portlet) rundata.getUser().getTemp("customizer"), "control");
                  controlListBox = controlListBox.substring(12);
                  controlListBox = controlListBox.replace('\n', ' ');
                  controlListBox = controlListBox.replace('\r', ' ');
                  int z = 0;
              }
          }
      }
      
      public void doSave(RunData data, Context context)
      {
          applyModelChanges(data, context);
          super.doSave(data, context);
      }
  
      public void doDelete(RunData data, Context context)
      {
          applyModelChanges(data, context);
          super.doDelete(data, context);
      }
  
      public void doControl(RunData data, Context context)
      {
          applyModelChanges(data, context);
          super.doControl(data, context);
      }
  
      protected void applyModelChanges(RunData data, Context context)
      {
          ServletRequest request = data.getRequest();
          String[] modelChangeList = request.getParameterValues("modelChangeList");
          if (modelChangeList != null)
          {
              String[] moves = StringUtils.stringToArray(modelChangeList[0], ";");
  
              SessionState customizationState = ((JetspeedRunData) data).getPageSessionState();
              List[] columns = (List[]) customizationState.getAttribute("customize-columns");
  
              for (int i = 0; i < moves.length; i++)
              {
                  String[] values = StringUtils.stringToArray(moves[i], ",");
                  int originCol = Integer.parseInt(values[0]);
                  int originRow = Integer.parseInt(values[1]);
                  int destCol = Integer.parseInt(values[2]);
                  int destRow = Integer.parseInt(values[3]);
  
                  Object portletEntry = columns[originCol].get(originRow);
                  columns[originCol].remove(originRow);
                  columns[destCol].add(destRow, portletEntry);
              }
          }
      }
  }    
  
  
  
  
  1.6       +448 -365  jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/GenericMVCPortlet.java
  
  Index: GenericMVCPortlet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/GenericMVCPortlet.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- GenericMVCPortlet.java	5 Aug 2003 19:07:00 -0000	1.5
  +++ GenericMVCPortlet.java	2 Nov 2003 20:07:16 -0000	1.6
  @@ -1,365 +1,448 @@
  -/* ====================================================================
  - * 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 apache@apache.org.
  - *
  - * 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.ViewProcessor;
  -import org.apache.jetspeed.portal.portlets.viewprocessor.ViewProcessorFactory;
  -//import org.apache.jetspeed.portal.portlets.viewprocessor.*;
  -// using the * form due to the puggable nature
  -//ie no recompile to support new view processors
  -// The above * form removed. No need, as imports are only used at compile time
  -// Pluggable will work fine anyway. (HO)
  -import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
  -import org.apache.jetspeed.services.logging.JetspeedLogger;
  -import org.apache.jetspeed.util.PortletSessionState;
  -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.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
  - * 
  - * @stereotype role
  - * @author tkuebler
  - * @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
  - * @version $Id$
  - */
  -public class GenericMVCPortlet extends AbstractInstancePortlet
  -{
  -    
  -    /**
  -     * Static initialization of the logger for this class
  -     */    
  -    private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(GenericMVCPortlet.class.getName());    
  -    
  -    // STW: Context keys
  -    public static final String PORTLET = "portlet";
  -    public static final String TEMPLATE = "template";
  -    public static final String RUNDATA = "data";
  -    public static final String PORTLET_CONFIG = "conf";
  -    public static final String SKIN = "skin";
  -    public static final String VIEW_TYPE = "viewType";	
  -    public static final String IS_CACHEABLE = "_IsCacheable";	
  -
  -    // 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: 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
  -        logger.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);
  -    }
  -
  -    /**
  -     * By default MVCPortlets are cacheable. This can be overriden by specifying
  -     * "_IsCacheable" parameter.
  -     * 
  -     * @return 
  -     */
  -    public boolean isCacheable()
  -    {
  -        return getPortletConfig().getInitParameter(IS_CACHEABLE, "true").equalsIgnoreCase("true");
  -    }
  -
  -/**
  - * 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(RUNDATA, rundata);
  -        context.put(PORTLET, this);
  -        context.put(PORTLET_CONFIG, this.getPortletConfig());
  -        context.put(SKIN, this.getPortletConfig().getPortletSkin());
  -        context.put(TEMPLATE, getCurrentTemplate(rundata));
  -        context.put(VIEW_TYPE, viewType);
  -        populateRequest(rundata);
  -
  -        // put references to the pull tools in the context
  -        TurbinePull.populateContext(context, rundata);
  -        // 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 (logger.isDebugEnabled())
  -                {
  -                    logger.debug(
  -                        "GenericMVCPortlet: Executing action ["
  -                            + actionName
  -                            + "] for portlet ["
  -                            + this.getName()
  -                            + "]");
  -                }
  -
  -                ActionLoader.getInstance().exec(rundata, actionName);
  -            }
  -            catch (Exception e)
  -            {
  -                logger.error("GenericMVCPortlet - error executing action",  e);
  -            }
  -        }
  -
  -        // Process View
  -        // call processView method
  -        logger.info("GenericMVCPortlet - calling processView on processor");
  -
  -        ConcreteElement result = (ConcreteElement) processor.processView(context);
  -        logger.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:sweaver@rippe.com">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", getCurrentTemplate(rundata));
  -        request.setAttribute("viewType", viewType);
  -    }
  -    
  -    /**
  -     * 
  -     */
  -    protected String getCurrentTemplate( RunData data)
  -    {
  -    	String useTemplate = (String) PortletSessionState.getAttribute(this, data, TEMPLATE);
  -    	if(useTemplate == null)
  -    	{
  -    		useTemplate = this.template;
  -    	}
  -    	
  -    	return useTemplate;
  -    }
  -}
  +/* ====================================================================
  + * The Apache Software License, Version 1.1
  + *
  + * Copyright (c) 2000-2003 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 apache@apache.org.
  + *
  + * 5. Products derived from this software may not be called "Apache",
  + *    "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;
  +
  +import java.io.IOException;
  +import java.io.PrintWriter;
  +import java.io.UnsupportedEncodingException;
  +import java.net.URLEncoder;
  +
  +import javax.servlet.http.HttpServletRequest;
  +
  +import org.apache.ecs.ConcreteElement;
  +import org.apache.jetspeed.om.profile.Profile;
  +import org.apache.jetspeed.portal.PortletException;
  +import org.apache.jetspeed.portal.portlets.viewprocessor.ViewProcessor;
  +import org.apache.jetspeed.portal.portlets.viewprocessor.ViewProcessorFactory;
  +import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
  +import org.apache.jetspeed.services.logging.JetspeedLogger;
  +import org.apache.jetspeed.services.rundata.JetspeedRunData;
  +import org.apache.jetspeed.util.PortletSessionState;
  +import org.apache.jetspeed.util.template.JetspeedLink;
  +import org.apache.jetspeed.util.template.JetspeedTemplateLink;
  +import org.apache.jetspeed.util.template.JspTemplate;
  +import org.apache.turbine.modules.ActionLoader;
  +import org.apache.turbine.services.pull.TurbinePull;
  +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
  + * 
  + * @stereotype role
  + * @author tkuebler
  + * @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
  + * @version $Id$
  + */
  +public class GenericMVCPortlet extends AbstractInstancePortlet
  +{
  +    
  +    /**
  +     * Static initialization of the logger for this class
  +     */    
  +    private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(GenericMVCPortlet.class.getName());    
  +    
  +    // STW: Context keys
  +    public static final String PORTLET = "portlet";
  +    public static final String TEMPLATE = "template";
  +    public static final String RUNDATA = "data";
  +    public static final String PORTLET_CONFIG = "conf";
  +    public static final String SKIN = "skin";
  +    public static final String VIEW_TYPE = "viewType";
  +    public static final String IS_CACHEABLE = "_IsCacheable";
  +
  +    // 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 static final String RENDERING_DELAYED = "renderingDelayed";
  +    public static final String SIMULATE_DELAY = "simulateDelay";
  +    public static final String PORTLET_ID = "__portletId";
  +    public static final String DOC_URL = "__docUrl";
  +  
  +    public void init() throws PortletException
  +    {
  +        
  +        //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
  +        logger.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);
  +    }
  +
  +    /**
  +     * By default MVCPortlets are cacheable. This can be overriden by specifying
  +     * "_IsCacheable" parameter.
  +     * 
  +     * @return 
  +     */
  +    public boolean isCacheable()
  +    {
  +        return getPortletConfig().getInitParameter(IS_CACHEABLE, "true").equalsIgnoreCase("true");
  +    }
  +
  +/**
  + * 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 (useDelayedRendering(rundata))
  +        {
  +            Profile profile = ((JetspeedRunData) rundata).getProfile();
  +            String path = profile.getPath();
  +            String portletId = getID();
  +            
  +            // FIXME: please use JetspeedLink to create Portal URLs           
  +            String docUrl = "portal/" + path + "/js_peid/" + portletId + "?action=controls.Print";
  +            try 
  +            {
  +                docUrl = URLEncoder.encode(docUrl, "UTF-8");
  +            } 
  +            catch (UnsupportedEncodingException e)   
  +            {
  +                e.printStackTrace();
  +            }
  +            // END FIXME:
  +            
  +            HttpServletRequest request = rundata.getRequest();
  +            request.setAttribute(PORTLET_ID, portletId);
  +            request.setAttribute(DOC_URL, docUrl);
  +
  +            // render content that pulls
  +            return renderJspTemplate(rundata, "delayedContent.jsp");          
  +        }
  +        
  +        simulateDelay();             
  +            
  +        //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(RUNDATA, rundata);
  +        context.put(PORTLET, this);
  +        context.put(PORTLET_CONFIG, this.getPortletConfig());
  +        context.put(SKIN, this.getPortletConfig().getPortletSkin());
  +        context.put(TEMPLATE, getCurrentTemplate(rundata));
  +        context.put(VIEW_TYPE, viewType);
  +        populateRequest(rundata);
  +
  +        // put references to the pull tools in the context
  +        TurbinePull.populateContext(context, rundata);
  +        // 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 (logger.isDebugEnabled())
  +                {
  +                    logger.debug(
  +                        "GenericMVCPortlet: Executing action ["
  +                            + actionName
  +                            + "] for portlet ["
  +                            + this.getName()
  +                            + "]");
  +                }
  +
  +                ActionLoader.getInstance().exec(rundata, actionName);
  +            }
  +            catch (Exception e)
  +            {
  +                logger.error("GenericMVCPortlet - error executing action",  e);
  +            }
  +        }
  +
  +        // Process View
  +        // call processView method
  +        logger.info("GenericMVCPortlet - calling processView on processor");
  +
  +        ConcreteElement result = (ConcreteElement) processor.processView(context);
  +        logger.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:sweaver@rippe.com">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", getCurrentTemplate(rundata));
  +        request.setAttribute("viewType", viewType);
  +    }
  +    
  +    /**
  +     * 
  +     */
  +    protected String getCurrentTemplate( RunData data)
  +    {
  +        String useTemplate = (String) PortletSessionState.getAttribute(this, data, TEMPLATE);
  +        if(useTemplate == null)
  +        {
  +            useTemplate = this.template;
  +        }
  +
  +        return useTemplate;
  +    }
  +    
  +    protected boolean useDelayedRendering(RunData rundata)
  +    {
  +        String renderingDelayedString = getPortletConfig().getInitParameter(RENDERING_DELAYED);
  +        boolean renderingDelayed = false;
  +        if (renderingDelayedString != null)
  +        {
  +            renderingDelayed = (Boolean.valueOf(renderingDelayedString) == Boolean.TRUE);
  +        }
  +
  +        HttpServletRequest request = rundata.getRequest();
  +        String action = rundata.getAction();
  +
  +        return renderingDelayed && (action == null || action.length() == 0 || "controls.Restore".equals(action));
  +    }
  +
  +    protected ConcreteElement renderJspTemplate(RunData rundata, String templateName)
  +    {
  +        JspTemplate t = new JspTemplate(rundata, "/portlets/html/" + templateName);
  +        PrintWriter out = null;
  +        try
  +        {
  +            out = rundata.getOut();
  +            out.println(t.getContent());
  +        }
  +        catch (IOException ioe)
  +        {
  +            logger.error(ioe);
  +        }
  +
  +        return null;
  +    }
  +    
  +    private void simulateDelay()
  +    {        
  +        String simulateDelayString = getPortletConfig().getInitParameter(SIMULATE_DELAY);
  +        int simulateDelay = 0;  // seconds
  +        if (simulateDelayString != null)
  +        {
  +            simulateDelay = Integer.parseInt(simulateDelayString);
  +        }
  +
  +        if (simulateDelay > 0)
  +        {
  +            long delayInMilliseconds = simulateDelay * 1000;
  +            try 
  +            { 
  +                Thread.sleep(delayInMilliseconds); 
  +            } 
  +            catch (InterruptedException e) 
  +            {
  +            }
  +        }
  +                
  +    }
  +}
  
  
  
  1.1                  jakarta-jetspeed/src/java/org/apache/jetspeed/util/template/JspTemplate.java
  
  Index: JspTemplate.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2003 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 apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "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.util.template;
  
  import org.apache.log4j.Logger;
  import org.apache.turbine.services.TurbineServices;
  import org.apache.turbine.services.jsp.JspService;
  import org.apache.turbine.util.RunData;
  import org.apache.turbine.util.TurbineException;
  
  /**
   * JspTemplate
   *
   * @author <a href="mailto:junyang@cisco.com">Jun Yang</a>
   * @version $Id: JspTemplate.java,v 1.1 2003/11/02 20:07:17 taylor Exp $
   */
  public class JspTemplate 
  {
      protected RunData runData;
      protected String templateName;
      private static Logger logger = Logger.getLogger(JspTemplate.class);    
      public JspTemplate(RunData runData, String templateName)
      {
          this.runData = runData;
          this.templateName = templateName;
      }
  
      public String getContent()
      {
          JspService jsp = (JspService) TurbineServices.getInstance().getService(JspService.SERVICE_NAME);
          try
          {
              jsp.handleRequest(this.runData, this.templateName);
          }
          catch (TurbineException te1)
          {
              if (!this.templateName.endsWith(".jsp"))
              {
                  try
                  {
                      jsp.handleRequest(this.runData, this.templateName + ".jsp");
                  }
                  catch (TurbineException te2)
                  {
                      logger.error("failed to invoke JSP Template '" + 
                                      this.templateName + "' and '" + this.templateName + ".jsp'", te2);
                  }
              }
              else
              {
                  logger.error("failed to invoke JSP Template '" + this.templateName + "'", te1);            
              }
          }
          
          return "";
      }
  }
  
  
  
  1.70      +0 -0      jakarta-jetspeed/webapp/WEB-INF/conf/JetspeedSecurity.properties
  
  Index: JetspeedSecurity.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-jetspeed/webapp/WEB-INF/conf/JetspeedSecurity.properties,v
  retrieving revision 1.69
  retrieving revision 1.70
  diff -u -r1.69 -r1.70
  
  
  
  1.44      +9 -0      jakarta-jetspeed/webapp/WEB-INF/conf/demo-portlets.xreg
  
  Index: demo-portlets.xreg
  ===================================================================
  RCS file: /home/cvs/jakarta-jetspeed/webapp/WEB-INF/conf/demo-portlets.xreg,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- demo-portlets.xreg	29 Sep 2003 18:07:52 -0000	1.43
  +++ demo-portlets.xreg	2 Nov 2003 20:07:17 -0000	1.44
  @@ -765,4 +765,13 @@
   		<url>/examples/organized.html</url>
   		<category>sites</category>
   	</portlet-entry>
  +    <portlet-entry name="DelayRenderedStockQuote" hidden="false" type="ref" parent="StockQuote" application="false">
  +        <meta-info>
  +            <title>Delay-rendered Stock Portfolio</title>
  +	    <description>Delay-rendered Stock Portfolio Portlet</description>
  +        </meta-info>
  +        <parameter name="renderingDelayed" value="true" hidden="false" cachedOnName="true" cachedOnValue="true"/>
  +        <parameter name="simulateDelay" value="2" hidden="false" cachedOnName="true" cachedOnValue="true"/>
  +        <category group="Jetspeed">finance.stocks</category>
  +    </portlet-entry>
   </registry>
  
  
  
  1.1                  jakarta-jetspeed/webapp/WEB-INF/conf/enhancedPortletControllers.xreg
  
  Index: enhancedPortletControllers.xreg
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <registry>
      <portlet-controller-entry name="XTwoColumns1" hidden="false">
          <meta-info>
              <title>Enhanced Two columns (50/50)</title>
          </meta-info>
          <classname>org.apache.jetspeed.portal.controllers.VelocityPortletController</classname>
          <parameter name="template" value="multicolumn.vm" hidden="false"/>
          <parameter name="action"
              value="controllers.XMultiColumnControllerAction" hidden="false"/>
          <parameter name="sizes" value="50%,50%" hidden="false"/>
          <parameter name="cols" value="2" hidden="false"/>
          <media-type ref="html"/>
      </portlet-controller-entry>
      <portlet-controller-entry name="XTwoColumns2" hidden="false">
          <meta-info>
              <title>Enhanced Two columns (25/75)</title>
          </meta-info>
          <classname>org.apache.jetspeed.portal.controllers.VelocityPortletController</classname>
          <parameter name="template" value="multicolumn.vm" hidden="false"/>
          <parameter name="action"
              value="controllers.XMultiColumnControllerAction" hidden="false"/>
          <parameter name="sizes" value="25%,75%" hidden="false"/>
          <parameter name="cols" value="2" hidden="false"/>
          <media-type ref="html"/>
      </portlet-controller-entry>
      <portlet-controller-entry name="XTwoColumns3" hidden="false">
          <meta-info>
              <title>Enhanced Two columns (75/25)</title>
          </meta-info>
          <classname>org.apache.jetspeed.portal.controllers.VelocityPortletController</classname>
          <parameter name="template" value="multicolumn.vm" hidden="false"/>
          <parameter name="action"
              value="controllers.XMultiColumnControllerAction" hidden="false"/>
          <parameter name="sizes" value="75%,25%" hidden="false"/>
          <parameter name="cols" value="2" hidden="false"/>
          <media-type ref="html"/>
      </portlet-controller-entry>
      <portlet-controller-entry name="XThreeColumns1" hidden="false">
          <meta-info>
              <title>Enhanced Three columns (33/34/33)</title>
          </meta-info>
          <classname>org.apache.jetspeed.portal.controllers.VelocityPortletController</classname>
          <parameter name="template" value="multicolumn.vm" hidden="false"/>
          <parameter name="action"
              value="controllers.XMultiColumnControllerAction" hidden="false"/>
          <parameter name="sizes" value="33%,34%,33%" hidden="false"/>
          <parameter name="cols" value="3" hidden="false"/>
          <media-type ref="html"/>
      </portlet-controller-entry>
      <portlet-controller-entry name="XThreeColumns2" hidden="false">
          <meta-info>
              <title>Enhanced Three columns (25/50/25)</title>
          </meta-info>
          <classname>org.apache.jetspeed.portal.controllers.VelocityPortletController</classname>
          <parameter name="template" value="multicolumn.vm" hidden="false"/>
          <parameter name="action"
              value="controllers.XMultiColumnControllerAction" hidden="false"/>
          <parameter name="sizes" value="25%,50%,25%" hidden="false"/>
          <parameter name="cols" value="3" hidden="false"/>
          <media-type ref="html"/>
      </portlet-controller-entry>
  </registry>
  
  
  
  1.1                  jakarta-jetspeed/webapp/WEB-INF/templates/jsp/controllers/html/x-multicolumn-customize.jsp
  
  Index: x-multicolumn-customize.jsp
  ===================================================================
  <%@ page import = "java.util.*" %>
  <%@ page import = "org.apache.turbine.util.*" %>
  <%@ page import = "org.apache.velocity.context.Context" %>
  <%@ page import = "org.apache.jetspeed.util.Config" %>
  <%@ page import = "org.apache.jetspeed.portal.*" %>
  <%@ page import = "org.apache.jetspeed.om.profile.psml.PsmlEntry" %>
  <%@ page import = "org.apache.jetspeed.om.SecurityReference" %>
  <%@ page import = "org.apache.jetspeed.util.template.*" %>
  <%@ page import = "org.apache.jetspeed.modules.actions.controllers.Util" %>
  <%@ page import = "org.apache.jetspeed.services.customlocalization.CustomLocalizationTool" %>
  
  <%
  Context context = (Context) request.getAttribute("jspContext");
  Object[] columns = (Object[]) context.get("portlets");
  PortletController controller = (PortletController) context.get("controller");
  Config myConfig = controller.getConfig();
  String[] sizes = Util.convertStringsToArray(myConfig.getInitParameter("sizes"), ",");
  JetspeedLink jslink = (JetspeedLink) context.get("jslink");
  String action = (String) context.get("action");
  CustomLocalizationTool l10n = (CustomLocalizationTool) context.get("l10n");
  Map portletTitleMap = (Map) context.get("titles");
  RunData runData = (RunData) context.get("data");
  JetspeedTool jetspeed = (JetspeedTool) context.get("jetspeed");
  %>
  
  <style>
  .drag-block {
  	position: relative;
  	border: solid gray;
  	cursor: pointer;
  	height: 120px;
  }
  .drag-sink {
  	position: relative;
  	border: solid #EEEEEE;
  }
  </style>
  
  <script type="text/javascript" src="js/util.js"></script>
  <script type="text/javascript">
  
  // global variables
  
  dragBlockTemplate = '<div class="drag-block" name="{col:${col},row:${row}}"><form name="decoration-${portletId}" action="${jslinkTemplate}" method="post" onSubmit="javascript:submitFormWithModelChanges(this)"><table border="0" width="100%"><tr><td align="center" colspan="2"><b>${portletTitle}</b></td><td align="right"><input type="image" src="${closeImageSrc}" border="0" name="eventSubmit_doDelete" title="remove"></td></tr><tr><td valign="top" width="45%">Skin : ${portletSkinName}</td><td valign="top">Security ID : ${portletSecurityId}</td><td></td></tr><tr><td colspan="2">Decoration : ${portletDecoration}</td><td></td></tr></table><input type="hidden" name="js_peid" value="${portletId}"><input type="hidden" name="col" value="${originalCol}"><input type="hidden" name="row" value="${originalRow}"><input type="hidden" name="eventSubmit_doControl" value="doControl"><input type="hidden" name="<%= jslink.getActionKey() %>" value="<%= action %>" ><input type="hidden" name="modelChangeList"></form></div>';
  
  dragSinkTemplate = '<div class="drag-sink" name="{col:${col},row:${row}}"></div>';
  
  layoutPlaygroundTableColumnTemplate = '<td valign="top" width="${width}">${columnContent}</td>';
  
  var modelRoot = [
  <%
  for (int i = 0; i < columns.length; i++)
  {
  %>
  	<%= i > 0 ? "," : "" %>[
  <%
  	List portletList = (List) columns[i];
  	for (int j = 0; j < portletList.size(); j++)
  	{
  %>
  		<%= j > 0 ? "," : "" %>
  <%
  		PsmlEntry entry = (PsmlEntry) portletList.get(j);
  		String portletId = entry.getId();
  		String portletTitle = (String) portletTitleMap.get(entry.getId());
  		String portletSkinName = entry.getSkin() == null ? "-- Default --" : entry.getSkin().getName();
  
  		// security reference
  		SecurityReference securityReference = jetspeed.getSecurityReference(entry);
  		String portletSecurityRef;
  		if (securityReference != null)
  		{
  			portletSecurityRef = securityReference.getParent();
  			if (jetspeed.getSecuritySource(entry) == 1)
  			{
  				portletSecurityRef = portletSecurityRef  + "<span style=\"color:red\"><br/>" + l10n.get("SECURITY_IS_REGISTRY_LEVEL") + ".</span>";
  			}
  			else if (jetspeed.getSecuritySource(entry) == 2)
  			{
  				portletSecurityRef = portletSecurityRef  + "<span style=\"color:red\"><br/>" + l10n.get("SECURITY_IS_SYSTEM_DEFAULT") + ".</span>";
  			}
  		}
  		else
  		{
  			portletSecurityRef = "-- Default --";
  		}
  
  		// decoration
  		String controlListBox =
  			(entry.getControl() != null && entry.getControl().getName() != null) ?
  			JetspeedTool.getPortletParameter(runData, (Portlet) runData.getUser().getTemp("customizer"), "control", entry.getControl().getName()) :
  			JetspeedTool.getPortletParameter(runData, (Portlet) runData.getUser().getTemp("customizer"), "control");
  		controlListBox = controlListBox.substring(12);
  		controlListBox = controlListBox.replace('\n', ' ');
  		controlListBox = controlListBox.replace('\r', ' ');
  %>
  		{id:'<%= portletId %>', parent:'<%= entry.getParent() %>',title:'<%= portletTitle %>',description:'<%= entry.getDescription() %>',skinName:'<%= portletSkinName %>',securityId:'<%= portletSecurityRef %>',controlListBox:'<%= controlListBox %>'}
  <%
  	}
  %>
  	]
  <%
  }
  %>
  ];
  var sizes = [
  <%
  for (int i = 0; i < sizes.length; i++)
  {
  %>
  	<%= i > 0 ? "," : "" %>'<%= sizes[i] %>'
  <%
  }
  %>
  ];
  
  var dragBlockList;
  var dragSinkList;
  
  function renderLayoutPlayground(columns)
  {
  	var content = '<table border="0" width="100%" id="layoutPlaygroundTable"><tr>';
  
  	for (var i = 0; i < columns.length; i++)
  	{
  		var columnContent = fillTemplate(
  			dragSinkTemplate,
  			'col', i,
  			'row', 0
  		);
  		var portletList = columns[i];
  		for (var j = 0; j < portletList.length; j++)
  		{
  			var psmlEntry = portletList[j];
  			var controlListBox = psmlEntry.controlListBox.replace(/this.form.submit\(\)/gi, 'submitFormWithModelChanges(this.form)');
  			columnContent += fillTemplate(
  				dragBlockTemplate,
  				'portletId', psmlEntry.id,
  				'portletTitle', psmlEntry.title,
  				'portletSkinName', psmlEntry.skinName,
  				'portletSecurityId', psmlEntry.securityId,
  				'portletDecoration', controlListBox,
  				'closeImageSrc', 'images/close.gif',
  				'jslinkTemplate', '<%= jslink.getTemplate() %>',
  				'col', i,
  				'row', j,
  				'originalCol', i,
  				'originalRow', j
  			);
  			columnContent += fillTemplate(
  				dragSinkTemplate,
  				'col', i,
  				'row', j + 1
  			);
  		}
  		content += fillTemplate(
  			layoutPlaygroundTableColumnTemplate,
  			'width', sizes[i],
  			'columnContent', columnContent
  		);
  	}
  
  	content += '</tr></table>';
  	var layoutPlaygroundDiv = document.getElementById('layoutPlayground');
  	layoutPlaygroundDiv.innerHTML = content;
  
  	buildDragBlockList();
  	buildDragSinkList();
  }
  
  var target = null;
  var highlightedDragSink = null;
  var previousX = 0;
  var previousY = 0;
  
  function elementGetTop(elem)
  {
  	var top = parseInt(elem.style.top);
  	if (isNaN(top))
  		return 0;
  	else
  		return top;
  }
  
  function elementGetLeft(elem)
  {
  	var left = parseInt(elem.style.left);
  	if (isNaN(left))
  		return 0;
  	else
  		return left;
  }
  
  function elementMoveBy(elem, point)
  {
  	var newTop = elementGetTop(elem) + point.y;
  	var newLeft = elementGetLeft(elem) + point.x;
  	elem.style.top = newTop + 'px';
  	elem.style.left = newLeft + 'px';
  }
  
  function elementMoveTo(elem, point)
  {
  	elem.style.top = point.x + 'px';
  	elem.style.left = point.y + 'px';
  }
  
  function getEventPositionX(e)
  {
  	if (!e)
  	{
  		// IE
  		e = window.event;
  		return e.clientX + document.body.scrollLeft;
  	}
  	else
  	{
  		// standard
  		return e.clientX + document.body.scrollLeft;
  	}
  }
  
  function getEventPositionY(e)
  {
  	if (!e)
  	{
  		// IE
  		e = window.event;
  		return e.clientY + document.body.scrollTop;
  	}
  	else
  	{
  		// standard
  		return e.clientY + document.body.scrollTop;
  	}
  }
  
  function findTargetDragBlock(e)
  {
  	var x = getEventPositionX(e);
  	var y = getEventPositionY(e);
  
  	for (var i = 0; i < dragBlockList.length; i++)
  	{
  		var dragBlock = dragBlockList[i];
  		if (elementContainsPoint(dragBlock, x, y))
  		{
  			return dragBlock;
  		}
  	}
  
  	return null;
  }
  
  function handleMouseDown(event)
  {
  	if (!event)	// IE
  	{
  		event = window.event;
  //		event.target = event.srcElement;
  	}
  
  	target = findTargetDragBlock(event);
  
  	if (target)
  	{
  		previousX = getEventPositionX(event);
  		previousY = getEventPositionY(event);
  		target.originalPosition = {x:elementGetLeft(target), y:elementGetTop(target)};
  		target.style.borderColor = 'black';
  		event.cancelBubble = true;
  		event.returnValue = false;
  		return false;
  	}
  	else
  	{
  		return true;
  	}
  }
  
  function handleMouseMove(event)
  {
  	if (!event)	// IE
  	{
  		event = window.event;
  //		event.target = event.srcElement;
  	}
  
  	if (target)
  	{
  		var currentX = getEventPositionX(event);
  		var currentY = getEventPositionY(event);
  		var dx = currentX - previousX;
  		var dy = currentY - previousY;
  		target.style.cursor = 'move';
  		elementMoveBy(target, {x:dx, y:dy});
  		highlightDragSink(currentX, currentY);
  		previousX = currentX;
  		previousY = currentY;
  		event.cancelBubble = true;
  		event.returnValue = false;
  		return false;
  	}
  	else
  	{
  		return true;
  	}
  }
  
  function handleMouseUp(event)
  {
  	if (!event)	// IE
  	{
  		event = window.event;
  //		event.target = event.srcElement;
  	}
  
  	if (target)
  	{
  		target.style.cursor = 'pointer';
  		target.style.borderColor = 'gray';
  		if (highlightedDragSink)
  		{
  			drop(target, highlightedDragSink);
  			unhighlight(highlightedDragSink);
  			highlightedDragSink = null;
  		}
  		else
  		{
  			elementMoveTo(target, target.originalPosition);
  		}
  		target.originalPosition = null;
  		target = null;
  		previousX = 0;
  		previousY = 0;
  		event.cancelBubble = true;
  		event.returnValue = false;
  		return false;
  	}
  	else
  	{
  		return true;
  	}
  }
  
  document.onmousedown = handleMouseDown;
  document.onmousemove = handleMouseMove;
  document.onmouseup = handleMouseUp;
  
  function highlightDragSink(x, y)
  {
  	for (var i = 0; i < dragSinkList.length; i++)
  	{
  		var dragSink = dragSinkList[i];
  		if (elementContainsPoint(dragSink, x, y))
  		{
  			if (highlightedDragSink)
  				unhighlight(highlightedDragSink);
  			highlight(dragSink);
  			highlightedDragSink = dragSink;
  			return;
  		}
  	}
  
  	if (highlightedDragSink)
  	{
  		unhighlight(highlightedDragSink);
  		highlightedDragSink = null;
  	}
  }
  
  function elementContainsPoint(elem, x, y)
  {
  	var top = elem.offsetTop;
  	var left = elem.offsetLeft;
  	var height = elem.offsetHeight;
  	var width = elem.offsetWidth;
  	return	(0 <= x - left && x - left <= width) &&
  		(0 <= y - top && y - top <= height);
  }
  
  function highlight(elem)
  {
  	elem.style.borderColor = '#FF0000';
  }
  
  function unhighlight(elem)
  {
  	elem.style.borderColor = '#EEEEEE';
  }
  
  function buildDragBlockList()
  {
  	var layoutPlaygroundTable = document.getElementById('layoutPlaygroundTable');
  	var dragBlockCandidateList = layoutPlaygroundTable.getElementsByTagName("div");
  	dragBlockList = new Array();
  	for (var i = 0; i < dragBlockCandidateList.length; i++)
  	{
  		var dragBlockCandidate = dragBlockCandidateList[i];
  		if (dragBlockCandidate.className == 'drag-block')
  			dragBlockList[dragBlockList.length] = dragBlockCandidate;
  	}
  }
  
  function buildDragSinkList()
  {
  	var layoutPlaygroundTable = document.getElementById('layoutPlaygroundTable');
  	var dragSinkCandidateList = layoutPlaygroundTable.getElementsByTagName("div");
  	dragSinkList = new Array();
  	for (var i = 0; i < dragSinkCandidateList.length; i++)
  	{
  		var dragSinkCandidate = dragSinkCandidateList[i];
  		if (dragSinkCandidate.className == 'drag-sink')
  			dragSinkList[dragSinkList.length] = dragSinkCandidate;
  	}
  }
  
  function drop(target, dragSink)
  {
  	var targetRowCol = eval('_rowcol=' + target.attributes['name'].value);
  	var dragSinkRowCol = eval('_rowcol=' + dragSink.attributes['name'].value);
  
  	if (destSameAsOrigin(targetRowCol, dragSinkRowCol))
  		return;
  
  	// get reference to portletEtnry
  	var portletEntry = modelRoot[targetRowCol.col][targetRowCol.row];
  
  	// remove from old position
  	modelRoot[targetRowCol.col].splice(targetRowCol.row, 1);
  
  	// insert into new position
  	modelRoot[dragSinkRowCol.col].splice(dragSinkRowCol.row, 0, portletEntry);
  
  	recordModelChange(targetRowCol, dragSinkRowCol);
  
  	renderLayoutPlayground(modelRoot);
  }
  
  function destSameAsOrigin(origin, dest)
  {
  	return
  		(origin.col == dest.col) &&
  		(origin.row == dest.row || origin.row + 1 == dest.row);
  }
  
  function recordModelChange(origin, dest)
  {
  	var change = origin.col + ',' + origin.row + ',' + dest.col + ',' + dest.row;	
  	var f = document.forms['xform'];
  	if (f.modelChangeList.value == '')
  		f.modelChangeList.value = change;
  	else
  		f.modelChangeList.value += ';' + change;
  }
  
  function submitFormWithModelChanges(form)
  {
  	var modelChangeList = document.forms.xform.modelChangeList.value;
  	form.modelChangeList.value = modelChangeList;
  	form.submit();
  }
  
  function getPrintString(o)
  {
  	var s = '{';
  	for (p in o)
  	{
  		s += p + ':' + o[p] + ', ';
  	}
  	s += '}';
  	return s;
  }
  </script>
  
  <!-- layout table -->
  <br>
  
  <div id='layoutPlayground'></div>
  <script type="text/javascript">
  renderLayoutPlayground(modelRoot);
  </script>
  
  <br>
  
  <!-- buttons -->
    <form name="xform" action="<%= jslink.getTemplate() %>" method="post">
    <input type="hidden" name="<%= jslink.getActionKey() %>" value="<%= action %>" >
    <input type="hidden" name="modelChangeList" value="">
    <center>
      <table cellspacing="2">
        <tr>
          <td>
            <input type="submit" name="eventSubmit_doSave" value="<%= l10n.get("CUSTOMIZER_SAVEAPPLY") %>">
          </td>
          <td>
            <input type="submit" name="eventSubmit_doCancel" value="<%= l10n.get("CUSTOMIZER_CANCEL") %>">
          </td>
        </tr>
      </table>
    </center>
  </form>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jetspeed-dev-help@jakarta.apache.org


RE: cvs commit: jakarta-jetspeed/webapp/WEB-INF/templates/jsp/controllers/html x-multicolumn-customize.jsp

Posted by Mark Orciuch <ma...@ngsltd.com>.
I recompile it with 1.3 and it worked fine. Thanks!

Best regards,

Mark Orciuch - morciuch@apache.org
Jakarta Jetspeed - Enterprise Portal in Java
http://jakarta.apache.org/jetspeed/

> -----Original Message-----
> From: David Sean Taylor [mailto:david@bluesunrise.com]
> Sent: Tuesday, November 04, 2003 4:39 AM
> To: Jetspeed Developers List
> Subject: Re: cvs commit: 
> jakarta-jetspeed/webapp/WEB-INF/templates/jsp/controllers/html 
> x-multicolumn-customize.jsp
> 
> 
> 
> On Monday, November 3, 2003, at 10:08  PM, Mark Orciuch wrote:
> 
> > Do we want to keep backward compatibility with JDK 1.3?
> >
> Yes.
> Its fixed, although I don't have 1.3 here to test with.
> Actually we should be using JetspeedLink here.
> I will leave it for Jun to change it, to introduce him to the interface
> 
> --
> David Sean Taylor
> Bluesunrise Software
> david@bluesunrise.com
> +01 707 773-4646
> +01 707 529 9194
> +44 (0)79 8538 6471
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jetspeed-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: jetspeed-dev-help@jakarta.apache.org
> 
> 
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jetspeed-dev-help@jakarta.apache.org


Re: cvs commit: jakarta-jetspeed/webapp/WEB-INF/templates/jsp/controllers/html x-multicolumn-customize.jsp

Posted by David Sean Taylor <da...@bluesunrise.com>.
On Monday, November 3, 2003, at 10:08  PM, Mark Orciuch wrote:

> Do we want to keep backward compatibility with JDK 1.3?
>
Yes.
Its fixed, although I don't have 1.3 here to test with.
Actually we should be using JetspeedLink here.
I will leave it for Jun to change it, to introduce him to the interface

--
David Sean Taylor
Bluesunrise Software
david@bluesunrise.com
+01 707 773-4646
+01 707 529 9194
+44 (0)79 8538 6471



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jetspeed-dev-help@jakarta.apache.org


RE: cvs commit: jakarta-jetspeed/webapp/WEB-INF/templates/jsp/controllers/html x-multicolumn-customize.jsp

Posted by Mark Orciuch <ma...@ngsltd.com>.
Do we want to keep backward compatibility with JDK 1.3?

....
     [echo] java.home = c:\jdk1.3.1_02\jre
....
compile:
    [javac] Compiling 5 source files to C:\jakarta-jetspeed\bin\classes
    [javac]
C:\jakarta-jetspeed\src\java\org\apache\jetspeed\portal\portlets\GenericMVCP
ortlet.java:461: encode(java.lang.String) in
 java.net.URLEncoder cannot be applied to
(java.lang.String,java.lang.String)
    [javac]                 docUrl = URLEncoder.encode(docUrl, "UTF-8");
    [javac]                                    ^
    [javac] Note: Some input files use or override a deprecated API.
    [javac] Note: Recompile with -deprecation for details.
    [javac] 1 error

BUILD FAILED
file:C:/jakarta-jetspeed/build/build.xml:363: Compile failed; see the
compiler error output for details.
....

Best regards,

Mark Orciuch - morciuch@apache.org
Jakarta Jetspeed - Enterprise Portal in Java
http://jakarta.apache.org/jetspeed/


> -----Original Message-----
> From: taylor@apache.org [mailto:taylor@apache.org]
> Sent: Sunday, November 02, 2003 2:07 PM
> To: jakarta-jetspeed-cvs@apache.org
> Subject: cvs commit:
> jakarta-jetspeed/webapp/WEB-INF/templates/jsp/controllers/html
> x-multicolumn-customize.jsp
>
>
> taylor      2003/11/02 12:07:17
>
>   Modified:    src/java/org/apache/jetspeed/portal/portlets
>                         GenericMVCPortlet.java
>                webapp/WEB-INF/conf JetspeedSecurity.properties
>                         demo-portlets.xreg
>   Added:       src/java/org/apache/jetspeed/modules/actions/controllers
>                         XMultiColumnControllerAction.java
>                src/java/org/apache/jetspeed/util/template JspTemplate.java
>                webapp/WEB-INF/conf enhancedPortletControllers.xreg
>                webapp/WEB-INF/templates/jsp/controllers/html
>                         x-multicolumn-customize.jsp
>   Log:
>   drag and drop multicolumn controller contributed by Jun Yang
>   delayed rendering feature contributed by Jun Yang
>
>   Revision  Changes    Path
>   1.1
> jakarta-jetspeed/src/java/org/apache/jetspeed/modules/actions/cont
> rollers/XMultiColumnControllerAction.java
>
>   Index: XMultiColumnControllerAction.java
>   ===================================================================
>   /* ====================================================================
>    * The Apache Software License, Version 1.1
>    *
>    * Copyright (c) 2000-2003 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 apache@apache.org.
>    *
>    * 5. Products derived from this software may not be called "Apache",
>    *    "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.modules.actions.controllers;
>
>   import java.util.List;
>   import java.util.Map;
>
>   import javax.servlet.ServletRequest;
>
>   import org.apache.jetspeed.om.profile.psml.PsmlEntry;
>   import org.apache.jetspeed.portal.Portlet;
>   import org.apache.jetspeed.portal.PortletController;
>   import org.apache.jetspeed.services.rundata.JetspeedRunData;
>   import org.apache.jetspeed.services.statemanager.SessionState;
>   import org.apache.jetspeed.util.template.JetspeedTool;
>   import org.apache.jetspeed.util.template.JspTemplate;
>   import org.apache.jetspeed.util.StringUtils;
>   import org.apache.turbine.util.RunData;
>   import org.apache.velocity.context.Context;
>
>   /**
>    * XMultiColumnControllerAction
>    *
>    * @author <a href="mailto:junyang@cisco.com">Jun Yang</a>
>    * @version $Id: XMultiColumnControllerAction.java,v 1.1
> 2003/11/02 20:07:16 taylor Exp $
>    */
>   public class XMultiColumnControllerAction extends
> MultiColumnControllerAction
>   {
>       protected void buildCustomizeContext(
>           PortletController controller,
>           Context context,
>           RunData rundata
>       )
>       {
>           super.buildCustomizeContext(controller, context, rundata);
>           context.put("template", "x-multicolumn-customize.vm");
>           context.put("action",
> "controllers.XMultiColumnControllerAction");
>
>           context.put("includedContent", new JspTemplate(rundata,
> "/controllers/html/x-multicolumn-customize.jsp"));
>           ServletRequest request = rundata.getRequest();
>           request.setAttribute("jspContext", context);
>
>           // debug
>           Object[] columns = (Object[]) context.get("portlets");
>           Map portletTitleMap = (Map) context.get("titles");
>           for (int i = 0; i < columns.length; i++)
>           {
>               List portletList = (List) columns[i];
>               for (int j = 0; j < portletList.size(); j++)
>               {
>                   PsmlEntry entry = (PsmlEntry) portletList.get(j);
>                   String portletTitle = (String)
> portletTitleMap.get(entry.getId());
>                   String portletSkinName = entry.getSkin() ==
> null ? "-- Default --" : entry.getSkin().getName();
>                   String portletSecurityId =
>                       entry.getSecurityRef() == null ?
>                       "-- Default --" :
>                       entry.getSecurityRef().getParent();
>                   String controlListBox =
>                   (entry.getControl() != null &&
> entry.getControl().getName() != null) ?
>                       JetspeedTool.getPortletParameter(rundata,
>                                                        (Portlet)
> rundata.getUser().getTemp("customizer"),
>
> "control", entry.getControl().getName()) :
>                       JetspeedTool.getPortletParameter(rundata,
> (Portlet) rundata.getUser().getTemp("customizer"), "control");
>                   controlListBox = controlListBox.substring(12);
>                   controlListBox = controlListBox.replace('\n', ' ');
>                   controlListBox = controlListBox.replace('\r', ' ');
>                   int z = 0;
>               }
>           }
>       }
>
>       public void doSave(RunData data, Context context)
>       {
>           applyModelChanges(data, context);
>           super.doSave(data, context);
>       }
>
>       public void doDelete(RunData data, Context context)
>       {
>           applyModelChanges(data, context);
>           super.doDelete(data, context);
>       }
>
>       public void doControl(RunData data, Context context)
>       {
>           applyModelChanges(data, context);
>           super.doControl(data, context);
>       }
>
>       protected void applyModelChanges(RunData data, Context context)
>       {
>           ServletRequest request = data.getRequest();
>           String[] modelChangeList =
> request.getParameterValues("modelChangeList");
>           if (modelChangeList != null)
>           {
>               String[] moves =
> StringUtils.stringToArray(modelChangeList[0], ";");
>
>               SessionState customizationState =
> ((JetspeedRunData) data).getPageSessionState();
>               List[] columns = (List[])
> customizationState.getAttribute("customize-columns");
>
>               for (int i = 0; i < moves.length; i++)
>               {
>                   String[] values =
> StringUtils.stringToArray(moves[i], ",");
>                   int originCol = Integer.parseInt(values[0]);
>                   int originRow = Integer.parseInt(values[1]);
>                   int destCol = Integer.parseInt(values[2]);
>                   int destRow = Integer.parseInt(values[3]);
>
>                   Object portletEntry = columns[originCol].get(originRow);
>                   columns[originCol].remove(originRow);
>                   columns[destCol].add(destRow, portletEntry);
>               }
>           }
>       }
>   }
>
>
>
>
>   1.6       +448 -365
> jakarta-jetspeed/src/java/org/apache/jetspeed/portal/portlets/Gene
> ricMVCPortlet.java
>
>   Index: GenericMVCPortlet.java
>   ===================================================================
>   RCS file:
> /home/cvs/jakarta-jetspeed/src/java/org/apache/jetspeed/portal/por
> tlets/GenericMVCPortlet.java,v
>   retrieving revision 1.5
>   retrieving revision 1.6
>   diff -u -r1.5 -r1.6
>   --- GenericMVCPortlet.java	5 Aug 2003 19:07:00 -0000	1.5
>   +++ GenericMVCPortlet.java	2 Nov 2003 20:07:16 -0000	1.6
>   @@ -1,365 +1,448 @@
>   -/* ====================================================================
>   - * 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 apache@apache.org.
>   - *
>   - * 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.ViewProcessor;
>   -import
> org.apache.jetspeed.portal.portlets.viewprocessor.ViewProcessorFactory;
>   -//import org.apache.jetspeed.portal.portlets.viewprocessor.*;
>   -// using the * form due to the puggable nature
>   -//ie no recompile to support new view processors
>   -// The above * form removed. No need, as imports are only used
> at compile time
>   -// Pluggable will work fine anyway. (HO)
>   -import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
>   -import org.apache.jetspeed.services.logging.JetspeedLogger;
>   -import org.apache.jetspeed.util.PortletSessionState;
>   -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.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
>   - *
>   - * @stereotype role
>   - * @author tkuebler
>   - * @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
>   - * @version $Id$
>   - */
>   -public class GenericMVCPortlet extends AbstractInstancePortlet
>   -{
>   -
>   -    /**
>   -     * Static initialization of the logger for this class
>   -     */
>   -    private static final JetspeedLogger logger =
> JetspeedLogFactoryService.getLogger(GenericMVCPortlet.class.getNam
> e());
>   -
>   -    // STW: Context keys
>   -    public static final String PORTLET = "portlet";
>   -    public static final String TEMPLATE = "template";
>   -    public static final String RUNDATA = "data";
>   -    public static final String PORTLET_CONFIG = "conf";
>   -    public static final String SKIN = "skin";
>   -    public static final String VIEW_TYPE = "viewType";
>   -    public static final String IS_CACHEABLE = "_IsCacheable";
>   -
>   -    // 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: 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
>   -        logger.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);
>   -    }
>   -
>   -    /**
>   -     * By default MVCPortlets are cacheable. This can be
> overriden by specifying
>   -     * "_IsCacheable" parameter.
>   -     *
>   -     * @return
>   -     */
>   -    public boolean isCacheable()
>   -    {
>   -        return
> getPortletConfig().getInitParameter(IS_CACHEABLE,
> "true").equalsIgnoreCase("true");
>   -    }
>   -
>   -/**
>   - * 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(RUNDATA, rundata);
>   -        context.put(PORTLET, this);
>   -        context.put(PORTLET_CONFIG, this.getPortletConfig());
>   -        context.put(SKIN, this.getPortletConfig().getPortletSkin());
>   -        context.put(TEMPLATE, getCurrentTemplate(rundata));
>   -        context.put(VIEW_TYPE, viewType);
>   -        populateRequest(rundata);
>   -
>   -        // put references to the pull tools in the context
>   -        TurbinePull.populateContext(context, rundata);
>   -        // 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("VelocityPortletConte
> xt", context);
>   -
>   -                if (logger.isDebugEnabled())
>   -                {
>   -                    logger.debug(
>   -                        "GenericMVCPortlet: Executing action ["
>   -                            + actionName
>   -                            + "] for portlet ["
>   -                            + this.getName()
>   -                            + "]");
>   -                }
>   -
>   -                ActionLoader.getInstance().exec(rundata, actionName);
>   -            }
>   -            catch (Exception e)
>   -            {
>   -                logger.error("GenericMVCPortlet - error
> executing action",  e);
>   -            }
>   -        }
>   -
>   -        // Process View
>   -        // call processView method
>   -        logger.info("GenericMVCPortlet - calling processView
> on processor");
>   -
>   -        ConcreteElement result = (ConcreteElement)
> processor.processView(context);
>   -        logger.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:sweaver@rippe.com">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", getCurrentTemplate(rundata));
>   -        request.setAttribute("viewType", viewType);
>   -    }
>   -
>   -    /**
>   -     *
>   -     */
>   -    protected String getCurrentTemplate( RunData data)
>   -    {
>   -    	String useTemplate = (String)
> PortletSessionState.getAttribute(this, data, TEMPLATE);
>   -    	if(useTemplate == null)
>   -    	{
>   -    		useTemplate = this.template;
>   -    	}
>   -
>   -    	return useTemplate;
>   -    }
>   -}
>   +/* ====================================================================
>
>   + * The Apache Software License, Version 1.1
>
>   + *
>
>   + * Copyright (c) 2000-2003 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 apache@apache.org.
>
>   + *
>
>   + * 5. Products derived from this software may not be called "Apache",
>
>   + *    "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;
>
>   +
>
>   +import java.io.IOException;
>
>   +import java.io.PrintWriter;
>
>   +import java.io.UnsupportedEncodingException;
>
>   +import java.net.URLEncoder;
>
>   +
>
>   +import javax.servlet.http.HttpServletRequest;
>
>   +
>
>   +import org.apache.ecs.ConcreteElement;
>
>   +import org.apache.jetspeed.om.profile.Profile;
>
>   +import org.apache.jetspeed.portal.PortletException;
>
>   +import org.apache.jetspeed.portal.portlets.viewprocessor.ViewProcessor;
>
>   +import
> org.apache.jetspeed.portal.portlets.viewprocessor.ViewProcessorFactory;
>
>   +import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
>
>   +import org.apache.jetspeed.services.logging.JetspeedLogger;
>
>   +import org.apache.jetspeed.services.rundata.JetspeedRunData;
>
>   +import org.apache.jetspeed.util.PortletSessionState;
>
>   +import org.apache.jetspeed.util.template.JetspeedLink;
>
>   +import org.apache.jetspeed.util.template.JetspeedTemplateLink;
>
>   +import org.apache.jetspeed.util.template.JspTemplate;
>
>   +import org.apache.turbine.modules.ActionLoader;
>
>   +import org.apache.turbine.services.pull.TurbinePull;
>
>   +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
>
>   + *
>
>   + * @stereotype role
>
>   + * @author tkuebler
>
>   + * @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
>
>   + * @version $Id$
>
>   + */
>
>   +public class GenericMVCPortlet extends AbstractInstancePortlet
>
>   +{
>
>   +
>
>   +    /**
>
>   +     * Static initialization of the logger for this class
>
>   +     */
>
>   +    private static final JetspeedLogger logger =
> JetspeedLogFactoryService.getLogger(GenericMVCPortlet.class.getNam
> e());
>
>   +
>
>   +    // STW: Context keys
>
>   +    public static final String PORTLET = "portlet";
>
>   +    public static final String TEMPLATE = "template";
>
>   +    public static final String RUNDATA = "data";
>
>   +    public static final String PORTLET_CONFIG = "conf";
>
>   +    public static final String SKIN = "skin";
>
>   +    public static final String VIEW_TYPE = "viewType";
>
>   +    public static final String IS_CACHEABLE = "_IsCacheable";
>
>   +
>
>   +    // 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 static final String RENDERING_DELAYED = "renderingDelayed";
>
>   +    public static final String SIMULATE_DELAY = "simulateDelay";
>
>   +    public static final String PORTLET_ID = "__portletId";
>
>   +    public static final String DOC_URL = "__docUrl";
>
>   +
>
>   +    public void init() throws PortletException
>
>   +    {
>
>   +
>
>   +        //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
>
>   +        logger.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);
>
>   +    }
>
>   +
>
>   +    /**
>
>   +     * By default MVCPortlets are cacheable. This can be
> overriden by specifying
>
>   +     * "_IsCacheable" parameter.
>
>   +     *
>
>   +     * @return
>
>   +     */
>
>   +    public boolean isCacheable()
>
>   +    {
>
>   +        return
> getPortletConfig().getInitParameter(IS_CACHEABLE,
> "true").equalsIgnoreCase("true");
>
>   +    }
>
>   +
>
>   +/**
>
>   + * 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 (useDelayedRendering(rundata))
>
>   +        {
>
>   +            Profile profile = ((JetspeedRunData) rundata).getProfile();
>
>   +            String path = profile.getPath();
>
>   +            String portletId = getID();
>
>   +
>
>   +            // FIXME: please use JetspeedLink to create Portal
> URLs
>
>   +            String docUrl = "portal/" + path + "/js_peid/" +
> portletId + "?action=controls.Print";
>
>   +            try
>
>   +            {
>
>   +                docUrl = URLEncoder.encode(docUrl, "UTF-8");
>
>   +            }
>
>   +            catch (UnsupportedEncodingException e)
>
>   +            {
>
>   +                e.printStackTrace();
>
>   +            }
>
>   +            // END FIXME:
>
>   +
>
>   +            HttpServletRequest request = rundata.getRequest();
>
>   +            request.setAttribute(PORTLET_ID, portletId);
>
>   +            request.setAttribute(DOC_URL, docUrl);
>
>   +
>
>   +            // render content that pulls
>
>   +            return renderJspTemplate(rundata,
> "delayedContent.jsp");
>
>   +        }
>
>   +
>
>   +        simulateDelay();
>
>   +
>
>   +        //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(RUNDATA, rundata);
>
>   +        context.put(PORTLET, this);
>
>   +        context.put(PORTLET_CONFIG, this.getPortletConfig());
>
>   +        context.put(SKIN, this.getPortletConfig().getPortletSkin());
>
>   +        context.put(TEMPLATE, getCurrentTemplate(rundata));
>
>   +        context.put(VIEW_TYPE, viewType);
>
>   +        populateRequest(rundata);
>
>   +
>
>   +        // put references to the pull tools in the context
>
>   +        TurbinePull.populateContext(context, rundata);
>
>   +        // 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("VelocityPortletConte
> xt", context);
>
>   +
>
>   +                if (logger.isDebugEnabled())
>
>   +                {
>
>   +                    logger.debug(
>
>   +                        "GenericMVCPortlet: Executing action ["
>
>   +                            + actionName
>
>   +                            + "] for portlet ["
>
>   +                            + this.getName()
>
>   +                            + "]");
>
>   +                }
>
>   +
>
>   +                ActionLoader.getInstance().exec(rundata, actionName);
>
>   +            }
>
>   +            catch (Exception e)
>
>   +            {
>
>   +                logger.error("GenericMVCPortlet - error
> executing action",  e);
>
>   +            }
>
>   +        }
>
>   +
>
>   +        // Process View
>
>   +        // call processView method
>
>   +        logger.info("GenericMVCPortlet - calling processView
> on processor");
>
>   +
>
>   +        ConcreteElement result = (ConcreteElement)
> processor.processView(context);
>
>   +        logger.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:sweaver@rippe.com">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", getCurrentTemplate(rundata));
>
>   +        request.setAttribute("viewType", viewType);
>
>   +    }
>
>   +
>
>   +    /**
>
>   +     *
>
>   +     */
>
>   +    protected String getCurrentTemplate( RunData data)
>
>   +    {
>
>   +        String useTemplate = (String)
> PortletSessionState.getAttribute(this, data, TEMPLATE);
>
>   +        if(useTemplate == null)
>
>   +        {
>
>   +            useTemplate = this.template;
>
>   +        }
>
>   +
>
>   +        return useTemplate;
>
>   +    }
>
>   +
>
>   +    protected boolean useDelayedRendering(RunData rundata)
>
>   +    {
>
>   +        String renderingDelayedString =
> getPortletConfig().getInitParameter(RENDERING_DELAYED);
>
>   +        boolean renderingDelayed = false;
>
>   +        if (renderingDelayedString != null)
>
>   +        {
>
>   +            renderingDelayed =
> (Boolean.valueOf(renderingDelayedString) == Boolean.TRUE);
>
>   +        }
>
>   +
>
>   +        HttpServletRequest request = rundata.getRequest();
>
>   +        String action = rundata.getAction();
>
>   +
>
>   +        return renderingDelayed && (action == null ||
> action.length() == 0 || "controls.Restore".equals(action));
>
>   +    }
>
>   +
>
>   +    protected ConcreteElement renderJspTemplate(RunData
> rundata, String templateName)
>
>   +    {
>
>   +        JspTemplate t = new JspTemplate(rundata,
> "/portlets/html/" + templateName);
>
>   +        PrintWriter out = null;
>
>   +        try
>
>   +        {
>
>   +            out = rundata.getOut();
>
>   +            out.println(t.getContent());
>
>   +        }
>
>   +        catch (IOException ioe)
>
>   +        {
>
>   +            logger.error(ioe);
>
>   +        }
>
>   +
>
>   +        return null;
>
>   +    }
>
>   +
>
>   +    private void simulateDelay()
>
>   +    {
>
>   +        String simulateDelayString =
> getPortletConfig().getInitParameter(SIMULATE_DELAY);
>
>   +        int simulateDelay = 0;  // seconds
>
>   +        if (simulateDelayString != null)
>
>   +        {
>
>   +            simulateDelay = Integer.parseInt(simulateDelayString);
>
>   +        }
>
>   +
>
>   +        if (simulateDelay > 0)
>
>   +        {
>
>   +            long delayInMilliseconds = simulateDelay * 1000;
>
>   +            try
>
>   +            {
>
>   +                Thread.sleep(delayInMilliseconds);
>
>   +            }
>
>   +            catch (InterruptedException e)
>
>   +            {
>
>   +            }
>
>   +        }
>
>   +
>
>   +    }
>
>   +}
>
>
>
>
>   1.1
> jakarta-jetspeed/src/java/org/apache/jetspeed/util/template/JspTem
> plate.java
>
>   Index: JspTemplate.java
>   ===================================================================
>   /* ====================================================================
>    * The Apache Software License, Version 1.1
>    *
>    * Copyright (c) 2000-2003 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 apache@apache.org.
>    *
>    * 5. Products derived from this software may not be called "Apache",
>    *    "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.util.template;
>
>   import org.apache.log4j.Logger;
>   import org.apache.turbine.services.TurbineServices;
>   import org.apache.turbine.services.jsp.JspService;
>   import org.apache.turbine.util.RunData;
>   import org.apache.turbine.util.TurbineException;
>
>   /**
>    * JspTemplate
>    *
>    * @author <a href="mailto:junyang@cisco.com">Jun Yang</a>
>    * @version $Id: JspTemplate.java,v 1.1 2003/11/02 20:07:17 taylor Exp $
>    */
>   public class JspTemplate
>   {
>       protected RunData runData;
>       protected String templateName;
>       private static Logger logger =
> Logger.getLogger(JspTemplate.class);
>       public JspTemplate(RunData runData, String templateName)
>       {
>           this.runData = runData;
>           this.templateName = templateName;
>       }
>
>       public String getContent()
>       {
>           JspService jsp = (JspService)
> TurbineServices.getInstance().getService(JspService.SERVICE_NAME);
>           try
>           {
>               jsp.handleRequest(this.runData, this.templateName);
>           }
>           catch (TurbineException te1)
>           {
>               if (!this.templateName.endsWith(".jsp"))
>               {
>                   try
>                   {
>                       jsp.handleRequest(this.runData,
> this.templateName + ".jsp");
>                   }
>                   catch (TurbineException te2)
>                   {
>                       logger.error("failed to invoke JSP Template '" +
>                                       this.templateName + "' and
> '" + this.templateName + ".jsp'", te2);
>                   }
>               }
>               else
>               {
>                   logger.error("failed to invoke JSP Template '"
> + this.templateName + "'", te1);
>               }
>           }
>
>           return "";
>       }
>   }
>
>
>
>   1.70      +0 -0
> jakarta-jetspeed/webapp/WEB-INF/conf/JetspeedSecurity.properties
>
>   Index: JetspeedSecurity.properties
>   ===================================================================
>   RCS file:
> /home/cvs/jakarta-jetspeed/webapp/WEB-INF/conf/JetspeedSecurity.pr
> operties,v
>   retrieving revision 1.69
>   retrieving revision 1.70
>   diff -u -r1.69 -r1.70
>
>
>
>   1.44      +9 -0
> jakarta-jetspeed/webapp/WEB-INF/conf/demo-portlets.xreg
>
>   Index: demo-portlets.xreg
>   ===================================================================
>   RCS file:
> /home/cvs/jakarta-jetspeed/webapp/WEB-INF/conf/demo-portlets.xreg,v
>   retrieving revision 1.43
>   retrieving revision 1.44
>   diff -u -r1.43 -r1.44
>   --- demo-portlets.xreg	29 Sep 2003 18:07:52 -0000	1.43
>   +++ demo-portlets.xreg	2 Nov 2003 20:07:17 -0000	1.44
>   @@ -765,4 +765,13 @@
>    		<url>/examples/organized.html</url>
>    		<category>sites</category>
>    	</portlet-entry>
>   +    <portlet-entry name="DelayRenderedStockQuote"
> hidden="false" type="ref" parent="StockQuote" application="false">
>   +        <meta-info>
>   +            <title>Delay-rendered Stock Portfolio</title>
>   +	    <description>Delay-rendered Stock Portfolio
> Portlet</description>
>   +        </meta-info>
>   +        <parameter name="renderingDelayed" value="true"
> hidden="false" cachedOnName="true" cachedOnValue="true"/>
>   +        <parameter name="simulateDelay" value="2"
> hidden="false" cachedOnName="true" cachedOnValue="true"/>
>   +        <category group="Jetspeed">finance.stocks</category>
>   +    </portlet-entry>
>    </registry>
>
>
>
>   1.1
> jakarta-jetspeed/webapp/WEB-INF/conf/enhancedPortletControllers.xreg
>
>   Index: enhancedPortletControllers.xreg
>   ===================================================================
>   <?xml version="1.0" encoding="UTF-8"?>
>   <registry>
>       <portlet-controller-entry name="XTwoColumns1" hidden="false">
>           <meta-info>
>               <title>Enhanced Two columns (50/50)</title>
>           </meta-info>
>
> <classname>org.apache.jetspeed.portal.controllers.VelocityPortletC
> ontroller</classname>
>           <parameter name="template" value="multicolumn.vm"
> hidden="false"/>
>           <parameter name="action"
>               value="controllers.XMultiColumnControllerAction"
> hidden="false"/>
>           <parameter name="sizes" value="50%,50%" hidden="false"/>
>           <parameter name="cols" value="2" hidden="false"/>
>           <media-type ref="html"/>
>       </portlet-controller-entry>
>       <portlet-controller-entry name="XTwoColumns2" hidden="false">
>           <meta-info>
>               <title>Enhanced Two columns (25/75)</title>
>           </meta-info>
>
> <classname>org.apache.jetspeed.portal.controllers.VelocityPortletC
> ontroller</classname>
>           <parameter name="template" value="multicolumn.vm"
> hidden="false"/>
>           <parameter name="action"
>               value="controllers.XMultiColumnControllerAction"
> hidden="false"/>
>           <parameter name="sizes" value="25%,75%" hidden="false"/>
>           <parameter name="cols" value="2" hidden="false"/>
>           <media-type ref="html"/>
>       </portlet-controller-entry>
>       <portlet-controller-entry name="XTwoColumns3" hidden="false">
>           <meta-info>
>               <title>Enhanced Two columns (75/25)</title>
>           </meta-info>
>
> <classname>org.apache.jetspeed.portal.controllers.VelocityPortletC
> ontroller</classname>
>           <parameter name="template" value="multicolumn.vm"
> hidden="false"/>
>           <parameter name="action"
>               value="controllers.XMultiColumnControllerAction"
> hidden="false"/>
>           <parameter name="sizes" value="75%,25%" hidden="false"/>
>           <parameter name="cols" value="2" hidden="false"/>
>           <media-type ref="html"/>
>       </portlet-controller-entry>
>       <portlet-controller-entry name="XThreeColumns1" hidden="false">
>           <meta-info>
>               <title>Enhanced Three columns (33/34/33)</title>
>           </meta-info>
>
> <classname>org.apache.jetspeed.portal.controllers.VelocityPortletC
> ontroller</classname>
>           <parameter name="template" value="multicolumn.vm"
> hidden="false"/>
>           <parameter name="action"
>               value="controllers.XMultiColumnControllerAction"
> hidden="false"/>
>           <parameter name="sizes" value="33%,34%,33%" hidden="false"/>
>           <parameter name="cols" value="3" hidden="false"/>
>           <media-type ref="html"/>
>       </portlet-controller-entry>
>       <portlet-controller-entry name="XThreeColumns2" hidden="false">
>           <meta-info>
>               <title>Enhanced Three columns (25/50/25)</title>
>           </meta-info>
>
> <classname>org.apache.jetspeed.portal.controllers.VelocityPortletC
> ontroller</classname>
>           <parameter name="template" value="multicolumn.vm"
> hidden="false"/>
>           <parameter name="action"
>               value="controllers.XMultiColumnControllerAction"
> hidden="false"/>
>           <parameter name="sizes" value="25%,50%,25%" hidden="false"/>
>           <parameter name="cols" value="3" hidden="false"/>
>           <media-type ref="html"/>
>       </portlet-controller-entry>
>   </registry>
>
>
>
>   1.1
> jakarta-jetspeed/webapp/WEB-INF/templates/jsp/controllers/html/x-m
> ulticolumn-customize.jsp
>
>   Index: x-multicolumn-customize.jsp
>   ===================================================================
>   <%@ page import = "java.util.*" %>
>
>   <%@ page import = "org.apache.turbine.util.*" %>
>
>   <%@ page import = "org.apache.velocity.context.Context" %>
>
>   <%@ page import = "org.apache.jetspeed.util.Config" %>
>
>   <%@ page import = "org.apache.jetspeed.portal.*" %>
>
>   <%@ page import = "org.apache.jetspeed.om.profile.psml.PsmlEntry" %>
>
>   <%@ page import = "org.apache.jetspeed.om.SecurityReference" %>
>
>   <%@ page import = "org.apache.jetspeed.util.template.*" %>
>
>   <%@ page import =
> "org.apache.jetspeed.modules.actions.controllers.Util" %>
>
>   <%@ page import =
> "org.apache.jetspeed.services.customlocalization.CustomLocalizatio
> nTool" %>
>
>
>
>   <%
>
>   Context context = (Context) request.getAttribute("jspContext");
>
>   Object[] columns = (Object[]) context.get("portlets");
>
>   PortletController controller = (PortletController)
> context.get("controller");
>
>   Config myConfig = controller.getConfig();
>
>   String[] sizes =
> Util.convertStringsToArray(myConfig.getInitParameter("sizes"), ",");
>
>   JetspeedLink jslink = (JetspeedLink) context.get("jslink");
>
>   String action = (String) context.get("action");
>
>   CustomLocalizationTool l10n = (CustomLocalizationTool)
> context.get("l10n");
>
>   Map portletTitleMap = (Map) context.get("titles");
>
>   RunData runData = (RunData) context.get("data");
>
>   JetspeedTool jetspeed = (JetspeedTool) context.get("jetspeed");
>
>   %>
>
>
>
>   <style>
>
>   .drag-block {
>
>   	position: relative;
>
>   	border: solid gray;
>
>   	cursor: pointer;
>
>   	height: 120px;
>
>   }
>
>   .drag-sink {
>
>   	position: relative;
>
>   	border: solid #EEEEEE;
>
>   }
>
>   </style>
>
>
>
>   <script type="text/javascript" src="js/util.js"></script>
>
>   <script type="text/javascript">
>
>
>
>   // global variables
>
>
>
>   dragBlockTemplate = '<div class="drag-block"
> name="{col:${col},row:${row}}"><form
> name="decoration-${portletId}" action="${jslinkTemplate}"
> method="post"
> onSubmit="javascript:submitFormWithModelChanges(this)"><table
> border="0" width="100%"><tr><td align="center"
> colspan="2"><b>${portletTitle}</b></td><td align="right"><input
> type="image" src="${closeImageSrc}" border="0"
> name="eventSubmit_doDelete" title="remove"></td></tr><tr><td
> valign="top" width="45%">Skin : ${portletSkinName}</td><td
> valign="top">Security ID :
> ${portletSecurityId}</td><td></td></tr><tr><td
> colspan="2">Decoration :
> ${portletDecoration}</td><td></td></tr></table><input
> type="hidden" name="js_peid" value="${portletId}"><input
> type="hidden" name="col" value="${originalCol}"><input
> type="hidden" name="row" value="${originalRow}"><input
> type="hidden" name="eventSubmit_doControl"
> value="doControl"><input type="hidden" name="<%=
> jslink.getActionKey() %>" value="<%= action %>" ><input
> type="hidden" name="modelChangeList"></form></div>';
>
>
>
>   dragSinkTemplate = '<div class="drag-sink"
> name="{col:${col},row:${row}}"></div>';
>
>
>
>   layoutPlaygroundTableColumnTemplate = '<td valign="top"
> width="${width}">${columnContent}</td>';
>
>
>
>   var modelRoot = [
>
>   <%
>
>   for (int i = 0; i < columns.length; i++)
>
>   {
>
>   %>
>
>   	<%= i > 0 ? "," : "" %>[
>
>   <%
>
>   	List portletList = (List) columns[i];
>
>   	for (int j = 0; j < portletList.size(); j++)
>
>   	{
>
>   %>
>
>   		<%= j > 0 ? "," : "" %>
>
>   <%
>
>   		PsmlEntry entry = (PsmlEntry) portletList.get(j);
>
>   		String portletId = entry.getId();
>
>   		String portletTitle = (String)
> portletTitleMap.get(entry.getId());
>
>   		String portletSkinName = entry.getSkin() == null ?
> "-- Default --" : entry.getSkin().getName();
>
>
>
>   		// security reference
>
>   		SecurityReference securityReference =
> jetspeed.getSecurityReference(entry);
>
>   		String portletSecurityRef;
>
>   		if (securityReference != null)
>
>   		{
>
>   			portletSecurityRef = securityReference.getParent();
>
>   			if (jetspeed.getSecuritySource(entry) == 1)
>
>   			{
>
>   				portletSecurityRef =
> portletSecurityRef  + "<span style=\"color:red\"><br/>" +
> l10n.get("SECURITY_IS_REGISTRY_LEVEL") + ".</span>";
>
>   			}
>
>   			else if (jetspeed.getSecuritySource(entry) == 2)
>
>   			{
>
>   				portletSecurityRef =
> portletSecurityRef  + "<span style=\"color:red\"><br/>" +
> l10n.get("SECURITY_IS_SYSTEM_DEFAULT") + ".</span>";
>
>   			}
>
>   		}
>
>   		else
>
>   		{
>
>   			portletSecurityRef = "-- Default --";
>
>   		}
>
>
>
>   		// decoration
>
>   		String controlListBox =
>
>   			(entry.getControl() != null &&
> entry.getControl().getName() != null) ?
>
>   			JetspeedTool.getPortletParameter(runData,
> (Portlet) runData.getUser().getTemp("customizer"), "control",
> entry.getControl().getName()) :
>
>   			JetspeedTool.getPortletParameter(runData,
> (Portlet) runData.getUser().getTemp("customizer"), "control");
>
>   		controlListBox = controlListBox.substring(12);
>
>   		controlListBox = controlListBox.replace('\n', ' ');
>
>   		controlListBox = controlListBox.replace('\r', ' ');
>
>   %>
>
>   		{id:'<%= portletId %>', parent:'<%=
> entry.getParent() %>',title:'<%= portletTitle
> %>',description:'<%= entry.getDescription() %>',skinName:'<%=
> portletSkinName %>',securityId:'<%= portletSecurityRef
> %>',controlListBox:'<%= controlListBox %>'}
>
>   <%
>
>   	}
>
>   %>
>
>   	]
>
>   <%
>
>   }
>
>   %>
>
>   ];
>
>   var sizes = [
>
>   <%
>
>   for (int i = 0; i < sizes.length; i++)
>
>   {
>
>   %>
>
>   	<%= i > 0 ? "," : "" %>'<%= sizes[i] %>'
>
>   <%
>
>   }
>
>   %>
>
>   ];
>
>
>
>   var dragBlockList;
>
>   var dragSinkList;
>
>
>
>   function renderLayoutPlayground(columns)
>
>   {
>
>   	var content = '<table border="0" width="100%"
> id="layoutPlaygroundTable"><tr>';
>
>
>
>   	for (var i = 0; i < columns.length; i++)
>
>   	{
>
>   		var columnContent = fillTemplate(
>
>   			dragSinkTemplate,
>
>   			'col', i,
>
>   			'row', 0
>
>   		);
>
>   		var portletList = columns[i];
>
>   		for (var j = 0; j < portletList.length; j++)
>
>   		{
>
>   			var psmlEntry = portletList[j];
>
>   			var controlListBox =
> psmlEntry.controlListBox.replace(/this.form.submit\(\)/gi,
> 'submitFormWithModelChanges(this.form)');
>
>   			columnContent += fillTemplate(
>
>   				dragBlockTemplate,
>
>   				'portletId', psmlEntry.id,
>
>   				'portletTitle', psmlEntry.title,
>
>   				'portletSkinName', psmlEntry.skinName,
>
>   				'portletSecurityId', psmlEntry.securityId,
>
>   				'portletDecoration', controlListBox,
>
>   				'closeImageSrc', 'images/close.gif',
>
>   				'jslinkTemplate', '<%=
> jslink.getTemplate() %>',
>
>   				'col', i,
>
>   				'row', j,
>
>   				'originalCol', i,
>
>   				'originalRow', j
>
>   			);
>
>   			columnContent += fillTemplate(
>
>   				dragSinkTemplate,
>
>   				'col', i,
>
>   				'row', j + 1
>
>   			);
>
>   		}
>
>   		content += fillTemplate(
>
>   			layoutPlaygroundTableColumnTemplate,
>
>   			'width', sizes[i],
>
>   			'columnContent', columnContent
>
>   		);
>
>   	}
>
>
>
>   	content += '</tr></table>';
>
>   	var layoutPlaygroundDiv =
> document.getElementById('layoutPlayground');
>
>   	layoutPlaygroundDiv.innerHTML = content;
>
>
>
>   	buildDragBlockList();
>
>   	buildDragSinkList();
>
>   }
>
>
>
>   var target = null;
>
>   var highlightedDragSink = null;
>
>   var previousX = 0;
>
>   var previousY = 0;
>
>
>
>   function elementGetTop(elem)
>
>   {
>
>   	var top = parseInt(elem.style.top);
>
>   	if (isNaN(top))
>
>   		return 0;
>
>   	else
>
>   		return top;
>
>   }
>
>
>
>   function elementGetLeft(elem)
>
>   {
>
>   	var left = parseInt(elem.style.left);
>
>   	if (isNaN(left))
>
>   		return 0;
>
>   	else
>
>   		return left;
>
>   }
>
>
>
>   function elementMoveBy(elem, point)
>
>   {
>
>   	var newTop = elementGetTop(elem) + point.y;
>
>   	var newLeft = elementGetLeft(elem) + point.x;
>
>   	elem.style.top = newTop + 'px';
>
>   	elem.style.left = newLeft + 'px';
>
>   }
>
>
>
>   function elementMoveTo(elem, point)
>
>   {
>
>   	elem.style.top = point.x + 'px';
>
>   	elem.style.left = point.y + 'px';
>
>   }
>
>
>
>   function getEventPositionX(e)
>
>   {
>
>   	if (!e)
>
>   	{
>
>   		// IE
>
>   		e = window.event;
>
>   		return e.clientX + document.body.scrollLeft;
>
>   	}
>
>   	else
>
>   	{
>
>   		// standard
>
>   		return e.clientX + document.body.scrollLeft;
>
>   	}
>
>   }
>
>
>
>   function getEventPositionY(e)
>
>   {
>
>   	if (!e)
>
>   	{
>
>   		// IE
>
>   		e = window.event;
>
>   		return e.clientY + document.body.scrollTop;
>
>   	}
>
>   	else
>
>   	{
>
>   		// standard
>
>   		return e.clientY + document.body.scrollTop;
>
>   	}
>
>   }
>
>
>
>   function findTargetDragBlock(e)
>
>   {
>
>   	var x = getEventPositionX(e);
>
>   	var y = getEventPositionY(e);
>
>
>
>   	for (var i = 0; i < dragBlockList.length; i++)
>
>   	{
>
>   		var dragBlock = dragBlockList[i];
>
>   		if (elementContainsPoint(dragBlock, x, y))
>
>   		{
>
>   			return dragBlock;
>
>   		}
>
>   	}
>
>
>
>   	return null;
>
>   }
>
>
>
>   function handleMouseDown(event)
>
>   {
>
>   	if (!event)	// IE
>
>   	{
>
>   		event = window.event;
>
>   //		event.target = event.srcElement;
>
>   	}
>
>
>
>   	target = findTargetDragBlock(event);
>
>
>
>   	if (target)
>
>   	{
>
>   		previousX = getEventPositionX(event);
>
>   		previousY = getEventPositionY(event);
>
>   		target.originalPosition =
> {x:elementGetLeft(target), y:elementGetTop(target)};
>
>   		target.style.borderColor = 'black';
>
>   		event.cancelBubble = true;
>
>   		event.returnValue = false;
>
>   		return false;
>
>   	}
>
>   	else
>
>   	{
>
>   		return true;
>
>   	}
>
>   }
>
>
>
>   function handleMouseMove(event)
>
>   {
>
>   	if (!event)	// IE
>
>   	{
>
>   		event = window.event;
>
>   //		event.target = event.srcElement;
>
>   	}
>
>
>
>   	if (target)
>
>   	{
>
>   		var currentX = getEventPositionX(event);
>
>   		var currentY = getEventPositionY(event);
>
>   		var dx = currentX - previousX;
>
>   		var dy = currentY - previousY;
>
>   		target.style.cursor = 'move';
>
>   		elementMoveBy(target, {x:dx, y:dy});
>
>   		highlightDragSink(currentX, currentY);
>
>   		previousX = currentX;
>
>   		previousY = currentY;
>
>   		event.cancelBubble = true;
>
>   		event.returnValue = false;
>
>   		return false;
>
>   	}
>
>   	else
>
>   	{
>
>   		return true;
>
>   	}
>
>   }
>
>
>
>   function handleMouseUp(event)
>
>   {
>
>   	if (!event)	// IE
>
>   	{
>
>   		event = window.event;
>
>   //		event.target = event.srcElement;
>
>   	}
>
>
>
>   	if (target)
>
>   	{
>
>   		target.style.cursor = 'pointer';
>
>   		target.style.borderColor = 'gray';
>
>   		if (highlightedDragSink)
>
>   		{
>
>   			drop(target, highlightedDragSink);
>
>   			unhighlight(highlightedDragSink);
>
>   			highlightedDragSink = null;
>
>   		}
>
>   		else
>
>   		{
>
>   			elementMoveTo(target, target.originalPosition);
>
>   		}
>
>   		target.originalPosition = null;
>
>   		target = null;
>
>   		previousX = 0;
>
>   		previousY = 0;
>
>   		event.cancelBubble = true;
>
>   		event.returnValue = false;
>
>   		return false;
>
>   	}
>
>   	else
>
>   	{
>
>   		return true;
>
>   	}
>
>   }
>
>
>
>   document.onmousedown = handleMouseDown;
>
>   document.onmousemove = handleMouseMove;
>
>   document.onmouseup = handleMouseUp;
>
>
>
>   function highlightDragSink(x, y)
>
>   {
>
>   	for (var i = 0; i < dragSinkList.length; i++)
>
>   	{
>
>   		var dragSink = dragSinkList[i];
>
>   		if (elementContainsPoint(dragSink, x, y))
>
>   		{
>
>   			if (highlightedDragSink)
>
>   				unhighlight(highlightedDragSink);
>
>   			highlight(dragSink);
>
>   			highlightedDragSink = dragSink;
>
>   			return;
>
>   		}
>
>   	}
>
>
>
>   	if (highlightedDragSink)
>
>   	{
>
>   		unhighlight(highlightedDragSink);
>
>   		highlightedDragSink = null;
>
>   	}
>
>   }
>
>
>
>   function elementContainsPoint(elem, x, y)
>
>   {
>
>   	var top = elem.offsetTop;
>
>   	var left = elem.offsetLeft;
>
>   	var height = elem.offsetHeight;
>
>   	var width = elem.offsetWidth;
>
>   	return	(0 <= x - left && x - left <= width) &&
>
>   		(0 <= y - top && y - top <= height);
>
>   }
>
>
>
>   function highlight(elem)
>
>   {
>
>   	elem.style.borderColor = '#FF0000';
>
>   }
>
>
>
>   function unhighlight(elem)
>
>   {
>
>   	elem.style.borderColor = '#EEEEEE';
>
>   }
>
>
>
>   function buildDragBlockList()
>
>   {
>
>   	var layoutPlaygroundTable =
> document.getElementById('layoutPlaygroundTable');
>
>   	var dragBlockCandidateList =
> layoutPlaygroundTable.getElementsByTagName("div");
>
>   	dragBlockList = new Array();
>
>   	for (var i = 0; i < dragBlockCandidateList.length; i++)
>
>   	{
>
>   		var dragBlockCandidate = dragBlockCandidateList[i];
>
>   		if (dragBlockCandidate.className == 'drag-block')
>
>   			dragBlockList[dragBlockList.length] =
> dragBlockCandidate;
>
>   	}
>
>   }
>
>
>
>   function buildDragSinkList()
>
>   {
>
>   	var layoutPlaygroundTable =
> document.getElementById('layoutPlaygroundTable');
>
>   	var dragSinkCandidateList =
> layoutPlaygroundTable.getElementsByTagName("div");
>
>   	dragSinkList = new Array();
>
>   	for (var i = 0; i < dragSinkCandidateList.length; i++)
>
>   	{
>
>   		var dragSinkCandidate = dragSinkCandidateList[i];
>
>   		if (dragSinkCandidate.className == 'drag-sink')
>
>   			dragSinkList[dragSinkList.length] =
> dragSinkCandidate;
>
>   	}
>
>   }
>
>
>
>   function drop(target, dragSink)
>
>   {
>
>   	var targetRowCol = eval('_rowcol=' +
> target.attributes['name'].value);
>
>   	var dragSinkRowCol = eval('_rowcol=' +
> dragSink.attributes['name'].value);
>
>
>
>   	if (destSameAsOrigin(targetRowCol, dragSinkRowCol))
>
>   		return;
>
>
>
>   	// get reference to portletEtnry
>
>   	var portletEntry = modelRoot[targetRowCol.col][targetRowCol.row];
>
>
>
>   	// remove from old position
>
>   	modelRoot[targetRowCol.col].splice(targetRowCol.row, 1);
>
>
>
>   	// insert into new position
>
>   	modelRoot[dragSinkRowCol.col].splice(dragSinkRowCol.row, 0,
> portletEntry);
>
>
>
>   	recordModelChange(targetRowCol, dragSinkRowCol);
>
>
>
>   	renderLayoutPlayground(modelRoot);
>
>   }
>
>
>
>   function destSameAsOrigin(origin, dest)
>
>   {
>
>   	return
>
>   		(origin.col == dest.col) &&
>
>   		(origin.row == dest.row || origin.row + 1 == dest.row);
>
>   }
>
>
>
>   function recordModelChange(origin, dest)
>
>   {
>
>   	var change = origin.col + ',' + origin.row + ',' + dest.col
> + ',' + dest.row;
>
>   	var f = document.forms['xform'];
>
>   	if (f.modelChangeList.value == '')
>
>   		f.modelChangeList.value = change;
>
>   	else
>
>   		f.modelChangeList.value += ';' + change;
>
>   }
>
>
>
>   function submitFormWithModelChanges(form)
>
>   {
>
>   	var modelChangeList = document.forms.xform.modelChangeList.value;
>
>   	form.modelChangeList.value = modelChangeList;
>
>   	form.submit();
>
>   }
>
>
>
>   function getPrintString(o)
>
>   {
>
>   	var s = '{';
>
>   	for (p in o)
>
>   	{
>
>   		s += p + ':' + o[p] + ', ';
>
>   	}
>
>   	s += '}';
>
>   	return s;
>
>   }
>
>   </script>
>
>
>
>   <!-- layout table -->
>
>   <br>
>
>
>
>   <div id='layoutPlayground'></div>
>
>   <script type="text/javascript">
>
>   renderLayoutPlayground(modelRoot);
>
>   </script>
>
>
>
>   <br>
>
>
>
>   <!-- buttons -->
>
>     <form name="xform" action="<%= jslink.getTemplate() %>" method="post">
>
>     <input type="hidden" name="<%= jslink.getActionKey() %>"
> value="<%= action %>" >
>
>     <input type="hidden" name="modelChangeList" value="">
>
>     <center>
>
>       <table cellspacing="2">
>
>         <tr>
>
>           <td>
>
>             <input type="submit" name="eventSubmit_doSave"
> value="<%= l10n.get("CUSTOMIZER_SAVEAPPLY") %>">
>
>           </td>
>
>           <td>
>
>             <input type="submit" name="eventSubmit_doCancel"
> value="<%= l10n.get("CUSTOMIZER_CANCEL") %>">
>
>           </td>
>
>         </tr>
>
>       </table>
>
>     </center>
>
>   </form>
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jetspeed-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: jetspeed-dev-help@jakarta.apache.org
>
>
>
>



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jetspeed-dev-help@jakarta.apache.org