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

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

never copy over library_url_gs2/3 or open_collection_gs2/3 when updating the gli config file as it may be wrong. affects the case when you are running several greenstone installations

  • Property svn:keywords set to Author Date Id Revision
File size: 39.8 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 // we don't want to carry over open_collection or library_url
290 // as these may be invalid
291 if (!new_argument_element_name.equals("general.open_collection"+Configuration.gliPropertyNameSuffix()) && !new_argument_element_name.equals("general.library_url"+Configuration.gliPropertyNameSuffix())) {
292
293 String old_argument_element_value = XMLTools.getElementTextValue(old_argument_element);
294 if (!old_argument_element_value.equals(new_argument_element_value)) {
295 XMLTools.setElementTextValue(new_argument_element, old_argument_element_value);
296 }
297 }
298
299 // We don't care about this option any more
300 old_argument_element.getParentNode().removeChild(old_argument_element);
301 break;
302 }
303 }
304 }
305
306 // Are there any old Argument elements left over? Keep these around for old time's sake
307 old_argument_elements_nodelist = old_document.getElementsByTagName("Argument");
308 if (old_argument_elements_nodelist.getLength() > 0) {
309 NodeList new_gathererconfig_elements_nodelist = new_document.getElementsByTagName("GathererConfig");
310 if (new_gathererconfig_elements_nodelist.getLength() > 0) {
311 Element new_gathererconfig_element = (Element) new_gathererconfig_elements_nodelist.item(0);
312 new_gathererconfig_element.appendChild(new_document.createComment(" Legacy options "));
313
314 // Add the legacy Arguments to the GathererConfig element
315 for (int i = 0; i < old_argument_elements_nodelist.getLength(); i++) {
316 Element old_argument_element = (Element) old_argument_elements_nodelist.item(i);
317 new_gathererconfig_element.appendChild(new_document.importNode(old_argument_element, true));
318 }
319 }
320 }
321
322 // Keep all the Mapping elements
323 NodeList new_directorymappings_elements_nodelist = new_document.getElementsByTagName("DirectoryMappings");
324 if (new_directorymappings_elements_nodelist.getLength() > 0) {
325 Element new_directorymappings_element = (Element) new_directorymappings_elements_nodelist.item(0);
326
327 NodeList old_mapping_elements_nodelist = old_document.getElementsByTagName("Mapping");
328 for (int i = 0; i < old_mapping_elements_nodelist.getLength(); i++) {
329 Element old_mapping_element = (Element) old_mapping_elements_nodelist.item(i);
330 new_directorymappings_element.appendChild(new_document.importNode(old_mapping_element, true));
331 }
332 }
333
334 // Check all of the Associations elements in the new config.xml file
335 NodeList new_entry_elements_nodelist = new_document.getElementsByTagName("Entry");
336 NodeList old_entry_elements_nodelist = old_document.getElementsByTagName("Entry");
337 for (int i = 0; i < new_entry_elements_nodelist.getLength(); i++) {
338 Element new_entry_element = (Element) new_entry_elements_nodelist.item(i);
339 String new_entry_element_name = new_entry_element.getAttribute("extension");
340 String new_entry_element_value = XMLTools.getElementTextValue(new_entry_element);
341
342 // Did this Entry have a non-default value set?
343 for (int j = old_entry_elements_nodelist.getLength() - 1; j >= 0; j--) {
344 Element old_entry_element = (Element) old_entry_elements_nodelist.item(j);
345 String old_entry_element_name = old_entry_element.getAttribute("extension");
346
347 // Entry found
348 if (old_entry_element_name.equals(new_entry_element_name)) {
349 String old_entry_element_value = XMLTools.getElementTextValue(old_entry_element);
350 if (!old_entry_element_value.equals(new_entry_element_value)) {
351 XMLTools.setElementTextValue(new_entry_element, old_entry_element_value);
352 }
353
354 // We don't care about this option any more
355 old_entry_element.getParentNode().removeChild(old_entry_element);
356 break;
357 }
358 }
359 }
360
361 // Are there any old Entry elements left over? We want to keep these
362 old_entry_elements_nodelist = old_document.getElementsByTagName("Entry");
363 if (old_entry_elements_nodelist.getLength() > 0) {
364 NodeList new_associations_elements_nodelist = new_document.getElementsByTagName("Associations");
365 if (new_associations_elements_nodelist.getLength() > 0) {
366 Element new_associations_element = (Element) new_associations_elements_nodelist.item(0);
367
368 // Add the legacy Entries to the Associations element
369 for (int i = 0; i < old_entry_elements_nodelist.getLength(); i++) {
370 Element old_entry_element = (Element) old_entry_elements_nodelist.item(i);
371 new_associations_element.appendChild(new_document.importNode(old_entry_element, true));
372 }
373 }
374 }
375
376 // Write out the updated config.xml file
377 XMLTools.writeXMLFile(config_xml_file, new_document);
378 return true;
379 }
380
381
382 /** Add a special directory mapping. */
383 static public boolean addDirectoryMapping(String name, File file) {
384 boolean result = false;
385 try {
386 // Ensure the name isn't already in use.
387 boolean found = false;
388 NodeList mappings = directory_mappings_element.getElementsByTagName(StaticStrings.MAPPING_ELEMENT);
389 for(int i = 0; !found && i < mappings.getLength(); i++) {
390 Element mapping_element = (Element) mappings.item(i);
391 if(mapping_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(name)) {
392 found = true;
393 }
394 mapping_element = null;
395 }
396 // Otherwise add the mapping.
397 if(!found) {
398 Element mapping_element = general_config.createElement(StaticStrings.MAPPING_ELEMENT);
399 mapping_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
400 mapping_element.setAttribute(StaticStrings.FILE_ATTRIBUTE, file.toString());
401 directory_mappings_element.appendChild(mapping_element);
402 result = true;
403 mapping_element = null;
404 }
405 mappings = null;
406 }
407 catch (Exception exception) {
408 DebugStream.printStackTrace(exception);
409 }
410 return result;
411 } /** addDirectoryMapping(String name, String file) **/
412
413 /** The default get action retrieves the named property from the desired configuration, and returns a true or false. */
414 static public boolean get(String property, boolean general) {
415 String raw = getString(property, general);
416 return (raw != null && raw.equalsIgnoreCase("true"));
417 }
418
419 /** Retrieve all of the configuration preferences which match a certain string. They are returned as a hash map of property names to String objects. */
420 static public HashMap getAll(String property_pattern, boolean general) {
421 HashMap properties = new HashMap();
422 try {
423 // Locate the appropriate element
424 Element document_element = null;
425 if(general) {
426 document_element = general_config.getDocumentElement();
427 }
428 else if(collection_config != null) {
429 document_element = collection_config.getDocumentElement();
430 }
431 if(document_element != null) {
432 // Retrieve the Gatherer element
433 Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
434 NodeList arguments = gatherer_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
435 for(int i = 0; i < arguments.getLength(); i++) {
436 Element argument_element = (Element) arguments.item(i);
437 if(argument_element.getAttribute(ARGUMENT_NAME).matches(property_pattern)) {
438 String result = XMLTools.getValue(argument_element);
439 // 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.
440 self.put(argument_element.getAttribute(ARGUMENT_NAME) + general, new SoftReference(argument_element));
441 // Add mapping to the properties we're going to return
442 properties.put(argument_element.getAttribute(ARGUMENT_NAME), result);
443 }
444 }
445 }
446 }
447 catch (Exception exception) {
448 DebugStream.printStackTrace(exception);
449 }
450 return properties;
451 }
452
453 /** Retrieve the value of the named property as a Rectangle. */
454 static public Rectangle getBounds(String property, boolean general) {
455 Rectangle result = null;
456 try {
457 String raw = getString(property, general);
458 // Rectangle is (x, y, width, height)
459 StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN1);
460 int x = Integer.parseInt(tokenizer.nextToken());
461 int y = Integer.parseInt(tokenizer.nextToken());
462 int width = Integer.parseInt(tokenizer.nextToken());
463 int height = Integer.parseInt(tokenizer.nextToken());
464 result = new Rectangle(x, y, width, height);
465 }
466 catch (Exception exception) {
467 DebugStream.printStackTrace(exception);
468 }
469 return result;
470 }
471
472 /** Retrieve the value of the named property as a Color. */
473 static public Color getColor(String property, boolean general) {
474 Color result = Color.white; // Default
475 try {
476 String raw = getString(property, general);
477 // Color is a RGB triplet list, comma separated (also remove whitespace)
478 StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN1);
479 int red = Integer.parseInt(tokenizer.nextToken());
480 int green = Integer.parseInt(tokenizer.nextToken());
481 int blue = Integer.parseInt(tokenizer.nextToken());
482 result = new Color(red, green, blue);
483 }
484 catch (Exception exception) {
485 DebugStream.printStackTrace(exception);
486 }
487 return result;
488 }
489
490
491 /** Retrieve the special directory mappings associated with this collection.
492 * @return A <strong>HashMap</strong> containing mappings from names to directories.
493 */
494 static public HashMap getDirectoryMappings() {
495 HashMap special_directories = new HashMap();
496 try {
497 // Ensure the name isn't already in use.
498 boolean found = false;
499 NodeList mappings = directory_mappings_element.getElementsByTagName(StaticStrings.MAPPING_ELEMENT);
500 for(int i = 0; !found && i < mappings.getLength(); i++) {
501 Element mapping_element = (Element) mappings.item(i);
502 String name = mapping_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
503 File file = new File(mapping_element.getAttribute(StaticStrings.FILE_ATTRIBUTE));
504 special_directories.put(name, file);
505 file = null;
506 name = null;
507 mapping_element = null;
508 }
509 mappings = null;
510 }
511 catch (Exception exception) {
512 DebugStream.printStackTrace(exception);
513 }
514 return special_directories;
515 } /** getDirectoryMappings() */
516
517 /** Retrieve the current users email. These are always stored in the general settings.
518 * @return the email address, if it is set, as a String
519 */
520 static public String getEmail() {
521 String email = getString(GENERAL_EMAIL_SETTING, true);
522 return (email.length() > 0 ? email : null);
523 }
524
525 static public Element getFileAssociations() {
526 NodeList file_association_elements = general_config.getDocumentElement().getElementsByTagName(StaticStrings.ASSOCIATIONS_ELEMENT);
527 return (Element) file_association_elements.item(0);
528 }
529
530 /** Retrieve the value of the named property as a FontUIResource. */
531 static public FontUIResource getFont(String property, boolean general) {
532 FontUIResource result = new FontUIResource("Times New Roman", Font.PLAIN, 10);
533 try {
534 String raw = getString(property, general);
535 // Font is a face, style, size triplet.
536 StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN3);
537 String face = tokenizer.nextToken().trim();
538 ///ystem.err.println("Face: " + face);
539 int style = Font.PLAIN;
540 String temp = tokenizer.nextToken().toUpperCase().trim();
541 ///ystem.err.println("Style: " + temp);
542 if(temp.equals("BOLD")) {
543 style = Font.BOLD;
544 }
545 else if(temp.equals("ITALIC")) {
546 style = Font.ITALIC;
547 }
548 int size = Integer.parseInt(tokenizer.nextToken().trim());
549 ///ystem.err.println("Size: " + size);
550 result = new FontUIResource(face, style, size);
551 }
552 catch (Exception exception) {
553 DebugStream.printStackTrace(exception);
554 }
555 return result;
556 }
557
558 /** Retrieve the value of the named property as an integer. */
559 static public int getInt(String property, boolean general) {
560 int result = 0;
561 try {
562 String raw = getString(property, general);
563 result = Integer.parseInt(raw);
564 }
565 catch (Exception exception) {
566 DebugStream.printStackTrace(exception);
567 }
568 return result;
569 }
570
571 /** Retrieves the current interface language two letter code. */
572 static public String getLanguage() {
573 Locale locale = getLocale("general.locale", GENERAL_SETTING);
574 String code = "en"; // Default
575 if(locale != null) {
576 code = locale.getLanguage();
577 }
578 return code;
579 }
580
581 /** Retrieve the value of the named property as a Locale. */
582 static public Locale getLocale(String property, boolean general) {
583 Locale result = Locale.getDefault();
584 try {
585 String raw = getString(property, general);
586 // Locale is a underscore separated code.
587 StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN2);
588 String language = tokenizer.nextToken();
589 if(tokenizer.hasMoreTokens()) {
590 String country = tokenizer.nextToken();
591 result = new Locale(language, country);
592 }
593 else {
594 result = new Locale(language);
595 }
596 }
597 catch (Exception exception) {
598 DebugStream.printStackTrace(exception);
599 }
600 return result;
601 }
602
603 /** 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.
604 * @return an int representing the mode
605 */
606 static public int getMode() {
607 return getInt("general.mode", GENERAL_SETTING);
608 }
609
610 /** Return the current mode as a string for use in title bar etc
611 * @return the mode as a String
612 */
613 static public String getModeAsString() {
614 String result;
615 switch(getInt("general.mode", GENERAL_SETTING)) {
616 case ASSISTANT_MODE:
617 result = Dictionary.get("Preferences.Mode.Assistant");
618 break;
619 case SYSTEMS_MODE:
620 result = Dictionary.get("Preferences.Mode.Systems");
621 break;
622 case EXPERT_MODE:
623 result = Dictionary.get("Preferences.Mode.Expert");
624 break;
625 default:
626 result = Dictionary.get("Preferences.Mode.Librarian");
627 }
628 return result;
629 }
630
631 static public String getPreviewCommand() {
632 return getString("general.preview_program", GENERAL_SETTING);
633 }
634
635 static public String getApplicationTitle() {
636 String gli_title = getString("GLI.Title", GENERAL_SETTING);
637 String title = (gli_title=="") ? Gatherer.PROGRAM_NAME : gli_title;
638
639 return title;
640 }
641
642
643 static public String getServletPath() {
644 return servlet_path;
645 }
646
647 /** Retrieve the value of the named property, and noting whether we consult the general or collection specific configuration. */
648 static public String getString(String property, boolean general) {
649 // Its up to this method to find the appropriate node and retrieve the data itself.
650 String result = "";
651 try {
652 // First of all we look in the cache to see if we have a match.
653 SoftReference reference = (SoftReference) self.get(property + general);
654 if(reference != null) {
655 Element argument_element = (Element) reference.get();
656 if(argument_element != null) {
657 cache_hit++;
658 result = XMLTools.getValue(argument_element);
659 }
660 }
661 // We may have missed in the cache, or the reference may have been consumed.
662 if(result.length() == 0) {
663 cache_miss++;
664 // Locate the appropriate element
665 Element document_element = null;
666 if(general) {
667 document_element = general_config.getDocumentElement();
668 }
669 else if(collection_config != null) {
670 document_element = collection_config.getDocumentElement();
671 }
672 if(document_element != null) {
673 // Retrieve the Gatherer element
674 Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
675 NodeList arguments = gatherer_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
676 for(int i = 0; result.length() == 0 && i < arguments.getLength(); i++) {
677 Element argument_element = (Element) arguments.item(i);
678 if(argument_element.getAttribute(ARGUMENT_NAME).equalsIgnoreCase(property)) {
679 result = XMLTools.getValue(argument_element);
680 // 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.
681 self.put(property + general, new SoftReference(argument_element));
682 }
683 }
684 }
685 }
686 }
687 catch (Exception exception) {
688 DebugStream.printStackTrace(exception);
689 }
690 // If we still have no result, and the search was made in the collection configuration, retrieve the general one instead.
691 if(result.length() == 0 && !general) {
692 result = getString(property, true);
693 }
694 return result;
695 }
696
697 static public String getGS3ScriptPath() {
698 return gsdl3_src_path + "bin" + File.separator + "script" + File.separator;
699 }
700
701 /** Remove a previously defined special directory mapping.
702 * @param name The name of the mapping to remove as a <strong>String</strong>.
703 * @return The <strong>File</strong> of the mapping removed.
704 */
705 static public File removeDirectoryMapping(String name) {
706 File file = null;
707 try {
708 // Ensure the name isn't already in use.
709 boolean found = false;
710 NodeList mappings = directory_mappings_element.getElementsByTagName(StaticStrings.MAPPING_ELEMENT);
711 for(int i = 0; !found && i < mappings.getLength(); i++) {
712 Element mapping_element = (Element) mappings.item(i);
713 if(mapping_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(name)) {
714 file = new File(XMLTools.getValue(mapping_element));
715 directory_mappings_element.removeChild(mapping_element);
716 found = true;
717 }
718 mapping_element = null;
719 }
720 mappings = null;
721 }
722 catch (Exception exception) {
723 DebugStream.printStackTrace(exception);
724 }
725 return file;
726 } /** removeDirectoryMapping(String name) */
727
728 /** Export the general configuration to file. */
729 static public void save() {
730 ///ystem.err.println("Hits " + cache_hit + " vs Misses " + cache_miss);
731 // We first try exporting to a user specific place
732 File user_config_xml = null;
733 String config_xml_name = CONFIG_XML;
734
735 if (fedora_info != null && fedora_info.isActive()) {
736 config_xml_name = FEDORA_CONFIG_PREFIX + config_xml_name;
737 }
738
739 try {
740 user_config_xml = new File(gli_user_directory_path + config_xml_name);
741 ///ystem.err.println("Trying to save to: " + user_config_xml.getAbsolutePath());
742 ///ystem.err.println("Writing.");
743 user_config_xml.getParentFile().mkdirs();
744 XMLTools.writeXMLFile(new File(user_config_xml.getAbsolutePath()), general_config);
745 }
746 catch (Exception exception) {
747 DebugStream.printStackTrace(exception);
748 user_config_xml = null;
749 }
750 }
751
752 /** Set the named property, from the specified configuration, using the given boolean value. */
753 static public void set(String property, boolean general, boolean value) {
754 if(property.startsWith("workflow")) {
755 DebugStream.println("Set property: " + property + ", general=" + general + ", value=" + value);
756 }
757 setString(property, general, (value ? "true" : "false"));
758 }
759
760 /** Set the collection configuration. */
761 static public void setCollectionConfiguration(Document collection_config_arg) {
762 // clear the cached values
763 self.clear();
764 collection_config = collection_config_arg;
765 updateUI();
766 ///atherer.println("Collection configuration set.");
767 }
768
769 /** Set the named property, from the specified configuration, using the given Rectangle value. */
770 static public void setBounds(String property, boolean general, Rectangle value) {
771 StringBuffer text = new StringBuffer("");
772 text.append(value.x);
773 text.append(", ");
774 text.append(value.y);
775 text.append(", ");
776 text.append(value.width);
777 text.append(", ");
778 text.append(value.height);
779 setString(property, general, text.toString());
780 }
781
782 /** Set the named property, from the specified configuration, using the given Color value. */
783 static public void setColor(String property, boolean general, Color value) {
784 StringBuffer text = new StringBuffer("");
785 text.append(value.getRed());
786 text.append(", ");
787 text.append(value.getGreen());
788 text.append(", ");
789 text.append(value.getBlue());
790 setString(property, general, text.toString());
791 }
792
793 /** Establish the current users email.
794 * @param email the email as a String
795 */
796 static public void setEmail(String email) {
797 setString(GENERAL_EMAIL_SETTING, true, email);
798 }
799
800 /** Set the named property, from the specified configuration, using the given Font value. */
801 static public void setFont(String property, boolean general, Font value) {
802 StringBuffer text = new StringBuffer("");
803 text.append(value.getName());
804 text.append(", ");
805 switch(value.getStyle()) {
806 case Font.BOLD:
807 text.append("BOLD");
808 break;
809 case Font.ITALIC:
810 text.append("ITALIC");
811 break;
812 default:
813 text.append("PLAIN");
814 }
815 text.append(", ");
816 text.append(value.getSize());
817 setString(property, general, text.toString());
818 }
819
820 /** Set the named property, from the specified configuration, using the given integer value. */
821 static public void setInt(String property, boolean general, int value) {
822 setString(property, general, String.valueOf(value));
823 }
824
825 /** Set the named property, from the specified configuration, using the given Locale value. */
826 static public void setLocale(String property, boolean general, Locale value) {
827 StringBuffer text = new StringBuffer("");
828 text.append(value.getLanguage());
829 String country = value.getCountry();
830 if(country != null && country.length() > 0) {
831 text.append("_");
832 text.append(country);
833 }
834 country = null;
835 setString(property, general, text.toString());
836 }
837
838 /** 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.
839 * @param value the new value for mode
840 */
841 static public void setMode(int value) {
842 setInt("general.mode", GENERAL_SETTING, value);
843 }
844
845 static public void setPreviewCommand(String value) {
846 setString("general.preview_program", GENERAL_SETTING, value);
847 }
848
849 static public void setSiteAndServlet(String site, String servlet) {
850 site_name = site;
851 servlet_path = servlet;
852 setString("general.site_name", GENERAL_SETTING, site);
853 setString("general.servlet_path", GENERAL_SETTING, servlet);
854
855 }
856 /** Sets the value of the named property argument using the given string. */
857 static public void setString(String property, boolean general, String value) {
858 DebugStream.println("Set configuration property: " + property + " = " + value + (general ? "" : " [Collection]"));
859 try {
860 Document document = general_config;
861 if(!general && collection_config != null) {
862 document = collection_config;
863 }
864 if(document != null) {
865 Element argument_element = null;
866 // Try to retrieve from cache
867 SoftReference reference = (SoftReference) self.get(property + general);
868 if(reference != null) {
869 argument_element = (Element) reference.get();
870 }
871 if(argument_element == null) {
872 Element document_element = document.getDocumentElement();
873 Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
874 NodeList arguments = document_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
875 boolean found = false;
876 for(int i = 0; argument_element == null && i < arguments.getLength(); i++) {
877 Element possible_element = (Element) arguments.item(i);
878 if(possible_element.getAttribute(ARGUMENT_NAME).equalsIgnoreCase(property)) {
879 argument_element = possible_element;
880 }
881 }
882 // If argument element is still null, create it in the target document.
883 if(argument_element == null) {
884 argument_element = document.createElement(GATHERER_CONFIG_ARGUMENT);
885 argument_element.setAttribute(ARGUMENT_NAME, property);
886 gatherer_element.appendChild(argument_element);
887 }
888 // Update cache
889 self.put(property + general, new SoftReference(argument_element));
890
891 }
892 if(value == null) {
893 value = "";
894 }
895 // Now remove any current text node children.
896 NodeList children = argument_element.getChildNodes();
897 for(int i = 0; i < children.getLength(); i++) {
898 argument_element.removeChild(children.item(i));
899 }
900 // Add a new text node child with the new value
901 argument_element.appendChild(document.createTextNode(value));
902 }
903 }
904 catch (Exception exception) {
905 DebugStream.printStackTrace(exception);
906 }
907 }
908
909 static private void updateUI() {
910 // Buttons
911 UIManager.put("Button.select", new ColorUIResource(getColor("coloring.button_selected_background", false)));
912 UIManager.put("Button.background", new ColorUIResource(getColor("coloring.button_background", false)));
913 UIManager.put("Button.foreground", new ColorUIResource(getColor("coloring.button_foreground", false)));
914
915 UIManager.put("ToggleButton.background", new ColorUIResource(getColor("coloring.button_background", false)));
916 UIManager.put("ToggleButton.foreground", new ColorUIResource(getColor("coloring.button_foreground", false)));
917 UIManager.put("ToggleButton.select", new ColorUIResource(getColor("coloring.button_selected_background", false)));
918
919 // All the things with a lovely Collection green background
920 UIManager.put("OptionPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
921 UIManager.put("Panel.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
922 UIManager.put("Label.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
923 UIManager.put("TabbedPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
924 UIManager.put("SplitPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
925 UIManager.put("CheckBox.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
926
927
928 // Editable coloring
929 UIManager.put("ComboBox.background", new ColorUIResource(getColor("coloring.collection_tree_background", false))); // Indicate clickable
930 UIManager.put("Tree.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
931 UIManager.put("Tree.textBackground", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
932 UIManager.put("ProgressBar.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
933 UIManager.put("TextArea.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
934 UIManager.put("TextField.background", new ColorUIResource(getColor("coloring.editable_background", false)));
935 UIManager.put("Table.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
936 UIManager.put("List.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
937 UIManager.put("RadioButton.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
938
939 // Selection color
940 UIManager.put("TabbedPane.selected", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
941 UIManager.put("Tree.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
942 UIManager.put("ComboBox.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
943 UIManager.put("ProgressBar.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
944 UIManager.put("TextArea.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
945 UIManager.put("TextField.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
946 UIManager.put("List.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
947
948 // Scroll bar stuff
949 UIManager.put("ScrollBar.background", new ColorUIResource(getColor("coloring.scrollbar_background", false)));
950 UIManager.put("ScrollBar.thumb", new ColorUIResource(getColor("coloring.scrollbar_foreground", false)));
951 }
952}
Note: See TracBrowser for help on using the repository browser.