1 /*
2 * db2sa: DB2 Syntax Assistant
3 * Copyright (C) Andres Gomez Casanova
4 *
5 * This file is part of db2sa.
6 *
7 * db2sa is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * db2sa is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, see <http://www.gnu.org/licenses/>.
19 *
20 * Contact:
21 * a n g o c a at y a h o o dot c o m
22 * Cra. 45 No 61 - 31, Bogota, Colombia.
23 *
24 * Author: $LastChangedBy: angoca $:
25 * Date: $LastChangedDate: 2009-07-08 19:56:43 +0200 (Wed, 08 Jul 2009) $:
26 * Revision: $LastChangedRevision: 357 $:
27 * URL: $HeadURL: https://db2sa.svn.sourceforge.net/svnroot/db2sa/branches/db2sa_beta/source-code/src/main/java/name/angoca/db2sa/Configurator.java $:
28 */
29 package name.angoca.db2sa;
30
31 import java.util.Properties;
32
33 import name.angoca.db2sa.messages.Messages;
34 import name.angoca.db2sa.readers.ConfigurationReader;
35 import name.angoca.db2sa.readers.exceptions.AbstractReaderException;
36
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 /**
41 * This class loads the configuration of the application. The implementation is
42 * with a singleton. The name of the configuration file is in a Constant
43 * (DB2SA_CONF_XML = db2sa_conf.xml) <br/>
44 * This class defines all the default values in a set of constants; their names
45 * are in the Constants interface.<br/>
46 * <b>Control Version</b><br />
47 * <ul>
48 * <li>0.0.1 Class creation.</li>
49 * <li>0.1.0 Singleton and get method.</li>
50 * <li>0.1.1 Basic configuration and new values.</li>
51 * <li>0.2.0 Destroy instance and set property.</li>
52 * <li>0.2.1 Warn level when file problem.</li>
53 * <li>0.2.2 Use of constants.</li>
54 * <li>0.2.3 getInstance synchronized.</li>
55 * <li>0.3.0 Remove of circular dependencies.</li>
56 * <li>0.3.1 Include file name in log.</li>
57 * <li>0.3.2 Log the filename.</li>
58 * <li>1.0.0 Moved to version 1.</li>
59 * </ul>
60 *
61 * @author Andres Gomez Casanova <a
62 * href="mailto:a n g o c a at y a h o o dot c o m">(AngocA)</a>
63 * @version 1.0.0 2009-07-19
64 */
65 public final class Configurator {
66
67 /**
68 * Value for the grammar file.
69 */
70 static final String GRAMMAR_FILE_NAME = "grammar.xml"; //$NON-NLS-1$
71 /**
72 * Value for the prompt.
73 */
74 static final String PROMPT = "db2>"; //$NON-NLS-1$
75 /**
76 * Value for the exit.
77 */
78 static final String EXIT = "exit"; //$NON-NLS-1$
79 /**
80 * Property: About token.
81 */
82 static final String ABOUT_TOKEN = "about"; //$NON-NLS-1$
83 /**
84 * Property: Help token.
85 */
86 static final String HELP_TOKEN = "?"; //$NON-NLS-1$
87 /**
88 * Property: Delimiters.
89 */
90 static final String DELIMITERS = " ,()"; //$NON-NLS-1$
91 /**
92 * Logger.
93 */
94 private static final Logger LOGGER = LoggerFactory
95 .getLogger(Configurator.class);
96 /**
97 * Singleton instance.
98 */
99 private static Configurator s_instance;
100
101 /**
102 * Set of properties.
103 */
104 private Properties m_prop;
105
106 /**
107 * Default constructor.
108 */
109 private Configurator() {
110 // Loads the XML properties file in a Properties structure.
111 // Tries to retrieve a filename in the system properties. It's for
112 // unit test.
113 final String fileName = System.getProperty(Constants.DB2SA_CONF_XML);
114 try {
115 if (fileName == null) {
116 if (Configurator.LOGGER.isDebugEnabled()) {
117 Configurator.LOGGER.debug("Properties from: " //$NON-NLS-1$
118 + Constants.DB2SA_CONF_XML);
119 }
120
121 this.loadXMLFile(Constants.DB2SA_CONF_XML);
122
123 } else {
124 if (Configurator.LOGGER.isDebugEnabled()) {
125 Configurator.LOGGER.debug("Properties from: " + fileName); //$NON-NLS-1$
126 }
127 this.loadXMLFile(fileName);
128 }
129 } catch (AbstractReaderException e) {
130 if (fileName == null) {
131 Configurator.LOGGER.warn(Messages.getString("Configurator."//$NON-NLS-1$
132 + "PROBLEM_READING_THE_CONFIGURATION_FILE."//$NON-NLS-1$
133 + "_LOADING_DEFAULT_PROPERTIES"), //$NON-NLS-1$
134 Constants.DB2SA_CONF_XML + " (Default file)"); //$NON-NLS-1$
135 } else {
136 Configurator.LOGGER.warn(Messages.getString("Configurator."//$NON-NLS-1$
137 + "PROBLEM_READING_THE_CONFIGURATION_FILE."//$NON-NLS-1$
138 + "_LOADING_DEFAULT_PROPERTIES"), //$NON-NLS-1$
139 fileName);
140 }
141 Configurator.LOGGER.debug(Messages.getString("Configurator." + //$NON-NLS-1$
142 "FILES_PROBLEM"), e); //$NON-NLS-1$
143
144 this.loadDefaults();
145 }
146
147 // If Debug level then show the properties.
148 if (Configurator.LOGGER.isDebugEnabled()) {
149 this.m_prop.list(System.out);
150 }
151 }
152
153 /**
154 * This is the singleton implementation. This method returns the sole
155 * instance of this class.
156 *
157 * @return The sole instance of the Configurator class.
158 */
159 public static Configurator getInstance() {
160 synchronized (Configurator.LOGGER) {
161 if (Configurator.s_instance == null) {
162 Configurator.s_instance = new Configurator();
163 }
164 }
165 return Configurator.s_instance;
166 }
167
168 /**
169 * Destroys the sole instance. Useful for testing purposes.
170 */
171 public static void destroyInstance() {
172 if (Configurator.s_instance != null) {
173 Configurator.s_instance.m_prop.clear();
174 Configurator.s_instance.m_prop = null;
175 }
176 Configurator.s_instance = null;
177 }
178
179 /**
180 * Defines a set of defaults properties.
181 */
182 private void loadDefaults() {
183 this.m_prop = new Properties();
184 this.m_prop.setProperty(Constants.GRAMMAR_FILE_NAME,
185 Configurator.GRAMMAR_FILE_NAME);
186 this.m_prop.setProperty(Constants.PROMPT, Configurator.PROMPT);
187 this.m_prop.setProperty(Constants.EXIT, Configurator.EXIT);
188 this.m_prop
189 .setProperty(Constants.ABOUT_TOKEN, Configurator.ABOUT_TOKEN);
190 this.m_prop.setProperty(Constants.HELP_TOKEN, Configurator.HELP_TOKEN);
191 this.m_prop.setProperty(Constants.DELIMITERS, Configurator.DELIMITERS);
192 }
193
194 /**
195 * Loads the properties that are in a XML file.
196 *
197 * @param fileName
198 * Name of configuration file.
199 * @throws AbstractReaderException
200 * If there is a problem with the file (when finding or
201 * reading.)
202 */
203 private void loadXMLFile(final String/* ! */fileName)
204 throws AbstractReaderException {
205 this.m_prop = ConfigurationReader.readFile(fileName);
206 }
207
208 /**
209 * Retrieves a property from the load properties.
210 *
211 * @param key
212 * Name of the property to load.
213 * @return Value of the property. Null if there is no value with that name.
214 */
215 public String /* ? */getProperty(final String/* ! */key) {
216 return this.m_prop.getProperty(key);
217 }
218
219 /**
220 * Set a property after the properties file has been read. This is for
221 * testing purposes, because the configuration is not the same for all
222 * cases.
223 *
224 * @param key
225 * Name of the property.
226 * @param value
227 * Value of the property.
228 */
229 public void setProperty(final String /* ! */key, final String /* ! */value) {
230 this.m_prop.setProperty(key, value);
231 }
232 }