You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by ni...@apache.org on 2008/01/21 11:09:07 UTC

svn commit: r613823 [3/4] - in /struts/sandbox/trunk/struts2-portlet2-plugin: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/struts2/ src/main/java/org/apache/struts2/components/ src/main/java/org...

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletRequest.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletRequest.java?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletRequest.java (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletRequest.java Mon Jan 21 02:09:00 2008
@@ -0,0 +1,584 @@
+/*
+ * $Id: PortletServletRequest.java 590812 2007-10-31 20:32:54Z apetrelli $
+ *
+ * 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.struts2.portlet.servlet;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.EventRequest;
+import javax.portlet.PortletContext;
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.PortletSession;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.struts2.portlet.PortletActionConstants;
+
+/**
+ * Wrapper object exposing a {@link PortletRequest} as a {@link HttpServletRequest} instance.
+ * Clients accessing this request object will in fact operate on the
+ * {@link PortletRequest} object wrapped by this request object.
+ */
+public class PortletServletRequest implements HttpServletRequest, PortletActionConstants {
+
+	private PortletRequest portletRequest;
+	private PortletContext portletContext;
+	private Map<String, String[]> extraParams;
+	
+	public PortletServletRequest(PortletRequest portletRequest, PortletContext portletContext) {
+		this(portletRequest, portletContext, Collections.EMPTY_MAP);
+	}
+	
+	public PortletServletRequest(PortletRequest portletRequest, PortletContext portletContext, Map<String, String[]> extraParams) {
+		this.portletContext = portletContext;
+		this.portletRequest = portletRequest;
+		this.extraParams = extraParams;
+	}
+	
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#getAuthType()
+	 */
+	public String getAuthType() {
+		return portletRequest.getAuthType();
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#getContextPath()
+	 */
+	public String getContextPath() {
+		return portletRequest.getContextPath();
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public Cookie[] getCookies() {
+		if(portletRequest instanceof HttpServletRequest) {
+			return ((HttpServletRequest)portletRequest).getCookies();
+		}
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public long getDateHeader(String name) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Gets a property from the {@link PortletRequest}. Note that a {@link PortletRequest} is not 
+	 * guaranteed to map properties to headers.
+	 * @see PortletRequest#getProperty(String)
+	 * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String)
+	 */
+	public String getHeader(String name) {
+		return portletRequest.getProperty(name);
+	}
+
+	/**
+	 * Gets the property names from the {@link PortletRequest}. Note that a {@link PortletRequest} is not 
+	 * guaranteed to map properties to headers.
+	 * @see PortletRequest#getPropertyNames()
+	 * @see javax.servlet.http.HttpServletRequest#getHeaderNames()
+	 */
+	public Enumeration getHeaderNames() {
+		return portletRequest.getPropertyNames();
+	}
+
+	/**
+	 * Gets the values for the specified property from the {@link PortletRequest}. Note that a 
+	 * {@link PortletRequest} is not guaranteed to map properties to headers.
+	 * @see PortletRequest#getProperties(String)
+	 * @see HttpServletRequest#getHeaders(String)
+	 */
+	public Enumeration getHeaders(String name) {
+		return portletRequest.getProperties(name);
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public int getIntHeader(String name) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#getMethod()
+	 */
+	public String getMethod() {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#getPathInfo()
+	 */
+	public String getPathInfo() {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#getPathTranslated()
+	 */
+	public String getPathTranslated() {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#getQueryString()
+	 */
+	public String getQueryString() {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#getRemoteUser()
+	 */
+	public String getRemoteUser() {
+		return portletRequest.getRemoteUser();
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public String getRequestURI() {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public StringBuffer getRequestURL() {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
+	 */
+	public String getRequestedSessionId() {
+		return portletRequest.getRequestedSessionId();
+	}
+
+	/**
+	 * A {@link PortletRequest} has no servlet path. But for compatibility with Struts 2 components and
+	 * interceptors, the action parameter on the request is mapped to the servlet path.
+	 * @see javax.servlet.http.HttpServletRequest#getServletPath()
+	 */
+	public String getServletPath() {
+		String actionPath = getParameter(ACTION_PARAM);
+		actionPath = removeBadCharacters(actionPath);
+		if(actionPath != null && !actionPath.endsWith(".action")) {
+			actionPath += ".action";
+		}
+		return actionPath;
+	}
+	
+
+	private String removeBadCharacters(String actionPath) {
+		if(actionPath.indexOf("%2F") >= 0) {
+			return actionPath.replace("%2F", "/");
+		}
+		else {
+			return actionPath.replace("%252525252525252F", "/");
+		}
+	}
+
+	/**
+	 * Get the {@link PortletSession} as a {@link PortletHttpSession} instance.
+	 * @see javax.servlet.http.HttpServletRequest#getSession()
+	 */
+	public HttpSession getSession() {
+		return new PortletHttpSession(portletRequest.getPortletSession());
+	}
+
+	/**
+	 * Get the {@link PortletSession} as a {@link PortletHttpSession} instance.
+	 * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
+	 */
+	public HttpSession getSession(boolean create) {
+		return new PortletHttpSession(portletRequest.getPortletSession(create));
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
+	 */
+	public Principal getUserPrincipal() {
+		return portletRequest.getUserPrincipal();
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public boolean isRequestedSessionIdFromCookie() {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public boolean isRequestedSessionIdFromURL() {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public boolean isRequestedSessionIdFromUrl() {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
+	 */
+	public boolean isRequestedSessionIdValid() {
+		return portletRequest.isRequestedSessionIdValid();
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
+	 */
+	public boolean isUserInRole(String role) {
+		return portletRequest.isUserInRole(role);
+	}
+
+	/**
+	 * Gets an attribute value on the {@link PortletRequest}. If the attribute name is 
+	 * <tt>javax.servlet.include.servlet_path</tt>, it returns the same as
+	 * {@link PortletServletRequest#getServletPath()}
+	 * @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
+	 */
+	public Object getAttribute(String name) {
+		if("javax.servlet.include.servlet_path".equals(name)) {
+			return getServletPath();
+		}
+		else {
+			return portletRequest.getAttribute(name);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#getAttributeNames()
+	 */
+	public Enumeration getAttributeNames() {
+		return portletRequest.getAttributeNames();
+	}
+
+	/**
+	 * Can only be invoked in the event phase.
+	 * @see ServletRequest#getCharacterEncoding()
+	 * @throws IllegalStateException If the portlet is not in the event phase.
+	 */
+	public String getCharacterEncoding() {
+		if(portletRequest instanceof ActionRequest) {
+			return ((ActionRequest)portletRequest).getCharacterEncoding();
+		}
+		else {
+			throw new IllegalStateException("Not allowed in render phase");
+		}
+	}
+
+	/**
+	 * Can only be invoked in the event phase.
+	 * @see ServletRequest#getContentLength()
+	 * @throws IllegalStateException If the portlet is not in the event phase.
+	 */
+	public int getContentLength() {
+		if(portletRequest instanceof ActionRequest) {
+			return ((ActionRequest)portletRequest).getContentLength();
+		}
+		else {
+			throw new IllegalStateException("Not allowed in render phase");
+		}
+	}
+
+	/**
+	 * Can only be invoked in the event phase.
+	 * @see ServletRequest#getContentType()
+	 * @throws IllegalStateException If the portlet is not in the event phase.
+	 */
+	public String getContentType() {
+		if(portletRequest instanceof ActionRequest) {
+			return ((ActionRequest)portletRequest).getContentType();
+		}
+		else {
+			throw new IllegalStateException("Not allowed in render phase");
+		}
+	}
+
+	/**
+	 * Can only be invoked in the event phase. When invoked in the event phase, it will wrap the
+	 * portlet's {@link InputStream} as a {@link PortletServletInputStream}.
+	 * @see ServletRequest#getInputStream()
+	 * @throws IllegalStateException If the portlet is not in the event phase.
+	 */
+	public ServletInputStream getInputStream() throws IOException {
+		if(portletRequest instanceof ActionRequest) {
+			return new PortletServletInputStream(((ActionRequest)portletRequest).getPortletInputStream());
+		}
+		else {
+			throw new IllegalStateException("Not allowed in render phase");
+		}
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public String getLocalAddr() {
+		if(portletRequest instanceof HttpServletRequest) {
+			return ((HttpServletRequest)portletRequest).getLocalAddr();
+		}
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public String getLocalName() {
+		if(portletRequest instanceof HttpServletRequest) {
+			return ((HttpServletRequest)portletRequest).getLocalName();
+		}
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public int getLocalPort() {
+		if(portletRequest instanceof HttpServletRequest) {
+			return ((HttpServletRequest)portletRequest).getLocalPort();
+		}
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#getLocale()
+	 */
+	public Locale getLocale() {
+		return portletRequest.getLocale();
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#getLocales()
+	 */
+	public Enumeration getLocales() {
+		return portletRequest.getLocales();
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
+	 */
+	public String getParameter(String name) {
+		String value = portletRequest.getParameter(name);
+		if(value == null) {
+			String[] values = extraParams.get(name);
+			if(values != null && values.length > 0) {
+				value = values[0];
+			}
+		}
+		return value;
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#getParameterMap()
+	 */
+	public Map getParameterMap() {
+		return portletRequest.getParameterMap();
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#getParameterNames()
+	 */
+	public Enumeration getParameterNames() {
+		return portletRequest.getParameterNames();
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
+	 */
+	public String[] getParameterValues(String name) {
+		return portletRequest.getParameterValues(name);
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public String getProtocol() {
+		if(portletRequest instanceof HttpServletRequest) {
+			return ((HttpServletRequest)portletRequest).getProtocol();
+		}
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Can only be invoked in the event phase.
+	 * @see ServletRequest#getReader()
+	 * @throws IllegalStateException If the portlet is not in the event phase.
+	 */
+	public BufferedReader getReader() throws IOException {
+		if(portletRequest instanceof ActionRequest) {
+			return ((ActionRequest)portletRequest).getReader();
+		}
+		else {
+			throw new IllegalStateException("Not allowed in render phase");
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#getRealPath(java.lang.String)
+	 */
+	public String getRealPath(String path) {
+		return portletContext.getRealPath(path);
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public String getRemoteAddr() {
+		if(portletRequest instanceof HttpServletRequest) {
+			return ((HttpServletRequest)portletRequest).getRemoteAddr();
+		}
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public String getRemoteHost() {
+		if(portletRequest instanceof HttpServletRequest) {
+			return ((HttpServletRequest)portletRequest).getRemoteHost();
+		}
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public int getRemotePort() {
+		if(portletRequest instanceof HttpServletRequest) {
+			return ((HttpServletRequest)portletRequest).getRemotePort();
+		}
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/**
+	 * Get the {@link PortletRequestDispatcher} as a {@link PortletServletRequestDispatcher} instance.
+	 * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String)
+	 */
+	public RequestDispatcher getRequestDispatcher(String path) {
+		return new PortletServletRequestDispatcher(portletContext.getRequestDispatcher(path));
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#getScheme()
+	 */
+	public String getScheme() {
+		return portletRequest.getScheme();
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#getServerName()
+	 */
+	public String getServerName() {
+		return portletRequest.getServerName();
+	}
+
+	/**
+	 * Not allowed in a portlet. 
+	 * @throws IllegalStateException Not allowed in a portlet.
+	 */
+	public int getServerPort() {
+		if(portletRequest instanceof HttpServletRequest) {
+			return ((HttpServletRequest)portletRequest).getServerPort();
+		}
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#isSecure()
+	 */
+	public boolean isSecure() {
+		return portletRequest.isSecure();
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
+	 */
+	public void removeAttribute(String name) {
+		portletRequest.removeAttribute(name);
+	}
+
+	/* (non-Javadoc)
+	 * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object)
+	 */
+	public void setAttribute(String name, Object o) {
+		portletRequest.setAttribute(name, o);
+	}
+
+	/**
+	 * Can only be invoked in the event phase.
+	 * @see ServletRequest#setCharacterEncoding(String)
+	 * @throws IllegalStateException If the portlet is not in the event phase.
+	 */
+	public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
+		if(portletRequest instanceof ActionRequest) {
+			((ActionRequest)portletRequest).setCharacterEncoding(env);
+		}
+		else {
+			throw new IllegalStateException("Not allowed in render phase");
+		}
+	}
+	
+	/**
+	 * Get the wrapped {@link PortletRequest} instance. 
+	 * @return The wrapped {@link PortletRequest} instance.
+	 */
+	public PortletRequest getPortletRequest() {
+		return portletRequest;
+	}
+}

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletRequestDispatcher.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletRequestDispatcher.java?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletRequestDispatcher.java (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletRequestDispatcher.java Mon Jan 21 02:09:00 2008
@@ -0,0 +1,70 @@
+/*
+ * $Id: PortletServletRequestDispatcher.java 590812 2007-10-31 20:32:54Z apetrelli $
+ *
+ * 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.struts2.portlet.servlet;
+
+import java.io.IOException;
+
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.PortletResponse;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+public class PortletServletRequestDispatcher implements RequestDispatcher {
+
+	private PortletRequestDispatcher portletRequestDispatcher;
+	
+	public PortletServletRequestDispatcher(PortletRequestDispatcher portletRequestDispatcher) {
+		this.portletRequestDispatcher = portletRequestDispatcher;
+	}
+
+	public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
+		throw new IllegalStateException("Not allowed in a portlet");
+		
+	}
+
+	public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException {
+		if(request instanceof PortletServletRequest && response instanceof PortletServletResponse) {
+			PortletRequest req = ((PortletServletRequest)request).getPortletRequest();
+			PortletResponse resp = ((PortletServletResponse)response).getPortletResponse();
+			if(req instanceof RenderRequest && resp instanceof RenderResponse) {
+				try {
+					portletRequestDispatcher.include((RenderRequest)req, (RenderResponse)resp);
+				}
+				catch(PortletException e) {
+					throw new ServletException(e);
+				}
+			}
+			else {
+				throw new IllegalStateException("Can only be invoked in the render phase");
+			}
+		}
+		else {
+			throw new IllegalStateException("Can only be invoked in a portlet");
+		}
+	}
+
+}

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletResponse.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletResponse.java?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletResponse.java (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/PortletServletResponse.java Mon Jan 21 02:09:00 2008
@@ -0,0 +1,244 @@
+/*
+ * $Id: PortletServletResponse.java 590812 2007-10-31 20:32:54Z apetrelli $
+ *
+ * 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.struts2.portlet.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Locale;
+
+import javax.portlet.MimeResponse;
+import javax.portlet.PortletResponse;
+import javax.portlet.RenderResponse;
+import javax.portlet.ResourceResponse;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+public class PortletServletResponse implements HttpServletResponse {
+
+	private PortletResponse portletResponse;
+	
+	public PortletServletResponse(PortletResponse portletResponse) {
+		this.portletResponse = portletResponse;
+	}
+	
+	public void addCookie(Cookie cookie) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void addDateHeader(String name, long date) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void addHeader(String name, String value) {
+		portletResponse.addProperty(name, value);
+	}
+
+	public void addIntHeader(String name, int value) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public boolean containsHeader(String name) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public String encodeRedirectURL(String url) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public String encodeRedirectUrl(String url) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public String encodeURL(String url) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public String encodeUrl(String url) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void sendError(int sc) throws IOException {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void sendError(int sc, String msg) throws IOException {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void sendRedirect(String location) throws IOException {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void setDateHeader(String name, long date) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void setHeader(String name, String value) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void setIntHeader(String name, int value) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void setStatus(int sc) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void setStatus(int sc, String sm) {
+		throw new IllegalStateException("Not allowed in a portlet");
+	}
+
+	public void flushBuffer() throws IOException {
+		if(portletResponse instanceof MimeResponse) {
+			((MimeResponse)portletResponse).flushBuffer();
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public int getBufferSize() {
+		if(portletResponse instanceof MimeResponse) {
+			return ((MimeResponse)portletResponse).getBufferSize();
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public String getCharacterEncoding() {
+		if(portletResponse instanceof MimeResponse) {
+			return ((MimeResponse)portletResponse).getCharacterEncoding();
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public String getContentType() {
+		if(portletResponse instanceof MimeResponse) {
+			return ((MimeResponse)portletResponse).getContentType();
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public Locale getLocale() {
+		if(portletResponse instanceof MimeResponse) {
+			return ((MimeResponse)portletResponse).getLocale();
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public ServletOutputStream getOutputStream() throws IOException {
+		if(portletResponse instanceof MimeResponse) {
+			return new PortletServletOutputStream(((MimeResponse)portletResponse).getPortletOutputStream());
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public PrintWriter getWriter() throws IOException {
+		if(portletResponse instanceof MimeResponse) {
+			return ((MimeResponse)portletResponse).getWriter();
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public boolean isCommitted() {
+		if(portletResponse instanceof MimeResponse) {
+			return ((MimeResponse)portletResponse).isCommitted();
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public void reset() {
+		if(portletResponse instanceof MimeResponse) {
+			((MimeResponse)portletResponse).reset();
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public void resetBuffer() {
+		if(portletResponse instanceof MimeResponse) {
+			((MimeResponse)portletResponse).resetBuffer();
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public void setBufferSize(int size) {
+		if(portletResponse instanceof MimeResponse) {
+			((MimeResponse)portletResponse).setBufferSize(size);
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public void setCharacterEncoding(String charset) {
+		if(portletResponse instanceof ResourceResponse) {
+			((ResourceResponse)portletResponse).setCharacterEncoding(charset);
+		}
+		throw new IllegalStateException("Only allowed in resource phase");
+	}
+
+	public void setContentLength(int len) {
+		if(portletResponse instanceof ResourceResponse) {
+			((ResourceResponse)portletResponse).setContentLength(len);
+		}
+		throw new IllegalStateException("Only allowed in resource phase");
+	}
+
+	public void setContentType(String type) {
+		if(portletResponse instanceof MimeResponse) {
+			((MimeResponse)portletResponse).setContentType(type);
+		}
+		else {
+			throw new IllegalStateException("Only allowed in render or resource phase");
+		}
+	}
+
+	public void setLocale(Locale loc) {
+		if(portletResponse instanceof ResourceResponse) {
+			((ResourceResponse)portletResponse).setLocale(loc);
+		}
+		throw new IllegalStateException("Only allowed in resource phase");
+	}
+
+	public PortletResponse getPortletResponse() {
+		return portletResponse;
+	}
+
+}

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/package.html
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/package.html?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/package.html (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/servlet/package.html Mon Jan 21 02:09:00 2008
@@ -0,0 +1,27 @@
+<!--
+/*
+ * $Id: package.html 590812 2007-10-31 20:32:54Z apetrelli $
+ *
+ * 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.
+ */
+-->
+<body>
+	Portlet wrapper objects for some of the servlet api objects. The wrappers simply delegate to the 
+	underlying, corresponding portlet objects. The portlet wrapper objects makes it easier to reuse 
+	interceptors and components from struts2 core.
+</body>
\ No newline at end of file

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/util/PortletUrlHelper.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/util/PortletUrlHelper.java?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/util/PortletUrlHelper.java (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/portlet/util/PortletUrlHelper.java Mon Jan 21 02:09:00 2008
@@ -0,0 +1,315 @@
+/*
+ * $Id: PortletUrlHelper.java 582626 2007-10-07 13:26:12Z mrdon $
+ *
+ * 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.struts2.portlet.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.portlet.BaseURL;
+import javax.portlet.PortletMode;
+import javax.portlet.PortletSecurityException;
+import javax.portlet.PortletURL;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.WindowState;
+
+import org.apache.struts2.StrutsException;
+import org.apache.struts2.portlet.PortletActionConstants;
+import org.apache.struts2.portlet.context.PortletActionContext;
+
+import com.opensymphony.xwork2.util.TextUtils;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+/**
+ * Helper class for creating Portlet URLs. Portlet URLs are fundamentally different from regular
+ * servlet URLs since they never target the application itself; all requests go through the portlet
+ * container and must therefore be programatically constructed using the
+ * {@link javax.portlet.RenderResponse#createActionURL()} and
+ * {@link javax.portlet.RenderResponse#createRenderURL()} APIs.
+ *
+ */
+public class PortletUrlHelper {
+    public static final String ENCODING = "UTF-8";
+
+    private static final Logger LOG = LoggerFactory.getLogger(PortletUrlHelper.class);
+
+    /**
+     * Create a portlet URL with for the specified action and namespace.
+     *
+     * @param action The action the URL should invoke.
+     * @param namespace The namespace of the action to invoke.
+     * @param method The method of the action to invoke.
+     * @param params The parameters of the URL.
+     * @param type The type of the url, either <tt>action</tt> or <tt>render</tt>
+     * @param mode The PortletMode of the URL.
+     * @param state The WindowState of the URL.
+     * @return The URL String.
+     */
+    public static String buildUrl(String action, String namespace, String method, Map params,
+            String type, String mode, String state) {
+        return buildUrl(action, namespace, method, params, null, type, mode, state,
+                true, true);
+    }
+
+    /**
+     * Create a portlet URL with for the specified action and namespace.
+     *
+     * @see #buildUrl(String, String, Map, String, String, String)
+     */
+    public static String buildUrl(String action, String namespace, String method, Map params,
+            String scheme, String type, String portletMode, String windowState,
+            boolean includeContext, boolean encodeResult) {
+    	StringBuffer resultingAction = new StringBuffer();
+        RenderRequest request = PortletActionContext.getRenderRequest();
+        RenderResponse response = PortletActionContext.getRenderResponse();
+        LOG.debug("Creating url. Action = " + action + ", Namespace = "
+                + namespace + ", Type = " + type);
+        namespace = prependNamespace(namespace, portletMode);
+        if (!TextUtils.stringSet(portletMode)) {
+            portletMode = PortletActionContext.getRenderRequest().getPortletMode().toString();
+        }
+        String result = null;
+        int paramStartIndex = action.indexOf('?');
+        if (paramStartIndex > 0) {
+            String value = action;
+            action = value.substring(0, value.indexOf('?'));
+            String queryStr = value.substring(paramStartIndex + 1);
+            StringTokenizer tok = new StringTokenizer(queryStr, "&");
+            while (tok.hasMoreTokens()) {
+                String paramVal = tok.nextToken();
+                String key = paramVal.substring(0, paramVal.indexOf('='));
+                String val = paramVal.substring(paramVal.indexOf('=') + 1);
+                params.put(key, new String[] { val });
+            }
+        }
+        if (TextUtils.stringSet(namespace)) {
+            resultingAction.append(namespace);
+            if(!action.startsWith("/") && !namespace.endsWith("/")) {
+                resultingAction.append("/");
+            }
+        }
+        resultingAction.append(action);
+        if(TextUtils.stringSet(method)) {
+        	resultingAction.append("!").append(method);
+        }
+        LOG.debug("Resulting actionPath: " + resultingAction);
+        params.put(PortletActionConstants.ACTION_PARAM, new String[] { resultingAction.toString() });
+
+        BaseURL url = null;
+        if ("action".equalsIgnoreCase(type)) {
+            LOG.debug("Creating action url");
+            url = response.createActionURL();
+        }
+        else if("resource".equalsIgnoreCase(type)) {
+        	LOG.debug("Creating resource url");
+        	url = response.createResourceURL();
+        }
+        else {
+            LOG.debug("Creating render url");
+            url = response.createRenderURL();
+        }
+
+        params.put(PortletActionConstants.MODE_PARAM, portletMode);
+        url.setParameters(ensureParamsAreStringArrays(params));
+
+        if ("HTTPS".equalsIgnoreCase(scheme)) {
+            try {
+                url.setSecure(true);
+            } catch (PortletSecurityException e) {
+                LOG.error("Cannot set scheme to https", e);
+            }
+        }
+        if(url instanceof PortletURL) {
+        	try {
+        		((PortletURL)url).setPortletMode(getPortletMode(request, portletMode));
+        		((PortletURL)url).setWindowState(getWindowState(request, windowState));
+        	} catch (Exception e) {
+        		LOG.error("Unable to set mode or state:" + e.getMessage(), e);
+        	}
+        }
+        result = url.toString();
+        // TEMP BUG-WORKAROUND FOR DOUBLE ESCAPING OF AMPERSAND
+        if(result.indexOf("&amp;") >= 0) {
+            result = result.replace("&amp;", "&");
+        }
+        return result;
+
+    }
+
+    /**
+     *
+     * Prepend the namespace configuration for the specified namespace and PortletMode.
+     *
+     * @param namespace The base namespace.
+     * @param portletMode The PortletMode.
+     *
+     * @return prepended namespace.
+     */
+    private static String prependNamespace(String namespace, String portletMode) {
+        StringBuffer sb = new StringBuffer();
+        PortletMode mode = PortletActionContext.getRenderRequest().getPortletMode();
+        if(TextUtils.stringSet(portletMode)) {
+            mode = new PortletMode(portletMode);
+        }
+        String portletNamespace = PortletActionContext.getPortletNamespace();
+        String modeNamespace = (String)PortletActionContext.getModeNamespaceMap().get(mode);
+        LOG.debug("PortletNamespace: " + portletNamespace + ", modeNamespace: " + modeNamespace);
+        if(TextUtils.stringSet(portletNamespace)) {
+            sb.append(portletNamespace);
+        }
+        if(TextUtils.stringSet(modeNamespace)) {
+            if(!modeNamespace.startsWith("/")) {
+                sb.append("/");
+            }
+            sb.append(modeNamespace);
+        }
+        if(TextUtils.stringSet(namespace)) {
+            if(!namespace.startsWith("/")) {
+                sb.append("/");
+            }
+            sb.append(namespace);
+        }
+        LOG.debug("Resulting namespace: " + sb);
+        return sb.toString();
+    }
+
+    /**
+     * Encode an url to a non Struts action resource, like stylesheet, image or
+     * servlet.
+     *
+     * @param value
+     * @return encoded url to non Struts action resources.
+     */
+    public static String buildResourceUrl(String value, Map params) {
+        StringBuffer sb = new StringBuffer();
+        // Relative URLs are not allowed in a portlet
+        if (!value.startsWith("/")) {
+            sb.append("/");
+        }
+        sb.append(value);
+        if(params != null && params.size() > 0) {
+            sb.append("?");
+            Iterator it = params.keySet().iterator();
+            try {
+            while(it.hasNext()) {
+                String key = (String)it.next();
+                String val = (String)params.get(key);
+
+                sb.append(URLEncoder.encode(key, ENCODING)).append("=");
+                sb.append(URLEncoder.encode(val, ENCODING));
+                if(it.hasNext()) {
+                    sb.append("&");
+                }
+            }
+            } catch (UnsupportedEncodingException e) {
+                throw new StrutsException("Encoding "+ENCODING+" not found");
+            }
+        }
+        RenderResponse resp = PortletActionContext.getRenderResponse();
+        RenderRequest req = PortletActionContext.getRenderRequest();
+        return resp.encodeURL(req.getContextPath() + sb.toString());
+    }
+
+    /**
+     * Will ensure that all entries in <code>params</code> are String arrays,
+     * as requried by the setParameters on the PortletURL.
+     *
+     * @param params The parameters to the URL.
+     * @return A Map with all parameters as String arrays.
+     */
+    public static Map ensureParamsAreStringArrays(Map params) {
+        Map result = null;
+        if (params != null) {
+            result = new LinkedHashMap(params.size());
+            Iterator it = params.keySet().iterator();
+            while (it.hasNext()) {
+                Object key = it.next();
+                Object val = params.get(key);
+                if (val instanceof String[]) {
+                    result.put(key, val);
+                } else {
+                    result.put(key, new String[] { val.toString() });
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Convert the given String to a WindowState object.
+     *
+     * @param portletReq The RenderRequest.
+     * @param windowState The WindowState as a String.
+     * @return The WindowState that mathces the <tt>windowState</tt> String, or if
+     * the Sring is blank, the current WindowState.
+     */
+    private static WindowState getWindowState(RenderRequest portletReq,
+            String windowState) {
+        WindowState state = portletReq.getWindowState();
+        if (TextUtils.stringSet(windowState)) {
+            state = portletReq.getWindowState();
+            if ("maximized".equalsIgnoreCase(windowState)) {
+                state = WindowState.MAXIMIZED;
+            } else if ("normal".equalsIgnoreCase(windowState)) {
+                state = WindowState.NORMAL;
+            } else if ("minimized".equalsIgnoreCase(windowState)) {
+                state = WindowState.MINIMIZED;
+            }
+        }
+        if(state == null) {
+            state = WindowState.NORMAL;
+        }
+        return state;
+    }
+
+    /**
+     * Convert the given String to a PortletMode object.
+     *
+     * @param portletReq The RenderRequest.
+     * @param portletMode The PortletMode as a String.
+     * @return The PortletMode that mathces the <tt>portletMode</tt> String, or if
+     * the Sring is blank, the current PortletMode.
+     */
+    private static PortletMode getPortletMode(RenderRequest portletReq,
+            String portletMode) {
+        PortletMode mode = portletReq.getPortletMode();
+
+        if (TextUtils.stringSet(portletMode)) {
+            mode = portletReq.getPortletMode();
+            if ("edit".equalsIgnoreCase(portletMode)) {
+                mode = PortletMode.EDIT;
+            } else if ("view".equalsIgnoreCase(portletMode)) {
+                mode = PortletMode.VIEW;
+            } else if ("help".equalsIgnoreCase(portletMode)) {
+                mode = PortletMode.HELP;
+            }
+        }
+        if(mode == null) {
+            mode = PortletMode.VIEW;
+        }
+        return mode;
+    }
+}

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/views/freemarker/PortletFreemarkerResult.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/views/freemarker/PortletFreemarkerResult.java?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/views/freemarker/PortletFreemarkerResult.java (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/main/java/org/apache/struts2/views/freemarker/PortletFreemarkerResult.java Mon Jan 21 02:09:00 2008
@@ -0,0 +1,281 @@
+/*
+ * $Id: PortletFreemarkerResult.java 564599 2007-08-10 14:05:17Z nilsga $
+ *
+ * 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.struts2.views.freemarker;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Locale;
+
+import javax.portlet.ActionResponse;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.dispatcher.StrutsResultSupport;
+import org.apache.struts2.portlet.PortletActionConstants;
+import org.apache.struts2.portlet.context.PortletActionContext;
+import org.apache.struts2.views.util.ResourceUtil;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ValueStack;
+
+import freemarker.template.Configuration;
+import freemarker.template.ObjectWrapper;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+
+/**
+ */
+public class PortletFreemarkerResult extends StrutsResultSupport {
+
+    private static final long serialVersionUID = -5570612389289887543L;
+
+    protected ActionInvocation invocation;
+
+    protected Configuration configuration;
+
+    protected ObjectWrapper wrapper;
+    protected FreemarkerManager freemarkerManager;
+
+    /*
+     * Struts results are constructed for each result execeution
+     *
+     * the current context is availible to subclasses via these protected fields
+     */
+    protected String location;
+
+    private String pContentType = "text/html";
+
+    public PortletFreemarkerResult() {
+        super();
+    }
+
+    public PortletFreemarkerResult(String location) {
+        super(location);
+    }
+    
+    @Inject
+    public void setFreemarkerManager(FreemarkerManager mgr) {
+        this.freemarkerManager = mgr;
+    }
+
+    public void setContentType(String aContentType) {
+        pContentType = aContentType;
+    }
+
+    /**
+     * allow parameterization of the contentType the default being text/html
+     */
+    public String getContentType() {
+        return pContentType;
+    }
+
+    /**
+     * Execute this result, using the specified template location. <p/>The
+     * template location has already been interoplated for any variable
+     * substitutions <p/>this method obtains the freemarker configuration and
+     * the object wrapper from the provided hooks. It them implements the
+     * template processing workflow by calling the hooks for preTemplateProcess
+     * and postTemplateProcess
+     */
+    public void doExecute(String location, ActionInvocation invocation)
+            throws IOException, TemplateException, PortletException {
+        if (PortletActionContext.isAction()) {
+            executeActionResult(location, invocation);
+        } else if (PortletActionContext.isRender()) {
+            executeRenderResult(location, invocation);
+        }
+    }
+
+    /**
+     * @param location
+     * @param invocation
+     */
+    private void executeActionResult(String location,
+                                     ActionInvocation invocation) {
+        ActionResponse res = PortletActionContext.getActionResponse();
+        // View is rendered outside an action...uh oh...
+        res.setRenderParameter(PortletActionConstants.ACTION_PARAM, "freemarkerDirect");
+        res.setRenderParameter("location", location);
+        res.setRenderParameter(PortletActionConstants.MODE_PARAM, PortletActionContext
+                .getRequest().getPortletMode().toString());
+
+    }
+
+    /**
+     * @param location
+     * @param invocation
+     * @throws TemplateException
+     * @throws IOException
+     * @throws TemplateModelException
+     */
+    private void executeRenderResult(String location,
+                                     ActionInvocation invocation) throws TemplateException, IOException,
+            TemplateModelException, PortletException {
+        this.location = location;
+        this.invocation = invocation;
+        this.configuration = getConfiguration();
+        this.wrapper = getObjectWrapper();
+
+        HttpServletRequest req = ServletActionContext.getRequest();
+
+        if (!location.startsWith("/")) {
+            String base = ResourceUtil.getResourceBase(req);
+            location = base + "/" + location;
+        }
+
+        Template template = configuration.getTemplate(location, deduceLocale());
+        TemplateModel model = createModel();
+        // Give subclasses a chance to hook into preprocessing
+        if (preTemplateProcess(template, model)) {
+            try {
+                // Process the template
+                PortletActionContext.getRenderResponse().setContentType(pContentType);
+                template.process(model, getWriter());
+            } finally {
+                // Give subclasses a chance to hook into postprocessing
+                postTemplateProcess(template, model);
+            }
+        }
+    }
+
+    /**
+     * This method is called from {@link #doExecute(String, ActionInvocation)}
+     * to obtain the FreeMarker configuration object that this result will use
+     * for template loading. This is a hook that allows you to custom-configure
+     * the configuration object in a subclass, or to fetch it from an IoC
+     * container. <p/><b>The default implementation obtains the configuration
+     * from the ConfigurationManager instance. </b>
+     */
+    protected Configuration getConfiguration() throws TemplateException {
+        return freemarkerManager.getConfiguration(
+                ServletActionContext.getServletContext());
+    }
+
+    /**
+     * This method is called from {@link #doExecute(String, ActionInvocation)}
+     * to obtain the FreeMarker object wrapper object that this result will use
+     * for adapting objects into template models. This is a hook that allows you
+     * to custom-configure the wrapper object in a subclass. <p/><b>The default
+     * implementation returns {@link Configuration#getObjectWrapper()}</b>
+     */
+    protected ObjectWrapper getObjectWrapper() {
+        return configuration.getObjectWrapper();
+    }
+
+    /**
+     * The default writer writes directly to the response writer.
+     */
+    protected Writer getWriter() throws IOException {
+        return PortletActionContext.getRenderResponse().getWriter();
+    }
+
+    /**
+     * Build the instance of the ScopesHashModel, including JspTagLib support
+     * <p/>Objects added to the model are <p/>
+     * <ul>
+     * <li>Application - servlet context attributes hash model
+     * <li>JspTaglibs - jsp tag lib factory model
+     * <li>Request - request attributes hash model
+     * <li>Session - session attributes hash model
+     * <li>request - the HttpServletRequst object for direct access
+     * <li>response - the HttpServletResponse object for direct access
+     * <li>stack - the OgnLValueStack instance for direct access
+     * <li>ognl - the instance of the OgnlTool
+     * <li>action - the action itself
+     * <li>exception - optional : the JSP or Servlet exception as per the
+     * servlet spec (for JSP Exception pages)
+     * <li>struts - instance of the StrutsUtil class
+     * </ul>
+     */
+    protected TemplateModel createModel() throws TemplateModelException {
+        ServletContext servletContext = ServletActionContext
+                .getServletContext();
+        HttpServletRequest request = ServletActionContext.getRequest();
+        HttpServletResponse response = ServletActionContext.getResponse();
+        ValueStack stack = ServletActionContext.getContext()
+                .getValueStack();
+        return freemarkerManager.buildTemplateModel(stack,
+                invocation.getAction(), servletContext, request, response,
+                wrapper);
+    }
+
+    /**
+     * Returns the locale used for the
+     * {@link Configuration#getTemplate(String, Locale)}call. The base
+     * implementation simply returns the locale setting of the configuration.
+     * Override this method to provide different behaviour,
+     */
+    protected Locale deduceLocale() {
+        return configuration.getLocale();
+    }
+
+    /**
+     * the default implementation of postTemplateProcess applies the contentType
+     * parameter
+     */
+    protected void postTemplateProcess(Template template, TemplateModel data)
+            throws IOException {
+    }
+
+    /**
+     * Called before the execution is passed to template.process(). This is a
+     * generic hook you might use in subclasses to perform a specific action
+     * before the template is processed. By default does nothing. A typical
+     * action to perform here is to inject application-specific objects into the
+     * model root
+     *
+     * @return true to process the template, false to suppress template
+     *         processing.
+     */
+    protected boolean preTemplateProcess(Template template, TemplateModel model)
+            throws IOException {
+        Object attrContentType = template.getCustomAttribute("content_type");
+
+        if (attrContentType != null) {
+            ServletActionContext.getResponse().setContentType(
+                    attrContentType.toString());
+        } else {
+            String contentType = getContentType();
+
+            if (contentType == null) {
+                contentType = "text/html";
+            }
+
+            String encoding = template.getEncoding();
+
+            if (encoding != null) {
+                contentType = contentType + "; charset=" + encoding;
+            }
+
+            ServletActionContext.getResponse().setContentType(contentType);
+        }
+
+        return true;
+    }
+}
+

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/LICENSE.txt
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/LICENSE.txt?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/LICENSE.txt (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/LICENSE.txt Mon Jan 21 02:09:00 2008
@@ -0,0 +1,174 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/NOTICE.txt
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/NOTICE.txt?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/NOTICE.txt (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/NOTICE.txt Mon Jan 21 02:09:00 2008
@@ -0,0 +1,5 @@
+Apache Struts
+Copyright 2000-2007 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/struts-plugin.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/struts-plugin.xml?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/struts-plugin.xml (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/main/resources/struts-plugin.xml Mon Jan 21 02:09:00 2008
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+/*
+ * $Id: struts-plugin.xml 609581 2008-01-07 12:16:39Z nilsga $
+ *
+ * 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.
+ */
+-->
+
+<!DOCTYPE struts PUBLIC
+    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
+    "http://struts.apache.org/dtds/struts-2.0.dtd">
+    
+<struts>
+	
+	<bean type="org.apache.struts2.components.UrlRenderer" name="portlet" class="org.apache.struts2.components.PortletUrlRenderer"/>
+	
+	<constant name="struts.urlRenderer" value="portlet" />
+	<constant name="struts.portlet.useDispatcherServlet" value="false" />
+	<constant name="struts.portlet.dispatcherServletName" value="Struts2PortletDispatcherServlet" />
+	
+    <package name="struts-portlet-default" extends="struts-default">
+
+	   <result-types>
+			<result-type name="dispatcher" class="org.apache.struts2.portlet.result.PortletResult" default="true"/>
+            <result-type name="redirect" class="org.apache.struts2.portlet.result.PortletResult"/>
+		    <result-type name="redirectAction" class="org.apache.struts2.portlet.result.PortletActionRedirectResult"/>
+			<result-type name="freemarker" class="org.apache.struts2.views.freemarker.PortletFreemarkerResult"/>
+			<result-type name="velocity" class="org.apache.struts2.portlet.result.PortletVelocityResult"/>
+	   </result-types>
+       
+       <interceptors>
+        <interceptor name="portletAware" class="org.apache.struts2.portlet.interceptor.PortletAwareInterceptor"/>
+		<interceptor name="portletState" class="org.apache.struts2.portlet.interceptor.PortletStateInterceptor"/>
+		<!-- Default stack for operating in portlet environment -->
+        <interceptor-stack name="portletDefaultStack">
+			<interceptor-ref name="portletState"/>
+            <interceptor-ref name="portletAware"/>
+            <interceptor-ref name="defaultStack"/>
+        </interceptor-stack>
+        <!-- Extension of the default portlet stack which also includes the token interceptor --> 
+		<interceptor-stack name="portletDefaultStackWithToken">
+			<interceptor-ref name="portletState"/>
+			<interceptor-ref name="portletAware"/>
+			<interceptor-ref name="token"/>
+			<interceptor-ref name="defaultStack"/>
+		</interceptor-stack>
+		   
+       </interceptors>
+       
+       <default-interceptor-ref name="portletDefaultStack"/>
+		
+	   <action name="renderDirect" class="org.apache.struts2.portlet.dispatcher.DirectRenderFromEventAction">
+	   		<result name="success">${location}</result>
+	   </action>
+	   <action name="freemarkerDirect" class="org.apache.struts2.portlet.dispatcher.DirectRenderFromEventAction">
+	   		<result type="freemarker" name="success">${location}</result>
+	   </action>
+	   <action name="velocityDirect" class="org.apache.struts2.portlet.dispatcher.DirectRenderFromEventAction">
+	   		<result type="velocity" name="success">${location}</result>
+	   </action>
+	</package>
+</struts>

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/test/java/org/apache/struts2/portlet/PortletApplicationMapTest.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/test/java/org/apache/struts2/portlet/PortletApplicationMapTest.java?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/test/java/org/apache/struts2/portlet/PortletApplicationMapTest.java (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/test/java/org/apache/struts2/portlet/PortletApplicationMapTest.java Mon Jan 21 02:09:00 2008
@@ -0,0 +1,169 @@
+/*
+ * $Id: PortletApplicationMapTest.java 557544 2007-07-19 10:03:06Z nilsga $
+ *
+ * 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.struts2.portlet;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.portlet.PortletContext;
+
+import org.jmock.Mock;
+import org.jmock.MockObjectTestCase;
+import org.jmock.core.Constraint;
+
+/**
+ */
+public class PortletApplicationMapTest extends MockObjectTestCase {
+
+    Mock mockPortletContext;
+
+    PortletContext portletContext;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        mockPortletContext = mock(PortletContext.class);
+        portletContext = (PortletContext) mockPortletContext.proxy();
+    }
+
+    public void testGetFromAttributes() {
+        mockPortletContext.stubs().method("getAttribute").with(eq("dummyKey"))
+                .will(returnValue("dummyValue"));
+
+        PortletApplicationMap map = new PortletApplicationMap(
+                (PortletContext) mockPortletContext.proxy());
+
+        assertEquals("dummyValue", map.get("dummyKey"));
+    }
+
+    public void testGetFromInitParameters() {
+        mockPortletContext.stubs().method("getAttribute").with(eq("dummyKey"));
+        mockPortletContext.stubs().method("getInitParameter").with(
+                eq("dummyKey")).will(returnValue("dummyValue"));
+
+        PortletApplicationMap map = new PortletApplicationMap(
+                (PortletContext) mockPortletContext.proxy());
+
+        assertEquals("dummyValue", map.get("dummyKey"));
+    }
+
+    public void testPut() {
+        mockPortletContext.expects(once()).method("setAttribute").with(
+                new Constraint[] { eq("dummyKey"), eq("dummyValue") });
+        mockPortletContext.expects(once()).method("getAttribute").with(
+                eq("dummyKey")).will(returnValue("dummyValue"));
+        PortletApplicationMap map = new PortletApplicationMap(portletContext);
+        Object val = map.put("dummyKey", "dummyValue");
+        assertEquals("dummyValue", val);
+    }
+
+    public void testRemove() {
+        mockPortletContext.expects(once()).method("getAttribute").with(
+                eq("dummyKey")).will(returnValue("dummyValue"));
+        mockPortletContext.expects(once()).method("removeAttribute").with(
+                eq("dummyKey"));
+        PortletApplicationMap map = new PortletApplicationMap(portletContext);
+        Object val = map.remove("dummyKey");
+        assertEquals("dummyValue", val);
+    }
+
+    public void testEntrySet() {
+
+        Enumeration names = new Enumeration() {
+
+            List keys = Arrays.asList(new Object[] { "key1", "key2" });
+
+            Iterator it = keys.iterator();
+
+            public boolean hasMoreElements() {
+                return it.hasNext();
+            }
+
+            public Object nextElement() {
+                return it.next();
+            }
+
+        };
+        Enumeration initParamNames = new Enumeration() {
+
+            List keys = Arrays.asList(new Object[] { "key3" });
+
+            Iterator it = keys.iterator();
+
+            public boolean hasMoreElements() {
+                return it.hasNext();
+            }
+
+            public Object nextElement() {
+                return it.next();
+            }
+
+        };
+
+        mockPortletContext.stubs().method("getAttributeNames").will(
+                returnValue(names));
+        mockPortletContext.stubs().method("getInitParameterNames").will(
+                returnValue(initParamNames));
+        mockPortletContext.stubs().method("getAttribute").with(eq("key1"))
+                .will(returnValue("value1"));
+        mockPortletContext.stubs().method("getAttribute").with(eq("key2"))
+                .will(returnValue("value2"));
+        mockPortletContext.stubs().method("getInitParameter").with(eq("key3"))
+                .will(returnValue("value3"));
+
+        PortletApplicationMap map = new PortletApplicationMap(portletContext);
+        Set entries = map.entrySet();
+
+        assertEquals(3, entries.size());
+        Iterator it = entries.iterator();
+        Map.Entry entry = (Map.Entry) it.next();
+        assertEquals("key2", entry.getKey());
+        assertEquals("value2", entry.getValue());
+        entry = (Map.Entry) it.next();
+        assertEquals("key1", entry.getKey());
+        assertEquals("value1", entry.getValue());
+        entry = (Map.Entry) it.next();
+        assertEquals("key3", entry.getKey());
+        assertEquals("value3", entry.getValue());
+
+    }
+
+    public void testClear() {
+
+        mockPortletContext.expects(once()).method("removeAttribute").with(eq("key1"));
+        mockPortletContext.expects(once()).method("removeAttribute").with(eq("key2"));
+
+        ArrayList dummy = new ArrayList();
+        dummy.add("key1");
+        dummy.add("key2");
+
+        mockPortletContext.expects(once()).method("getAttributeNames").will(
+                returnValue(Collections.enumeration(dummy)));
+
+        PortletApplicationMap map = new PortletApplicationMap(portletContext);
+        map.clear();
+    }
+}

Added: struts/sandbox/trunk/struts2-portlet2-plugin/src/test/java/org/apache/struts2/portlet/PortletRequestMapTest.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-portlet2-plugin/src/test/java/org/apache/struts2/portlet/PortletRequestMapTest.java?rev=613823&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-portlet2-plugin/src/test/java/org/apache/struts2/portlet/PortletRequestMapTest.java (added)
+++ struts/sandbox/trunk/struts2-portlet2-plugin/src/test/java/org/apache/struts2/portlet/PortletRequestMapTest.java Mon Jan 21 02:09:00 2008
@@ -0,0 +1,107 @@
+/*
+ * $Id: PortletRequestMapTest.java 580134 2007-09-27 19:44:01Z nilsga $
+ *
+ * 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.struts2.portlet;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.portlet.PortletRequest;
+
+import org.jmock.MockObjectTestCase;
+import org.springframework.mock.web.portlet.MockPortletRequest;
+
+
+/**
+ * PortletRequestMapTest. Insert description.
+ *
+ */
+public class PortletRequestMapTest extends MockObjectTestCase {
+
+    public void testGet() {
+    	PortletRequest request = new MockPortletRequest();
+    	request.setAttribute("testAttribute", "testValue");
+
+    	PortletRequestMap map = new PortletRequestMap(request);
+        String value = (String)map.get("testAttribute");
+        assertEquals("testValue", value);
+    }
+
+    public void testPut() {
+    	PortletRequest request = new MockPortletRequest();
+    	PortletRequestMap map = new PortletRequestMap(request);
+        Object obj = map.put("testAttribute", "testValue1");
+        
+        assertEquals(obj, "testValue1");
+        assertEquals("testValue1", request.getAttribute("testAttribute"));
+    }
+
+    public void testClear() {
+    	MockPortletRequest request = new MockPortletRequest();
+    	request.setAttribute("testAttribute1", "testValue1");
+    	request.setAttribute("testAttribute2", "testValue2");
+
+
+        PortletRequestMap map = new PortletRequestMap(request);
+        map.clear();
+
+        assertFalse(request.getAttributeNames().hasMoreElements());
+    }
+
+    public void testRemove() {
+        MockPortletRequest request = new MockPortletRequest();
+        request.setAttribute("testAttribute1", "testValue1");
+        
+        PortletRequestMap map = new PortletRequestMap(request);
+        assertEquals("testValue1", map.remove("testAttribute1"));
+        assertNull(request.getAttribute("testAttribute1"));
+    }
+
+    public void testEntrySet() {
+    	MockPortletRequest request = new MockPortletRequest();
+    	request.setAttribute("testAttribute1", "testValue1");
+    	request.setAttribute("testAttribute2", "testValue2");
+
+        PortletRequestMap map = new PortletRequestMap(request);
+        Set entries = map.entrySet();
+
+        assertEquals(2, entries.size());
+        Iterator it = entries.iterator();
+        Map.Entry entry = (Map.Entry)it.next();
+        checkEntry(entry);
+        entry = (Map.Entry)it.next();
+        checkEntry(entry);
+
+    }
+    
+	private void checkEntry(Map.Entry entry) {
+		if(entry.getKey().equals("testAttribute1")) {
+        	assertEquals("testValue1", entry.getValue());
+        }
+        else if(entry.getKey().equals("testAttribute2")) {
+        	assertEquals("testValue2", entry.getValue());
+        }
+        else {
+        	fail("Unexpected entry in etry set: " + entry);
+        }
+	}
+
+}