You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pluto-scm@portals.apache.org by es...@apache.org on 2006/09/12 03:59:57 UTC

svn commit: r442414 - in /portals/pluto/trunk: pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/config/impl/ pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/impl/resource/ pluto-portal-driver/src/main/java/org/apac...

Author: esm
Date: Mon Sep 11 18:59:56 2006
New Revision: 442414

URL: http://svn.apache.org/viewvc?view=rev&rev=442414
Log:
[PLUTO-233]:  Adding the SupportedModesService for the portal driver.


Added:
    portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/impl/resource/SupportedModesServiceImpl.java   (with props)
    portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/services/portal/SupportedModesService.java   (with props)
    portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletModeAnchorTag.java   (with props)
Modified:
    portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/config/impl/DriverConfigurationImpl.java
    portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java
    portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/config/DriverConfiguration.java
    portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/pluto-portal-driver-services-config.xml
    portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/themes/portlet-skin.jsp
    portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/tld/pluto.tld

Modified: portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/config/impl/DriverConfigurationImpl.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/config/impl/DriverConfigurationImpl.java?view=diff&rev=442414&r1=442413&r2=442414
==============================================================================
--- portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/config/impl/DriverConfigurationImpl.java (original)
+++ portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/config/impl/DriverConfigurationImpl.java Mon Sep 11 18:59:56 2006
@@ -15,20 +15,22 @@
  */
 package org.apache.pluto.driver.config.impl;
 
-import org.apache.pluto.driver.services.portal.PortletApplicationConfig;
-import org.apache.pluto.driver.services.portal.PortletWindowConfig;
+import java.util.Collection;
+
+import javax.servlet.ServletContext;
+
+import org.apache.pluto.driver.config.DriverConfiguration;
 import org.apache.pluto.driver.services.portal.PageConfig;
+import org.apache.pluto.driver.services.portal.PortletApplicationConfig;
 import org.apache.pluto.driver.services.portal.PortletRegistryService;
+import org.apache.pluto.driver.services.portal.PortletWindowConfig;
 import org.apache.pluto.driver.services.portal.PropertyConfigService;
 import org.apache.pluto.driver.services.portal.RenderConfigService;
-import org.apache.pluto.driver.config.DriverConfiguration;
+import org.apache.pluto.driver.services.portal.SupportedModesService;
 import org.apache.pluto.driver.url.PortalURLParser;
 import org.apache.pluto.spi.PortalCallbackService;
 import org.apache.pluto.spi.optional.PortletPreferencesService;
 
