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 ms...@apache.org on 2015/01/27 09:01:47 UTC

[03/19] portals-pluto git commit: Progress towards a public render parameter mapping service

Progress towards a public render parameter mapping service


Project: http://git-wip-us.apache.org/repos/asf/portals-pluto/repo
Commit: http://git-wip-us.apache.org/repos/asf/portals-pluto/commit/c2504532
Tree: http://git-wip-us.apache.org/repos/asf/portals-pluto/tree/c2504532
Diff: http://git-wip-us.apache.org/repos/asf/portals-pluto/diff/c2504532

Branch: refs/heads/PortletHub
Commit: c250453267ae2ad742a58d5b34a9ce6cc56116ca
Parents: 386c1d7
Author: Scott Nicklous <ms...@apache.org>
Authored: Sun Jan 18 22:26:44 2015 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Sun Jan 18 22:26:44 2015 +0100

----------------------------------------------------------------------
 .../PortletStateAwareResponseContext.java       |  99 +-
 .../pluto/container/PortletURLProvider.java     | 178 ++--
 .../pluto/container/impl/PortletURLImpl.java    | 976 ++++++++++---------
 .../container/impl/StateAwareResponseImpl.java  | 580 ++++++-----
 .../PortletStateAwareResponseContextImpl.java   | 292 +++---
 .../container/PortletURLProviderImpl.java       | 482 ++++-----
 .../portal/PublicRenderParameterMapper.java     |  60 ++
 .../driver/url/PortalURLPublicParameter.java    |   6 -
 8 files changed, 1455 insertions(+), 1218 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c2504532/pluto-container-api/src/main/java/org/apache/pluto/container/PortletStateAwareResponseContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletStateAwareResponseContext.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletStateAwareResponseContext.java
