HttpFormattedHandler.java
/*
* This file is part of Waarp Project (named also Waarp or GG).
*
* Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
* tags. See the COPYRIGHT.txt in the distribution for a full listing of
* individual contributors.
*
* All Waarp Project is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Waarp 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Waarp . If not, see <http://www.gnu.org/licenses/>.
*/
package org.waarp.openr66.protocol.http;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.cookie.DefaultCookie;
import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
import io.netty.handler.codec.http.cookie.ServerCookieEncoder;
import io.netty.handler.traffic.TrafficCounter;
import org.waarp.common.database.DbAdmin;
import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
import org.waarp.common.database.exception.WaarpDatabaseSqlException;
import org.waarp.common.exception.FileTransferException;
import org.waarp.common.exception.InvalidArgumentException;
import org.waarp.common.logging.SysErrLogger;
import org.waarp.common.logging.WaarpLogger;
import org.waarp.common.logging.WaarpLoggerFactory;
import org.waarp.common.utility.ParametersChecker;
import org.waarp.common.utility.WaarpStringUtils;
import org.waarp.gateway.kernel.http.HttpWriteCacheEnable;
import org.waarp.openr66.context.ErrorCode;
import org.waarp.openr66.context.R66Session;
import org.waarp.openr66.context.task.SpooledInformTask;
import org.waarp.openr66.dao.DAOFactory;
import org.waarp.openr66.dao.Filter;
import org.waarp.openr66.dao.TransferDAO;
import org.waarp.openr66.dao.database.DBTransferDAO;
import org.waarp.openr66.dao.exception.DAOConnectionException;
import org.waarp.openr66.database.data.DbTaskRunner;
import org.waarp.openr66.database.data.DbTaskRunner.TASKSTEP;
import org.waarp.openr66.pojo.Transfer;
import org.waarp.openr66.pojo.UpdatedInfo;
import org.waarp.openr66.protocol.configuration.Configuration;
import org.waarp.openr66.protocol.configuration.Messages;
import org.waarp.openr66.protocol.exception.OpenR66Exception;
import org.waarp.openr66.protocol.exception.OpenR66ExceptionTrappedFactory;
import org.waarp.openr66.protocol.exception.OpenR66ProtocolBusinessNoWriteBackException;
import org.waarp.openr66.protocol.localhandler.LocalChannelReference;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Handler for HTTP information support
*/
public class HttpFormattedHandler
extends SimpleChannelInboundHandler<FullHttpRequest> {
private static final String OPEN_R66_WEB_ERROR = "OpenR66 Web Error {}";
/**
* Internal Logger
*/
private static final WaarpLogger logger =
WaarpLoggerFactory.getLogger(HttpFormattedHandler.class);
private static final String MONITORING_HEADER_HTML = "monitoring_header.html";
private static final String MONITORING_END_HTML = "monitoring_end.html";
private enum REQUEST {
index("index.html"), active(MONITORING_HEADER_HTML, MONITORING_END_HTML),
error(MONITORING_HEADER_HTML, MONITORING_END_HTML),
done(MONITORING_HEADER_HTML, MONITORING_END_HTML),
all(MONITORING_HEADER_HTML, MONITORING_END_HTML),
status(MONITORING_HEADER_HTML, MONITORING_END_HTML), statusxml(""),
statusjson("");
private static final String MONITOR = "monitor/";
private final String header;
private final String end;
/**
* Constructor for a unique file
*
* @param uniquefile
*/
REQUEST(final String uniquefile) {
header = uniquefile;
end = uniquefile;
}
/**
* @param header
* @param end
*/
REQUEST(final String header, final String end) {
this.header = header;
this.end = end;
}
/**
* Reader for a unique file
*
* @return the content of the unique file
*/
public final String readFileUnique(final HttpFormattedHandler handler) {
return handler.readFileHeader(
Configuration.configuration.getHttpBasePath() + MONITOR + header);
}
public final String readHeader(final HttpFormattedHandler handler) {
return handler.readFileHeader(
Configuration.configuration.getHttpBasePath() + MONITOR + header);
}
public final String readEnd() {
return WaarpStringUtils.readFile(
Configuration.configuration.getHttpBasePath() + MONITOR + end);
}
}
protected enum REPLACEMENT {
XXXHOSTIDXXX, XXXLOCACTIVEXXX, XXXNETACTIVEXXX, XXXBANDWIDTHXXX, XXXDATEXXX,
XXXLANGXXX
}
public static final int LIMITROW = 60; // better if it can be divided by 4
private static final String I18NEXT = "i18next";
private final R66Session authentHttp = new R66Session(false);
protected String lang = Messages.getSlocale();
protected FullHttpRequest request;
protected final StringBuilder responseContent = new StringBuilder();
protected HttpResponseStatus status;
protected String uriRequest;
private static final String sINFO = "INFO";
private static final String sNB = "NB";
private static final String sDETAIL = "DETAIL";
protected boolean isCurrentRequestXml;
protected boolean isCurrentRequestJson;
protected Map<String, List<String>> params;
private String readFileHeader(final String filename) {
final String value;
try {
value = WaarpStringUtils.readFileException(filename);
} catch (final FileTransferException e) {
logger.error("Error while trying to read: " + filename, e);
return "";
}
final StringBuilder builder = new StringBuilder(value);
WaarpStringUtils.replace(builder, REPLACEMENT.XXXDATEXXX.toString(),
new Date().toString());
WaarpStringUtils.replace(builder, REPLACEMENT.XXXLOCACTIVEXXX.toString(),
Integer.toString(
Configuration.configuration.getLocalTransaction()
.getNumberLocalChannel()));
WaarpStringUtils.replace(builder, REPLACEMENT.XXXNETACTIVEXXX.toString(),
Integer.toString(DbAdmin.getNbConnection()));
WaarpStringUtils.replace(builder, REPLACEMENT.XXXHOSTIDXXX.toString(),
Configuration.configuration.getHostId());
final TrafficCounter trafficCounter =
Configuration.configuration.getGlobalTrafficShapingHandler()
.trafficCounter();
WaarpStringUtils.replace(builder, REPLACEMENT.XXXBANDWIDTHXXX.toString(),
"IN:" +
trafficCounter.lastReadThroughput() / 131072 +
"Mbits OUT:" +
trafficCounter.lastWriteThroughput() / 131072 +
"Mbits");
WaarpStringUtils.replace(builder, REPLACEMENT.XXXLANGXXX.toString(), lang);
return builder.toString();
}
protected final String getTrimValue(final String varname) {
String value;
try {
value = params.get(varname).get(0).trim();
} catch (final NullPointerException e) {
return null;
}
if (value.isEmpty()) {
value = null;
}
return value;
}
@Override
protected void channelRead0(final ChannelHandlerContext ctx,
final FullHttpRequest msg) {
isCurrentRequestXml = false;
isCurrentRequestJson = false;
status = HttpResponseStatus.OK;
final FullHttpRequest httpRequest = this.request = msg;
QueryStringDecoder queryStringDecoder =
new QueryStringDecoder(httpRequest.uri());
uriRequest = queryStringDecoder.path();
logger.debug("Msg: {}", uriRequest);
if (uriRequest.contains("gre/") || uriRequest.contains("img/") ||
uriRequest.contains("res/") || uriRequest.contains("favicon.ico")) {
HttpWriteCacheEnable.writeFile(httpRequest, ctx,
Configuration.configuration.getHttpBasePath() +
uriRequest, "XYZR66NOSESSION");
return;
}
char cval = 'z';
long nb = LIMITROW;
// check the URI
if ("/active".equalsIgnoreCase(uriRequest)) {
cval = '0';
} else if ("/error".equalsIgnoreCase(uriRequest)) {
cval = '1';
} else if ("/done".equalsIgnoreCase(uriRequest)) {
cval = '2';
} else if ("/all".equalsIgnoreCase(uriRequest)) {
cval = '3';
} else if ("/status".equalsIgnoreCase(uriRequest)) {
cval = '4';
} else if ("/statusxml".equalsIgnoreCase(uriRequest)) {
cval = '5';
nb = 0; // since it could be the default or setup by request
isCurrentRequestXml = true;
} else if (uriRequest.toLowerCase().startsWith("/spooled")) {
cval = '6';
} else if ("/statusjson".equalsIgnoreCase(uriRequest)) {
cval = '7';
nb = 0; // since it could be the default or setup by request
isCurrentRequestJson = true;
}
// Get the params according to get or post
if (httpRequest.method() == HttpMethod.GET) {
params = queryStringDecoder.parameters();
} else if (httpRequest.method() == HttpMethod.POST) {
final ByteBuf content = httpRequest.content();
if (content.isReadable()) {
final String param = content.toString(WaarpStringUtils.UTF8);
queryStringDecoder = new QueryStringDecoder("/?" + param);
} else {
responseContent.append(REQUEST.index.readFileUnique(this));
writeResponse(ctx);
return;
}
params = queryStringDecoder.parameters();
boolean invalidEntry = false;
for (final Entry<String, List<String>> paramCheck : params.entrySet()) {
try {
ParametersChecker.checkSanityString(paramCheck.getValue().toArray(
ParametersChecker.ZERO_ARRAY_STRING));
} catch (final InvalidArgumentException e) {
logger.error(
"Arguments incompatible with Security: " + paramCheck.getKey() +
": {}", e.getMessage());
invalidEntry = true;
}
}
if (invalidEntry) {
for (final Entry<String, List<String>> paramCheck : params.entrySet()) {
paramCheck.getValue().clear();
}
params.clear();
logger.error("No parameter validated since security issue found");
}
}
boolean getMenu = cval == 'z';
boolean extraBoolean = false;
if (!params.isEmpty()) {
// if not uri, from get or post
if (getMenu) {
final String info = getTrimValue(sINFO);
if (info != null) {
getMenu = false;
cval = info.charAt(0);
} else {
getMenu = true;
}
}
// search the nb param
final String snb = getTrimValue(sNB);
if (snb != null) {
try {
nb = Long.parseLong(snb);
} catch (final Exception ignored) {
SysErrLogger.FAKE_LOGGER.ignoreLog(ignored);
}
}
// search the detail param
final String sdetail = getTrimValue(sDETAIL);
if (sdetail != null) {
try {
if (Integer.parseInt(sdetail) > 0) {
extraBoolean = true;
}
} catch (final Exception ignored) {
SysErrLogger.FAKE_LOGGER.ignoreLog(ignored);
}
}
final String langarg = getTrimValue("setLng");
if (ParametersChecker.isNotEmpty(langarg)) {
lang = langarg;
}
}
if (getMenu) {
responseContent.append(REQUEST.index.readFileUnique(this));
} else {
// Use value 0=Active 1=Error 2=Done 3=All
switch (cval) {
case '0':
active(ctx, (int) nb);
break;
case '1':
error(ctx, (int) nb);
break;
case '2':
done(ctx, (int) nb);
break;
case '3':
all(ctx, (int) nb);
break;
case '4':
status(ctx);
break;
case '5':
statusxml(ctx, nb, extraBoolean);
break;
case '6':
String name = null;
if (params.containsKey("name")) {
name = getTrimValue("name");
}
int istatus = 0;
if (params.containsKey("status")) {
final String statusNew = getTrimValue("status");
try {
istatus = Integer.parseInt(statusNew);
} catch (final NumberFormatException e1) {
istatus = 0;
}
}
if (uriRequest.toLowerCase().startsWith("/spooleddetail")) {
extraBoolean = true;
}
spooled(extraBoolean, name, istatus);
break;
case '7':
statusjson(ctx, nb, extraBoolean);
break;
default:
responseContent.append(REQUEST.index.readFileUnique(this));
}
}
writeResponse(ctx);
}
/**
* Add all runners from preparedStatement for type
*
* @param type
* @param nb
*
* @throws WaarpDatabaseNoConnectionException
* @throws WaarpDatabaseSqlException
*/
private void addRunners(final List<Transfer> transfers, final String type,
final int nb) {
responseContent.append(
"<style>td{font-size: 8pt;}</style><table border=\"2\">")
.append("<tr><td>").append(type).append("</td>")
.append(DbTaskRunner.headerHtml()).append("</tr>\r\n");
int i = 0;
for (final Transfer transfer : transfers) {
final DbTaskRunner taskRunner = new DbTaskRunner(transfer);
responseContent.append("<tr><td>")
.append(taskRunner.isSender()? "S" : "R").append("</td>");
final LocalChannelReference lcr =
Configuration.configuration.getLocalTransaction()
.getFromRequest(taskRunner.getKey());
responseContent.append(taskRunner.toHtml(getAuthentHttp(), lcr != null?
Messages.getString("HttpSslHandler.Active") :
Messages.getString("HttpSslHandler.NotActive"))).append("</tr>\r\n");
if (nb > 0) {
i++;
if (i >= nb) {
break;
}
}
}
responseContent.append("</table><br>\r\n");
}
/**
* print all active transfers
*
* @param ctx
* @param nb
*/
private void active(final ChannelHandlerContext ctx, final int nb) {
responseContent.append(REQUEST.active.readHeader(this));
TransferDAO transferAccess = null;
final List<Filter> filters = new ArrayList<Filter>();
List<Transfer> transfers;
try {
transferAccess = DAOFactory.getInstance().getTransferDAO();
// Find Status = RUNNING transfer
filters.add(new Filter(DBTransferDAO.STEP_STATUS_FIELD, "=",
ErrorCode.Running.getCode()));
filters.add(DbTaskRunner.getOwnerFilter());
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb);
addRunners(transfers, ErrorCode.Running.getMesg(), nb);
transfers.clear();
filters.clear();
// Find UpdatedInfo = INTERUPTED transfer
filters.add(new Filter(DBTransferDAO.UPDATED_INFO_FIELD, "=",
UpdatedInfo.INTERRUPTED.ordinal()));
filters.add(DbTaskRunner.getOwnerFilter());
filters.add(new Filter(DBTransferDAO.TRANSFER_START_FIELD, "<",
new Timestamp(System.currentTimeMillis())));
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb);
addRunners(transfers, UpdatedInfo.INTERRUPTED.name(), nb);
transfers.clear();
filters.clear();
// Find UpdatedInfo = TOSUBMIT transfer
filters.add(new Filter(DBTransferDAO.UPDATED_INFO_FIELD, "=",
UpdatedInfo.TOSUBMIT.ordinal()));
filters.add(DbTaskRunner.getOwnerFilter());
filters.add(new Filter(DBTransferDAO.TRANSFER_START_FIELD, "<",
new Timestamp(System.currentTimeMillis())));
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb);
addRunners(transfers, UpdatedInfo.TOSUBMIT.name(), nb);
transfers.clear();
filters.clear();
// Find Status = INITOK transfer
filters.add(new Filter(DBTransferDAO.STEP_STATUS_FIELD, "=",
ErrorCode.InitOk.getCode()));
filters.add(DbTaskRunner.getOwnerFilter());
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb);
addRunners(transfers, ErrorCode.InitOk.getMesg(), nb);
transfers.clear();
filters.clear();
// Find Status = PREPROCESSINGOK transfer
filters.add(new Filter(DBTransferDAO.STEP_STATUS_FIELD, "=",
ErrorCode.PreProcessingOk.getCode()));
filters.add(DbTaskRunner.getOwnerFilter());
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb);
addRunners(transfers, ErrorCode.PreProcessingOk.getMesg(), nb);
transfers.clear();
filters.clear();
// Find Status = TRANSFEROK transfer
filters.add(new Filter(DBTransferDAO.STEP_STATUS_FIELD, "=",
ErrorCode.TransferOk.getCode()));
filters.add(DbTaskRunner.getOwnerFilter());
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb);
addRunners(transfers, ErrorCode.TransferOk.getMesg(), nb);
transfers.clear();
filters.clear();
// Find Status = POSTPROCESSING transfer
filters.add(new Filter(DBTransferDAO.STEP_STATUS_FIELD, "=",
ErrorCode.PostProcessingOk.getCode()));
filters.add(DbTaskRunner.getOwnerFilter());
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb);
addRunners(transfers, ErrorCode.PostProcessingOk.getMesg(), nb);
} catch (final DAOConnectionException e) {
logger.warn(OPEN_R66_WEB_ERROR, e.getMessage());
sendError(ctx, HttpResponseStatus.SERVICE_UNAVAILABLE);
} finally {
DAOFactory.closeDAO(transferAccess);
}
responseContent.append(REQUEST.active.readEnd());
}
/**
* print all transfers in error
*
* @param ctx
* @param nb
*/
private void error(final ChannelHandlerContext ctx, final int nb) {
responseContent.append(REQUEST.error.readHeader(this));
TransferDAO transferAccess = null;
final List<Filter> filters = new ArrayList<Filter>();
List<Transfer> transfers;
try {
transferAccess = DAOFactory.getInstance().getTransferDAO();
// Find UpdatedInfo = INERROR transfer
filters.add(new Filter(DBTransferDAO.UPDATED_INFO_FIELD, "=",
UpdatedInfo.INERROR.ordinal()));
filters.add(DbTaskRunner.getOwnerFilter());
filters.add(new Filter(DBTransferDAO.TRANSFER_START_FIELD, "<",
new Timestamp(System.currentTimeMillis())));
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb / 2);
addRunners(transfers, UpdatedInfo.INERROR.name(), nb / 2);
transfers.clear();
filters.clear();
// Find UpdatedInfo = INTERUPTED transfer
filters.add(new Filter(DBTransferDAO.UPDATED_INFO_FIELD, "=",
UpdatedInfo.INTERRUPTED.ordinal()));
filters.add(DbTaskRunner.getOwnerFilter());
filters.add(new Filter(DBTransferDAO.TRANSFER_START_FIELD, "<",
new Timestamp(System.currentTimeMillis())));
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb / 2);
addRunners(transfers, UpdatedInfo.INTERRUPTED.name(), nb / 2);
transfers.clear();
filters.clear();
// Find GlobalStep = ERRORTASK transfer
filters.add(new Filter(DBTransferDAO.GLOBAL_STEP_FIELD, "=",
Transfer.TASKSTEP.ERRORTASK.ordinal()));
filters.add(DbTaskRunner.getOwnerFilter());
filters.add(new Filter(DBTransferDAO.TRANSFER_START_FIELD, "<",
new Timestamp(System.currentTimeMillis())));
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb / 4);
addRunners(transfers, TASKSTEP.ERRORTASK.name(), nb / 4);
} catch (final DAOConnectionException e) {
logger.warn(OPEN_R66_WEB_ERROR, e.getMessage());
sendError(ctx, HttpResponseStatus.SERVICE_UNAVAILABLE);
return;
} finally {
DAOFactory.closeDAO(transferAccess);
}
responseContent.append(REQUEST.error.readEnd());
}
/**
* Print all done transfers
*
* @param ctx
* @param nb
*/
private void done(final ChannelHandlerContext ctx, final int nb) {
responseContent.append(REQUEST.done.readHeader(this));
TransferDAO transferAccess = null;
final List<Transfer> transfers;
try {
transferAccess = DAOFactory.getInstance().getTransferDAO();
final List<Filter> filters = new ArrayList<Filter>();
filters.add(new Filter(DBTransferDAO.STEP_STATUS_FIELD, "=",
ErrorCode.CompleteOk.getCode()));
filters.add(DbTaskRunner.getOwnerFilter());
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb);
addRunners(transfers, "ALL RUNNERS: " + nb, nb);
} catch (final DAOConnectionException e) {
logger.warn(OPEN_R66_WEB_ERROR, e.getMessage());
sendError(ctx, HttpResponseStatus.SERVICE_UNAVAILABLE);
return;
} finally {
DAOFactory.closeDAO(transferAccess);
}
responseContent.append(REQUEST.done.readEnd());
}
/**
* Print all nb last transfers
*
* @param ctx
* @param nb
*/
private void all(final ChannelHandlerContext ctx, final int nb) {
responseContent.append(REQUEST.all.readHeader(this));
TransferDAO transferAccess = null;
final List<Transfer> transfers;
try {
transferAccess = DAOFactory.getInstance().getTransferDAO();
final List<Filter> filters = new ArrayList<Filter>();
filters.add(DbTaskRunner.getOwnerFilter());
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, nb);
addRunners(transfers, "ALL RUNNERS: " + nb, nb);
} catch (final DAOConnectionException e) {
logger.warn(OPEN_R66_WEB_ERROR, e.getMessage());
sendError(ctx, HttpResponseStatus.SERVICE_UNAVAILABLE);
return;
} finally {
DAOFactory.closeDAO(transferAccess);
}
responseContent.append(REQUEST.all.readEnd());
}
/**
* print only status
*
* @param ctx
*/
private void status(final ChannelHandlerContext ctx) {
responseContent.append(REQUEST.status.readHeader(this));
TransferDAO transferAccess = null;
final List<Filter> filters = new ArrayList<Filter>();
List<Transfer> transfers;
try {
transferAccess = DAOFactory.getInstance().getTransferDAO();
// Find UpdatedInfo = INERROR transfer
filters.add(new Filter(DBTransferDAO.UPDATED_INFO_FIELD, "=",
UpdatedInfo.INERROR.ordinal()));
filters.add(DbTaskRunner.getOwnerFilter());
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, 1);
if (!transfers.isEmpty()) {
responseContent.append("<p>Some Transfers are in ERROR</p><br>");
status = HttpResponseStatus.INTERNAL_SERVER_ERROR;
}
filters.clear();
transfers.clear();
// Find UpdatedInfo = INTERUPTED transfer
filters.add(new Filter(DBTransferDAO.UPDATED_INFO_FIELD, "=",
UpdatedInfo.INTERRUPTED.ordinal()));
filters.add(DbTaskRunner.getOwnerFilter());
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, 1);
if (!transfers.isEmpty()) {
responseContent.append("<p>Some Transfers are INTERRUPTED</p><br>");
status = HttpResponseStatus.INTERNAL_SERVER_ERROR;
}
filters.clear();
transfers.clear();
// Find GLOBAL_STEP = Error transfer
filters.add(new Filter(DBTransferDAO.GLOBAL_STEP_FIELD, "=",
Transfer.TASKSTEP.ERRORTASK.ordinal()));
filters.add(DbTaskRunner.getOwnerFilter());
transfers =
transferAccess.find(filters, DBTransferDAO.TRANSFER_START_FIELD,
false, 1);
if (!transfers.isEmpty()) {
responseContent.append("<p>Some Transfers are in ERRORTASK</p><br>");
status = HttpResponseStatus.INTERNAL_SERVER_ERROR;
}
} catch (final DAOConnectionException e) {
logger.warn(OPEN_R66_WEB_ERROR, e.getMessage());
sendError(ctx, HttpResponseStatus.SERVICE_UNAVAILABLE);
return;
} finally {
DAOFactory.closeDAO(transferAccess);
}
if (status != HttpResponseStatus.INTERNAL_SERVER_ERROR) {
responseContent.append("<p>No problem is found in Transfers</p><br>");
}
responseContent.append(REQUEST.status.readEnd());
}
/**
* print only status
*
* @param ctx
* @param nb
*/
protected final void statusxml(final ChannelHandlerContext ctx, final long nb,
final boolean detail) {
Configuration.configuration.getMonitoring().run(nb, detail);
responseContent.append(
Configuration.configuration.getMonitoring().exportXml(detail));
}
/**
* print only status
*
* @param ctx
* @param nb
*/
protected final void statusjson(final ChannelHandlerContext ctx,
final long nb, final boolean detail) {
Configuration.configuration.getMonitoring().run(nb, detail);
responseContent.append(
Configuration.configuration.getMonitoring().exportJson(detail));
}
private void spooled(final boolean detail, final String name,
final int istatus) {
responseContent.append(REQUEST.status.readHeader(this)).append(
"<p><table border='0' cellpadding='0' cellspacing='0' >").append(
"<tr style='background-image:url(gre/gresm.png);background-repeat:repeat-x;background-position:left top;'><td class='col_MenuHaut'>")
.append(
"<a data-i18n='menu2.sous-menu4a' href='Spooled.html' style='display:block;width:100%;height:100%;line-height:15px;'>")
.append(
"SPOOLED DIRECTORY no detail</a></td><td></td><td><img src='gre/gre11.png' height='15' width='1' style='border: none; display: block;' alt='' /></td>")
.append(
"<td></td><td class='col_MenuHaut'><a data-i18n='menu2.sous-menu4c' href='Spooled.html?status=-1' style='display:block;width:100%;height:100%;line-height:15px;'>")
.append(
"SPOOLED DIRECTORY no detail KO</a></td><td></td><td><img src='gre/gre11.png' height='15' width='1' style='border: none; display: block;' alt='' /></td>")
.append(
"<td></td><td class='col_MenuHaut'><a data-i18n='menu2.sous-menu4d' href='Spooled.html?status=1' style='display:block;width:100%;height:100%;line-height:15px;'>")
.append(
"SPOOLED DIRECTORY no detail OK</a></td></tr><tr style='background-image:url(gre/gre11.png);background-repeat:repeat-x;background-position:left top;'>")
.append(
"<td><img src='gre/gre11.png' height='1' width='100%' style='border: none; display: block;' alt='' /></td></tr>")
.append(
"<tr style='background-image:url(gre/gresm.png);background-repeat:repeat-x;background-position:left top;'>")
.append(
"<td class='col_MenuHaut'><a data-i18n='menu2.sous-menu4b' href='SpooledDetailed.html' style='display:block;width:100%;height:100%;line-height:15px;'>")
.append(
"SPOOLED DIRECTORY detailed</a></td><td></td><td><img src='gre/gre11.png' height='15' width='1' style='border: none; display: block;' alt='' /></td>")
.append(
"<td></td><td class='col_MenuHaut'><a data-i18n='menu2.sous-menu4e' href='SpooledDetailed.html?status=-1' style='display:block;width:100%;height:100%;line-height:15px;'>")
.append(
"SPOOLED DIRECTORY detailed KO</a></td><td></td><td><img src='gre/gre11.png' height='15' width='1' style='border: none; display: block;' alt='' /></td>")
.append(
"<td></td><td class='col_MenuHaut'><a data-i18n='menu2.sous-menu4f' href='SpooledDetailed.html?status=1' style='display:block;width:100%;height:100%;line-height:15px;'>")
.append(
"SPOOLED DIRECTORY detailed OK</a></td></tr></table></p>");
String uri;
if (detail) {
uri = "SpooledDetailed.html";
} else {
uri = "Spooled.html";
}
if (ParametersChecker.isNotEmpty(name)) {
// name is specified
uri = request.uri();
if (istatus != 0) {
uri += "&status=" + istatus;
}
responseContent.append(
SpooledInformTask.buildSpooledUniqueTable(uri, name));
} else {
if (istatus != 0) {
uri += "&status=" + istatus;
}
responseContent.append(
SpooledInformTask.buildSpooledTable(detail, istatus, uri));
}
responseContent.append(REQUEST.status.readEnd());
}
/**
* Write the response
*
* @param ctx
*/
protected final void writeResponse(final ChannelHandlerContext ctx) {
// Convert the response content to a ByteBuf.
final ByteBuf buf = Unpooled.copiedBuffer(responseContent.toString(),
WaarpStringUtils.UTF8);
responseContent.setLength(0);
// Decide whether to close the connection or not.
final boolean keepAlive = HttpUtil.isKeepAlive(request);
final boolean close = HttpHeaderValues.CLOSE.contentEqualsIgnoreCase(
request.headers().get(HttpHeaderNames.CONNECTION)) || !keepAlive;
// Build the response object.
final FullHttpResponse response =
new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buf);
response.headers().add(HttpHeaderNames.CONTENT_LENGTH,
response.content().readableBytes());
if (isCurrentRequestXml) {
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/xml");
} else if (isCurrentRequestJson) {
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json");
} else {
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html");
}
if (keepAlive) {
response.headers()
.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
}
if (!close) {
// There's no need to add 'Content-Length' header
// if this is the last response.
response.headers().set(HttpHeaderNames.CONTENT_LENGTH,
String.valueOf(buf.readableBytes()));
}
final String cookieString = request.headers().get(HttpHeaderNames.COOKIE);
if (cookieString != null) {
final Set<Cookie> cookies = ServerCookieDecoder.LAX.decode(cookieString);
boolean i18nextFound = false;
if (!cookies.isEmpty()) {
// Reset the cookies if necessary.
for (final Cookie cookie : cookies) {
if (cookie.name().equalsIgnoreCase(I18NEXT)) {
i18nextFound = true;
cookie.setValue(lang);
response.headers().add(HttpHeaderNames.SET_COOKIE,
ServerCookieEncoder.LAX.encode(cookie));
} else {
response.headers().add(HttpHeaderNames.SET_COOKIE,
ServerCookieEncoder.LAX.encode(cookie));
}
}
if (!i18nextFound) {
final Cookie cookie = new DefaultCookie(I18NEXT, lang);
response.headers().add(HttpHeaderNames.SET_COOKIE,
ServerCookieEncoder.LAX.encode(cookie));
}
}
if (!i18nextFound) {
final Cookie cookie = new DefaultCookie(I18NEXT, lang);
response.headers().add(HttpHeaderNames.SET_COOKIE,
ServerCookieEncoder.LAX.encode(cookie));
}
}
// Write the response.
final ChannelFuture future = ctx.writeAndFlush(response);
// Close the connection after the write operation is done if necessary.
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
/**
* Send an error and close
*
* @param ctx
* @param status
*/
protected final void sendError(final ChannelHandlerContext ctx,
final HttpResponseStatus status) {
responseContent.setLength(0);
responseContent.append(REQUEST.error.readHeader(this))
.append("OpenR66 Web Failure: ").append(status)
.append(REQUEST.error.readEnd());
final ByteBuf buf = Unpooled.copiedBuffer(responseContent.toString(),
WaarpStringUtils.UTF8);
final FullHttpResponse response =
new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buf);
response.headers().add(HttpHeaderNames.CONTENT_LENGTH,
response.content().readableBytes());
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html");
responseContent.setLength(0);
// Close the connection as soon as the error message is sent.
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx,
final Throwable cause) {
final OpenR66Exception exception =
OpenR66ExceptionTrappedFactory.getExceptionFromTrappedException(
ctx.channel(), cause);
if (exception != null) {
if (!(exception instanceof OpenR66ProtocolBusinessNoWriteBackException)) {
if (cause instanceof IOException) {
// Nothing to do
return;
}
logger.warn("Exception in HttpHandler {}", exception.getMessage());
}
if (ctx.channel().isActive()) {
sendError(ctx, HttpResponseStatus.BAD_REQUEST);
}
}
}
@Override
public void channelInactive(final ChannelHandlerContext ctx)
throws Exception {
super.channelInactive(ctx);
logger.debug("Closed");
}
@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
logger.debug("Connected");
getAuthentHttp().getAuth().specialNoSessionAuth(false,
Configuration.configuration.getHostId());
super.channelActive(ctx);
final ChannelGroup group =
Configuration.configuration.getHttpChannelGroup();
if (group != null) {
group.add(ctx.channel());
}
}
/**
* @return the authentHttp
*/
public R66Session getAuthentHttp() {
return authentHttp;
}
}