-import javax.servlet.ServletContext;
-import java.util.Collection;
-
 /**
  * Encapsulation of the Pluto Driver ResourceConfig.
  *
@@ -43,6 +45,7 @@
     private PropertyConfigService propertyService;
     private PortletRegistryService registryService;
     private RenderConfigService renderService;
+    private SupportedModesService supportedModesService;
 
     // Container Services
     private PortalCallbackService portalCallbackService;
@@ -52,12 +55,14 @@
                                    PropertyConfigService propertyService,
                                    PortletRegistryService registryService,
                                    RenderConfigService renderService,
-                                   PortalCallbackService portalCallback) {
+                                   PortalCallbackService portalCallback,
+                                   SupportedModesService supportedModesService) {
         this.portalUrlParser = portalUrlParser;
         this.propertyService = propertyService;
         this.registryService = registryService;
         this.renderService = renderService;
         this.portalCallbackService = portalCallback;
+        this.supportedModesService = supportedModesService;
     }
 
     /**
@@ -137,6 +142,18 @@
     public PageConfig getPageConfig(String pageId) {
         return renderService.getPage(pageId);
     }
+    
+    public boolean isPortletModeSupportedByPortal(String mode) {
+        return supportedModesService.isPortletModeSupportedByPortal(mode);
+    }
+    
+    public boolean isPortletModeSupportedByPortlet(String portletId, String mode) {
+        return supportedModesService.isPortletModeSupportedByPortlet(portletId, mode);
+    }
+    
+    public boolean isPortletModeSupported(String portletId, String mode) {
+        return supportedModesService.isPortletModeSupported(portletId, mode);
+    }
 
     public void init(ServletContext context) {
         this.propertyService.init(context);
@@ -165,7 +182,7 @@
 
     public void setPortalUrlParser(PortalURLParser portalUrlParser) {
         this.portalUrlParser = portalUrlParser;
-    }
+    }       
 
 //
 // Container Services

Added: portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/impl/resource/SupportedModesServiceImpl.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/impl/resource/SupportedModesServiceImpl.java?view=auto&rev=442414
==============================================================================
--- portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/impl/resource/SupportedModesServiceImpl.java (added)
+++ portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/impl/resource/SupportedModesServiceImpl.java Mon Sep 11 18:59:56 2006
@@ -0,0 +1,244 @@
+package org.apache.pluto.driver.services.impl.resource;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.portlet.PortletMode;
+import javax.servlet.ServletContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pluto.PortletContainer;
+import org.apache.pluto.PortletContainerException;
+import org.apache.pluto.descriptors.portlet.PortletAppDD;
+import org.apache.pluto.descriptors.portlet.PortletDD;
+import org.apache.pluto.descriptors.portlet.SupportsDD;
+import org.apache.pluto.driver.AttributeKeys;
+import org.apache.pluto.driver.config.DriverConfigurationException;
+import org.apache.pluto.driver.services.portal.PortletApplicationConfig;
+import org.apache.pluto.driver.services.portal.PortletRegistryService;
+import org.apache.pluto.driver.services.portal.PortletWindowConfig;
+import org.apache.pluto.driver.services.portal.PropertyConfigService;
+import org.apache.pluto.driver.services.portal.SupportedModesService;
+
+/**
+ * Allows clients to determine if a particular PortletMode is supported
+ * by the portal, a particular portlet, or both.
+ * 
+ * This implementation depends on {@link PropertyConfigService},  
+ * {@link PortletRegistryService}, and {@link PortletContainer}.  
+ * The two services are injected by Spring, and the container is obtained
+ * from the <code>ServletContext</code>. 
+ * 
+ * @author <a href="mailto:esm@apache.org">Elliot Metsger</a>
+ * @version $Id$
+ * @since September 9, 2006
+ * @todo How will hot-deploy of portlets via the admin portlet work with this impl?
+ */
+public class SupportedModesServiceImpl implements SupportedModesService 
+{
+    /** Logger */
+    private static final Log LOG = LogFactory.getLog(SupportedModesServiceImpl.class);
+
+    /** PortletApplicationConfig objects keyed by their String context path */
+    private Map portletApps = new HashMap();
+    
+    /** Sets containing PortletMode objects keyed by String portlet Id */
+    private Map supportedPortletModesByPortlet = new HashMap();
+    
+    /** PortletMode objects supported by the portal */
+    private Set supportedPortletModesByPortal = new HashSet();        
+    
+    /** PortletContainer used to obtain Portlet Descriptors (PortletAppDD) */
+    private PortletContainer container = null;
+    
+    /** PortletRegistryService used to obtain PortletApplicationConfig objects */
+    private PortletRegistryService portletRegistry = null;
+    
+    /** PropertyConfig Service used to obtain supported portal modes */
+    private PropertyConfigService propertySvc = null;
+    
+    
+    /**
+     * Constructs a SupportedModesService with its dependencies.
+     * 
+     * @param portletRegistry the PortletRegistryService
+     * @param propertySvc the PropertyConfigService
+     */
+    public SupportedModesServiceImpl(PortletRegistryService portletRegistry, PropertyConfigService propertySvc)
+    {
+        this.portletRegistry = portletRegistry;
+        this.propertySvc = propertySvc;        
+    }
+    
+    //  SupportedModesService Implementation -----------------
+    
+    public boolean isPortletModeSupported(String portletId, String mode) 
+    {
+        return isPortletModeSupportedByPortal(mode) && isPortletModeSupportedByPortlet(portletId, mode);
+    }
+
+    public boolean isPortletModeSupportedByPortal(String mode) 
+    {
+        LOG.debug("Is mode [" + mode + "] supported by the portal?");
+        return supportedPortletModesByPortal.contains(new PortletMode(mode));
+    }
+
+    public boolean isPortletModeSupportedByPortlet(String portletId, String mode) 
+    {
+        LOG.debug("Is mode [" + mode + "] for portlet [" + portletId + "] supported by the portlet?");
+        Set supportedModes = (Set)supportedPortletModesByPortlet.get(portletId);
+        if (supportedModes == null)
+        {
+            return false;
+        }        
+        return supportedModes.contains(new PortletMode(mode));
+    }
+
+    // DriverConfiguration Lifecycle Implementation ---------
+    
+    public void destroy() throws DriverConfigurationException 
+    {
+        LOG.debug("Destroying Supported Modes Service...");
+        supportedPortletModesByPortlet = null;
+        supportedPortletModesByPortal = null;
+        container = null;
+        portletRegistry = null;
+        portletApps = null;        
+        propertySvc = null;
+        LOG.debug("Supported Modes Service destroyed.");
+    }
+
+    public void init(ServletContext ctx) throws DriverConfigurationException 
+    {
+        LOG.debug("Initializing Supported Modes Service...");
+        // Obtain the Portlet Container
+        this.container = (PortletContainer)ctx.getAttribute(AttributeKeys.PORTLET_CONTAINER);
+        initInternal();
+        LOG.debug("Supported Modes Service initalized.");
+    }
+    
+    // Private Methods --------------------------------------
+    
+    /**
+     * Initialize the data structures for supportedPortletModesByPortal,
+     * supportedPortletModesByPortlet, and portletApps.
+     * 
+     * Note that the order of initalization matters.
+     */
+    private void initInternal() 
+    {
+        // portlet applications should be loaded first
+        loadPortletApplications();
+        loadPortalModes();
+        loadPortletModes();        
+    }    
+    
+    /** 
+     * Populates the portletApps map with PortletApplicationConfig objects
+     * keyed by their context path.
+     */
+    private void loadPortletApplications() 
+    {
+        LOG.debug("Loading Portlet Applications...");
+        Iterator apps = portletRegistry.getPortletApplications().iterator();
+        while (apps.hasNext())
+        {
+            PortletApplicationConfig app = (PortletApplicationConfig)apps.next();
+            LOG.debug("Loading [" + app.getContextPath() + "]");
+            portletApps.put(app.getContextPath(), app);
+        }
+        LOG.debug("Loaded [" + portletApps.size() + "] Portlet Applications.");
+    }
+    
+    /** Populates the supportedPortletModesByPortal set. */
+    private void loadPortalModes() 
+    {
+        // Add the PortletModes supported by the portal to the
+        // supportedPortletModesByPortal set.
+        LOG.debug("Loading supported portal modes...");        
+        Iterator modes = propertySvc.getSupportedPortletModes().iterator();
+        while (modes.hasNext()) {
+            String mode = (String) modes.next();
+            LOG.debug("Loading mode [" + mode + "]");
+            supportedPortletModesByPortal.add(new PortletMode(mode));
+        }
+        LOG.debug("Loaded [" + supportedPortletModesByPortal.size() + "] supported portal modes");
+    }
+    
+    /** 
+     * Populates the supportedPortletModesByPortlet map, which contains
+     * Sets of PortletMode objects keyed by String portlet Ids.
+     */
+    private void loadPortletModes()
+    {                
+        // Add the PortletModes supported by each portlet to
+        // the supportedPortletModesByPortlet map.
+        LOG.debug("Loading modes supported by each Portlet...");
+        Iterator apps = portletApps.values().iterator();
+        while (apps.hasNext())
+        {
+            PortletApplicationConfig app = (PortletApplicationConfig)apps.next();            
+            PortletAppDD portletAppDD;
+            try {
+                portletAppDD = container
+                    .getPortletApplicationDescriptor(app.getContextPath());
+            } catch (PortletContainerException e) {
+                LOG.warn(e);
+                continue;
+            }
+                        
+            // for each portletAppDD, retrieve the portletDD and the supported modes
+            Iterator portlets = portletAppDD.getPortlets().iterator();
+            while (portlets.hasNext()) {                
+                PortletDD portlet = (PortletDD)portlets.next();
+                LOG.debug("Loading modes supported by portlet [" + app.getContextPath() + "]." +
+                        "[" + portlet.getPortletName() + "]");
+                Iterator supports = portlet.getSupports().iterator();
+                Set pModes = new HashSet();
+                while (supports.hasNext())
+                {
+                    SupportsDD supportsDD = (SupportsDD)supports.next();
+                    Iterator portletModes = supportsDD.getPortletModes().iterator();
+                    
+                    while (portletModes.hasNext())
+                    {
+                        PortletMode pMode = new PortletMode((String)portletModes.next());
+                        LOG.debug("Adding mode [" + pMode + "]");
+                        pModes.add(pMode);                                
+                    }                    
+                }
+                
+                supportedPortletModesByPortlet.put(
+                        PortletWindowConfig.createPortletId(app.getContextPath(), portlet.getPortletName()), 
+                        pModes);                     
+            } 
+        }
+    }
+    
+    /**
+     * Retrieve the PortletApplicationConfig by its context path.
+     * 
+     * @param contextPath the context
+     * @return the PortletApplicationConfig, or null if it wasn't found.
+     */
+    private PortletApplicationConfig getPortletApplication(String contextPath) 
+    {
+        PortletApplicationConfig app = null;
+        // attempt to retrieve the PortletApplicationConfig from the map
+        app = (PortletApplicationConfig)portletApps.get(contextPath);
+        
+        // if it wasn't in the map, perhaps it has been added since 
+        // the container was started
+        if (app == null)
+        {
+            loadPortletApplications();
+        }        
+        app = (PortletApplicationConfig)portletApps.get(contextPath);
+        return app;
+    }    
+
+}

