/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.resiliency.spi.agent;
import com.liferay.portal.kernel.model.Layout;
import com.liferay.portal.kernel.resiliency.PortalResiliencyException;
import com.liferay.portal.kernel.resiliency.spi.agent.annotation.Direction;
import com.liferay.portal.kernel.servlet.BufferCacheServletResponse;
import com.liferay.portal.kernel.servlet.MetaInfoCacheServletResponse;
import com.liferay.portal.kernel.servlet.MetaInfoCacheServletResponse.MetaData;
import com.liferay.portal.kernel.servlet.ServletResponseUtil;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.PortalUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.util.PropsValues;
import java.io.IOException;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @author Shuyang Zhou
*/
public class SPIAgentResponse extends SPIAgentSerializable {
public SPIAgentResponse(String servletContextName) {
super(servletContextName);
}
public void captureRequestSessionAttributes(HttpServletRequest request) {
distributedRequestAttributes = extractDistributedRequestAttributes(
request, Direction.RESPONSE);
SPIAgentRequest spiAgentRequest = (SPIAgentRequest)request.getAttribute(
WebKeys.SPI_AGENT_REQUEST);
Map<String, Serializable> originalSessionAttributes =
spiAgentRequest.getOriginalSessionAttributes();
Map<String, Serializable> newSessionAttributes =
extractSessionAttributes(request);
Set<String> removedSessionAttributeNames =
originalSessionAttributes.keySet();
removedSessionAttributeNames.removeAll(newSessionAttributes.keySet());
deltaSessionAttributes = new HashMap<>(newSessionAttributes);
for (String removedSessionAttributeName :
removedSessionAttributeNames) {
deltaSessionAttributes.put(removedSessionAttributeName, null);
}
captureThreadLocals();
}
public void captureResponse(
HttpServletRequest request,
BufferCacheServletResponse bufferCacheServletResponse)
throws IOException {
Boolean portalResiliencyAction = (Boolean)request.getAttribute(
WebKeys.PORTAL_RESILIENCY_ACTION);
if (portalResiliencyAction != Boolean.TRUE) {
portalResiliencyResponse = false;
return;
}
portalResiliencyResponse = true;
metaData = bufferCacheServletResponse.getMetaData();
byteData = null;
if (bufferCacheServletResponse.isByteMode()) {
ByteBuffer byteBuffer = bufferCacheServletResponse.getByteBuffer();
if (byteBuffer.remaining() > 0) {
if (byteBuffer.hasArray()) {
byte[] byteArray = byteBuffer.array();
if (byteBuffer.remaining() == byteArray.length) {
byteData = byteArray;
}
}
if (byteData == null) {
byteData = new byte[byteBuffer.remaining()];
byteBuffer.get(byteData);
}
}
}
stringData = null;
if (!bufferCacheServletResponse.isCharMode()) {
return;
}
String content = bufferCacheServletResponse.getString();
if (content.length() == 0) {
return;
}
if (ParamUtil.get(
request, "portalResiliencyPortletShowFooter",
PropsValues.PORTAL_RESILIENCY_PORTLET_SHOW_FOOTER)) {
int index = content.lastIndexOf("</div>");
if (index > 0) {
StringBundler sb = new StringBundler(6);
sb.append(content.substring(0, index));
sb.append("<div class=\"alert alert-info\"><strong>");
sb.append("This portlet is from SPI ");
sb.append(PortalUtil.getPortalLocalPort(false));
sb.append("</strong></div>");
sb.append(content.substring(index));
content = sb.toString();
}
}
stringData = content;
}
public void populate(
HttpServletRequest request, HttpServletResponse response)
throws PortalResiliencyException {
if (exception != null) {
throw new PortalResiliencyException("SPI exception", exception);
}
if (!portalResiliencyResponse) {
return;
}
String typeSettings = (String)distributedRequestAttributes.remove(
WebKeys.SPI_AGENT_LAYOUT_TYPE_SETTINGS);
if (typeSettings != null) {
Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
layout.setTypeSettings(typeSettings);
}
for (Map.Entry<String, Serializable> entry :
distributedRequestAttributes.entrySet()) {
request.setAttribute(entry.getKey(), entry.getValue());
}
HttpSession session = request.getSession();
for (Map.Entry<String, Serializable> entry :
deltaSessionAttributes.entrySet()) {
session.setAttribute(entry.getKey(), entry.getValue());
}
try {
MetaInfoCacheServletResponse.finishResponse(metaData, response);
if (byteData != null) {
ServletResponseUtil.write(response, ByteBuffer.wrap(byteData));
}
if (stringData != null) {
ServletResponseUtil.write(
response, CharBuffer.wrap(stringData));
}
}
catch (IOException ioe) {
throw new PortalResiliencyException(ioe);
}
restoreThreadLocals();
}
public void setException(Exception exception) {
this.exception = exception;
}
protected byte[] byteData;
protected Map<String, Serializable> deltaSessionAttributes;
protected Map<String, Serializable> distributedRequestAttributes;
protected Exception exception;
protected MetaData metaData;
protected boolean portalResiliencyResponse;
protected String stringData;
}