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

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

GLI three modes change: systems mode is no more.

  • 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 special_directories.put(name, file);
504 file = null;
505 name = null;
506 mapping_element = null;
507 }
508 mappings = null;
509 }
510 catch (Exception exception) {
511 DebugStream.printStackTrace(exception);
512 }
513 return special_directories;
514 } /** getDirectoryMappings() */
515
516 /** Retrieve the current users email. These are always stored in the general settings.
517 * @return the email address, if it is set, as a String
518 */
519 static public String getEmail() {
520 String email = getString(GENERAL_EMAIL_SETTING, true);
521 return (email.length() > 0 ? email : null);
522 }
523
524 static public Element getFileAssociations() {
525 NodeList file_association_elements = general_config.getDocumentElement().getElementsByTagName(StaticStrings.ASSOCIATIONS_ELEMENT);
526 return (Element) file_association_elements.item(0);
527 }
528
529 /** Retrieve the value of the named property as a FontUIResource. */
530 static public FontUIResource getFont(String property, boolean general) {
531 FontUIResource result = new FontUIResource("Times New Roman", Font.PLAIN, 10);
532 try {
533 String raw = getString(property, general);
534 // Font is a face, style, size triplet.
535 StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN3);
536 String face = tokenizer.nextToken().trim();
537 ///ystem.err.println("Face: " + face);
538 int style = Font.PLAIN;
539 String temp = tokenizer.nextToken().toUpperCase().trim();
540 ///ystem.err.println("Style: " + temp);
541 if(temp.equals("BOLD")) {
542 style = Font.BOLD;
543 }
544 else if(temp.equals("ITALIC")) {
545 style = Font.ITALIC;
546 }
547 int size = Integer.parseInt(tokenizer.nextToken().trim());
548 ///ystem.err.println("Size: " + size);
549 result = new FontUIResource(face, style, size);
550 }
551 catch (Exception exception) {
552 DebugStream.printStackTrace(exception);
553 }
554 return result;
555 }
556
557 /** Retrieve the value of the named property as an integer. */
558 static public int getInt(String property, boolean general) {
559 int result = 0;
560 try {
561 String raw = getString(property, general);
562 result = Integer.parseInt(raw);
563 }
564 catch (Exception exception) {
565 DebugStream.printStackTrace(exception);
566 }
567 return result;
568 }
569
570 /** Retrieves the current interface language two letter code. */
571 static public String getLanguage() {
572 Locale locale = getLocale("general.locale", GENERAL_SETTING);
573 String code = "en"; // Default
574 if(locale != null) {
575 code = locale.getLanguage();
576 }
577 return code;
578 }
579
580 /** Retrieve the value of the named property as a Locale. */
581 static public Locale getLocale(String property, boolean general) {
582 Locale result = Locale.getDefault();
583 try {
584 String raw = getString(property, general);
585 // Locale is a underscore separated code.
586 StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN2);
587 String language = tokenizer.nextToken();
588 if(tokenizer.hasMoreTokens()) {
589 String country = tokenizer.nextToken();
590 result = new Locale(language, country);
591 }
592 else {
593 result = new Locale(language);
594 }
595 }
596 catch (Exception exception) {
597 DebugStream.printStackTrace(exception);
598 }
599 return result;
600 }
601
602 /** 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.
603 * @return an int representing the mode
604 */
605 static public int getMode() {
606 return getInt("general.mode", GENERAL_SETTING);
607 }
608
609 /** Return the current mode as a string for use in title bar etc
610 * @return the mode as a String
611 */
612 static public String getModeAsString() {
613 String result;
614 switch(getInt("general.mode", GENERAL_SETTING)) {
615 case ASSISTANT_MODE:
616 result = Dictionary.get("Preferences.Mode.Assistant");
617 break;
618 case EXPERT_MODE:
619 result = Dictionary.get("Preferences.Mode.Expert");
620 break;
621 default:
622 result = Dictionary.get("Preferences.Mode.Librarian");
623 }
624 return result;
625 }
626
627 static public String getPreviewCommand() {
628 return getString("general.preview_program", GENERAL_SETTING);
629 }
630
631 static public String getApplicationTitle() {
632 String gli_title = getString("GLI.Title", GENERAL_SETTING);
633 String title = (gli_title=="") ? Gatherer.PROGRAM_NAME : gli_title;
634
635 return title;
636 }
637
638
639 static public String getServletPath() {
640 return servlet_path;
641 }
642
643 /** Retrieve the value of the named property, and noting whether we consult the general or collection specific configuration. */
644 static public String getString(String property, boolean general) {
645 // Its up to this method to find the appropriate node and retrieve the data itself.
646 String result = "";
647 try {
648 // First of all we look in the cache to see if we have a match.
649 SoftReference reference = (SoftReference) self.get(property + general);
650 if(reference != null) {
651 Element argument_element = (Element) reference.get();
652 if(argument_element != null) {
653 cache_hit++;
654 result = XMLTools.getValue(argument_element);
655 }
656 }
657 // We may have missed in the cache, or the reference may have been consumed.
658 if(result.length() == 0) {
659 cache_miss++;
660 // Locate the appropriate element
661 Element document_element = null;
662 if(general) {
663 document_element = general_config.getDocumentElement();
664 }
665 else if(collection_config != null) {
666 document_element = collection_config.getDocumentElement();
667 }
668 if(document_element != null) {
669 // Retrieve the Gatherer element
670 Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
671 NodeList arguments = gatherer_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
672 for(int i = 0; result.length() == 0 && i < arguments.getLength(); i++) {
673 Element argument_element = (Element) arguments.item(i);
674 if(argument_element.getAttribute(ARGUMENT_NAME).equalsIgnoreCase(property)) {
675 result = XMLTools.getValue(argument_element);
676 // 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.
677 self.put(property + general, new SoftReference(argument_element));
678 }
679 }
680 }
681 }
682 }
683 catch (Exception exception) {
684 DebugStream.printStackTrace(exception);
685 }
686 // If we still have no result, and the search was made in the collection configuration, retrieve the general one instead.
687 if(result.length() == 0 && !general) {
688 result = getString(property, true);
689 }
690 return result;
691 }
692
693 static public String getGS3ScriptPath() {
694 return gsdl3_src_path + "bin" + File.separator + "script" + File.separator;
695 }
696
697 /** Remove a previously defined special directory mapping.
698 * @param name The name of the mapping to remove as a <strong>String</strong>.
699 * @return The <strong>File</strong> of the mapping removed.
700 */
701 static public File removeDirectoryMapping(String name) {
702 File file = null;
703 try {
704 // Ensure the name isn't already in use.
705 boolean found = false;
706 NodeList mappings = directory_mappings_element.getElementsByTagName(StaticStrings.MAPPING_ELEMENT);
707 for(int i = 0; !found && i < mappings.getLength(); i++) {
708 Element mapping_element = (Element) mappings.item(i);
709 if(mapping_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(name)) {
710 file = new File(XMLTools.getValue(mapping_element));
711 directory_mappings_element.removeChild(mapping_element);
712 found = true;
713 }
714 mapping_element = null;
715 }
716 mappings = null;
717 }
718 catch (Exception exception) {
719 DebugStream.printStackTrace(exception);
720 }
721 return file;
722 } /** removeDirectoryMapping(String name) */
723
724 /** Export the general configuration to file. */
725 static public void save() {
726 ///ystem.err.println("Hits " + cache_hit + " vs Misses " + cache_miss);
727 // We first try exporting to a user specific place
728 File user_config_xml = null;
729 String config_xml_name = CONFIG_XML;
730
731 if (fedora_info != null && fedora_info.isActive()) {
732 config_xml_name = FEDORA_CONFIG_PREFIX + config_xml_name;
733 }
734
735 try {
736 user_config_xml = new File(gli_user_directory_path + config_xml_name);
737 ///ystem.err.println("Trying to save to: " + user_config_xml.getAbsolutePath());
738 ///ystem.err.println("Writing.");
739 user_config_xml.getParentFile().mkdirs();
740 XMLTools.writeXMLFile(new File(user_config_xml.getAbsolutePath()), general_config);
741 }
742 catch (Exception exception) {
743 DebugStream.printStackTrace(exception);
744 user_config_xml = null;
745 }
746 }
747
748 /** Set the named property, from the specified configuration, using the given boolean value. */
749 static public void set(String property, boolean general, boolean value) {
750 if(property.startsWith("workflow")) {
751 DebugStream.println("Set property: " + property + ", general=" + general + ", value=" + value);
752 }
753 setString(property, general, (value ? "true" : "false"));
754 }
755
756 /** Set the collection configuration. */
757 static public void setCollectionConfiguration(Document collection_config_arg) {
758 // clear the cached values
759 self.clear();
760 collection_config = collection_config_arg;
761 updateUI();
762 ///atherer.println("Collection configuration set.");
763 }
764
765 /** Set the named property, from the specified configuration, using the given Rectangle value. */
766 static public void setBounds(String property, boolean general, Rectangle value) {
767 StringBuffer text = new StringBuffer("");
768 text.append(value.x);
769 text.append(", ");
770 text.append(value.y);
771 text.append(", ");
772 text.append(value.width);
773 text.append(", ");
774 text.append(value.height);
775 setString(property, general, text.toString());
776 }
777
778 /** Set the named property, from the specified configuration, using the given Color value. */
779 static public void setColor(String property, boolean general, Color value) {
780 StringBuffer text = new StringBuffer("");
781 text.append(value.getRed());
782 text.append(", ");
783 text.append(value.getGreen());
784 text.append(", ");
785 text.append(value.getBlue());
786 setString(property, general, text.toString());
787 }
788
789 /** Establish the current users email.
790 * @param email the email as a String
791 */
792 static public void setEmail(String email) {
793 setString(GENERAL_EMAIL_SETTING, true, email);
794 }
795
796 /** Set the named property, from the specified configuration, using the given Font value. */
797 static public void setFont(String property, boolean general, Font value) {
798 StringBuffer text = new StringBuffer("");
799 text.append(value.getName());
800 text.append(", ");
801 switch(value.getStyle()) {
802 case Font.BOLD:
803 text.append("BOLD");
804 break;
805 case Font.ITALIC:
806 text.append("ITALIC");
807 break;
808 default:
809 text.append("PLAIN");
810 }
811 text.append(", ");
812 text.append(value.getSize());
813 setString(property, general, text.toString());
814 }
815
816 /** Set the named property, from the specified configuration, using the given integer value. */
817 static public void setInt(String property, boolean general, int value) {
818 setString(property, general, String.valueOf(value));
819 }
820
821 /** Set the named property, from the specified configuration, using the given Locale value. */
822 static public void setLocale(String property, boolean general, Locale value) {
823 StringBuffer text = new StringBuffer("");
824 text.append(value.getLanguage());
825 String country = value.getCountry();
826 if(country != null && country.length() > 0) {
827 text.append("_");
828 text.append(country);
829 }
830 country = null;
831 setString(property, general, text.toString());
832 }
833
834 /** 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.
835 * @param value the new value for mode
836 */
837 static public void setMode(int value) {
838 setInt("general.mode", GENERAL_SETTING, value);
839 }
840
841 static public void setPreviewCommand(String value) {
842 setString("general.preview_program", GENERAL_SETTING, value);
843 }
844
845 static public void setSiteAndServlet(String site, String servlet) {
846 site_name = site;
847 servlet_path = servlet;
848 setString("general.site_name", GENERAL_SETTING, site);
849 setString("general.servlet_path", GENERAL_SETTING, servlet);
850
851 }
852 /** Sets the value of the named property argument using the given string. */
853 static public void setString(String property, boolean general, String value) {
854 DebugStream.println("Set configuration property: " + property + " = " + value + (general ? "" : " [Collection]"));
855 try {
856 Document document = general_config;
857 if(!general && collection_config != null) {
858 document = collection_config;
859 }
860 if(document != null) {
861 Element argument_element = null;
862 // Try to retrieve from cache
863 SoftReference reference = (SoftReference) self.get(property + general);
864 if(reference != null) {
865 argument_element = (Element) reference.get();
866 }
867 if(argument_element == null) {
868 Element document_element = document.getDocumentElement();
869 Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
870 NodeList arguments = document_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
871 boolean found = false;
872 for(int i = 0; argument_element == null && i < arguments.getLength(); i++) {
873 Element possible_element = (Element) arguments.item(i);
874 if(possible_element.getAttribute(ARGUMENT_NAME).equalsIgnoreCase(property)) {
875 argument_element = possible_element;
876 }
877 }
878 // If argument element is still null, create it in the target document.
879 if(argument_element == null) {
880 argument_element = document.createElement(GATHERER_CONFIG_ARGUMENT);
881 argument_element.setAttribute(ARGUMENT_NAME, property);
882 gatherer_element.appendChild(argument_element);
883 }
884 // Update cache
885 self.put(property + general, new SoftReference(argument_element));
886
887 }
888 if(value == null) {
889 value = "";
890 }
891 // Now remove any current text node children.
892 NodeList children = argument_element.getChildNodes();
893 for(int i = 0; i < children.getLength(); i++) {
894 argument_element.removeChild(children.item(i));
895 }
896 // Add a new text node child with the new value
897 argument_element.appendChild(document.createTextNode(value));
898 }
899 }
900 catch (Exception exception) {
901 DebugStream.printStackTrace(exception);
902 }
903 }
904
905 static private void updateUI() {
906 // Buttons
907 UIManager.put("Button.select", new ColorUIResource(getColor("coloring.button_selected_background", false)));
908 UIManager.put("Button.background", new ColorUIResource(getColor("coloring.button_background", false)));
909 UIManager.put("Button.foreground", new ColorUIResource(getColor("coloring.button_foreground", false)));
910
911 UIManager.put("ToggleButton.background", new ColorUIResource(getColor("coloring.button_background", false)));
912 UIManager.put("ToggleButton.foreground", new ColorUIResource(getColor("coloring.button_foreground", false)));
913 UIManager.put("ToggleButton.select", new ColorUIResource(getColor("coloring.button_selected_background", false)));
914
915 // All the things with a lovely Collection green background
916 UIManager.put("OptionPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
917 UIManager.put("Panel.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
918 UIManager.put("Label.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
919 UIManager.put("TabbedPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
920 UIManager.put("SplitPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
921 UIManager.put("CheckBox.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
922
923
924 // Editable coloring
925 UIManager.put("ComboBox.background", new ColorUIResource(getColor("coloring.collection_tree_background", false))); // Indicate clickable
926 UIManager.put("Tree.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
927 UIManager.put("Tree.textBackground", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
928 UIManager.put("ProgressBar.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
929 UIManager.put("TextArea.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
930 UIManager.put("TextField.background", new ColorUIResource(getColor("coloring.editable_background", false)));
931 UIManager.put("Table.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
932 UIManager.put("List.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
933 UIManager.put("RadioButton.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
934
935 // Selection color
936 UIManager.put("TabbedPane.selected", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
937 UIManager.put("Tree.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
938 UIManager.put("ComboBox.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
939 UIManager.put("ProgressBar.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
940 UIManager.put("TextArea.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
941 UIManager.put("TextField.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
942 UIManager.put("List.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
943
944 // Scroll bar stuff
945 UIManager.put("ScrollBar.background", new ColorUIResource(getColor("coloring.scrollbar_background", false)));
946 UIManager.put("ScrollBar.thumb", new ColorUIResource(getColor("coloring.scrollbar_foreground", false)));
947 }
948}
Note: See TracBrowser for help on using the repository browser.