Propchange: portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/impl/resource/SupportedModesServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/pluto/trunk/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/impl/resource/SupportedModesServiceImpl.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java?view=diff&rev=442414&r1=442413&r2=442414
==============================================================================
--- portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java (original)
+++ portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/PortalDriverServlet.java Mon Sep 11 18:59:56 2006
@@ -15,6 +15,16 @@
  */
 package org.apache.pluto.driver;
 
+import java.io.IOException;
+
+import javax.portlet.PortletException;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.pluto.PortletContainer;
@@ -24,16 +34,10 @@
 import org.apache.pluto.driver.core.PortletWindowImpl;
 import org.apache.pluto.driver.services.portal.PageConfig;
 import org.apache.pluto.driver.services.portal.PortletWindowConfig;
+import org.apache.pluto.driver.services.portal.SupportedModesService;
 import org.apache.pluto.driver.url.PortalURL;
-
-import javax.portlet.PortletException;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.context.WebApplicationContext;
 
 /**
  * The controller servlet used to drive the Portal Driver. All requests mapped
@@ -41,14 +45,21 @@
  * 
  * @author <a href="mailto:ddewolf@apache.org">David H. DeWolf</a>
  * @author <a href="mailto:zheng@apache.org">ZHENG Zhong</a>
+ * @author <a href="mailto:esm@apache.org">Elliot Metsger</a>
  * @version 1.0
  * @since Sep 22, 2004
  */
 public class PortalDriverServlet extends HttpServlet {
 
     /** Internal Logger. */
-    private static final Log LOG = LogFactory.getLog(PortalDriverServlet.class);
+    private static final Log LOG = LogFactory.getLog(PortalDriverServlet.class);    
+    
+    /** The Portal Driver sServlet Context */
+    private ServletContext servletContext = null;
     
+    /** Is the SupportedModesService initialized? */
+    private boolean isSupportedModesServiceInitialized = false;
+        
     protected static final String DEFAULT_PAGE_URI =
     		"/WEB-INF/themes/pluto-default-theme.jsp";
     
@@ -56,6 +67,8 @@
     protected PortletContainer container = null;
     
     
+    
+    
     // HttpServlet Impl --------------------------------------------------------
     
     public String getServletInfo() {
@@ -68,9 +81,9 @@
      * @see PortletContainer
      */
     public void init() {
-        ServletContext servletContext = getServletContext();
+        servletContext = getServletContext();
         container = (PortletContainer) servletContext.getAttribute(
-        		AttributeKeys.PORTLET_CONTAINER);
+        		AttributeKeys.PORTLET_CONTAINER);        
     }
     
 
@@ -83,13 +96,12 @@
      */
     public void doGet(HttpServletRequest request, HttpServletResponse response)
     throws ServletException, IOException {
-    	
+
+        initSupportedModesService();
+        
         PortalRequestContext portalRequestContext =
             new PortalRequestContext(getServletContext(), request, response);
 
-
-
-
         PortalURL portalURL = portalRequestContext.getRequestedPortalURL();
         String actionWindowId = portalURL.getActionWindow();
         PortletWindowConfig actionWindowConfig = getDriverConfiguration()
@@ -125,6 +137,7 @@
             {
                 LOG.error("PageConfig for render path [" + portalURL.getRenderPath() + "] could not be found.");
             }
+            
             request.setAttribute(AttributeKeys.CURRENT_PAGE, pageConfig);
             String uri = (pageConfig.getUri() != null)
             		? pageConfig.getUri() : DEFAULT_PAGE_URI;
@@ -174,9 +187,22 @@
     private DriverConfiguration getDriverConfiguration() {
         return (DriverConfiguration) getServletContext().getAttribute(
         		AttributeKeys.DRIVER_CONFIG);
-    }
-
+    }    
     
+    private void initSupportedModesService()
+    {
+        if (isSupportedModesServiceInitialized)
+        {
+            return;
+        }
+
+        ApplicationContext springContext = (ApplicationContext)servletContext.getAttribute(
+                WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
+        SupportedModesService service = (SupportedModesService)springContext.getBean("SupportedModesService");
+        service.init(servletContext);
+        
+        isSupportedModesServiceInitialized = true;
+    }
     
 }
 

Modified: portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/config/DriverConfiguration.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/config/DriverConfiguration.java?view=diff&rev=442414&r1=442413&r2=442414
==============================================================================
--- portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/config/DriverConfiguration.java (original)
+++ portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/config/DriverConfiguration.java Mon Sep 11 18:59:56 2006
@@ -97,6 +97,12 @@
     Collection getPages();
 
     PageConfig getPageConfig(String pageId);
+    
+    boolean isPortletModeSupportedByPortal(String mode);
+    
+    boolean isPortletModeSupportedByPortlet(String portletId, String mode);
+    
+    boolean isPortletModeSupported(String portletId, String mode);
 
 //
 // Utility methods for the container

Added: portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/services/portal/SupportedModesService.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/services/portal/SupportedModesService.java?view=auto&rev=442414
==============================================================================
--- portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/services/portal/SupportedModesService.java (added)
+++ portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/services/portal/SupportedModesService.java Mon Sep 11 18:59:56 2006
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pluto.driver.services.portal;
+
+/**
+ * Allows clients to determine if a particular PortletMode is supported
+ * by the portal, a particular portlet, or both. 
+ * 
+ * @author <a href="mailto:esm@apache.org">Elliot Metsger</a>
+ * @version $Id$
+ * @since September 9, 2006
+ * @see PortletMode
+ */
+public interface SupportedModesService extends DriverConfigurationService {
+    
+    /**
+     * Returns true if the portlet and the portal support the supplied mode.
+     * @param portletId the id uniquely identifiying the portlet
+     * @param mode the portlet mode
+     * @return true if the portlet and portal both support the supplied mode
+     */
+    boolean isPortletModeSupported(String portletId, String mode);
+    
+    /**
+     * Returns true if the portal supports the supplied mode.
+     * @param mode the portlet mode
+     * @return true if the portal supports the supplied mode
+     */
+    boolean isPortletModeSupportedByPortal(String mode);
+    
+    /**
+     * Returns true if the portlet supports the supplied mode.
+     * @param portletId the id uniquely identifying the portlet
+     * @param mode the portlet mode
+     * @return true if the portlet supports the supplied mode.
+     */
+    boolean isPortletModeSupportedByPortlet(String portletId, String mode);
+
+}

Propchange: portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/services/portal/SupportedModesService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/services/portal/SupportedModesService.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletModeAnchorTag.java
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletModeAnchorTag.java?view=auto&rev=442414
==============================================================================
--- portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletModeAnchorTag.java (added)
+++ portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletModeAnchorTag.java Mon Sep 11 18:59:56 2006
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pluto.driver.tags;
+
+import java.io.IOException;
+
+import javax.portlet.PortletMode;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspWriter;
+import javax.servlet.jsp.tagext.BodyTagSupport;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pluto.driver.AttributeKeys;
+import org.apache.pluto.driver.config.DriverConfiguration;
+import org.apache.pluto.driver.core.PortalRequestContext;
+import org.apache.pluto.driver.services.portal.PortletWindowConfig;
+import org.apache.pluto.driver.url.PortalURL;
+import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
+
+/**
+ * The tag is used to render a portlet mode anchor specified by the portlet ID and mode.
+ * This is designed to live inside of a <pluto:portlet/> tag.
+ * 
+ * <pluto:modeAnchor portletId="" portletMode="edit"/>
+ *
+ * @author <a href="mailto:esm@apache.org">Elliot Metsger</a>
+ * @author <a href="mailto:cdoremus@apache.org">Craig Doremus</a>
+ * @todo Test supported Window States using a version of ActionResponseImpl.isWindowStateAllowed()
+ */
+public class PortletModeAnchorTag extends BodyTagSupport {
+    
+    /** Logger. */
+    private static final Log LOG = LogFactory.getLog(PortletModeAnchorTag.class);
+        
+    
+    // Private Member Variables ------------------------------------------------
+    private String portletMode = null;
+    
+    /** The portlet ID attribute obtained from parent tag. */
+    private String portletId = null;
+    
+    /** The evaluated value of the portlet ID attribute. */
+    private String evaluatedPortletId = null;       
+    
+    // BodyTagSupport Impl -----------------------------------------------------
+    
+    /**
+     * Method invoked when the start tag is encountered.
+     * @throws JspException  if an error occurs.
+     */
+    public int doStartTag() throws JspException {
+        
+        // Ensure that the modeAnchor tag resides within a portlet tag.
+        PortletTag parentTag = (PortletTag) TagSupport.findAncestorWithClass(
+                this, PortletTag.class);
+        if (parentTag == null) {
+            throw new JspException("Portlet window controls may only reside "
+                    + "within a pluto:portlet tag.");
+        }
+        
+        portletId = parentTag.getPortletId();        
+        // Evaluate portlet ID attribute.
+        evaluatePortletId();
+        
+        // Retrieve the portlet window config for the evaluated portlet ID.
+        ServletContext servletContext = pageContext.getServletContext();
+        DriverConfiguration driverConfig = (DriverConfiguration)
+                servletContext.getAttribute(AttributeKeys.DRIVER_CONFIG);
+        PortletWindowConfig windowConfig = driverConfig
+                .getPortletWindowConfig(evaluatedPortletId);
+       
+        if (isPortletModeAllowed(driverConfig, windowConfig, portletMode)) {
+            // Retrieve the portal environment.
+            PortalRequestContext portalEnv = PortalRequestContext.getContext(
+                    (HttpServletRequest) pageContext.getRequest());        
+
+            PortalURL portalUrl =  portalEnv.createPortalURL();
+            portalUrl.setPortletMode(evaluatedPortletId, new PortletMode(portletMode));
+
+            // Print the mode anchor tag.
+            try {
+                JspWriter out = pageContext.getOut();
+                out.print("<a href=\"");
+                out.print(portalUrl.toString());
+                out.print("\">");
+                out.print("<span class=\"");
+                out.print(portletMode);
+                out.print("\"></span></a>");
+            } catch (IOException ex) {
+                throw new JspException(ex);
+            }
+        }
+        
+        
+        // Continue to evaluate the tag body.
+        return EVAL_BODY_INCLUDE;
+    }
+    
+    
+    // Package Methods ---------------------------------------------------------
+    
+    /**
+     * Returns the evaluated portlet ID.
+     * @return the evaluated portlet ID.
+     */
+    String getEvaluatedPortletId() {
+        return evaluatedPortletId;
+    }
+
+    
+    
+    // Private Methods ---------------------------------------------------------
+    
+    /**
+     * Evaluates the portlet ID attribute passed into this tag. This method
+     * evaluates the member variable <code>portletId</code> and saves the
+     * evaluated result to <code>evaluatedPortletId</code>
+     * @throws JspException  if an error occurs.
+     */
+    private void evaluatePortletId() throws JspException {
+        Object obj = ExpressionEvaluatorManager.evaluate(
+                "portletId", portletId, String.class, this, pageContext);
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Evaluated portletId to: " + obj);
+        }
+        evaluatedPortletId = (String) obj;
+    }
+
+    /**
+     * @return the portletMode
+     */
+    public String getPortletMode() {
+        return portletMode;
+    }
+
+    /**
+     * @param portletMode the portletMode to set
+     */
+    public void setPortletMode(String portletMode) {
+        this.portletMode = portletMode;
+    }
+    
+    private boolean isPortletModeAllowed(DriverConfiguration config, PortletWindowConfig window, String mode) {
+        LOG.debug("Testing if PortletWindowConfig [" + Integer.toHexString(window.hashCode()) + "] supports mode [" + mode + "]");
+        return config.isPortletModeSupported(getEvaluatedPortletId(), mode);       
+    }
+
+    
+}
\ No newline at end of file

