/*
|
* Radiozentrale - Webradio App
|
* Copyright (C) 2018 Ulrich Hilger, http://uhilger.de
|
*
|
* This program 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.
|
*
|
* 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 General Public License for more details.
|
*
|
* You should have received a copy of the GNU General Public License
|
* along with this program. If not, see http://www.gnu.org/licenses/
|
*/
|
|
package de.uhilger.radiozentrale.web;
|
|
import de.uhilger.baselink.GenericRecord;
|
import de.uhilger.baselink.PersistenceManager;
|
import de.uhilger.baselink.Record;
|
import de.uhilger.radiozentrale.daten.Abspieler;
|
import de.uhilger.radiozentrale.daten.Sender;
|
import java.io.BufferedReader;
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.io.InputStreamReader;
|
import java.util.List;
|
import java.util.Properties;
|
import java.util.logging.Level;
|
import java.util.logging.Logger;
|
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContextEvent;
|
import javax.servlet.ServletContextListener;
|
|
/**
|
* Initialisierungsklasse der Anwendung Nutzerverwaltung
|
*
|
* Hier wird u.a. geprüft, ob die Datenbank vorhanden ist und diese
|
* angelegt, falls nicht. Das SQL-Skript zur Anlage der Datenbank findet
|
* sich in WEB-INF/create_database.sql
|
*
|
* @author Ulrich Hilger
|
*/
|
public class Initialiser implements ServletContextListener {
|
|
private static final Logger logger = Logger.getLogger(Initialiser.class.getName());
|
|
/** Name der Datei mit dem SQL-Skript zum Erzeugen der Datenbank */
|
private static final String SCRIPT_NAME = "create_database.sql";
|
/** Name der Datei mit den SQL-Kommandos dieser Anwendung */
|
public static final String SQL_PROPERTIES_NAME = "sql.properties";
|
/** Name des Parameters, unter dem der Name der DataSource im Deployment Descritpor zu finden ist */
|
public static final String P_DSNAME = "dsname";
|
/** Name, unter dem das Properties-Objekt mit den SQL-Befehlen im ServletContext hinterlegt ist */
|
public static final String RZ_SQL_PROPERTIES = "radiozentraleSqlProperties";
|
/** Name, unter dem das Zugriffsobjekt zur Datenbank im ServletContext hinterlegt ist */
|
public static final String RZ_DB = "radiozentraleDb";
|
|
|
/** Name des SQL-Befehls zum Pruefen, ob die Datenbank vorhanden ist */
|
public static final String SQL_DB_VORHANDEN = "dbVorhanden";
|
|
public static final String MP_SENDER = "senderMapper";
|
public static final String MP_ABSPIELER = "abspielerMapper";
|
|
/**
|
* Diese Webanwendung initialisieren, also z.B. Elemente instantiieren, die
|
* über den Deployment Descritpor veränderlich gehalten sind.
|
*
|
* @param servletContext der zur Laufzeit bestehende ServletContext
|
*/
|
private void initApp(ServletContext servletContext) {
|
try {
|
initSql(servletContext);
|
initDb(servletContext);
|
} catch (Exception ex) {
|
logger.log(Level.SEVERE, null, ex);
|
}
|
}
|
|
/**
|
* Ein Eigenschaften-Objekt mit den SQL-Statements initialisieren,
|
* die von dieser Webanwendung verwendet werden
|
*
|
* Die SQL-Kommandos werden aus der Datei
|
* [CatalinaBase]/webapps/[Context]/WEB-INF/sql.properties
|
* gelesen und als Properties-Objekt unter dem von der Konstante
|
* SPOT_SQL_PROPERTIES bezeichneten Namen im ServletContext hinterlegt
|
*/
|
private void initSql(ServletContext servletContext) {
|
try {
|
File basis = new File(this.getClass().getResource("/").toURI());
|
File sqlFile = new File(basis.getParentFile(), SQL_PROPERTIES_NAME);
|
logger.fine("lese SQL-Eigenschaften von " + sqlFile.getAbsolutePath());
|
Properties sql = new Properties();
|
sql.loadFromXML(new FileInputStream(sqlFile));
|
servletContext.setAttribute(RZ_SQL_PROPERTIES, sql);
|
logger.fine("Abfrage dbVorhanden='" + sql.getProperty(SQL_DB_VORHANDEN) + "'");
|
} catch(Exception ex) {
|
logger.log(Level.SEVERE, ex.getMessage(), ex);
|
}
|
}
|
|
/* ----------------- Logik zur Datenbank-Erzeugung ------------ */
|
|
/*
|
Die Logik zur Datenbank-Erzeugung benoetigt zwei Parameter:
|
1. den Namen der DataSource
|
2. einen SQL-Befehl, mit dem geprueft werden kann, ob die
|
Datenbank vorhanden ist
|
|
Der Name der DataSource ist im Deployment Descriptor unter dem mit
|
P_DSNAME bezeichneten Namen hinterlegt, der SQL-Befehl ist
|
im Properties-Objekt mit den SQL-Befehlen dieser Anwendung unter dem
|
mit SQL_DB_VORHANDEN bezeichneten Namen zu finden.
|
*/
|
|
/**
|
* Pruefen, ob die von dieser Webanwendung benoetigte Datenbank
|
* vorhanden ist. Erzeugen der Datenbank, wenn sie nicht vorgefunden
|
* wird.
|
*
|
* @param servletContext der ServletContext dieser Webanwendung, in dem
|
* die Parameter zu finden sind, welche die Datenbankverbindung beschreiben
|
*/
|
private void initDb(ServletContext servletContext) {
|
try {
|
PersistenceManager db = new PersistenceManager();
|
db.setDataSourceName(servletContext.getInitParameter(P_DSNAME));
|
servletContext.setAttribute(RZ_DB, db);
|
initMapper(servletContext);
|
Properties sql = (Properties) servletContext.getAttribute(RZ_SQL_PROPERTIES);
|
if(!dbVorhanden(db, sql.getProperty(SQL_DB_VORHANDEN))) {
|
logger.info("Datenbank ist nicht vorhanden");
|
int[] ergebnis = db.executeScript(getSqlSkript());
|
/*
|
User admin = new User();
|
admin.setId("admin");
|
admin.setPw("admin");
|
admin.setFirstName("admin");
|
admin.setLastName("admin");
|
admin.setEmail("none");
|
UserMgr um = new UserMgr();
|
um.setServletContext(servletContext);
|
um.createUser(admin);
|
*/
|
}
|
} catch(Exception ex) {
|
logger.log(Level.INFO, ex.getMessage(), ex);
|
}
|
}
|
|
/**
|
* Mapper erzeugen
|
* @param servletContext der ServletContext dieser Webanwendung
|
*/
|
/*
|
TODO: das noch auf on demand anlegen: GenericRecord wird erst angelegt
|
wenn er erstmals benoetigt wird. Ggf. auch einen Mechanismus zum entfernen
|
laenger nicht benoetigter Mapper hinzufuegen
|
*/
|
private void initMapper(ServletContext servletContext) {
|
servletContext.setAttribute(MP_SENDER, new GenericRecord(Sender.class));
|
servletContext.setAttribute(MP_ABSPIELER, new GenericRecord(Abspieler.class));
|
}
|
|
@SuppressWarnings("rawtypes")
|
private boolean dbVorhanden(PersistenceManager pm, String sql) {
|
boolean istVorhanden = false;
|
List<List<String>> list = pm.select(sql, Record.WITHOUT_BLOBS);
|
if(list != null && list.size() > 1) {
|
istVorhanden = true;
|
logger.fine("Datenbank ist vorhanden");
|
}
|
return istVorhanden;
|
}
|
|
private String getSqlSkript() throws Exception {
|
File basis = new File(this.getClass().getResource("/").toURI());
|
File skript = new File(basis.getParentFile(), SCRIPT_NAME);
|
return fromStream(new FileInputStream(skript));
|
}
|
|
private String fromStream(InputStream in) throws IOException
|
{
|
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
StringBuilder out = new StringBuilder();
|
String line;
|
while ((line = reader.readLine()) != null) {
|
out.append(line);
|
}
|
return out.toString();
|
}
|
|
/* --- ServletContextListener --- */
|
|
@Override
|
public void contextInitialized(ServletContextEvent sce) {
|
ServletContext servletContext = sce.getServletContext();
|
initApp(servletContext);
|
}
|
|
@Override
|
public void contextDestroyed(ServletContextEvent sce) {
|
// destroy whatever
|
ServletContext ctx = sce.getServletContext();
|
ctx.removeAttribute(MP_SENDER);
|
ctx.removeAttribute(MP_ABSPIELER);
|
ctx.removeAttribute(RZ_SQL_PROPERTIES);
|
ctx.removeAttribute(RZ_DB);
|
}
|
|
}
|