ServerHandler.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.restv2.dbhandlers;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.cdap.http.HttpResponder;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.waarp.common.json.JsonHandler;
import org.waarp.common.utility.ParametersChecker;
import org.waarp.common.utility.WaarpShutdownHook;
import org.waarp.gateway.kernel.rest.RestConfiguration.CRUD;
import org.waarp.openr66.context.ErrorCode;
import org.waarp.openr66.dao.BusinessDAO;
import org.waarp.openr66.dao.DAOFactory;
import org.waarp.openr66.dao.Filter;
import org.waarp.openr66.dao.HostDAO;
import org.waarp.openr66.dao.RuleDAO;
import org.waarp.openr66.dao.TransferDAO;
import org.waarp.openr66.dao.exception.DAOConnectionException;
import org.waarp.openr66.dao.exception.DAONoDataException;
import org.waarp.openr66.pojo.Business;
import org.waarp.openr66.pojo.Host;
import org.waarp.openr66.pojo.Rule;
import org.waarp.openr66.pojo.Transfer;
import org.waarp.openr66.pojo.UpdatedInfo;
import org.waarp.openr66.protocol.http.restv2.converters.ServerStatusMaker;
import org.waarp.openr66.protocol.http.restv2.errors.RestError;
import org.waarp.openr66.protocol.http.restv2.errors.RestErrorException;
import org.waarp.openr66.protocol.http.restv2.utils.JsonUtils;
import org.waarp.openr66.protocol.http.restv2.utils.RestUtils;
import org.waarp.openr66.protocol.http.restv2.utils.XmlSerializable.Hosts;
import org.waarp.openr66.protocol.http.restv2.utils.XmlSerializable.Rules;
import org.waarp.openr66.protocol.http.restv2.utils.XmlSerializable.Transfers;
import org.waarp.openr66.protocol.http.restv2.utils.XmlUtils;
import org.waarp.openr66.protocol.utils.ChannelUtils;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
import static java.lang.Boolean.*;
import static javax.ws.rs.core.HttpHeaders.*;
import static javax.ws.rs.core.MediaType.*;
import static org.waarp.common.role.RoleDefault.ROLE.*;
import static org.waarp.openr66.dao.database.DBTransferDAO.*;
import static org.waarp.openr66.protocol.configuration.Configuration.*;
import static org.waarp.openr66.protocol.http.rest.HttpRestR66Handler.RESTHANDLERS.*;
import static org.waarp.openr66.protocol.http.restv2.RestConstants.*;
import static org.waarp.openr66.protocol.http.restv2.RestConstants.ExportConfigParams.*;
import static org.waarp.openr66.protocol.http.restv2.RestConstants.GetLogsParams.*;
import static org.waarp.openr66.protocol.http.restv2.RestConstants.GetStatusParams.*;
import static org.waarp.openr66.protocol.http.restv2.RestConstants.ImportConfigParams.*;
import static org.waarp.openr66.protocol.http.restv2.RestConstants.ServerCommandsURI.*;
import static org.waarp.openr66.protocol.http.restv2.errors.RestErrors.*;
/**
* This is the {@link AbstractRestDbHandler} handling all requests made on the
* server commands REST entry
* point.
*/
@Path(SERVER_HANDLER_URI)
public class ServerHandler extends AbstractRestDbHandler {
/**
* Stores the path to the archive directory.
*/
private static final String ARCH_PATH =
configuration.getBaseDirectory() + configuration.getArchivePath();
/**
* Stores the path to the configuration directory.
*/
private static final String CONFIGS_PATH =
configuration.getBaseDirectory() + configuration.getConfigPath();
/**
* Stores a {@link Map} associating each sub-path of the handler to their
* respective CRUD configuration.
*/
private final Map<String, Byte> serverCRUD = new HashMap<String, Byte>();
/**
* Instantiates the handler with the given CRUD configuration array.
*
* @param crud An array of byte containing all the REST CRUD
* configurations.
*/
public ServerHandler(final byte[] crud) {
super((byte) 0);
serverCRUD.put(STATUS_URI, crud[Information.ordinal()]);
serverCRUD.put(DEACTIVATE_URI, crud[Server.ordinal()]);
serverCRUD.put(SHUTDOWN_URI, crud[Server.ordinal()]);
serverCRUD.put(RESTART_URI, crud[Server.ordinal()]);
serverCRUD.put(LOGS_URI, crud[Log.ordinal()]);
serverCRUD.put(CONFIG_URI, crud[Config.ordinal()]);
}
/**
* Checks if the request can be made in consideration to the handler's CRUD
* configuration.
*
* @param request the HttpRequest made to the handler
*
* @return {@code true} if the request is valid, {@code false} if the CRUD
* configuration does not allow this
* request
*/
@Override
public boolean checkCRUD(final HttpRequest request) {
if (request.method().equals(HttpMethod.OPTIONS)) {
return true;
}
final Pattern pattern =
Pattern.compile('(' + SERVER_HANDLER_URI + ")(\\w+)(\\?.+)?");
final Matcher matcher = pattern.matcher(request.uri());
final HttpMethod method = request.method();
final Byte crud;
if (!matcher.find()) {
crud = 0;
} else {
final String subPath = matcher.group(2);
crud = serverCRUD.get(subPath);
}
if (crud == null) {
return false;
} else if (method.equals(HttpMethod.GET)) {
return CRUD.READ.isValid(crud);
} else if (method.equals(HttpMethod.POST)) {
return CRUD.CREATE.isValid(crud);
} else if (method.equals(HttpMethod.DELETE)) {
return CRUD.DELETE.isValid(crud);
} else if (method.equals(HttpMethod.PUT)) {
return CRUD.UPDATE.isValid(crud);
} else {
return false;
}
}
/**
* Get the general status of the server.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request
*/
@Path(STATUS_URI)
@GET
@Consumes(WILDCARD)
@RequiredRole(READONLY)
public final void getStatus(final HttpRequest request,
final HttpResponder responder,
@QueryParam(PERIOD) @DefaultValue("P1DT0H0M0S")
final String periodStr) {
checkSanity(periodStr);
try {
final Period period = Period.parse(periodStr);
final ObjectNode status = ServerStatusMaker.exportAsJson(period);
final String responseText = JsonUtils.nodeToString(status);
responder.sendJson(OK, responseText);
} catch (final IllegalArgumentException e) {
throw new RestErrorException(ILLEGAL_PARAMETER_VALUE(PERIOD, periodStr));
} catch (final UnsupportedOperationException e) {
throw new RestErrorException(ILLEGAL_PARAMETER_VALUE(PERIOD, periodStr));
}
}
/**
* Method called to get a list of all allowed HTTP methods on the
* '/server/status' entry point. The HTTP
* methods are sent as an array in the reply's headers.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request.
*/
@Path(STATUS_URI)
@OPTIONS
@Consumes(WILDCARD)
@RequiredRole(NOACCESS)
public final void status_options(final HttpRequest request,
final HttpResponder responder) {
final HttpHeaders allow = new DefaultHttpHeaders();
final List<HttpMethod> options = new ArrayList<HttpMethod>();
options.add(HttpMethod.GET);
options.add(HttpMethod.OPTIONS);
allow.add(ALLOW, options);
responder.sendStatus(OK, allow);
}
/**
* Deactivates the server so that it doesn't accept any new transfer
* request.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request
*/
@Path(DEACTIVATE_URI)
@PUT
@Consumes(WILDCARD)
@RequiredRole(FULLADMIN)
public final void deactivate(final HttpRequest request,
final HttpResponder responder) {
HostDAO hostDAO = null;
try {
hostDAO = DAO_FACTORY.getHostDAO(false);
final Host host = hostDAO.select(serverName());
host.setActive(!host.isActive());
hostDAO.update(host);
final DefaultHttpHeaders headers = new DefaultHttpHeaders();
headers.add("active", host.isActive());
responder.sendStatus(NO_CONTENT, headers);
} catch (final DAOConnectionException e) {
throw new InternalServerErrorException(e);
} catch (final DAONoDataException e) {
responder.sendStatus(NOT_FOUND);
} finally {
DAOFactory.closeDAO(hostDAO);
}
}
/**
* Shut down the server.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request
*/
@Path(SHUTDOWN_URI)
@PUT
@Consumes(WILDCARD)
@RequiredRole(FULLADMIN)
public final void shutdown(final HttpRequest request,
final HttpResponder responder) {
WaarpShutdownHook.setRestart(false);
ChannelUtils.startShutdown();
responder.sendStatus(NO_CONTENT);
}
/**
* Method called to get a list of all allowed HTTP methods on the
* '/server/shutdown' entry point. The HTTP
* methods are sent as an array in the reply's headers.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request.
*/
@Path(SHUTDOWN_URI)
@OPTIONS
@Consumes(WILDCARD)
@RequiredRole(NOACCESS)
public final void shutdown_options(final HttpRequest request,
final HttpResponder responder) {
final HttpHeaders allow = new DefaultHttpHeaders();
final List<HttpMethod> options = new ArrayList<HttpMethod>();
options.add(HttpMethod.PUT);
options.add(HttpMethod.OPTIONS);
allow.add(ALLOW, options);
responder.sendStatus(OK, allow);
}
/**
* Restart the server.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request
*/
@Path(RESTART_URI)
@PUT
@Consumes(WILDCARD)
@RequiredRole(FULLADMIN)
public final void restart(final HttpRequest request,
final HttpResponder responder) {
WaarpShutdownHook.setRestart(true);
ChannelUtils.startShutdown();
responder.sendStatus(NO_CONTENT);
}
/**
* Export the server logs to a file. Only the entries that satisfy the
* desired filters will be exported.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request
* @param purgeStr states whether to delete exported entries or not
* @param cleanStr states whether to fix the incoherent entries
* @param statusStr only transfers with this status will be
* exported
* @param rule only transfers using this rule will be exported
* @param start lower bound for the date of the transfer
* @param stop upper bound for the date of the transfer
* @param startID lower bound for the transfer's ID
* @param stopID upper bound for the transfer's ID
*/
@Path(LOGS_URI)
@GET
@Consumes(APPLICATION_FORM_URLENCODED)
@RequiredRole(LOGCONTROL)
public final void getLogs(final HttpRequest request,
final HttpResponder responder,
@QueryParam(PURGE) @DefaultValue("false")
final String purgeStr,
@QueryParam(CLEAN) @DefaultValue("false")
final String cleanStr,
@QueryParam(STATUS) @DefaultValue("")
final String statusStr,
@QueryParam(RULE_NAME) @DefaultValue("")
final String rule,
@QueryParam(START) @DefaultValue("")
final String start,
@QueryParam(STOP) @DefaultValue("")
final String stop,
@QueryParam(START_ID) @DefaultValue("")
final String startID,
@QueryParam(STOP_ID) @DefaultValue("")
final String stopID,
@QueryParam(REQUESTED) @DefaultValue("")
final String requester) {
checkSanity(purgeStr, cleanStr, statusStr, rule, start, stop, startID,
stopID, requester);
final List<RestError> errors = new ArrayList<RestError>();
RestUtils.getLocale(request);
final List<Filter> filters = new ArrayList<Filter>();
final String filePath =
ARCH_PATH + File.separator + serverName() + "_export_" +
DateTime.now() + ".xml";
boolean purge = false;
boolean clean = false;
try {
purge = RestUtils.stringToBoolean(purgeStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(PURGE, purgeStr));
}
try {
clean = RestUtils.stringToBoolean(cleanStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(CLEAN, cleanStr));
}
if (ParametersChecker.isNotEmpty(start, stop)) {
try {
filters.add(new Filter(TRANSFER_START_FIELD, Filter.BETWEEN,
DateTime.parse(start), DateTime.parse(stop)));
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(START, start));
errors.add(ILLEGAL_PARAMETER_VALUE(STOP, stop));
}
} else if (ParametersChecker.isNotEmpty(start)) {
try {
final DateTime lowerDate = DateTime.parse(start);
filters.add(new Filter(TRANSFER_START_FIELD, ">=", lowerDate));
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(START, start));
}
} else if (ParametersChecker.isNotEmpty(stop)) {
try {
final DateTime upperDate = DateTime.parse(stop);
filters.add(new Filter(TRANSFER_START_FIELD, "<=", upperDate));
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(STOP, stop));
}
}
if (ParametersChecker.isNotEmpty(startID, stopID)) {
try {
filters.add(
new Filter(ID_FIELD, Filter.BETWEEN, Long.parseLong(startID),
Long.parseLong(stopID)));
} catch (final NumberFormatException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(START_ID, startID));
errors.add(ILLEGAL_PARAMETER_VALUE(STOP_ID, stopID));
}
} else if (ParametersChecker.isNotEmpty(startID)) {
try {
final Long lowerID = Long.parseLong(startID);
filters.add(new Filter(ID_FIELD, ">=", lowerID));
} catch (final NumberFormatException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(START_ID, startID));
}
} else if (ParametersChecker.isNotEmpty(stopID)) {
try {
final Long upperID = Long.parseLong(stopID);
filters.add(new Filter(ID_FIELD, "<=", upperID));
} catch (final NumberFormatException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(STOP_ID, stopID));
}
}
if (!rule.isEmpty()) {
filters.add(new Filter(ID_RULE_FIELD, "=", rule));
}
if (!statusStr.isEmpty()) {
try {
final UpdatedInfo status = UpdatedInfo.valueOf(statusStr);
filters.add(new Filter(UPDATED_INFO_FIELD, "=", status.ordinal()));
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(STATUS, statusStr));
}
}
if (!requester.isEmpty()) {
filters.add(new Filter(REQUESTER_FIELD, "=", requester));
}
if (!errors.isEmpty()) {
throw new RestErrorException(errors);
}
TransferDAO transferDAO = null;
try {
transferDAO = DAO_FACTORY.getTransferDAO();
final Transfers transfers = new Transfers(transferDAO.find(filters));
final int exported = transfers.transfers.size();
XmlUtils.saveObject(transfers, filePath);
int purged = 0;
if (purge) {
for (final Transfer transfer : transfers.transfers) {
transferDAO.delete(transfer);
++purged;
}
}
// Update all UpdatedInfo to DONE
// where GlobalLastStep = ALLDONETASK and status = CompleteOk
if (clean) {
for (final Transfer transfer : transfers.transfers) {
if (transfer.getGlobalStep() == Transfer.TASKSTEP.ALLDONETASK &&
transfer.getInfoStatus() == ErrorCode.CompleteOk) {
transfer.setUpdatedInfo(UpdatedInfo.DONE);
transferDAO.update(transfer);
}
}
}
final ObjectNode responseObject = JsonHandler.createObjectNode();
responseObject.put("filePath", filePath);
responseObject.put("exported", exported);
responseObject.put("purged", purged);
final String responseText = JsonUtils.nodeToString(responseObject);
responder.sendJson(OK, responseText);
} catch (final DAOConnectionException e) {
throw new InternalServerErrorException(e);
} catch (final DAONoDataException e) {
responder.sendStatus(NOT_FOUND);
} finally {
DAOFactory.closeDAO(transferDAO);
}
}
/**
* Exports parts of the current server configuration to multiple XML files,
* depending on the parameters of the
* request.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request
* @param hostStr states whether to export the host database or
* not.
* @param ruleStr states whether to export the rules database or
* not.
* @param businessStr states whether to export the host's business
* or not.
* @param aliasStr states whether to export the host's aliases or
* not.
* @param roleStr states whether to export the host's permission
* database or not.
*/
@Path(CONFIG_URI)
@GET
@Consumes(APPLICATION_FORM_URLENCODED)
@RequiredRole(CONFIGADMIN)
public final void getConfig(final HttpRequest request,
final HttpResponder responder,
@QueryParam(EXPORT_HOSTS) @DefaultValue("false")
final String hostStr,
@QueryParam(EXPORT_RULES) @DefaultValue("false")
final String ruleStr, @QueryParam(EXPORT_BUSINESS)
@DefaultValue("false") final String businessStr,
@QueryParam(EXPORT_ALIASES) @DefaultValue("false")
final String aliasStr,
@QueryParam(EXPORT_ROLES) @DefaultValue("false")
final String roleStr) {
checkSanity(hostStr, ruleStr, businessStr, aliasStr, roleStr);
final List<RestError> errors = new ArrayList<RestError>();
boolean host = false;
boolean rule = false;
boolean business = false;
boolean alias = false;
boolean role = false;
try {
host = RestUtils.stringToBoolean(hostStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(EXPORT_HOSTS, hostStr));
}
try {
rule = RestUtils.stringToBoolean(ruleStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(EXPORT_RULES, ruleStr));
}
try {
business = RestUtils.stringToBoolean(businessStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(EXPORT_BUSINESS, businessStr));
}
try {
alias = RestUtils.stringToBoolean(aliasStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(EXPORT_ALIASES, aliasStr));
}
try {
role = RestUtils.stringToBoolean(roleStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(EXPORT_ROLES, roleStr));
}
if (!errors.isEmpty()) {
throw new RestErrorException(errors);
}
final String hostsFilePath =
CONFIGS_PATH + File.separator + serverName() + "_hosts.xml";
final String rulesFilePath =
CONFIGS_PATH + File.separator + serverName() + "_rules.xml";
final String businessFilePath =
CONFIGS_PATH + File.separator + serverName() + "_business.xml";
final String aliasFilePath =
CONFIGS_PATH + File.separator + serverName() + "_aliases.xml";
final String rolesFilePath =
CONFIGS_PATH + File.separator + serverName() + "_roles.xml";
final ObjectNode responseObject = JsonHandler.createObjectNode();
HostDAO hostDAO = null;
RuleDAO ruleDAO = null;
BusinessDAO businessDAO = null;
try {
if (host) {
hostDAO = DAO_FACTORY.getHostDAO(false);
final List<Host> hostList = hostDAO.getAll();
final Hosts hosts = new Hosts(hostList);
XmlUtils.saveObject(hosts, hostsFilePath);
responseObject.put("fileHost", hostsFilePath);
}
if (rule) {
ruleDAO = DAO_FACTORY.getRuleDAO(false);
final Rules rules = new Rules(ruleDAO.getAll());
XmlUtils.saveObject(rules, rulesFilePath);
responseObject.put("fileRule", rulesFilePath);
}
businessDAO = DAO_FACTORY.getBusinessDAO(true);
final Business businessEntry = businessDAO.select(serverName());
if (business) {
final String businessXML = businessEntry.getBusiness();
XmlUtils.saveXML(businessXML, businessFilePath);
responseObject.put("fileBusiness", businessFilePath);
}
if (alias) {
final String aliasXML = businessEntry.getAliases();
XmlUtils.saveXML(aliasXML, aliasFilePath);
responseObject.put("fileAlias", aliasFilePath);
}
if (role) {
final String rolesXML = businessEntry.getRoles();
XmlUtils.saveXML(rolesXML, rolesFilePath);
responseObject.put("fileRoles", rolesFilePath);
}
final String responseText = JsonUtils.nodeToString(responseObject);
responder.sendJson(OK, responseText);
} catch (final DAOConnectionException e) {
throw new InternalServerErrorException(e);
} catch (final DAONoDataException e) {
responder.sendStatus(NOT_FOUND);
} finally {
DAOFactory.closeDAO(hostDAO);
DAOFactory.closeDAO(ruleDAO);
DAOFactory.closeDAO(businessDAO);
}
}
/**
* Imports different parts of the server configuration from the XML files
* given as parameters of the request.
* These imported values will replace those already present in the
* database.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request
* @param purgeHostStr states if a new host database should be
* imported.
* @param purgeRuleStr states if a new transfer rule database
* should be imported
* @param purgeBusinessStr states if a new business database should
* be imported
* @param purgeAliasStr states if a new alias database should be
* imported
* @param purgeRoleStr states if a new role database should be
* imported
* @param hostFile path to the XML file containing the host database
* to import
* @param ruleFile path to the XML file containing the rule database
* to import
* @param businessFile path to the XML file containing the business
* database to import
* @param aliasFile path to the XML file containing the alias
* database to import
* @param roleFile path to the XML file containing the role database
* to import
*/
@Path(CONFIG_URI)
@PUT
@Consumes(APPLICATION_FORM_URLENCODED)
@RequiredRole(CONFIGADMIN)
public final void setConfig(final HttpRequest request,
final HttpResponder responder,
@QueryParam(PURGE_HOST) @DefaultValue("false")
final String purgeHostStr,
@QueryParam(PURGE_RULE) @DefaultValue("false")
final String purgeRuleStr,
@QueryParam(PURGE_BUSINESS) @DefaultValue("false")
final String purgeBusinessStr,
@QueryParam(PURGE_ALIASES) @DefaultValue("false")
final String purgeAliasStr,
@QueryParam(PURGE_ROLES) @DefaultValue("false")
final String purgeRoleStr,
@QueryParam(HOST_FILE) @DefaultValue("")
final String hostFile,
@QueryParam(RULE_FILE) @DefaultValue("")
final String ruleFile,
@QueryParam(BUSINESS_FILE) @DefaultValue("")
final String businessFile,
@QueryParam(ALIAS_FILE) @DefaultValue("")
final String aliasFile,
@QueryParam(ROLE_FILE) @DefaultValue("")
final String roleFile) {
checkSanity(purgeHostStr, purgeRuleStr, purgeBusinessStr, purgeAliasStr,
purgeRoleStr, hostFile, ruleFile, businessFile, aliasFile,
ruleFile);
final List<RestError> errors = new ArrayList<RestError>();
RestUtils.getLocale(request);
boolean purgeHost = false;
boolean purgeRule = false;
boolean purgeBusiness = false;
boolean purgeAlias = false;
boolean purgeRole = false;
try {
purgeHost = RestUtils.stringToBoolean(purgeHostStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(EXPORT_HOSTS, purgeHostStr));
}
try {
purgeRule = RestUtils.stringToBoolean(purgeRuleStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(EXPORT_RULES, purgeRuleStr));
}
try {
purgeBusiness = RestUtils.stringToBoolean(purgeBusinessStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(EXPORT_BUSINESS, purgeBusinessStr));
}
try {
purgeAlias = RestUtils.stringToBoolean(purgeAliasStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(EXPORT_ALIASES, purgeAliasStr));
}
try {
purgeRole = RestUtils.stringToBoolean(purgeRoleStr);
} catch (final IllegalArgumentException e) {
errors.add(ILLEGAL_PARAMETER_VALUE(EXPORT_ROLES, purgeRoleStr));
}
if (!errors.isEmpty()) {
throw new RestErrorException(errors);
}
HostDAO hostDAO = null;
RuleDAO ruleDAO = null;
BusinessDAO businessDAO = null;
final ObjectNode responseObject = JsonHandler.createObjectNode();
try {
hostDAO = DAO_FACTORY.getHostDAO(false);
final Hosts hosts = XmlUtils.loadObject(hostFile, Hosts.class);
// if a purge is requested, we can add the new entries without
// checking with 'exist' to gain performance
if (purgeHost) {
hostDAO.deleteAll();
for (final Host host : hosts.hosts) {
hostDAO.insert(host);
}
} else {
for (final Host host : hosts.hosts) {
if (hostDAO.exist(host.getHostid())) {
hostDAO.update(host);
} else {
hostDAO.insert(host);
}
}
}
responseObject.put("purgedHost", TRUE.toString());
ruleDAO = DAO_FACTORY.getRuleDAO(false);
final Rules rules = XmlUtils.loadObject(ruleFile, Rules.class);
if (purgeRule) {
ruleDAO.deleteAll();
for (final Rule rule : rules.rules) {
ruleDAO.insert(rule);
}
} else {
for (final Rule rule : rules.rules) {
if (ruleDAO.exist(rule.getName())) {
ruleDAO.update(rule);
} else {
ruleDAO.insert(rule);
}
}
}
responseObject.put("purgedRule", TRUE.toString());
businessDAO = DAO_FACTORY.getBusinessDAO(false);
if (purgeBusiness) {
final Business business = businessDAO.select(serverName());
final String new_business = XmlUtils.loadXML(businessFile);
business.setBusiness(new_business);
businessDAO.update(business);
responseObject.put("purgedBusiness", TRUE.toString());
}
if (purgeAlias) {
final Business business = businessDAO.select(serverName());
business.setAliases(XmlUtils.loadXML(aliasFile));
businessDAO.update(business);
responseObject.put("purgedAlias", TRUE.toString());
}
if (purgeRole) {
final Business business = businessDAO.select(serverName());
business.setRoles(XmlUtils.loadXML(roleFile));
businessDAO.update(business);
responseObject.put("purgedRoles", TRUE.toString());
}
if (errors.isEmpty()) {
responder.sendJson(OK, JsonUtils.nodeToString(responseObject));
} else {
throw new RestErrorException(errors);
}
} catch (final DAOConnectionException e) {
throw new InternalServerErrorException(e);
} catch (final DAONoDataException e) {
responder.sendStatus(NOT_FOUND);
} finally {
DAOFactory.closeDAO(hostDAO);
DAOFactory.closeDAO(ruleDAO);
DAOFactory.closeDAO(businessDAO);
}
}
/**
* Method called to get a list of all allowed HTTP methods on the '/server'
* entry point. The HTTP methods are
* sent as an array in the reply's headers.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request.
*/
@OPTIONS
@Consumes(WILDCARD)
@RequiredRole(NOACCESS)
public final void options(final HttpRequest request,
final HttpResponder responder) {
final HttpHeaders allow = new DefaultHttpHeaders();
allow.add(ALLOW, HttpMethod.OPTIONS);
responder.sendStatus(OK, allow);
}
/**
* Method called to get a list of all allowed HTTP methods on all sub entry
* points of the '/server' entry
* point. The HTTP methods are sent as an array in the reply's headers.
*
* @param request the HttpRequest made on the resource
* @param responder the HttpResponder which sends the reply to the
* request.
*/
@Path("{ep}")
@OPTIONS
@Consumes(WILDCARD)
@RequiredRole(NOACCESS)
public final void command_options(final HttpRequest request,
final HttpResponder responder,
@PathParam("ep") final String ep) {
checkSanity(ep);
final HttpHeaders allow = new DefaultHttpHeaders();
final List<HttpMethod> options = new ArrayList<HttpMethod>();
if (ep.equals(STATUS_URI)) {
options.add(HttpMethod.GET);
} else if (ep.equals(DEACTIVATE_URI)) {
options.add(HttpMethod.PUT);
} else if (ep.equals(SHUTDOWN_URI)) {
options.add(HttpMethod.PUT);
} else if (ep.equals(RESTART_URI)) {
options.add(HttpMethod.PUT);
} else if (ep.equals(LOGS_URI)) {
options.add(HttpMethod.GET);
} else if (ep.equals(CONFIG_URI)) {
options.add(HttpMethod.PUT);
} else {
responder.sendStatus(FOUND);
return;
}
options.add(HttpMethod.OPTIONS);
allow.add(ALLOW, options);
responder.sendStatus(OK, allow);
}
}