Propchange: portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletModeAnchorTag.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/pluto/trunk/pluto-portal-driver/src/main/java/org/apache/pluto/driver/tags/PortletModeAnchorTag.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/pluto-portal-driver-services-config.xml
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/pluto-portal-driver-services-config.xml?view=diff&rev=442414&r1=442413&r2=442414
==============================================================================
--- portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/pluto-portal-driver-services-config.xml (original)
+++ portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/pluto-portal-driver-services-config.xml Mon Sep 11 18:59:56 2006
@@ -68,6 +68,7 @@
       <constructor-arg><ref bean="PropertyConfigService"/></constructor-arg>
       <constructor-arg><ref bean="PortletRegistryConfig"/></constructor-arg>
       <constructor-arg><ref bean="RenderConfigService"/></constructor-arg>
+      <constructor-arg><ref bean="SupportedModesService"/></constructor-arg>
 
       <!-- === Container Services === -->
       <constructor-arg><ref bean="PortalCallbackService"/></constructor-arg>
@@ -110,6 +111,13 @@
     <bean id="RenderConfigService"
           class="org.apache.pluto.driver.services.impl.resource.RenderConfigServiceImpl"
           singleton="true">
+    </bean>
+    
+    <bean id="SupportedModesService"
+          class="org.apache.pluto.driver.services.impl.resource.SupportedModesServiceImpl"
+          singleton="true">
+          <constructor-arg><ref bean="PortletRegistryConfig"/></constructor-arg>
+          <constructor-arg><ref bean="PropertyConfigService"/></constructor-arg>          
     </bean>
 
     <!-- ================================================ -->

