| New file | 
 |  |  | 
 |  |  | /* | 
 |  |  |  *  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); | 
 |  |  |   } | 
 |  |  |    | 
 |  |  | } |