source: main/trunk/gli/src/org/greenstone/gatherer/Configuration.java@ 28628

Last change on this file since 28628 was 22340, checked in by sjm84, 14 years ago

Ticket #697: GLI shortcuts to locations that don't exist anymore are no longer loaded upon GLI startup.

  • Property svn:keywords set to Author Date Id Revision
File size: 39.7 KB
Line 
1/**
2 *#########################################################################
3 * Configuration
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer;
38
39import java.awt.*;
40import java.io.*;
41import java.lang.ref.*;
42import java.net.*;
43import java.util.*;
44import javax.swing.*;
45import javax.swing.plaf.*;
46import org.greenstone.gatherer.util.StaticStrings;
47import org.greenstone.gatherer.util.XMLTools;
48import org.w3c.dom.*;
49
50/** This class stores the various configurable settings inside the Gatherer, both during a session, and between sessions in the form of XML. However not all data members are retained during xml serialization. To further improve efficiency, the property-name -> DOM Element pairs are stored in a SoftReferenced Hashtable.
51 * @author John Thompson, Greenstone Digital Library, University of Waikato
52 * @version 2.3
53 */
54public class Configuration
55 extends Hashtable {
56
57 static final public boolean COLLECTION_SPECIFIC = true;
58 static final public boolean GENERAL_SETTING = true;
59
60 static final public int ASSISTANT_MODE = 1;
61 static final public int LIBRARIAN_MODE = 2;
62 static final public int EXPERT_MODE = 3;
63
64 /** The string identifying an argument's name attribute. */
65 static final private String ARGUMENT_NAME = "name";
66 /** The name of the general Gatherer configuration file. */
67 static public String CONFIG_XML = "config.xml";
68 static public String FEDORA_CONFIG_PREFIX = "fedora-";
69
70 /** The name of the root element of the subtree containing gatherer configuration options. This is required as the document itself may contain several other subtrees of settings (such as in the case of a '.col' file). */
71 static final private String GATHERER_CONFIG = "GathererConfig";
72 /** The string identifying an argument element. */
73 static final private String GATHERER_CONFIG_ARGUMENT = "Argument";
74
75 static final private String GENERAL_EMAIL_SETTING = "general.email";
76 /** the lang attribute of the other element */
77 static final private String LANGUAGE = "lang";
78 /** The name of a Name Element. */
79 static final private String NAME = "Name";
80 /** The name of the other arguments element. */
81 static final private String OTHER = "Other";
82 /** The name of the general Gatherer configuration template. */
83 static public String TEMPLATE_CONFIG_XML = "xml/config.xml";
84 /** The first of three patterns used during tokenization, this pattern handles a comma separated list. */
85 static final private String TOKENIZER_PATTERN1 = " ,\n\t";
86 /** The second of three patterns used during tokenization, this pattern handles an underscore separated list. */
87 static final private String TOKENIZER_PATTERN2 = "_\n\t";
88 /** The last of three patterns used during tokenization, this pattern handles an comma separated list containing spaces. */
89 static final private String TOKENIZER_PATTERN3 = ",\n\t";
90
91 static public Configuration self = null;
92 static public String gli_user_directory_path = null;
93
94 static public boolean just_updated_config_xml_file = false;
95 /** The path to the Greenstone Suite installation directory. */
96 static public String gsdl_path = "";
97 /** If we are using GLI in Greenstone 3, the path to gsdl3 home (== web dir) */
98 static public String gsdl3_path = "";
99 /** If we are using GLI in Greenstone 3, the path to gsdl3 src directory (== gsdl3 dir)*/
100 static public String gsdl3_src_path = "";
101
102 static public FedoraInfo fedora_info = null;
103
104 /** The path to the PERL executable, up to and including Perl.exe. */
105 static public String perl_path = "";
106 /** The password for the proxy server indicated above. */
107 static public String proxy_pass = null;
108 /** The username for the proxy server indicated above. */
109 static public String proxy_user = null;
110 /** The screen size of the desktop the Gatherer will be displayed on. */
111 static public Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
112 /** The site name if we are using GS3 */
113 static public String site_name = "";
114 /** The servlet path if we are using GS3 */
115 static public String servlet_path = "";
116 /** Collection level configuration (which in some cases overrides general configuration. */
117 static private Document collection_config;
118 /** The general configuration settings. */
119 static private Document general_config;
120
121 /** The element, from glis config file, that contains the various directory mappings. */
122 static private Element directory_mappings_element;
123
124 static private int cache_hit = 0;
125 static private int cache_miss = 0;
126
127 static public URL gliserver_url = null;
128 static public URL library_url = null;
129
130
131 /** Constructor.
132 * @param gsdl_path The path to the Greenstone directory as a <strong>String</strong>.
133 * @param gsdl3_path The path to the Greenstone 3 home (web) directory as a <strong>String</strong>.
134 * @param gsdl3_src_path The path to the Greenstone 3 src directory as a <strong>String</strong>.
135 * @param site_name The name of the Greenstone 3 site currently in use.
136 * @param fedora_info A FedoraInfo object containing the user-provided details for creating
137 * a connection to a Fedora repository.
138 */
139 public Configuration(String gli_user_directory_path, String gsdl_path, String gsdl3_path, String gsdl3_src_path,
140 String site_name, FedoraInfo fedora_info)
141 {
142 super();
143 self = this; // allows Configuration to statically refer to itself in the static methods
144
145 this.gli_user_directory_path = gli_user_directory_path;
146 this.gsdl_path = gsdl_path;
147 this.gsdl3_path = gsdl3_path;
148 this.gsdl3_src_path = gsdl3_src_path;
149 this.site_name = site_name;
150
151 this.fedora_info = fedora_info;
152
153 // Try to load the configuration file from the user specific location
154 String config_xml_file_name = CONFIG_XML;
155
156 if (fedora_info != null && fedora_info.isActive()) {
157 config_xml_file_name = FEDORA_CONFIG_PREFIX + config_xml_file_name;
158 }
159
160 // If the existing user config.xml file isn't recent enough, backup the old version and update it
161 File config_xml_file = new File(gli_user_directory_path + config_xml_file_name);
162
163 if (config_xml_file != null && config_xml_file.exists()) {
164 just_updated_config_xml_file = updateUserConfigXMLFileIfNecessary(config_xml_file);
165 general_config = XMLTools.parseXMLFile(config_xml_file);
166 }
167
168 // Create a new config from the default configuration file from our xml library
169 if (general_config == null) {
170 general_config = XMLTools.parseXMLFile(TEMPLATE_CONFIG_XML, true);
171 just_updated_config_xml_file = true;
172 }
173
174 // Determine the Directory Mappings element
175 directory_mappings_element = (Element) XMLTools.getNodeFromNamed(general_config.getDocumentElement(), StaticStrings.DIRECTORY_MAPPINGS_ELEMENT);
176
177 // Re-establish the color settings.
178 updateUI();
179
180 // Read the Greenstone library URL from the config file
181 String library_url_string = getString("general.library_url"+gliPropertyNameSuffix(), true);
182 if (!library_url_string.equals("")) {
183 try {
184 library_url = new URL(library_url_string);
185 }
186 catch (MalformedURLException exception) {
187 DebugStream.printStackTrace(exception);
188 }
189 }
190
191 // Read the Greenstone gliserver URL from the config file, if using a remote Greenstone
192 if (Gatherer.isGsdlRemote) {
193 String gliserver_url_string = getString("general.gliserver_url", true);
194 if (!gliserver_url_string.equals("")) {
195 try {
196 gliserver_url = new URL(gliserver_url_string);
197 }
198 catch (MalformedURLException exception) {
199 DebugStream.printStackTrace(exception);
200 }
201 }
202 }
203
204 if(gsdl3_path != null) {
205 prepareForGS3();
206 }
207
208 }
209
210 /** @return the suffix for the the config file's library_url/open_collection propertyname.
211 * For Fedora and remote GS2 cases, there is no suffix.
212 * However, when dealing with a local Greenstone server, this returns suffix _gs2 or _gs3
213 * so it can be appended to the default library_url/open_collection propertynames.
214 * Having 2 separate library URL properties and open_collection properties for the two
215 * local versions of Greenstone allows GLI to save the library_url and last opened
216 * collection for both GS2 and GS3, in case anyone runs them alternatively. (This is useful
217 * when developing and testing across GS versions.) */
218 static public String gliPropertyNameSuffix() {
219 if(Gatherer.isGsdlRemote) {
220 return ""; // no special suffix
221 } else if(Gatherer.GS3) { // local GS3, including FLI for GS3
222 return "_gs3";
223 } else { // local GS2, including FLI for GS2
224 return "_gs2";
225 }
226 }
227
228
229 // Called when (gsdl3_path != null) || (Gatherer.GS3 && Gatherer.isGsdlRemote)
230 static public void prepareForGS3() {
231 if (site_name == null || site_name.equals("")) {
232 site_name = getString("general.site_name", true);
233 servlet_path = getString("general.servlet_path", true);
234 if (site_name.equals("")) {
235 site_name = "localsite"; // can we assume these??
236 servlet_path = "/library";
237 setString("general.site_name", true, site_name);
238 setString("general.servlet_path", true, servlet_path);
239 }
240
241 } else {
242 // we set the current one in the config
243 setString("general.site_name", true, site_name);
244 if (servlet_path != null && !servlet_path.equals("")) {
245 setString("general.servlet_path", true, servlet_path);
246 }
247 }
248 }
249
250 static private boolean updateUserConfigXMLFileIfNecessary(File config_xml_file)
251 {
252 // Check if the configuration file actually needs updating by looking at the version numbers
253 Document new_document = XMLTools.parseXMLFile(TEMPLATE_CONFIG_XML, true);
254 Document old_document = XMLTools.parseXMLFile(config_xml_file);
255 if (new_document == null || old_document == null) {
256 // Something has gone badly wrong, so we can't update the file
257 return false;
258 }
259
260 String new_version = new_document.getDocumentElement().getAttribute(StaticStrings.VERSION_ATTRIBUTE);
261 String old_version = old_document.getDocumentElement().getAttribute(StaticStrings.VERSION_ATTRIBUTE);
262 if (new_version.equals(old_version)) {
263 // Don't need to update file
264 return false;
265 }
266
267 System.err.println("Converting user config.xml from version " + old_version + " to version " + new_version + "...");
268
269 // Build up the new user config.xml file from the template config.xml with the user's preferences added
270 // Make a backup of the old config.xml file first
271 config_xml_file.renameTo(new File(config_xml_file.getAbsolutePath() + ".old"));
272
273 // Check all of the Argument elements in the new config.xml file
274 NodeList new_argument_elements_nodelist = new_document.getElementsByTagName("Argument");
275 NodeList old_argument_elements_nodelist = old_document.getElementsByTagName("Argument");
276 for (int i = 0; i < new_argument_elements_nodelist.getLength(); i++) {
277 Element new_argument_element = (Element) new_argument_elements_nodelist.item(i);
278 String new_argument_element_name = new_argument_element.getAttribute("name");
279 String new_argument_element_value = XMLTools.getElementTextValue(new_argument_element);
280
281 // Did this Argument have a non-default value set?
282 for (int j = old_argument_elements_nodelist.getLength() - 1; j >= 0; j--) {
283 Element old_argument_element = (Element) old_argument_elements_nodelist.item(j);
284 String old_argument_element_name = old_argument_element.getAttribute("name");
285
286 // Argument found
287 if (old_argument_element_name.equals(new_argument_element_name)) {
288 // we don't want to carry over open_collection or library_url
289 // as these may be invalid
290 if (!new_argument_element_name.equals("general.open_collection"+Configuration.gliPropertyNameSuffix()) && !new_argument_element_name.equals("general.library_url"+Configuration.gliPropertyNameSuffix())) {
291
292 String old_argument_element_value = XMLTools.getElementTextValue(old_argument_element);
293 if (!old_argument_element_value.equals(new_argument_element_value)) {
294 XMLTools.setElementTextValue(new_argument_element, old_argument_element_value);
295 }
296 }
297
298 // We don't care about this option any more
299 old_argument_element.getParentNode().removeChild(old_argument_element);
300 break;
301 }
302 }
303 }
304
305 // Are there any old Argument elements left over? Keep these around for old time's sake
306 old_argument_elements_nodelist = old_document.getElementsByTagName("Argument");
307 if (old_argument_elements_nodelist.getLength() > 0) {
308 NodeList new_gathererconfig_elements_nodelist = new_document.getElementsByTagName("GathererConfig");
309 if (new_gathererconfig_elements_nodelist.getLength() > 0) {
310 Element new_gathererconfig_element = (Element) new_gathererconfig_elements_nodelist.item(0);
311 new_gathererconfig_element.appendChild(new_document.createComment(" Legacy options "));
312
313 // Add the legacy Arguments to the GathererConfig element
314 for (int i = 0; i < old_argument_elements_nodelist.getLength(); i++) {
315 Element old_argument_element = (Element) old_argument_elements_nodelist.item(i);
316 new_gathererconfig_element.appendChild(new_document.importNode(old_argument_element, true));
317 }
318 }
319 }
320
321 // Keep all the Mapping elements
322 NodeList new_directorymappings_elements_nodelist = new_document.getElementsByTagName("DirectoryMappings");
323 if (new_directorymappings_elements_nodelist.getLength() > 0) {
324 Element new_directorymappings_element = (Element) new_directorymappings_elements_nodelist.item(0);
325
326 NodeList old_mapping_elements_nodelist = old_document.getElementsByTagName("Mapping");
327 for (int i = 0; i < old_mapping_elements_nodelist.getLength(); i++) {
328 Element old_mapping_element = (Element) old_mapping_elements_nodelist.item(i);
329 new_directorymappings_element.appendChild(new_document.importNode(old_mapping_element, true));
330 }
331 }
332
333 // Check all of the Associations elements in the new config.xml file
334 NodeList new_entry_elements_nodelist = new_document.getElementsByTagName("Entry");
335 NodeList old_entry_elements_nodelist = old_document.getElementsByTagName("Entry");
336 for (int i = 0; i < new_entry_elements_nodelist.getLength(); i++) {
337 Element new_entry_element = (Element) new_entry_elements_nodelist.item(i);
338 String new_entry_element_name = new_entry_element.getAttribute("extension");
339 String new_entry_element_value = XMLTools.getElementTextValue(new_entry_element);
340
341 // Did this Entry have a non-default value set?
342 for (int j = old_entry_elements_nodelist.getLength() - 1; j >= 0; j--) {
343 Element old_entry_element = (Element) old_entry_elements_nodelist.item(j);
344 String old_entry_element_name = old_entry_element.getAttribute("extension");
345
346 // Entry found
347 if (old_entry_element_name.equals(new_entry_element_name)) {
348 String old_entry_element_value = XMLTools.getElementTextValue(old_entry_element);
349 if (!old_entry_element_value.equals(new_entry_element_value)) {
350 XMLTools.setElementTextValue(new_entry_element, old_entry_element_value);
351 }
352
353 // We don't care about this option any more
354 old_entry_element.getParentNode().removeChild(old_entry_element);
355 break;
356 }
357 }
358 }
359
360 // Are there any old Entry elements left over? We want to keep these
361 old_entry_elements_nodelist = old_document.getElementsByTagName("Entry");
362 if (old_entry_elements_nodelist.getLength() > 0) {
363 NodeList new_associations_elements_nodelist = new_document.getElementsByTagName("Associations");
364 if (new_associations_elements_nodelist.getLength() > 0) {
365 Element new_associations_element = (Element) new_associations_elements_nodelist.item(0);
366
367 // Add the legacy Entries to the Associations element
368 for (int i = 0; i < old_entry_elements_nodelist.getLength(); i++) {
369 Element old_entry_element = (Element) old_entry_elements_nodelist.item(i);
370 new_associations_element.appendChild(new_document.importNode(old_entry_element, true));
371 }
372 }
373 }
374
375 // Write out the updated config.xml file
376 XMLTools.writeXMLFile(config_xml_file, new_document);
377 return true;
378 }
379
380
381 /** Add a special directory mapping. */
382 static public boolean addDirectoryMapping(String name, File file) {
383 boolean result = false;
384 try {
385 // Ensure the name isn't already in use.
386 boolean found = false;
387 NodeList mappings = directory_mappings_element.getElementsByTagName(StaticStrings.MAPPING_ELEMENT);
388 for(int i = 0; !found && i < mappings.getLength(); i++) {
389 Element mapping_element = (Element) mappings.item(i);
390 if(mapping_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(name)) {
391 found = true;
392 }
393 mapping_element = null;
394 }
395 // Otherwise add the mapping.
396 if(!found) {
397 Element mapping_element = general_config.createElement(StaticStrings.MAPPING_ELEMENT);
398 mapping_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
399 mapping_element.setAttribute(StaticStrings.FILE_ATTRIBUTE, file.toString());
400 directory_mappings_element.appendChild(mapping_element);
401 result = true;
402 mapping_element = null;
403 }
404 mappings = null;
405 }
406 catch (Exception exception) {
407 DebugStream.printStackTrace(exception);
408 }
409 return result;
410 } /** addDirectoryMapping(String name, String file) **/
411
412 /** The default get action retrieves the named property from the desired configuration, and returns a true or false. */
413 static public boolean get(String property, boolean general) {
414 String raw = getString(property, general);
415 return (raw != null && raw.equalsIgnoreCase("true"));
416 }
417
418 /** Retrieve all of the configuration preferences which match a certain string. They are returned as a hash map of property names to String objects. */
419 static public HashMap getAll(String property_pattern, boolean general) {
420 HashMap properties = new HashMap();
421 try {
422 // Locate the appropriate element
423 Element document_element = null;
424 if(general) {
425 document_element = general_config.getDocumentElement();
426 }
427 else if(collection_config != null) {
428 document_element = collection_config.getDocumentElement();
429 }
430 if(document_element != null) {
431 // Retrieve the Gatherer element
432 Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
433 NodeList arguments = gatherer_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
434 for(int i = 0; i < arguments.getLength(); i++) {
435 Element argument_element = (Element) arguments.item(i);
436 if(argument_element.getAttribute(ARGUMENT_NAME).matches(property_pattern)) {
437 String result = XMLTools.getValue(argument_element);
438 // Store a mapping in the cache. Sometimes we will overwrite an existing value (say for collection and general level workflow options) but the processing overhead of detecting these clashes far exceeds any savings.
439 self.put(argument_element.getAttribute(ARGUMENT_NAME) + general, new SoftReference(argument_element));
440 // Add mapping to the properties we're going to return
441 properties.put(argument_element.getAttribute(ARGUMENT_NAME), result);
442 }
443 }
444 }
445 }
446 catch (Exception exception) {
447 DebugStream.printStackTrace(exception);
448 }
449 return properties;
450 }
451
452 /** Retrieve the value of the named property as a Rectangle. */
453 static public Rectangle getBounds(String property, boolean general) {
454 Rectangle result = null;
455 try {
456 String raw = getString(property, general);
457 // Rectangle is (x, y, width, height)
458 StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN1);
459 int x = Integer.parseInt(tokenizer.nextToken());
460 int y = Integer.parseInt(tokenizer.nextToken());
461 int width = Integer.parseInt(tokenizer.nextToken());
462 int height = Integer.parseInt(tokenizer.nextToken());
463 result = new Rectangle(x, y, width, height);
464 }
465 catch (Exception exception) {
466 DebugStream.printStackTrace(exception);
467 }
468 return result;
469 }
470
471 /** Retrieve the value of the named property as a Color. */
472 static public Color getColor(String property, boolean general) {
473 Color result = Color.white; // Default
474 try {
475 String raw = getString(property, general);
476 // Color is a RGB triplet list, comma separated (also remove whitespace)
477 StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN1);
478 int red = Integer.parseInt(tokenizer.nextToken());
479 int green = Integer.parseInt(tokenizer.nextToken());
480 int blue = Integer.parseInt(tokenizer.nextToken());
481 result = new Color(red, green, blue);
482 }
483 catch (Exception exception) {
484 DebugStream.printStackTrace(exception);
485 }
486 return result;
487 }
488
489
490 /** Retrieve the special directory mappings associated with this collection.
491 * @return A <strong>HashMap</strong> containing mappings from names to directories.
492 */
493 static public HashMap getDirectoryMappings() {
494 HashMap special_directories = new HashMap();
495 try {
496 // Ensure the name isn't already in use.
497 boolean found = false;
498 NodeList mappings = directory_mappings_element.getElementsByTagName(StaticStrings.MAPPING_ELEMENT);
499 for(int i = 0; !found && i < mappings.getLength(); i++) {
500 Element mapping_element = (Element) mappings.item(i);
501 String name = mapping_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
502 File file = new File(mapping_element.getAttribute(StaticStrings.FILE_ATTRIBUTE));
503 if(file.exists()) {
504 special_directories.put(name, file);
505 }
506 file = null;
507 name = null;
508 mapping_element = null;
509 }
510 mappings = null;
511 }
512 catch (Exception exception) {
513 DebugStream.printStackTrace(exception);
514 }
515 return special_directories;
516 } /** getDirectoryMappings() */
517
518 /** Retrieve the current users email. These are always stored in the general settings.
519 * @return the email address, if it is set, as a String
520 */
521 static public String getEmail() {
522 String email = getString(GENERAL_EMAIL_SETTING, true);
523 return (email.length() > 0 ? email : null);
524 }
525
526 static public Element getFileAssociations() {
527 NodeList file_association_elements = general_config.getDocumentElement().getElementsByTagName(StaticStrings.ASSOCIATIONS_ELEMENT);
528 return (Element) file_association_elements.item(0);
529 }
530
531 /** Retrieve the value of the named property as a FontUIResource. */
532 static public FontUIResource getFont(String property, boolean general) {
533 FontUIResource result = new FontUIResource("Times New Roman", Font.PLAIN, 10);
534 try {
535 String raw = getString(property, general);
536 // Font is a face, style, size triplet.
537 StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN3);
538 String face = tokenizer.nextToken().trim();
539 ///ystem.err.println("Face: " + face);
540 int style = Font.PLAIN;
541 String temp = tokenizer.nextToken().toUpperCase().trim();
542 ///ystem.err.println("Style: " + temp);
543 if(temp.equals("BOLD")) {
544 style = Font.BOLD;
545 }
546 else if(temp.equals("ITALIC")) {
547 style = Font.ITALIC;
548 }
549 int size = Integer.parseInt(tokenizer.nextToken().trim());
550 ///ystem.err.println("Size: " + size);
551 result = new FontUIResource(face, style, size);
552 }
553 catch (Exception exception) {
554 DebugStream.printStackTrace(exception);
555 }
556 return result;
557 }
558
559 /** Retrieve the value of the named property as an integer. */
560 static public int getInt(String property, boolean general) {
561 int result = 0;
562 try {
563 String raw = getString(property, general);
564 result = Integer.parseInt(raw);
565 }
566 catch (Exception exception) {
567 DebugStream.printStackTrace(exception);
568 }
569 return result;
570 }
571
572 /** Retrieves the current interface language two letter code. */
573 static public String getLanguage() {
574 Locale locale = getLocale("general.locale", GENERAL_SETTING);
575 String code = "en"; // Default
576 if(locale != null) {
577 code = locale.getLanguage();
578 }
579 return code;
580 }
581
582 /** Retrieve the value of the named property as a Locale. */
583 static public Locale getLocale(String property, boolean general) {
584 Locale result = Locale.getDefault();
585 try {
586 String raw = getString(property, general);
587 // Locale is a underscore separated code.
588 StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN2);
589 String language = tokenizer.nextToken();
590 if(tokenizer.hasMoreTokens()) {
591 String country = tokenizer.nextToken();
592 result = new Locale(language, country);
593 }
594 else {
595 result = new Locale(language);
596 }
597 }
598 catch (Exception exception) {
599 DebugStream.printStackTrace(exception);
600 }
601 return result;
602 }
603
604 /** Because modes will soon be an integral part of GLI, they get their own easy to remember methods such as this one to get the mode.
605 * @return an int representing the mode
606 */
607 static public int getMode() {
608 return getInt("general.mode", GENERAL_SETTING);
609 }
610
611 /** Return the current mode as a string for use in title bar etc
612 * @return the mode as a String
613 */
614 static public String getModeAsString() {
615 String result;
616 switch(getInt("general.mode", GENERAL_SETTING)) {
617 case ASSISTANT_MODE:
618 result = Dictionary.get("Preferences.Mode.Assistant");
619 break;
620 case EXPERT_MODE:
621 result = Dictionary.get("Preferences.Mode.Expert");
622 break;
623 default:
624 result = Dictionary.get("Preferences.Mode.Librarian");
625 }
626 return result;
627 }
628
629 static public String getPreviewCommand() {
630 return getString("general.preview_program", GENERAL_SETTING);
631 }
632
633 static public String getApplicationTitle() {
634 String gli_title = getString("GLI.Title", GENERAL_SETTING);
635 String title = (gli_title=="") ? Gatherer.PROGRAM_NAME : gli_title;
636
637 return title;
638 }
639
640
641 static public String getServletPath() {
642 return servlet_path;
643 }
644
645 /** Retrieve the value of the named property, and noting whether we consult the general or collection specific configuration. */
646 static public String getString(String property, boolean general) {
647 // Its up to this method to find the appropriate node and retrieve the data itself.
648 String result = "";
649 try {
650 // First of all we look in the cache to see if we have a match.
651 SoftReference reference = (SoftReference) self.get(property + general);
652 if(reference != null) {
653 Element argument_element = (Element) reference.get();
654 if(argument_element != null) {
655 cache_hit++;
656 result = XMLTools.getValue(argument_element);
657 }
658 }
659 // We may have missed in the cache, or the reference may have been consumed.
660 if(result.length() == 0) {
661 cache_miss++;
662 // Locate the appropriate element
663 Element document_element = null;
664 if(general) {
665 document_element = general_config.getDocumentElement();
666 }
667 else if(collection_config != null) {
668 document_element = collection_config.getDocumentElement();
669 }
670 if(document_element != null) {
671 // Retrieve the Gatherer element
672 Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
673 NodeList arguments = gatherer_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
674 for(int i = 0; result.length() == 0 && i < arguments.getLength(); i++) {
675 Element argument_element = (Element) arguments.item(i);
676 if(argument_element.getAttribute(ARGUMENT_NAME).equalsIgnoreCase(property)) {
677 result = XMLTools.getValue(argument_element);
678 // Store a mapping in the cache. Sometimes we will overwrite an existing value (say for collection and general level workflow options) but the processing overhead of detecting these clashes far exceeds any savings.
679 self.put(property + general, new SoftReference(argument_element));
680 }
681 }
682 }
683 }
684 }
685 catch (Exception exception) {
686 DebugStream.printStackTrace(exception);
687 }
688 // If we still have no result, and the search was made in the collection configuration, retrieve the general one instead.
689 if(result.length() == 0 && !general) {
690 result = getString(property, true);
691 }
692 return result;
693 }
694
695 static public String getGS3ScriptPath() {
696 return gsdl3_src_path + "bin" + File.separator + "script" + File.separator;
697 }
698
699 /** Remove a previously defined special directory mapping.
700 * @param name The name of the mapping to remove as a <strong>String</strong>.
701 * @return The <strong>File</strong> of the mapping removed.
702 */
703 static public File removeDirectoryMapping(String name) {
704 File file = null;
705 try {
706 // Ensure the name isn't already in use.
707 boolean found = false;
708 NodeList mappings = directory_mappings_element.getElementsByTagName(StaticStrings.MAPPING_ELEMENT);
709 for(int i = 0; !found && i < mappings.getLength(); i++) {
710 Element mapping_element = (Element) mappings.item(i);
711 if(mapping_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(name)) {
712 file = new File(XMLTools.getValue(mapping_element));
713 directory_mappings_element.removeChild(mapping_element);
714 found = true;
715 }
716 mapping_element = null;
717 }
718 mappings = null;
719 }
720 catch (Exception exception) {
721 DebugStream.printStackTrace(exception);
722 }
723 return file;
724 } /** removeDirectoryMapping(String name) */
725
726 /** Export the general configuration to file. */
727 static public void save() {
728 ///ystem.err.println("Hits " + cache_hit + " vs Misses " + cache_miss);
729 // We first try exporting to a user specific place
730 File user_config_xml = null;
731 String config_xml_name = CONFIG_XML;
732
733 if (fedora_info != null && fedora_info.isActive()) {
734 config_xml_name = FEDORA_CONFIG_PREFIX + config_xml_name;
735 }
736
737 try {
738 user_config_xml = new File(gli_user_directory_path + config_xml_name);
739 ///ystem.err.println("Trying to save to: " + user_config_xml.getAbsolutePath());
740 ///ystem.err.println("Writing.");
741 user_config_xml.getParentFile().mkdirs();
742 XMLTools.writeXMLFile(new File(user_config_xml.getAbsolutePath()), general_config);
743 }
744 catch (Exception exception) {
745 DebugStream.printStackTrace(exception);
746 user_config_xml = null;
747 }
748 }
749
750 /** Set the named property, from the specified configuration, using the given boolean value. */
751 static public void set(String property, boolean general, boolean value) {
752 if(property.startsWith("workflow")) {
753 DebugStream.println("Set property: " + property + ", general=" + general + ", value=" + value);
754 }
755 setString(property, general, (value ? "true" : "false"));
756 }
757
758 /** Set the collection configuration. */
759 static public void setCollectionConfiguration(Document collection_config_arg) {
760 // clear the cached values
761 self.clear();
762 collection_config = collection_config_arg;
763 updateUI();
764 ///atherer.println("Collection configuration set.");
765 }
766
767 /** Set the named property, from the specified configuration, using the given Rectangle value. */
768 static public void setBounds(String property, boolean general, Rectangle value) {
769 StringBuffer text = new StringBuffer("");
770 text.append(value.x);
771 text.append(", ");
772 text.append(value.y);
773 text.append(", ");
774 text.append(value.width);
775 text.append(", ");
776 text.append(value.height);
777 setString(property, general, text.toString());
778 }
779
780 /** Set the named property, from the specified configuration, using the given Color value. */
781 static public void setColor(String property, boolean general, Color value) {
782 StringBuffer text = new StringBuffer("");
783 text.append(value.getRed());
784 text.append(", ");
785 text.append(value.getGreen());
786 text.append(", ");
787 text.append(value.getBlue());
788 setString(property, general, text.toString());
789 }
790
791 /** Establish the current users email.
792 * @param email the email as a String
793 */
794 static public void setEmail(String email) {
795 setString(GENERAL_EMAIL_SETTING, true, email);
796 }
797
798 /** Set the named property, from the specified configuration, using the given Font value. */
799 static public void setFont(String property, boolean general, Font value) {
800 StringBuffer text = new StringBuffer("");
801 text.append(value.getName());
802 text.append(", ");
803 switch(value.getStyle()) {
804 case Font.BOLD:
805 text.append("BOLD");
806 break;
807 case Font.ITALIC:
808 text.append("ITALIC");
809 break;
810 default:
811 text.append("PLAIN");
812 }
813 text.append(", ");
814 text.append(value.getSize());
815 setString(property, general, text.toString());
816 }
817
818 /** Set the named property, from the specified configuration, using the given integer value. */
819 static public void setInt(String property, boolean general, int value) {
820 setString(property, general, String.valueOf(value));
821 }
822
823 /** Set the named property, from the specified configuration, using the given Locale value. */
824 static public void setLocale(String property, boolean general, Locale value) {
825 StringBuffer text = new StringBuffer("");
826 text.append(value.getLanguage());
827 String country = value.getCountry();
828 if(country != null && country.length() > 0) {
829 text.append("_");
830 text.append(country);
831 }
832 country = null;
833 setString(property, general, text.toString());
834 }
835
836 /** Because modes will soon be an integral part of GLI, they get their own easy to remember methods such as this one to set the mode.
837 * @param value the new value for mode
838 */
839 static public void setMode(int value) {
840 setInt("general.mode", GENERAL_SETTING, value);
841 }
842
843 static public void setPreviewCommand(String value) {
844 setString("general.preview_program", GENERAL_SETTING, value);
845 }
846
847 static public void setSiteAndServlet(String site, String servlet) {
848 site_name = site;
849 servlet_path = servlet;
850 setString("general.site_name", GENERAL_SETTING, site);
851 setString("general.servlet_path", GENERAL_SETTING, servlet);
852
853 }
854 /** Sets the value of the named property argument using the given string. */
855 static public void setString(String property, boolean general, String value) {
856 DebugStream.println("Set configuration property: " + property + " = " + value + (general ? "" : " [Collection]"));
857 try {
858 Document document = general_config;
859 if(!general && collection_config != null) {
860 document = collection_config;
861 }
862 if(document != null) {
863 Element argument_element = null;
864 // Try to retrieve from cache
865 SoftReference reference = (SoftReference) self.get(property + general);
866 if(reference != null) {
867 argument_element = (Element) reference.get();
868 }
869 if(argument_element == null) {
870 Element document_element = document.getDocumentElement();
871 Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
872 NodeList arguments = document_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
873 boolean found = false;
874 for(int i = 0; argument_element == null && i < arguments.getLength(); i++) {
875 Element possible_element = (Element) arguments.item(i);
876 if(possible_element.getAttribute(ARGUMENT_NAME).equalsIgnoreCase(property)) {
877 argument_element = possible_element;
878 }
879 }
880 // If argument element is still null, create it in the target document.
881 if(argument_element == null) {
882 argument_element = document.createElement(GATHERER_CONFIG_ARGUMENT);
883 argument_element.setAttribute(ARGUMENT_NAME, property);
884 gatherer_element.appendChild(argument_element);
885 }
886 // Update cache
887 self.put(property + general, new SoftReference(argument_element));
888
889 }
890 if(value == null) {
891 value = "";
892 }
893 // Now remove any current text node children.
894 NodeList children = argument_element.getChildNodes();
895 for(int i = 0; i < children.getLength(); i++) {
896 argument_element.removeChild(children.item(i));
897 }
898 // Add a new text node child with the new value
899 argument_element.appendChild(document.createTextNode(value));
900 }
901 }
902 catch (Exception exception) {
903 DebugStream.printStackTrace(exception);
904 }
905 }
906
907 static private void updateUI() {
908 // Buttons
909 UIManager.put("Button.select", new ColorUIResource(getColor("coloring.button_selected_background", false)));
910 UIManager.put("Button.background", new ColorUIResource(getColor("coloring.button_background", false)));
911 UIManager.put("Button.foreground", new ColorUIResource(getColor("coloring.button_foreground", false)));
912
913 UIManager.put("ToggleButton.background", new ColorUIResource(getColor("coloring.button_background", false)));
914 UIManager.put("ToggleButton.foreground", new ColorUIResource(getColor("coloring.button_foreground", false)));
915 UIManager.put("ToggleButton.select", new ColorUIResource(getColor("coloring.button_selected_background", false)));
916
917 // All the things with a lovely Collection green background
918 UIManager.put("OptionPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
919 UIManager.put("Panel.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
920 UIManager.put("Label.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
921 UIManager.put("TabbedPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
922 UIManager.put("SplitPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
923 UIManager.put("CheckBox.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
924
925
926 // Editable coloring
927 UIManager.put("ComboBox.background", new ColorUIResource(getColor("coloring.collection_tree_background", false))); // Indicate clickable
928 UIManager.put("Tree.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
929 UIManager.put("Tree.textBackground", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
930 UIManager.put("ProgressBar.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
931 UIManager.put("TextArea.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
932 UIManager.put("TextField.background", new ColorUIResource(getColor("coloring.editable_background", false)));
933 UIManager.put("Table.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
934 UIManager.put("List.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
935 UIManager.put("RadioButton.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
936
937 // Selection color
938 UIManager.put("TabbedPane.selected", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
939 UIManager.put("Tree.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
940 UIManager.put("ComboBox.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
941 UIManager.put("ProgressBar.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
942 UIManager.put("TextArea.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
943 UIManager.put("TextField.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
944 UIManager.put("List.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
945
946 // Scroll bar stuff
947 UIManager.put("ScrollBar.background", new ColorUIResource(getColor("coloring.scrollbar_background", false)));
948 UIManager.put("ScrollBar.thumb", new ColorUIResource(getColor("coloring.scrollbar_foreground", false)));
949 }
950}
Note: See TracBrowser for help on using the repository browser.