Modified: portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/themes/portlet-skin.jsp
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/themes/portlet-skin.jsp?view=diff&rev=442414&r1=442413&r2=442414
==============================================================================
--- portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/themes/portlet-skin.jsp (original)
+++ portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/themes/portlet-skin.jsp Mon Sep 11 18:59:56 2006
@@ -23,9 +23,9 @@
   <div class="portlet" id='<c:out value="${portlet}"/>'>
     <div class="header">
       <!-- Portlet Mode Controls -->
-      <a href="<pluto:url portletMode="help"/>"><span class="help"></span></a>
-      <a href="<pluto:url portletMode="edit"/>"><span class="edit"></span></a>
-      <a href="<pluto:url portletMode="view"/>"><span class="view"></span></a>
+      <pluto:modeAnchor portletMode="view"/>
+      <pluto:modeAnchor portletMode="edit"/>
+      <pluto:modeAnchor portletMode="help"/>
       <!-- Window State Controls -->
       <a href="<pluto:url windowState="minimized"/>"><span class="min"></span></a>
       <a href="<pluto:url windowState="maximized"/>"><span class="max"></span></a>

Modified: portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/tld/pluto.tld
URL: http://svn.apache.org/viewvc/portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/tld/pluto.tld?view=diff&rev=442414&r1=442413&r2=442414
==============================================================================
--- portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/tld/pluto.tld (original)
+++ portals/pluto/trunk/pluto-portal/src/main/webapp/WEB-INF/tld/pluto.tld Mon Sep 11 18:59:56 2006
@@ -40,6 +40,17 @@
   </tag>
 
   <tag>
+    <name>modeAnchor</name>
+    <tagclass>org.apache.pluto.driver.tags.PortletModeAnchorTag</tagclass>
+    <bodycontent>empty</bodycontent>
+    <attribute>
+      <name>portletMode</name>
+      <required>true</required>
+      <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+     
+  <tag>
     <name>title</name>
     <tagclass>org.apache.pluto.driver.tags.PortletTitleTag</tagclass>
     <bodycontent>empty</bodycontent>