OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 156 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
17 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 /*
15
 * Créé le 18 avr. 2005
16
 */
17
package org.openconcerto.sql;
18
 
94 ilm 19
import org.openconcerto.sql.element.SQLElement;
17 ilm 20
import org.openconcerto.sql.element.SQLElementDirectory;
21
import org.openconcerto.sql.model.DBFileCache;
22
import org.openconcerto.sql.model.DBItemFileCache;
23
import org.openconcerto.sql.model.DBRoot;
24
import org.openconcerto.sql.model.DBStructureItem;
25
import org.openconcerto.sql.model.DBSystemRoot;
80 ilm 26
import org.openconcerto.sql.model.FieldMapper;
17 ilm 27
import org.openconcerto.sql.model.SQLBase;
28
import org.openconcerto.sql.model.SQLFilter;
94 ilm 29
import org.openconcerto.sql.model.SQLRow;
30
import org.openconcerto.sql.model.SQLRowListRSH;
31
import org.openconcerto.sql.model.SQLSelect;
17 ilm 32
import org.openconcerto.sql.model.SQLTable;
94 ilm 33
import org.openconcerto.sql.model.Where;
17 ilm 34
import org.openconcerto.sql.request.SQLFieldTranslator;
142 ilm 35
import org.openconcerto.utils.BaseDirs;
17 ilm 36
import org.openconcerto.utils.FileUtils;
142 ilm 37
import org.openconcerto.utils.StringUtils;
38
 
39
import java.io.File;
40
import java.io.IOException;
41
import java.io.StringReader;
42
import java.util.List;
177 ilm 43
import java.util.Locale;
142 ilm 44
import java.util.concurrent.Executor;
45
import java.util.concurrent.ExecutorService;
46
import java.util.concurrent.Executors;
47
 
48
import javax.xml.parsers.DocumentBuilder;
49
import javax.xml.parsers.DocumentBuilderFactory;
50
import javax.xml.parsers.ParserConfigurationException;
51
 
52
import org.w3c.dom.Document;
53
import org.xml.sax.InputSource;
54
import org.xml.sax.SAXException;
55
 
83 ilm 56
import net.jcip.annotations.GuardedBy;
57
 
17 ilm 58
/**
59
 * Regroupe les objets nécessaires au framework.
60
 *
61
 * @author Sylvain CUAZ
62
 */
