/*
* Data Hub Service (DHuS) - For Space data distribution.
* Copyright (C) 2013,2014,2015,2016 GAEL Systems
*
* This file is part of DHuS software sources.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.gael.dhus.olingo.v1;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.olingo.odata2.api.ODataDebugCallback;
import org.apache.olingo.odata2.api.ODataDebugResponseWrapperCallback;
import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
import org.apache.olingo.odata2.api.ep.EntityProvider;
import org.apache.olingo.odata2.api.exception.ODataApplicationException;
import org.apache.olingo.odata2.api.exception.ODataException;
import org.apache.olingo.odata2.api.processor.ODataContext;
import org.apache.olingo.odata2.api.processor.ODataErrorCallback;
import org.apache.olingo.odata2.api.processor.ODataErrorContext;
import org.apache.olingo.odata2.api.processor.ODataRequest;
import org.apache.olingo.odata2.api.processor.ODataResponse;
import org.apache.olingo.odata2.api.uri.UriInfo;
/** This class implements some callbacks to log error, exception and debug messages. */
class ServiceLogger implements ODataDebugCallback,
ODataDebugResponseWrapperCallback, ODataErrorCallback
{
private static final Logger LOGGER = LogManager.getLogger(ServiceLogger.class);
/**
* Enables the debug output in the response when the request has its
* `odata-debug` set to 'json' or 'html'.
*/
@Override
public boolean isDebugEnabled()
{
return true;
}
/**
* Logs the request URIs. Always logs at DEBUG level except when an exception
* occurs. From ODataDebugResponseWrapperCallback.
*/
@Override
public ODataResponse handle(ODataContext ctx, ODataRequest rq,
ODataResponse rsp, UriInfo uri, Exception e)
{
// I do not print the exception here; exceptions are managed by the
// `handleError` method below
try
{
// Always logs at DEBUG level except when an exception occurs
if (e == null || e instanceof ExpectedException)
{
if(e instanceof ExpectedException.MediaRegulationException)
{
LOGGER.warn("Uri {}: {}", ctx.getPathInfo().getRequestUri(), e.getMessage());
}
else
{
LOGGER.debug("Uri {}", ctx.getPathInfo().getRequestUri());
}
}
else
{
LOGGER.error("Uri {}: {}", ctx.getPathInfo().getRequestUri(), e.getMessage(), e);
}
}
catch (ODataException e1)
{
LOGGER.fatal("An exception occured while logging an ODataResponse", e1);
}
return rsp;
}
/**
* Handle an error with adding the error message in the stream thanks to
* {@link EntityProvider#writeErrorDocument(ODataErrorContext)} method, but
* when the response stream is not identified as binary stream (uri contains
* $value), no ascii message is inserted into the stream.
*/
@Override
public ODataResponse handleError(ODataErrorContext ctx) throws ODataApplicationException
{
// Compute the error message
String message = ctx.getMessage();
if (ctx.getException() != null)
{
message = ctx.getException().getClass().getSimpleName();
if (ctx.getException().getMessage() != null)
{
message += " : " + ctx.getException().getMessage();
}
else if (ctx.getMessage() != null)
{
message += " : " + ctx.getMessage();
}
}
// Suppress in-stream error messages
// ExpectedException are never thrown while streaming the payload
if (ctx.getRequestUri().toString().endsWith("$value")
&& (ctx.getException() == null || ctx.getException() instanceof ExpectedException))
{
return ODataResponse
.header("cause-message", message)
.status(HttpStatusCodes.INTERNAL_SERVER_ERROR)
.build();
}
return ODataResponse
.fromResponse(EntityProvider.writeErrorDocument(ctx))
.header("cause-message", message)
.build();
}
}