/* | |
* Copyright 2003,2004 The Apache Software Foundation. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package org.apache.pluto.internal.impl; | |
import org.apache.commons.logging.Log; | |
import org.apache.commons.logging.LogFactory; | |
import org.apache.pluto.PortletContainer; | |
import org.apache.pluto.internal.InternalPortletWindow; | |
import org.apache.pluto.internal.InternalRenderResponse; | |
import org.apache.pluto.descriptors.portlet.PortletDD; | |
import org.apache.pluto.descriptors.portlet.SupportsDD; | |
import org.apache.pluto.spi.PortalCallbackService; | |
import org.apache.pluto.util.ArgumentUtility; | |
import org.apache.pluto.util.NamespaceMapper; | |
import org.apache.pluto.util.StringManager; | |
import org.apache.pluto.util.StringUtils; | |
import org.apache.pluto.util.impl.NamespaceMapperImpl; | |
import javax.portlet.PortletURL; | |
import javax.portlet.RenderResponse; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import java.io.IOException; | |
import java.io.OutputStream; | |
import java.io.PrintWriter; | |
import java.util.Iterator; | |
import java.util.Locale; | |
/** | |
* Implementation of the <code>javax.portlet.RenderResponse</code> interface. | |
* | |
* @author <a href="mailto:ddewolf@apache.org">David H. DeWolf</a> | |
* @author <a href="mailto:zheng@apache.org">ZHENG Zhong</a> | |
*/ | |
public class RenderResponseImpl extends PortletResponseImpl | |
implements RenderResponse, InternalRenderResponse { | |
/** Logger. */ | |
private static final Log LOG = LogFactory.getLog(RenderResponseImpl.class); | |
private static final StringManager EXCEPTIONS = StringManager.getManager( | |
RenderResponseImpl.class.getPackage().getName()); | |
// Private Member Variables ------------------------------------------------ | |
/** True if we are in an include call. */ | |
private boolean included = false; | |
/** The current content type. */ | |
private String currentContentType = null; | |
private NamespaceMapper mapper = new NamespaceMapperImpl(); | |
// Constructor ------------------------------------------------------------- | |
public RenderResponseImpl(PortletContainer container, | |
InternalPortletWindow internalPortletWindow, | |
HttpServletRequest servletRequest, | |
HttpServletResponse servletResponse) { | |
super(container, internalPortletWindow, servletRequest, servletResponse); | |
} | |
// RenderResponse Impl ----------------------------------------------------- | |
public String getContentType() { | |
// NOTE: in servlet 2.4 we could simply use this: | |
// return super.getHttpServletResponse().getContentType(); | |
return currentContentType; | |
} | |
public PortletURL createRenderURL() { | |
return createURL(false); | |
} | |
public PortletURL createActionURL() { | |
return createURL(true); | |
} | |
public String getNamespace() { | |
String namespace = mapper.encode(getInternalPortletWindow().getId(), ""); | |
StringBuffer validNamespace = new StringBuffer(); | |
for (int i = 0; i < namespace.length(); i++) { | |
char ch = namespace.charAt(i); | |
if (Character.isJavaIdentifierPart(ch)) { | |
validNamespace.append(ch); | |
} else { | |
validNamespace.append('_'); | |
} | |
} | |
return validNamespace.toString(); | |
} | |
public void setTitle(String title) { | |
PortalCallbackService callback = getContainer() | |
.getRequiredContainerServices() | |
.getPortalCallbackService(); | |
callback.setTitle(this.getHttpServletRequest(), | |
getInternalPortletWindow(), | |
title); | |
} | |
public void setContentType(String contentType) | |
throws IllegalArgumentException { | |
ArgumentUtility.validateNotNull("contentType", contentType); | |
String mimeType = StringUtils.getMimeTypeWithoutEncoding(contentType); | |
if (!isValidContentType(mimeType)) { | |
throw new IllegalArgumentException("Specified content type '" | |
+ mimeType + "' is not supported."); | |
} | |
getHttpServletResponse().setContentType(mimeType); | |
this.currentContentType = mimeType; | |
} | |
public String getCharacterEncoding() { | |
return getHttpServletResponse().getCharacterEncoding(); | |
} | |
/** | |
* @see PortletResponseImpl#getOutputStream() | |
* @see #getWriter() | |
*/ | |
public OutputStream getPortletOutputStream() | |
throws IOException, IllegalStateException { | |
if (currentContentType == null) { | |
String message = EXCEPTIONS.getString("error.contenttype.null"); | |
if (LOG.isWarnEnabled()) { | |
LOG.warn("Current content type is not set."); | |
} | |
throw new IllegalStateException(message); | |
} | |
return super.getOutputStream(); | |
} | |
/** | |
* @see PortletResponseImpl#getWriter() | |
* @see #getPortletOutputStream() | |
*/ | |
public PrintWriter getWriter() throws IOException, IllegalStateException { | |
if (currentContentType == null) { | |
String message = EXCEPTIONS.getString("error.contenttype.null"); | |
if (LOG.isWarnEnabled()) { | |
LOG.warn("Current content type is not set."); | |
} | |
throw new IllegalStateException(message); | |
} | |
return super.getWriter(); | |
} | |
public Locale getLocale() { | |
return getHttpServletRequest().getLocale(); | |
} | |
// TODO: port 1.0.1 setBufferSize fix to 1.1 | |
public void setBufferSize(int size) { | |
throw new IllegalStateException( | |
"portlet container does not support buffering"); | |
} | |
public int getBufferSize() { | |
// TODO: return this.getHttpServletResponse().getBufferSize(); | |
return 0; | |
} | |
public void flushBuffer() throws IOException { | |
getHttpServletResponse().flushBuffer(); | |
} | |
public void resetBuffer() { | |
getHttpServletResponse().resetBuffer(); | |
} | |
public boolean isCommitted() { | |
return getHttpServletResponse().isCommitted(); | |
} | |
public void reset() { | |
getHttpServletResponse().reset(); | |
} | |
// InternalRenderResponse Impl --------------------------------------------- | |
public void setIncluded(boolean included) { | |
this.included = included; | |
} | |
public boolean isIncluded() { | |
return included; | |
} | |
// Included HttpServletResponse (Limited) Impl ----------------------------- | |
/** | |
* TODO | |
*/ | |
public String encodeRedirectUrl(String url) { | |
if (included) { | |
return null; | |
} else { | |
return super.encodeRedirectUrl(url); | |
} | |
} | |
/** | |
* TODO | |
*/ | |
public String encodeRedirectURL(String url) { | |
if (included) { | |
return null; | |
} else { | |
return super.encodeRedirectURL(url); | |
} | |
} | |
// Private Methods --------------------------------------------------------- | |
/** | |
* Creates a portlet URL. | |
* TODO: make dynamic? as service? | |
* @param isAction true for an action URL, false for a render URL. | |
* @return the created portlet (action/render) URL. | |
*/ | |
private PortletURL createURL(boolean isAction) { | |
return new PortletURLImpl(getContainer(), | |
getInternalPortletWindow(), | |
getHttpServletRequest(), | |
getHttpServletResponse(), | |
isAction); | |
} | |
/** | |
* Checks if the specified content type is valid (supported by the portlet). | |
* The specified content type should be a tripped mime type without any | |
* character encoding suffix. | |
* @param contentType the content type to check. | |
* @return true if the content type is valid, false otherwise. | |
*/ | |
private boolean isValidContentType(String contentType) { | |
boolean valid = false; | |
PortletDD portletDD = getInternalPortletWindow().getPortletEntity() | |
.getPortletDefinition(); | |
for (Iterator it = portletDD.getSupports().iterator(); | |
!valid && it.hasNext(); ) { | |
SupportsDD supportsDD = (SupportsDD) it.next(); | |
String supportedType = supportsDD.getMimeType(); | |
// Content type is supported by an exact match. | |
if (supportedType.equals(contentType)) { | |
valid = true; | |
} | |
// The supported type contains a wildcard. | |
else if (supportedType.indexOf("*") >= 0) { | |
int index = supportedType.indexOf("/"); | |
String supportedPrefix = supportedType.substring(0, index); | |
String supportedSuffix = supportedType.substring(index + 1); | |
index = contentType.indexOf("/"); | |
String typePrefix = contentType.substring(0, index); | |
String typeSuffix = contentType.substring(index + 1); | |
// Check if the prefixes match AND the suffixes match. | |
if (supportedPrefix.equals("*") || supportedPrefix.equals(typePrefix)) { | |
if (supportedSuffix.equals("*") || supportedSuffix.equals(typeSuffix)) { | |
valid = true; | |
} | |
} | |
} | |
} | |
// Return the check result. | |
return valid; | |
} | |
} |