/**
* Copyright 2011 Marco Berri - marcoberri@gmail.com
*
* 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;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Random;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import com.utils.Default;
import com.utils.StringUtil;
import com.utils.VelocityUtil;
/**
* Classe Base estesa dalle varie servlet
*
* @author Marco Berri marcoberri@gmail.com
*/
public class Base extends HttpServlet {
/**
* rimappatura della servlet application per storare dei dati
*/
protected ServletContext application;
/**
* servlet configuration
*/
protected ServletConfig config;
/**
* connessione al dbb
*/
protected Connection conn_url;
/**
* connessione al db delle statistiche
*/
protected Connection conn_stats;
/**
*
*/
protected com.utils.VelocityUtil velocity;
/**
* logger
*/
protected Logger log = null;
/**
* logger per il cron
*/
protected Logger cron_log = null;
/**
* posizione del file di configurazione
*/
protected String path_file_conf = "/WEB-INF/conf.xml";
/**
* Path della web-app
*/
protected String path_app_root;
/**
* Configurazione
*/
protected com.conf.Main conf;
/**
*
*/
public static final String APP_ATT_APP_CONF = "app_conf";
/**
* lof della app
*/
public static final String APP_ATT_CRON_LOG = "cron_log";
/**
* log del cron
*/
public static final String APP_ATT_LOG = "log";
/**
* connessione al db principale
*/
public static final String APP_ATT_CONN_URL = "conn_url";
/**
* connessione al db delle statistiche
*/
public static final String APP_ATT_CONN_STATS = "conn_stats";
/**
*
* @param config
* @throws ServletException
*/
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
super.init(config);
this.application = config.getServletContext();
this.path_app_root = application.getRealPath("/");
velocity = new VelocityUtil();
velocity.init(path_app_root);
if (application.getAttribute(APP_ATT_APP_CONF) == null) {
this.conf = new com.conf.Main(this.path_app_root + this.path_file_conf);
application.setAttribute(APP_ATT_APP_CONF, this.conf);
} else {
this.conf = (com.conf.Main) application.getAttribute(APP_ATT_APP_CONF);
}
//verfico se è da ricaricare il file di conf
if (this.conf.reload_if_changed(this.path_app_root + this.path_file_conf)) {
application.setAttribute(APP_ATT_APP_CONF, this.conf);
}
try {
if (application.getAttribute(APP_ATT_LOG) == null) {
this.log = com.utils.Log4j.getLogger(conf.getLog().getFilename(), this.path_app_root + "/" + conf.getLog().getPath(), conf.getLog().getRolling());
application.setAttribute(APP_ATT_LOG, this.log);
} else {
this.log = (Logger) application.getAttribute(APP_ATT_LOG);
}
if (application.getAttribute(APP_ATT_CRON_LOG) == null) {
this.cron_log = com.utils.Log4j.getLogger(conf.getLogCron().getFilename(), this.path_app_root + "/" + conf.getLogCron().getPath(), conf.getLogCron().getRolling());
application.setAttribute(APP_ATT_CRON_LOG, this.cron_log);
} else {
this.cron_log = (Logger) application.getAttribute(APP_ATT_CRON_LOG);
}
} catch (Exception e) {
System.out.println("Problemi di configurazione per la parte dei log: " + e.getMessage());
}
debug("Conf:" + this.conf);
if (application.getAttribute(APP_ATT_CONN_URL) != null) {
this.conn_url = (Connection) application.getAttribute(APP_ATT_CONN_URL);
}
if (application.getAttribute(APP_ATT_CONN_STATS) != null) {
this.conn_stats = (Connection) application.getAttribute(APP_ATT_CONN_STATS);
}
try {
if (conn_url == null || conn_url.isClosed()) {
Class.forName(conf.getDb().getClazz());
conn_url = DriverManager.getConnection(conf.getDb().getConn());
application.setAttribute(APP_ATT_CONN_URL, conn_url);
}
if (conn_stats == null || conn_stats.isClosed()) {
Class.forName(conf.getStats().getClazz());
conn_stats = DriverManager.getConnection(conf.getStats().getConn());
application.setAttribute("conn_stats", conn_stats);
}
} catch (ClassNotFoundException ex) {
fatal("ClassNotFoundException:" + ex, ex);
} catch (SQLException ex) {
fatal("SQLException:" + ex, ex);
}
try {
for (String q : conf.getDb().getCreate()) {
Statement stat = this.conn_url.createStatement();
stat.executeUpdate(q);
stat.close();
}
for (String q : conf.getStats().getCreate()) {
Statement stat = this.conn_stats.createStatement();
stat.executeUpdate(q);
stat.close();
}
} catch (SQLException ex) {
fatal("SQLException:" + ex, ex);
}
debug("end init - proc: " + Runtime.getRuntime().availableProcessors() + " - tot : " + bytesToMeg(Runtime.getRuntime().totalMemory()) + " - max : " + bytesToMeg(Runtime.getRuntime().maxMemory()) + " - free: " + bytesToMeg(Runtime.getRuntime().freeMemory()));
}
/**
*
*/
protected void close_connection() {
debug("close_connection()");
try {
this.conn_url.close();
this.conn_stats.close();
this.application.removeAttribute("conn_url");
this.application.removeAttribute("conn_stats");
} catch (SQLException ex) {
fatal("SQLException", ex);
}
}
/**
* destroy di tutte le servelt collegate
*/
@Override
public void destroy() {
debug("destroy");
this.close_connection();
this.log.removeAllAppenders();
this.log = null;
application = null;
config = null;
conn_url = null;
path_file_conf = null;
path_app_root = null;
conf = null;
}
/**
*
* @param text
* @param e
*/
protected void debug(String text, Exception e) {
if (this.conf.getLog() == null || !this.conf.getLog().isDebug()) {
return;
}
text = this.getClass().getName() + " - " + (bytesToMeg(Runtime.getRuntime().totalMemory()) - bytesToMeg(Runtime.getRuntime().freeMemory())) + "/" + bytesToMeg(Runtime.getRuntime().totalMemory()) + " - " + text;
if (e == null) {
this.log.debug(text);
} else {
this.log.debug(text, e);
}
}
/**
*
* @param text
*/
protected void debug(String text) {
debug(text, null);
}
/**
*
* @param text
* @param e
*/
protected void fatal(String text, Exception e) {
text = this.getClass().getName() + " - " + (bytesToMeg(Runtime.getRuntime().totalMemory()) - bytesToMeg(Runtime.getRuntime().freeMemory())) + "/" + bytesToMeg(Runtime.getRuntime().totalMemory()) + " - " + text;
if (e == null) {
this.log.fatal(text);
} else {
this.log.fatal(text, e);
}
}
/**
*
* @param text
*/
protected void fatal(String text) {
fatal(text, null);
}
/**
*
* @param id
* @return in base alla chiave richiesta ritorna l'url
*/
protected String getUrlFromMap(String id) {
HashMap<String, String> most_used_url;
//verifico se esiste la mappa con gli ultimi url usati
if (application.getAttribute("most_used_url") == null) {
most_used_url = new HashMap<String, String>();
application.setAttribute("most_used_url", most_used_url);
}
most_used_url = (HashMap<String, String>) application.getAttribute("most_used_url");
return Default.toString(most_used_url.get(id), null);
}
/**
*
* @param id
* @param url
*/
@SuppressWarnings("unchecked")
protected void putUrlIdToMap(String id, String url) {
//devo verificare che la mappa non superi un tot di elementi ed eventualmente segare quelli aggiuntivi.
HashMap<String, String> most_used_url;
//verifico se esiste la mappa con gli ultimi url usati
if (application.getAttribute("most_used_url") == null) {
most_used_url = new HashMap<String, String>();
application.setAttribute("most_used_url", most_used_url);
}
most_used_url = (HashMap<String, String>) application.getAttribute("most_used_url");
if (most_used_url.size() > 1000) {
most_used_url = new HashMap<String, String>();
}
most_used_url.put(id, url);
application.setAttribute("most_used_url", most_used_url);
}
/**
* Genera una stringa casuale di dimensione length
*
* @param length dinmensione della stringa casuale in caratteri
* @return stringa casuale
*/
protected static String randomString(int length) {
Random rnd = new Random();
char[] arr = new char[length];
for (int i = 0; i < length; i++) {
int n = rnd.nextInt(36);
arr[i] = (char) (n < 10 ? '0' + n : 'a' + n - 10);
}
return new String(arr);
}
/**
* salva le statistiche nel db delle statistiche per le visualizzazioni
*
* @param request la request attuale
* @param url_id l'id dell'url
*/
protected void saveStatsSave(HttpServletRequest request, String url_id) {
saveStats("save", request, url_id);
}
/**
* salva le statistiche nel db delle statistiche per le visualizzazioni
*
* @param request la request attuale
* @param url_id l'id dell'url
*/
protected void saveStatsView(HttpServletRequest request, String url_id) {
saveStats("view", request, url_id);
}
/**
*
* @param request
* @param url_id
*/
protected void saveStatsQrcode(HttpServletRequest request, String url_id) {
saveStats("qrcode", request, url_id);
}
/**
*
* @param table
* @param request
* @param url_id
*/
protected void saveStats(String table, HttpServletRequest request, String url_id) {
Statement stat;
try {
stat = this.conn_stats.createStatement();
String header = "";
Enumeration headerNames = request.getHeaderNames();
String X_Forwarded_For = null;
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
if (headerName.equals("X-Forwarded-For")) {
X_Forwarded_For = request.getHeader(headerName);
}
if (!StringUtil.isNullOrEmpty(header)) {
header += "||";
}
header += headerName + "|" + request.getHeader(headerName);
}
header += "||request_remote_addr" + "|" + request.getRemoteAddr();
header += "||request_remote_host" + "|" + request.getRemoteHost();
header += "||request_remote_user" + "|" + request.getRemoteUser();
header += "||request_remote_remote_port" + "|" + request.getRemotePort();
header += "||request_remote_url" + "|" + request.getRemotePort();
//questo è da capire se ha senso
String ip = request.getRemoteAddr();
if (ip.equals("127.0.0.1") && X_Forwarded_For != null) {
header += "||MBURL_request.getRemoteAddr()|" + ip;
ip = X_Forwarded_For;
}
header = header.replaceAll("'", "\"");
stat.executeUpdate("insert into " + table + " (fk_url_id,ip,header) values('" + url_id + "','" + ip + "','" + header + "')");
stat.close();
} catch (SQLException ex) {
fatal("SQLException", ex);
}
}
/**
* verifica la presenza dell'ip nella tabella blacklist
*
* @param ip
* @return boolean
*/
protected boolean isBlackList(String ip) {
if (getIPException(ip)) {
return false;
}
try {
Statement stat = this.conn_url.createStatement();
ResultSet rs = stat.executeQuery("select * from blacklist where url='" + ip + "'");
boolean is_bl = rs.next();
rs.close();
stat.close();
return is_bl;
} catch (SQLException ex) {
fatal("SQLException", ex);
return false;
}
}
/**
* Utility per la conversione da byte a Mega per la visualizzazione sul debug
* @param bytes
* @return long
*/
public static long bytesToMeg(long bytes) {
return bytes / (1024L * 1024L);
}
//da portare nelle conf oppure in un file a parte modificabile a mano.
/**
*
* @param ip
* @return boolean
*/
protected boolean getIPException(String ip) {
if (ip.equals("127.0.0.1")) {
return true;
}
if (ip.equals("localhost")) {
return true;
}
return false;
}
/**
* Verifica che l'ip non sia nullo o presente nella blacklist
*
* @param ip
* @return true|false
*/
protected boolean isIpNullOrSpam(String ip) {
if (com.utils.StringUtil.isNullOrEmpty(ip)) {
fatal("tentativo di spam, remote address is null or Empty");
return true;
}
//verifico che non sia nella blacklist
if (isBlackList(ip)) {
fatal("l'inidirizzo: " + ip + " è presente nella lista di spam");
return true;
}
return false;
}
/**
*
* @param k
* @return
*/
protected boolean isValidHeaderKey(String k) {
HashMap<String, String> key_not_valid = new HashMap<String, String>();
key_not_valid.put("Host", "not valid");
key_not_valid.put("Connection", "not valid");
key_not_valid.put("X-Forwarded-Server", "not valid");
key_not_valid.put("X-Forwarded-Host", "not valid");
key_not_valid.put("X-Forwarded-For", "not valid");
key_not_valid.put("request_remote_addr", "not valid");
key_not_valid.put("request_remote_host", "not valid");
key_not_valid.put("request_remote_user", "not valid");
key_not_valid.put("Via", "not valid");
key_not_valid.put("MBURL_request.getRemoteAddr()", "not valid");
return (key_not_valid.get(k) == null);
}
}