ulrich
2018-02-24 9c2c3c7fa694464e8eb16affe9fdca9363ee0b05
commit | author | age
5eee56 1 /*
U 2  *  Radiozentrale - Webradio App
3  *  Copyright (C) 2018 Ulrich Hilger, http://uhilger.de
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see http://www.gnu.org/licenses/
17  */
18
19 package de.uhilger.radiozentrale.web;
20
21 import de.uhilger.baselink.GenericRecord;
22 import de.uhilger.baselink.PersistenceManager;
23 import de.uhilger.baselink.Record;
24 import de.uhilger.radiozentrale.daten.Abspieler;
25 import de.uhilger.radiozentrale.daten.Sender;
26 import java.io.BufferedReader;
27 import java.io.File;
28 import java.io.FileInputStream;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.InputStreamReader;
32 import java.util.List;
33 import java.util.Properties;
34 import java.util.logging.Level;
35 import java.util.logging.Logger;
36 import javax.servlet.ServletContext;
37 import javax.servlet.ServletContextEvent;
38 import javax.servlet.ServletContextListener;
39
40 /**
9c2c3c 41  * Initialisierungsklasse der Anwendung radiozentrale
5eee56 42  * 
U 43  * Hier wird u.a. geprüft, ob die Datenbank vorhanden ist und diese 
44  * angelegt, falls nicht. Das SQL-Skript zur Anlage der Datenbank findet 
45  * sich in WEB-INF/create_database.sql
46  * 
47  * @author Ulrich Hilger
48  */
49 public class Initialiser implements ServletContextListener {
50   
51   private static final Logger logger = Logger.getLogger(Initialiser.class.getName());
52
53   /** Name der Datei mit dem SQL-Skript zum Erzeugen der Datenbank */
54   private static final String SCRIPT_NAME = "create_database.sql";  
55   /** Name der Datei mit den SQL-Kommandos dieser Anwendung */
56   public static final String SQL_PROPERTIES_NAME = "sql.properties";
57   /** Name des Parameters, unter dem der Name der DataSource im Deployment Descritpor zu finden ist */
58   public static final String P_DSNAME = "dsname";
59   /** Name, unter dem das Properties-Objekt mit den SQL-Befehlen im ServletContext hinterlegt ist */
60   public static final String RZ_SQL_PROPERTIES = "radiozentraleSqlProperties";
61   /** Name, unter dem das Zugriffsobjekt zur Datenbank im ServletContext hinterlegt ist */
62   public static final String RZ_DB = "radiozentraleDb";
63   
64     
65   /** Name des SQL-Befehls zum Pruefen, ob die Datenbank vorhanden ist */
66   public static final String SQL_DB_VORHANDEN = "dbVorhanden";  
67   
68   public static final String MP_SENDER = "senderMapper";
69   public static final String MP_ABSPIELER = "abspielerMapper";
70
71   /**
72    * Diese Webanwendung initialisieren, also z.B. Elemente instantiieren, die
73    * über den Deployment Descritpor veränderlich gehalten sind.
74    * 
75    * @param servletContext  der zur Laufzeit bestehende ServletContext
76    */
77   private void initApp(ServletContext servletContext) {
78     try {
79       initSql(servletContext);
80       initDb(servletContext);
81     } catch (Exception ex) {
82       logger.log(Level.SEVERE, null, ex);
83     }
84   }
85   
86  /**
87    * Ein Eigenschaften-Objekt mit den SQL-Statements initialisieren, 
88    * die von dieser Webanwendung verwendet werden
89    * 
90    * Die SQL-Kommandos werden aus der Datei 
91    * [CatalinaBase]/webapps/[Context]/WEB-INF/sql.properties 
92    * gelesen und als Properties-Objekt unter dem von der Konstante 
93    * SPOT_SQL_PROPERTIES bezeichneten Namen im ServletContext hinterlegt
94    */
95   private void initSql(ServletContext servletContext) {
96     try {
97       File basis = new File(this.getClass().getResource("/").toURI());
98       File sqlFile = new File(basis.getParentFile(), SQL_PROPERTIES_NAME);
99       logger.fine("lese SQL-Eigenschaften von " + sqlFile.getAbsolutePath());
100       Properties sql = new Properties();
101       sql.loadFromXML(new FileInputStream(sqlFile));
102       servletContext.setAttribute(RZ_SQL_PROPERTIES, sql);
103       logger.fine("Abfrage dbVorhanden='" + sql.getProperty(SQL_DB_VORHANDEN) + "'");
104     } catch(Exception ex) {
105       logger.log(Level.SEVERE, ex.getMessage(), ex);
106     }
107   }
108   
109   /* ----------------- Logik zur Datenbank-Erzeugung ------------ */
110   
111   /*
112     Die Logik zur Datenbank-Erzeugung benoetigt zwei Parameter: 
113       1. den Namen der DataSource
114       2. einen SQL-Befehl, mit dem geprueft werden kann, ob die 
115           Datenbank vorhanden ist
116   
117     Der Name der DataSource ist im Deployment Descriptor unter dem mit 
118     P_DSNAME bezeichneten Namen hinterlegt, der SQL-Befehl ist 
119     im Properties-Objekt mit den SQL-Befehlen dieser Anwendung unter dem 
120     mit SQL_DB_VORHANDEN bezeichneten Namen zu finden.
121   */
122   
123   /**
124    * Pruefen, ob die von dieser Webanwendung benoetigte Datenbank 
125    * vorhanden ist. Erzeugen der Datenbank, wenn sie nicht vorgefunden 
126    * wird.
127    * 
128    * @param servletContext der ServletContext dieser Webanwendung, in dem 
129    * die Parameter zu finden sind, welche die Datenbankverbindung beschreiben
130    */
131   private void initDb(ServletContext servletContext) {
132     try {
133       PersistenceManager db = new PersistenceManager();
134       db.setDataSourceName(servletContext.getInitParameter(P_DSNAME));
135       servletContext.setAttribute(RZ_DB, db);
136       initMapper(servletContext);
137       Properties sql = (Properties) servletContext.getAttribute(RZ_SQL_PROPERTIES);
138       if(!dbVorhanden(db, sql.getProperty(SQL_DB_VORHANDEN))) {
139         logger.info("Datenbank ist nicht vorhanden");
140         int[] ergebnis = db.executeScript(getSqlSkript());
141       }
142     } catch(Exception ex) {
143       logger.log(Level.INFO, ex.getMessage(), ex);
144     }
145   }
146   
147   /**
148    * Mapper erzeugen
149    * @param servletContext der ServletContext dieser Webanwendung
150    */
151   /*
152   TODO: das noch auf on demand anlegen: GenericRecord wird erst angelegt
153    wenn er erstmals benoetigt wird. Ggf. auch einen Mechanismus zum entfernen 
154    laenger nicht benoetigter Mapper hinzufuegen
155   */
156   private void initMapper(ServletContext servletContext) {
157     servletContext.setAttribute(MP_SENDER, new GenericRecord(Sender.class));
158     servletContext.setAttribute(MP_ABSPIELER, new GenericRecord(Abspieler.class));
159   }
160   
161   @SuppressWarnings("rawtypes")
162   private boolean dbVorhanden(PersistenceManager pm, String sql) {
163     boolean istVorhanden = false;
164     List<List<String>> list = pm.select(sql, Record.WITHOUT_BLOBS);
165     if(list != null && list.size() > 1) {
166       istVorhanden = true;
167       logger.fine("Datenbank ist vorhanden");
168     }
169     return istVorhanden;
170   }
171     
172   private String getSqlSkript() throws Exception {
173     File basis = new File(this.getClass().getResource("/").toURI());
174     File skript = new File(basis.getParentFile(), SCRIPT_NAME);
175     return fromStream(new FileInputStream(skript));
176   }
177   
178   private String fromStream(InputStream in) throws IOException
179   {
180     BufferedReader reader = new BufferedReader(new InputStreamReader(in));
181     StringBuilder out = new StringBuilder();
182     String line;
183     while ((line = reader.readLine()) != null) {
184       out.append(line);
185     }
186     return out.toString();
187   }
188
189   /* --- ServletContextListener --- */
190   
191   @Override
192   public void contextInitialized(ServletContextEvent sce) {
193     ServletContext servletContext = sce.getServletContext();
194     initApp(servletContext);
195   }
196
197   @Override
198   public void contextDestroyed(ServletContextEvent sce) {
199     // destroy whatever 
200     ServletContext ctx = sce.getServletContext();
201     ctx.removeAttribute(MP_SENDER);
202     ctx.removeAttribute(MP_ABSPIELER);
203     ctx.removeAttribute(RZ_SQL_PROPERTIES);
204     ctx.removeAttribute(RZ_DB);
205   }
206   
207 }