OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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