package org.ff4j.web.controller;
import static org.ff4j.web.utils.WebUtils.getCookie;
import static org.ff4j.web.utils.WebUtils.getSessionAttribute;
import static org.ff4j.web.utils.WebUtils.setSessionAttribute;
/*
* #%L
* ff4j-sample-web
* %%
* Copyright (C) 2013 - 2016 FF4J
* %%
* 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.
* #L%
*/
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Set;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.ff4j.FF4j;
import org.ff4j.audit.EventQueryDefinition;
import org.ff4j.utils.Util;
import org.ff4j.web.bean.WebConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
/**
* Display view.
*
* @author Cedrick LUNVEN (@clunven)
*/
public abstract class AbstractController {
/** Logger for this class. */
public static final Logger LOGGER = LoggerFactory.getLogger(AbstractController.class);
/** Date format. */
protected static SimpleDateFormat SDF = new SimpleDateFormat("yyyyMMdd-HHmmss");
/** Slot for the date. */
public static final SimpleDateFormat SDFSLOT = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
/** KEY. */
protected static final String KEY_TITLE = "TITLE";
/** FF4J instance. */
protected FF4j ff4j;
/** Template engine. */
protected TemplateEngine templateEngine = null;
/** Success View. */
protected String successView = null;
/**
* Default constructor.
*
* @param ff4j
* current instance of FF4J.
* @param te
* target template engine.
*/
public AbstractController(FF4j ff4j, String view, TemplateEngine te) {
this.ff4j = ff4j;
this.successView = view;
this.templateEngine = te;
}
/**
* Format uptime.
*
* @return
* current runtime
*/
private String getUptime() {
StringBuilder sb = new StringBuilder();
long uptime = System.currentTimeMillis() - ff4j.getStartTime();
long daynumber = uptime / (1000 * 3600 * 24L);
uptime = uptime - daynumber * 1000 * 3600 * 24L;
long hourNumber = uptime / (1000 * 3600L);
uptime = uptime - hourNumber * 1000 * 3600L;
long minutenumber = uptime / (1000 * 60L);
sb.append(daynumber + " days ");
sb.append(hourNumber + " hours ");
sb.append(minutenumber + " min ");
return sb.toString();
}
/**
* Define response Locale (Cookie <-> HttpSession <-> Request)
*
* @param req
* current request.
* @param res
* current response.
*/
private void i18n(HttpServletRequest req, HttpServletResponse res) {
String lang = req.getParameter(WebConstants.LANG);
if (lang != null) {
// Update Request
res.setLocale(new Locale(lang));
// Update Session
setSessionAttribute(req, WebConstants.LANG_ATTRIBUTE, lang);
// Create Cookie
Cookie cookie = new Cookie(WebConstants.LANG_ATTRIBUTE, lang);
cookie.setMaxAge(365 * 24 * 60 * 60); // 1 years
res.addCookie(cookie);
} else {
String langSession = (String) getSessionAttribute(req, WebConstants.LANG_ATTRIBUTE);
if (langSession != null) {
res.setLocale(new Locale(langSession));
} else {
// Not in session, look for cookie if cookie update session
Cookie cookie = getCookie(req, WebConstants.LANG_ATTRIBUTE);
if (cookie != null) {
setSessionAttribute(req, WebConstants.LANG_ATTRIBUTE, cookie.getValue());
res.setLocale(new Locale(cookie.getValue()));
}
}
}
}
/**
* Invoked by dispatcher.
*
* @param req
* current request
* @param res
* current response
* @throws IOException
* error occured.
*/
public void get(HttpServletRequest req, HttpServletResponse res)
throws IOException {
i18n(req, res);
WebContext ctx = new WebContext(req, res, req.getSession().getServletContext(), res.getLocale());
ctx.setVariable("uptime", getUptime());
ctx.setVariable("version", ff4j.getVersion());
// Security
ctx.setVariable("secure", false);
if (getFf4j().getAuthorizationsManager() != null) {
ctx.setVariable("secure", true);
ctx.setVariable("userName", getFf4j().getAuthorizationsManager().getCurrentUserName());
Set < String > permissions = getFf4j().getAuthorizationsManager().getCurrentUserPermissions();
ctx.setVariable("userPermissions", permissions);
// If no role FF4J_CONSOLE_READ => 403
if (!permissions.contains(WebConstants.ROLE_USER)) {
res.setStatus(WebConstants.STATUS_FORBIDDEN);
res.getWriter().println("You cannot access FF4J console, insuffisant permissions");
return;
}
}
try {
get(req, res, ctx);
} catch(Throwable t) {
ctx.setVariable("msgType", "error");
ctx.setVariable("msgInfo", t.getMessage());
}
// Render to view
templateEngine.process(getSuccessView(), ctx, res.getWriter());
}
/**
* Invoked by dispatcher.
*
* @param req
* current request
* @param res
* current response
* @throws IOException
* error occured.
*/
public void post(HttpServletRequest req, HttpServletResponse res)
throws IOException {
WebContext ctx = new WebContext(req, res, req.getSession().getServletContext(), req.getLocale());
ctx.setVariable("uptime", getUptime());
ctx.setVariable("version", ff4j.getVersion());
// Adding attribute to response
try {
post(req, res, ctx);
} catch(Throwable t) {
ctx.setVariable("msgType", "error");
ctx.setVariable("msgInfo", t.getMessage());
}
// Render to view
templateEngine.process(getSuccessView(), ctx, res.getWriter());
}
/**
* Create view from template.
*
* @param req
* current http request
* @param res
* current http response
* @throws IOException
* target error
*/
public abstract void get(HttpServletRequest req, HttpServletResponse res, WebContext ctx)
throws Exception;
/**
* Create view from template.
*
* @param req
* current http request
* @param res
* current http response
* @throws IOException
* target error
*/
public abstract void post(HttpServletRequest req, HttpServletResponse res, WebContext ctx)
throws Exception;
/**
* Check parameter for date.
*
* @param req
* current http request.
* @param param
* parameter name
* @return
* if the param exist and is not null
*/
protected boolean isValidParam(HttpServletRequest req, String param) {
String pValue = req.getParameter(param);
return (Util.hasLength(pValue) && !"null".equals(pValue));
}
/**
* Retrieve time interval for audit events in history by parsing incoming http request.
*
* @param req
* current http request
* @return
* a time intervale startTime - endTime
*/
protected EventQueryDefinition parseQuery(HttpServletRequest req) {
EventQueryDefinition def = new EventQueryDefinition();
try {
if (isValidParam(req, WebConstants.START_DATE)) {
def.setFrom(SDF.parse(req.getParameter(WebConstants.START_DATE)).getTime());
}
if (isValidParam(req, WebConstants.END_DATE)) {
def.setTo(SDF.parse(req.getParameter(WebConstants.END_DATE)).getTime());
}
} catch(ParseException pe) {}
return def;
}
protected EventQueryDefinition buildQuery(HttpServletRequest req) {
EventQueryDefinition edf = new EventQueryDefinition();
try {
Date from = SDFSLOT.parse(req.getParameter("slotfrom"));
Date to = SDFSLOT.parse(req.getParameter("slotto"));
edf = new EventQueryDefinition(from.getTime(), to.getTime());
} catch(ParseException pe) {
// Nothing to raise, use default values.
}
return edf;
}
/**
* Getter accessor for attribute 'ff4j'.
*
* @return
* current value of 'ff4j'
*/
public FF4j getFf4j() {
return ff4j;
}
/**
* Setter accessor for attribute 'ff4j'.
* @param ff4j
* new value for 'ff4j '
*/
public void setFf4j(FF4j ff4j) {
this.ff4j = ff4j;
}
/**
* Getter accessor for attribute 'templateEngine'.
*
* @return
* current value of 'templateEngine'
*/
public TemplateEngine getTemplateEngine() {
return templateEngine;
}
/**
* Setter accessor for attribute 'templateEngine'.
* @param templateEngine
* new value for 'templateEngine '
*/
public void setTemplateEngine(TemplateEngine templateEngine) {
this.templateEngine = templateEngine;
}
/**
* Getter accessor for attribute 'successView'.
*
* @return
* current value of 'successView'
*/
public String getSuccessView() {
return successView;
}
/**
* Setter accessor for attribute 'successView'.
* @param successView
* new value for 'successView '
*/
public void setSuccessView(String successView) {
this.successView = successView;
}
}