63
public abstract class Configuration {
64
 
65
    public static File getDefaultConfDir() {
66
        return new File(System.getProperty("user.home"), ".java/ilm/sql-config/");
67
    }
68
 
144 ilm 69
    @GuardedBy("this")
17 ilm 70
    private static Configuration instance;
71
 
72
    public static SQLFieldTranslator getTranslator(SQLTable t) {
132 ilm 73
        // FIXME : Parametre inutile...
17 ilm 74
        return getInstance().getTranslator();
75
    }
76
 
144 ilm 77
    public synchronized static Configuration getInstance() {
17 ilm 78
        return instance;
79
    }
80
 
81
    public static final void setInstance(Configuration instance) {
144 ilm 82
        setInstance(instance, false);
83
    }
84
 
85
    public static final Configuration setInstance(final Configuration instance, final boolean destroyPrevious) {
86
        final Configuration prev;
87
        synchronized (Configuration.class) {
88
            prev = Configuration.instance;
89
            // don't destroy new instance
90
            if (prev == instance)
91
                return prev;
92
            Configuration.instance = instance;
93
            if (instance != null) {
94
                try {
95
                    instance.migrateToNewDBConfDir();
96
                } catch (IOException e) {
97
                    throw new IllegalStateException("Couldn't migrate");
98
                }
99
            }
142 ilm 100
        }
144 ilm 101
        if (prev != null && destroyPrevious)
102
            prev.destroy();
103
        return prev;
17 ilm 104
    }
105
 
142 ilm 106
    static public final void migrateToNewDir(final File oldDir, final File newDir) throws IOException {
107
        if (oldDir.exists() && !newDir.exists()) {
108
            if (!oldDir.isDirectory())
109
                throw new IOException("Old file isn't a directory : " + oldDir);
110
            FileUtils.mkdir_p(newDir.getParentFile());
111
            final String err = FileUtils.mv(oldDir, newDir);
112
            if (err != null)
113
                throw new IOException("Couldn't migrate from " + oldDir + " : " + err);
114
        }
115
    }
116
 
83 ilm 117
    @GuardedBy("this")
118
    private ExecutorService nonInteractiveSQLExecutor;
63 ilm 119
 
17 ilm 120
    public abstract ShowAs getShowAs();
121
 
122
    public abstract SQLBase getBase();
123
 
124
    public abstract DBRoot getRoot();
125
 
126
    public abstract DBSystemRoot getSystemRoot();
127
 
128
    public abstract SQLFilter getFilter();
129
 
156 ilm 130
    public final SQLFieldTranslator getTranslator() {
131
        return this.getDirectory().getTranslator();
132
    }
17 ilm 133
 
134
    public abstract SQLElementDirectory getDirectory();
135
 
80 ilm 136
    public abstract FieldMapper getFieldMapper();
137
 
17 ilm 138
    public abstract File getWD();
139
 
73 ilm 140
    // abstract :
141
    // - we can't return a default name as we don't know how to localize it
142
    // - avoid that 2 different application share the same name (and perhaps configuration)
143
    public abstract String getAppName();
17 ilm 144
 
73 ilm 145
    /**
146
     * A string that should be unique to an application and this configuration. E.g. allow to store
147
     * different settings for different uses of a same application.
148
     *
149
     * @return a string beginning with {@link #getAppName()}, <code>null</code> if appName is
150
     *         <code>null</code> or empty.
151
     */
17 ilm 152
    public final String getAppID() {
73 ilm 153
        final String appName = this.getAppName();
142 ilm 154
        if (StringUtils.isEmpty(appName))
73 ilm 155
            return null;
142 ilm 156
        final String variant = this.getAppVariant();
157
        if (StringUtils.isEmpty(variant, true))
158
            return appName;
159
        return appName + '-' + variant;
17 ilm 160
    }
161
 
142 ilm 162
    public String getAppVariant() {
163
        return null;
17 ilm 164
    }
165
 
142 ilm 166
    public abstract BaseDirs getBaseDirs();
167
 
168
    public final File getConfDir() {
169
        return getBaseDirs().getPreferencesFolder();
170
    }
171
 
172
    // for migration use
173
    @Deprecated
174
    protected File getOldConfDir() {
17 ilm 175
        return new File(getDefaultConfDir(), this.getAppID());
176
    }
177
 
178
    /**
179
     * A directory to store data depending on this {@link #getRoot() root}.
180
     *
181
     * @return a directory for this root.
182
     */
183
    public final File getConfDirForRoot() {
184
        return getConfDir(getRoot());
185
    }
186
 
142 ilm 187
    public final void migrateToNewDBConfDir() throws IOException {
188
        final File oldFile = getOldDBConfDir();
189
        final File newFile = getDBConfDir();
190
        migrateToNewDir(oldFile, newFile);
17 ilm 191
    }
192
 
142 ilm 193
    // for migration use
194
    private File getOldDBConfDir() {
195
        return new File(getOldConfDir(), "dataDepedent");
196
    }
197
 
198
    // for migration use
199
    @Deprecated
200
    protected final File getOldConfDir(DBStructureItem<?> db) {
201
        return DBItemFileCache.getDescendant(getOldDBConfDir(), DBFileCache.getJDBCAncestorNames(db, true));
202
    }
203
 
204
    private File getDBConfDir() {
205
        return new File(getConfDir(), "dataDependent");
206
    }
207
 
25 ilm 208
    public final File getConfDir(DBStructureItem<?> db) {
142 ilm 209
        return DBItemFileCache.getDescendant(getDBConfDir(), DBFileCache.getJDBCAncestorNames(db, true));
17 ilm 210
    }
211
 
177 ilm 212
    public Locale getLocale() {
213
        return Locale.getDefault();
214
    }
215
 
17 ilm 216
    /**
156 ilm 217
     * Add the directory of <code>o</code> to this.
17 ilm 218
     *
219
     * @param o the configuration to add.
220
     * @return this.
221
     * @see SQLElementDirectory#putAll(SQLElementDirectory)
222
     */
223
    public Configuration add(Configuration o) {
224
        this.getDirectory().putAll(o.getDirectory());
225
        return this;
226
    }
227
 
228
    /**
229
     * Signal that this conf will not be used anymore.
230
     */
83 ilm 231
    public void destroy() {
232
        synchronized (this) {
233
            if (this.nonInteractiveSQLExecutor != null) {
234
                this.nonInteractiveSQLExecutor.shutdown();
235
            }
236
        }
237
    }
63 ilm 238
 
65 ilm 239
    /**
94 ilm 240
     * Get xml value from table FWK_LIST_PREFS for an user and a table.
241
     *
142 ilm 242
     * @param userId - Id of user
243
     * @param idTable - Id of table
244
     *
245
     * @throws IllegalStateException
246
     * @throws IllegalArgumentException
94 ilm 247
     */
142 ilm 248
    public Document getXMLConf(final Number userId, final String idTable) throws IllegalStateException, IllegalArgumentException {
94 ilm 249
        final SQLElement element = this.getDirectory().getElement("FWK_LIST_PREFS");
250
        final SQLTable columnPrefsTable = element.getTable();
251
        final SQLSelect select = new SQLSelect();
252
        select.addSelectStar(columnPrefsTable);
253
        select.setWhere((new Where(columnPrefsTable.getField("ID_USER"), "=", userId)).and(new Where(columnPrefsTable.getField("ID_TABLE"), "=", idTable)));
254
        final List<SQLRow> rqResult = SQLRowListRSH.execute(select);
255
        if (rqResult != null && !rqResult.isEmpty()) {
256
            final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
142 ilm 257
            DocumentBuilder docBuilder;
258
            try {
259
                docBuilder = docFactory.newDocumentBuilder();
260
            } catch (final ParserConfigurationException ex) {
261
                throw new IllegalStateException("Impossible to create new XML document", ex);
262
            }
263
 
264
            try {
265
                return docBuilder.parse(new InputSource(new StringReader(rqResult.get(0).getString("VALUE"))));
266
            } catch (final SAXException ex) {
267
                throw new IllegalArgumentException("Impossible to parse XML from database", ex);
268
            } catch (final IOException ex) {
269
                throw new IllegalStateException("Impossible to read content of database", ex);
270
            }
94 ilm 271
        }
272
        return null;
273
    }
274
 
275
    /**
142 ilm 276
     * Remove XML value from table FWK_LIST_PREFS for an user and a table.
277
     *
278
     * @param userId - Id of user
279
     * @param idTable - Id of table
280
     *
281
     * @throws IllegalStateException
282
     * @throws IllegalArgumentException
283
     */
284
    public void removeXMLConf(final Number userId, final String idTable) throws IllegalStateException, IllegalArgumentException {
285
        final SQLElement element = this.getDirectory().getElement("FWK_LIST_PREFS");
286
        final SQLTable columnPrefsTable = element.getTable();
287
 
288
        this.getRoot().getDBSystemRoot().getDataSource().execute("DELETE FROM " + columnPrefsTable.getSQLName().quote() + " WHERE \"ID_USER\" = " + userId + " AND \"ID_TABLE\" = '" + idTable + "'");
289
    }
290
 
291
    /**
65 ilm 292
     * An executor that should be used for background SQL requests. It can be used to limit the
293
     * concurrent number of database connections (as establishing a connection is expensive and the
294
     * server might have restrictions).
295
     *
296
     * @return a SQL executor.
297
     */
83 ilm 298
    public synchronized final Executor getNonInteractiveSQLExecutor() {
65 ilm 299
        if (this.nonInteractiveSQLExecutor == null) {
300
            this.nonInteractiveSQLExecutor = createNonInteractiveSQLExecutor();
63 ilm 301
        }
65 ilm 302
        return this.nonInteractiveSQLExecutor;
63 ilm 303
    }
304
 
83 ilm 305
    protected ExecutorService createNonInteractiveSQLExecutor() {
63 ilm 306
        return Executors.newFixedThreadPool(2);
307
    }
17 ilm 308
}