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

Last change on this file since 37341 was 37341, checked in by davidb, 14 months ago

Next phase of webswing gli development: better colour for text on disabled tab text; busy cursor shown when first loading in; expanded to previewURL and downloadURL for better future-proofing

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