index 80ac516..51064b1 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletStateAwareResponseContext.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletStateAwareResponseContext.java
@@ -1,40 +1,59 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pluto.container;
-
-import java.util.List;
-import java.util.Map;
-
-import javax.portlet.Event;
-import javax.portlet.PortletMode;
-import javax.portlet.WindowState;
-
-/**
- * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
- * @version $Id$
- */
-public interface PortletStateAwareResponseContext extends PortletResponseContext
-{
-    PortletMode getPortletMode();
-    void setPortletMode(PortletMode portletMode);
-    WindowState getWindowState();
-    void setWindowState(WindowState windowState);
-    Map<String, String[]> getRenderParameters();
-    Map<String, String[]> getPublicRenderParameters();
-    EventProvider getEventProvider();
-    List<Event> getEvents();
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pluto.container;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.Event;
+import javax.portlet.PortletMode;
+import javax.portlet.WindowState;
+import javax.xml.namespace.QName;
+
+/**
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public interface PortletStateAwareResponseContext extends PortletResponseContext
+{
+    PortletMode getPortletMode();
+    void setPortletMode(PortletMode portletMode);
+    WindowState getWindowState();
+    void setWindowState(WindowState windowState);
+    Map<String, String[]> getRenderParameters();
+    Map<String, String[]> getPublicRenderParameters();
+    EventProvider getEventProvider();
+    List<Event> getEvents();
+    
+    /**
+     * Add a public render parameter including QName to allow for use of
+     * PRP mapping algorithm.
+     *  
+     * @param qn           QName
+     * @param identifier   Identifier for PRP
+     * @param values       values array
+     */
+    void addPublicRenderParameter(QName qn, String identifier, String[] values);
+    
+    /**
+     * Remove the PRP referred to by the QName
+     * 
+     * @param qn
+     */
+    void removePublicRenderParameter(QName qn);
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c2504532/pluto-container-api/src/main/java/org/apache/pluto/container/PortletURLProvider.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletURLProvider.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletURLProvider.java
index 1e9170f..da6f0c6 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletURLProvider.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletURLProvider.java
@@ -1,80 +1,98 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pluto.container;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.List;
-import java.util.Map;
-
-import javax.portlet.PortletMode;
-import javax.portlet.PortletSecurityException;
-import javax.portlet.WindowState;
-
-/**
- * Defines the interface used by the portlet container to create Portlet URLs.
- * This provider must be implemented by the Portal and provided via the
- * container services upon initialization of the container.
- *
- * @version 1.0
- */
-public interface PortletURLProvider {
-
-    enum TYPE { ACTION, RENDER, RESOURCE };
-    
-    TYPE getType();
-
-    /**
-     * Sets the new portlet mode at the URL. If no mode is set at the URL the
-     * currently active mode is used.
-     * @param mode the new portlet mode
-     */
-    void setPortletMode(PortletMode mode);
-    
-    PortletMode getPortletMode();
-
-    /**
-     * Sets the new window state at the URL. If no state is set at the URL the
-     * currently active state is used.
-     * @param state the new window state
-     */
-    void setWindowState(WindowState state);
-    
-    WindowState getWindowState();
-
-    void setSecure(boolean secure) throws PortletSecurityException;
-    boolean isSecure();
-
-    Map<String, String[]> getRenderParameters();
-    Map<String, String[]> getPublicRenderParameters();
-    
-    String getCacheability();
-    void setCacheability(String cacheLevel);
-    
-    String getResourceID();
-    void setResourceID(String resourceID);
-    
-    String toURL();
-    
-    void write(Writer out, boolean escapeXML) throws IOException;
-
-    /**
-     * Gets the mutable map of vendor-specific properties as set on the BaseURL
-     * @return parameters a map containing the name and value(s) of the properties (may return null)
-     */
-    public Map<String, List<String>> getProperties();
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pluto.container;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+import java.util.Map;
+
+import javax.portlet.PortletMode;
+import javax.portlet.PortletSecurityException;
+import javax.portlet.WindowState;
+import javax.xml.namespace.QName;
+
+/**
+ * Defines the interface used by the portlet container to create Portlet URLs.
+ * This provider must be implemented by the Portal and provided via the
+ * container services upon initialization of the container.
+ *
+ * @version 1.0
+ */
+public interface PortletURLProvider {
+
+    enum TYPE { ACTION, RENDER, RESOURCE };
+    
+    TYPE getType();
+
+    /**
+     * Sets the new portlet mode at the URL. If no mode is set at the URL the
+     * currently active mode is used.
+     * @param mode the new portlet mode
+     */
+    void setPortletMode(PortletMode mode);
+    
+    PortletMode getPortletMode();
+
+    /**
+     * Sets the new window state at the URL. If no state is set at the URL the
+     * currently active state is used.
+     * @param state the new window state
+     */
+    void setWindowState(WindowState state);
+    
+    WindowState getWindowState();
+
+    void setSecure(boolean secure) throws PortletSecurityException;
+    boolean isSecure();
+
+    Map<String, String[]> getRenderParameters();
+    Map<String, String[]> getPublicRenderParameters();
+    
+    /**
+     * Add a public render parameter including QName to allow for use of
+     * PRP mapping algorithm.
+     *  
+     * @param qn           QName
+     * @param identifier   Identifier for PRP
+     * @param values       values array
+     */
+    void addPublicRenderParameter(QName qn, String identifier, String[] values);
+    
+    /**
+     * Remove the PRP referred to by the QName
+     * 
+     * @param qn
+     */
+    void removePublicRenderParameter(QName qn);
+    
+    String getCacheability();
+    void setCacheability(String cacheLevel);
+    
+    String getResourceID();
+    void setResourceID(String resourceID);
+    
+    String toURL();
+    
+    void write(Writer out, boolean escapeXML) throws IOException;
+
+    /**
+     * Gets the mutable map of vendor-specific properties as set on the BaseURL
+     * @return parameters a map containing the name and value(s) of the properties (may return null)
+     */
+    public Map<String, List<String>> getProperties();
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c2504532/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletURLImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletURLImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletURLImpl.java
index 5d9f7c5..60e9652 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletURLImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletURLImpl.java
@@ -1,467 +1,509 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pluto.container.impl;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.portlet.PortalContext;
-import javax.portlet.PortletMode;
-import javax.portlet.PortletModeException;
-import javax.portlet.PortletSecurityException;
-import javax.portlet.PortletURL;
-import javax.portlet.PortletURLGenerationListener;
-import javax.portlet.ResourceURL;
-import javax.portlet.WindowState;
-import javax.portlet.WindowStateException;
-
-import org.apache.pluto.container.PortletMimeResponseContext;
-import org.apache.pluto.container.PortletResponseContext;
-import org.apache.pluto.container.PortletURLListenerService;
-import org.apache.pluto.container.PortletURLProvider;
-import org.apache.pluto.container.om.portlet.CustomPortletMode;
-import org.apache.pluto.container.om.portlet.PortletApplicationDefinition;
-import org.apache.pluto.container.om.portlet.PortletDefinition;
-import org.apache.pluto.container.om.portlet.Supports;
-import org.apache.pluto.container.util.ArgumentUtility;
-
-/**
- * Refactoring where functionality was pushed into JSR-286 <code>BaseURL</code>.
- *
- * @since 2.0
- */
-public class PortletURLImpl implements PortletURL, ResourceURL {
-
-    private PortletResponseContext responseContext;
-    private PortalContext portalContext;
-    private PortletURLProvider urlProvider;
-    private String cacheLevel = ResourceURL.PAGE;
-    private boolean filtering;
-    private boolean renderURL;
-    
-    public PortletURLImpl(PortletResponseContext responseContext, PortletURLProvider urlProvider)
-    {
-        this.responseContext = responseContext;
-        this.portalContext = responseContext.getContainer().getContainerServices().getPortalContext();
-        this.urlProvider = urlProvider;
-        renderURL = PortletURLProvider.TYPE.RENDER == urlProvider.getType();
-    }
-    
-    public PortletURLImpl(PortletMimeResponseContext responseContext, PortletURLProvider.TYPE type)
-    {
-        this(responseContext, responseContext.getPortletURLProvider(type));
-    }
-    
-    public PortletURLImpl(PortletMimeResponseContext responseContext, String cacheLevel)
-    {
-        this(responseContext, PortletURLProvider.TYPE.RESOURCE);
-        if (cacheLevel != null)
-        {
-            this.cacheLevel = cacheLevel;
-        }
-        urlProvider.setCacheability(this.cacheLevel);
-    }
-
-    private boolean isPortletModeAllowed(PortletMode mode)
-    {
-        if(PortletMode.VIEW.equals(mode))
-        {
-            return true;
-        }
-        
-        String modeName = mode.toString();
-
-        PortletDefinition dd = responseContext.getPortletWindow().getPortletDefinition();
-
-        for (Supports sup : dd.getSupports())
-        {
-            for (String m : sup.getPortletModes())
-            {
-                if (m.equalsIgnoreCase(modeName)) 
-                {
-                    // check if a portlet managed mode which is always allowed.
-                    CustomPortletMode cpm = dd.getApplication().getCustomPortletMode(modeName);
-                    if (cpm != null && !cpm.isPortalManaged())
-                    {
-                        return true;
-                    }
-                    Enumeration<PortletMode> supportedModes = portalContext.getSupportedPortletModes();
-                    while (supportedModes.hasMoreElements()) 
-                    {
-                        if (supportedModes.nextElement().equals(mode)) 
-                        {
-                            return true;
-                        }
-                    }
-                    return false;
-                }
-            }
-        }
-        return false;
-    }
-
-    private boolean isWindowStateAllowed(WindowState state)
-    {
-        Enumeration<WindowState> supportedStates = portalContext.getSupportedWindowStates();
-        while (supportedStates.hasMoreElements()) {
-            if (supportedStates.nextElement().equals(state))
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-    
-    private boolean isPublicRenderParameter(String name)
-    {
-        List<String> publicRenderParameterNames = responseContext.getPortletWindow().getPortletDefinition().getSupportedPublicRenderParameters();
-        return publicRenderParameterNames.isEmpty() ? false : publicRenderParameterNames.contains(name);
-    }
-        
-    private static String[] cloneParameterValues(String[] values)
-    {
-        int count = 0;
-        for (String s : values)
-        {
-            if (s != null)
-            {
-                count++;
-            }
-        }
-        if (count == 0)
-        {
-            return null;
-        }
-        else if (count < values.length)
-        {
-            String[] copy = new String[count];
-            count = 0;
-            for (String s : values)
-            {
-                if (s != null)
-                {
-                    copy[count++] = s;
-                }
-            }
-            return copy;
-        }
-        else
-        {
-            return values.clone();
-        }
-    }
-    
-    public void filterURL()
-    {
-        if (filtering)
-        {
-            throw new IllegalStateException("Calling PortletURL toString or write methods from a PortletURLGenerationListener not allowed");
-        }
-        filtering = true;
-        try
-        {
-            PortletURLListenerService service = responseContext.getContainer().getContainerServices().getPortletURLListenerService();
-            PortletApplicationDefinition portletApp = responseContext.getPortletWindow().getPortletDefinition().getApplication();
-            for (PortletURLGenerationListener listener : service.getPortletURLGenerationListeners(portletApp))
-            {
-                if (PortletURLProvider.TYPE.ACTION == urlProvider.getType())
-                {
-                    listener.filterActionURL(this);
-                }
-                else if (PortletURLProvider.TYPE.RESOURCE == urlProvider.getType())
-                {
-                    listener.filterResourceURL(this);
-                }
-                else
-                {
-                    listener.filterRenderURL(this);
-                }
-            }
-        }
-        finally
-        {
-            filtering = false;
-        }
-    }
-
-    
-    // BaseURL impl ------------------------------------------------------------
-    
-    public void addProperty(String key, String value)
-    {
-        ArgumentUtility.validateNotEmpty("key", key);
-        if (value != null)
-        {
-            Map<String, List<String>> properties = urlProvider.getProperties();
-            List<String> values = properties.get(key);
-            if (values == null)
-            {
-                values = new ArrayList<String>();
-                urlProvider.getProperties().put(key, values);
-            }
-            values.add(value);
-        }
-    }
-
-    public Map<String, String[]> getParameterMap()
-    {
-        Map<String, String[]> parameters = urlProvider.getRenderParameters();
-        if (parameters.isEmpty())
-        {
-            parameters = Collections.emptyMap();
-        }
-        else
-        {
-            parameters = new HashMap<String,String[]>(parameters);
-            for (Map.Entry<String,String[]> entry : parameters.entrySet())
-            {
-                entry.setValue(entry.getValue().clone());
-            }
-        }
-        return parameters;
-    }
-
-    public void setParameter(String name, String value)
-    {
-        ArgumentUtility.validateNotEmpty("name", name);
-        ArgumentUtility.validateNotNull("value", value);
-        String[] values = new String[]{value};
-        urlProvider.getRenderParameters().put(name, values);
-        if (renderURL && isPublicRenderParameter(name))
-        {
-            urlProvider.getPublicRenderParameters().put(name, values);
-        }
-    }
-
-    public void setParameter(String name, String[] values)
-    {
-        ArgumentUtility.validateNotEmpty("name", name);
-        ArgumentUtility.validateNotNull("values", values);
-        values = cloneParameterValues(values);
-        if (values == null )            
-        {
-            throw new IllegalStateException("Illegal Argument: values array is empty or contains only null values");
-        }
-        urlProvider.getRenderParameters().put(name, values);
-        if (renderURL && isPublicRenderParameter(name))
-        {
-            urlProvider.getPublicRenderParameters().put(name, values);
-        }
-    }
-
-    public void setParameters(Map<String, String[]> parameters)
-    {
-        ArgumentUtility.validateNotNull("parameters", parameters);
-        
-        // validate map first
-        boolean emptyValuesArray;
-        for (Map.Entry<? extends Object, ? extends Object> entry : parameters.entrySet())
-        {
-            if (entry.getKey() == null || entry.getValue() == null)
-            {
-                throw new IllegalArgumentException("parameters map contains a null key or value entry");
-            }
-            if (!(entry.getKey() instanceof String))
-            {
-                throw new IllegalArgumentException("parameters map contains a key which is not of type String");
-            }
-            if (!(entry.getValue() instanceof String[]))
-            {
-                throw new IllegalArgumentException("parameters map contains a value which is not of type String[]");
-            }
-            emptyValuesArray = true;
-            for (String s : (String[])entry.getValue())
-            {
-                if (s != null)
-                {
-                    emptyValuesArray = false;
-                    break;
-                }
-            }
-            if (emptyValuesArray)
-            {
-                throw new IllegalStateException("parameters map contains a values array which is empty or contains only null values");
-            }
-        }
-        urlProvider.getRenderParameters().clear();
-        if (renderURL)
-        {
-            for (Iterator<Map.Entry<String,String[]>> iter = urlProvider.getPublicRenderParameters().entrySet().iterator(); iter.hasNext();)
-            {
-                if (iter.next().getValue() != null)
-                {
-                    iter.remove();
-                }
-            }
-        }
-        for (Map.Entry<String,String[]> entry : parameters.entrySet())
-        {
-            String[] values = cloneParameterValues(entry.getValue());
-            urlProvider.getRenderParameters().put(entry.getKey(), values);
-            if (renderURL && isPublicRenderParameter(entry.getKey()))
-            {
-                urlProvider.getPublicRenderParameters().put(entry.getKey(), values);
-            }
-        }
-    }
-
-    public void setProperty(String key, String value)
-    {
-        ArgumentUtility.validateNotEmpty("key", key);
-        Map<String, List<String>> properties = urlProvider.getProperties();
-        if (value == null)
-        {
-            properties.remove(key);
-        }
-        else
-        {
-            List<String> values = properties.get(key);
-            if (values == null)
-            {
-                values = new ArrayList<String>();
-                properties.put(key,values);
-            }
-            else
-            {
-                values.clear();
-            }
-            values.add(value);
-        }
-    }
-
-    public void setSecure(boolean secure) throws PortletSecurityException
-    {
-        urlProvider.setSecure(secure);
-    }
-
-    public void write(Writer out, boolean escapeXML) throws IOException
-    {
-        filterURL();
-        urlProvider.write(out, escapeXML);
-    }
-
-    public void write(Writer out) throws IOException
-    {
-        write(out, true);
-    }
-    
-    public String toString()
-    {
-        filterURL();
-        return urlProvider.toURL();
-    }
-
-    // PortletURL impl ------------------------------------------------------------    
-    
-    public PortletMode getPortletMode() 
-    {
-        return urlProvider.getPortletMode();
-    }
-    
-    public WindowState getWindowState() 
-    {
-        return urlProvider.getWindowState();
-    }
-    
-    public void setPortletMode(PortletMode portletMode) throws PortletModeException 
-    {
-        ArgumentUtility.validateNotNull("portletMode", portletMode);
-        if (isPortletModeAllowed(portletMode))
-        {
-            urlProvider.setPortletMode(portletMode);
-        }
-        else 
-        {
-            throw new PortletModeException("Can't set this PortletMode", portletMode);
-        }
-    }
-
-    public void setWindowState(WindowState windowState) throws WindowStateException
-    {
-        ArgumentUtility.validateNotNull("windowState", windowState);
-        if (isWindowStateAllowed(windowState))
-        {
-            urlProvider.setWindowState(windowState);
-        }
-        else 
-        {
-            throw new WindowStateException("Can't set this WindowState", windowState);
-        }
-    }
-
-    public void removePublicRenderParameter(String name)
-    {
-        ArgumentUtility.validateNotEmpty("name", name);
-        if (isPublicRenderParameter(name))
-        {
-            urlProvider.getPublicRenderParameters().put(name, null);
-            urlProvider.getRenderParameters().remove(name);
-        }
-    }
-
-    // ResourceURL impl ------------------------------------------------------------    
-    
-    public String getCacheability()
-    {
-        return urlProvider.getCacheability();
-    }
-
-    public void setCacheability(String cacheLevel)
-    {
-        ArgumentUtility.validateNotEmpty("cachelevel", cacheLevel);
-        if (FULL.equals(cacheLevel))
-        {
-            // always OK
-        }
-        else if (PORTLET.equals(cacheLevel))
-        {
-            if (FULL.equals(this.cacheLevel))
-            {
-                throw new IllegalStateException("Current request cacheablility is FULL: URLs with cacheability PORTLET not allowed");
-            }
-            
-        }
-        else if (PAGE.equals(cacheLevel))
-        {
-            if (FULL.equals(this.cacheLevel))
-            {
-                throw new IllegalStateException("Current request cacheablility is FULL: URLs with cacheability PORTLET not allowed");
-            }
-            else if (PORTLET.equals(this.cacheLevel))
-            {
-                throw new IllegalStateException("Current request cacheablility is PORTLET: URLs with cacheability PAGE not allowed");
-            }
-        }
-        else
-        {
-            throw new IllegalArgumentException("Unknown cacheLevel: "+cacheLevel);
-        }
-        urlProvider.setCacheability(cacheLevel);
-    }
-
-    public void setResourceID(String resourceID)
-    {
-        urlProvider.setResourceID(resourceID);
-    }        
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pluto.container.impl;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.portlet.PortalContext;
+import javax.portlet.PortletMode;
+import javax.portlet.PortletModeException;
+import javax.portlet.PortletSecurityException;
+import javax.portlet.PortletURL;
+import javax.portlet.PortletURLGenerationListener;
+import javax.portlet.ResourceURL;
+import javax.portlet.WindowState;
+import javax.portlet.WindowStateException;
+import javax.xml.namespace.QName;
+
+import org.apache.pluto.container.PortletMimeResponseContext;
+import org.apache.pluto.container.PortletResponseContext;
+import org.apache.pluto.container.PortletURLListenerService;
+import org.apache.pluto.container.PortletURLProvider;
+import org.apache.pluto.container.om.portlet.CustomPortletMode;
+import org.apache.pluto.container.om.portlet.PortletApplicationDefinition;
+import org.apache.pluto.container.om.portlet.PortletDefinition;
+import org.apache.pluto.container.om.portlet.PublicRenderParameter;
+import org.apache.pluto.container.om.portlet.Supports;
+import org.apache.pluto.container.util.ArgumentUtility;
+
+/**
+ * Refactoring where functionality was pushed into JSR-286 <code>BaseURL</code>.
+ *
+ * @since 2.0
+ */
+public class PortletURLImpl implements PortletURL, ResourceURL {
+    private final Logger LOGGER = LoggerFactory.getLogger(PortletURLImpl.class);
+
+    private PortletResponseContext responseContext;
+    private PortalContext portalContext;
+    private PortletURLProvider urlProvider;
+    private String cacheLevel = ResourceURL.PAGE;
+    private boolean filtering;
+    private boolean renderURL;
+    
+    public PortletURLImpl(PortletResponseContext responseContext, PortletURLProvider urlProvider)
+    {
+        this.responseContext = responseContext;
+        this.portalContext = responseContext.getContainer().getContainerServices().getPortalContext();
+        this.urlProvider = urlProvider;
+        renderURL = PortletURLProvider.TYPE.RENDER == urlProvider.getType();
+    }
+    
+    public PortletURLImpl(PortletMimeResponseContext responseContext, PortletURLProvider.TYPE type)
+    {
+        this(responseContext, responseContext.getPortletURLProvider(type));
+    }
+    
+    public PortletURLImpl(PortletMimeResponseContext responseContext, String cacheLevel)
+    {
+        this(responseContext, PortletURLProvider.TYPE.RESOURCE);
+        if (cacheLevel != null)
+        {
+            this.cacheLevel = cacheLevel;
+        }
+        urlProvider.setCacheability(this.cacheLevel);
+    }
+
+    private boolean isPortletModeAllowed(PortletMode mode)
+    {
+        if(PortletMode.VIEW.equals(mode))
+        {
+            return true;
+        }
+        
+        String modeName = mode.toString();
+
+        PortletDefinition dd = responseContext.getPortletWindow().getPortletDefinition();
+
+        for (Supports sup : dd.getSupports())
+        {
+            for (String m : sup.getPortletModes())
+            {
+                if (m.equalsIgnoreCase(modeName)) 
+                {
+                    // check if a portlet managed mode which is always allowed.
+                    CustomPortletMode cpm = dd.getApplication().getCustomPortletMode(modeName);
+                    if (cpm != null && !cpm.isPortalManaged())
+                    {
+                        return true;
+                    }
+                    Enumeration<PortletMode> supportedModes = portalContext.getSupportedPortletModes();
+                    while (supportedModes.hasMoreElements()) 
+                    {
+                        if (supportedModes.nextElement().equals(mode)) 
+                        {
+                            return true;
+                        }
+                    }
+                    return false;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean isWindowStateAllowed(WindowState state)
+    {
+        Enumeration<WindowState> supportedStates = portalContext.getSupportedWindowStates();
+        while (supportedStates.hasMoreElements()) {
+            if (supportedStates.nextElement().equals(state))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    private boolean isPublicRenderParameter(String name)
+    {
+        List<String> publicRenderParameterNames = responseContext.getPortletWindow().getPortletDefinition().getSupportedPublicRenderParameters();
+        return publicRenderParameterNames.isEmpty() ? false : publicRenderParameterNames.contains(name);
+    }
+    
+   private QName getQNameForPRPName(String name) {
+      QName qn = null;
+      PortletDefinition pd = responseContext.getPortletWindow().getPortletDefinition();
+      PortletApplicationDefinition pad = pd.getApplication();
+      List<? extends PublicRenderParameter> prps = pad.getPublicRenderParameters();
+      for (PublicRenderParameter prp : prps) {
+         if (name.equals(prp.getIdentifier())) {
+            qn = prp.getQName();
+            if (qn == null) {
+               String ns = pad.getDefaultNamespace();
+               String lp = prp.getName();
+               if (lp != null) {
+                  qn = new QName(ns, lp);
+               } else {
+                  LOGGER.error("Error in descriptor for " + responseContext.getPortletWindow()
+                        + " - neither QName nor Name is defined");
+               }
+            }
+         }
+      }
+      return qn;
+   }
+        
+    private static String[] cloneParameterValues(String[] values)
+    {
+        int count = 0;
+        for (String s : values)
+        {
+            if (s != null)
+            {
+                count++;
+            }
+        }
+        if (count == 0)
+        {
+            return null;
+        }
+        else if (count < values.length)
+        {
+            String[] copy = new String[count];
+            count = 0;
+            for (String s : values)
+            {
+                if (s != null)
+                {
+                    copy[count++] = s;
+                }
+            }
+            return copy;
+        }
+        else
+        {
+            return values.clone();
+        }
+    }
+    
+    public void filterURL()
+    {
+        if (filtering)
+        {
+            throw new IllegalStateException("Calling PortletURL toString or write methods from a PortletURLGenerationListener not allowed");
+        }
+        filtering = true;
+        try
+        {
+            PortletURLListenerService service = responseContext.getContainer().getContainerServices().getPortletURLListenerService();
+            PortletApplicationDefinition portletApp = responseContext.getPortletWindow().getPortletDefinition().getApplication();
+            for (PortletURLGenerationListener listener : service.getPortletURLGenerationListeners(portletApp))
+            {
+                if (PortletURLProvider.TYPE.ACTION == urlProvider.getType())
+                {
+                    listener.filterActionURL(this);
+                }
+                else if (PortletURLProvider.TYPE.RESOURCE == urlProvider.getType())
+                {
+                    listener.filterResourceURL(this);
+                }
+                else
+                {
+                    listener.filterRenderURL(this);
+                }
+            }
+        }
+        finally
+        {
+            filtering = false;
+        }
+    }
+
+    
+    // BaseURL impl ------------------------------------------------------------
+    
+    public void addProperty(String key, String value)
+    {
+        ArgumentUtility.validateNotEmpty("key", key);
+        if (value != null)
+        {
+            Map<String, List<String>> properties = urlProvider.getProperties();
+            List<String> values = properties.get(key);
+            if (values == null)
+            {
+                values = new ArrayList<String>();
+                urlProvider.getProperties().put(key, values);
+            }
+            values.add(value);
+        }
+    }
+
+    public Map<String, String[]> getParameterMap()
+    {
+        Map<String, String[]> parameters = urlProvider.getRenderParameters();
+        if (parameters.isEmpty())
+        {
+            parameters = Collections.emptyMap();
+        }
+        else
+        {
+            parameters = new HashMap<String,String[]>(parameters);
+            for (Map.Entry<String,String[]> entry : parameters.entrySet())
+            {
+                entry.setValue(entry.getValue().clone());
+            }
+        }
+        return parameters;
+    }
+
+    public void setParameter(String name, String value)
+    {
+        ArgumentUtility.validateNotEmpty("name", name);
+        ArgumentUtility.validateNotNull("value", value);
+        String[] values = new String[]{value};
+        urlProvider.getRenderParameters().put(name, values);
+        if (renderURL && isPublicRenderParameter(name))
+        {
+            urlProvider.getPublicRenderParameters().put(name, values);
+            
+            QName qn = getQNameForPRPName(name);
+            urlProvider.addPublicRenderParameter(qn, name, values);
+        }
+    }
+
+    public void setParameter(String name, String[] values)
+    {
+        ArgumentUtility.validateNotEmpty("name", name);
+        ArgumentUtility.validateNotNull("values", values);
+        values = cloneParameterValues(values);
+        if (values == null )            
+        {
+            throw new IllegalStateException("Illegal Argument: values array is empty or contains only null values");
+        }
+        urlProvider.getRenderParameters().put(name, values);
+        if (renderURL && isPublicRenderParameter(name))
+        {
+            urlProvider.getPublicRenderParameters().put(name, values);
+            
+            QName qn = getQNameForPRPName(name);
+            urlProvider.addPublicRenderParameter(qn, name, values);
+        }
+    }
+
+    public void setParameters(Map<String, String[]> parameters)
+    {
+        ArgumentUtility.validateNotNull("parameters", parameters);
+        
+        // validate map first
+        boolean emptyValuesArray;
+        for (Map.Entry<? extends Object, ? extends Object> entry : parameters.entrySet())
+        {
+            if (entry.getKey() == null || entry.getValue() == null)
+            {
+                throw new IllegalArgumentException("parameters map contains a null key or value entry");
+            }
+            if (!(entry.getKey() instanceof String))
+            {
+                throw new IllegalArgumentException("parameters map contains a key which is not of type String");
+            }
+            if (!(entry.getValue() instanceof String[]))
+            {
+                throw new IllegalArgumentException("parameters map contains a value which is not of type String[]");
+            }
+            emptyValuesArray = true;
+            for (String s : (String[])entry.getValue())
+            {
+                if (s != null)
+                {
+                    emptyValuesArray = false;
+                    break;
+                }
+            }
+            if (emptyValuesArray)
+            {
+                throw new IllegalStateException("parameters map contains a values array which is empty or contains only null values");
+            }
+        }
+        urlProvider.getRenderParameters().clear();
+        if (renderURL)
+        {
+            for (Iterator<Map.Entry<String,String[]>> iter = urlProvider.getPublicRenderParameters().entrySet().iterator(); iter.hasNext();)
+            {
+                if (iter.next().getValue() != null)
+                {
+                    iter.remove();
+                }
+            }
+        }
+        for (Map.Entry<String,String[]> entry : parameters.entrySet())
+        {
+            String[] values = cloneParameterValues(entry.getValue());
+            String key = entry.getKey();
+            urlProvider.getRenderParameters().put(key, values);
+            if (renderURL && isPublicRenderParameter(key))
+            {
+                urlProvider.getPublicRenderParameters().put(key, values);
+                
+                QName qn = getQNameForPRPName(key);
+                urlProvider.addPublicRenderParameter(qn, key, values);
+            }
+        }
+    }
+
+    public void setProperty(String key, String value)
+    {
+        ArgumentUtility.validateNotEmpty("key", key);
+        Map<String, List<String>> properties = urlProvider.getProperties();
+        if (value == null)
+        {
+            properties.remove(key);
+        }
+        else
+        {
+            List<String> values = properties.get(key);
+            if (values == null)
+            {
+                values = new ArrayList<String>();
+                properties.put(key,values);
+            }
+            else
+            {
+                values.clear();
+            }
+            values.add(value);
+        }
+    }
+
+    public void setSecure(boolean secure) throws PortletSecurityException
+    {
+        urlProvider.setSecure(secure);
+    }
+
+    public void write(Writer out, boolean escapeXML) throws IOException
+    {
+        filterURL();
+        urlProvider.write(out, escapeXML);
+    }
+
+    public void write(Writer out) throws IOException
+    {
+        write(out, true);
+    }
+    
+    public String toString()
+    {
+        filterURL();
+        return urlProvider.toURL();
+    }
+
+    // PortletURL impl ------------------------------------------------------------    
+    
+    public PortletMode getPortletMode() 
+    {
+        return urlProvider.getPortletMode();
+    }
+    
+    public WindowState getWindowState() 
+    {
+        return urlProvider.getWindowState();
+    }
+    
+    public void setPortletMode(PortletMode portletMode) throws PortletModeException 
+    {
+        ArgumentUtility.validateNotNull("portletMode", portletMode);
+        if (isPortletModeAllowed(portletMode))
+        {
+            urlProvider.setPortletMode(portletMode);
+        }
+        else 
+        {
+            throw new PortletModeException("Can't set this PortletMode", portletMode);
+        }
+    }
+
+    public void setWindowState(WindowState windowState) throws WindowStateException
+    {
+        ArgumentUtility.validateNotNull("windowState", windowState);
+        if (isWindowStateAllowed(windowState))
+        {
+            urlProvider.setWindowState(windowState);
+        }
+        else 
+        {
+            throw new WindowStateException("Can't set this WindowState", windowState);
+        }
+    }
+
+    public void removePublicRenderParameter(String name)
+    {
+        ArgumentUtility.validateNotEmpty("name", name);
+        if (isPublicRenderParameter(name))
+        {
+            urlProvider.getPublicRenderParameters().put(name, null);
+            urlProvider.getRenderParameters().remove(name);
+            
+            QName qn = getQNameForPRPName(name);
+            urlProvider.removePublicRenderParameter(qn);
+        }
+    }
+
+    // ResourceURL impl ------------------------------------------------------------    
+    
+    public String getCacheability()
+    {
+        return urlProvider.getCacheability();
+    }
+
+    public void setCacheability(String cacheLevel)
+    {
+        ArgumentUtility.validateNotEmpty("cachelevel", cacheLevel);
+        if (FULL.equals(cacheLevel))
+        {
+            // always OK
+        }
+        else if (PORTLET.equals(cacheLevel))
+        {
+            if (FULL.equals(this.cacheLevel))
+            {
+                throw new IllegalStateException("Current request cacheablility is FULL: URLs with cacheability PORTLET not allowed");
+            }
+            
+        }
+        else if (PAGE.equals(cacheLevel))
+        {
+            if (FULL.equals(this.cacheLevel))
+            {
+                throw new IllegalStateException("Current request cacheablility is FULL: URLs with cacheability PORTLET not allowed");
+            }
+            else if (PORTLET.equals(this.cacheLevel))
+            {
+                throw new IllegalStateException("Current request cacheablility is PORTLET: URLs with cacheability PAGE not allowed");
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException("Unknown cacheLevel: "+cacheLevel);
+        }
+        urlProvider.setCacheability(cacheLevel);
+    }
+
+    public void setResourceID(String resourceID)
+    {
+        urlProvider.setResourceID(resourceID);
+    }        
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c2504532/pluto-container/src/main/java/org/apache/pluto/container/impl/StateAwareResponseImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/StateAwareResponseImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/StateAwareResponseImpl.java
index 471916b..d8be6a2 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/StateAwareResponseImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/StateAwareResponseImpl.java
@@ -1,268 +1,312 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pluto.container.impl;
-
-import java.io.Serializable;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.portlet.Event;
-import javax.portlet.PortletMode;
-import javax.portlet.PortletModeException;
-import javax.portlet.StateAwareResponse;
-import javax.portlet.WindowState;
-import javax.portlet.WindowStateException;
-import javax.xml.namespace.QName;
-
-import org.apache.pluto.container.PortletStateAwareResponseContext;
-import org.apache.pluto.container.PortletWindow;
-import org.apache.pluto.container.util.ArgumentUtility;
-
-/**
- * Implementation of JSR-286 <code>StateAwareResponse</code>.
- *
- * @since 2.0
- */
-public abstract class StateAwareResponseImpl extends PortletResponseImpl implements StateAwareResponse
-{
-    private PortletStateAwareResponseContext responseContext;
-    
-	public StateAwareResponseImpl(PortletStateAwareResponseContext responseContext)
-	{
-		super(responseContext);
-		this.responseContext = responseContext;
-	}
-	
-    private boolean isPublicRenderParameter(String name)
-    {
-        List<String> publicRenderParameterNames = responseContext.getPortletWindow().getPortletDefinition().getSupportedPublicRenderParameters();
-        return publicRenderParameterNames.isEmpty() ? false : publicRenderParameterNames.contains(name);
-    }
-        
-	private static String[] cloneParameterValues(String[] values)
-	{
-	    int count = 0;
-	    for (String s : values)
-	    {
-	        if (s != null)
-	        {
-	            count++;
-	        }
-	    }
-	    if (count == 0)
-	    {
-	        return null;
-	    }
-	    else if (count < values.length)
-	    {
-	        String[] copy = new String[count];
-	        count = 0;
-	        for (String s : values)
-	        {
-	            if (s != null)
-	            {
-	                copy[count++] = s;
-	            }
-	        }
-	        return copy;
-	    }
-	    else
-	    {
-	        return values.clone();
-	    }
-	}
-	
-	protected abstract void checkSetStateChanged();
-	
-    protected boolean isWindowStateAllowed(WindowState state)
-    {
-        Enumeration<WindowState> supportedStates = getPortalContext().getSupportedWindowStates();
-        while (supportedStates.hasMoreElements()) {
-            if (supportedStates.nextElement().equals(state))
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-    
-    public PortletMode getPortletMode()
-    {
-        return responseContext.getPortletMode();
-    }
-
-    public Map<String, String[]> getRenderParameterMap()
-    {
-        Map<String, String[]> parameters = new HashMap<String, String[]>(responseContext.getRenderParameters());
-        for (Map.Entry<String,String[]> entry : parameters.entrySet())
-        {
-            entry.setValue(entry.getValue().clone());
-        }
-        return parameters;
-    }
-    
-    public WindowState getWindowState()
-    {
-        return responseContext.getWindowState();
-    }
-    
-    public void removePublicRenderParameter(String name)
-    {
-        ArgumentUtility.validateNotEmpty("name", name);
-        checkSetStateChanged();
-        if (isPublicRenderParameter(name))
-        {
-            responseContext.getPublicRenderParameters().put(name, null);
-            responseContext.getRenderParameters().remove(name);
-        }
-    }
-
-	public void setEvent(QName qname, Serializable value)
-	{
-        ArgumentUtility.validateNotNull("qname", qname);
-        Event event = responseContext.getEventProvider().createEvent(qname, value);
-        if (event != null)
-        {
-            responseContext.getEvents().add(event);
-        }
-	}
-
-	public void setEvent(String name, Serializable value)
-	{
-	    PortletWindow window = getPortletWindow();
-        String defaultNamespace;
-        defaultNamespace = window.getPortletDefinition().getApplication().getDefaultNamespace();
-        QName qname = new QName(defaultNamespace, name);
-        setEvent(qname, value);
-	}
-
-    public void setPortletMode(PortletMode portletMode) throws PortletModeException 
-    {
-        ArgumentUtility.validateNotNull("portletMode", portletMode);
-        if (isPortletModeAllowed(portletMode))
-        {
-            checkSetStateChanged();
-            responseContext.setPortletMode(portletMode);
-        }
-        else 
-        {
-            throw new PortletModeException("Can't set this PortletMode", portletMode);
-        }
-    }
-
-    public void setWindowState(WindowState windowState) throws WindowStateException
-    {
-        ArgumentUtility.validateNotNull("windowState", windowState);
-        if (isWindowStateAllowed(windowState))
-        {
-            checkSetStateChanged();
-            responseContext.setWindowState(windowState);
-        }
-        else 
-        {
-            throw new WindowStateException("Can't set this WindowState", windowState);
-        }
-    }
-	    
-    public void setRenderParameters(java.util.Map<String, String[]> parameters)
-    {
-        ArgumentUtility.validateNotNull("parameters", parameters);
-        
-        // validate map first
-        boolean emptyValuesArray;
-        for (Map.Entry<? extends Object, ? extends Object> entry : parameters.entrySet())
-        {
-            if (entry.getKey() == null || entry.getValue() == null)
-            {
-                throw new IllegalArgumentException("parameters map contains a null key or value entry");
-            }
-            if (!(entry.getKey() instanceof String))
-            {
-                throw new IllegalArgumentException("parameters map contains a key which is not of type String");
-            }
-            if (!(entry.getValue() instanceof String[]))
-            {
-                throw new IllegalArgumentException("parameters map contains a value which is not of type String[]");
-            }
-            emptyValuesArray = true;
-            for (String s : (String[])entry.getValue())
-            {
-                if (s != null)
-                {
-                    emptyValuesArray = false;
-                    break;
-                }
-            }
-            if (emptyValuesArray)
-            {
-                throw new IllegalStateException("parameters map contains a values array which is empty or contains only null values");
-            }
-        }
-        checkSetStateChanged();
-        
-        responseContext.getRenderParameters().clear();
-        for (Iterator<Map.Entry<String,String[]>> iter = responseContext.getPublicRenderParameters().entrySet().iterator(); iter.hasNext();)
-        {
-            if (iter.next().getValue() != null)
-            {
-                iter.remove();
-            }
-        }
-        for (Map.Entry<String,String[]> entry : parameters.entrySet())
-        {
-            String[] values = cloneParameterValues(entry.getValue());
-            responseContext.getRenderParameters().put(entry.getKey(), values);
-            if (isPublicRenderParameter(entry.getKey()))
-            {
-                responseContext.getPublicRenderParameters().put(entry.getKey(), values);
-            }
-        }
-    }
-    
-    public void setRenderParameter(String key, String value)
-    {
-        ArgumentUtility.validateNotEmpty("key", key);
-        ArgumentUtility.validateNotNull("value", value);
-        checkSetStateChanged();
-        String[] values = new String[]{value};
-        responseContext.getRenderParameters().put(key, values);
-        if (isPublicRenderParameter(key))
-        {
-            responseContext.getPublicRenderParameters().put(key, values);
-        }
-    }
-    
-    public void setRenderParameter(String key, String[] values)
-    {
-        ArgumentUtility.validateNotEmpty("key", key);
-        ArgumentUtility.validateNotNull("values", values);
-        values = cloneParameterValues(values);
-        if (values == null )            
-        {
-            throw new IllegalStateException("Illegal Argument: values array is empty or contains only null values");
-        }
-        checkSetStateChanged();
-        responseContext.getRenderParameters().put(key, values);
-        if (isPublicRenderParameter(key))
-        {
-            responseContext.getPublicRenderParameters().put(key, values);
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pluto.container.impl;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.portlet.Event;
+import javax.portlet.PortletMode;
+import javax.portlet.PortletModeException;
+import javax.portlet.StateAwareResponse;
+import javax.portlet.WindowState;
+import javax.portlet.WindowStateException;
+import javax.xml.namespace.QName;
+
+import org.apache.pluto.container.PortletStateAwareResponseContext;
+import org.apache.pluto.container.PortletWindow;
+import org.apache.pluto.container.om.portlet.PortletApplicationDefinition;
+import org.apache.pluto.container.om.portlet.PortletDefinition;
+import org.apache.pluto.container.om.portlet.PublicRenderParameter;
+import org.apache.pluto.container.util.ArgumentUtility;
+
+/**
+ * Implementation of JSR-286 <code>StateAwareResponse</code>.
+ *
+ * @since 2.0
+ */
+public abstract class StateAwareResponseImpl extends PortletResponseImpl implements StateAwareResponse
+{
+   private final Logger LOGGER = LoggerFactory.getLogger(StateAwareResponseImpl.class);
+   
+    private PortletStateAwareResponseContext responseContext;
+    
+	public StateAwareResponseImpl(PortletStateAwareResponseContext responseContext)
+	{
+		super(responseContext);
+		this.responseContext = responseContext;
+	}
+	
+    private boolean isPublicRenderParameter(String name)
+    {
+        List<String> publicRenderParameterNames = responseContext.getPortletWindow().getPortletDefinition().getSupportedPublicRenderParameters();
+        return publicRenderParameterNames.isEmpty() ? false : publicRenderParameterNames.contains(name);
+    }
+    
+   private QName getQNameForPRPName(String name) {
+      QName qn = null;
+      PortletDefinition pd = responseContext.getPortletWindow().getPortletDefinition();
+      PortletApplicationDefinition pad = pd.getApplication();
+      List<? extends PublicRenderParameter> prps = pad.getPublicRenderParameters();
+      for (PublicRenderParameter prp : prps) {
+         if (name.equals(prp.getIdentifier())) {
+            qn = prp.getQName();
+            if (qn == null) {
+               String ns = pad.getDefaultNamespace();
+               String lp = prp.getName();
+               if (lp != null) {
+                  qn = new QName(ns, lp);
+               } else {
+                  LOGGER.error("Error in descriptor for " + responseContext.getPortletWindow()
+                        + " - neither QName nor Name is defined");
+               }
+            }
+         }
+      }
+      return qn;
+   }
+        
+	private static String[] cloneParameterValues(String[] values)
+	{
+	    int count = 0;
+	    for (String s : values)
+	    {
+	        if (s != null)
+	        {
+	            count++;
+	        }
+	    }
+	    if (count == 0)
+	    {
+	        return null;
+	    }
+	    else if (count < values.length)
+	    {
+	        String[] copy = new String[count];
+	        count = 0;
+	        for (String s : values)
+	        {
+	            if (s != null)
+	            {
+	                copy[count++] = s;
+	            }
+	        }
+	        return copy;
+	    }
+	    else
+	    {
+	        return values.clone();
+	    }
+	}
+	
+	protected abstract void checkSetStateChanged();
+	
+    protected boolean isWindowStateAllowed(WindowState state)
+    {
+        Enumeration<WindowState> supportedStates = getPortalContext().getSupportedWindowStates();
+        while (supportedStates.hasMoreElements()) {
+            if (supportedStates.nextElement().equals(state))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    public PortletMode getPortletMode()
+    {
+        return responseContext.getPortletMode();
+    }
+
+    public Map<String, String[]> getRenderParameterMap()
+    {
+        Map<String, String[]> parameters = new HashMap<String, String[]>(responseContext.getRenderParameters());
+        for (Map.Entry<String,String[]> entry : parameters.entrySet())
+        {
+            entry.setValue(entry.getValue().clone());
+        }
+        return parameters;
+    }
+    
+    public WindowState getWindowState()
+    {
+        return responseContext.getWindowState();
+    }
+    
+    public void removePublicRenderParameter(String name)
+    {
+        ArgumentUtility.validateNotEmpty("name", name);
+        checkSetStateChanged();
+        if (isPublicRenderParameter(name))
+        {
+            responseContext.getPublicRenderParameters().put(name, null);
+            responseContext.getRenderParameters().remove(name);
+            
+            QName qn = getQNameForPRPName(name);
+            responseContext.removePublicRenderParameter(qn);
+        }
+    }
+
+	public void setEvent(QName qname, Serializable value)
+	{
+        ArgumentUtility.validateNotNull("qname", qname);
+        Event event = responseContext.getEventProvider().createEvent(qname, value);
+        if (event != null)
+        {
+            responseContext.getEvents().add(event);
+        }
+	}
+
+	public void setEvent(String name, Serializable value)
+	{
+	    PortletWindow window = getPortletWindow();
+        String defaultNamespace;
+        defaultNamespace = window.getPortletDefinition().getApplication().getDefaultNamespace();
+        QName qname = new QName(defaultNamespace, name);
+        setEvent(qname, value);
+	}
+
+    public void setPortletMode(PortletMode portletMode) throws PortletModeException 
+    {
+        ArgumentUtility.validateNotNull("portletMode", portletMode);
+        if (isPortletModeAllowed(portletMode))
+        {
+            checkSetStateChanged();
+            responseContext.setPortletMode(portletMode);
+        }
+        else 
+        {
+            throw new PortletModeException("Can't set this PortletMode", portletMode);
+        }
+    }
+
+    public void setWindowState(WindowState windowState) throws WindowStateException
+    {
+        ArgumentUtility.validateNotNull("windowState", windowState);
+        if (isWindowStateAllowed(windowState))
+        {
+            checkSetStateChanged();
+            responseContext.setWindowState(windowState);
+        }
+        else 
+        {
+            throw new WindowStateException("Can't set this WindowState", windowState);
+        }
+    }
+	    
+    public void setRenderParameters(java.util.Map<String, String[]> parameters)
+    {
+        ArgumentUtility.validateNotNull("parameters", parameters);
+        
+        // validate map first
+        boolean emptyValuesArray;
+        for (Map.Entry<? extends Object, ? extends Object> entry : parameters.entrySet())
+        {
+            if (entry.getKey() == null || entry.getValue() == null)
+            {
+                throw new IllegalArgumentException("parameters map contains a null key or value entry");
+            }
+            if (!(entry.getKey() instanceof String))
+            {
+                throw new IllegalArgumentException("parameters map contains a key which is not of type String");
+            }
+            if (!(entry.getValue() instanceof String[]))
+            {
+                throw new IllegalArgumentException("parameters map contains a value which is not of type String[]");
+            }
+            emptyValuesArray = true;
+            for (String s : (String[])entry.getValue())
+            {
+                if (s != null)
+                {
+                    emptyValuesArray = false;
+                    break;
+                }
+            }
+            if (emptyValuesArray)
+            {
+                throw new IllegalStateException("parameters map contains a values array which is empty or contains only null values");
+            }
+        }
+        checkSetStateChanged();
+        
+        responseContext.getRenderParameters().clear();
+        for (Iterator<Map.Entry<String,String[]>> iter = responseContext.getPublicRenderParameters().entrySet().iterator(); iter.hasNext();)
+        {
+            if (iter.next().getValue() != null)
+            {
+                iter.remove();
+            }
+        }
+        for (Map.Entry<String,String[]> entry : parameters.entrySet())
+        {
+            String[] values = cloneParameterValues(entry.getValue());
+            String key = entry.getKey();
+            responseContext.getRenderParameters().put(key, values);
+            if (isPublicRenderParameter(key))
+            {
+                responseContext.getPublicRenderParameters().put(key, values);
+
+                QName qn = getQNameForPRPName(key);
+                responseContext.addPublicRenderParameter(qn, key, values);
+            }
+        }
+    }
+    
+    public void setRenderParameter(String key, String value)
+    {
+        ArgumentUtility.validateNotEmpty("key", key);
+        ArgumentUtility.validateNotNull("value", value);
+        checkSetStateChanged();
+        String[] values = new String[]{value};
+        responseContext.getRenderParameters().put(key, values);
+        if (isPublicRenderParameter(key))
+        {
+            responseContext.getPublicRenderParameters().put(key, values);
+            
+            QName qn = getQNameForPRPName(key);
+            responseContext.addPublicRenderParameter(qn, key, values);
+        }
+    }
+    
+    public void setRenderParameter(String key, String[] values)
+    {
+        ArgumentUtility.validateNotEmpty("key", key);
+        ArgumentUtility.validateNotNull("values", values);
+        values = cloneParameterValues(values);
+        if (values == null )            
+        {
+            throw new IllegalStateException("Illegal Argument: values array is empty or contains only null values");
+        }
+        checkSetStateChanged();
+        responseContext.getRenderParameters().put(key, values);
+        if (isPublicRenderParameter(key))
+        {
+            responseContext.getPublicRenderParameters().put(key, values);
+
+            QName qn = getQNameForPRPName(key);
+            responseContext.addPublicRenderParameter(qn, key, values);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/c2504532/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletStateAwareResponseContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletStateAwareResponseContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletStateAwareResponseContextImpl.java
index 1be78a3..51fdc59 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletStateAwareResponseContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletStateAwareResponseContextImpl.java
@@ -1,134 +1,158 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pluto.driver.services.container;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import javax.portlet.Event;
-import javax.portlet.PortletMode;
-import javax.portlet.WindowState;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.pluto.container.EventProvider;
-import org.apache.pluto.container.PortletContainer;
-import org.apache.pluto.container.PortletStateAwareResponseContext;
-import org.apache.pluto.container.PortletURLProvider;
-import org.apache.pluto.container.PortletWindow;
-import org.apache.pluto.container.driver.PlutoServices;
-import org.apache.pluto.container.impl.PortletURLImpl;
-import org.apache.pluto.driver.core.PortalRequestContext;
-import org.apache.pluto.driver.url.PortalURL;
-
-/**
- * @version $Id$
- *
- */
-public abstract class PortletStateAwareResponseContextImpl extends PortletResponseContextImpl implements
-                PortletStateAwareResponseContext
-{
-    private List<Event> events;
-    private PortletURLProviderImpl portletURLProvider;
-    
-    public PortletStateAwareResponseContextImpl(PortletContainer container, HttpServletRequest containerRequest,
-                                                HttpServletResponse containerResponse, PortletWindow window)
-    {
-        super(container, containerRequest, containerResponse, window);
-        this.portletURLProvider = new PortletURLProviderImpl(getPortalURL(), PortletURLProvider.TYPE.RENDER, window);
-    }
-    
-    protected PortletURLProvider getPorletURLProvider()
-    {
-        return portletURLProvider;
-    }
-    
-    @Override
-    public void close()
-    {
-        if (!isClosed())
-        {
-            super.close();
-            new PortletURLImpl(this, portletURLProvider).filterURL();
-            PortalURL url = portletURLProvider.apply();
-            PortalRequestContext.getContext(getServletRequest()).mergePortalURL(url, getPortletWindow().getId().getStringId());
-        }
-    }
-    
-    @Override
-    public void release()
-    {
-        events = null;
-        portletURLProvider = null;
-        super.release();
-    }
-    
-    public List<Event> getEvents()
-    {
-        if (isReleased())
-        {
-            return null;
-        }
-        if (events == null)
-        {
-            events = new ArrayList<Event>();
-        }
-        return events;
-    }
-
-    public PortletMode getPortletMode()
-    {
-        return isClosed() ? null : portletURLProvider.getPortletMode();
-    }
-
-    public Map<String, String[]> getPublicRenderParameters()
-    {
-        return isClosed() ? null : portletURLProvider.getPublicRenderParameters();
-    }
-
-    public Map<String, String[]> getRenderParameters()
-    {
-        return isClosed() ? null : portletURLProvider.getRenderParameters();
-    }
-
-    public WindowState getWindowState()
-    {
-        return isClosed() ? null : portletURLProvider.getWindowState();
-    }
-
-    public void setPortletMode(PortletMode portletMode)
-    {
-        if (!isClosed())
-        {
-            portletURLProvider.setPortletMode(portletMode);
-        }
-    }
-
-    public void setWindowState(WindowState windowState)
-    {
-        if (!isClosed())
-        {
-            portletURLProvider.setWindowState(windowState);
-        }
-    }
-
-    public EventProvider getEventProvider()
-    {
-        return isClosed() ? null : new EventProviderImpl(getPortletWindow(), PlutoServices.getServices().getPortletRegistryService());
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pluto.driver.services.container;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.portlet.Event;
+import javax.portlet.PortletMode;
+import javax.portlet.WindowState;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.namespace.QName;
+
+import org.apache.pluto.container.EventProvider;
+import org.apache.pluto.container.PortletContainer;
+import org.apache.pluto.container.PortletStateAwareResponseContext;
+import org.apache.pluto.container.PortletURLProvider;
+import org.apache.pluto.container.PortletWindow;
+import org.apache.pluto.container.driver.PlutoServices;
+import org.apache.pluto.container.impl.PortletURLImpl;
+import org.apache.pluto.driver.core.PortalRequestContext;
+import org.apache.pluto.driver.url.PortalURL;
+
+/**
+ * @version $Id$
+ *
+ */
+public abstract class PortletStateAwareResponseContextImpl extends PortletResponseContextImpl implements
+                PortletStateAwareResponseContext
+{
+    private final Logger LOGGER = LoggerFactory.getLogger(PortletStateAwareResponseContextImpl.class);
+
+    private List<Event> events;
+    private PortletURLProviderImpl portletURLProvider;
+    
+    public PortletStateAwareResponseContextImpl(PortletContainer container, HttpServletRequest containerRequest,
+                                                HttpServletResponse containerResponse, PortletWindow window)
+    {
+        super(container, containerRequest, containerResponse, window);
+        this.portletURLProvider = new PortletURLProviderImpl(getPortalURL(), PortletURLProvider.TYPE.RENDER, window);
+    }
+    
+    protected PortletURLProvider getPorletURLProvider()
+    {
+        return portletURLProvider;
+    }
+    
+    @Override
+    public void close()
+    {
+        if (!isClosed())
+        {
+            super.close();
+            new PortletURLImpl(this, portletURLProvider).filterURL();
+            PortalURL url = portletURLProvider.apply();
+            PortalRequestContext.getContext(getServletRequest()).mergePortalURL(url, getPortletWindow().getId().getStringId());
+        }
+    }
+    
+    @Override
+    public void release()
+    {
+        events = null;
+        portletURLProvider = null;
+        super.release();
+    }
+    
+    public List<Event> getEvents()
+    {
+        if (isReleased())
+        {
+            return null;
+        }
+        if (events == null)
+        {
+            events = new ArrayList<Event>();
+        }
+        return events;
+    }
+
+    public PortletMode getPortletMode()
+    {
+        return isClosed() ? null : portletURLProvider.getPortletMode();
+    }
+
+    public Map<String, String[]> getPublicRenderParameters()
+    {
+        return isClosed() ? null : portletURLProvider.getPublicRenderParameters();
+    }
+
+    public Map<String, String[]> getRenderParameters()
+    {
+        return isClosed() ? null : portletURLProvider.getRenderParameters();
+    }
+
+    public WindowState getWindowState()
+    {
+        return isClosed() ? null : portletURLProvider.getWindowState();
+    }
+
+    public void setPortletMode(PortletMode portletMode)
+    {
+        if (!isClosed())
+        {
+            portletURLProvider.setPortletMode(portletMode);
+        }
+    }
+
+    public void setWindowState(WindowState windowState)
+    {
+        if (!isClosed())
+        {
+            portletURLProvider.setWindowState(windowState);
+        }
+    }
+
+    public EventProvider getEventProvider()
+    {
+        return isClosed() ? null : new EventProviderImpl(getPortletWindow(), PlutoServices.getServices().getPortletRegistryService());
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.pluto.container.PortletStateAwareResponseContext#addPublicRenderParameter(javax.xml.namespace.QName, java.lang.String, java.lang.String[])
+     */
+    public void addPublicRenderParameter(QName qn, String identifier, String[] values) {
+       LOGGER.debug("Add PRP. QName = " + qn.toString() + ", ID = " + identifier
+             + ", values = " + Arrays.toString(values));
+       portletURLProvider.addPublicRenderParameter(qn, identifier, values);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.pluto.container.PortletStateAwareResponseContext#removePublicRenderParameter(javax.xml.namespace.QName)
+     */
+    public void removePublicRenderParameter(QName qn) {
+       LOGGER.debug("Remove PRP. QName = " + qn.toString());
+       portletURLProvider.removePublicRenderParameter(qn);
+    }
+}