| /* |
| * 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.cocoon.environment.portlet; |
| |
| import org.apache.cocoon.environment.AbstractEnvironment; |
| import org.apache.cocoon.environment.Context; |
| import org.apache.cocoon.environment.ObjectModelHelper; |
| import org.apache.cocoon.environment.PermanentRedirector; |
| import org.apache.cocoon.environment.Redirector; |
| import org.apache.cocoon.environment.Session; |
| |
| import javax.portlet.PortletContext; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| |
| /** |
| * Implements {@link org.apache.cocoon.environment.Environment} interface for the JSR-168 |
| * Portlet environment. |
| * |
| * @author <a href="mailto:alex.rudnev@dc.gov">Alex Rudnev</a> |
| * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a> |
| * @version CVS $Id$ |
| */ |
| public class PortletEnvironment extends AbstractEnvironment implements Redirector, PermanentRedirector { |
| |
| /** |
| * As portlets do not have a pathInfo in the request, we can simulate this by passing |
| * a parameter. If parameter is null, this will translate to the absent pathInfo, |
| * and portlets will be matched in the sitemap using only servletPath. |
| */ |
| public static final String PARAMETER_PATH_INFO = "cocoon-portlet-path"; |
| |
| /** |
| * This header can be read from any portlet request, |
| * and can be set on action response. |
| */ |
| public static final String HEADER_PORTLET_MODE = "X-Portlet-Mode"; |
| |
| /** |
| * This header can be read from any portlet request, |
| * and can be set on action response. |
| */ |
| public static final String HEADER_WINDOW_STATE = "X-Window-State"; |
| |
| /** |
| * This header can be set only, and only on render response. |
| */ |
| public static final String HEADER_PORTLET_TITLE = "X-Portlet-Title"; |
| |
| /** |
| * This is the prefix for application scope session attributes. |
| */ |
| public static final String SESSION_APPLICATION_SCOPE = "portlet-application-"; |
| |
| /** |
| * This is the prefix for portlet scope session attributes. |
| */ |
| public static final String SESSION_PORTLET_SCOPE = "portlet-portlet-"; |
| |
| |
| /** |
| * The PortletRequest |
| */ |
| private PortletRequest request; |
| |
| /** |
| * The PortletResponse |
| */ |
| private PortletResponse response; |
| |
| /** |
| * The PortletContext |
| */ |
| private Context context; |
| |
| |
| /** |
| * Cache content type as there is no getContentType() |
| * method on reponse object |
| */ |
| private String contentType; |
| |
| /** |
| * Did we redirect? |
| */ |
| private boolean hasRedirected; |
| |
| /** |
| * @see #getDefaultSessionScope() |
| */ |
| private int defaultSessionScope; |
| |
| /** |
| * Constructs a PortletEnvironment object from a PortletRequest |
| * and PortletResponse objects |
| */ |
| public PortletEnvironment(String servletPath, |
| String pathInfo, |
| String uri, |
| String root, |
| javax.portlet.ActionRequest request, |
| javax.portlet.ActionResponse response, |
| PortletContext portletContext, |
| Context context, |
| String containerEncoding, |
| String defaultFormEncoding, |
| int defaultSessionScope) |
| throws IOException { |
| super(uri, null, root, null); |
| |
| this.request = new ActionRequest(servletPath, pathInfo, request, this); |
| this.request.setCharacterEncoding(defaultFormEncoding); |
| this.request.setContainerEncoding(containerEncoding); |
| this.response = new ActionResponse(response, request.getPreferences(), (ActionRequest) this.request, uri); |
| this.context = context; |
| this.defaultSessionScope = defaultSessionScope; |
| |
| setView(extractView(this.request)); |
| setAction(extractAction(this.request)); |
| |
| initObjectModel(request, response, portletContext); |
| } |
| |
| /** |
| * Constructs a PortletEnvironment object from a PortletRequest |
| * and PortletResponse objects |
| */ |
| public PortletEnvironment(String servletPath, |
| String pathInfo, |
| String uri, |
| String root, |
| javax.portlet.RenderRequest request, |
| javax.portlet.RenderResponse response, |
| PortletContext portletContext, |
| Context context, |
| String containerEncoding, |
| String defaultFormEncoding, |
| int defaultSessionScope) |
| throws IOException { |
| super(uri, null, root, null); |
| |
| this.request = new RenderRequest(servletPath, pathInfo, request, this); |
| this.request.setCharacterEncoding(defaultFormEncoding); |
| this.request.setContainerEncoding(containerEncoding); |
| this.response = new RenderResponse(response, request.getPreferences()); |
| this.context = context; |
| this.defaultSessionScope = defaultSessionScope; |
| |
| setView(extractView(this.request)); |
| setAction(extractAction(this.request)); |
| |
| initObjectModel(request, response, portletContext); |
| } |
| |
| private void initObjectModel(javax.portlet.PortletRequest portletRequest, |
| javax.portlet.PortletResponse portletResponse, |
| PortletContext portletContext) { |
| this.objectModel.put(ObjectModelHelper.REQUEST_OBJECT, this.request); |
| this.objectModel.put(ObjectModelHelper.RESPONSE_OBJECT, this.response); |
| this.objectModel.put(ObjectModelHelper.CONTEXT_OBJECT, this.context); |
| |
| // This is a kind of a hack for the components that need |
| // the real portlet objects to pass them along to other |
| // libraries. |
| PortletObjectModelHelper.setPortletRequest(this.objectModel, portletRequest); |
| PortletObjectModelHelper.setPortletResponse(this.objectModel, portletResponse); |
| PortletObjectModelHelper.setPortletContext(this.objectModel, portletContext); |
| } |
| |
| |
| public void redirect(boolean sessionmode, String newURL) throws IOException { |
| this.hasRedirected = true; |
| |
| // check if session mode shall be activated |
| if (sessionmode) { |
| if (getLogger().isDebugEnabled()) { |
| String s = request.getRequestedSessionId(); |
| if (s != null) { |
| getLogger().debug("Session ID in request = " + s + |
| (request.isRequestedSessionIdValid() ? " (valid)" : " (invalid)")); |
| } |
| } |
| |
| // get session from request, or create new session |
| Session session = request.getSession(true); |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("Session ID = " + session.getId()); |
| } |
| } |
| |
| // redirect |
| String redirect = newURL; |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("Sending redirect to '" + redirect + "'"); |
| } |
| |
| this.response.sendRedirect(redirect); |
| } |
| |
| /** |
| * In portlet environment this is the same as {@link #redirect(boolean, String)} |
| */ |
| public void permanentRedirect(boolean sessionmode, String newURL) throws IOException { |
| redirect(sessionmode, newURL); |
| } |
| |
| public boolean hasRedirected() { |
| return this.hasRedirected; |
| } |
| |
| /** |
| * Portlet environment does not support response status code. |
| */ |
| public void setStatus(int statusCode) { |
| } |
| |
| /** |
| * Portlet environment does not support response status code. |
| */ |
| public void sendStatus(int sc) { |
| throw new AbstractMethodError("Not Implemented"); |
| } |
| |
| /** |
| * Set the ContentType |
| */ |
| public void setContentType(String contentType) { |
| this.response.setContentType(contentType); |
| this.contentType = contentType; |
| } |
| |
| /** |
| * Get the ContentType |
| */ |
| public String getContentType() { |
| return this.contentType; |
| } |
| |
| /** |
| * Portlet environment does not support response content length. |
| * This method does nothing. |
| */ |
| public void setContentLength(int length) { |
| } |
| |
| /** |
| * This method always returns true because portlet environment |
| * does not support response codes. |
| */ |
| public boolean isResponseModified(long lastModified) { |
| return true; |
| } |
| |
| /** |
| * Portlet environment does not support response status code. |
| * This method does nothing. |
| */ |
| public void setResponseIsNotModified() { |
| } |
| |
| /** |
| * Reset the response if possible. This allows error handlers to have |
| * a higher chance to produce clean output if the pipeline that raised |
| * the error has already output some data. |
| * |
| * @return true if the response was successfully reset |
| */ |
| public boolean tryResetResponse() throws IOException { |
| if (!super.tryResetResponse()) { |
| try { |
| if (!this.response.isCommitted()) { |
| this.response.reset(); |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("Response successfully reset"); |
| } |
| return true; |
| } |
| } catch (Exception e) { |
| // Log the error, but don't transmit it |
| getLogger().warn("Problem resetting response", e); |
| } |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("Response wasn't reset"); |
| } |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Get the output stream where to write the generated resource. |
| * The returned stream is buffered by the environment. If the |
| * buffer size is -1 then the complete output is buffered. |
| * If the buffer size is 0, no buffering takes place. |
| * This method replaces {@link #getOutputStream()}. |
| */ |
| public OutputStream getOutputStream(final int bufferSize) throws IOException { |
| if (this.outputStream == null) { |
| this.outputStream = this.response.getOutputStream(); |
| } |
| return super.getOutputStream(bufferSize); |
| } |
| |
| /** |
| * Always return <code>true</code>. |
| */ |
| public boolean isExternal() { |
| return true; |
| } |
| |
| /** |
| * Default scope for the session attributes, either |
| * {@link javax.portlet.PortletSession#PORTLET_SCOPE} or |
| * {@link javax.portlet.PortletSession#APPLICATION_SCOPE}. |
| */ |
| int getDefaultSessionScope() { |
| return this.defaultSessionScope; |
| } |
| } |