1
2
3
4
5
6
7
8
9
10
11
12 package sk.uniba.euromath.config;
13 import java.io.File;
14 import java.io.IOException;
15 import java.net.MalformedURLException;
16 import java.net.URISyntaxException;
17 import java.net.URL;
18 import java.util.List;
19 import java.util.Locale;
20 import javax.xml.bind.JAXBContext;
21 import javax.xml.bind.JAXBException;
22 import javax.xml.bind.Unmarshaller;
23 import org.eclipse.core.runtime.IStatus;
24 import sk.baka.ikslibs.DOMUtils;
25 import sk.uniba.euromath.Const;
26 import sk.uniba.euromath.EuroMath;
27 import sk.uniba.euromath.config.bind.Config;
28 import sk.uniba.euromath.config.bind.NamespaceType;
29 import sk.uniba.euromath.config.bind.ObjectFactory;
30 import sk.uniba.euromath.config.bind.ResolveType;
31 import sk.uniba.euromath.config.bind.SchemaType;
32 import sk.uniba.euromath.config.bind.StylesheetType;
33 import sk.uniba.euromath.tools.URLDir;
34 /***
35 * <p>
36 * Ensures that the <code>emConfig.xml</code> configuration file is properly
37 * loaded. Before the <code>initInstance()</code>, one of the
38 * <code>setPluginRoot</code> functions must be called to set the root of the
39 * plugin.
40 * </p>
41 * <p>
42 * Implementation note: Error messages must not be localized in order for them
43 * to display always correctly.
44 * </p>
45 * @author Martin Vysny
46 */
47 public final class EuromathConfig {
48 /***
49 * In-memory configuration file, the <code>emConfig.xml</code>.
50 */
51 private static Config config = null;
52 /***
53 * Location of root directory of plugin.
54 */
55 private static URLDir root = null;
56 /***
57 * Returns in-memory representation of <code>emConfig.xml</code>
58 * configuration file.
59 * @return config.
60 */
61 public static Config getConfig() {
62 if (config == null)
63 throw new IllegalStateException(
64 "EuromathConfig.initInstance() was not called.");
65 return config;
66 }
67 /***
68 * Returns URL, determining position of config file.
69 * @return URL denoting EuroMath config file.
70 */
71 public static URL getConfigFile() {
72 try {
73 final URL result = root.resolve(Const.EM_CONFIG_NAME);
74 return result;
75 } catch (Exception e) {
76 e.printStackTrace();
77 throw new IllegalStateException(e.getMessage());
78 }
79 }
80 /***
81 * Returns user-specific config file, or <code>null</code> if user does
82 * not have home directory.
83 * @return File object pointing to user-specific config file.
84 */
85 public static String getUserConfigFileName() {
86 String homeDir = System.getProperty("user.home");
87 if (homeDir == null)
88 return null;
89 if (!homeDir.endsWith(File.separator))
90 homeDir += File.separator;
91 homeDir += "." + Const.EM_CONFIG_NAME;
92 return homeDir;
93 }
94 /***
95 * Returns user-specific config file, or <code>null</code> if the file
96 * does not exist.
97 * @return File object pointing to user-specific config file.
98 */
99 public static File getUserConfigFile() {
100 String fileName = getUserConfigFileName();
101 if (fileName == null)
102 return null;
103 File emConfig = new File(fileName);
104 if (!emConfig.isFile())
105 return null;
106 return emConfig;
107 }
108 /***
109 * Returns directory where the plugin is located.
110 * @return plugin root directory.
111 */
112 public static URLDir getPluginRoot() {
113 return root;
114 }
115 private static URLDir stylesheetLoc = null;
116 private static URLDir schemaLoc = null;
117 private static Locale locale = null;
118 /***
119 * Returns the stylesheet directory location. Valid after the
120 * <code>initInstance()</code> call.
121 * @return absolute path to stylesheet directory.
122 */
123 public static URLDir getStylesheetLoc() {
124 getConfig();
125 return stylesheetLoc;
126 }
127 /***
128 * Returns the schema directory location. Valid after the
129 * <code>initInstance()</code> call.
130 * @return absolute path to schema directory.
131 */
132 public static URLDir getSchemaLoc() {
133 getConfig();
134 return schemaLoc;
135 }
136 /***
137 * Loads the configuration file.
138 * @throws JAXBException if config file is not valid, well formed, etc.
139 * @throws IOException if I/O error occurs.
140 * @throws URISyntaxException if config file contains invalid URIs.
141 */
142 public static synchronized void initInstance() throws JAXBException,
143 IOException, URISyntaxException {
144 if (isInitialized())
145 throw new IllegalStateException("Already initialized.");
146 if (root == null)
147 setPluginRoot();
148 final JAXBContext jc = JAXBContext.newInstance(
149 "sk.uniba.euromath.config.bind", ObjectFactory.class
150 .getClassLoader());
151 final Unmarshaller u = jc.createUnmarshaller();
152
153 config = (Config) u.unmarshal(getConfigFile().openStream());
154 stylesheetLoc = root.resolveDir(config.getLocalCache()
155 .getStylesheetRoot());
156 schemaLoc = root.resolveDir(config.getLocalCache().getSchemaRoot());
157
158 final File userCfg = getUserConfigFile();
159 if (userCfg != null) {
160 final Config userConfig = (Config) u.unmarshal(getUserConfigFile());
161 merge(config, userConfig);
162 } else {
163 EuroMath.log(IStatus.INFO, 0, "User config file does not exist at "
164 + getUserConfigFileName(), null);
165 }
166
167 final String lang = config.getLocale().getLanguage();
168 final String country = config.getLocale().getCountry();
169 locale = (country == null) ? new Locale(lang) : new Locale(lang,
170 country);
171 }
172 /***
173 * Merges two configuration XMLs into the primary configuration files. All
174 * values in the <code>override</code> config overrides values in the
175 * primary config.
176 * @param primaryConfig the primary configuration file, here the merging
177 * result is kept.
178 * @param override merge shall grab all values from this config and places
179 * it into the primary config, overwriting data if necessary.
180 */
181 @SuppressWarnings("unchecked")
182 private static void merge(Config primaryConfig, Config override)
183 throws MalformedURLException, URISyntaxException, JAXBException {
184
185 if (override.getLocale().getLanguage() != null)
186 primaryConfig.getLocale().setLanguage(
187 override.getLocale().getLanguage());
188 if (override.getLocale().getCountry() != null)
189 primaryConfig.getLocale().setCountry(
190 override.getLocale().getCountry());
191
192 if (override.getLocale().getLanguage() != null)
193 primaryConfig.getLocale().setLanguage(
194 override.getLocale().getLanguage());
195 URLDir home = URLDir.create(new File(System.getProperty("user.home")));
196 URLDir schema = home.resolveDir(override.getLocalCache()
197 .getSchemaRoot());
198 URLDir stylesheet = home.resolveDir(override.getLocalCache()
199 .getStylesheetRoot());
200
201 for (ResolveType rt : (List<ResolveType>) override.getLocalCache()
202 .getResolve()) {
203 URLDir target = schema.resolveDir(rt.getValue());
204 rt.setValue(target.toString());
205 ((List<ResolveType>) primaryConfig.getLocalCache().getResolve())
206 .add(0, rt);
207 }
208
209 for (NamespaceType ns : (List<NamespaceType>) override.getNamespaces()
210 .getNamespace()) {
211 NamespaceType nsPrimary = getNamespace(ns.getNamespaceUri(),
212 primaryConfig);
213 if (nsPrimary == null) {
214 nsPrimary = new ObjectFactory().createNamespaceType();
215 nsPrimary.setNamespaceUri(ns.getNamespaceUri());
216 ((List<NamespaceType>) primaryConfig.getNamespaces()
217 .getNamespace()).add(nsPrimary);
218 }
219
220 if (ns.getDesc() != null)
221 nsPrimary.setDesc(ns.getDesc());
222 if (ns.getDefaultPrefix() != null)
223 nsPrimary.setDefaultPrefix(ns.getDefaultPrefix());
224 if (ns.getSchema() != null) {
225 SchemaType st = ns.getSchema();
226 if (st.getEntitiesUrl() != null)
227 st.setEntitiesUrl(schema.resolve(st.getEntitiesUrl())
228 .toString());
229 st.setLocationUrl(schema.resolve(st.getLocationUrl())
230 .toString());
231 nsPrimary.setSchema(st);
232 }
233 for (StylesheetType st : (List<StylesheetType>) ns.getStylesheet()) {
234 st.setLocationUrl(stylesheet.resolve(st.getLocationUrl())
235 .toString());
236 ((List<StylesheetType>) nsPrimary.getStylesheet()).add(0, st);
237 }
238 }
239 }
240 /***
241 * Returns the namespace definition for given namespace URI.
242 * @param namespaceURI the namespace identifier
243 * @return the namespace description object or <code>null</code> if such
244 * namespace is not defined.
245 */
246 public static NamespaceType getNamespace(String namespaceURI) {
247 return getNamespace(namespaceURI, getConfig());
248 }
249 /***
250 * Returns the namespace definition for given namespace URI.
251 * @param namespaceURI the namespace identifier
252 * @param config the config file where to search
253 * @return the namespace description object or <code>null</code> if such
254 * namespace is not defined.
255 */
256 private static NamespaceType getNamespace(String namespaceURI, Config config) {
257 @SuppressWarnings("unchecked")
258 final List<NamespaceType> ns = config.getNamespaces().getNamespace();
259 for (final NamespaceType result : ns) {
260 if (DOMUtils.equalsURI(result.getNamespaceUri(), namespaceURI))
261 return result;
262 }
263 return null;
264 }
265 /***
266 * Sets root of plugin. Should be called before <code>initInstance()</code>,
267 * to set other root than current directory.
268 * @param url address to the root of plugin.
269 */
270 public static void setPluginRoot(URLDir url) {
271 root = url;
272 }
273 /***
274 * Sets root of plugin to current dir.
275 */
276 public static void setPluginRoot() {
277 root = new URLDir();
278 }
279 /***
280 * Checks whether the class has been initialized.
281 * @return <code>true</code> if the config file is parsed and can be
282 * accessed, <code>false</code> if <code>initInstance()</code> was not
283 * yet called.
284 */
285 public static boolean isInitialized() {
286 return config != null;
287 }
288 /***
289 * Returns locale as configured in the config file.
290 * @return locale constructed from the config file.
291 */
292 public static Locale getLocale() {
293 getConfig();
294 return locale;
295 }
296 }