ulrich
2016-12-27 7f8a035fd7d290be1c7ba01956097cab466c9200
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package de.uhilger.um;
 
import de.uhilger.baselink.PersistenceManager;
import de.uhilger.baselink.Record;
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;
 
/**
 * Hauptklasse der Anwendung Nutzerverwaltung
 * 
 * Hier wird u.a. geprüft, ob die Datenbank vorhanden ist und diese 
 * angelegt, falls nicht.
 * 
 * @author Ulrich Hilger
 */
public class App implements ServletContextListener {
  
  private static final Logger logger = Logger.getLogger(App.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, unter dem das Properties-Objekt mit den SQL-Befehlen im ServletContext hinterlegt ist */
  public static final String UM_SQL_PROPERTIES = "umSqlProperties";
  /** Name des Parameters, unter dem der Name der DataSource im Deployment Descritpor zu finden ist */
  public static final String P_DSNAME = "dsname";
  
  /** Name des SQL-Befehls zum Pruefen, ob die Datenbank vorhanden ist */
  public static final String SQL_DB_VORHANDEN = "dbVorhanden";  
  
  public static final boolean WITHOUT_BLOBS = false;
 
  
  private static PersistenceManager db;
  private static Properties sql;
  
 /**
   * 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());
      sql = new Properties();
      sql.loadFromXML(new FileInputStream(sqlFile));
      servletContext.setAttribute(UM_SQL_PROPERTIES, sql);
      logger.fine("Abfrage dbVorhanden='" + sql.getProperty(SQL_DB_VORHANDEN) + "'");
    } catch(Exception ex) {
      logger.log(Level.SEVERE, ex.getMessage(), ex);
    }
  }
 
  /* ----------------- statische Getter --------------------- */
  
  /**
   * Das Zugriffsobjekt fuer die Datenbank dieser Webanwendung 
   * ermitteln
   * 
   * @return das Zugriffsobjekt zur Datenbank dieser Webanwendung
   */
  public static PersistenceManager getDatabase() {
    if(db == null) {
      db = new PersistenceManager();
    }
    return db;
  }
  
  /**
   * Ein benanntes SQL-Kommando ermitteln 
   * @param id Name des gewuenschten SQL-Kommandos
   * @return das SQL-Kommando mit der in id angegebenen Bezeichnung 
   */
  public static String getSqlStatement(String id) {
    return sql.getProperty(id);
  }
  
  /* ----------------- 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 {
      db = new PersistenceManager();
      db.setDataSourceName(servletContext.getInitParameter(P_DSNAME));
      Properties sql = (Properties) servletContext.getAttribute(UM_SQL_PROPERTIES);
      if(!dbVorhanden(db, sql.getProperty(SQL_DB_VORHANDEN))) {
        logger.info("Datenbank ist nicht vorhanden");
        int[] ergebnis = db.executeScript(getSqlSkript());
      }
    } catch(Exception ex) {
      logger.log(Level.INFO, ex.getMessage(), ex);
    }
  }
  
  @SuppressWarnings("rawtypes")
  private boolean dbVorhanden(PersistenceManager pm, String sql) {
    boolean istVorhanden = false;
    List<List<String>> list = pm.select(sql, Record.WITHOUT_BLOBS);
    if(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();
    initSql(servletContext);
    initDb(servletContext);
  }
 
  @Override
  public void contextDestroyed(ServletContextEvent sce) {
    // destroy whatever 
  }
  
}