blob: ae56cea4ac5400a935d733ba6ed9547af128e9a1 [file] [log] [blame]
/*
* 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;
}
}