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

Last change on this file since 17798 was 17798, checked in by kjdon, 15 years ago

always update config file unless version numbers match

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