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

Last change on this file since 31816 was 29300, checked in by ak19, 10 years ago

Fix to recent commit. Now the formatconverter binaries for the 3 OS are in their own new OS subfolders. However, they all share a single tidyconfig.cfg for html-tidy, which is still located in the bin superfolder.

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