/**
* Copyright (C) 2015 Orange
* 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 com.francetelecom.clara.cloud.presentation;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.wicket.Session;
import org.apache.wicket.core.request.handler.PageProvider;
import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.Url;
import org.apache.wicket.request.cycle.IRequestCycleListener;
import org.apache.wicket.request.cycle.RequestCycle;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import com.francetelecom.clara.cloud.commons.BusinessException;
import com.francetelecom.clara.cloud.commons.ResourceNotFoundException;
import com.francetelecom.clara.cloud.presentation.tools.WicketSession;
import com.francetelecom.clara.cloud.scalability.ManageStatistics;
import com.francetelecom.clara.cloud.scalability.helper.PaasStats;
/**
* Exception handler to display messages Updated : $LastChangedDate$
*
*/
public class ExecutionHandlerRequestCycle implements IRequestCycleListener {
/**
* logger
*/
private static final transient org.slf4j.Logger logger = LoggerFactory.getLogger(ExecutionHandlerRequestCycle.class);
private ManageStatistics manageStatistics;
private long statsSnapshotId;
private WebPageFactory webPageFactory;
private static Integer lastRequestId = 0;
private static final Integer MAX_VALUE = Integer.MAX_VALUE;
/**
* Key in logback context for connected user SSOID when available
*/
public static final String LOG_KEY_USER = "user_ssoid";
/**
* Key in logback context for connected user name when available
*/
public static final String LOG_KEY_USERNAME = "user_name";
/**
* Key in logback context for connected wicket session ID when available
*/
public static final String LOG_KEY_SESSION = "session";
private static final synchronized Integer nextRequestId() {
logger.trace("lastRequestId = {}", lastRequestId);
lastRequestId = (lastRequestId % MAX_VALUE) + 1;
return lastRequestId;
}
public ExecutionHandlerRequestCycle(WebApplication application, WebPageFactory webPageFactory) {
manageStatistics = ((WicketApplication) application).getManageStatistics();
if (webPageFactory==null) throw new IllegalArgumentException("Invalid value <"+webPageFactory+"> for webPageFactory");
this.webPageFactory = webPageFactory;
}
protected boolean isRequestAMainPage(RequestCycle cycle) {
String requestPage = cycle.getRequest().getContextPath();
return !requestPage.endsWith(".css") && !requestPage.endsWith(".js");
}
/**
* Init of user for wdm-core ActionContext and call parentMethod
*/
@Override
public void onBeginRequest(RequestCycle cycle) {
if (manageStatistics != null && manageStatistics.isStatEnable() && isRequestAMainPage(cycle)) {
statsSnapshotId = manageStatistics.startSnapshot(cycle.getRequest().getUrl().getPath()); // request.getPath());
}
if (cycle.getRequest() != null) {
try {
WicketSession wicketSession = (WicketSession) Session.get();
if (wicketSession.getPaasUser() != null) {
MDC.put(LOG_KEY_USER, wicketSession.getPaasUser().getSsoId().getValue());
MDC.put(LOG_KEY_USERNAME, wicketSession.getPaasUser().getFirstName());
MDC.put(LOG_KEY_SESSION, wicketSession.getId());
}
} catch (Exception e) {
// Ignore it
}
final int requestId = nextRequestId();
logger.trace("Setting MDC-requestId param to {}", requestId);
MDC.put("requestId", requestId + "");
if (cycle.getRequest().getUrl() != null) {
String urlPath = cycle.getRequest().getUrl().getPath();
logger.trace("Setting MDC-page param to {}", urlPath);
MDC.put("page", urlPath);
String url = cycle.getRequest().getUrl().toString();
logger.trace("Setting MDC-url param to {}", url);
MDC.put("url", url);
}
}
}
@Override
public void onEndRequest(RequestCycle cycle) {
logger.trace("Removing MDC-requestId");
MDC.remove("requestId");
logger.trace("Removing MDC-page");
MDC.remove("page");
logger.trace("Removing MDC-page");
MDC.remove("page");
if (manageStatistics != null && manageStatistics.isStatEnable() && isRequestAMainPage(cycle)) {
try {
PaasStats stats = manageStatistics.endSnapShot(statsSnapshotId);
WicketSession session = WicketSession.get();
session.addStats(stats);
} catch (ResourceNotFoundException rnfe) {
logger.error("stats error (url:{}): {}", cycle.getRequest().getUrl(), rnfe.getMessage());
} catch (BusinessException be) {
logger.error("stats error : {}", be.getMessage(), be);
}
}
MDC.remove(LOG_KEY_USER);
MDC.remove(LOG_KEY_USERNAME);
MDC.remove(LOG_KEY_SESSION);
}
@Override
/*
* * This method is executed when an exception is caught by wicket
*/
public IRequestHandler onException(RequestCycle cycle, Exception e) {
logger.error("RunTimeException {}", e);
cleanMDC();
//get the required anemic view to display exception
ExceptionView view = new ExceptionViewFactory(webPageFactory).newView(e);
//create a specific presenter to inject error details into the view
ExceptionPresenter presenter = new ExceptionPresenter(view);
presenter.onException(ExceptionUtils.getRootCause(e));
//return the view with injected error details
return new RenderPageRequestHandler(new PageProvider(view.asPage()));
}
private void cleanMDC() {
logger.trace("Removing MDC-requestId");
MDC.remove("requestId");
logger.trace("Removing MDC-page");
MDC.remove("page");
logger.trace("Removing MDC-url");
MDC.remove("url");
}
@Override
public void onDetach(RequestCycle cycle) {
// To change body of implemented methods use File | Settings | File
// Templates.
}
@Override
public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler) {
// To change body of implemented methods use File | Settings | File
// Templates.
}
@Override
public void onRequestHandlerScheduled(RequestCycle cycle, IRequestHandler handler) {
// To change body of implemented methods use File | Settings | File
// Templates.
}
@Override
public void onExceptionRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler, Exception exception) {
// To change body of implemented methods use File | Settings | File
// Templates.
}
@Override
public void onRequestHandlerExecuted(RequestCycle cycle, IRequestHandler handler) {
// To change body of implemented methods use File | Settings | File
// Templates.
}
@Override
public void onUrlMapped(RequestCycle cycle, IRequestHandler handler, Url url) {
// To change body of implemented methods use File | Settings | File
// Templates.
}
}